mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
refactor: extract web content core package (#88346)
Extract web-content shared runtime helpers into packages/web-content-core, move the focused tests with the new package, and split quiet CI shards so the node matrix no longer stalls past the no-output watchdog.\n\nVerification: node scripts/run-vitest.mjs test/scripts/ci-node-test-plan.test.ts test/scripts/run-vitest.test.ts src/infra/restart.test.ts src/infra/os-summary.test.ts src/infra/gateway-processes.test.ts src/infra/inline-option-token.test.ts src/infra/map-size.test.ts src/infra/machine-name.test.ts src/commands/doctor-whatsapp-responsiveness.test.ts; autoreview clean; manual CI https://github.com/openclaw/openclaw/actions/runs/26693962844; dependency guard https://github.com/openclaw/openclaw/actions/runs/26693959937. Admin merge used because optional Mantis Telegram Desktop proof was cancelled after blocking merge outside this PR's required proof.
This commit is contained in:
committed by
GitHub
parent
c6b1fede5a
commit
a20b2dc740
2
packages/web-content-core/dist/index.d.mts
vendored
Normal file
2
packages/web-content-core/dist/index.d.mts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { WebProviderConfigSource, hasWebProviderEntryCredential, providerRequiresCredential, readWebProviderEnvValue, resolveWebProviderConfig, resolveWebProviderDefinition } from "./provider-runtime-shared.mjs";
|
||||
export { WebProviderConfigSource, hasWebProviderEntryCredential, providerRequiresCredential, readWebProviderEnvValue, resolveWebProviderConfig, resolveWebProviderDefinition };
|
||||
2
packages/web-content-core/dist/index.mjs
vendored
Normal file
2
packages/web-content-core/dist/index.mjs
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { hasWebProviderEntryCredential, providerRequiresCredential, readWebProviderEnvValue, resolveWebProviderConfig, resolveWebProviderDefinition } from "./provider-runtime-shared.mjs";
|
||||
export { hasWebProviderEntryCredential, providerRequiresCredential, readWebProviderEnvValue, resolveWebProviderConfig, resolveWebProviderDefinition };
|
||||
78
packages/web-content-core/dist/provider-runtime-shared.d.mts
vendored
Normal file
78
packages/web-content-core/dist/provider-runtime-shared.d.mts
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
//#region packages/web-content-core/src/provider-runtime-shared.d.ts
|
||||
type WebProviderConfigSource = {
|
||||
tools?: {
|
||||
web?: {
|
||||
search?: unknown;
|
||||
fetch?: unknown;
|
||||
};
|
||||
};
|
||||
};
|
||||
type RuntimeWebProviderMetadata = {
|
||||
providerConfigured?: string;
|
||||
selectedProvider?: string;
|
||||
};
|
||||
type ProviderWithCredential = {
|
||||
envVars: string[];
|
||||
authProviderId?: string;
|
||||
requiresCredential?: boolean;
|
||||
};
|
||||
type WebContentProcessEnv = Record<string, string | undefined>;
|
||||
declare function resolveWebProviderConfig(cfg: WebProviderConfigSource | undefined, kind: "search" | "fetch"): Record<string, unknown> | undefined;
|
||||
declare function readWebProviderEnvValue(envVars: string[], processEnv?: WebContentProcessEnv): string | undefined;
|
||||
declare function providerRequiresCredential(provider: Pick<ProviderWithCredential, "requiresCredential">): boolean;
|
||||
declare function hasWebProviderEntryCredential<TProvider extends ProviderWithCredential, TConfigSource extends WebProviderConfigSource, TConfig extends Record<string, unknown> | undefined>(params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
resolveRawValue: (params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
}) => unknown;
|
||||
resolveFallbackRawValue?: (params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
}) => unknown;
|
||||
resolveEnvValue: (params: {
|
||||
provider: TProvider;
|
||||
configuredEnvVarId?: string;
|
||||
}) => string | undefined;
|
||||
resolveProviderAuthValue?: (providerId: string) => boolean;
|
||||
}): boolean;
|
||||
declare function resolveWebProviderDefinition<TProvider extends {
|
||||
id: string;
|
||||
}, TConfigSource extends WebProviderConfigSource, TConfig extends Record<string, unknown> | undefined, TRuntimeMetadata extends RuntimeWebProviderMetadata, TDefinition>(params: {
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
runtimeMetadata: TRuntimeMetadata | undefined;
|
||||
sandboxed?: boolean;
|
||||
providerId?: string;
|
||||
providers: TProvider[];
|
||||
resolveEnabled: (params: {
|
||||
toolConfig: TConfig;
|
||||
sandboxed?: boolean;
|
||||
}) => boolean;
|
||||
resolveAutoProviderId: (params: {
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
providers: TProvider[];
|
||||
}) => string;
|
||||
resolveFallbackProviderId?: (params: {
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
providers: TProvider[];
|
||||
providerId: string;
|
||||
}) => string | undefined;
|
||||
createTool: (params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
runtimeMetadata: TRuntimeMetadata | undefined;
|
||||
}) => TDefinition | null;
|
||||
}): {
|
||||
provider: TProvider;
|
||||
definition: TDefinition;
|
||||
} | null;
|
||||
//#endregion
|
||||
export { WebProviderConfigSource, hasWebProviderEntryCredential, providerRequiresCredential, readWebProviderEnvValue, resolveWebProviderConfig, resolveWebProviderDefinition };
|
||||
136
packages/web-content-core/dist/provider-runtime-shared.mjs
vendored
Normal file
136
packages/web-content-core/dist/provider-runtime-shared.mjs
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
//#region packages/web-content-core/src/provider-runtime-shared.ts
|
||||
const DEFAULT_SECRET_PROVIDER_ALIAS = "default";
|
||||
const ENV_SECRET_REF_ID_RE = /^[A-Z][A-Z0-9_]{0,127}$/;
|
||||
const LEGACY_SECRETREF_ENV_MARKER_PREFIX = "secretref-env:";
|
||||
const LEGACY_DOUBLE_UNDERSCORE_ENV_MARKER_PREFIX = "__env__:";
|
||||
const ENV_SECRET_TEMPLATE_RE = /^\$\{([A-Z][A-Z0-9_]{0,127})\}$/;
|
||||
const ENV_SECRET_SHORTHAND_RE = /^\$([A-Z][A-Z0-9_]{0,127})$/;
|
||||
function isRecord(value) {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
function normalizeSecretInputString(value) {
|
||||
if (typeof value !== "string") return;
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : void 0;
|
||||
}
|
||||
function normalizeSecretInput(value) {
|
||||
if (typeof value !== "string") return "";
|
||||
const collapsed = value.replace(/[\r\n\u2028\u2029]+/g, "");
|
||||
let latin1Only = "";
|
||||
for (const char of collapsed) {
|
||||
const codePoint = char.codePointAt(0);
|
||||
if (typeof codePoint === "number" && codePoint <= 255) latin1Only += char;
|
||||
}
|
||||
return latin1Only.trim();
|
||||
}
|
||||
function isSecretRef(value) {
|
||||
if (!isRecord(value)) return false;
|
||||
if (Object.keys(value).length !== 3) return false;
|
||||
return (value.source === "env" || value.source === "file" || value.source === "exec") && typeof value.provider === "string" && value.provider.trim().length > 0 && typeof value.id === "string" && value.id.trim().length > 0;
|
||||
}
|
||||
function coerceSecretRef(value) {
|
||||
if (isSecretRef(value)) return value;
|
||||
if (typeof value === "string") {
|
||||
const trimmed = value.trim();
|
||||
const legacyPrefix = trimmed.startsWith(LEGACY_SECRETREF_ENV_MARKER_PREFIX) ? LEGACY_SECRETREF_ENV_MARKER_PREFIX : trimmed.startsWith(LEGACY_DOUBLE_UNDERSCORE_ENV_MARKER_PREFIX) ? LEGACY_DOUBLE_UNDERSCORE_ENV_MARKER_PREFIX : void 0;
|
||||
if (legacyPrefix) {
|
||||
const id = trimmed.slice(legacyPrefix.length);
|
||||
return ENV_SECRET_REF_ID_RE.test(id) ? {
|
||||
source: "env",
|
||||
provider: DEFAULT_SECRET_PROVIDER_ALIAS,
|
||||
id
|
||||
} : null;
|
||||
}
|
||||
const match = ENV_SECRET_TEMPLATE_RE.exec(trimmed) ?? ENV_SECRET_SHORTHAND_RE.exec(trimmed);
|
||||
return match ? {
|
||||
source: "env",
|
||||
provider: DEFAULT_SECRET_PROVIDER_ALIAS,
|
||||
id: match[1]
|
||||
} : null;
|
||||
}
|
||||
if (isRecord(value) && (value.source === "env" || value.source === "file" || value.source === "exec") && typeof value.id === "string" && value.id.trim().length > 0 && value.provider === void 0) return {
|
||||
source: value.source,
|
||||
provider: DEFAULT_SECRET_PROVIDER_ALIAS,
|
||||
id: value.id
|
||||
};
|
||||
return null;
|
||||
}
|
||||
function resolveWebProviderConfig(cfg, kind) {
|
||||
const webConfig = cfg?.tools?.web;
|
||||
if (!webConfig || typeof webConfig !== "object") return;
|
||||
const toolConfig = webConfig[kind];
|
||||
if (!toolConfig || typeof toolConfig !== "object") return;
|
||||
return toolConfig;
|
||||
}
|
||||
function readWebProviderEnvValue(envVars, processEnv = process.env) {
|
||||
for (const envVar of envVars) {
|
||||
const value = normalizeSecretInput(processEnv[envVar]);
|
||||
if (value) return value;
|
||||
}
|
||||
}
|
||||
function providerRequiresCredential(provider) {
|
||||
return provider.requiresCredential !== false;
|
||||
}
|
||||
function hasWebProviderEntryCredential(params) {
|
||||
if (!providerRequiresCredential(params.provider)) return true;
|
||||
const rawValue = params.resolveRawValue({
|
||||
provider: params.provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig
|
||||
});
|
||||
const configuredRef = coerceSecretRef(rawValue);
|
||||
if (configuredRef && configuredRef.source !== "env") return true;
|
||||
if (normalizeSecretInput(normalizeSecretInputString(rawValue))) return true;
|
||||
if (params.provider.authProviderId && params.resolveProviderAuthValue?.(params.provider.authProviderId)) return true;
|
||||
if (params.resolveEnvValue({
|
||||
provider: params.provider,
|
||||
configuredEnvVarId: configuredRef?.source === "env" ? configuredRef.id : void 0
|
||||
})) return true;
|
||||
const fallbackRawValue = params.resolveFallbackRawValue?.({
|
||||
provider: params.provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig
|
||||
});
|
||||
const fallbackRef = coerceSecretRef(fallbackRawValue);
|
||||
if (fallbackRef && fallbackRef.source !== "env") return true;
|
||||
if (normalizeSecretInput(normalizeSecretInputString(fallbackRawValue))) return true;
|
||||
return Boolean(fallbackRef?.source === "env" ? params.resolveEnvValue({
|
||||
provider: params.provider,
|
||||
configuredEnvVarId: fallbackRef.id
|
||||
}) : void 0);
|
||||
}
|
||||
function resolveWebProviderDefinition(params) {
|
||||
if (!params.resolveEnabled({
|
||||
toolConfig: params.toolConfig,
|
||||
sandboxed: params.sandboxed
|
||||
})) return null;
|
||||
const providers = params.providers.filter(Boolean);
|
||||
if (providers.length === 0) return null;
|
||||
const autoProviderId = params.resolveAutoProviderId({
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
providers
|
||||
});
|
||||
const providerId = params.providerId ?? params.runtimeMetadata?.selectedProvider ?? autoProviderId;
|
||||
if (!providerId) return null;
|
||||
const provider = providers.find((entry) => entry.id === providerId) ?? providers.find((entry) => entry.id === params.resolveFallbackProviderId?.({
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
providers,
|
||||
providerId
|
||||
}));
|
||||
if (!provider) return null;
|
||||
const definition = params.createTool({
|
||||
provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
runtimeMetadata: params.runtimeMetadata
|
||||
});
|
||||
if (!definition) return null;
|
||||
return {
|
||||
provider,
|
||||
definition
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
export { hasWebProviderEntryCredential, providerRequiresCredential, readWebProviderEnvValue, resolveWebProviderConfig, resolveWebProviderDefinition };
|
||||
26
packages/web-content-core/package.json
Normal file
26
packages/web-content-core/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@openclaw/web-content-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"
|
||||
},
|
||||
"./provider-runtime-shared": {
|
||||
"types": "./dist/provider-runtime-shared.d.mts",
|
||||
"import": "./dist/provider-runtime-shared.mjs",
|
||||
"default": "./dist/provider-runtime-shared.mjs"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsdown src/index.ts src/provider-runtime-shared.ts --no-config --platform node --format esm --dts --out-dir dist --clean"
|
||||
}
|
||||
}
|
||||
1
packages/web-content-core/src/index.ts
Normal file
1
packages/web-content-core/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./provider-runtime-shared.js";
|
||||
117
packages/web-content-core/src/provider-runtime-shared.test.ts
Normal file
117
packages/web-content-core/src/provider-runtime-shared.test.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
hasWebProviderEntryCredential,
|
||||
readWebProviderEnvValue,
|
||||
resolveWebProviderConfig,
|
||||
resolveWebProviderDefinition,
|
||||
} from "./provider-runtime-shared.js";
|
||||
|
||||
describe("resolveWebProviderConfig", () => {
|
||||
it("selects the requested web tool config", () => {
|
||||
const search = { provider: "search-provider" };
|
||||
|
||||
expect(
|
||||
resolveWebProviderConfig(
|
||||
{
|
||||
tools: {
|
||||
web: {
|
||||
search,
|
||||
},
|
||||
},
|
||||
},
|
||||
"search",
|
||||
),
|
||||
).toBe(search);
|
||||
});
|
||||
});
|
||||
|
||||
describe("readWebProviderEnvValue", () => {
|
||||
it("normalizes env credentials before returning them", () => {
|
||||
expect(readWebProviderEnvValue(["API_KEY"], { API_KEY: " key\r\nvalue🙂 " })).toBe("keyvalue");
|
||||
});
|
||||
});
|
||||
|
||||
describe("hasWebProviderEntryCredential", () => {
|
||||
const provider = {
|
||||
id: "custom",
|
||||
envVars: ["CUSTOM_API_KEY"],
|
||||
};
|
||||
|
||||
it("treats non-env secret refs as configured credentials", () => {
|
||||
expect(
|
||||
hasWebProviderEntryCredential({
|
||||
provider,
|
||||
config: {},
|
||||
toolConfig: undefined,
|
||||
resolveRawValue: () => ({
|
||||
source: "file",
|
||||
provider: "mounted-json",
|
||||
id: "/custom/apiKey",
|
||||
}),
|
||||
resolveEnvValue: () => undefined,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("resolves env secret ref ids through the env resolver", () => {
|
||||
expect(
|
||||
hasWebProviderEntryCredential({
|
||||
provider,
|
||||
config: {},
|
||||
toolConfig: undefined,
|
||||
resolveRawValue: () => ({
|
||||
source: "env",
|
||||
provider: "default",
|
||||
id: "CUSTOM_API_KEY",
|
||||
}),
|
||||
resolveEnvValue: ({ configuredEnvVarId }) =>
|
||||
configuredEnvVarId === "CUSTOM_API_KEY" ? "secret" : undefined,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("falls back to provider auth before env probing", () => {
|
||||
expect(
|
||||
hasWebProviderEntryCredential({
|
||||
provider: {
|
||||
...provider,
|
||||
authProviderId: "custom-auth",
|
||||
},
|
||||
config: {},
|
||||
toolConfig: undefined,
|
||||
resolveRawValue: () => undefined,
|
||||
resolveEnvValue: () => undefined,
|
||||
resolveProviderAuthValue: (providerId) => providerId === "custom-auth",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveWebProviderDefinition", () => {
|
||||
it("falls back to auto-detect when runtime metadata has no selected provider", () => {
|
||||
const resolved = resolveWebProviderDefinition({
|
||||
config: {},
|
||||
toolConfig: { enabled: true },
|
||||
runtimeMetadata: {},
|
||||
providers: [
|
||||
{
|
||||
id: "custom",
|
||||
},
|
||||
],
|
||||
resolveEnabled: () => true,
|
||||
resolveAutoProviderId: () => "custom",
|
||||
createTool: ({ provider }) => ({
|
||||
name: provider.id,
|
||||
}),
|
||||
});
|
||||
|
||||
expect(resolved).toEqual({
|
||||
provider: {
|
||||
id: "custom",
|
||||
},
|
||||
definition: {
|
||||
name: "custom",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
302
packages/web-content-core/src/provider-runtime-shared.ts
Normal file
302
packages/web-content-core/src/provider-runtime-shared.ts
Normal file
@@ -0,0 +1,302 @@
|
||||
export type WebProviderConfigSource = {
|
||||
tools?: {
|
||||
web?: {
|
||||
search?: unknown;
|
||||
fetch?: unknown;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type SecretRefSource = "env" | "file" | "exec";
|
||||
|
||||
type SecretRef = {
|
||||
source: SecretRefSource;
|
||||
provider: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
const DEFAULT_SECRET_PROVIDER_ALIAS = "default";
|
||||
const ENV_SECRET_REF_ID_RE = /^[A-Z][A-Z0-9_]{0,127}$/;
|
||||
const LEGACY_SECRETREF_ENV_MARKER_PREFIX = "secretref-env:";
|
||||
const LEGACY_DOUBLE_UNDERSCORE_ENV_MARKER_PREFIX = "__env__:";
|
||||
const ENV_SECRET_TEMPLATE_RE = /^\$\{([A-Z][A-Z0-9_]{0,127})\}$/;
|
||||
const ENV_SECRET_SHORTHAND_RE = /^\$([A-Z][A-Z0-9_]{0,127})$/;
|
||||
|
||||
type RuntimeWebProviderMetadata = {
|
||||
providerConfigured?: string;
|
||||
selectedProvider?: string;
|
||||
};
|
||||
|
||||
type ProviderWithCredential = {
|
||||
envVars: string[];
|
||||
authProviderId?: string;
|
||||
requiresCredential?: boolean;
|
||||
};
|
||||
|
||||
type WebContentProcessEnv = Record<string, string | undefined>;
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function normalizeSecretInputString(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function normalizeSecretInput(value: unknown): string {
|
||||
if (typeof value !== "string") {
|
||||
return "";
|
||||
}
|
||||
const collapsed = value.replace(/[\r\n\u2028\u2029]+/g, "");
|
||||
let latin1Only = "";
|
||||
for (const char of collapsed) {
|
||||
const codePoint = char.codePointAt(0);
|
||||
if (typeof codePoint === "number" && codePoint <= 0xff) {
|
||||
latin1Only += char;
|
||||
}
|
||||
}
|
||||
return latin1Only.trim();
|
||||
}
|
||||
|
||||
function isSecretRef(value: unknown): value is SecretRef {
|
||||
if (!isRecord(value)) {
|
||||
return false;
|
||||
}
|
||||
if (Object.keys(value).length !== 3) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
(value.source === "env" || value.source === "file" || value.source === "exec") &&
|
||||
typeof value.provider === "string" &&
|
||||
value.provider.trim().length > 0 &&
|
||||
typeof value.id === "string" &&
|
||||
value.id.trim().length > 0
|
||||
);
|
||||
}
|
||||
|
||||
function coerceSecretRef(value: unknown): SecretRef | null {
|
||||
if (isSecretRef(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
const trimmed = value.trim();
|
||||
const legacyPrefix = trimmed.startsWith(LEGACY_SECRETREF_ENV_MARKER_PREFIX)
|
||||
? LEGACY_SECRETREF_ENV_MARKER_PREFIX
|
||||
: trimmed.startsWith(LEGACY_DOUBLE_UNDERSCORE_ENV_MARKER_PREFIX)
|
||||
? LEGACY_DOUBLE_UNDERSCORE_ENV_MARKER_PREFIX
|
||||
: undefined;
|
||||
if (legacyPrefix) {
|
||||
const id = trimmed.slice(legacyPrefix.length);
|
||||
return ENV_SECRET_REF_ID_RE.test(id)
|
||||
? { source: "env", provider: DEFAULT_SECRET_PROVIDER_ALIAS, id }
|
||||
: null;
|
||||
}
|
||||
const match = ENV_SECRET_TEMPLATE_RE.exec(trimmed) ?? ENV_SECRET_SHORTHAND_RE.exec(trimmed);
|
||||
return match ? { source: "env", provider: DEFAULT_SECRET_PROVIDER_ALIAS, id: match[1] } : null;
|
||||
}
|
||||
if (
|
||||
isRecord(value) &&
|
||||
(value.source === "env" || value.source === "file" || value.source === "exec") &&
|
||||
typeof value.id === "string" &&
|
||||
value.id.trim().length > 0 &&
|
||||
value.provider === undefined
|
||||
) {
|
||||
return {
|
||||
source: value.source,
|
||||
provider: DEFAULT_SECRET_PROVIDER_ALIAS,
|
||||
id: value.id,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function resolveWebProviderConfig(
|
||||
cfg: WebProviderConfigSource | undefined,
|
||||
kind: "search" | "fetch",
|
||||
): Record<string, unknown> | undefined {
|
||||
const webConfig = cfg?.tools?.web;
|
||||
if (!webConfig || typeof webConfig !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
const toolConfig = webConfig[kind];
|
||||
if (!toolConfig || typeof toolConfig !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
return toolConfig as Record<string, unknown>;
|
||||
}
|
||||
|
||||
export function readWebProviderEnvValue(
|
||||
envVars: string[],
|
||||
processEnv: WebContentProcessEnv = process.env,
|
||||
): string | undefined {
|
||||
for (const envVar of envVars) {
|
||||
const value = normalizeSecretInput(processEnv[envVar]);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function providerRequiresCredential(
|
||||
provider: Pick<ProviderWithCredential, "requiresCredential">,
|
||||
): boolean {
|
||||
return provider.requiresCredential !== false;
|
||||
}
|
||||
|
||||
export function hasWebProviderEntryCredential<
|
||||
TProvider extends ProviderWithCredential,
|
||||
TConfigSource extends WebProviderConfigSource,
|
||||
TConfig extends Record<string, unknown> | undefined,
|
||||
>(params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
resolveRawValue: (params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
}) => unknown;
|
||||
resolveFallbackRawValue?: (params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
}) => unknown;
|
||||
resolveEnvValue: (params: {
|
||||
provider: TProvider;
|
||||
configuredEnvVarId?: string;
|
||||
}) => string | undefined;
|
||||
resolveProviderAuthValue?: (providerId: string) => boolean;
|
||||
}): boolean {
|
||||
if (!providerRequiresCredential(params.provider)) {
|
||||
return true;
|
||||
}
|
||||
const rawValue = params.resolveRawValue({
|
||||
provider: params.provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
});
|
||||
const configuredRef = coerceSecretRef(rawValue);
|
||||
if (configuredRef && configuredRef.source !== "env") {
|
||||
return true;
|
||||
}
|
||||
const fromConfig = normalizeSecretInput(normalizeSecretInputString(rawValue));
|
||||
if (fromConfig) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
params.provider.authProviderId &&
|
||||
params.resolveProviderAuthValue?.(params.provider.authProviderId)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
params.resolveEnvValue({
|
||||
provider: params.provider,
|
||||
configuredEnvVarId: configuredRef?.source === "env" ? configuredRef.id : undefined,
|
||||
})
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
const fallbackRawValue = params.resolveFallbackRawValue?.({
|
||||
provider: params.provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
});
|
||||
const fallbackRef = coerceSecretRef(fallbackRawValue);
|
||||
if (fallbackRef && fallbackRef.source !== "env") {
|
||||
return true;
|
||||
}
|
||||
const fallbackConfig = normalizeSecretInput(normalizeSecretInputString(fallbackRawValue));
|
||||
if (fallbackConfig) {
|
||||
return true;
|
||||
}
|
||||
return Boolean(
|
||||
fallbackRef?.source === "env"
|
||||
? params.resolveEnvValue({
|
||||
provider: params.provider,
|
||||
configuredEnvVarId: fallbackRef.id,
|
||||
})
|
||||
: undefined,
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveWebProviderDefinition<
|
||||
TProvider extends { id: string },
|
||||
TConfigSource extends WebProviderConfigSource,
|
||||
TConfig extends Record<string, unknown> | undefined,
|
||||
TRuntimeMetadata extends RuntimeWebProviderMetadata,
|
||||
TDefinition,
|
||||
>(params: {
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
runtimeMetadata: TRuntimeMetadata | undefined;
|
||||
sandboxed?: boolean;
|
||||
providerId?: string;
|
||||
providers: TProvider[];
|
||||
resolveEnabled: (params: { toolConfig: TConfig; sandboxed?: boolean }) => boolean;
|
||||
resolveAutoProviderId: (params: {
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
providers: TProvider[];
|
||||
}) => string;
|
||||
resolveFallbackProviderId?: (params: {
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
providers: TProvider[];
|
||||
providerId: string;
|
||||
}) => string | undefined;
|
||||
createTool: (params: {
|
||||
provider: TProvider;
|
||||
config: TConfigSource | undefined;
|
||||
toolConfig: TConfig;
|
||||
runtimeMetadata: TRuntimeMetadata | undefined;
|
||||
}) => TDefinition | null;
|
||||
}): { provider: TProvider; definition: TDefinition } | null {
|
||||
if (!params.resolveEnabled({ toolConfig: params.toolConfig, sandboxed: params.sandboxed })) {
|
||||
return null;
|
||||
}
|
||||
const providers = params.providers.filter(Boolean);
|
||||
if (providers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const autoProviderId = params.resolveAutoProviderId({
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
providers,
|
||||
});
|
||||
const providerId =
|
||||
params.providerId ?? params.runtimeMetadata?.selectedProvider ?? autoProviderId;
|
||||
if (!providerId) {
|
||||
return null;
|
||||
}
|
||||
const provider =
|
||||
providers.find((entry) => entry.id === providerId) ??
|
||||
providers.find(
|
||||
(entry) =>
|
||||
entry.id ===
|
||||
params.resolveFallbackProviderId?.({
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
providers,
|
||||
providerId,
|
||||
}),
|
||||
);
|
||||
if (!provider) {
|
||||
return null;
|
||||
}
|
||||
const definition = params.createTool({
|
||||
provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
runtimeMetadata: params.runtimeMetadata,
|
||||
});
|
||||
if (!definition) {
|
||||
return null;
|
||||
}
|
||||
return { provider, definition };
|
||||
}
|
||||
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
@@ -1853,6 +1853,8 @@ importers:
|
||||
specifier: 5.6.2
|
||||
version: 5.6.2
|
||||
|
||||
packages/web-content-core: {}
|
||||
|
||||
ui:
|
||||
dependencies:
|
||||
'@create-markdown/preview':
|
||||
|
||||
@@ -51,6 +51,7 @@ export const BUILD_ALL_STEPS = [
|
||||
"packages/media-understanding-common/package.json",
|
||||
"packages/terminal-core/package.json",
|
||||
"packages/model-catalog-core/package.json",
|
||||
"packages/web-content-core/package.json",
|
||||
"packages/memory-host-sdk/package.json",
|
||||
"tsconfig.json",
|
||||
"tsconfig.plugin-sdk.dts.json",
|
||||
@@ -62,6 +63,7 @@ export const BUILD_ALL_STEPS = [
|
||||
"packages/media-generation-core/src",
|
||||
"packages/media-understanding-common/src",
|
||||
"packages/terminal-core/src",
|
||||
"packages/web-content-core/src",
|
||||
"src/types",
|
||||
"src/video-generation/dashscope-compatible.ts",
|
||||
"src/video-generation/types.ts",
|
||||
|
||||
@@ -67,38 +67,55 @@ function resolveCommandShardName(file) {
|
||||
if (name.startsWith("agent") || name.startsWith("channel") || name === "message.test.ts") {
|
||||
return "agentic-commands-agent-channel";
|
||||
}
|
||||
if (name.startsWith("oauth-tls-preflight.doctor")) {
|
||||
return "agentic-commands-doctor-auth";
|
||||
}
|
||||
if (name.startsWith("doctor")) {
|
||||
if (name.startsWith("doctor/shared/") || name.startsWith("doctor/")) {
|
||||
return "agentic-commands-doctor-shared";
|
||||
}
|
||||
if (name.startsWith("doctor-auth") || name.startsWith("doctor-claude")) {
|
||||
if (name.startsWith("doctor-auth")) {
|
||||
return "agentic-commands-doctor-auth";
|
||||
}
|
||||
if (name.startsWith("doctor-config") || name.startsWith("doctor-legacy-config")) {
|
||||
return "agentic-commands-doctor-config";
|
||||
}
|
||||
if (name.startsWith("doctor-cron")) {
|
||||
return "agentic-commands-doctor-cron";
|
||||
if (
|
||||
name.startsWith("doctor-config") ||
|
||||
name.startsWith("doctor-legacy-config") ||
|
||||
name.startsWith("doctor-state")
|
||||
) {
|
||||
return "agentic-commands-doctor-config-state";
|
||||
}
|
||||
if (
|
||||
name.startsWith("doctor-gateway") ||
|
||||
name.startsWith("doctor-cron") ||
|
||||
name.startsWith("doctor-heartbeat") ||
|
||||
name.startsWith("doctor-memory") ||
|
||||
name.startsWith("doctor-plugin") ||
|
||||
name.startsWith("doctor-session") ||
|
||||
name.startsWith("doctor-state") ||
|
||||
name.startsWith("doctor-workspace")
|
||||
name.startsWith("doctor-session")
|
||||
) {
|
||||
return "agentic-commands-doctor-runtime";
|
||||
return "agentic-commands-doctor-sessions-cron";
|
||||
}
|
||||
if (name.startsWith("doctor-gateway")) {
|
||||
return "agentic-commands-doctor-gateway";
|
||||
}
|
||||
if (name.startsWith("doctor-device")) {
|
||||
return "agentic-commands-doctor-device";
|
||||
}
|
||||
if (name.startsWith("doctor-platform")) {
|
||||
return "agentic-commands-doctor-platform";
|
||||
}
|
||||
if (name.startsWith("doctor-whatsapp")) {
|
||||
return "agentic-commands-doctor-whatsapp";
|
||||
}
|
||||
if (name.startsWith("doctor-workspace")) {
|
||||
return "agentic-commands-doctor-workspace";
|
||||
}
|
||||
if (
|
||||
name.startsWith("doctor-platform-notes") ||
|
||||
name.startsWith("doctor-sandbox") ||
|
||||
name.startsWith("doctor-whatsapp")
|
||||
name.startsWith("doctor-browser") ||
|
||||
name.startsWith("doctor-plugin") ||
|
||||
name.startsWith("doctor-skill") ||
|
||||
name.startsWith("doctor-memory") ||
|
||||
name.startsWith("doctor-claude")
|
||||
) {
|
||||
return "agentic-commands-doctor-misc-platform";
|
||||
return "agentic-commands-doctor-plugins-tools";
|
||||
}
|
||||
return "agentic-commands-doctor-misc-core";
|
||||
return "agentic-commands-doctor";
|
||||
}
|
||||
if (
|
||||
name.startsWith("auth-choice") ||
|
||||
@@ -131,13 +148,17 @@ function createAgenticCommandSplitShards() {
|
||||
|
||||
return [
|
||||
"agentic-commands-agent-channel",
|
||||
"agentic-commands-doctor",
|
||||
"agentic-commands-doctor-auth",
|
||||
"agentic-commands-doctor-config",
|
||||
"agentic-commands-doctor-cron",
|
||||
"agentic-commands-doctor-misc-core",
|
||||
"agentic-commands-doctor-misc-platform",
|
||||
"agentic-commands-doctor-runtime",
|
||||
"agentic-commands-doctor-config-state",
|
||||
"agentic-commands-doctor-device",
|
||||
"agentic-commands-doctor-gateway",
|
||||
"agentic-commands-doctor-platform",
|
||||
"agentic-commands-doctor-plugins-tools",
|
||||
"agentic-commands-doctor-sessions-cron",
|
||||
"agentic-commands-doctor-shared",
|
||||
"agentic-commands-doctor-whatsapp",
|
||||
"agentic-commands-doctor-workspace",
|
||||
"agentic-commands-models",
|
||||
"agentic-commands-onboard-config",
|
||||
"agentic-commands-status-tools",
|
||||
@@ -151,117 +172,6 @@ function createAgenticCommandSplitShards() {
|
||||
.filter((shard) => shard.includePatterns.length > 0);
|
||||
}
|
||||
|
||||
function resolveInfraStateShardName(file) {
|
||||
const name = relative("src/infra", file).replaceAll("\\", "/");
|
||||
if (name.startsWith("approval")) {
|
||||
return "core-runtime-infra-approval";
|
||||
}
|
||||
if (name.startsWith("exec") || name.startsWith("system-run")) {
|
||||
return "core-runtime-infra-exec";
|
||||
}
|
||||
if (name.startsWith("heartbeat")) {
|
||||
return "core-runtime-infra-heartbeat";
|
||||
}
|
||||
if (name.startsWith("outbound/")) {
|
||||
return "core-runtime-infra-outbound";
|
||||
}
|
||||
if (name.startsWith("net/") || name.startsWith("fetch")) {
|
||||
return "core-runtime-infra-network";
|
||||
}
|
||||
if (
|
||||
name.startsWith("device") ||
|
||||
name.startsWith("node-pairing") ||
|
||||
name.startsWith("pairing") ||
|
||||
name.startsWith("push")
|
||||
) {
|
||||
return "core-runtime-infra-device-push";
|
||||
}
|
||||
if (
|
||||
name.startsWith("install") ||
|
||||
name.startsWith("npm") ||
|
||||
name.startsWith("package") ||
|
||||
name.startsWith("provider-usage") ||
|
||||
name.startsWith("update")
|
||||
) {
|
||||
return "core-runtime-infra-package-provider";
|
||||
}
|
||||
if (name.startsWith("session") || name.startsWith("state-migrations")) {
|
||||
return "core-runtime-infra-session-state";
|
||||
}
|
||||
if (name < "g") {
|
||||
return "core-runtime-infra-misc-a-f";
|
||||
}
|
||||
if (name.startsWith("gateway")) {
|
||||
return "core-runtime-infra-misc-gateway";
|
||||
}
|
||||
if (name < "m") {
|
||||
return "core-runtime-infra-misc-g-l";
|
||||
}
|
||||
if (name < "p") {
|
||||
return "core-runtime-infra-misc-m-o";
|
||||
}
|
||||
if (
|
||||
name.startsWith("parse") ||
|
||||
name.startsWith("path") ||
|
||||
name.startsWith("plain") ||
|
||||
name.startsWith("plugin") ||
|
||||
name.startsWith("ports") ||
|
||||
name.startsWith("prototype")
|
||||
) {
|
||||
return "core-runtime-infra-misc-path-ports";
|
||||
}
|
||||
if (
|
||||
name.startsWith("process") ||
|
||||
name.startsWith("replace") ||
|
||||
name.startsWith("resolve") ||
|
||||
name.startsWith("restart") ||
|
||||
name.startsWith("retry") ||
|
||||
name.startsWith("run") ||
|
||||
name.startsWith("runtime")
|
||||
) {
|
||||
return "core-runtime-infra-misc-process-restart";
|
||||
}
|
||||
if (name < "t") {
|
||||
return "core-runtime-infra-misc-s-system";
|
||||
}
|
||||
return "core-runtime-infra-misc-t-z";
|
||||
}
|
||||
|
||||
function createInfraStateSplitShards() {
|
||||
const groups = new Map();
|
||||
for (const file of listTestFiles("src/infra")) {
|
||||
const shardName = resolveInfraStateShardName(file);
|
||||
groups.set(shardName, [...(groups.get(shardName) ?? []), file]);
|
||||
}
|
||||
|
||||
return [
|
||||
"core-runtime-infra-approval",
|
||||
"core-runtime-infra-device-push",
|
||||
"core-runtime-infra-exec",
|
||||
"core-runtime-infra-heartbeat",
|
||||
"core-runtime-infra-misc-a-f",
|
||||
"core-runtime-infra-misc-g-l",
|
||||
"core-runtime-infra-misc-gateway",
|
||||
"core-runtime-infra-misc-m-o",
|
||||
"core-runtime-infra-misc-path-ports",
|
||||
"core-runtime-infra-misc-process-restart",
|
||||
"core-runtime-infra-misc-s-system",
|
||||
"core-runtime-infra-misc-t-z",
|
||||
"core-runtime-infra-network",
|
||||
"core-runtime-infra-outbound",
|
||||
"core-runtime-infra-package-provider",
|
||||
"core-runtime-infra-session-state",
|
||||
]
|
||||
.map((shardName) => ({
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
includePatterns: groups.get(shardName) ?? [],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName,
|
||||
}))
|
||||
.filter((shard) => shard.includePatterns.length > 0);
|
||||
}
|
||||
|
||||
const GATEWAY_SERVER_BACKED_HTTP_TESTS = new Set([
|
||||
"src/gateway/embeddings-http.test.ts",
|
||||
"src/gateway/models-http.test.ts",
|
||||
@@ -387,6 +297,250 @@ function createCronSplitShards() {
|
||||
.filter((shard) => shard.includePatterns.length > 0);
|
||||
}
|
||||
|
||||
function resolveInfraShardName(file) {
|
||||
const name = relative("src/infra", file).replaceAll("\\", "/");
|
||||
if (name.startsWith("approval") || name.startsWith("exec")) {
|
||||
return "core-runtime-infra-approval-exec";
|
||||
}
|
||||
if (name.startsWith("heartbeat-runner")) {
|
||||
return "core-runtime-infra-heartbeat-runner";
|
||||
}
|
||||
if (name.startsWith("heartbeat")) {
|
||||
return "core-runtime-infra-heartbeat-core";
|
||||
}
|
||||
if (name.startsWith("outbound/message-action")) {
|
||||
return "core-runtime-infra-outbound-actions";
|
||||
}
|
||||
if (name.startsWith("outbound/")) {
|
||||
return "core-runtime-infra-outbound-core";
|
||||
}
|
||||
if (
|
||||
name.startsWith("net/") ||
|
||||
name.startsWith("install") ||
|
||||
name.startsWith("npm") ||
|
||||
name.startsWith("brew") ||
|
||||
name.startsWith("binaries")
|
||||
) {
|
||||
return "core-runtime-infra-net-install";
|
||||
}
|
||||
if (name.startsWith("device")) {
|
||||
return "core-runtime-infra-device";
|
||||
}
|
||||
if (name.startsWith("gateway-lock") || name.startsWith("gateway-process-argv")) {
|
||||
return "core-runtime-infra-gateway-lock-argv";
|
||||
}
|
||||
if (name.startsWith("gateway-processes")) {
|
||||
return "core-runtime-infra-gateway-processes";
|
||||
}
|
||||
if (name.startsWith("gateway-watch")) {
|
||||
return "core-runtime-infra-gateway-watch";
|
||||
}
|
||||
if (name.startsWith("node") || name.startsWith("bonjour") || name.startsWith("network")) {
|
||||
return "core-runtime-infra-network-node";
|
||||
}
|
||||
if (
|
||||
name.startsWith("archive") ||
|
||||
name.startsWith("backup") ||
|
||||
name.startsWith("diagnostic") ||
|
||||
name.startsWith("diagnostics")
|
||||
) {
|
||||
return "core-runtime-infra-diagnostics-state";
|
||||
}
|
||||
if (
|
||||
name.startsWith("command-analysis/") ||
|
||||
name.startsWith("command-explainer/") ||
|
||||
name.startsWith("file-") ||
|
||||
name.startsWith("fs-") ||
|
||||
name.startsWith("json") ||
|
||||
name.startsWith("path") ||
|
||||
name.startsWith("shell") ||
|
||||
name.startsWith("tmp-openclaw-dir")
|
||||
) {
|
||||
return "core-runtime-infra-files-commands";
|
||||
}
|
||||
if (name.startsWith("provider-usage") || name.startsWith("push-")) {
|
||||
return "core-runtime-infra-provider-push";
|
||||
}
|
||||
if (
|
||||
name.startsWith("kysely") ||
|
||||
name.startsWith("session") ||
|
||||
name.startsWith("sqlite") ||
|
||||
name.startsWith("stale-lock") ||
|
||||
name.startsWith("state-migrations")
|
||||
) {
|
||||
return "core-runtime-infra-storage-state";
|
||||
}
|
||||
if (
|
||||
name.startsWith("channel") ||
|
||||
name.startsWith("plugin") ||
|
||||
name.startsWith("pairing") ||
|
||||
name.startsWith("voicewake")
|
||||
) {
|
||||
return "core-runtime-infra-channel-plugin";
|
||||
}
|
||||
if (
|
||||
name.startsWith("package") ||
|
||||
name.startsWith("ports") ||
|
||||
name.startsWith("process") ||
|
||||
name.startsWith("restart") ||
|
||||
name.startsWith("runtime") ||
|
||||
name.startsWith("run-node") ||
|
||||
name.startsWith("system") ||
|
||||
name.startsWith("update")
|
||||
) {
|
||||
return "core-runtime-infra-system-runtime";
|
||||
}
|
||||
if (
|
||||
name.startsWith("dotenv") ||
|
||||
name.startsWith("env") ||
|
||||
name.startsWith("gemini-auth") ||
|
||||
name.startsWith("google-api") ||
|
||||
name.startsWith("home-dir") ||
|
||||
name.startsWith("host-env") ||
|
||||
name.startsWith("openclaw-exec-env") ||
|
||||
name.startsWith("secret") ||
|
||||
name.startsWith("secure-random")
|
||||
) {
|
||||
return "core-runtime-infra-env-auth";
|
||||
}
|
||||
if (
|
||||
name.startsWith("build-stamp") ||
|
||||
name.startsWith("changelog") ||
|
||||
name.startsWith("clawhub") ||
|
||||
name.startsWith("detect-package-manager") ||
|
||||
name.startsWith("git-") ||
|
||||
name.startsWith("openclaw-root") ||
|
||||
name.startsWith("tsdown") ||
|
||||
name.startsWith("vitest")
|
||||
) {
|
||||
return "core-runtime-infra-repo-tooling";
|
||||
}
|
||||
if (
|
||||
name.startsWith("scp") ||
|
||||
name.startsWith("ssh") ||
|
||||
name.startsWith("tailnet") ||
|
||||
name.startsWith("tailscale") ||
|
||||
name.startsWith("tcp") ||
|
||||
name.startsWith("tls/") ||
|
||||
name.startsWith("transport") ||
|
||||
name.startsWith("widearea") ||
|
||||
name.startsWith("windows") ||
|
||||
name.startsWith("ws") ||
|
||||
name.startsWith("wsl")
|
||||
) {
|
||||
return "core-runtime-infra-network-platform";
|
||||
}
|
||||
if (
|
||||
name.startsWith("abort") ||
|
||||
name.startsWith("backoff") ||
|
||||
name.startsWith("errors") ||
|
||||
name.startsWith("fatal-error") ||
|
||||
name.startsWith("fetch") ||
|
||||
name.startsWith("fixed-window") ||
|
||||
name.startsWith("format-time/") ||
|
||||
name.startsWith("http-body") ||
|
||||
name.startsWith("parse-finite-number") ||
|
||||
name.startsWith("plain-object") ||
|
||||
name.startsWith("prototype-keys") ||
|
||||
name.startsWith("retry") ||
|
||||
name.startsWith("warning-filter")
|
||||
) {
|
||||
return "core-runtime-infra-core-utils";
|
||||
}
|
||||
if (
|
||||
name.startsWith("browser") ||
|
||||
name.startsWith("cli-") ||
|
||||
name.startsWith("clipboard") ||
|
||||
name.startsWith("control-ui") ||
|
||||
name.startsWith("embedded") ||
|
||||
name.startsWith("is-main")
|
||||
) {
|
||||
return "core-runtime-infra-cli-ui";
|
||||
}
|
||||
if (
|
||||
name.startsWith("agent-events") ||
|
||||
name.startsWith("event-session") ||
|
||||
name.startsWith("infra-") ||
|
||||
name.startsWith("non-fatal") ||
|
||||
name.startsWith("supervisor") ||
|
||||
name.startsWith("unhandled")
|
||||
) {
|
||||
return "core-runtime-infra-events-runtime";
|
||||
}
|
||||
if (
|
||||
name.startsWith("boundary") ||
|
||||
name.startsWith("hardlink") ||
|
||||
name.startsWith("replace-file") ||
|
||||
name.startsWith("resolve-system-bin") ||
|
||||
name.startsWith("safe-package-install") ||
|
||||
name.startsWith("stable-node-path") ||
|
||||
name.startsWith("watch-node")
|
||||
) {
|
||||
return "core-runtime-infra-file-safety";
|
||||
}
|
||||
if (name.startsWith("dedupe") || name.startsWith("disk-space")) {
|
||||
return "core-runtime-infra-misc-dedupe-disk";
|
||||
}
|
||||
if (
|
||||
name.startsWith("inline-option-token") ||
|
||||
name.startsWith("map-size") ||
|
||||
name.startsWith("machine-name")
|
||||
) {
|
||||
return "core-runtime-infra-misc-values";
|
||||
}
|
||||
if (name.startsWith("os-summary")) {
|
||||
return "core-runtime-infra-misc-os";
|
||||
}
|
||||
return "core-runtime-infra-misc";
|
||||
}
|
||||
|
||||
function createInfraSplitShards() {
|
||||
const groups = new Map();
|
||||
for (const file of listTestFiles("src/infra")) {
|
||||
const shardName = resolveInfraShardName(file);
|
||||
groups.set(shardName, [...(groups.get(shardName) ?? []), file]);
|
||||
}
|
||||
|
||||
return [
|
||||
"core-runtime-infra-approval-exec",
|
||||
"core-runtime-infra-channel-plugin",
|
||||
"core-runtime-infra-cli-ui",
|
||||
"core-runtime-infra-device",
|
||||
"core-runtime-infra-diagnostics-state",
|
||||
"core-runtime-infra-core-utils",
|
||||
"core-runtime-infra-env-auth",
|
||||
"core-runtime-infra-events-runtime",
|
||||
"core-runtime-infra-file-safety",
|
||||
"core-runtime-infra-files-commands",
|
||||
"core-runtime-infra-gateway-lock-argv",
|
||||
"core-runtime-infra-gateway-processes",
|
||||
"core-runtime-infra-gateway-watch",
|
||||
"core-runtime-infra-heartbeat-core",
|
||||
"core-runtime-infra-heartbeat-runner",
|
||||
"core-runtime-infra-misc",
|
||||
"core-runtime-infra-misc-dedupe-disk",
|
||||
"core-runtime-infra-misc-os",
|
||||
"core-runtime-infra-misc-values",
|
||||
"core-runtime-infra-net-install",
|
||||
"core-runtime-infra-network-node",
|
||||
"core-runtime-infra-network-platform",
|
||||
"core-runtime-infra-outbound-actions",
|
||||
"core-runtime-infra-outbound-core",
|
||||
"core-runtime-infra-provider-push",
|
||||
"core-runtime-infra-repo-tooling",
|
||||
"core-runtime-infra-storage-state",
|
||||
"core-runtime-infra-system-runtime",
|
||||
]
|
||||
.map((shardName) => ({
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
includePatterns: groups.get(shardName) ?? [],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName,
|
||||
}))
|
||||
.filter((shard) => shard.includePatterns.length > 0);
|
||||
}
|
||||
|
||||
const SPLIT_NODE_SHARDS = new Map([
|
||||
[
|
||||
"core-unit-fast",
|
||||
@@ -429,13 +583,13 @@ const SPLIT_NODE_SHARDS = new Map([
|
||||
[
|
||||
"core-runtime",
|
||||
[
|
||||
...createInfraStateSplitShards(),
|
||||
{
|
||||
shardName: "core-runtime-hooks",
|
||||
configs: ["test/vitest/vitest.hooks.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
},
|
||||
...createInfraSplitShards(),
|
||||
{
|
||||
shardName: "core-runtime-secrets",
|
||||
configs: ["test/vitest/vitest.secrets.config.ts"],
|
||||
|
||||
@@ -14,6 +14,7 @@ const RUN_NODE_PACKAGE_SOURCE_ROOTS = [
|
||||
"packages/media-generation-core/src",
|
||||
"packages/media-understanding-common/src",
|
||||
"packages/terminal-core/src",
|
||||
"packages/web-content-core/src",
|
||||
"packages/net-policy/src",
|
||||
];
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ const TRUTHY_ENV_VALUES = new Set(["1", "true", "yes", "on"]);
|
||||
const ANSI_CSI_PREFIX = `${String.fromCharCode(27)}[`;
|
||||
const ANSI_CSI_SUFFIX_RE = /^[0-?]*[ -/]*[@-~]/u;
|
||||
const SUPPRESSED_VITEST_STDERR_PATTERNS = ["[PLUGIN_TIMINGS]"];
|
||||
export const DEFAULT_VITEST_NO_OUTPUT_TIMEOUT_MS = 300_000;
|
||||
export const DEFAULT_VITEST_NO_OUTPUT_HEARTBEAT_MS = 120_000;
|
||||
export const DEFAULT_VITEST_NO_OUTPUT_TIMEOUT_MS = 120_000;
|
||||
export const DEFAULT_VITEST_NO_OUTPUT_HEARTBEAT_MS = 60_000;
|
||||
const VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS";
|
||||
const VITEST_NO_OUTPUT_HEARTBEAT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS";
|
||||
const UI_VITEST_CONFIG = "test/vitest/vitest.ui.config.ts";
|
||||
|
||||
@@ -2357,6 +2357,9 @@ export function applyDefaultVitestNoOutputTimeout(specs, params = {}) {
|
||||
|
||||
export function shouldRetryVitestNoOutputTimeout(env = process.env) {
|
||||
const value = env[VITEST_NO_OUTPUT_RETRY_ENV_KEY]?.trim().toLowerCase();
|
||||
if (value === undefined && isCiLikeEnv(env)) {
|
||||
return false;
|
||||
}
|
||||
return !["0", "false", "no", "off"].includes(value ?? "");
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ describe("image resize utility", () => {
|
||||
maxHeight: 2_000,
|
||||
maxWidth: 2_000,
|
||||
},
|
||||
maxBase64Bytes: 4_000,
|
||||
maxBytes: 3_000,
|
||||
opaque: { format: "jpeg", quality: 70 },
|
||||
search: {
|
||||
compressionLevel: [6, 9],
|
||||
|
||||
@@ -32,6 +32,10 @@ const DEFAULT_OPTIONS: Required<ImageResizeOptions> = {
|
||||
jpegQuality: 80,
|
||||
};
|
||||
|
||||
function maxBinaryBytesForBase64Budget(maxBase64Bytes: number): number {
|
||||
return Math.floor(maxBase64Bytes / 4) * 3;
|
||||
}
|
||||
|
||||
interface EncodedCandidate {
|
||||
data: string;
|
||||
encodedSize: number;
|
||||
@@ -107,7 +111,7 @@ export async function resizeImage(
|
||||
maxWidth: opts.maxWidth,
|
||||
maxHeight: opts.maxHeight,
|
||||
},
|
||||
maxBase64Bytes: opts.maxBytes,
|
||||
maxBytes: maxBinaryBytesForBase64Budget(opts.maxBytes),
|
||||
opaque: { format: "jpeg", quality: opts.jpegQuality },
|
||||
transparent: { format: "png" },
|
||||
search: {
|
||||
|
||||
@@ -400,6 +400,22 @@ function storeHasUnsafeUntouchedHydratedSkillPrompts(
|
||||
if (!ref || !isSessionSkillPromptBlobReadable(storePath, ref)) {
|
||||
return true;
|
||||
}
|
||||
if (serializedPromptRefs?.has(key)) {
|
||||
const projected = projectSessionStoreForPersistence({ storePath, store: { [key]: entry } });
|
||||
for (const blob of projected.promptBlobs.values()) {
|
||||
if (!blob.path) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const stat = fs.statSync(blob.path);
|
||||
if (!stat.isFile() || stat.size !== blob.ref.bytes) {
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8,23 +8,16 @@ const parseProcCmdlineMock = vi.hoisted(() => vi.fn());
|
||||
const isGatewayArgvMock = vi.hoisted(() => vi.fn());
|
||||
const findGatewayPidsOnPortSyncMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("node:child_process", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("node:child_process")>()),
|
||||
vi.mock("node:child_process", () => ({
|
||||
spawnSync: spawnSyncMock,
|
||||
}));
|
||||
|
||||
vi.mock("node:fs", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("node:fs")>();
|
||||
const actualWithDefault = actual as typeof actual & { default?: typeof actual };
|
||||
return {
|
||||
...actual,
|
||||
default: {
|
||||
...(actualWithDefault.default ?? actual),
|
||||
readFileSync: (...args: unknown[]) => readFileSyncMock(...args),
|
||||
},
|
||||
vi.mock("node:fs", () => ({
|
||||
default: {
|
||||
readFileSync: (...args: unknown[]) => readFileSyncMock(...args),
|
||||
};
|
||||
});
|
||||
},
|
||||
readFileSync: (...args: unknown[]) => readFileSyncMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../daemon/cmd-argv.js", () => ({
|
||||
parseCmdScriptCommandLine: (...args: unknown[]) => parseCmdScriptCommandLineMock(...args),
|
||||
|
||||
@@ -7,7 +7,8 @@ const execFileMock = vi.hoisted(() => vi.fn());
|
||||
vi.mock("node:child_process", () => ({
|
||||
execFile: Object.assign(execFileMock, {
|
||||
[Symbol.for("nodejs.util.promisify.custom")]: vi.fn(),
|
||||
}),
|
||||
__promisify__: vi.fn(),
|
||||
}) as typeof import("node:child_process").execFile,
|
||||
}));
|
||||
|
||||
const originalVitest = process.env.VITEST;
|
||||
|
||||
@@ -3,8 +3,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const spawnSyncMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("node:child_process", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("node:child_process")>()),
|
||||
vi.mock("node:child_process", () => ({
|
||||
spawnSync: spawnSyncMock,
|
||||
}));
|
||||
|
||||
|
||||
@@ -3,28 +3,28 @@ import { captureFullEnv } from "../test-utils/env.js";
|
||||
import { mockProcessPlatform } from "../test-utils/vitest-spies.js";
|
||||
|
||||
const spawnSyncMock = vi.hoisted(() => vi.fn());
|
||||
const execFileMock = vi.hoisted(() =>
|
||||
Object.assign(vi.fn(), {
|
||||
[Symbol.for("nodejs.util.promisify.custom")]: vi.fn(),
|
||||
}),
|
||||
);
|
||||
const resolveLsofCommandSyncMock = vi.hoisted(() => vi.fn());
|
||||
const resolveGatewayPortMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("node:child_process", async () => {
|
||||
const actual = await vi.importActual<typeof import("node:child_process")>("node:child_process");
|
||||
return {
|
||||
...actual,
|
||||
spawnSync: (...args: unknown[]) => spawnSyncMock(...args),
|
||||
};
|
||||
});
|
||||
vi.mock("node:child_process", () => ({
|
||||
execFile: execFileMock,
|
||||
spawnSync: (...args: unknown[]) => spawnSyncMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock("./ports-lsof.js", () => ({
|
||||
resolveLsofCommandSync: (...args: unknown[]) => resolveLsofCommandSyncMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../config/paths.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../config/paths.js")>("../config/paths.js");
|
||||
return {
|
||||
...actual,
|
||||
resolveGatewayPort: (...args: unknown[]) => resolveGatewayPortMock(...args),
|
||||
};
|
||||
});
|
||||
vi.mock("../config/paths.js", () => ({
|
||||
resolveGatewayPort: (...args: unknown[]) => resolveGatewayPortMock(...args),
|
||||
resolveStateDir: (env: NodeJS.ProcessEnv = process.env) =>
|
||||
env.OPENCLAW_STATE_DIR ?? "/tmp/openclaw-state",
|
||||
}));
|
||||
|
||||
const { testing, cleanStaleGatewayProcessesSync, findGatewayPidsOnPortSync } =
|
||||
await import("./restart-stale-pids.js");
|
||||
@@ -34,6 +34,7 @@ let currentTimeMs = 0;
|
||||
const envSnapshot = captureFullEnv();
|
||||
|
||||
beforeEach(() => {
|
||||
execFileMock.mockReset();
|
||||
spawnSyncMock.mockReset();
|
||||
resolveLsofCommandSyncMock.mockReset();
|
||||
resolveGatewayPortMock.mockReset();
|
||||
|
||||
@@ -512,7 +512,10 @@ export const PLUGIN_COMPAT_RECORDS = [
|
||||
docsPath: "/plugins/sdk-agent-harness",
|
||||
surfaces: ["manifest/catalog execution policy", "runtime selection"],
|
||||
diagnostics: ["agent runtime compatibility warning"],
|
||||
tests: ["src/plugins/provider-runtime.test.ts", "src/web/provider-runtime-shared.test.ts"],
|
||||
tests: [
|
||||
"src/plugins/provider-runtime.test.ts",
|
||||
"packages/web-content-core/src/provider-runtime-shared.test.ts",
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "generated-bundled-channel-config-fallback",
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveWebProviderDefinition } from "./provider-runtime-shared.js";
|
||||
|
||||
describe("resolveWebProviderDefinition", () => {
|
||||
it("falls back to auto-detect when runtime metadata has no selected provider", () => {
|
||||
const resolved = resolveWebProviderDefinition({
|
||||
config: {},
|
||||
toolConfig: { enabled: true },
|
||||
runtimeMetadata: {},
|
||||
providers: [
|
||||
{
|
||||
id: "custom",
|
||||
},
|
||||
],
|
||||
resolveEnabled: () => true,
|
||||
resolveAutoProviderId: () => "custom",
|
||||
createTool: ({ provider }) => ({
|
||||
name: provider.id,
|
||||
}),
|
||||
});
|
||||
|
||||
expect(resolved).toEqual({
|
||||
provider: {
|
||||
id: "custom",
|
||||
},
|
||||
definition: {
|
||||
name: "custom",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,201 +1 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { normalizeSecretInputString, resolveSecretInputRef } from "../config/types.secrets.js";
|
||||
import { normalizeSecretInput } from "../utils/normalize-secret-input.js";
|
||||
|
||||
type RuntimeWebProviderMetadata = {
|
||||
providerConfigured?: string;
|
||||
selectedProvider?: string;
|
||||
};
|
||||
|
||||
type ProviderWithCredential = {
|
||||
envVars: string[];
|
||||
authProviderId?: string;
|
||||
requiresCredential?: boolean;
|
||||
};
|
||||
|
||||
export function resolveWebProviderConfig(
|
||||
cfg: OpenClawConfig | undefined,
|
||||
kind: "search" | "fetch",
|
||||
): Record<string, unknown> | undefined {
|
||||
const webConfig = cfg?.tools?.web;
|
||||
if (!webConfig || typeof webConfig !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
const toolConfig = webConfig[kind];
|
||||
if (!toolConfig || typeof toolConfig !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
return toolConfig as Record<string, unknown>;
|
||||
}
|
||||
|
||||
export function readWebProviderEnvValue(
|
||||
envVars: string[],
|
||||
processEnv: NodeJS.ProcessEnv = process.env,
|
||||
): string | undefined {
|
||||
for (const envVar of envVars) {
|
||||
const value = normalizeSecretInput(processEnv[envVar]);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function providerRequiresCredential(
|
||||
provider: Pick<ProviderWithCredential, "requiresCredential">,
|
||||
): boolean {
|
||||
return provider.requiresCredential !== false;
|
||||
}
|
||||
|
||||
export function hasWebProviderEntryCredential<
|
||||
TProvider extends ProviderWithCredential,
|
||||
TConfig extends Record<string, unknown> | undefined,
|
||||
>(params: {
|
||||
provider: TProvider;
|
||||
config: OpenClawConfig | undefined;
|
||||
toolConfig: TConfig;
|
||||
resolveRawValue: (params: {
|
||||
provider: TProvider;
|
||||
config: OpenClawConfig | undefined;
|
||||
toolConfig: TConfig;
|
||||
}) => unknown;
|
||||
resolveFallbackRawValue?: (params: {
|
||||
provider: TProvider;
|
||||
config: OpenClawConfig | undefined;
|
||||
toolConfig: TConfig;
|
||||
}) => unknown;
|
||||
resolveEnvValue: (params: {
|
||||
provider: TProvider;
|
||||
configuredEnvVarId?: string;
|
||||
}) => string | undefined;
|
||||
resolveProviderAuthValue?: (providerId: string) => boolean;
|
||||
}): boolean {
|
||||
if (!providerRequiresCredential(params.provider)) {
|
||||
return true;
|
||||
}
|
||||
const rawValue = params.resolveRawValue({
|
||||
provider: params.provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
});
|
||||
const configuredRef = resolveSecretInputRef({
|
||||
value: rawValue,
|
||||
}).ref;
|
||||
if (configuredRef && configuredRef.source !== "env") {
|
||||
return true;
|
||||
}
|
||||
const fromConfig = normalizeSecretInput(normalizeSecretInputString(rawValue));
|
||||
if (fromConfig) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
params.provider.authProviderId &&
|
||||
params.resolveProviderAuthValue?.(params.provider.authProviderId)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
params.resolveEnvValue({
|
||||
provider: params.provider,
|
||||
configuredEnvVarId: configuredRef?.source === "env" ? configuredRef.id : undefined,
|
||||
})
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
const fallbackRawValue = params.resolveFallbackRawValue?.({
|
||||
provider: params.provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
});
|
||||
const fallbackRef = resolveSecretInputRef({ value: fallbackRawValue }).ref;
|
||||
if (fallbackRef && fallbackRef.source !== "env") {
|
||||
return true;
|
||||
}
|
||||
const fallbackConfig = normalizeSecretInput(normalizeSecretInputString(fallbackRawValue));
|
||||
if (fallbackConfig) {
|
||||
return true;
|
||||
}
|
||||
return Boolean(
|
||||
fallbackRef?.source === "env"
|
||||
? params.resolveEnvValue({
|
||||
provider: params.provider,
|
||||
configuredEnvVarId: fallbackRef.id,
|
||||
})
|
||||
: undefined,
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveWebProviderDefinition<
|
||||
TProvider extends { id: string },
|
||||
TConfig extends Record<string, unknown> | undefined,
|
||||
TRuntimeMetadata extends RuntimeWebProviderMetadata,
|
||||
TDefinition,
|
||||
>(params: {
|
||||
config: OpenClawConfig | undefined;
|
||||
toolConfig: TConfig;
|
||||
runtimeMetadata: TRuntimeMetadata | undefined;
|
||||
sandboxed?: boolean;
|
||||
providerId?: string;
|
||||
providers: TProvider[];
|
||||
resolveEnabled: (params: { toolConfig: TConfig; sandboxed?: boolean }) => boolean;
|
||||
resolveAutoProviderId: (params: {
|
||||
config: OpenClawConfig | undefined;
|
||||
toolConfig: TConfig;
|
||||
providers: TProvider[];
|
||||
}) => string;
|
||||
resolveFallbackProviderId?: (params: {
|
||||
config: OpenClawConfig | undefined;
|
||||
toolConfig: TConfig;
|
||||
providers: TProvider[];
|
||||
providerId: string;
|
||||
}) => string | undefined;
|
||||
createTool: (params: {
|
||||
provider: TProvider;
|
||||
config: OpenClawConfig | undefined;
|
||||
toolConfig: TConfig;
|
||||
runtimeMetadata: TRuntimeMetadata | undefined;
|
||||
}) => TDefinition | null;
|
||||
}): { provider: TProvider; definition: TDefinition } | null {
|
||||
if (!params.resolveEnabled({ toolConfig: params.toolConfig, sandboxed: params.sandboxed })) {
|
||||
return null;
|
||||
}
|
||||
const providers = params.providers.filter(Boolean);
|
||||
if (providers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const autoProviderId = params.resolveAutoProviderId({
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
providers,
|
||||
});
|
||||
const providerId =
|
||||
params.providerId ?? params.runtimeMetadata?.selectedProvider ?? autoProviderId;
|
||||
if (!providerId) {
|
||||
return null;
|
||||
}
|
||||
const provider =
|
||||
providers.find((entry) => entry.id === providerId) ??
|
||||
providers.find(
|
||||
(entry) =>
|
||||
entry.id ===
|
||||
params.resolveFallbackProviderId?.({
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
providers,
|
||||
providerId,
|
||||
}),
|
||||
);
|
||||
if (!provider) {
|
||||
return null;
|
||||
}
|
||||
const definition = params.createTool({
|
||||
provider,
|
||||
config: params.config,
|
||||
toolConfig: params.toolConfig,
|
||||
runtimeMetadata: params.runtimeMetadata,
|
||||
});
|
||||
if (!definition) {
|
||||
return null;
|
||||
}
|
||||
return { provider, definition };
|
||||
}
|
||||
export * from "../../packages/web-content-core/src/provider-runtime-shared.js";
|
||||
|
||||
@@ -194,108 +194,174 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
|
||||
}));
|
||||
|
||||
expect(runtimeShards).toEqual([
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-approval",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-device-push",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-exec",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-heartbeat",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-a-f",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-g-l",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-gateway",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-m-o",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-path-ports",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-process-restart",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-s-system",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-t-z",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-network",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-outbound",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-package-provider",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-session-state",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.hooks.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-hooks",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-approval-exec",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-channel-plugin",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-cli-ui",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-device",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-diagnostics-state",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-core-utils",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-env-auth",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-events-runtime",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-file-safety",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-files-commands",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-gateway-lock-argv",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-gateway-processes",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-gateway-watch",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-heartbeat-core",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-heartbeat-runner",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-dedupe-disk",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-os",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-misc-values",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-net-install",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-network-node",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-network-platform",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-outbound-actions",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-outbound-core",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-provider-push",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-repo-tooling",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-storage-state",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.infra.config.ts"],
|
||||
requiresDist: false,
|
||||
runner: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shardName: "core-runtime-infra-system-runtime",
|
||||
},
|
||||
{
|
||||
configs: ["test/vitest/vitest.secrets.config.ts"],
|
||||
requiresDist: false,
|
||||
@@ -356,6 +422,48 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("covers every infra test exactly once across core runtime infra shards", () => {
|
||||
const infraShards = createNodeTestShards().filter((shard) =>
|
||||
shard.shardName.startsWith("core-runtime-infra-"),
|
||||
);
|
||||
const actual = infraShards
|
||||
.flatMap((shard) => shard.includePatterns ?? [])
|
||||
.toSorted((a, b) => a.localeCompare(b));
|
||||
|
||||
expect(infraShards.map((shard) => shard.shardName)).toEqual([
|
||||
"core-runtime-infra-approval-exec",
|
||||
"core-runtime-infra-channel-plugin",
|
||||
"core-runtime-infra-cli-ui",
|
||||
"core-runtime-infra-device",
|
||||
"core-runtime-infra-diagnostics-state",
|
||||
"core-runtime-infra-core-utils",
|
||||
"core-runtime-infra-env-auth",
|
||||
"core-runtime-infra-events-runtime",
|
||||
"core-runtime-infra-file-safety",
|
||||
"core-runtime-infra-files-commands",
|
||||
"core-runtime-infra-gateway-lock-argv",
|
||||
"core-runtime-infra-gateway-processes",
|
||||
"core-runtime-infra-gateway-watch",
|
||||
"core-runtime-infra-heartbeat-core",
|
||||
"core-runtime-infra-heartbeat-runner",
|
||||
"core-runtime-infra-misc-dedupe-disk",
|
||||
"core-runtime-infra-misc-os",
|
||||
"core-runtime-infra-misc-values",
|
||||
"core-runtime-infra-net-install",
|
||||
"core-runtime-infra-network-node",
|
||||
"core-runtime-infra-network-platform",
|
||||
"core-runtime-infra-outbound-actions",
|
||||
"core-runtime-infra-outbound-core",
|
||||
"core-runtime-infra-provider-push",
|
||||
"core-runtime-infra-repo-tooling",
|
||||
"core-runtime-infra-storage-state",
|
||||
"core-runtime-infra-system-runtime",
|
||||
"core-runtime-infra-process",
|
||||
]);
|
||||
expect(actual).toEqual(listTestFiles("src/infra"));
|
||||
expect(new Set(actual).size).toBe(actual.length);
|
||||
});
|
||||
|
||||
it("covers every cron test exactly once across core runtime cron shards", () => {
|
||||
const cronShards = createNodeTestShards().filter((shard) =>
|
||||
shard.shardName.startsWith("core-runtime-cron-"),
|
||||
@@ -373,36 +481,6 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
|
||||
expect(new Set(actual).size).toBe(actual.length);
|
||||
});
|
||||
|
||||
it("covers every infra test exactly once across core runtime infra shards", () => {
|
||||
const infraShards = createNodeTestShards().filter((shard) =>
|
||||
shard.configs.includes("test/vitest/vitest.infra.config.ts"),
|
||||
);
|
||||
const actual = infraShards
|
||||
.flatMap((shard) => shard.includePatterns ?? [])
|
||||
.toSorted((a, b) => a.localeCompare(b));
|
||||
|
||||
expect(infraShards.map((shard) => shard.shardName)).toEqual([
|
||||
"core-runtime-infra-approval",
|
||||
"core-runtime-infra-device-push",
|
||||
"core-runtime-infra-exec",
|
||||
"core-runtime-infra-heartbeat",
|
||||
"core-runtime-infra-misc-a-f",
|
||||
"core-runtime-infra-misc-g-l",
|
||||
"core-runtime-infra-misc-gateway",
|
||||
"core-runtime-infra-misc-m-o",
|
||||
"core-runtime-infra-misc-path-ports",
|
||||
"core-runtime-infra-misc-process-restart",
|
||||
"core-runtime-infra-misc-s-system",
|
||||
"core-runtime-infra-misc-t-z",
|
||||
"core-runtime-infra-network",
|
||||
"core-runtime-infra-outbound",
|
||||
"core-runtime-infra-package-provider",
|
||||
"core-runtime-infra-session-state",
|
||||
]);
|
||||
expect(actual).toEqual(listTestFiles("src/infra"));
|
||||
expect(new Set(actual).size).toBe(actual.length);
|
||||
});
|
||||
|
||||
it("splits the agentic lane into control-plane, command, agent, gateway, SDK, and plugin shards", () => {
|
||||
const shards = createNodeTestShards();
|
||||
const controlPlaneShards = shards.filter((shard) =>
|
||||
@@ -466,13 +544,17 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
|
||||
});
|
||||
expect(commandShards.map((shard) => shard.shardName)).toEqual([
|
||||
"agentic-commands-agent-channel",
|
||||
"agentic-commands-doctor",
|
||||
"agentic-commands-doctor-auth",
|
||||
"agentic-commands-doctor-config",
|
||||
"agentic-commands-doctor-cron",
|
||||
"agentic-commands-doctor-misc-core",
|
||||
"agentic-commands-doctor-misc-platform",
|
||||
"agentic-commands-doctor-runtime",
|
||||
"agentic-commands-doctor-config-state",
|
||||
"agentic-commands-doctor-device",
|
||||
"agentic-commands-doctor-gateway",
|
||||
"agentic-commands-doctor-platform",
|
||||
"agentic-commands-doctor-plugins-tools",
|
||||
"agentic-commands-doctor-sessions-cron",
|
||||
"agentic-commands-doctor-shared",
|
||||
"agentic-commands-doctor-whatsapp",
|
||||
"agentic-commands-doctor-workspace",
|
||||
"agentic-commands-models",
|
||||
"agentic-commands-onboard-config",
|
||||
"agentic-commands-status-tools",
|
||||
@@ -487,6 +569,10 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
|
||||
shardName: shard.shardName,
|
||||
})),
|
||||
);
|
||||
expect(
|
||||
commandShards.find((shard) => shard.shardName === "agentic-commands-doctor-auth")
|
||||
?.includePatterns,
|
||||
).toContain("src/commands/oauth-tls-preflight.doctor.test.ts");
|
||||
const commandShardFiles = commandShards
|
||||
.flatMap((shard) => shard.includePatterns ?? [])
|
||||
.toSorted((a, b) => a.localeCompare(b));
|
||||
|
||||
@@ -302,35 +302,35 @@ describe("scripts/run-vitest", () => {
|
||||
it("defaults direct non-watch runs to the stall watchdog", () => {
|
||||
expect(resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, ["run"])).toEqual({
|
||||
PATH: "/usr/bin",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "120000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "300000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "120000",
|
||||
});
|
||||
expect(resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, ["run", "-t", "watch"])).toEqual({
|
||||
PATH: "/usr/bin",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "120000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "300000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "120000",
|
||||
});
|
||||
expect(resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, ["--watch=false"])).toEqual({
|
||||
PATH: "/usr/bin",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "120000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "300000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "120000",
|
||||
});
|
||||
expect(resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, ["--watch", "false"])).toEqual({
|
||||
PATH: "/usr/bin",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "120000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "300000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "120000",
|
||||
});
|
||||
expect(resolveRunVitestSpawnEnv({ PATH: "/usr/bin" }, ["--no-watch"])).toEqual({
|
||||
PATH: "/usr/bin",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "120000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "300000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "120000",
|
||||
});
|
||||
expect(resolveRunVitestSpawnEnv({ CI: "true", PATH: "/usr/bin" }, ["src/foo.test.ts"])).toEqual(
|
||||
{
|
||||
CI: "true",
|
||||
PATH: "/usr/bin",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "120000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "300000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS: "60000",
|
||||
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "120000",
|
||||
},
|
||||
);
|
||||
expect(
|
||||
|
||||
@@ -2293,6 +2293,8 @@ describe("scripts/test-projects Vitest stall watchdog", () => {
|
||||
|
||||
it("allows changed checks to disable automatic silent-run retries", () => {
|
||||
expect(shouldRetryVitestNoOutputTimeout({})).toBe(true);
|
||||
expect(shouldRetryVitestNoOutputTimeout({ CI: "true" })).toBe(false);
|
||||
expect(shouldRetryVitestNoOutputTimeout({ GITHUB_ACTIONS: "true" })).toBe(false);
|
||||
expect(shouldRetryVitestNoOutputTimeout({ OPENCLAW_VITEST_NO_OUTPUT_RETRY: "1" })).toBe(true);
|
||||
expect(shouldRetryVitestNoOutputTimeout({ OPENCLAW_VITEST_NO_OUTPUT_RETRY: "0" })).toBe(false);
|
||||
expect(shouldRetryVitestNoOutputTimeout({ OPENCLAW_VITEST_NO_OUTPUT_RETRY: "false" })).toBe(
|
||||
|
||||
@@ -149,6 +149,11 @@
|
||||
],
|
||||
"@openclaw/net-policy/url-userinfo": ["./packages/net-policy/src/url-userinfo.ts"],
|
||||
"@openclaw/net-policy/*": ["./packages/net-policy/src/*"],
|
||||
"@openclaw/web-content-core": ["./packages/web-content-core/src/index.ts"],
|
||||
"@openclaw/web-content-core/provider-runtime-shared": [
|
||||
"./packages/web-content-core/src/provider-runtime-shared.ts"
|
||||
],
|
||||
"@openclaw/web-content-core/*": ["./packages/web-content-core/src/*"],
|
||||
"@openclaw/speech-core": ["./packages/speech-core/runtime-api.ts"],
|
||||
"@openclaw/speech-core/api": ["./packages/speech-core/api.ts"],
|
||||
"@openclaw/speech-core/runtime-api": ["./packages/speech-core/runtime-api.ts"],
|
||||
|
||||
@@ -448,6 +448,13 @@ function buildTerminalCoreDistEntries(): Record<string, string> {
|
||||
};
|
||||
}
|
||||
|
||||
function buildWebContentCoreDistEntries(): Record<string, string> {
|
||||
return {
|
||||
index: "packages/web-content-core/src/index.ts",
|
||||
"provider-runtime-shared": "packages/web-content-core/src/provider-runtime-shared.ts",
|
||||
};
|
||||
}
|
||||
|
||||
function buildSpeechCoreDistEntries(): Record<string, string> {
|
||||
return {
|
||||
api: "packages/speech-core/api.ts",
|
||||
@@ -647,6 +654,12 @@ export default defineConfig([
|
||||
neverBundle: shouldExternalizeTerminalCoreDependency,
|
||||
},
|
||||
}),
|
||||
nodeWorkspacePackageBuildConfig({
|
||||
clean: true,
|
||||
dts: RUN_NODE_SKIP_DTS_BUILD ? false : undefined,
|
||||
entry: buildWebContentCoreDistEntries(),
|
||||
outDir: "packages/web-content-core/dist",
|
||||
}),
|
||||
nodeWorkspacePackageBuildConfig({
|
||||
clean: true,
|
||||
dts: RUN_NODE_SKIP_DTS_BUILD ? false : undefined,
|
||||
|
||||
Reference in New Issue
Block a user