mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
refactor: extract media and ACP core packages (#88534)
* refactor: extract media and acp core packages * refactor: remove relocated media and acp sources * build: wire new core packages into dependency checks * test: alias new core packages in vitest * build: keep media sniffer runtime dependency * docs: refresh plugin sdk api baseline * fix: keep normalized proposal queries non-empty * test: keep channel timer tests isolated * fix: keep rebased plugin checks green * fix: preserve sms numeric allowlist entries * test: harden exec foreground timeout failure * test: remove duplicate skill workshop assertion * fix: remove channel config lint suppression * test: refresh lint suppression allowlist
This commit is contained in:
committed by
GitHub
parent
4b1e5b7943
commit
77f1359612
@@ -144,6 +144,7 @@ const config = {
|
||||
entry: rootEntries,
|
||||
ignoreDependencies: [
|
||||
"@openclaw/*",
|
||||
"file-type",
|
||||
"playwright-core",
|
||||
"sqlite-vec",
|
||||
"tree-sitter-bash",
|
||||
@@ -184,6 +185,14 @@ const config = {
|
||||
entry: ["src/*.ts!"],
|
||||
project: ["src/**/*.ts!"],
|
||||
},
|
||||
"packages/media-core": {
|
||||
entry: ["src/*.ts!"],
|
||||
project: ["src/**/*.ts!"],
|
||||
},
|
||||
"packages/acp-core": {
|
||||
entry: ["src/*.ts!"],
|
||||
project: ["src/**/*.ts!"],
|
||||
},
|
||||
"packages/terminal-core": {
|
||||
entry: ["src/*.ts!"],
|
||||
project: ["src/**/*.ts!"],
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
71e7b7d92cba7f971a8f8f9ee14045320120df0f137f7c5cf295b333d46ecf8c plugin-sdk-api-baseline.json
|
||||
c550d232c205924eb9e0df9995c205a68659febf0450d02d79bd3349d25a323c plugin-sdk-api-baseline.jsonl
|
||||
8b0cb667fc676d9cf9e47ec8b3889aaa1cd75d493cc78428844931ca0ac415ff plugin-sdk-api-baseline.json
|
||||
b97fddcfae489bb4496e5cba26de388e4fe7eb52584d6a6b8e9cb4e539b258c5 plugin-sdk-api-baseline.jsonl
|
||||
|
||||
@@ -81,6 +81,24 @@ describe("SMS account config", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes numeric allowFrom entries accepted by config schema", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
sms: {
|
||||
accountSid: "AC-parent",
|
||||
authToken: "parent-token",
|
||||
fromNumber: "+15550000000",
|
||||
allowFrom: [1_555_333_4444],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(SmsConfigSchema.parse(cfg.channels.sms).allowFrom).toEqual([1_555_333_4444]);
|
||||
expect(resolveSmsAccount(cfg)).toMatchObject({
|
||||
allowFrom: ["+15553334444"],
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the configured default account when accountId is omitted", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
|
||||
@@ -72,11 +72,11 @@ function parseTwilioSuccessPayload(text: string): TwilioMessagePayload {
|
||||
from: typeof record.from === "string" ? record.from : undefined,
|
||||
status: typeof record.status === "string" ? record.status : undefined,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message === "Twilio SMS send returned malformed JSON.") {
|
||||
throw error;
|
||||
} catch (cause) {
|
||||
if (cause instanceof Error && cause.message === "Twilio SMS send returned malformed JSON.") {
|
||||
throw cause;
|
||||
}
|
||||
throw new Error("Twilio SMS send returned malformed JSON.", { cause: error });
|
||||
throw new Error("Twilio SMS send returned malformed JSON.", { cause });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export type SmsChannelConfigFields = {
|
||||
publicWebhookUrl?: string;
|
||||
dangerouslyDisableSignatureValidation?: boolean;
|
||||
dmPolicy?: "pairing" | "open" | "allowlist" | "disabled";
|
||||
allowFrom?: string | string[];
|
||||
allowFrom?: string | Array<string | number>;
|
||||
textChunkLimit?: number;
|
||||
};
|
||||
|
||||
|
||||
@@ -203,6 +203,66 @@
|
||||
"@openclaw/media-generation-core/*": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/media-core": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/index.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/base64": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/base64.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/constants": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/constants.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/content-length": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/content-length.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/file-name": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/file-name.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/inbound-path-policy": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/inbound-path-policy.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/inline-image-data-url": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/inline-image-data-url.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/media-source-url": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/media-source-url.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/mime": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/mime.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/read-byte-stream-with-limit": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/read-byte-stream-with-limit.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/read-response-with-limit": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/read-response-with-limit.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/*": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/normalization-core/record-coerce": [
|
||||
"../dist/plugin-sdk/packages/normalization-core/src/record-coerce.d.ts"
|
||||
],
|
||||
"@openclaw/normalization-core/string-coerce": [
|
||||
"../dist/plugin-sdk/packages/normalization-core/src/string-coerce.d.ts"
|
||||
],
|
||||
"@openclaw/normalization-core/*": [
|
||||
"../dist/plugin-sdk/packages/normalization-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/index.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/normalize-text": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/normalize-text.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/record-shared": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/record-shared.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/runtime/types": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/runtime/types.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/*": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/terminal-core": [
|
||||
"../dist/plugin-sdk/packages/terminal-core/src/index.d.ts"
|
||||
],
|
||||
|
||||
@@ -189,6 +189,66 @@
|
||||
"@openclaw/media-generation-core/*": [
|
||||
"../../dist/plugin-sdk/packages/media-generation-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/media-core": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/index.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/base64": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/base64.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/constants": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/constants.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/content-length": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/content-length.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/file-name": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/file-name.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/inbound-path-policy": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/inbound-path-policy.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/inline-image-data-url": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/inline-image-data-url.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/media-source-url": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/media-source-url.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/mime": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/mime.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/read-byte-stream-with-limit": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/read-byte-stream-with-limit.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/read-response-with-limit": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/read-response-with-limit.d.ts"
|
||||
],
|
||||
"@openclaw/media-core/*": [
|
||||
"../../dist/plugin-sdk/packages/media-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/normalization-core/record-coerce": [
|
||||
"../../dist/plugin-sdk/packages/normalization-core/src/record-coerce.d.ts"
|
||||
],
|
||||
"@openclaw/normalization-core/string-coerce": [
|
||||
"../../dist/plugin-sdk/packages/normalization-core/src/string-coerce.d.ts"
|
||||
],
|
||||
"@openclaw/normalization-core/*": [
|
||||
"../../dist/plugin-sdk/packages/normalization-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core": [
|
||||
"../../dist/plugin-sdk/packages/acp-core/src/index.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/normalize-text": [
|
||||
"../../dist/plugin-sdk/packages/acp-core/src/normalize-text.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/record-shared": [
|
||||
"../../dist/plugin-sdk/packages/acp-core/src/record-shared.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/runtime/types": [
|
||||
"../../dist/plugin-sdk/packages/acp-core/src/runtime/types.d.ts"
|
||||
],
|
||||
"@openclaw/acp-core/*": [
|
||||
"../../dist/plugin-sdk/packages/acp-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/terminal-core": [
|
||||
"../../dist/plugin-sdk/packages/terminal-core/src/index.d.ts"
|
||||
],
|
||||
|
||||
39
packages/acp-core/package.json
Normal file
39
packages/acp-core/package.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "@openclaw/acp-core",
|
||||
"version": "0.0.0-private",
|
||||
"private": true,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"type": "module",
|
||||
"main": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.mts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.mts",
|
||||
"import": "./dist/index.mjs",
|
||||
"default": "./dist/index.mjs"
|
||||
},
|
||||
"./normalize-text": {
|
||||
"types": "./dist/normalize-text.d.mts",
|
||||
"import": "./dist/normalize-text.mjs",
|
||||
"default": "./dist/normalize-text.mjs"
|
||||
},
|
||||
"./record-shared": {
|
||||
"types": "./dist/record-shared.d.mts",
|
||||
"import": "./dist/record-shared.mjs",
|
||||
"default": "./dist/record-shared.mjs"
|
||||
},
|
||||
"./runtime/types": {
|
||||
"types": "./dist/runtime/types.d.mts",
|
||||
"import": "./dist/runtime/types.mjs",
|
||||
"default": "./dist/runtime/types.mjs"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@openclaw/normalization-core": "workspace:*"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsdown src/index.ts src/normalize-text.ts src/record-shared.ts src/runtime/types.ts --no-config --platform node --format esm --dts --out-dir dist --clean"
|
||||
}
|
||||
}
|
||||
3
packages/acp-core/src/index.ts
Normal file
3
packages/acp-core/src/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./normalize-text.js";
|
||||
export * from "./record-shared.js";
|
||||
export * from "./runtime/types.js";
|
||||
1
packages/acp-core/src/normalize-text.ts
Normal file
1
packages/acp-core/src/normalize-text.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { normalizeOptionalString as normalizeText } from "@openclaw/normalization-core/string-coerce";
|
||||
75
packages/media-core/package.json
Normal file
75
packages/media-core/package.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "@openclaw/media-core",
|
||||
"version": "0.0.0-private",
|
||||
"private": true,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"type": "module",
|
||||
"main": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.mts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.mts",
|
||||
"import": "./dist/index.mjs",
|
||||
"default": "./dist/index.mjs"
|
||||
},
|
||||
"./base64": {
|
||||
"types": "./dist/base64.d.mts",
|
||||
"import": "./dist/base64.mjs",
|
||||
"default": "./dist/base64.mjs"
|
||||
},
|
||||
"./constants": {
|
||||
"types": "./dist/constants.d.mts",
|
||||
"import": "./dist/constants.mjs",
|
||||
"default": "./dist/constants.mjs"
|
||||
},
|
||||
"./content-length": {
|
||||
"types": "./dist/content-length.d.mts",
|
||||
"import": "./dist/content-length.mjs",
|
||||
"default": "./dist/content-length.mjs"
|
||||
},
|
||||
"./file-name": {
|
||||
"types": "./dist/file-name.d.mts",
|
||||
"import": "./dist/file-name.mjs",
|
||||
"default": "./dist/file-name.mjs"
|
||||
},
|
||||
"./inbound-path-policy": {
|
||||
"types": "./dist/inbound-path-policy.d.mts",
|
||||
"import": "./dist/inbound-path-policy.mjs",
|
||||
"default": "./dist/inbound-path-policy.mjs"
|
||||
},
|
||||
"./inline-image-data-url": {
|
||||
"types": "./dist/inline-image-data-url.d.mts",
|
||||
"import": "./dist/inline-image-data-url.mjs",
|
||||
"default": "./dist/inline-image-data-url.mjs"
|
||||
},
|
||||
"./media-source-url": {
|
||||
"types": "./dist/media-source-url.d.mts",
|
||||
"import": "./dist/media-source-url.mjs",
|
||||
"default": "./dist/media-source-url.mjs"
|
||||
},
|
||||
"./mime": {
|
||||
"types": "./dist/mime.d.mts",
|
||||
"import": "./dist/mime.mjs",
|
||||
"default": "./dist/mime.mjs"
|
||||
},
|
||||
"./read-byte-stream-with-limit": {
|
||||
"types": "./dist/read-byte-stream-with-limit.d.mts",
|
||||
"import": "./dist/read-byte-stream-with-limit.mjs",
|
||||
"default": "./dist/read-byte-stream-with-limit.mjs"
|
||||
},
|
||||
"./read-response-with-limit": {
|
||||
"types": "./dist/read-response-with-limit.d.mts",
|
||||
"import": "./dist/read-response-with-limit.mjs",
|
||||
"default": "./dist/read-response-with-limit.mjs"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@openclaw/normalization-core": "workspace:*",
|
||||
"file-type": "22.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsdown src/index.ts src/base64.ts src/constants.ts src/content-length.ts src/file-name.ts src/inbound-path-policy.ts src/inline-image-data-url.ts src/media-source-url.ts src/mime.ts src/read-byte-stream-with-limit.ts src/read-response-with-limit.ts --no-config --platform node --format esm --dts --out-dir dist --clean"
|
||||
}
|
||||
}
|
||||
10
packages/media-core/src/index.ts
Normal file
10
packages/media-core/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export * from "./base64.js";
|
||||
export * from "./constants.js";
|
||||
export * from "./content-length.js";
|
||||
export * from "./file-name.js";
|
||||
export * from "./inbound-path-policy.js";
|
||||
export * from "./inline-image-data-url.js";
|
||||
export * from "./media-source-url.js";
|
||||
export * from "./mime.js";
|
||||
export * from "./read-byte-stream-with-limit.js";
|
||||
export * from "./read-response-with-limit.js";
|
||||
37
packages/media-core/src/lazy-import.ts
Normal file
37
packages/media-core/src/lazy-import.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export type LazyPromiseLoader<T> = {
|
||||
load(): Promise<T>;
|
||||
clear(): void;
|
||||
};
|
||||
|
||||
export type LazyPromiseLoaderOptions = {
|
||||
cacheRejections?: boolean;
|
||||
};
|
||||
|
||||
export function createLazyImportLoader<T>(
|
||||
load: () => Promise<T>,
|
||||
options: LazyPromiseLoaderOptions = {},
|
||||
): LazyPromiseLoader<T> {
|
||||
let promise: Promise<T> | undefined;
|
||||
|
||||
const createPromise = (): Promise<T> => {
|
||||
const loaded = Promise.resolve().then(load);
|
||||
if (options.cacheRejections !== true) {
|
||||
void loaded.catch(() => {
|
||||
if (promise === loaded) {
|
||||
promise = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
return loaded;
|
||||
};
|
||||
|
||||
return {
|
||||
async load(): Promise<T> {
|
||||
promise ??= createPromise();
|
||||
return await promise;
|
||||
},
|
||||
clear(): void {
|
||||
promise = undefined;
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from "node:path";
|
||||
import { createLazyImportLoader } from "../shared/lazy-promise.js";
|
||||
import { type MediaKind, mediaKindFromMime } from "./constants.js";
|
||||
import { createLazyImportLoader } from "./lazy-import.js";
|
||||
|
||||
/** @internal */
|
||||
export const FILE_TYPE_SNIFF_MAX_BYTES = 1024 * 1024;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion";
|
||||
import { readResponseTextSnippet, readResponseWithLimit } from "./read-response-with-limit.js";
|
||||
|
||||
function makeStream(chunks: Uint8Array[], delayMs?: number) {
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolveTimerTimeoutMs } from "../shared/number-coercion.js";
|
||||
import { resolveTimerTimeoutMs } from "@openclaw/normalization-core/number-coercion";
|
||||
|
||||
async function readChunkWithIdleTimeout(
|
||||
reader: ReadableStreamDefaultReader<Uint8Array>,
|
||||
@@ -94,7 +94,7 @@ export {
|
||||
export type { ProcessWarning } from "../../../../src/infra/warning-filter.js";
|
||||
export { redactSensitiveText } from "../../../../src/logging/redact.js";
|
||||
export { createSubsystemLogger } from "../../../../src/logging/subsystem.js";
|
||||
export { detectMime } from "../../../../src/media/mime.js";
|
||||
export { detectMime } from "@openclaw/media-core/mime";
|
||||
|
||||
// Memory plugin helpers.
|
||||
export {
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
},
|
||||
"include": [
|
||||
"../../packages/markdown-core/src/**/*.ts",
|
||||
"../../packages/media-core/src/**/*.ts",
|
||||
"../../packages/media-generation-core/src/**/*.ts",
|
||||
"../../packages/model-catalog-core/src/**/*.ts",
|
||||
"../../packages/normalization-core/src/**/*.ts",
|
||||
"../../packages/acp-core/src/**/*.ts",
|
||||
"../../packages/terminal-core/src/**/*.ts",
|
||||
"../../src/plugin-sdk/**/*.ts",
|
||||
"../../src/video-generation/dashscope-compatible.ts",
|
||||
|
||||
18
pnpm-lock.yaml
generated
18
pnpm-lock.yaml
generated
@@ -1770,6 +1770,12 @@ importers:
|
||||
specifier: 2026.5.28
|
||||
version: 2026.5.28
|
||||
|
||||
packages/acp-core:
|
||||
dependencies:
|
||||
'@openclaw/normalization-core':
|
||||
specifier: workspace:*
|
||||
version: link:../normalization-core
|
||||
|
||||
packages/agent-core:
|
||||
dependencies:
|
||||
'@openclaw/llm-core':
|
||||
@@ -1824,6 +1830,15 @@ importers:
|
||||
specifier: 2.9.0
|
||||
version: 2.9.0
|
||||
|
||||
packages/media-core:
|
||||
dependencies:
|
||||
'@openclaw/normalization-core':
|
||||
specifier: workspace:*
|
||||
version: link:../normalization-core
|
||||
file-type:
|
||||
specifier: 22.0.1
|
||||
version: 22.0.1
|
||||
|
||||
packages/media-generation-core: {}
|
||||
|
||||
packages/media-understanding-common: {}
|
||||
@@ -1877,6 +1892,9 @@ importers:
|
||||
'@noble/ed25519':
|
||||
specifier: 3.1.0
|
||||
version: 3.1.0
|
||||
'@openclaw/media-core':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/media-core
|
||||
'@openclaw/normalization-core':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/normalization-core
|
||||
|
||||
@@ -48,8 +48,10 @@ export const BUILD_ALL_STEPS = [
|
||||
"packages/plugin-sdk/package.json",
|
||||
"packages/llm-core/package.json",
|
||||
"packages/markdown-core/package.json",
|
||||
"packages/media-core/package.json",
|
||||
"packages/media-understanding-common/package.json",
|
||||
"packages/terminal-core/package.json",
|
||||
"packages/acp-core/package.json",
|
||||
"packages/model-catalog-core/package.json",
|
||||
"packages/normalization-core/package.json",
|
||||
"packages/web-content-core/package.json",
|
||||
@@ -59,10 +61,12 @@ export const BUILD_ALL_STEPS = [
|
||||
"src/plugin-sdk",
|
||||
"packages/llm-core/src",
|
||||
"packages/markdown-core/src",
|
||||
"packages/media-core/src",
|
||||
"packages/model-catalog-core/src",
|
||||
"packages/memory-host-sdk/src",
|
||||
"packages/media-generation-core/src",
|
||||
"packages/normalization-core/src",
|
||||
"packages/acp-core/src",
|
||||
"packages/media-understanding-common/src",
|
||||
"packages/terminal-core/src",
|
||||
"packages/web-content-core/src",
|
||||
|
||||
@@ -116,6 +116,48 @@ export const EXTENSION_PACKAGE_BOUNDARY_BASE_PATHS = {
|
||||
"@openclaw/media-generation-core/*": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/*.d.ts",
|
||||
],
|
||||
"@openclaw/media-core": ["../dist/plugin-sdk/packages/media-core/src/index.d.ts"],
|
||||
"@openclaw/media-core/base64": ["../dist/plugin-sdk/packages/media-core/src/base64.d.ts"],
|
||||
"@openclaw/media-core/constants": ["../dist/plugin-sdk/packages/media-core/src/constants.d.ts"],
|
||||
"@openclaw/media-core/content-length": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/content-length.d.ts",
|
||||
],
|
||||
"@openclaw/media-core/file-name": ["../dist/plugin-sdk/packages/media-core/src/file-name.d.ts"],
|
||||
"@openclaw/media-core/inbound-path-policy": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/inbound-path-policy.d.ts",
|
||||
],
|
||||
"@openclaw/media-core/inline-image-data-url": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/inline-image-data-url.d.ts",
|
||||
],
|
||||
"@openclaw/media-core/media-source-url": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/media-source-url.d.ts",
|
||||
],
|
||||
"@openclaw/media-core/mime": ["../dist/plugin-sdk/packages/media-core/src/mime.d.ts"],
|
||||
"@openclaw/media-core/read-byte-stream-with-limit": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/read-byte-stream-with-limit.d.ts",
|
||||
],
|
||||
"@openclaw/media-core/read-response-with-limit": [
|
||||
"../dist/plugin-sdk/packages/media-core/src/read-response-with-limit.d.ts",
|
||||
],
|
||||
"@openclaw/media-core/*": ["../dist/plugin-sdk/packages/media-core/src/*.d.ts"],
|
||||
"@openclaw/normalization-core/record-coerce": [
|
||||
"../dist/plugin-sdk/packages/normalization-core/src/record-coerce.d.ts",
|
||||
],
|
||||
"@openclaw/normalization-core/string-coerce": [
|
||||
"../dist/plugin-sdk/packages/normalization-core/src/string-coerce.d.ts",
|
||||
],
|
||||
"@openclaw/normalization-core/*": ["../dist/plugin-sdk/packages/normalization-core/src/*.d.ts"],
|
||||
"@openclaw/acp-core": ["../dist/plugin-sdk/packages/acp-core/src/index.d.ts"],
|
||||
"@openclaw/acp-core/normalize-text": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/normalize-text.d.ts",
|
||||
],
|
||||
"@openclaw/acp-core/record-shared": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/record-shared.d.ts",
|
||||
],
|
||||
"@openclaw/acp-core/runtime/types": [
|
||||
"../dist/plugin-sdk/packages/acp-core/src/runtime/types.d.ts",
|
||||
],
|
||||
"@openclaw/acp-core/*": ["../dist/plugin-sdk/packages/acp-core/src/*.d.ts"],
|
||||
"@openclaw/terminal-core": ["../dist/plugin-sdk/packages/terminal-core/src/index.d.ts"],
|
||||
"@openclaw/terminal-core/ansi": ["../dist/plugin-sdk/packages/terminal-core/src/ansi.d.ts"],
|
||||
"@openclaw/terminal-core/decorative-emoji": [
|
||||
|
||||
@@ -5,6 +5,7 @@ const TSDOWN_PACKAGE_NAMES = [
|
||||
"llm-core",
|
||||
"llm-runtime",
|
||||
"markdown-core",
|
||||
"media-core",
|
||||
"media-generation-core",
|
||||
"media-understanding-common",
|
||||
"model-catalog-core",
|
||||
@@ -12,6 +13,7 @@ const TSDOWN_PACKAGE_NAMES = [
|
||||
"normalization-core",
|
||||
"speech-core",
|
||||
"terminal-core",
|
||||
"acp-core",
|
||||
];
|
||||
|
||||
export const TSDOWN_PACKAGE_OUTPUT_ROOTS = TSDOWN_PACKAGE_NAMES.map(packageOutputRoot);
|
||||
|
||||
@@ -17,11 +17,13 @@ const PLUGIN_SDK_TYPE_INPUTS = [
|
||||
"src/auto-reply",
|
||||
"packages/llm-core/src",
|
||||
"packages/markdown-core/src",
|
||||
"packages/media-core/src",
|
||||
"packages/model-catalog-core/src",
|
||||
"packages/memory-host-sdk/src",
|
||||
"packages/media-generation-core/src",
|
||||
"packages/media-understanding-common/src",
|
||||
"packages/normalization-core/src",
|
||||
"packages/acp-core/src",
|
||||
"packages/terminal-core/src",
|
||||
"src/video-generation/dashscope-compatible.ts",
|
||||
"src/video-generation/types.ts",
|
||||
@@ -52,6 +54,17 @@ const ROOT_DTS_REQUIRED_OUTPUTS = [
|
||||
"dist/plugin-sdk/packages/media-generation-core/src/index.d.ts",
|
||||
"dist/plugin-sdk/packages/media-generation-core/src/model-ref.d.ts",
|
||||
"dist/plugin-sdk/packages/media-generation-core/src/normalization.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/base64.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/constants.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/content-length.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/file-name.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/inbound-path-policy.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/inline-image-data-url.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/media-source-url.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/mime.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/read-byte-stream-with-limit.d.ts",
|
||||
"dist/plugin-sdk/packages/media-core/src/read-response-with-limit.d.ts",
|
||||
"dist/plugin-sdk/packages/acp-core/src/runtime/types.d.ts",
|
||||
"dist/plugin-sdk/packages/terminal-core/src/ansi.d.ts",
|
||||
"dist/plugin-sdk/packages/terminal-core/src/decorative-emoji.d.ts",
|
||||
"dist/plugin-sdk/packages/terminal-core/src/health-style.d.ts",
|
||||
@@ -99,6 +112,17 @@ const PACKAGE_DTS_REQUIRED_OUTPUTS = [
|
||||
"packages/plugin-sdk/dist/packages/media-generation-core/src/index.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-generation-core/src/model-ref.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-generation-core/src/normalization.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/base64.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/constants.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/content-length.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/file-name.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/inbound-path-policy.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/inline-image-data-url.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/media-source-url.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/mime.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/read-byte-stream-with-limit.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-core/src/read-response-with-limit.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/acp-core/src/runtime/types.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/model-catalog-core/src/configured-model-refs.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/model-catalog-core/src/model-catalog-normalize.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/model-catalog-core/src/model-catalog-refs.d.ts",
|
||||
|
||||
@@ -11,9 +11,11 @@ const RUN_NODE_PACKAGE_SOURCE_ROOTS = [
|
||||
"packages/gateway-client/src",
|
||||
"packages/gateway-protocol/src",
|
||||
"packages/markdown-core/src",
|
||||
"packages/media-core/src",
|
||||
"packages/media-generation-core/src",
|
||||
"packages/media-understanding-common/src",
|
||||
"packages/normalization-core/src",
|
||||
"packages/acp-core/src",
|
||||
"packages/terminal-core/src",
|
||||
"packages/web-content-core/src",
|
||||
"packages/net-policy/src",
|
||||
|
||||
@@ -46,7 +46,9 @@ const RUNTIME_SHIMS: Partial<Record<string, string>> = {
|
||||
function isBareImportSpecifier(id: string): boolean {
|
||||
if (
|
||||
id === "@openclaw/model-catalog-core/model-catalog-types" ||
|
||||
id.startsWith("@openclaw/normalization-core/")
|
||||
id.startsWith("@openclaw/normalization-core/") ||
|
||||
id.startsWith("@openclaw/media-core/") ||
|
||||
id.startsWith("@openclaw/acp-core/")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { homedir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { asRecord } from "@openclaw/acp-core/record-shared";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
import { isKnownCoreToolId } from "../agents/tool-catalog.js";
|
||||
import { isMutatingToolCall } from "../agents/tool-mutation.js";
|
||||
import { isPathInside } from "../infra/path-guards.js";
|
||||
import { asRecord } from "./record-shared.js";
|
||||
|
||||
const SAFE_SEARCH_TOOL_IDS = new Set(["search", "web_search", "memory_search"]);
|
||||
const TRUSTED_SAFE_TOOL_ALIASES = new Set(["search"]);
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeCapabilities,
|
||||
AcpRuntimeHandle,
|
||||
AcpRuntimeSessionMode,
|
||||
AcpRuntimeStatus,
|
||||
} from "@openclaw/acp-core/runtime/types";
|
||||
import { clampTimerTimeoutMs } from "@openclaw/normalization-core/number-coercion";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
|
||||
@@ -32,13 +39,6 @@ import {
|
||||
resolveRuntimeHandleIdentifiersFromIdentity,
|
||||
resolveSessionIdentityFromMeta,
|
||||
} from "../runtime/session-identity.js";
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeCapabilities,
|
||||
AcpRuntimeHandle,
|
||||
AcpRuntimeSessionMode,
|
||||
AcpRuntimeStatus,
|
||||
} from "../runtime/types.js";
|
||||
import { reconcileManagerRuntimeSessionIdentifiers } from "./manager.identity-reconcile.js";
|
||||
import {
|
||||
applyManagerRuntimeControls,
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeHandle,
|
||||
AcpRuntimeStatus,
|
||||
} from "@openclaw/acp-core/runtime/types";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { withAcpRuntimeErrorBoundary } from "../runtime/errors.js";
|
||||
@@ -9,7 +14,6 @@ import {
|
||||
resolveRuntimeHandleIdentifiersFromIdentity,
|
||||
resolveSessionIdentityFromMeta,
|
||||
} from "../runtime/session-identity.js";
|
||||
import type { AcpRuntime, AcpRuntimeHandle, AcpRuntimeStatus } from "../runtime/types.js";
|
||||
import type { SessionAcpMeta, SessionEntry } from "./manager.types.js";
|
||||
import { hasLegacyAcpIdentityProjection } from "./manager.utils.js";
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { asNullableRecord } from "@openclaw/normalization-core/record-coerce";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import { AcpRuntimeError, withAcpRuntimeErrorBoundary } from "../runtime/errors.js";
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeCapabilities,
|
||||
AcpRuntimeHandle,
|
||||
AcpRuntimeStatus,
|
||||
} from "../runtime/types.js";
|
||||
} from "@openclaw/acp-core/runtime/types";
|
||||
import { asNullableRecord } from "@openclaw/normalization-core/record-coerce";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import { AcpRuntimeError, withAcpRuntimeErrorBoundary } from "../runtime/errors.js";
|
||||
import type { SessionAcpMeta } from "./manager.types.js";
|
||||
import { createUnsupportedControlError } from "./manager.utils.js";
|
||||
import type { CachedRuntimeState } from "./runtime-cache.js";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { setTimeout as scheduleNativeTimeout } from "node:timers";
|
||||
import { setTimeout as sleep } from "node:timers/promises";
|
||||
import type { AcpRuntime, AcpRuntimeCapabilities } from "@openclaw/acp-core/runtime/types";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { AcpSessionRuntimeOptions, SessionAcpMeta } from "../../config/sessions/types.js";
|
||||
import { resetHeartbeatWakeStateForTests } from "../../infra/heartbeat-wake.js";
|
||||
import { withTempDir } from "../../test-helpers/temp-dir.js";
|
||||
import type { AcpRuntime, AcpRuntimeCapabilities } from "../runtime/types.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => {
|
||||
const listAcpSessionEntriesMock = vi.fn();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { AcpRuntimeError } from "../runtime/errors.js";
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeEvent,
|
||||
AcpRuntimeTurnInput,
|
||||
AcpRuntimeTurnResult,
|
||||
} from "../runtime/types.js";
|
||||
} from "@openclaw/acp-core/runtime/types";
|
||||
import { AcpRuntimeError } from "../runtime/errors.js";
|
||||
import { normalizeAcpErrorCode } from "./manager.utils.js";
|
||||
import { normalizeText } from "./runtime-options.js";
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeCapabilities,
|
||||
AcpRuntimeEvent,
|
||||
AcpRuntimeHandle,
|
||||
AcpRuntimePromptMode,
|
||||
AcpRuntimeSessionMode,
|
||||
AcpRuntimeStatus,
|
||||
} from "@openclaw/acp-core/runtime/types";
|
||||
import type {
|
||||
SessionAcpIdentity,
|
||||
AcpSessionRuntimeOptions,
|
||||
@@ -12,15 +21,6 @@ import {
|
||||
readAcpSessionEntry,
|
||||
upsertAcpSessionMeta,
|
||||
} from "../runtime/session-meta.js";
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeCapabilities,
|
||||
AcpRuntimeEvent,
|
||||
AcpRuntimeHandle,
|
||||
AcpRuntimePromptMode,
|
||||
AcpRuntimeSessionMode,
|
||||
AcpRuntimeStatus,
|
||||
} from "../runtime/types.js";
|
||||
|
||||
export type AcpSessionResolution =
|
||||
| {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AcpRuntime } from "@openclaw/acp-core/runtime/types";
|
||||
import type { AcpRuntimeHandle } from "@openclaw/acp-core/runtime/types";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { AcpRuntime } from "../runtime/types.js";
|
||||
import type { AcpRuntimeHandle } from "../runtime/types.js";
|
||||
import type { CachedRuntimeState } from "./runtime-cache.js";
|
||||
import { RuntimeCache } from "./runtime-cache.js";
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import type { AcpRuntime, AcpRuntimeHandle, AcpRuntimeSessionMode } from "../runtime/types.js";
|
||||
import type {
|
||||
AcpRuntime,
|
||||
AcpRuntimeHandle,
|
||||
AcpRuntimeSessionMode,
|
||||
} from "@openclaw/acp-core/runtime/types";
|
||||
|
||||
export type CachedRuntimeState = {
|
||||
runtime: AcpRuntime;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { isAbsolute } from "node:path";
|
||||
import { normalizeText } from "@openclaw/acp-core/normalize-text";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { AcpSessionRuntimeOptions, SessionAcpMeta } from "../../config/sessions/types.js";
|
||||
import { parseStrictPositiveInteger } from "../../infra/parse-finite-number.js";
|
||||
import { normalizeText } from "../normalize-text.js";
|
||||
import { AcpRuntimeError } from "../runtime/errors.js";
|
||||
|
||||
export { normalizeText } from "../normalize-text.js";
|
||||
export { normalizeText } from "@openclaw/acp-core/normalize-text";
|
||||
|
||||
const MAX_RUNTIME_MODE_LENGTH = 64;
|
||||
const MAX_MODEL_LENGTH = 200;
|
||||
|
||||
@@ -5,13 +5,13 @@ import type {
|
||||
ToolCallLocation,
|
||||
ToolKind,
|
||||
} from "@agentclientprotocol/sdk";
|
||||
import { asRecord } from "@openclaw/acp-core/record-shared";
|
||||
import {
|
||||
hasNonEmptyString,
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
readStringValue,
|
||||
} from "@openclaw/normalization-core/string-coerce";
|
||||
import { asRecord } from "./record-shared.js";
|
||||
|
||||
type GatewayAttachment = {
|
||||
type: string;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { normalizeOptionalString as normalizeText } from "../../packages/normalization-core/src/string-coerce.js";
|
||||
@@ -1,13 +1,13 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { normalizeText } from "@openclaw/acp-core/normalize-text";
|
||||
import type { AcpRuntimeSessionMode } from "@openclaw/acp-core/runtime/types";
|
||||
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { ChannelId } from "../channels/plugins/types.public.js";
|
||||
import type { SessionBindingRecord } from "../infra/outbound/session-binding-service.js";
|
||||
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
||||
import { sanitizeAgentId } from "../routing/session-key.js";
|
||||
import { normalizeText } from "./normalize-text.js";
|
||||
import type { AcpRuntimeSessionMode } from "./runtime/types.js";
|
||||
|
||||
export { normalizeText } from "./normalize-text.js";
|
||||
export { normalizeText } from "@openclaw/acp-core/normalize-text";
|
||||
|
||||
export type ConfiguredAcpBindingChannel = ChannelId;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { AcpRuntime, AcpRuntimeEvent } from "@openclaw/acp-core/runtime/types";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { expect } from "vitest";
|
||||
import { toAcpRuntimeError } from "./errors.js";
|
||||
import type { AcpRuntime, AcpRuntimeEvent } from "./types.js";
|
||||
|
||||
export type AcpRuntimeAdapterContractParams = {
|
||||
createRuntime: () => Promise<AcpRuntime> | AcpRuntime;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { AcpRuntime } from "@openclaw/acp-core/runtime/types";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { AcpRuntimeError } from "./errors.js";
|
||||
import {
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
requireAcpRuntimeBackend,
|
||||
unregisterAcpRuntimeBackend,
|
||||
} from "./registry.js";
|
||||
import type { AcpRuntime } from "./types.js";
|
||||
|
||||
function createRuntimeStub(): AcpRuntime {
|
||||
return {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { AcpRuntime } from "@openclaw/acp-core/runtime/types";
|
||||
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { resolveGlobalSingleton } from "../../shared/global-singleton.js";
|
||||
import { AcpRuntimeError } from "./errors.js";
|
||||
import type { AcpRuntime } from "./types.js";
|
||||
|
||||
export type AcpRuntimeBackend = {
|
||||
id: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { normalizeText } from "@openclaw/acp-core/normalize-text";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { SessionAcpIdentity, SessionAcpMeta } from "../../config/sessions/types.js";
|
||||
import { normalizeText } from "../normalize-text.js";
|
||||
import { isSessionIdentityPending, resolveSessionIdentityFromMeta } from "./session-identity.js";
|
||||
|
||||
export const ACP_SESSION_IDENTITY_RENDERER_VERSION = "v1";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { normalizeText } from "@openclaw/acp-core/normalize-text";
|
||||
import type { AcpRuntimeHandle, AcpRuntimeStatus } from "@openclaw/acp-core/runtime/types";
|
||||
import type {
|
||||
SessionAcpIdentity,
|
||||
SessionAcpIdentitySource,
|
||||
SessionAcpMeta,
|
||||
} from "../../config/sessions/types.js";
|
||||
import { normalizeText } from "../normalize-text.js";
|
||||
import type { AcpRuntimeHandle, AcpRuntimeStatus } from "./types.js";
|
||||
|
||||
function normalizeIdentityState(value: unknown): SessionAcpIdentity["state"] | undefined {
|
||||
if (value !== "pending" && value !== "resolved") {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import type { AcpRuntimeSessionMode } from "@openclaw/acp-core/runtime/types";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
@@ -15,7 +16,6 @@ import {
|
||||
resolveAcpSessionCwd,
|
||||
resolveAcpThreadSessionDetailLines,
|
||||
} from "../acp/runtime/session-identifiers.js";
|
||||
import type { AcpRuntimeSessionMode } from "../acp/runtime/types.js";
|
||||
import { DEFAULT_HEARTBEAT_EVERY } from "../auto-reply/heartbeat.js";
|
||||
import {
|
||||
resolveChannelDefaultBindingPlacement,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { URL } from "node:url";
|
||||
import { detectMime } from "@openclaw/media-core/mime";
|
||||
import { isWindowsDrivePath } from "../infra/archive-path.js";
|
||||
import {
|
||||
canonicalPathFromExistingAncestor,
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
} from "../infra/fs-safe.js";
|
||||
import { expandHomePrefix, resolveOsHomeDir } from "../infra/home-dir.js";
|
||||
import { hasEncodedFileUrlSeparator, trySafeFileURLToPath } from "../infra/local-file-access.js";
|
||||
import { detectMime } from "../media/mime.js";
|
||||
import { sniffMimeFromBase64 } from "../media/sniff-mime-from-base64.js";
|
||||
import {
|
||||
REQUIRED_PARAM_GROUPS,
|
||||
|
||||
@@ -22,6 +22,27 @@ const defaultShell = isWin
|
||||
? undefined
|
||||
: process.env.OPENCLAW_TEST_SHELL || resolveShellFromPath("bash") || process.env.SHELL || "sh";
|
||||
|
||||
function requireTextContent(
|
||||
result: Awaited<ReturnType<ReturnType<typeof createExecTool>["execute"]>>,
|
||||
) {
|
||||
const content = result.content[0];
|
||||
expect(content?.type).toBe("text");
|
||||
if (content?.type !== "text") {
|
||||
throw new Error(`expected text content, got ${content?.type ?? "missing"}`);
|
||||
}
|
||||
return content.text;
|
||||
}
|
||||
|
||||
function requireFailedDetails(
|
||||
details: Awaited<ReturnType<ReturnType<typeof createExecTool>["execute"]>>["details"],
|
||||
) {
|
||||
expect(details.status).toBe("failed");
|
||||
if (details.status !== "failed") {
|
||||
throw new Error(`expected failed details, got ${details.status}`);
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
describe("exec foreground failures", () => {
|
||||
let envSnapshot: ReturnType<typeof captureEnv> | undefined;
|
||||
|
||||
@@ -49,7 +70,7 @@ describe("exec foreground failures", () => {
|
||||
const tool = createExecTool({
|
||||
security: "full",
|
||||
ask: "off",
|
||||
timeoutSec: 0.05,
|
||||
timeoutSec: 1,
|
||||
backgroundMs: 10,
|
||||
allowBackground: false,
|
||||
});
|
||||
@@ -81,16 +102,11 @@ describe("exec foreground failures", () => {
|
||||
});
|
||||
|
||||
expect(supervisorMock.spawn).toHaveBeenCalledOnce();
|
||||
expect((supervisorMock.spawn.mock.calls[0]?.[0] as SpawnInput | undefined)?.timeoutMs).toBe(50);
|
||||
expect(result.content[0]?.type).toBe("text");
|
||||
const details = result.details as {
|
||||
status?: string;
|
||||
exitCode?: number | null;
|
||||
aggregated?: string;
|
||||
durationMs?: number;
|
||||
timedOut?: boolean;
|
||||
};
|
||||
expect(details.status).toBe("failed");
|
||||
expect(supervisorMock.spawn.mock.calls[0]?.[0]?.timeoutMs).toBe(1_000);
|
||||
const text = requireTextContent(result);
|
||||
expect(text).toMatch(/timed out/i);
|
||||
expect(text).toMatch(/re-run with a higher timeout/i);
|
||||
const details = requireFailedDetails(result.details);
|
||||
expect(details.exitCode).toBeNull();
|
||||
expect(details.timedOut).toBe(true);
|
||||
expect(details.aggregated).toBe("");
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { MAX_IMAGE_BYTES } from "@openclaw/media-core/constants";
|
||||
import type { ImageContent } from "openclaw/plugin-sdk/llm";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createSolidPngBuffer } from "../../test/helpers/image-fixtures.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
|
||||
import { MAX_IMAGE_BYTES } from "../media/constants.js";
|
||||
import { escapeRegExp } from "../shared/regexp.js";
|
||||
import {
|
||||
buildCliArgs,
|
||||
|
||||
@@ -2,6 +2,8 @@ import crypto from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { MAX_IMAGE_BYTES } from "@openclaw/media-core/constants";
|
||||
import { extensionForMime } from "@openclaw/media-core/mime";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
@@ -16,8 +18,6 @@ import { privateFileStore } from "../../infra/private-file-store.js";
|
||||
import { tempWorkspace } from "../../infra/private-temp-workspace.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../../infra/tmp-openclaw-dir.js";
|
||||
import type { ImageContent } from "../../llm/types.js";
|
||||
import { MAX_IMAGE_BYTES } from "../../media/constants.js";
|
||||
import { extensionForMime } from "../../media/mime.js";
|
||||
import { listRegisteredPluginAgentPromptGuidance } from "../../plugins/command-registry-state.js";
|
||||
import type { EmbeddedContextFile } from "../embedded-agent-helpers.js";
|
||||
import { detectImageReferences, loadImageFromRef } from "../embedded-agent-runner/run/images.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AcpRuntimeEvent } from "@openclaw/acp-core/runtime/types";
|
||||
import { sanitizeForLog } from "../../../packages/terminal-core/src/ansi.js";
|
||||
import { formatAcpErrorChain } from "../../acp/runtime/errors.js";
|
||||
import type { AcpRuntimeEvent } from "../../acp/runtime/types.js";
|
||||
import { normalizeReplyPayload } from "../../auto-reply/reply/normalize-reply.js";
|
||||
import type { ThinkLevel, VerboseLevel } from "../../auto-reply/thinking.js";
|
||||
import { appendSessionTranscriptMessage } from "../../config/sessions/transcript-append.js";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import { MAX_IMAGE_BYTES } from "@openclaw/media-core/constants";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { isAcpRuntimeSpawnAvailable } from "../../../acp/runtime/availability.js";
|
||||
import { buildHierarchyReinforcementMessage } from "../../../auto-reply/handoff-summarizer.js";
|
||||
@@ -34,7 +35,6 @@ import { resolveHeartbeatSummaryForAgent } from "../../../infra/heartbeat-summar
|
||||
import { getMachineDisplayName } from "../../../infra/machine-name.js";
|
||||
import { createCodexNativeWebSearchWrapper } from "../../../llm/providers/stream-wrappers/openai.js";
|
||||
import type { AssistantMessage } from "../../../llm/types.js";
|
||||
import { MAX_IMAGE_BYTES } from "../../../media/constants.js";
|
||||
import { listRegisteredPluginAgentPromptGuidance } from "../../../plugins/command-registry-state.js";
|
||||
import { getCurrentPluginMetadataSnapshot } from "../../../plugins/current-plugin-metadata-snapshot.js";
|
||||
import { buildAgentHookContextChannelFields } from "../../../plugins/hook-agent-context.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { basenameFromAnyPath } from "@openclaw/media-core/file-name";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { uniqueStrings } from "@openclaw/normalization-core/string-normalization";
|
||||
import { basenameFromAnyPath } from "../media/file-name.js";
|
||||
|
||||
export type AgentGeneratedAttachment = {
|
||||
type?: "image" | "audio" | "video" | "file";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import crypto from "node:crypto";
|
||||
import { estimateBase64DecodedBytes } from "@openclaw/media-core/base64";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import { estimateBase64DecodedBytes } from "../media/base64.js";
|
||||
|
||||
const REDACTED_IMAGE_DATA = "<redacted>";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export { asFiniteNumber } from "../../packages/normalization-core/src/number-coercion.js";
|
||||
import { readResponseWithLimit } from "@openclaw/media-core/read-response-with-limit";
|
||||
import { normalizeOptionalString as trimToUndefined } from "../../packages/normalization-core/src/string-coerce.js";
|
||||
import { redactSensitiveText } from "../logging/redact.js";
|
||||
import { readResponseWithLimit } from "../media/read-response-with-limit.js";
|
||||
export { asBoolean } from "../utils/boolean.js";
|
||||
export { normalizeOptionalString as trimToUndefined } from "../../packages/normalization-core/src/string-coerce.js";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { sanitizeInlineImageDataUrl as sanitizeSharedInlineImageDataUrl } from "@openclaw/media-core/inline-image-data-url";
|
||||
import { isRecord } from "@openclaw/normalization-core/record-coerce";
|
||||
import { sanitizeInlineImageDataUrl as sanitizeSharedInlineImageDataUrl } from "../media/inline-image-data-url.js";
|
||||
|
||||
const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { URL } from "node:url";
|
||||
import { isPassThroughRemoteMediaSource } from "@openclaw/media-core/media-source-url";
|
||||
import { isWindowsDrivePath } from "../infra/archive-path.js";
|
||||
import {
|
||||
assertNoWindowsNetworkPath,
|
||||
@@ -10,7 +11,6 @@ import {
|
||||
import { assertNoPathAliasEscape, type PathAliasPolicy } from "../infra/path-alias-guards.js";
|
||||
import { isPathInside } from "../infra/path-guards.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
|
||||
import { isPassThroughRemoteMediaSource } from "../media/media-source-url.js";
|
||||
import { resolveConfigDir } from "../utils.js";
|
||||
|
||||
const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { canonicalizeBase64 } from "@openclaw/media-core/base64";
|
||||
import { resolveIntegerOption } from "@openclaw/normalization-core/number-coercion";
|
||||
import type { ImageContent } from "../llm/types.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { canonicalizeBase64 } from "../media/base64.js";
|
||||
import {
|
||||
buildImageResizeSideGrid,
|
||||
getImageMetadata,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { detectMime } from "@openclaw/media-core/mime";
|
||||
import {
|
||||
asPositiveSafeInteger,
|
||||
asSafeIntegerInRange,
|
||||
@@ -6,7 +7,6 @@ import {
|
||||
import { normalizeStringEntries } from "@openclaw/normalization-core/string-normalization";
|
||||
import type { TSchema } from "typebox";
|
||||
import { readLocalFileSafely } from "../../infra/fs-safe.js";
|
||||
import { detectMime } from "../../media/mime.js";
|
||||
import { readSnakeCaseParamRaw } from "../../param-key.js";
|
||||
import type { ImageSanitizationLimits } from "../image-sanitization.js";
|
||||
import type {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { estimateBase64DecodedBytes } from "@openclaw/media-core/base64";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { AssistantMessage } from "../../llm/types.js";
|
||||
import { estimateBase64DecodedBytes } from "../../media/base64.js";
|
||||
import { extractAssistantText } from "../embedded-agent-utils.js";
|
||||
import { isMinimaxVlmProvider } from "../minimax-vlm.js";
|
||||
import { findNormalizedProviderValue, normalizeProviderId } from "../model-selection.js";
|
||||
|
||||
@@ -2,10 +2,10 @@ import fsSync from "node:fs";
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { isInboundPathAllowed } from "@openclaw/media-core/inbound-path-policy";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { ModelDefinitionConfig } from "../../config/types.models.js";
|
||||
import { isInboundPathAllowed } from "../../media/inbound-path-policy.js";
|
||||
import { encodePngRgba, fillPixel } from "../../media/png-encode.js";
|
||||
import type {
|
||||
ImageDescriptionRequest,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeInboundPathRoots } from "@openclaw/media-core/inbound-path-policy";
|
||||
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
@@ -13,7 +14,6 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { SsrFPolicy } from "../../infra/net/ssrf.js";
|
||||
import type { Model } from "../../llm/types.js";
|
||||
import { resolveChannelInboundAttachmentRootsForChannel } from "../../media/channel-inbound-roots.js";
|
||||
import { normalizeInboundPathRoots } from "../../media/inbound-path-policy.js";
|
||||
import { getDefaultLocalRoots } from "../../media/local-media-access.js";
|
||||
import { readSnakeCaseParamRaw } from "../../param-key.js";
|
||||
import { loadCapabilityManifestSnapshot } from "../../plugins/capability-provider-runtime.js";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import crypto from "node:crypto";
|
||||
import { imageMimeFromFormat } from "@openclaw/media-core/mime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
|
||||
import {
|
||||
type CameraFacing,
|
||||
@@ -14,7 +15,6 @@ import {
|
||||
writeScreenRecordToFile,
|
||||
} from "../../cli/nodes-screen.js";
|
||||
import { parseDurationMs } from "../../cli/parse-duration.js";
|
||||
import { imageMimeFromFormat } from "../../media/mime.js";
|
||||
import type { ImageSanitizationLimits } from "../image-sanitization.js";
|
||||
import type { AgentToolResult } from "../runtime/index.js";
|
||||
import { sanitizeToolResultImages } from "../tool-images.js";
|
||||
|
||||
@@ -175,6 +175,9 @@ describe("skill_workshop tool", () => {
|
||||
status: "pending",
|
||||
query: "!!!",
|
||||
});
|
||||
expect((punctuationOnly.content[0] as { text: string }).text).toBe(
|
||||
"No skill proposals matched.",
|
||||
);
|
||||
expect((punctuationOnly.details as { proposals: unknown[] }).proposals).toEqual([]);
|
||||
|
||||
const inspected = await tool.execute("call-4", {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MAX_VIDEO_BYTES } from "@openclaw/media-core/constants";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { MAX_VIDEO_BYTES } from "../../media/constants.js";
|
||||
import * as mediaStore from "../../media/store.js";
|
||||
import * as webMedia from "../../media/web-media.js";
|
||||
import {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { AcpRuntimeEvent, AcpSessionUpdateTag } from "@openclaw/acp-core/runtime/types";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "@openclaw/normalization-core/string-coerce";
|
||||
import type { AcpRuntimeEvent, AcpSessionUpdateTag } from "../../acp/runtime/types.js";
|
||||
import { EmbeddedBlockChunker } from "../../agents/embedded-agent-block-chunker.js";
|
||||
import { formatToolSummary, resolveToolDisplay } from "../../agents/tool-display.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AcpSessionUpdateTag } from "../../acp/runtime/types.js";
|
||||
import type { AcpSessionUpdateTag } from "@openclaw/acp-core/runtime/types";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { clampPositiveInteger, resolveEffectiveBlockStreamingConfig } from "./block-streaming.js";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { isAudioFileName } from "@openclaw/media-core/mime";
|
||||
import {
|
||||
hasOutboundReplyContent,
|
||||
resolveSendableOutboundReplyParts,
|
||||
} from "openclaw/plugin-sdk/reply-payload";
|
||||
import { loadSessionStore } from "../../config/sessions.js";
|
||||
import { isAudioFileName } from "../../media/mime.js";
|
||||
import { normalizeVerboseLevel, type VerboseLevel } from "../thinking.js";
|
||||
import type { ReplyPayload } from "../types.js";
|
||||
import type { TypingSignaler } from "./typing-mode.js";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { AcpRuntimeSessionMode } from "@openclaw/acp-core/runtime/types";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "@openclaw/normalization-core/string-coerce";
|
||||
import { toAcpRuntimeErrorText } from "../../../acp/runtime/error-text.js";
|
||||
import type { AcpRuntimeError } from "../../../acp/runtime/errors.js";
|
||||
import type { AcpRuntimeSessionMode } from "../../../acp/runtime/types.js";
|
||||
import { supportsAutomaticThreadBindingSpawn } from "../../../channels/thread-bindings-policy.js";
|
||||
import type { AcpSessionRuntimeOptions } from "../../../config/sessions/types.js";
|
||||
import { normalizeAgentId } from "../../../routing/session-key.js";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { mimeTypeFromFilePath } from "@openclaw/media-core/mime";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import type { ImageContent } from "../../llm/types.js";
|
||||
import { mimeTypeFromFilePath } from "../../media/mime.js";
|
||||
import type { PromptImageOrderEntry } from "../../media/prompt-image-order.js";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import { resolveAgentTurnAttachments } from "./agent-turn-attachments.js";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { mimeTypeFromFilePath } from "@openclaw/media-core/mime";
|
||||
import { asFiniteNumber } from "@openclaw/normalization-core/number-coercion";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { mimeTypeFromFilePath } from "../../media/mime.js";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import type { HistoryEntry, HistoryMediaEntry } from "./history.types.js";
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from "node:path";
|
||||
import { isPassThroughRemoteMediaSource } from "@openclaw/media-core/media-source-url";
|
||||
import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
||||
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
||||
import { resolvePathFromInput, toRelativeWorkspacePath } from "../../agents/path-policy.js";
|
||||
@@ -11,7 +12,6 @@ import { ensureSandboxWorkspaceForSession } from "../../agents/sandbox.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { resolveChannelAccountMediaMaxMb } from "../../media/configured-max-bytes.js";
|
||||
import { isPassThroughRemoteMediaSource } from "../../media/media-source-url.js";
|
||||
import { resolveOutboundAttachmentFromUrl } from "../../media/outbound-attachment.js";
|
||||
import { resolveAgentScopedOutboundMediaAccess } from "../../media/read-capability.js";
|
||||
import { MEDIA_MAX_BYTES } from "../../media/store.js";
|
||||
|
||||
@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { isInboundPathAllowed } from "@openclaw/media-core/inbound-path-policy";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { assertSandboxPath } from "../../agents/sandbox-paths.js";
|
||||
import { ensureSandboxWorkspaceForSession } from "../../agents/sandbox.js";
|
||||
@@ -12,7 +13,6 @@ import { root as fsRoot, FsSafeError } from "../../infra/fs-safe.js";
|
||||
import { normalizeScpRemoteHost, normalizeScpRemotePath } from "../../infra/scp-host.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../../infra/tmp-openclaw-dir.js";
|
||||
import { resolveChannelRemoteInboundAttachmentRoots } from "../../media/channel-inbound-roots.js";
|
||||
import { isInboundPathAllowed } from "../../media/inbound-path-policy.js";
|
||||
import { resolveInboundMediaReference } from "../../media/media-reference.js";
|
||||
import { getMediaDir, MEDIA_MAX_BYTES } from "../../media/store.js";
|
||||
import { CONFIG_DIR } from "../../utils.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { setImmediate as realSetImmediate } from "node:timers";
|
||||
import { setImmediate as nextMacrotask } from "node:timers/promises";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js";
|
||||
import { createDraftStreamLoop } from "./draft-stream-loop.js";
|
||||
@@ -9,7 +9,7 @@ const flushMicrotasks = async () => {
|
||||
};
|
||||
|
||||
const flushMacrotask = async () => {
|
||||
await new Promise<void>((resolve) => realSetImmediate(resolve));
|
||||
await nextMacrotask();
|
||||
};
|
||||
|
||||
async function waitForBackgroundFlushError(
|
||||
|
||||
@@ -32,6 +32,10 @@ function isMentionPatternsPolicyConfig(value: unknown): value is MentionPatterns
|
||||
return value != null && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return value != null && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function resolveProviderMentionPatternsPolicy(
|
||||
cfg: OpenClawConfig | undefined,
|
||||
provider: string | undefined,
|
||||
@@ -39,7 +43,8 @@ function resolveProviderMentionPatternsPolicy(
|
||||
if (!cfg || !provider) {
|
||||
return undefined;
|
||||
}
|
||||
const policy = cfg.channels?.[provider]?.mentionPatterns;
|
||||
const channelConfig = cfg.channels?.[provider];
|
||||
const policy = isRecord(channelConfig) ? channelConfig.mentionPatterns : undefined;
|
||||
return isMentionPatternsPolicyConfig(policy) ? policy : undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ type ChannelConfigWithAccounts = {
|
||||
};
|
||||
|
||||
type ConfigWritePolicyConfig = {
|
||||
channels?: Record<string, ChannelConfigWithAccounts>;
|
||||
channels?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type ConfigWriteScopeLike<TChannelId extends string = string> = {
|
||||
@@ -55,7 +55,10 @@ function resolveChannelConfig(
|
||||
if (!channelId) {
|
||||
return undefined;
|
||||
}
|
||||
return cfg.channels?.[channelId];
|
||||
const channelConfig = cfg.channels?.[channelId];
|
||||
return channelConfig != null && typeof channelConfig === "object" && !Array.isArray(channelConfig)
|
||||
? (channelConfig as ChannelConfigWithAccounts)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function resolveChannelAccountConfig(
|
||||
|
||||
@@ -25,6 +25,18 @@ type DirectSendFn<TOpts extends Record<string, unknown>, TResult extends DirectS
|
||||
text: string,
|
||||
opts: TOpts,
|
||||
) => Promise<TResult>;
|
||||
|
||||
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
||||
return value != null && typeof value === "object" && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function readNumberField(record: Record<string, unknown> | undefined, key: string) {
|
||||
const value = record?.[key];
|
||||
return typeof value === "number" ? value : undefined;
|
||||
}
|
||||
|
||||
export {
|
||||
resolvePayloadMediaUrls,
|
||||
sendPayloadMediaSequence,
|
||||
@@ -50,9 +62,14 @@ export function createScopedChannelMediaMaxBytesResolver(channel: string) {
|
||||
resolveScopedChannelMediaMaxBytes({
|
||||
cfg: params.cfg,
|
||||
accountId: params.accountId,
|
||||
resolveChannelLimitMb: ({ cfg, accountId }) =>
|
||||
(cfg.channels?.[channel]?.accounts?.[accountId] as { mediaMaxMb?: number } | undefined)
|
||||
?.mediaMaxMb ?? cfg.channels?.[channel]?.mediaMaxMb,
|
||||
resolveChannelLimitMb: ({ cfg, accountId }) => {
|
||||
const channelConfig = asRecord(cfg.channels?.[channel]);
|
||||
const accountConfig = asRecord(asRecord(channelConfig?.accounts)?.[accountId]);
|
||||
return (
|
||||
readNumberField(accountConfig, "mediaMaxMb") ??
|
||||
readNumberField(channelConfig, "mediaMaxMb")
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ function rebindChannelConfig(
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
[sourceChannelId]: (cfg.channels as Record<string, unknown>)[targetChannelId],
|
||||
[sourceChannelId]: cfg.channels[targetChannelId],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,6 +32,20 @@ function loadProviderAuthInput() {
|
||||
return providerAuthInputPromise;
|
||||
}
|
||||
|
||||
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
||||
return value != null && typeof value === "object" && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function asAllowFromList(value: unknown): ReadonlyArray<string | number> | undefined {
|
||||
return Array.isArray(value)
|
||||
? value.filter(
|
||||
(entry): entry is string | number => typeof entry === "string" || typeof entry === "number",
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export const promptAccountId: PromptAccountId = async (params: PromptAccountIdParams) => {
|
||||
const existingIds = params.listAccountIds(params.cfg);
|
||||
const initial = params.currentId?.trim() || params.defaultAccountId || DEFAULT_ACCOUNT_ID;
|
||||
@@ -537,14 +551,17 @@ export function setChannelDmPolicyWithAllowFrom(params: {
|
||||
dmPolicy: DmPolicy;
|
||||
}): OpenClawConfig {
|
||||
const { cfg, channel, dmPolicy } = params;
|
||||
const channelConfig = asRecord(cfg.channels?.[channel]);
|
||||
const allowFrom =
|
||||
dmPolicy === "open" ? addWildcardAllowFrom(cfg.channels?.[channel]?.allowFrom) : undefined;
|
||||
dmPolicy === "open"
|
||||
? addWildcardAllowFrom(asAllowFromList(channelConfig?.allowFrom))
|
||||
: undefined;
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
[channel]: {
|
||||
...cfg.channels?.[channel],
|
||||
...channelConfig,
|
||||
dmPolicy,
|
||||
...(allowFrom ? { allowFrom } : {}),
|
||||
},
|
||||
|
||||
@@ -80,14 +80,6 @@ describe("createTypingCallbacks", () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (vi.isFakeTimers()) {
|
||||
vi.clearAllTimers();
|
||||
}
|
||||
vi.useRealTimers();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("invokes start on reply start", async () => {
|
||||
const { start, onStartError, callbacks } = createTypingHarness();
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { Readable } from "node:stream";
|
||||
import { pipeline } from "node:stream/promises";
|
||||
import { detectMime, extensionForMime, normalizeMimeType } from "@openclaw/media-core/mime";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
@@ -61,7 +62,6 @@ import {
|
||||
transcribeAudioFile,
|
||||
} from "../media-understanding/runtime.js";
|
||||
import { convertHeicToJpeg, getImageMetadata } from "../media/media-services.js";
|
||||
import { detectMime, extensionForMime, normalizeMimeType } from "../media/mime.js";
|
||||
import { saveMediaBuffer } from "../media/store.js";
|
||||
import {
|
||||
createEmbeddingProvider,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AcpSessionUpdateTag } from "../acp/runtime/types.js";
|
||||
import type { AcpSessionUpdateTag } from "@openclaw/acp-core/runtime/types";
|
||||
|
||||
export type AcpDispatchConfig = {
|
||||
/** Master switch for ACP turn dispatch in the reply pipeline. */
|
||||
|
||||
@@ -38,6 +38,16 @@ export type ExtensionNestedPolicyConfig = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export type ExtensionAccountConfig = ExtensionNestedPolicyConfig & {
|
||||
defaultTo?: string | number;
|
||||
dmPolicy?: string;
|
||||
dm?: ExtensionNestedPolicyConfig;
|
||||
mediaMaxMb?: number;
|
||||
configWrites?: boolean;
|
||||
};
|
||||
|
||||
type OpenWorldChannelConfig = ReturnType<typeof JSON.parse>;
|
||||
|
||||
/**
|
||||
* Base type for extension channel config sections.
|
||||
* Extensions can use this as a starting point for their channel config.
|
||||
@@ -51,7 +61,7 @@ export type ExtensionChannelConfig = {
|
||||
defaultAccount?: string;
|
||||
dmPolicy?: string;
|
||||
groupPolicy?: GroupPolicy;
|
||||
mentionPatterns?: MentionPatternsPolicyConfig;
|
||||
mentionPatterns?: MentionPatternsPolicyConfig | string[];
|
||||
contextVisibility?: ContextVisibilityMode;
|
||||
healthMonitor?: ChannelHealthMonitorConfig;
|
||||
dm?: ExtensionNestedPolicyConfig;
|
||||
@@ -74,7 +84,7 @@ export type ExtensionChannelConfig = {
|
||||
botLoopProtection?: ChannelBotLoopProtectionConfig;
|
||||
spawnSubagentSessions?: boolean;
|
||||
dangerouslyAllowPrivateNetwork?: boolean;
|
||||
accounts?: Record<string, unknown>;
|
||||
accounts?: Record<string, ExtensionAccountConfig>;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
@@ -93,10 +103,7 @@ export interface ChannelsConfig {
|
||||
whatsapp?: WhatsAppConfig;
|
||||
/**
|
||||
* Channel sections are plugin-owned and keyed by arbitrary channel ids.
|
||||
* Keep the lookup permissive so augmented channel configs remain ergonomic at call sites.
|
||||
* Open-world config keeps SDK/plugin-owned sections ergonomic for dynamic ids.
|
||||
*/
|
||||
// Plugin-owned channel sections are open-world config; narrowing this breaks
|
||||
// SDK config-write helpers that accept account-shaped channel records.
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
[key: string]: any;
|
||||
[key: string]: OpenWorldChannelConfig;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { isValidInboundPathRootPattern } from "@openclaw/media-core/inbound-path-policy";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { z } from "zod";
|
||||
import { isSafeScpRemoteHost } from "../infra/scp-host.js";
|
||||
import { isValidInboundPathRootPattern } from "../media/inbound-path-policy.js";
|
||||
import {
|
||||
normalizeCommandDescription,
|
||||
normalizeSlashCommandName,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { isAudioFileName } from "@openclaw/media-core/mime";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { retireSessionMcpRuntime } from "../../agents/agent-bundle-mcp-tools.js";
|
||||
import type { ReplyPayload } from "../../auto-reply/reply-payload.js";
|
||||
@@ -31,7 +32,6 @@ import {
|
||||
import type { SourceDeliveryOutcome } from "../../infra/outbound/source-delivery-plan.js";
|
||||
import { normalizeTargetForProvider } from "../../infra/outbound/target-normalization.js";
|
||||
import { hasReplyPayloadContent } from "../../interactive/payload.js";
|
||||
import { isAudioFileName } from "../../media/mime.js";
|
||||
import { stringifyRouteThreadId } from "../../plugin-sdk/channel-route.js";
|
||||
import {
|
||||
isCronSessionKey,
|
||||
|
||||
@@ -21,8 +21,8 @@ vi.mock("../media/store.js", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
import { MAX_IMAGE_BYTES } from "@openclaw/media-core/constants";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { MAX_IMAGE_BYTES } from "../media/constants.js";
|
||||
import {
|
||||
buildMessageWithAttachments,
|
||||
type ChatAttachment,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { estimateBase64DecodedBytes } from "@openclaw/media-core/base64";
|
||||
import { MAX_IMAGE_BYTES } from "@openclaw/media-core/constants";
|
||||
import { extensionForMime, mimeTypeFromFilePath } from "@openclaw/media-core/mime";
|
||||
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { estimateBase64DecodedBytes } from "../media/base64.js";
|
||||
import { MAX_IMAGE_BYTES } from "../media/constants.js";
|
||||
import { extensionForMime, mimeTypeFromFilePath } from "../media/mime.js";
|
||||
import type { PromptImageOrderEntry } from "../media/prompt-image-order.js";
|
||||
import { sniffMimeFromBase64 } from "../media/sniff-mime-from-base64.js";
|
||||
import { deleteMediaBuffer, saveMediaBuffer } from "../media/store.js";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user