mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-19 14:00:51 +00:00
fix(release): isolate config doc surfaces and sdk exports
This commit is contained in:
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/device-pair.js";
|
||||
export * from "openclaw/plugin-sdk/device-pair";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/diagnostics-otel.js";
|
||||
export * from "openclaw/plugin-sdk/diagnostics-otel";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/diffs.js";
|
||||
export * from "openclaw/plugin-sdk/diffs";
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "../../src/plugin-sdk/line.js";
|
||||
export * from "openclaw/plugin-sdk/line";
|
||||
export * from "./setup-api.js";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/llm-task.js";
|
||||
export * from "openclaw/plugin-sdk/llm-task";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/memory-lancedb.js";
|
||||
export * from "openclaw/plugin-sdk/memory-lancedb";
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
import {
|
||||
buildOauthProviderAuthResult,
|
||||
definePluginEntry,
|
||||
type ProviderAuthContext,
|
||||
type ProviderAuthResult,
|
||||
type ProviderCatalogContext,
|
||||
} from "openclaw/plugin-sdk/minimax-portal-auth";
|
||||
import {
|
||||
MINIMAX_OAUTH_MARKER,
|
||||
createProviderApiKeyAuthMethod,
|
||||
@@ -5,13 +12,6 @@ import {
|
||||
listProfilesForProvider,
|
||||
} from "openclaw/plugin-sdk/provider-auth";
|
||||
import { fetchMinimaxUsage } from "openclaw/plugin-sdk/provider-usage";
|
||||
import {
|
||||
buildOauthProviderAuthResult,
|
||||
definePluginEntry,
|
||||
type ProviderAuthContext,
|
||||
type ProviderAuthResult,
|
||||
type ProviderCatalogContext,
|
||||
} from "../../src/plugin-sdk/minimax-portal-auth.js";
|
||||
import {
|
||||
minimaxMediaUnderstandingProvider,
|
||||
minimaxPortalMediaUnderstandingProvider,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomBytes, randomUUID } from "node:crypto";
|
||||
import {
|
||||
generatePkceVerifierChallenge,
|
||||
toFormUrlEncoded,
|
||||
} from "../../src/plugin-sdk/minimax-portal-auth.js";
|
||||
} from "openclaw/plugin-sdk/minimax-portal-auth";
|
||||
|
||||
export type MiniMaxRegion = "cn" | "global";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/nostr.js";
|
||||
export * from "openclaw/plugin-sdk/nostr";
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
resolveAccountEntry,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/account-resolution";
|
||||
import type { SignalAccountConfig } from "../../../src/plugin-sdk/signal-core.js";
|
||||
import type { SignalAccountConfig } from "openclaw/plugin-sdk/signal-core";
|
||||
|
||||
export type ResolvedSignalAccount = {
|
||||
accountId: string;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "../../src/plugin-sdk/synology-chat.js";
|
||||
export * from "openclaw/plugin-sdk/synology-chat";
|
||||
export * from "./setup-api.js";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/talk-voice.js";
|
||||
export * from "openclaw/plugin-sdk/talk-voice";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/thread-ownership.js";
|
||||
export * from "openclaw/plugin-sdk/thread-ownership";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/tlon.js";
|
||||
export * from "openclaw/plugin-sdk/tlon";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/twitch.js";
|
||||
export * from "openclaw/plugin-sdk/twitch";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "../../src/plugin-sdk/voice-call.js";
|
||||
export * from "openclaw/plugin-sdk/voice-call";
|
||||
|
||||
72
package.json
72
package.json
@@ -182,6 +182,10 @@
|
||||
"types": "./dist/plugin-sdk/discord-core.d.ts",
|
||||
"default": "./dist/plugin-sdk/discord-core.js"
|
||||
},
|
||||
"./plugin-sdk/feishu": {
|
||||
"types": "./dist/plugin-sdk/feishu.d.ts",
|
||||
"default": "./dist/plugin-sdk/feishu.js"
|
||||
},
|
||||
"./plugin-sdk/slack": {
|
||||
"types": "./dist/plugin-sdk/slack.d.ts",
|
||||
"default": "./dist/plugin-sdk/slack.js"
|
||||
@@ -250,6 +254,18 @@
|
||||
"types": "./dist/plugin-sdk/boolean-param.d.ts",
|
||||
"default": "./dist/plugin-sdk/boolean-param.js"
|
||||
},
|
||||
"./plugin-sdk/device-pair": {
|
||||
"types": "./dist/plugin-sdk/device-pair.d.ts",
|
||||
"default": "./dist/plugin-sdk/device-pair.js"
|
||||
},
|
||||
"./plugin-sdk/diagnostics-otel": {
|
||||
"types": "./dist/plugin-sdk/diagnostics-otel.d.ts",
|
||||
"default": "./dist/plugin-sdk/diagnostics-otel.js"
|
||||
},
|
||||
"./plugin-sdk/diffs": {
|
||||
"types": "./dist/plugin-sdk/diffs.d.ts",
|
||||
"default": "./dist/plugin-sdk/diffs.js"
|
||||
},
|
||||
"./plugin-sdk/channel-config-helpers": {
|
||||
"types": "./dist/plugin-sdk/channel-config-helpers.d.ts",
|
||||
"default": "./dist/plugin-sdk/channel-config-helpers.js"
|
||||
@@ -290,6 +306,22 @@
|
||||
"types": "./dist/plugin-sdk/keyed-async-queue.d.ts",
|
||||
"default": "./dist/plugin-sdk/keyed-async-queue.js"
|
||||
},
|
||||
"./plugin-sdk/line": {
|
||||
"types": "./dist/plugin-sdk/line.d.ts",
|
||||
"default": "./dist/plugin-sdk/line.js"
|
||||
},
|
||||
"./plugin-sdk/llm-task": {
|
||||
"types": "./dist/plugin-sdk/llm-task.d.ts",
|
||||
"default": "./dist/plugin-sdk/llm-task.js"
|
||||
},
|
||||
"./plugin-sdk/memory-lancedb": {
|
||||
"types": "./dist/plugin-sdk/memory-lancedb.d.ts",
|
||||
"default": "./dist/plugin-sdk/memory-lancedb.js"
|
||||
},
|
||||
"./plugin-sdk/minimax-portal-auth": {
|
||||
"types": "./dist/plugin-sdk/minimax-portal-auth.d.ts",
|
||||
"default": "./dist/plugin-sdk/minimax-portal-auth.js"
|
||||
},
|
||||
"./plugin-sdk/provider-auth": {
|
||||
"types": "./dist/plugin-sdk/provider-auth.d.ts",
|
||||
"default": "./dist/plugin-sdk/provider-auth.js"
|
||||
@@ -334,6 +366,10 @@
|
||||
"types": "./dist/plugin-sdk/image-generation.d.ts",
|
||||
"default": "./dist/plugin-sdk/image-generation.js"
|
||||
},
|
||||
"./plugin-sdk/nostr": {
|
||||
"types": "./dist/plugin-sdk/nostr.d.ts",
|
||||
"default": "./dist/plugin-sdk/nostr.js"
|
||||
},
|
||||
"./plugin-sdk/reply-history": {
|
||||
"types": "./dist/plugin-sdk/reply-history.d.ts",
|
||||
"default": "./dist/plugin-sdk/reply-history.js"
|
||||
@@ -342,6 +378,14 @@
|
||||
"types": "./dist/plugin-sdk/media-understanding.d.ts",
|
||||
"default": "./dist/plugin-sdk/media-understanding.js"
|
||||
},
|
||||
"./plugin-sdk/secret-input-runtime": {
|
||||
"types": "./dist/plugin-sdk/secret-input-runtime.d.ts",
|
||||
"default": "./dist/plugin-sdk/secret-input-runtime.js"
|
||||
},
|
||||
"./plugin-sdk/secret-input-schema": {
|
||||
"types": "./dist/plugin-sdk/secret-input-schema.d.ts",
|
||||
"default": "./dist/plugin-sdk/secret-input-schema.js"
|
||||
},
|
||||
"./plugin-sdk/request-url": {
|
||||
"types": "./dist/plugin-sdk/request-url.d.ts",
|
||||
"default": "./dist/plugin-sdk/request-url.js"
|
||||
@@ -362,6 +406,34 @@
|
||||
"types": "./dist/plugin-sdk/secret-input.d.ts",
|
||||
"default": "./dist/plugin-sdk/secret-input.js"
|
||||
},
|
||||
"./plugin-sdk/signal-core": {
|
||||
"types": "./dist/plugin-sdk/signal-core.d.ts",
|
||||
"default": "./dist/plugin-sdk/signal-core.js"
|
||||
},
|
||||
"./plugin-sdk/synology-chat": {
|
||||
"types": "./dist/plugin-sdk/synology-chat.d.ts",
|
||||
"default": "./dist/plugin-sdk/synology-chat.js"
|
||||
},
|
||||
"./plugin-sdk/talk-voice": {
|
||||
"types": "./dist/plugin-sdk/talk-voice.d.ts",
|
||||
"default": "./dist/plugin-sdk/talk-voice.js"
|
||||
},
|
||||
"./plugin-sdk/thread-ownership": {
|
||||
"types": "./dist/plugin-sdk/thread-ownership.d.ts",
|
||||
"default": "./dist/plugin-sdk/thread-ownership.js"
|
||||
},
|
||||
"./plugin-sdk/tlon": {
|
||||
"types": "./dist/plugin-sdk/tlon.d.ts",
|
||||
"default": "./dist/plugin-sdk/tlon.js"
|
||||
},
|
||||
"./plugin-sdk/twitch": {
|
||||
"types": "./dist/plugin-sdk/twitch.d.ts",
|
||||
"default": "./dist/plugin-sdk/twitch.js"
|
||||
},
|
||||
"./plugin-sdk/voice-call": {
|
||||
"types": "./dist/plugin-sdk/voice-call.d.ts",
|
||||
"default": "./dist/plugin-sdk/voice-call.js"
|
||||
},
|
||||
"./plugin-sdk/web-media": {
|
||||
"types": "./dist/plugin-sdk/web-media.d.ts",
|
||||
"default": "./dist/plugin-sdk/web-media.js"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"telegram-core",
|
||||
"discord",
|
||||
"discord-core",
|
||||
"feishu",
|
||||
"slack",
|
||||
"slack-core",
|
||||
"imessage",
|
||||
@@ -52,6 +53,9 @@
|
||||
"allowlist-resolution",
|
||||
"allowlist-config-edit",
|
||||
"boolean-param",
|
||||
"device-pair",
|
||||
"diagnostics-otel",
|
||||
"diffs",
|
||||
"channel-config-helpers",
|
||||
"channel-config-schema",
|
||||
"channel-lifecycle",
|
||||
@@ -62,6 +66,10 @@
|
||||
"directory-runtime",
|
||||
"json-store",
|
||||
"keyed-async-queue",
|
||||
"line",
|
||||
"llm-task",
|
||||
"memory-lancedb",
|
||||
"minimax-portal-auth",
|
||||
"provider-auth",
|
||||
"provider-auth-api-key",
|
||||
"provider-auth-login",
|
||||
@@ -73,13 +81,23 @@
|
||||
"provider-usage",
|
||||
"provider-web-search",
|
||||
"image-generation",
|
||||
"nostr",
|
||||
"reply-history",
|
||||
"media-understanding",
|
||||
"secret-input-runtime",
|
||||
"secret-input-schema",
|
||||
"request-url",
|
||||
"webhook-ingress",
|
||||
"webhook-path",
|
||||
"runtime-store",
|
||||
"secret-input",
|
||||
"signal-core",
|
||||
"synology-chat",
|
||||
"talk-voice",
|
||||
"thread-ownership",
|
||||
"tlon",
|
||||
"twitch",
|
||||
"voice-call",
|
||||
"web-media",
|
||||
"speech",
|
||||
"state-paths",
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { pathToFileURL } from "node:url";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { buildChannelConfigSchema } from "../src/channels/plugins/config-schema.js";
|
||||
|
||||
function isBuiltChannelConfigSchema(
|
||||
@@ -41,16 +43,177 @@ function resolveConfigSchemaExport(
|
||||
return null;
|
||||
}
|
||||
|
||||
const modulePath = process.argv[2]?.trim();
|
||||
if (!modulePath) {
|
||||
process.exit(2);
|
||||
function resolveRepoRoot(): string {
|
||||
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
}
|
||||
|
||||
const imported = (await import(pathToFileURL(modulePath).href)) as Record<string, unknown>;
|
||||
const resolved = resolveConfigSchemaExport(imported);
|
||||
if (!resolved) {
|
||||
process.exit(3);
|
||||
function resolvePackageRoot(modulePath: string): string {
|
||||
let cursor = path.dirname(path.resolve(modulePath));
|
||||
while (true) {
|
||||
if (fs.existsSync(path.join(cursor, "package.json"))) {
|
||||
return cursor;
|
||||
}
|
||||
const parent = path.dirname(cursor);
|
||||
if (parent === cursor) {
|
||||
throw new Error(`package root not found for ${modulePath}`);
|
||||
}
|
||||
cursor = parent;
|
||||
}
|
||||
}
|
||||
|
||||
process.stdout.write(JSON.stringify(resolved));
|
||||
process.exit(0);
|
||||
function shouldRetryViaIsolatedCopy(error: unknown): boolean {
|
||||
if (!error || typeof error !== "object") {
|
||||
return false;
|
||||
}
|
||||
const code = "code" in error ? error.code : undefined;
|
||||
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
||||
return code === "ERR_MODULE_NOT_FOUND" && message.includes(`${path.sep}node_modules${path.sep}`);
|
||||
}
|
||||
|
||||
const SOURCE_FILE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
||||
|
||||
function resolveImportCandidates(basePath: string): string[] {
|
||||
const extension = path.extname(basePath);
|
||||
const candidates = new Set<string>([basePath]);
|
||||
if (extension) {
|
||||
const stem = basePath.slice(0, -extension.length);
|
||||
for (const sourceExtension of SOURCE_FILE_EXTENSIONS) {
|
||||
candidates.add(`${stem}${sourceExtension}`);
|
||||
}
|
||||
} else {
|
||||
for (const sourceExtension of SOURCE_FILE_EXTENSIONS) {
|
||||
candidates.add(`${basePath}${sourceExtension}`);
|
||||
candidates.add(path.join(basePath, `index${sourceExtension}`));
|
||||
}
|
||||
}
|
||||
return Array.from(candidates);
|
||||
}
|
||||
|
||||
function resolveRelativeImportPath(fromFile: string, specifier: string): string | null {
|
||||
for (const candidate of resolveImportCandidates(
|
||||
path.resolve(path.dirname(fromFile), specifier),
|
||||
)) {
|
||||
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function collectRelativeImportGraph(entryPath: string): Set<string> {
|
||||
const discovered = new Set<string>();
|
||||
const queue = [path.resolve(entryPath)];
|
||||
const importPattern =
|
||||
/(?:import|export)\s+(?:[^"'`]*?\s+from\s+)?["'`]([^"'`]+)["'`]|import\(\s*["'`]([^"'`]+)["'`]\s*\)/g;
|
||||
|
||||
while (queue.length > 0) {
|
||||
const currentPath = queue.pop();
|
||||
if (!currentPath || discovered.has(currentPath)) {
|
||||
continue;
|
||||
}
|
||||
discovered.add(currentPath);
|
||||
|
||||
const source = fs.readFileSync(currentPath, "utf8");
|
||||
for (const match of source.matchAll(importPattern)) {
|
||||
const specifier = match[1] ?? match[2];
|
||||
if (!specifier?.startsWith(".")) {
|
||||
continue;
|
||||
}
|
||||
const resolved = resolveRelativeImportPath(currentPath, specifier);
|
||||
if (resolved) {
|
||||
queue.push(resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return discovered;
|
||||
}
|
||||
|
||||
function resolveCommonAncestor(paths: Iterable<string>): string {
|
||||
const resolvedPaths = Array.from(paths, (entry) => path.resolve(entry));
|
||||
const [first, ...rest] = resolvedPaths;
|
||||
if (!first) {
|
||||
throw new Error("cannot resolve common ancestor for empty path set");
|
||||
}
|
||||
let ancestor = first;
|
||||
for (const candidate of rest) {
|
||||
while (path.relative(ancestor, candidate).startsWith(`..${path.sep}`)) {
|
||||
const parent = path.dirname(ancestor);
|
||||
if (parent === ancestor) {
|
||||
return ancestor;
|
||||
}
|
||||
ancestor = parent;
|
||||
}
|
||||
}
|
||||
return ancestor;
|
||||
}
|
||||
|
||||
function copyModuleImportGraphWithoutNodeModules(params: {
|
||||
modulePath: string;
|
||||
repoRoot: string;
|
||||
}): {
|
||||
copiedModulePath: string;
|
||||
cleanup: () => void;
|
||||
} {
|
||||
const packageRoot = resolvePackageRoot(params.modulePath);
|
||||
const relativeFiles = collectRelativeImportGraph(params.modulePath);
|
||||
const copyRoot = resolveCommonAncestor([packageRoot, ...relativeFiles]);
|
||||
const relativeModulePath = path.relative(copyRoot, params.modulePath);
|
||||
const tempParent = path.join(params.repoRoot, ".openclaw-config-doc-cache");
|
||||
fs.mkdirSync(tempParent, { recursive: true });
|
||||
const isolatedRoot = fs.mkdtempSync(path.join(tempParent, `${path.basename(packageRoot)}-`));
|
||||
|
||||
for (const sourcePath of relativeFiles) {
|
||||
const relativePath = path.relative(copyRoot, sourcePath);
|
||||
const targetPath = path.join(isolatedRoot, relativePath);
|
||||
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
}
|
||||
return {
|
||||
copiedModulePath: path.join(isolatedRoot, relativeModulePath),
|
||||
cleanup: () => {
|
||||
fs.rmSync(isolatedRoot, { recursive: true, force: true });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function loadChannelConfigSurfaceModule(
|
||||
modulePath: string,
|
||||
options?: { repoRoot?: string },
|
||||
): Promise<{ schema: Record<string, unknown>; uiHints?: Record<string, unknown> } | null> {
|
||||
const repoRoot = options?.repoRoot ?? resolveRepoRoot();
|
||||
|
||||
try {
|
||||
const imported = (await import(pathToFileURL(modulePath).href)) as Record<string, unknown>;
|
||||
return resolveConfigSchemaExport(imported);
|
||||
} catch (error) {
|
||||
if (!shouldRetryViaIsolatedCopy(error)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const isolatedCopy = copyModuleImportGraphWithoutNodeModules({ modulePath, repoRoot });
|
||||
try {
|
||||
const imported = (await import(
|
||||
`${pathToFileURL(isolatedCopy.copiedModulePath).href}?isolated=${Date.now()}`
|
||||
)) as Record<string, unknown>;
|
||||
return resolveConfigSchemaExport(imported);
|
||||
} finally {
|
||||
isolatedCopy.cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
|
||||
const modulePath = process.argv[2]?.trim();
|
||||
if (!modulePath) {
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const resolved = await loadChannelConfigSurfaceModule(modulePath);
|
||||
if (!resolved) {
|
||||
process.exit(3);
|
||||
}
|
||||
|
||||
process.stdout.write(JSON.stringify(resolved));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
89
src/config/load-channel-config-surface.test.ts
Normal file
89
src/config/load-channel-config-surface.test.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { loadChannelConfigSurfaceModule } from "../../scripts/load-channel-config-surface.ts";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
function makeTempRoot(prefix: string): string {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
||||
tempDirs.push(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
for (const dir of tempDirs.splice(0, tempDirs.length)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
describe("loadChannelConfigSurfaceModule", () => {
|
||||
it("retries from an isolated package copy when extension-local node_modules is broken", async () => {
|
||||
const repoRoot = makeTempRoot("openclaw-config-surface-");
|
||||
const packageRoot = path.join(repoRoot, "extensions", "demo");
|
||||
const modulePath = path.join(packageRoot, "src", "config-schema.js");
|
||||
|
||||
fs.mkdirSync(path.join(packageRoot, "src"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(packageRoot, "package.json"),
|
||||
JSON.stringify({ name: "@openclaw/demo", type: "module" }, null, 2),
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
modulePath,
|
||||
[
|
||||
"import { z } from 'zod';",
|
||||
"export const DemoChannelConfigSchema = {",
|
||||
" schema: {",
|
||||
" type: 'object',",
|
||||
" properties: { ok: { type: z.object({}).shape ? 'string' : 'string' } },",
|
||||
" },",
|
||||
"};",
|
||||
"",
|
||||
].join("\n"),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
fs.mkdirSync(path.join(repoRoot, "node_modules", "zod"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(repoRoot, "node_modules", "zod", "package.json"),
|
||||
JSON.stringify({
|
||||
name: "zod",
|
||||
type: "module",
|
||||
exports: { ".": "./index.js" },
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(repoRoot, "node_modules", "zod", "index.js"),
|
||||
"export const z = { object: () => ({ shape: {} }) };\n",
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const poisonedStorePackage = path.join(
|
||||
repoRoot,
|
||||
"node_modules",
|
||||
".pnpm",
|
||||
"zod@0.0.0",
|
||||
"node_modules",
|
||||
"zod",
|
||||
);
|
||||
fs.mkdirSync(poisonedStorePackage, { recursive: true });
|
||||
fs.mkdirSync(path.join(packageRoot, "node_modules"), { recursive: true });
|
||||
fs.symlinkSync(
|
||||
"../../../node_modules/.pnpm/zod@0.0.0/node_modules/zod",
|
||||
path.join(packageRoot, "node_modules", "zod"),
|
||||
"dir",
|
||||
);
|
||||
|
||||
await expect(loadChannelConfigSurfaceModule(modulePath, { repoRoot })).resolves.toMatchObject({
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
ok: { type: "string" },
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,62 +1,3 @@
|
||||
import {
|
||||
KIMI_CODING_BASE_URL,
|
||||
KIMI_CODING_DEFAULT_MODEL_ID as KIMI_CODING_MODEL_ID,
|
||||
} from "../../extensions/kimi-coding/provider-catalog.js";
|
||||
import {
|
||||
DEFAULT_MINIMAX_BASE_URL,
|
||||
MINIMAX_API_BASE_URL,
|
||||
MINIMAX_API_COST,
|
||||
MINIMAX_CN_API_BASE_URL,
|
||||
MINIMAX_HOSTED_COST,
|
||||
MINIMAX_HOSTED_MODEL_ID,
|
||||
MINIMAX_HOSTED_MODEL_REF,
|
||||
MINIMAX_LM_STUDIO_COST,
|
||||
buildMinimaxApiModelDefinition,
|
||||
buildMinimaxModelDefinition,
|
||||
} from "../../extensions/minimax/model-definitions.js";
|
||||
import {
|
||||
MISTRAL_BASE_URL,
|
||||
MISTRAL_DEFAULT_COST,
|
||||
MISTRAL_DEFAULT_MODEL_ID,
|
||||
MISTRAL_DEFAULT_MODEL_REF,
|
||||
buildMistralModelDefinition,
|
||||
} from "../../extensions/mistral/model-definitions.js";
|
||||
import {
|
||||
MODELSTUDIO_CN_BASE_URL,
|
||||
MODELSTUDIO_DEFAULT_COST,
|
||||
MODELSTUDIO_DEFAULT_MODEL_ID,
|
||||
MODELSTUDIO_DEFAULT_MODEL_REF,
|
||||
MODELSTUDIO_GLOBAL_BASE_URL,
|
||||
buildModelStudioDefaultModelDefinition,
|
||||
buildModelStudioModelDefinition,
|
||||
} from "../../extensions/modelstudio/model-definitions.js";
|
||||
import { MOONSHOT_CN_BASE_URL } from "../../extensions/moonshot/onboard.js";
|
||||
import {
|
||||
MOONSHOT_BASE_URL,
|
||||
MOONSHOT_DEFAULT_MODEL_ID,
|
||||
buildMoonshotProvider,
|
||||
} from "../../extensions/moonshot/provider-catalog.js";
|
||||
import {
|
||||
QIANFAN_BASE_URL,
|
||||
QIANFAN_DEFAULT_MODEL_ID,
|
||||
} from "../../extensions/qianfan/provider-catalog.js";
|
||||
import {
|
||||
XAI_BASE_URL,
|
||||
XAI_DEFAULT_COST,
|
||||
XAI_DEFAULT_MODEL_ID,
|
||||
XAI_DEFAULT_MODEL_REF,
|
||||
buildXaiModelDefinition,
|
||||
} from "../../extensions/xai/model-definitions.js";
|
||||
import {
|
||||
ZAI_CN_BASE_URL,
|
||||
ZAI_CODING_CN_BASE_URL,
|
||||
ZAI_CODING_GLOBAL_BASE_URL,
|
||||
ZAI_DEFAULT_COST,
|
||||
ZAI_DEFAULT_MODEL_ID,
|
||||
ZAI_GLOBAL_BASE_URL,
|
||||
buildZaiModelDefinition,
|
||||
resolveZaiBaseUrl,
|
||||
} from "../../extensions/zai/model-definitions.js";
|
||||
import type { ModelDefinitionConfig } from "../config/types.models.js";
|
||||
import {
|
||||
KILOCODE_DEFAULT_CONTEXT_WINDOW,
|
||||
@@ -66,10 +7,258 @@ import {
|
||||
KILOCODE_DEFAULT_MODEL_NAME,
|
||||
} from "../providers/kilocode-shared.js";
|
||||
|
||||
const KIMI_CODING_BASE_URL = "https://api.kimi.com/coding/";
|
||||
const KIMI_CODING_MODEL_ID = "kimi-code";
|
||||
const KIMI_CODING_MODEL_REF = `kimi/${KIMI_CODING_MODEL_ID}`;
|
||||
|
||||
const DEFAULT_MINIMAX_BASE_URL = "https://api.minimax.io/v1";
|
||||
const MINIMAX_API_BASE_URL = "https://api.minimax.io/anthropic";
|
||||
const MINIMAX_CN_API_BASE_URL = "https://api.minimaxi.com/anthropic";
|
||||
const MINIMAX_HOSTED_MODEL_ID = "MiniMax-M2.7";
|
||||
const MINIMAX_HOSTED_MODEL_REF = `minimax/${MINIMAX_HOSTED_MODEL_ID}`;
|
||||
const DEFAULT_MINIMAX_CONTEXT_WINDOW = 200000;
|
||||
const DEFAULT_MINIMAX_MAX_TOKENS = 8192;
|
||||
const MINIMAX_API_COST = { input: 0.3, output: 1.2, cacheRead: 0.03, cacheWrite: 0.12 };
|
||||
const MINIMAX_HOSTED_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
||||
const MINIMAX_LM_STUDIO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
||||
const MINIMAX_MODEL_CATALOG = {
|
||||
"MiniMax-M2.7": { name: "MiniMax M2.7", reasoning: true },
|
||||
"MiniMax-M2.7-highspeed": { name: "MiniMax M2.7 Highspeed", reasoning: true },
|
||||
"MiniMax-M2.5": { name: "MiniMax M2.5", reasoning: true },
|
||||
"MiniMax-M2.5-highspeed": { name: "MiniMax M2.5 Highspeed", reasoning: true },
|
||||
} as const;
|
||||
|
||||
const MISTRAL_BASE_URL = "https://api.mistral.ai/v1";
|
||||
const MISTRAL_DEFAULT_MODEL_ID = "mistral-large-latest";
|
||||
const MISTRAL_DEFAULT_MODEL_REF = `mistral/${MISTRAL_DEFAULT_MODEL_ID}`;
|
||||
const MISTRAL_DEFAULT_CONTEXT_WINDOW = 262144;
|
||||
const MISTRAL_DEFAULT_MAX_TOKENS = 262144;
|
||||
const MISTRAL_DEFAULT_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
||||
|
||||
const MODELSTUDIO_CN_BASE_URL = "https://coding.dashscope.aliyuncs.com/v1";
|
||||
const MODELSTUDIO_GLOBAL_BASE_URL = "https://coding-intl.dashscope.aliyuncs.com/v1";
|
||||
const MODELSTUDIO_DEFAULT_MODEL_ID = "qwen3.5-plus";
|
||||
const MODELSTUDIO_DEFAULT_MODEL_REF = `modelstudio/${MODELSTUDIO_DEFAULT_MODEL_ID}`;
|
||||
const MODELSTUDIO_DEFAULT_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
||||
const MODELSTUDIO_MODEL_CATALOG = {
|
||||
"qwen3.5-plus": {
|
||||
name: "qwen3.5-plus",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 1000000,
|
||||
maxTokens: 65536,
|
||||
},
|
||||
"qwen3-max-2026-01-23": {
|
||||
name: "qwen3-max-2026-01-23",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
contextWindow: 262144,
|
||||
maxTokens: 65536,
|
||||
},
|
||||
"qwen3-coder-next": {
|
||||
name: "qwen3-coder-next",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
contextWindow: 262144,
|
||||
maxTokens: 65536,
|
||||
},
|
||||
"qwen3-coder-plus": {
|
||||
name: "qwen3-coder-plus",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
contextWindow: 1000000,
|
||||
maxTokens: 65536,
|
||||
},
|
||||
"MiniMax-M2.5": {
|
||||
name: "MiniMax-M2.5",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
contextWindow: 1000000,
|
||||
maxTokens: 65536,
|
||||
},
|
||||
"glm-5": {
|
||||
name: "glm-5",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
contextWindow: 202752,
|
||||
maxTokens: 16384,
|
||||
},
|
||||
"glm-4.7": {
|
||||
name: "glm-4.7",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
contextWindow: 202752,
|
||||
maxTokens: 16384,
|
||||
},
|
||||
"kimi-k2.5": {
|
||||
name: "kimi-k2.5",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
contextWindow: 262144,
|
||||
maxTokens: 32768,
|
||||
},
|
||||
} as const;
|
||||
|
||||
const MOONSHOT_BASE_URL = "https://api.moonshot.ai/v1";
|
||||
const MOONSHOT_CN_BASE_URL = "https://api.moonshot.cn/v1";
|
||||
const MOONSHOT_DEFAULT_MODEL_ID = "kimi-k2.5";
|
||||
const MOONSHOT_DEFAULT_MODEL_REF = `moonshot/${MOONSHOT_DEFAULT_MODEL_ID}`;
|
||||
const MOONSHOT_DEFAULT_CONTEXT_WINDOW = 256000;
|
||||
const MOONSHOT_DEFAULT_MAX_TOKENS = 8192;
|
||||
const MOONSHOT_DEFAULT_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
||||
|
||||
const QIANFAN_BASE_URL = "https://qianfan.baidubce.com/v2";
|
||||
const QIANFAN_DEFAULT_MODEL_ID = "deepseek-v3.2";
|
||||
const QIANFAN_DEFAULT_MODEL_REF = `qianfan/${QIANFAN_DEFAULT_MODEL_ID}`;
|
||||
|
||||
const XAI_BASE_URL = "https://api.x.ai/v1";
|
||||
const XAI_DEFAULT_MODEL_ID = "grok-4";
|
||||
const XAI_DEFAULT_MODEL_REF = `xai/${XAI_DEFAULT_MODEL_ID}`;
|
||||
const XAI_DEFAULT_CONTEXT_WINDOW = 131072;
|
||||
const XAI_DEFAULT_MAX_TOKENS = 8192;
|
||||
const XAI_DEFAULT_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
||||
|
||||
const ZAI_CODING_GLOBAL_BASE_URL = "https://api.z.ai/api/coding/paas/v4";
|
||||
const ZAI_CODING_CN_BASE_URL = "https://open.bigmodel.cn/api/coding/paas/v4";
|
||||
const ZAI_GLOBAL_BASE_URL = "https://api.z.ai/api/paas/v4";
|
||||
const ZAI_CN_BASE_URL = "https://open.bigmodel.cn/api/paas/v4";
|
||||
const ZAI_DEFAULT_MODEL_ID = "glm-5";
|
||||
const ZAI_DEFAULT_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
||||
const ZAI_MODEL_CATALOG = {
|
||||
"glm-5": { name: "GLM-5", reasoning: true },
|
||||
"glm-5-turbo": { name: "GLM-5 Turbo", reasoning: true },
|
||||
"glm-4.7": { name: "GLM-4.7", reasoning: true },
|
||||
"glm-4.7-flash": { name: "GLM-4.7 Flash", reasoning: true },
|
||||
"glm-4.7-flashx": { name: "GLM-4.7 FlashX", reasoning: true },
|
||||
} as const;
|
||||
|
||||
function buildMinimaxModelDefinition(params: {
|
||||
id: string;
|
||||
name?: string;
|
||||
reasoning?: boolean;
|
||||
cost: ModelDefinitionConfig["cost"];
|
||||
contextWindow: number;
|
||||
maxTokens: number;
|
||||
}): ModelDefinitionConfig {
|
||||
const catalog = MINIMAX_MODEL_CATALOG[params.id as keyof typeof MINIMAX_MODEL_CATALOG];
|
||||
return {
|
||||
id: params.id,
|
||||
name: params.name ?? catalog?.name ?? `MiniMax ${params.id}`,
|
||||
reasoning: params.reasoning ?? catalog?.reasoning ?? false,
|
||||
input: ["text"],
|
||||
cost: params.cost,
|
||||
contextWindow: params.contextWindow,
|
||||
maxTokens: params.maxTokens,
|
||||
};
|
||||
}
|
||||
|
||||
function buildMinimaxApiModelDefinition(modelId: string): ModelDefinitionConfig {
|
||||
return buildMinimaxModelDefinition({
|
||||
id: modelId,
|
||||
cost: MINIMAX_API_COST,
|
||||
contextWindow: DEFAULT_MINIMAX_CONTEXT_WINDOW,
|
||||
maxTokens: DEFAULT_MINIMAX_MAX_TOKENS,
|
||||
});
|
||||
}
|
||||
|
||||
function buildMistralModelDefinition(): ModelDefinitionConfig {
|
||||
return {
|
||||
id: MISTRAL_DEFAULT_MODEL_ID,
|
||||
name: "Mistral Large",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: MISTRAL_DEFAULT_COST,
|
||||
contextWindow: MISTRAL_DEFAULT_CONTEXT_WINDOW,
|
||||
maxTokens: MISTRAL_DEFAULT_MAX_TOKENS,
|
||||
};
|
||||
}
|
||||
|
||||
function buildModelStudioModelDefinition(params: {
|
||||
id: string;
|
||||
name?: string;
|
||||
reasoning?: boolean;
|
||||
input?: string[];
|
||||
cost?: ModelDefinitionConfig["cost"];
|
||||
contextWindow?: number;
|
||||
maxTokens?: number;
|
||||
}): ModelDefinitionConfig {
|
||||
const catalog = MODELSTUDIO_MODEL_CATALOG[params.id as keyof typeof MODELSTUDIO_MODEL_CATALOG];
|
||||
return {
|
||||
id: params.id,
|
||||
name: params.name ?? catalog?.name ?? params.id,
|
||||
reasoning: params.reasoning ?? catalog?.reasoning ?? false,
|
||||
input:
|
||||
(params.input as ("text" | "image")[]) ??
|
||||
([...(catalog?.input ?? ["text"])] as ("text" | "image")[]),
|
||||
cost: params.cost ?? MODELSTUDIO_DEFAULT_COST,
|
||||
contextWindow: params.contextWindow ?? catalog?.contextWindow ?? 262144,
|
||||
maxTokens: params.maxTokens ?? catalog?.maxTokens ?? 65536,
|
||||
};
|
||||
}
|
||||
|
||||
function buildModelStudioDefaultModelDefinition(): ModelDefinitionConfig {
|
||||
return buildModelStudioModelDefinition({ id: MODELSTUDIO_DEFAULT_MODEL_ID });
|
||||
}
|
||||
|
||||
function createMoonshotModelDefinition(): ModelDefinitionConfig {
|
||||
return {
|
||||
id: MOONSHOT_DEFAULT_MODEL_ID,
|
||||
name: "Kimi K2.5",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: MOONSHOT_DEFAULT_COST,
|
||||
contextWindow: MOONSHOT_DEFAULT_CONTEXT_WINDOW,
|
||||
maxTokens: MOONSHOT_DEFAULT_MAX_TOKENS,
|
||||
};
|
||||
}
|
||||
|
||||
function buildXaiModelDefinition(): ModelDefinitionConfig {
|
||||
return {
|
||||
id: XAI_DEFAULT_MODEL_ID,
|
||||
name: "Grok 4",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: XAI_DEFAULT_COST,
|
||||
contextWindow: XAI_DEFAULT_CONTEXT_WINDOW,
|
||||
maxTokens: XAI_DEFAULT_MAX_TOKENS,
|
||||
};
|
||||
}
|
||||
|
||||
function resolveZaiBaseUrl(endpoint?: string): string {
|
||||
switch (endpoint) {
|
||||
case "coding-cn":
|
||||
return ZAI_CODING_CN_BASE_URL;
|
||||
case "global":
|
||||
return ZAI_GLOBAL_BASE_URL;
|
||||
case "cn":
|
||||
return ZAI_CN_BASE_URL;
|
||||
case "coding-global":
|
||||
return ZAI_CODING_GLOBAL_BASE_URL;
|
||||
default:
|
||||
return ZAI_GLOBAL_BASE_URL;
|
||||
}
|
||||
}
|
||||
|
||||
function buildZaiModelDefinition(params: {
|
||||
id: string;
|
||||
name?: string;
|
||||
reasoning?: boolean;
|
||||
cost?: ModelDefinitionConfig["cost"];
|
||||
contextWindow?: number;
|
||||
maxTokens?: number;
|
||||
}): ModelDefinitionConfig {
|
||||
const catalog = ZAI_MODEL_CATALOG[params.id as keyof typeof ZAI_MODEL_CATALOG];
|
||||
return {
|
||||
id: params.id,
|
||||
name: params.name ?? catalog?.name ?? `GLM ${params.id}`,
|
||||
reasoning: params.reasoning ?? catalog?.reasoning ?? true,
|
||||
input: ["text"],
|
||||
cost: params.cost ?? ZAI_DEFAULT_COST,
|
||||
contextWindow: params.contextWindow ?? 204800,
|
||||
maxTokens: params.maxTokens ?? 131072,
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
DEFAULT_MINIMAX_BASE_URL,
|
||||
MINIMAX_API_BASE_URL,
|
||||
@@ -123,7 +312,7 @@ export {
|
||||
};
|
||||
|
||||
export function buildMoonshotModelDefinition(): ModelDefinitionConfig {
|
||||
return buildMoonshotProvider().models[0];
|
||||
return createMoonshotModelDefinition();
|
||||
}
|
||||
|
||||
export function buildKilocodeModelDefinition(): ModelDefinitionConfig {
|
||||
|
||||
Reference in New Issue
Block a user