mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-09 15:59:30 +00:00
refactor: extract media generation core package
Extract pure media generation catalog/model-ref/normalization helpers into a private workspace package and wire the package through build, watch, SDK alias, and plugin boundary d.ts paths. Verification: - node scripts/run-vitest.mjs test/scripts/crabbox-wrapper.test.ts packages/media-generation-core/src src/media-generation/runtime-shared.test.ts src/plugins/sdk-alias.test.ts src/infra/watch-node.test.ts src/plugins/registry.provider-like.test.ts src/agents/model-ref-shared.test.ts extensions/codex-supervisor/src/plugin-tools.test.ts extensions/codex-supervisor/src/supervisor.test.ts src/wizard/setup.official-plugins.test.ts src/infra/net/http-connect-tunnel.test.ts - node scripts/prepare-extension-package-boundary-artifacts.mjs --mode=all - node scripts/run-vitest.mjs src/plugins/contracts/extension-package-project-boundaries.test.ts src/plugins/sdk-alias.test.ts - pnpm protocol:check - pnpm check:changed - .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main - GitHub CI 26676608512
This commit is contained in:
parent
be2c43ee3e
commit
7c1484d637
40 changed files with 480 additions and 189 deletions
|
|
@ -1,5 +1,4 @@
|
|||
import { jsonResult, readStringParam, type AnyAgentTool } from "openclaw/plugin-sdk/core";
|
||||
import { asSafeIntegerInRange } from "openclaw/plugin-sdk/number-runtime";
|
||||
import { Type } from "typebox";
|
||||
import {
|
||||
redactCodexSupervisorEndpoint,
|
||||
|
|
@ -74,14 +73,13 @@ function readIntegerParam(params: Record<string, unknown>, key: string): number
|
|||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const integer = asSafeIntegerInRange(value, { min: 1, max: 1000 });
|
||||
if (integer === undefined) {
|
||||
if (typeof value === "number" && Number.isInteger(value)) {
|
||||
throw new Error(`${key} must be between 1 and 1000`);
|
||||
}
|
||||
if (typeof value !== "number" || !Number.isInteger(value)) {
|
||||
throw new Error(`${key} must be an integer`);
|
||||
}
|
||||
return integer;
|
||||
if (value < 1 || value > 1000) {
|
||||
throw new Error(`${key} must be between 1 and 1000`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function readModeParam(params: Record<string, unknown>): CodexSupervisorTurnMode | undefined {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,24 @@
|
|||
"../dist/plugin-sdk/packages/llm-core/src/validation.d.ts"
|
||||
],
|
||||
"@openclaw/llm-core/*": ["../dist/plugin-sdk/packages/llm-core/src/*.d.ts"],
|
||||
"@openclaw/media-generation-core": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/index.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/capability-model-ref": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/capability-model-ref.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/catalog": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/catalog.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/model-ref": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/model-ref.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/normalization": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/normalization.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/*": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/*.js": ["../packages/plugin-sdk/dist/extensions/*.d.ts", "../extensions/*"],
|
||||
"@openclaw/*": ["../packages/plugin-sdk/dist/extensions/*", "../extensions/*"],
|
||||
"openclaw/plugin-sdk/qa-channel": ["../dist/plugin-sdk/src/plugin-sdk/qa-channel.d.ts"],
|
||||
|
|
|
|||
|
|
@ -111,6 +111,24 @@
|
|||
"@openclaw/llm-core/*": [
|
||||
"../../dist/plugin-sdk/packages/llm-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core": [
|
||||
"../../dist/plugin-sdk/packages/media-generation-core/src/index.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/capability-model-ref": [
|
||||
"../../dist/plugin-sdk/packages/media-generation-core/src/capability-model-ref.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/catalog": [
|
||||
"../../dist/plugin-sdk/packages/media-generation-core/src/catalog.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/model-ref": [
|
||||
"../../dist/plugin-sdk/packages/media-generation-core/src/model-ref.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/normalization": [
|
||||
"../../dist/plugin-sdk/packages/media-generation-core/src/normalization.d.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/*": [
|
||||
"../../dist/plugin-sdk/packages/media-generation-core/src/*.d.ts"
|
||||
],
|
||||
"@openclaw/*.js": ["../../packages/plugin-sdk/dist/extensions/*.d.ts", "../*"],
|
||||
"@openclaw/*": ["../*"],
|
||||
"openclaw/plugin-sdk/qa-channel": [
|
||||
|
|
|
|||
41
packages/media-generation-core/package.json
Normal file
41
packages/media-generation-core/package.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "@openclaw/media-generation-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"
|
||||
},
|
||||
"./capability-model-ref": {
|
||||
"types": "./dist/capability-model-ref.d.mts",
|
||||
"import": "./dist/capability-model-ref.mjs",
|
||||
"default": "./dist/capability-model-ref.mjs"
|
||||
},
|
||||
"./catalog": {
|
||||
"types": "./dist/catalog.d.mts",
|
||||
"import": "./dist/catalog.mjs",
|
||||
"default": "./dist/catalog.mjs"
|
||||
},
|
||||
"./model-ref": {
|
||||
"types": "./dist/model-ref.d.mts",
|
||||
"import": "./dist/model-ref.mjs",
|
||||
"default": "./dist/model-ref.mjs"
|
||||
},
|
||||
"./normalization": {
|
||||
"types": "./dist/normalization.d.mts",
|
||||
"import": "./dist/normalization.mjs",
|
||||
"default": "./dist/normalization.mjs"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsdown src/index.ts src/capability-model-ref.ts src/catalog.ts src/model-ref.ts src/normalization.ts --no-config --platform node --format esm --dts --out-dir dist --clean"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { normalizeOptionalString } from "./string.js";
|
||||
|
||||
export type CapabilityModelProviderCandidate = {
|
||||
id: string;
|
||||
|
|
@ -19,10 +19,7 @@ function normalizeProviderForMatch(
|
|||
normalizeProviderId: ProviderIdNormalizer | undefined,
|
||||
): string | undefined {
|
||||
const normalized = normalizeOptionalString(value);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
return normalizeProviderId ? normalizeProviderId(normalized) : normalized;
|
||||
return normalized && normalizeProviderId ? normalizeProviderId(normalized) : normalized;
|
||||
}
|
||||
|
||||
export function findCapabilityProviderById<T extends CapabilityModelProviderCandidate>(params: {
|
||||
|
|
@ -36,11 +33,12 @@ export function findCapabilityProviderById<T extends CapabilityModelProviderCand
|
|||
}
|
||||
return params.providers.find((provider) => {
|
||||
const providerId = normalizeProviderForMatch(provider.id, params.normalizeProviderId);
|
||||
if (providerId === selectedProvider) {
|
||||
return true;
|
||||
}
|
||||
return (provider.aliases ?? []).some(
|
||||
(alias) => normalizeProviderForMatch(alias, params.normalizeProviderId) === selectedProvider,
|
||||
return (
|
||||
providerId === selectedProvider ||
|
||||
(provider.aliases ?? []).some(
|
||||
(alias) =>
|
||||
normalizeProviderForMatch(alias, params.normalizeProviderId) === selectedProvider,
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -1,23 +1,27 @@
|
|||
import type {
|
||||
UnifiedModelCatalogEntry,
|
||||
UnifiedModelCatalogKind,
|
||||
UnifiedModelCatalogSource,
|
||||
} from "../model-catalog/types.js";
|
||||
import { normalizeUniqueSingleOrTrimmedStringList } from "../shared/string-normalization.js";
|
||||
import { uniqueTrimmedStrings } from "./string.js";
|
||||
|
||||
export type MediaGenerationCatalogKind = Extract<
|
||||
UnifiedModelCatalogKind,
|
||||
"image_generation" | "video_generation" | "music_generation"
|
||||
>;
|
||||
export type MediaGenerationCatalogKind =
|
||||
| "image_generation"
|
||||
| "video_generation"
|
||||
| "music_generation";
|
||||
|
||||
export type MediaGenerationCatalogSource = Extract<
|
||||
UnifiedModelCatalogSource,
|
||||
"static" | "live" | "cache" | "configured"
|
||||
>;
|
||||
export type MediaGenerationCatalogSource = "static" | "live" | "cache" | "configured";
|
||||
|
||||
export type MediaGenerationCatalogEntry<TCapabilities> = UnifiedModelCatalogEntry<TCapabilities> & {
|
||||
export type MediaGenerationCatalogEntry<TCapabilities = unknown> = {
|
||||
kind: MediaGenerationCatalogKind;
|
||||
provider: string;
|
||||
model: string;
|
||||
label?: string;
|
||||
source: MediaGenerationCatalogSource;
|
||||
default?: boolean;
|
||||
configured?: boolean;
|
||||
capabilities?: TCapabilities;
|
||||
modes?: readonly string[];
|
||||
authEnvVars?: readonly string[];
|
||||
docsPath?: string;
|
||||
fetchedAt?: number;
|
||||
expiresAt?: number;
|
||||
warnings?: readonly string[];
|
||||
};
|
||||
|
||||
export type MediaGenerationCatalogProvider<TCapabilities = unknown> = {
|
||||
|
|
@ -30,10 +34,7 @@ export type MediaGenerationCatalogProvider<TCapabilities = unknown> = {
|
|||
};
|
||||
|
||||
function uniqueModels(provider: { defaultModel?: string; models?: readonly string[] }): string[] {
|
||||
return normalizeUniqueSingleOrTrimmedStringList([
|
||||
provider.defaultModel,
|
||||
...(provider.models ?? []),
|
||||
]);
|
||||
return uniqueTrimmedStrings([provider.defaultModel, ...(provider.models ?? [])]);
|
||||
}
|
||||
|
||||
export function synthesizeMediaGenerationCatalogEntries<TCapabilities>(params: {
|
||||
|
|
@ -41,8 +42,7 @@ export function synthesizeMediaGenerationCatalogEntries<TCapabilities>(params: {
|
|||
provider: MediaGenerationCatalogProvider<TCapabilities>;
|
||||
modes?: readonly string[];
|
||||
}): Array<MediaGenerationCatalogEntry<TCapabilities>> {
|
||||
const models = uniqueModels(params.provider);
|
||||
return models.map((model) => {
|
||||
return uniqueModels(params.provider).map((model) => {
|
||||
const entry: MediaGenerationCatalogEntry<TCapabilities> = {
|
||||
kind: params.kind,
|
||||
provider: params.provider.id,
|
||||
4
packages/media-generation-core/src/index.ts
Normal file
4
packages/media-generation-core/src/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export * from "./capability-model-ref.js";
|
||||
export * from "./catalog.js";
|
||||
export * from "./model-ref.js";
|
||||
export * from "./normalization.js";
|
||||
74
packages/media-generation-core/src/model-ref.test.ts
Normal file
74
packages/media-generation-core/src/model-ref.test.ts
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
resolveCapabilityModelRefForProviders,
|
||||
resolveCapabilityProviderModelOnlyRef,
|
||||
} from "./capability-model-ref.js";
|
||||
import { parseGenerationModelRef } from "./model-ref.js";
|
||||
|
||||
describe("media-generation model refs", () => {
|
||||
it("parses provider/model refs without splitting slash-containing model ids", () => {
|
||||
expect(parseGenerationModelRef("fal/fal-ai/flux/dev")).toEqual({
|
||||
provider: "fal",
|
||||
model: "fal-ai/flux/dev",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects incomplete provider/model refs", () => {
|
||||
expect(parseGenerationModelRef(undefined)).toBeNull();
|
||||
expect(parseGenerationModelRef("openai")).toBeNull();
|
||||
expect(parseGenerationModelRef("/gpt-image-2")).toBeNull();
|
||||
expect(parseGenerationModelRef("openai/")).toBeNull();
|
||||
});
|
||||
|
||||
it("resolves model-only refs from provider metadata", () => {
|
||||
expect(
|
||||
resolveCapabilityProviderModelOnlyRef({
|
||||
raw: "fal-ai/flux/dev",
|
||||
providers: [
|
||||
{
|
||||
id: "fal",
|
||||
defaultModel: "fal-ai/flux/dev",
|
||||
models: ["fal-ai/flux/dev/image-to-image"],
|
||||
},
|
||||
],
|
||||
}),
|
||||
).toEqual({ provider: "fal", model: "fal-ai/flux/dev" });
|
||||
});
|
||||
|
||||
it("keeps explicit provider refs ahead of colliding model-only refs", () => {
|
||||
expect(
|
||||
resolveCapabilityModelRefForProviders({
|
||||
raw: "google/lyria-3-pro-preview",
|
||||
parseModelRef: parseGenerationModelRef,
|
||||
providers: [
|
||||
{
|
||||
id: "google",
|
||||
defaultModel: "lyria-3-clip-preview",
|
||||
models: ["lyria-3-pro-preview"],
|
||||
},
|
||||
{
|
||||
id: "openrouter",
|
||||
defaultModel: "google/lyria-3-pro-preview",
|
||||
},
|
||||
],
|
||||
}),
|
||||
).toEqual({ provider: "google", model: "lyria-3-pro-preview" });
|
||||
});
|
||||
|
||||
it("matches provider aliases through a caller-supplied normalizer", () => {
|
||||
expect(
|
||||
resolveCapabilityModelRefForProviders({
|
||||
raw: "openai-codex/gpt-image-2",
|
||||
parseModelRef: parseGenerationModelRef,
|
||||
normalizeProviderId: (value) => value.toLowerCase(),
|
||||
providers: [
|
||||
{
|
||||
id: "openai",
|
||||
aliases: ["openai-codex"],
|
||||
defaultModel: "gpt-image-2",
|
||||
},
|
||||
],
|
||||
}),
|
||||
).toEqual({ provider: "openai-codex", model: "gpt-image-2" });
|
||||
});
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { normalizeOptionalString } from "./string.js";
|
||||
|
||||
type ParsedGenerationModelRef = {
|
||||
export type ParsedGenerationModelRef = {
|
||||
provider: string;
|
||||
model: string;
|
||||
};
|
||||
|
|
@ -16,8 +16,5 @@ export function parseGenerationModelRef(raw: string | undefined): ParsedGenerati
|
|||
}
|
||||
const provider = normalizeOptionalString(trimmed.slice(0, slashIndex));
|
||||
const model = normalizeOptionalString(trimmed.slice(slashIndex + 1));
|
||||
if (!provider || !model) {
|
||||
return null;
|
||||
}
|
||||
return { provider, model };
|
||||
return provider && model ? { provider, model } : null;
|
||||
}
|
||||
|
|
@ -13,3 +13,15 @@ export type MediaGenerationNormalizationMetadataInput = {
|
|||
resolution?: MediaNormalizationEntry<string>;
|
||||
durationSeconds?: MediaNormalizationEntry<number>;
|
||||
};
|
||||
|
||||
export function hasMediaNormalizationEntry<TValue extends MediaNormalizationValue>(
|
||||
entry: MediaNormalizationEntry<TValue> | undefined,
|
||||
): entry is MediaNormalizationEntry<TValue> {
|
||||
return Boolean(
|
||||
entry &&
|
||||
(entry.requested !== undefined ||
|
||||
entry.applied !== undefined ||
|
||||
entry.derivedFrom !== undefined ||
|
||||
(entry.supportedValues?.length ?? 0) > 0),
|
||||
);
|
||||
}
|
||||
21
packages/media-generation-core/src/string.ts
Normal file
21
packages/media-generation-core/src/string.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
export function normalizeOptionalString(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed ? trimmed : undefined;
|
||||
}
|
||||
|
||||
export function uniqueTrimmedStrings(values: readonly unknown[]): string[] {
|
||||
const seen = new Set<string>();
|
||||
const result: string[] = [];
|
||||
for (const value of values) {
|
||||
const normalized = normalizeOptionalString(value);
|
||||
if (!normalized || seen.has(normalized)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(normalized);
|
||||
result.push(normalized);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
"tsBuildInfoFile": "dist/.tsbuildinfo"
|
||||
},
|
||||
"include": [
|
||||
"../../packages/media-generation-core/src/**/*.ts",
|
||||
"../../src/plugin-sdk/**/*.ts",
|
||||
"../../src/video-generation/dashscope-compatible.ts",
|
||||
"../../src/video-generation/types.ts",
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"../../packages/**/*.test.ts",
|
||||
"../../src/**/*.test.ts",
|
||||
"../../src/plugin-sdk/AGENTS.md",
|
||||
"../../src/plugin-sdk/CLAUDE.md"
|
||||
|
|
|
|||
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
|
|
@ -1812,6 +1812,8 @@ importers:
|
|||
specifier: workspace:*
|
||||
version: link:../llm-core
|
||||
|
||||
packages/media-generation-core: {}
|
||||
|
||||
packages/memory-host-sdk: {}
|
||||
|
||||
packages/net-policy:
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export const BUILD_ALL_STEPS = [
|
|||
"src/plugin-sdk",
|
||||
"packages/llm-core/src",
|
||||
"packages/memory-host-sdk/src",
|
||||
"packages/media-generation-core/src",
|
||||
"src/types",
|
||||
"src/video-generation/dashscope-compatible.ts",
|
||||
"src/video-generation/types.ts",
|
||||
|
|
|
|||
|
|
@ -59,6 +59,24 @@ export const EXTENSION_PACKAGE_BOUNDARY_BASE_PATHS = {
|
|||
"@openclaw/llm-core/types": ["../dist/plugin-sdk/packages/llm-core/src/types.d.ts"],
|
||||
"@openclaw/llm-core/validation": ["../dist/plugin-sdk/packages/llm-core/src/validation.d.ts"],
|
||||
"@openclaw/llm-core/*": ["../dist/plugin-sdk/packages/llm-core/src/*.d.ts"],
|
||||
"@openclaw/media-generation-core": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/index.d.ts",
|
||||
],
|
||||
"@openclaw/media-generation-core/capability-model-ref": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/capability-model-ref.d.ts",
|
||||
],
|
||||
"@openclaw/media-generation-core/catalog": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/catalog.d.ts",
|
||||
],
|
||||
"@openclaw/media-generation-core/model-ref": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/model-ref.d.ts",
|
||||
],
|
||||
"@openclaw/media-generation-core/normalization": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/normalization.d.ts",
|
||||
],
|
||||
"@openclaw/media-generation-core/*": [
|
||||
"../dist/plugin-sdk/packages/media-generation-core/src/*.d.ts",
|
||||
],
|
||||
"@openclaw/*.js": ["../packages/plugin-sdk/dist/extensions/*.d.ts", "../extensions/*"],
|
||||
"@openclaw/*": ["../packages/plugin-sdk/dist/extensions/*", "../extensions/*"],
|
||||
"openclaw/plugin-sdk/qa-channel": ["../dist/plugin-sdk/src/plugin-sdk/qa-channel.d.ts"],
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const PLUGIN_SDK_TYPE_INPUTS = [
|
|||
"src/auto-reply",
|
||||
"packages/llm-core/src",
|
||||
"packages/memory-host-sdk/src",
|
||||
"packages/media-generation-core/src",
|
||||
"src/video-generation/dashscope-compatible.ts",
|
||||
"src/video-generation/types.ts",
|
||||
"src/types",
|
||||
|
|
@ -32,6 +33,11 @@ const ROOT_DTS_REQUIRED_OUTPUTS = [
|
|||
"dist/plugin-sdk/packages/llm-core/src/utils/diagnostics.d.ts",
|
||||
"dist/plugin-sdk/packages/llm-core/src/utils/event-stream.d.ts",
|
||||
"dist/plugin-sdk/packages/llm-core/src/validation.d.ts",
|
||||
"dist/plugin-sdk/packages/media-generation-core/src/capability-model-ref.d.ts",
|
||||
"dist/plugin-sdk/packages/media-generation-core/src/catalog.d.ts",
|
||||
"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/error-runtime.d.ts",
|
||||
"dist/plugin-sdk/plugin-entry.d.ts",
|
||||
"dist/plugin-sdk/provider-auth.d.ts",
|
||||
|
|
@ -40,6 +46,11 @@ const ROOT_DTS_REQUIRED_OUTPUTS = [
|
|||
const PACKAGE_DTS_INPUTS = ["packages/plugin-sdk/tsconfig.json", ...PLUGIN_SDK_TYPE_INPUTS];
|
||||
const PACKAGE_DTS_STAMP = "packages/plugin-sdk/dist/.boundary-dts.stamp";
|
||||
const PACKAGE_DTS_REQUIRED_OUTPUTS = [
|
||||
"packages/plugin-sdk/dist/packages/media-generation-core/src/capability-model-ref.d.ts",
|
||||
"packages/plugin-sdk/dist/packages/media-generation-core/src/catalog.d.ts",
|
||||
"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/src/plugin-sdk/error-runtime.d.ts",
|
||||
"packages/plugin-sdk/dist/src/plugin-sdk/plugin-entry.d.ts",
|
||||
"packages/plugin-sdk/dist/src/plugin-sdk/provider-auth.d.ts",
|
||||
|
|
|
|||
|
|
@ -40,36 +40,48 @@ const STRICT_LITERAL_STRUCTS = new Set([
|
|||
"PluginsSessionActionFailureResult",
|
||||
]);
|
||||
|
||||
const DEFAULTED_OPTIONAL_INIT_PARAMS: Record<string, Set<string>> = {
|
||||
SessionOperationEvent: new Set(["agentId"]),
|
||||
SessionsCompactionListParams: new Set(["agentId"]),
|
||||
SessionsCompactionGetParams: new Set(["agentId"]),
|
||||
SessionsCompactionBranchParams: new Set(["agentId"]),
|
||||
SessionsCompactionRestoreParams: new Set(["agentId"]),
|
||||
SessionsSendParams: new Set(["agentId"]),
|
||||
SessionsMessagesSubscribeParams: new Set(["agentId"]),
|
||||
SessionsMessagesUnsubscribeParams: new Set(["agentId"]),
|
||||
SessionsAbortParams: new Set(["agentId"]),
|
||||
SessionsPatchParams: new Set(["agentId"]),
|
||||
SessionsResetParams: new Set(["agentId"]),
|
||||
SessionsDeleteParams: new Set(["agentId"]),
|
||||
SessionsCompactParams: new Set(["agentId"]),
|
||||
SessionsUsageParams: new Set(["agentId", "agentScope"]),
|
||||
ChatHistoryParams: new Set(["agentId"]),
|
||||
ChatSendParams: new Set(["agentId"]),
|
||||
ChatAbortParams: new Set(["agentId"]),
|
||||
ChatInjectParams: new Set(["agentId"]),
|
||||
ChatDeltaEvent: new Set(["agentId"]),
|
||||
ChatFinalEvent: new Set(["agentId"]),
|
||||
ChatAbortedEvent: new Set(["agentId"]),
|
||||
ChatErrorEvent: new Set(["agentId"]),
|
||||
ArtifactsListParams: new Set(["agentId"]),
|
||||
ArtifactsGetParams: new Set(["agentId"]),
|
||||
ArtifactsDownloadParams: new Set(["agentId"]),
|
||||
MessageActionParams: new Set(["inboundTurnKind"]),
|
||||
CronRunLogEntry: new Set(["errorReason", "failureNotificationDelivery"]),
|
||||
ExecApprovalRequestParams: new Set(["requireDeliveryRoute", "suppressDelivery"]),
|
||||
};
|
||||
const DEFAULTED_OPTIONAL_INIT_PARAM_ENTRIES: readonly [string, readonly string[]][] = [
|
||||
["SessionOperationEvent", ["agentId"]],
|
||||
["SessionsCompactionListParams", ["agentId"]],
|
||||
["SessionsCompactionGetParams", ["agentId"]],
|
||||
["SessionsCompactionBranchParams", ["agentId"]],
|
||||
["SessionsCompactionRestoreParams", ["agentId"]],
|
||||
["SessionsSendParams", ["agentId"]],
|
||||
["SessionsMessagesSubscribeParams", ["agentId"]],
|
||||
["SessionsMessagesUnsubscribeParams", ["agentId"]],
|
||||
["SessionsAbortParams", ["agentId"]],
|
||||
["SessionsPatchParams", ["agentId"]],
|
||||
["SessionsResetParams", ["agentId"]],
|
||||
["SessionsDeleteParams", ["agentId"]],
|
||||
["SessionsCompactParams", ["agentId"]],
|
||||
["SessionsUsageParams", ["agentId", "agentScope"]],
|
||||
["ChatHistoryParams", ["agentId"]],
|
||||
["ChatSendParams", ["agentId"]],
|
||||
["ChatAbortParams", ["agentId"]],
|
||||
["ChatInjectParams", ["agentId"]],
|
||||
["ChatDeltaEvent", ["agentId"]],
|
||||
["ChatFinalEvent", ["agentId"]],
|
||||
["ChatAbortedEvent", ["agentId"]],
|
||||
["ChatErrorEvent", ["agentId"]],
|
||||
["ArtifactsListParams", ["agentId"]],
|
||||
["ArtifactsGetParams", ["agentId"]],
|
||||
["ArtifactsDownloadParams", ["agentId"]],
|
||||
["ChatAbortParams", ["agentId"]],
|
||||
["ChatAbortedEvent", ["agentId"]],
|
||||
["ChatDeltaEvent", ["agentId"]],
|
||||
["ChatErrorEvent", ["agentId"]],
|
||||
["ChatFinalEvent", ["agentId"]],
|
||||
["ChatHistoryParams", ["agentId"]],
|
||||
["ChatInjectParams", ["agentId"]],
|
||||
["ChatSendParams", ["agentId"]],
|
||||
["MessageActionParams", ["inboundTurnKind"]],
|
||||
["CronRunLogEntry", ["errorReason", "failureNotificationDelivery"]],
|
||||
["ExecApprovalRequestParams", ["requireDeliveryRoute", "suppressDelivery"]],
|
||||
];
|
||||
|
||||
const DEFAULTED_OPTIONAL_INIT_PARAMS: Record<string, Set<string>> = Object.fromEntries(
|
||||
DEFAULTED_OPTIONAL_INIT_PARAM_ENTRIES.map(([name, params]) => [name, new Set(params)]),
|
||||
);
|
||||
|
||||
const header = `// Generated by scripts/protocol-gen-swift.ts — do not edit by hand\n// swiftlint:disable file_length\nimport Foundation\n\npublic let GATEWAY_PROTOCOL_VERSION = ${PROTOCOL_VERSION}\npublic let GATEWAY_MIN_PROTOCOL_VERSION = ${MIN_CLIENT_PROTOCOL_VERSION}\n\nprivate struct GatewayAnyCodingKey: CodingKey, Hashable {\n let stringValue: String\n let intValue: Int?\n\n init?(stringValue: String) {\n self.stringValue = stringValue\n self.intValue = nil\n }\n\n init?(intValue: Int) {\n self.stringValue = String(intValue)\n self.intValue = intValue\n }\n}\n\npublic enum ErrorCode: String, Codable, Sendable {\n${Object.values(
|
||||
ErrorCodes,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const RUN_NODE_PACKAGE_SOURCE_ROOTS = [
|
|||
// src/ so edits restart the same process that consumes them.
|
||||
"packages/gateway-client/src",
|
||||
"packages/gateway-protocol/src",
|
||||
"packages/media-generation-core/src",
|
||||
"packages/net-policy/src",
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import { MAX_SAFE_TIMEOUT_DELAY_MS } from "../utils/timer-delay.js";
|
|||
type StrictInlineEvalBoundary =
|
||||
typeof import("./bash-tools.exec-host-shared.js").enforceStrictInlineEvalApprovalBoundary;
|
||||
type ExecAutoReviewer = typeof import("../infra/exec-auto-review.js").defaultExecAutoReviewer;
|
||||
type ExecAsk = import("../infra/exec-approvals.js").ExecAsk;
|
||||
type ExecSecurity = import("../infra/exec-approvals.js").ExecSecurity;
|
||||
type MockAllowlistSegment = {
|
||||
raw?: string;
|
||||
resolution: null;
|
||||
|
|
@ -17,11 +19,21 @@ type MockAllowlistResult = {
|
|||
segments: MockAllowlistSegment[];
|
||||
segmentAllowlistEntries: unknown[];
|
||||
};
|
||||
type MockExecApprovalAllowlistEntry = {
|
||||
type MockExecAllowlistEntry = {
|
||||
pattern: string;
|
||||
source?: string;
|
||||
source?: "allow-always";
|
||||
commandText?: string;
|
||||
};
|
||||
type MockExecApprovalsResolved = {
|
||||
allowlist: MockExecAllowlistEntry[];
|
||||
file: { version: 1; agents: Record<string, unknown> };
|
||||
agent: {
|
||||
security: ExecSecurity;
|
||||
ask: ExecAsk;
|
||||
askFallback: "deny";
|
||||
autoAllowSkills: false;
|
||||
};
|
||||
};
|
||||
|
||||
const INLINE_EVAL_HIT = {
|
||||
executable: "python3",
|
||||
|
|
@ -60,16 +72,18 @@ const evaluateShellAllowlistMock = vi.hoisted(() =>
|
|||
),
|
||||
);
|
||||
const resolveExecApprovalsFromFileMock = vi.hoisted(() =>
|
||||
vi.fn(() => ({
|
||||
allowlist: [] as MockExecApprovalAllowlistEntry[],
|
||||
file: { version: 1, agents: {} },
|
||||
agent: {
|
||||
security: "full",
|
||||
ask: "off",
|
||||
askFallback: "deny",
|
||||
autoAllowSkills: false,
|
||||
},
|
||||
})),
|
||||
vi.fn(
|
||||
(): MockExecApprovalsResolved => ({
|
||||
allowlist: [],
|
||||
file: { version: 1, agents: {} },
|
||||
agent: {
|
||||
security: "full",
|
||||
ask: "off",
|
||||
askFallback: "deny",
|
||||
autoAllowSkills: false,
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
const requiresExecApprovalMock = vi.hoisted(() => vi.fn(() => true));
|
||||
const hasDurableExecApprovalMock = vi.hoisted(() => vi.fn(() => false));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import {
|
||||
listMediaGenerationProviderModels,
|
||||
synthesizeMediaGenerationCatalogEntries,
|
||||
type MediaGenerationCatalogKind,
|
||||
} from "../../media-generation/catalog.js";
|
||||
} from "../../../packages/media-generation-core/src/catalog.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { getProviderEnvVars } from "../../secrets/provider-env-vars.js";
|
||||
import type { AuthProfileStore } from "../auth-profiles/types.js";
|
||||
import { isCapabilityProviderConfigured } from "./media-tool-shared.js";
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import {
|
||||
findCapabilityProviderById,
|
||||
resolveCapabilityModelRefForProviders,
|
||||
} from "../../../packages/media-generation-core/src/capability-model-ref.js";
|
||||
import type { AgentModelConfig } from "../../config/types.agents-shared.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import type { SsrFPolicy } from "../../infra/net/ssrf.js";
|
||||
import type { Model } from "../../llm/types.js";
|
||||
import {
|
||||
findCapabilityProviderById,
|
||||
resolveCapabilityModelRefForProviders,
|
||||
} from "../../media-generation/capability-model-ref.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";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { parseGenerationModelRef } from "../media-generation/model-ref.js";
|
||||
import { parseGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js";
|
||||
|
||||
export function parseImageGenerationModelRef(
|
||||
raw: string | undefined,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { MediaNormalizationEntry } from "../../packages/media-generation-core/src/normalization.js";
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { SsrFPolicy } from "../infra/net/ssrf.js";
|
||||
import type { MediaNormalizationEntry } from "../media-generation/normalization.types.js";
|
||||
|
||||
export type GeneratedImageAsset = {
|
||||
buffer: Buffer;
|
||||
|
|
|
|||
|
|
@ -342,6 +342,7 @@ describe("openHttpConnectTunnel", () => {
|
|||
targetPort: 443,
|
||||
timeoutMs: 1,
|
||||
});
|
||||
void tunnel.catch(() => undefined);
|
||||
const rejected = expect(tunnel).rejects.toThrow(
|
||||
"Proxy CONNECT failed via http://proxy.example:8080: Proxy CONNECT timed out after 1ms",
|
||||
);
|
||||
|
|
@ -364,6 +365,7 @@ describe("openHttpConnectTunnel", () => {
|
|||
targetPort: 443,
|
||||
timeoutMs: Number.MAX_SAFE_INTEGER,
|
||||
});
|
||||
void tunnel.catch(() => undefined);
|
||||
const rejected = expect(tunnel).rejects.toThrow(
|
||||
`Proxy CONNECT failed via http://proxy.example:8080: Proxy CONNECT timed out after ${MAX_TIMER_TIMEOUT_MS}ms`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ describe("watch-node script", () => {
|
|||
expect(watchPaths).toContain("extensions");
|
||||
expect(watchPaths).toContain("packages/gateway-client/src");
|
||||
expect(watchPaths).toContain("packages/gateway-protocol/src");
|
||||
expect(watchPaths).toContain("packages/media-generation-core/src");
|
||||
expect(watchPaths).toContain("packages/net-policy/src");
|
||||
expect(watchPaths).toContain("tsdown.config.ts");
|
||||
expect(watchOptions.ignoreInitial).toBe(true);
|
||||
|
|
@ -140,6 +141,10 @@ describe("watch-node script", () => {
|
|||
expect(watchOptions.ignored("packages/gateway-client/src/client.ts")).toBe(false);
|
||||
expect(watchOptions.ignored("packages/gateway-client/src/client.test.ts")).toBe(true);
|
||||
expect(watchOptions.ignored("packages/gateway-protocol/src/schema/cron.ts")).toBe(false);
|
||||
expect(watchOptions.ignored("packages/media-generation-core/src/model-ref.ts")).toBe(false);
|
||||
expect(watchOptions.ignored("packages/media-generation-core/src/model-ref.test.ts")).toBe(
|
||||
true,
|
||||
);
|
||||
expect(watchOptions.ignored("packages/net-policy/src/ip.ts")).toBe(false);
|
||||
expect(watchOptions.ignored("packages/net-policy/src/ip.test.ts")).toBe(true);
|
||||
expect(watchOptions.ignored("extensions")).toBe(false);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { resolveCapabilityModelRefForProviders } from "../../packages/media-generation-core/src/capability-model-ref.js";
|
||||
import type { MediaGenerationNormalizationMetadataInput } from "../../packages/media-generation-core/src/normalization.js";
|
||||
import { listProfilesForProvider } from "../agents/auth-profiles.js";
|
||||
import { ensureAuthProfileStore } from "../agents/auth-profiles.js";
|
||||
import { DEFAULT_PROVIDER } from "../agents/defaults.js";
|
||||
|
|
@ -14,23 +16,17 @@ import { formatErrorMessage } from "../infra/errors.js";
|
|||
import { getProviderEnvVars as getDefaultProviderEnvVars } from "../secrets/provider-env-vars.js";
|
||||
import { clampTimerTimeoutMs } from "../shared/number-coercion.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { resolveCapabilityModelRefForProviders } from "./capability-model-ref.js";
|
||||
import type {
|
||||
export type {
|
||||
MediaGenerationNormalizationMetadataInput,
|
||||
MediaNormalizationEntry,
|
||||
MediaNormalizationValue,
|
||||
} from "./normalization.types.js";
|
||||
} from "../../packages/media-generation-core/src/normalization.js";
|
||||
export { hasMediaNormalizationEntry } from "../../packages/media-generation-core/src/normalization.js";
|
||||
|
||||
export type ParsedProviderModelRef = {
|
||||
provider: string;
|
||||
model: string;
|
||||
};
|
||||
export type {
|
||||
MediaGenerationNormalizationMetadataInput,
|
||||
MediaNormalizationEntry,
|
||||
MediaNormalizationValue,
|
||||
} from "./normalization.types.js";
|
||||
|
||||
export function recordCapabilityCandidateFailure(params: {
|
||||
attempts: FallbackAttempt[];
|
||||
provider: string;
|
||||
|
|
@ -48,18 +44,6 @@ export function recordCapabilityCandidateFailure(params: {
|
|||
});
|
||||
}
|
||||
|
||||
export function hasMediaNormalizationEntry<TValue extends MediaNormalizationValue>(
|
||||
entry: MediaNormalizationEntry<TValue> | undefined,
|
||||
): entry is MediaNormalizationEntry<TValue> {
|
||||
return Boolean(
|
||||
entry &&
|
||||
(entry.requested !== undefined ||
|
||||
entry.applied !== undefined ||
|
||||
entry.derivedFrom !== undefined ||
|
||||
(entry.supportedValues?.length ?? 0) > 0),
|
||||
);
|
||||
}
|
||||
|
||||
const IMAGE_RESOLUTION_ORDER = ["1K", "2K", "4K"] as const;
|
||||
|
||||
export function resolveMediaProviderDefaultTimeoutMs(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { parseGenerationModelRef } from "../media-generation/model-ref.js";
|
||||
import { parseGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js";
|
||||
|
||||
export function parseMusicGenerationModelRef(
|
||||
raw: string | undefined,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { MediaNormalizationEntry } from "../../packages/media-generation-core/src/normalization.js";
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { MediaNormalizationEntry } from "../media-generation/normalization.types.js";
|
||||
|
||||
export type MusicGenerationOutputFormat = "mp3" | "wav";
|
||||
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ describe("opt-in extension package boundaries", () => {
|
|||
expect(tsconfig.compilerOptions?.outDir).toBe("dist");
|
||||
expect(tsconfig.compilerOptions?.rootDir).toBe("../..");
|
||||
expect(tsconfig.include).toEqual([
|
||||
"../../packages/media-generation-core/src/**/*.ts",
|
||||
"../../src/plugin-sdk/**/*.ts",
|
||||
"../../src/video-generation/dashscope-compatible.ts",
|
||||
"../../src/video-generation/types.ts",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import {
|
||||
synthesizeMediaGenerationCatalogEntries,
|
||||
type MediaGenerationCatalogKind,
|
||||
type MediaGenerationCatalogProvider,
|
||||
} from "../../packages/media-generation-core/src/catalog.js";
|
||||
import {
|
||||
synthesizeVoiceModelCatalogEntries,
|
||||
type VoiceModelCapabilities,
|
||||
type VoiceModelProvider,
|
||||
} from "../../packages/speech-core/voice-models.js";
|
||||
import {
|
||||
synthesizeMediaGenerationCatalogEntries,
|
||||
type MediaGenerationCatalogKind,
|
||||
type MediaGenerationCatalogProvider,
|
||||
} from "../media-generation/catalog.js";
|
||||
import type {
|
||||
UnifiedModelCatalogEntry,
|
||||
UnifiedModelCatalogSource,
|
||||
|
|
|
|||
|
|
@ -1378,6 +1378,18 @@ describe("plugin sdk alias helpers", () => {
|
|||
srcFile: "index.ts",
|
||||
distFile: "index.mjs",
|
||||
});
|
||||
const mediaGenerationCore = writeWorkspacePackageEntry({
|
||||
root: fixture.root,
|
||||
packageDir: "media-generation-core",
|
||||
srcFile: "index.ts",
|
||||
distFile: "index.mjs",
|
||||
});
|
||||
const mediaGenerationModelRef = writeWorkspacePackageEntry({
|
||||
root: fixture.root,
|
||||
packageDir: "media-generation-core",
|
||||
srcFile: "model-ref.ts",
|
||||
distFile: "model-ref.mjs",
|
||||
});
|
||||
const netPolicyIp = writeWorkspacePackageEntry({
|
||||
root: fixture.root,
|
||||
packageDir: "net-policy",
|
||||
|
|
@ -1388,6 +1400,8 @@ describe("plugin sdk alias helpers", () => {
|
|||
fs.rmSync(gatewayClientTimeouts.distFile);
|
||||
fs.rmSync(gatewayProtocol.distFile);
|
||||
fs.rmSync(gatewayProtocolSchema.distFile);
|
||||
fs.rmSync(mediaGenerationCore.distFile);
|
||||
fs.rmSync(mediaGenerationModelRef.distFile);
|
||||
fs.rmSync(netPolicy.distFile);
|
||||
fs.rmSync(netPolicyIp.distFile);
|
||||
const sourcePluginEntry = writePluginEntry(
|
||||
|
|
@ -1411,6 +1425,12 @@ describe("plugin sdk alias helpers", () => {
|
|||
expect(fs.realpathSync(aliases["@openclaw/gateway-protocol/schema"] ?? "")).toBe(
|
||||
fs.realpathSync(gatewayProtocolSchema.srcFile),
|
||||
);
|
||||
expect(fs.realpathSync(aliases["@openclaw/media-generation-core"] ?? "")).toBe(
|
||||
fs.realpathSync(mediaGenerationCore.srcFile),
|
||||
);
|
||||
expect(fs.realpathSync(aliases["@openclaw/media-generation-core/model-ref"] ?? "")).toBe(
|
||||
fs.realpathSync(mediaGenerationModelRef.srcFile),
|
||||
);
|
||||
expect(fs.realpathSync(aliases["@openclaw/net-policy"] ?? "")).toBe(
|
||||
fs.realpathSync(netPolicy.srcFile),
|
||||
);
|
||||
|
|
@ -1433,6 +1453,12 @@ describe("plugin sdk alias helpers", () => {
|
|||
srcFile: "connect-error-details.ts",
|
||||
distFile: "connect-error-details.mjs",
|
||||
});
|
||||
const mediaGenerationCore = writeWorkspacePackageEntry({
|
||||
root: fixture.root,
|
||||
packageDir: "media-generation-core",
|
||||
srcFile: "catalog.ts",
|
||||
distFile: "catalog.mjs",
|
||||
});
|
||||
const netPolicy = writeWorkspacePackageEntry({
|
||||
root: fixture.root,
|
||||
packageDir: "net-policy",
|
||||
|
|
@ -1454,6 +1480,9 @@ describe("plugin sdk alias helpers", () => {
|
|||
expect(fs.realpathSync(aliases["@openclaw/gateway-protocol/connect-error-details"] ?? "")).toBe(
|
||||
fs.realpathSync(gatewayProtocol.distFile),
|
||||
);
|
||||
expect(fs.realpathSync(aliases["@openclaw/media-generation-core/catalog"] ?? "")).toBe(
|
||||
fs.realpathSync(mediaGenerationCore.distFile),
|
||||
);
|
||||
expect(fs.realpathSync(aliases["@openclaw/net-policy/redact-sensitive-url"] ?? "")).toBe(
|
||||
fs.realpathSync(netPolicy.distFile),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -560,6 +560,41 @@ const WORKSPACE_PACKAGE_ALIAS_ENTRIES = [
|
|||
srcFile: "version.ts",
|
||||
distFile: "version.mjs",
|
||||
},
|
||||
{
|
||||
packageName: "@openclaw/media-generation-core",
|
||||
packageDir: "media-generation-core",
|
||||
subpath: "",
|
||||
srcFile: "index.ts",
|
||||
distFile: "index.mjs",
|
||||
},
|
||||
{
|
||||
packageName: "@openclaw/media-generation-core",
|
||||
packageDir: "media-generation-core",
|
||||
subpath: "capability-model-ref",
|
||||
srcFile: "capability-model-ref.ts",
|
||||
distFile: "capability-model-ref.mjs",
|
||||
},
|
||||
{
|
||||
packageName: "@openclaw/media-generation-core",
|
||||
packageDir: "media-generation-core",
|
||||
subpath: "catalog",
|
||||
srcFile: "catalog.ts",
|
||||
distFile: "catalog.mjs",
|
||||
},
|
||||
{
|
||||
packageName: "@openclaw/media-generation-core",
|
||||
packageDir: "media-generation-core",
|
||||
subpath: "model-ref",
|
||||
srcFile: "model-ref.ts",
|
||||
distFile: "model-ref.mjs",
|
||||
},
|
||||
{
|
||||
packageName: "@openclaw/media-generation-core",
|
||||
packageDir: "media-generation-core",
|
||||
subpath: "normalization",
|
||||
srcFile: "normalization.ts",
|
||||
distFile: "normalization.mjs",
|
||||
},
|
||||
{
|
||||
packageName: "@openclaw/net-policy",
|
||||
packageDir: "net-policy",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { parseGenerationModelRef } from "../media-generation/model-ref.js";
|
||||
import { parseGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js";
|
||||
|
||||
export function parseVideoGenerationModelRef(
|
||||
raw: string | undefined,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { MediaNormalizationEntry } from "../../packages/media-generation-core/src/normalization.js";
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { MediaNormalizationEntry } from "../media-generation/normalization.types.js";
|
||||
|
||||
export type GeneratedVideoAsset = {
|
||||
/** Raw video bytes. Required for local delivery; omit when url is provided instead. */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createWizardPrompter } from "../../test/helpers/wizard-prompter.js";
|
||||
import { createNonExitingRuntime } from "../runtime.js";
|
||||
import type { WizardPrompter } from "./prompts.js";
|
||||
import type { WizardMultiSelectParams, WizardPrompter } from "./prompts.js";
|
||||
|
||||
const ensureOnboardingPluginInstalled = vi.hoisted(() =>
|
||||
vi.fn(async ({ cfg }: { cfg: Record<string, unknown> }) => ({
|
||||
|
|
@ -92,9 +92,9 @@ describe("setupOfficialPluginInstalls", () => {
|
|||
});
|
||||
|
||||
it("installs selected optional official plugins through the shared onboarding installer", async () => {
|
||||
const multiselect = vi.fn(async () => ["diagnostics-otel"]);
|
||||
const multiselect = vi.fn(async (_params: WizardMultiSelectParams) => ["diagnostics-otel"]);
|
||||
const prompter = createWizardPrompter({
|
||||
multiselect: multiselect as WizardPrompter["multiselect"],
|
||||
multiselect: multiselect as unknown as WizardPrompter["multiselect"],
|
||||
});
|
||||
const runtime = createNonExitingRuntime();
|
||||
|
||||
|
|
@ -105,14 +105,19 @@ describe("setupOfficialPluginInstalls", () => {
|
|||
workspaceDir: "/tmp/workspace",
|
||||
});
|
||||
|
||||
expect(multiselect).toHaveBeenCalledExactlyOnceWith({
|
||||
message: "Install optional plugins",
|
||||
options: [
|
||||
{
|
||||
value: "__skip__",
|
||||
label: "Skip for now",
|
||||
hint: "Continue without installing optional plugins",
|
||||
},
|
||||
expect(multiselect).toHaveBeenCalledTimes(1);
|
||||
const prompt = multiselect.mock.calls[0]?.[0];
|
||||
if (!prompt) {
|
||||
throw new Error("expected optional plugin multiselect prompt");
|
||||
}
|
||||
expect(prompt.message).toBe("Install optional plugins");
|
||||
expect(prompt.options[0]).toEqual({
|
||||
value: "__skip__",
|
||||
label: "Skip for now",
|
||||
hint: "Continue without installing optional plugins",
|
||||
});
|
||||
expect(prompt.options).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
value: "acpx",
|
||||
label: "ACPX Runtime",
|
||||
|
|
@ -128,58 +133,8 @@ describe("setupOfficialPluginInstalls", () => {
|
|||
label: "Diagnostics Prometheus",
|
||||
hint: "OpenClaw diagnostics Prometheus exporter",
|
||||
},
|
||||
{
|
||||
value: "diffs-language-pack",
|
||||
label: "Diff Viewer Language Pack",
|
||||
hint: "OpenClaw diffs viewer syntax highlighting language pack",
|
||||
},
|
||||
{
|
||||
value: "diffs",
|
||||
label: "Diffs",
|
||||
hint: "OpenClaw diff viewer plugin",
|
||||
},
|
||||
{
|
||||
value: "copilot",
|
||||
label: "GitHub Copilot agent runtime",
|
||||
hint: "OpenClaw GitHub Copilot agent runtime plugin",
|
||||
},
|
||||
{
|
||||
value: "google-meet",
|
||||
label: "Google Meet",
|
||||
hint: "OpenClaw Google Meet participant plugin",
|
||||
},
|
||||
{
|
||||
value: "lobster",
|
||||
label: "Lobster",
|
||||
hint: "Lobster workflow tool plugin (typed pipelines + resumable approvals)",
|
||||
},
|
||||
{
|
||||
value: "memory-lancedb",
|
||||
label: "Memory LanceDB",
|
||||
hint: "OpenClaw LanceDB-backed long-term memory plugin with auto-recall/capture",
|
||||
},
|
||||
{
|
||||
value: "openshell",
|
||||
label: "OpenShell Sandbox",
|
||||
hint: "OpenClaw OpenShell sandbox backend",
|
||||
},
|
||||
{
|
||||
value: "pixverse",
|
||||
label: "PixVerse",
|
||||
hint: "OpenClaw PixVerse video generation provider plugin",
|
||||
},
|
||||
{
|
||||
value: "tokenjuice",
|
||||
label: "Tokenjuice",
|
||||
hint: "OpenClaw tokenjuice exec output compaction plugin",
|
||||
},
|
||||
{
|
||||
value: "voice-call",
|
||||
label: "Voice Call",
|
||||
hint: "OpenClaw voice-call plugin",
|
||||
},
|
||||
],
|
||||
});
|
||||
]),
|
||||
);
|
||||
expect(ensureOnboardingPluginInstalled).toHaveBeenCalledExactlyOnceWith({
|
||||
cfg: {},
|
||||
entry: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
import { spawnSync } from "node:child_process";
|
||||
import { chmodSync, mkdirSync, mkdtempSync, rmSync, statSync, writeFileSync } from "node:fs";
|
||||
import {
|
||||
chmodSync,
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
rmSync,
|
||||
statSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
|
|
|
|||
|
|
@ -51,6 +51,20 @@
|
|||
],
|
||||
"@openclaw/gateway-protocol/version": ["./packages/gateway-protocol/src/version.ts"],
|
||||
"@openclaw/gateway-protocol/*": ["./packages/gateway-protocol/src/*"],
|
||||
"@openclaw/media-generation-core": ["./packages/media-generation-core/src/index.ts"],
|
||||
"@openclaw/media-generation-core/capability-model-ref": [
|
||||
"./packages/media-generation-core/src/capability-model-ref.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/catalog": [
|
||||
"./packages/media-generation-core/src/catalog.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/model-ref": [
|
||||
"./packages/media-generation-core/src/model-ref.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/normalization": [
|
||||
"./packages/media-generation-core/src/normalization.ts"
|
||||
],
|
||||
"@openclaw/media-generation-core/*": ["./packages/media-generation-core/src/*"],
|
||||
"@openclaw/net-policy": ["./packages/net-policy/src/index.ts"],
|
||||
"@openclaw/net-policy/ip": ["./packages/net-policy/src/ip.ts"],
|
||||
"@openclaw/net-policy/ipv4": ["./packages/net-policy/src/ipv4.ts"],
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@
|
|||
"include": [
|
||||
"src/plugin-sdk/**/*.ts",
|
||||
"packages/llm-core/src/**/*.ts",
|
||||
"packages/media-generation-core/src/**/*.ts",
|
||||
"packages/memory-host-sdk/src/**/*.ts",
|
||||
"src/video-generation/dashscope-compatible.ts",
|
||||
"src/video-generation/types.ts",
|
||||
"src/types/**/*.d.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "dist", "src/**/*.test.ts"]
|
||||
"exclude": ["node_modules", "dist", "packages/**/*.test.ts", "src/**/*.test.ts"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -384,6 +384,16 @@ function buildNetPolicyDistEntries(): Record<string, string> {
|
|||
};
|
||||
}
|
||||
|
||||
function buildMediaGenerationCoreDistEntries(): Record<string, string> {
|
||||
return {
|
||||
index: "packages/media-generation-core/src/index.ts",
|
||||
"capability-model-ref": "packages/media-generation-core/src/capability-model-ref.ts",
|
||||
catalog: "packages/media-generation-core/src/catalog.ts",
|
||||
"model-ref": "packages/media-generation-core/src/model-ref.ts",
|
||||
normalization: "packages/media-generation-core/src/normalization.ts",
|
||||
};
|
||||
}
|
||||
|
||||
function buildSpeechCoreDistEntries(): Record<string, string> {
|
||||
return {
|
||||
api: "packages/speech-core/api.ts",
|
||||
|
|
@ -523,6 +533,12 @@ export default defineConfig([
|
|||
neverBundle: shouldExternalizeNetPolicyDependency,
|
||||
},
|
||||
}),
|
||||
nodeWorkspacePackageBuildConfig({
|
||||
clean: true,
|
||||
dts: RUN_NODE_SKIP_DTS_BUILD ? false : undefined,
|
||||
entry: buildMediaGenerationCoreDistEntries(),
|
||||
outDir: "packages/media-generation-core/dist",
|
||||
}),
|
||||
nodeWorkspacePackageBuildConfig({
|
||||
clean: true,
|
||||
dts: RUN_NODE_SKIP_DTS_BUILD ? false : undefined,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue