negotium 0.19.2 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-helpers.js +1147 -213
- package/dist/agent-helpers.js.map +28 -20
- package/dist/background-bash.js +2 -2
- package/dist/background-bash.js.map +3 -3
- package/dist/browser-runtime.js +2 -2
- package/dist/browser-runtime.js.map +3 -3
- package/dist/{chunk-aqqmzmft.js → chunk-143j4nxd.js} +1 -1
- package/dist/{chunk-55dd0xw7.js → chunk-myhmb8tn.js} +3 -3
- package/dist/{chunk-55dd0xw7.js.map → chunk-myhmb8tn.js.map} +3 -3
- package/dist/{chunk-cv7vdsrn.js → chunk-t7vs5k9t.js} +287 -10
- package/dist/{chunk-cv7vdsrn.js.map → chunk-t7vs5k9t.js.map} +11 -8
- package/dist/{chunk-exqz8bez.js → chunk-wpp1x0tx.js} +3 -3
- package/dist/{chunk-exqz8bez.js.map → chunk-wpp1x0tx.js.map} +2 -2
- package/dist/{chunk-kkftbxh2.js → chunk-zkyp090x.js} +1 -1
- package/dist/hosted-agent.js +290 -12
- package/dist/hosted-agent.js.map +10 -7
- package/dist/main.js +5019 -3134
- package/dist/main.js.map +51 -40
- package/dist/mcp-factories.js +1167 -163
- package/dist/mcp-factories.js.map +28 -20
- package/dist/media.js +2 -2
- package/dist/media.js.map +3 -3
- package/dist/prompts.js +2 -2
- package/dist/prompts.js.map +3 -3
- package/dist/query-runtime.js +2 -2
- package/dist/query-runtime.js.map +5 -5
- package/dist/registry.js +3 -3
- package/dist/rollout.js +2 -2
- package/dist/runtime/src/agents/explicit-agent-switch.ts +101 -0
- package/dist/runtime/src/agents/mcp-tools/spawn-subagent.ts +126 -43
- package/dist/runtime/src/agents/public-helpers.ts +5 -0
- package/dist/runtime/src/agents/self-config-core.ts +28 -58
- package/dist/runtime/src/application/submit-runtime-gateway-turn.ts +34 -8
- package/dist/runtime/src/index.ts +75 -0
- package/dist/runtime/src/mcp/peer-bridge.ts +6 -1
- package/dist/runtime/src/mcp/runtime-spec.ts +145 -10
- package/dist/runtime/src/mcp/session-comm/actor-policy.ts +87 -0
- package/dist/runtime/src/mcp/session-comm/context.ts +42 -1
- package/dist/runtime/src/mcp/session-comm/default-host.ts +178 -2
- package/dist/runtime/src/mcp/session-comm/hub-remote-session.ts +553 -0
- package/dist/runtime/src/mcp/session-comm/limits.ts +8 -0
- package/dist/runtime/src/mcp/session-comm/peer-forward.ts +78 -3
- package/dist/runtime/src/mcp/session-comm/server.ts +167 -4
- package/dist/runtime/src/mcp/session-comm/topic-catalog.ts +7 -0
- package/dist/runtime/src/mcp/session-comm/topics.ts +32 -10
- package/dist/runtime/src/mcp-runtime-host.ts +2 -1
- package/dist/runtime/src/node-host.ts +26 -0
- package/dist/runtime/src/platform/config.ts +1 -1
- package/dist/runtime/src/platform/mcp-config.ts +56 -2
- package/dist/runtime/src/query/active-rooms.ts +6 -0
- package/dist/runtime/src/runtime/actor-topic-reach.ts +85 -0
- package/dist/runtime/src/runtime/actor-topic-scope.ts +175 -0
- package/dist/runtime/src/runtime/ask-callbacks.ts +73 -20
- package/dist/runtime/src/runtime/bashrs-completions.ts +19 -1
- package/dist/runtime/src/runtime/gateway-capabilities.ts +22 -0
- package/dist/runtime/src/runtime/remote-session-grant.ts +221 -0
- package/dist/runtime/src/runtime/remote-session-inbox.ts +476 -0
- package/dist/runtime/src/runtime/remote-session-reply-outbox.ts +156 -0
- package/dist/runtime/src/runtime/turn-runner.ts +157 -33
- package/dist/runtime/src/runtime-gateway.ts +20 -0
- package/dist/runtime/src/storage/api-topics.ts +22 -3
- package/dist/runtime/src/storage/remote-session.ts +526 -0
- package/dist/runtime/src/storage/runtime-turn-requests.ts +75 -2
- package/dist/runtime/src/topics/derive.ts +3 -0
- package/dist/runtime/src/types/api.ts +6 -0
- package/dist/runtime/src/types.ts +42 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-gateway.js.map +2 -2
- package/dist/runtime-helpers.js +13 -3
- package/dist/runtime-helpers.js.map +5 -5
- package/dist/storage.js +16 -4
- package/dist/storage.js.map +4 -4
- package/dist/types/packages/core/src/agents/explicit-agent-switch.d.ts +26 -0
- package/dist/types/packages/core/src/agents/mcp-tools/spawn-subagent.d.ts +12 -2
- package/dist/types/packages/core/src/agents/public-helpers.d.ts +1 -0
- package/dist/types/packages/core/src/agents/self-config-core.d.ts +15 -1
- package/dist/types/packages/core/src/mcp/peer-bridge.d.ts +6 -1
- package/dist/types/packages/core/src/mcp/runtime-spec.d.ts +69 -2
- package/dist/types/packages/core/src/mcp/session-comm/context.d.ts +17 -1
- package/dist/types/packages/core/src/mcp/session-comm/hub-remote-session.d.ts +149 -0
- package/dist/types/packages/core/src/mcp/session-comm/limits.d.ts +8 -0
- package/dist/types/packages/core/src/mcp/session-comm/peer-forward.d.ts +23 -2
- package/dist/types/packages/core/src/mcp/session-comm/topic-catalog.d.ts +6 -0
- package/dist/types/packages/core/src/platform/config.d.ts +1 -1
- package/dist/types/packages/core/src/platform/mcp-config.d.ts +10 -1
- package/dist/types/packages/core/src/query/active-rooms.d.ts +6 -0
- package/dist/types/packages/core/src/runtime/actor-topic-reach.d.ts +49 -0
- package/dist/types/packages/core/src/runtime/actor-topic-scope.d.ts +91 -0
- package/dist/types/packages/core/src/runtime/ask-callbacks.d.ts +8 -2
- package/dist/types/packages/core/src/runtime/remote-session-grant.d.ts +91 -0
- package/dist/types/packages/core/src/runtime/remote-session-inbox.d.ts +83 -0
- package/dist/types/packages/core/src/runtime/remote-session-reply-outbox.d.ts +37 -0
- package/dist/types/packages/core/src/runtime/turn-runner.d.ts +22 -3
- package/dist/types/packages/core/src/runtime-gateway.d.ts +20 -0
- package/dist/types/packages/core/src/storage/api-topics.d.ts +3 -0
- package/dist/types/packages/core/src/storage/remote-session.d.ts +135 -0
- package/dist/types/packages/core/src/storage/runtime-turn-requests.d.ts +12 -1
- package/dist/types/packages/core/src/topics/derive.d.ts +2 -0
- package/dist/types/packages/core/src/types/api.d.ts +6 -0
- package/dist/types/packages/core/src/types.d.ts +40 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +2 -2
- package/dist/vault.js.map +3 -3
- package/install-browser-rs.mjs +4 -4
- package/package.json +1 -1
- /package/dist/{chunk-aqqmzmft.js.map → chunk-143j4nxd.js.map} +0 -0
- /package/dist/{chunk-kkftbxh2.js.map → chunk-zkyp090x.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
hostedCodexHomePath,
|
|
4
4
|
latestCodexRolloutPath
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-t7vs5k9t.js";
|
|
6
6
|
|
|
7
7
|
// ../../packages/core/src/agents/codex-app-server.ts
|
|
8
8
|
import { spawn } from "child_process";
|
|
@@ -23,7 +23,7 @@ import { createRequire } from "module";
|
|
|
23
23
|
import { dirname, join } from "path";
|
|
24
24
|
|
|
25
25
|
// ../../packages/core/src/version.ts
|
|
26
|
-
var NEGOTIUM_VERSION = "0.
|
|
26
|
+
var NEGOTIUM_VERSION = "0.20.1";
|
|
27
27
|
|
|
28
28
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
29
29
|
var moduleRequire = createRequire(import.meta.url);
|
|
@@ -158,4 +158,4 @@ export {
|
|
|
158
158
|
createCodexAppServerForker
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
-
//# debugId=
|
|
161
|
+
//# debugId=C595D5173F5CFF9664756E2164756E21
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { type ChildProcessWithoutNullStreams, spawn } from \"node:child_process\";\nimport { codexCliScriptPath } from \"#agents/codex-native-multi-agent\";\nimport { hostedCodexHomePath } from \"#agents/execution-host\";\nimport { latestCodexRolloutPath } from \"#agents/rollout/codex\";\nimport { NEGOTIUM_VERSION } from \"#version\";\n\ninterface CodexAppServerForkResult {\n forkId: string;\n rolloutPath: string;\n}\n\ninterface CodexAppServerForkHost {\n spawnServer(): ChildProcessWithoutNullStreams;\n findRolloutPath(threadId: string): string | undefined;\n timeoutMs: number;\n}\n\ntype JsonRpcResponse = {\n id?: number;\n result?: { thread?: { id?: unknown } };\n error?: { message?: unknown };\n};\n\nexport function createCodexAppServerForker(host: CodexAppServerForkHost) {\n return async (parentThreadId: string): Promise<CodexAppServerForkResult> => {\n const child = host.spawnServer();\n\n return await new Promise<CodexAppServerForkResult>((resolve, reject) => {\n let settled = false;\n let stdoutBuffer = \"\";\n let stderr = \"\";\n const timer = setTimeout(\n () => finish(new Error(\"Codex thread fork timed out\")),\n host.timeoutMs,\n );\n\n const finish = (error?: Error, result?: CodexAppServerForkResult) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n try {\n child.stdin.end();\n child.kill();\n } catch {\n // The app server may already have exited after stdin closed.\n }\n if (error) reject(error);\n else if (result) resolve(result);\n else reject(new Error(\"Codex thread fork returned no result\"));\n };\n\n const send = (message: Record<string, unknown>) => {\n child.stdin.write(`${JSON.stringify(message)}\\n`);\n };\n\n child.stderr.on(\"data\", (chunk) => {\n if (stderr.length < 8_192) stderr += String(chunk);\n });\n child.on(\"error\", (error) => finish(error));\n child.on(\"exit\", (code, signal) => {\n if (settled) return;\n const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`;\n finish(\n new Error(\n `Codex app server exited with ${detail}${stderr.trim() ? `: ${stderr.trim()}` : \"\"}`,\n ),\n );\n });\n child.stdout.on(\"data\", (chunk) => {\n stdoutBuffer += String(chunk);\n for (;;) {\n const newline = stdoutBuffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = stdoutBuffer.slice(0, newline);\n stdoutBuffer = stdoutBuffer.slice(newline + 1);\n let message: JsonRpcResponse;\n try {\n message = JSON.parse(line) as JsonRpcResponse;\n } catch {\n continue;\n }\n\n if (message.id === 1) {\n if (message.error) {\n finish(new Error(String(message.error.message || \"Codex initialization failed\")));\n return;\n }\n send({ method: \"initialized\" });\n send({ id: 2, method: \"thread/fork\", params: { threadId: parentThreadId } });\n continue;\n }\n if (message.id !== 2) continue;\n if (message.error) {\n finish(new Error(String(message.error.message || \"Codex thread fork failed\")));\n return;\n }\n const forkId = message.result?.thread?.id;\n if (typeof forkId !== \"string\" || !forkId) {\n finish(new Error(\"Codex thread fork returned no thread id\"));\n return;\n }\n const rolloutPath = host.findRolloutPath(forkId);\n if (!rolloutPath) {\n finish(new Error(`Codex thread fork rollout was not found for ${forkId}`));\n return;\n }\n finish(undefined, { forkId, rolloutPath });\n return;\n }\n });\n\n send({\n id: 1,\n method: \"initialize\",\n params: {\n clientInfo: { name: \"negotium\", version: NEGOTIUM_VERSION },\n },\n });\n });\n };\n}\n\nconst forkCodexThread = createCodexAppServerForker({\n spawnServer() {\n return spawn(process.execPath, [codexCliScriptPath(), \"app-server\", \"--stdio\"], {\n env: { ...process.env, CODEX_HOME: hostedCodexHomePath() },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n // Background stdio server — no console window on Windows. Ignored on POSIX.\n windowsHide: true,\n });\n },\n findRolloutPath: latestCodexRolloutPath,\n timeoutMs: 15_000,\n});\n\nexport async function forkCodexSession(parentThreadId: string): Promise<CodexAppServerForkResult> {\n return await forkCodexThread(parentThreadId);\n}\n",
|
|
6
6
|
"import { type ChildProcess, spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n mkdtempSync,\n readFileSync,\n renameSync,\n rmSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { NEGOTIUM_VERSION } from \"#version\";\n\ntype CodexModel = Record<string, unknown>;\ntype CodexModelCache = {\n client_version?: unknown;\n models?: unknown;\n};\n\nconst moduleRequire = createRequire(import.meta.url);\nconst codexSdkPackagePath = moduleRequire.resolve(\"@openai/codex-sdk/package.json\");\nconst codexSdkRequire = createRequire(codexSdkPackagePath);\nconst bundledCodexPackagePath = codexSdkRequire.resolve(\"@openai/codex/package.json\");\n\nfunction readPackageVersion(packageJsonPath: string): string {\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { version?: unknown };\n if (typeof parsed.version !== \"string\" || !parsed.version.trim()) {\n throw new Error(`Codex package has no valid version: ${packageJsonPath}`);\n }\n return parsed.version;\n}\n\nexport const BUNDLED_CODEX_VERSION = readPackageVersion(bundledCodexPackagePath);\nconst SAFE_BUNDLED_CODEX_VERSION = BUNDLED_CODEX_VERSION.replace(/[^a-zA-Z0-9._-]/g, \"_\");\nconst NEGOTIUM_MODEL_CACHE = `negotium-models-cache-${SAFE_BUNDLED_CODEX_VERSION}.json`;\nconst NEGOTIUM_MODEL_CATALOG = `negotium-model-catalog-${SAFE_BUNDLED_CODEX_VERSION}.json`;\n\nexport function codexCliScriptPath(): string {\n return join(dirname(bundledCodexPackagePath), \"bin\", \"codex.js\");\n}\n\nfunction parseCodexModelCache(contents: string, sourcePath: string): CodexModelCache {\n let parsed: CodexModelCache;\n try {\n parsed = JSON.parse(contents) as CodexModelCache;\n } catch (error) {\n throw new Error(`Codex model cache is invalid JSON: ${sourcePath}`, { cause: error });\n }\n if (!Array.isArray(parsed.models) || parsed.models.length === 0) {\n throw new Error(`Codex model cache has no models: ${sourcePath}`);\n }\n return parsed;\n}\n\nfunction readCodexModelCache(cachePath: string): {\n contents: string;\n parsed: CodexModelCache;\n} {\n const contents = readFileSync(cachePath, \"utf8\");\n return { contents, parsed: parseCodexModelCache(contents, cachePath) };\n}\n\nfunction readCompatibleCodexModelCache(cachePath: string): {\n contents: string;\n parsed: CodexModelCache;\n} {\n const cache = readCodexModelCache(cachePath);\n if (cache.parsed.client_version !== BUNDLED_CODEX_VERSION) {\n const found =\n typeof cache.parsed.client_version === \"string\"\n ? cache.parsed.client_version\n : \"missing or invalid\";\n throw new Error(\n `Codex model cache version ${found} does not match Negotium's bundled Codex ${BUNDLED_CODEX_VERSION}: ${cachePath}`,\n );\n }\n return cache;\n}\n\nfunction writePrivateFileAtomic(path: string, contents: string): void {\n if (existsSync(path) && readFileSync(path, \"utf8\") === contents) return;\n\n const tempPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n writeFileSync(tempPath, contents, { encoding: \"utf8\", mode: 0o600 });\n renameSync(tempPath, path);\n chmodSync(path, 0o600);\n } finally {\n try {\n unlinkSync(tempPath);\n } catch {\n // renameSync normally consumed the temporary file.\n }\n }\n}\n\nexport function bundledCodexModelCachePath(authFilePath: string): string {\n return join(dirname(authFilePath), NEGOTIUM_MODEL_CACHE);\n}\n\nasync function bootstrapCodexModelCache(codexHome: string, cachePath: string): Promise<void> {\n const child = spawn(process.execPath, [codexCliScriptPath(), \"app-server\", \"--stdio\"], {\n env: { ...process.env, CODEX_HOME: codexHome },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n // Background stdio server — no console window on Windows. Ignored on POSIX.\n windowsHide: true,\n });\n\n const refreshed = new Promise<void>((resolve, reject) => {\n let settled = false;\n let stdoutBuffer = \"\";\n let stderr = \"\";\n const timer = setTimeout(\n () => finish(new Error(\"timed out while refreshing the Codex model catalog\")),\n 15_000,\n );\n\n const finish = (error?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n try {\n child.stdin.end();\n child.kill();\n } catch {\n // The app server may already have exited after stdin closed.\n }\n if (error) reject(error);\n else if (!existsSync(cachePath)) reject(new Error(\"Codex did not create its model cache\"));\n else resolve();\n };\n\n const send = (message: Record<string, unknown>) => {\n child.stdin.write(`${JSON.stringify(message)}\\n`);\n };\n\n child.stderr.on(\"data\", (chunk) => {\n if (stderr.length < 4_096) stderr += String(chunk);\n });\n child.on(\"error\", (error) => finish(error));\n child.on(\"exit\", (code, signal) => {\n if (!settled) {\n finish(\n new Error(\n `Codex model catalog refresh exited with ${signal ? `signal ${signal}` : `code ${code ?? 1}`}${stderr.trim() ? `: ${stderr.trim()}` : \"\"}`,\n ),\n );\n }\n });\n child.stdout.on(\"data\", (chunk) => {\n stdoutBuffer += String(chunk);\n for (;;) {\n const newline = stdoutBuffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = stdoutBuffer.slice(0, newline);\n stdoutBuffer = stdoutBuffer.slice(newline + 1);\n let message: { id?: number; error?: { message?: string } };\n try {\n message = JSON.parse(line) as typeof message;\n } catch {\n continue;\n }\n if (message.id === 1) {\n if (message.error) {\n finish(new Error(message.error.message || \"Codex initialization failed\"));\n return;\n }\n send({ method: \"initialized\" });\n send({ id: 2, method: \"model/list\", params: { includeHidden: true } });\n } else if (message.id === 2) {\n if (message.error) {\n finish(new Error(message.error.message || \"Codex model listing failed\"));\n } else {\n finish();\n }\n return;\n }\n }\n });\n\n send({\n id: 1,\n method: \"initialize\",\n params: {\n clientInfo: { name: \"negotium\", version: NEGOTIUM_VERSION },\n capabilities: { experimentalApi: true },\n },\n });\n });\n\n try {\n await refreshed;\n } finally {\n // `child.kill()` only signals. The caller deletes CODEX_HOME right after we\n // return, and Windows cannot delete a directory the child still holds open\n // (EBUSY), so wait for the process to actually exit first.\n await waitForChildExit(child, CODEX_BOOTSTRAP_EXIT_WAIT_MS);\n }\n}\n\nconst CODEX_BOOTSTRAP_EXIT_WAIT_MS = 3_000;\n\nfunction waitForChildExit(child: ChildProcess, timeoutMs: number): Promise<void> {\n if (child.exitCode !== null || child.signalCode !== null) return Promise.resolve();\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, timeoutMs);\n timer.unref?.();\n child.once(\"exit\", () => {\n clearTimeout(timer);\n resolve();\n });\n });\n}\n\n/**\n * Remove the temporary CODEX_HOME. On Windows a just-exited child (or an\n * antivirus scan of the files it wrote) can keep the directory busy for a\n * moment, so retry, and never let cleanup of a throwaway directory fail a turn\n * whose result was already read. POSIX keeps the original behaviour: unlinking\n * open files works there, and a genuine failure still surfaces.\n */\nfunction removeIsolatedCodexHome(dir: string): void {\n if (process.platform !== \"win32\") {\n rmSync(dir, { recursive: true, force: true });\n return;\n }\n try {\n rmSync(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });\n } catch {\n // Best effort: the OS temp cleaner will reclaim it.\n }\n}\n\nasync function bootstrapIsolatedCodexModelCache(\n authFilePath: string,\n bootstrap: (codexHome: string, cachePath: string) => Promise<void>,\n): Promise<string> {\n const sourceHome = dirname(authFilePath);\n const isolatedHome = mkdtempSync(join(tmpdir(), \"negotium-codex-models-\"));\n const isolatedCachePath = join(isolatedHome, \"models_cache.json\");\n\n try {\n const isolatedAuthPath = join(isolatedHome, \"auth.json\");\n copyFileSync(authFilePath, isolatedAuthPath);\n chmodSync(isolatedAuthPath, 0o600);\n\n // Preserve custom provider configuration while keeping the bundled CLI's\n // cache write completely outside the user's shared CODEX_HOME.\n const sourceConfigPath = join(sourceHome, \"config.toml\");\n if (existsSync(sourceConfigPath)) {\n const isolatedConfigPath = join(isolatedHome, \"config.toml\");\n copyFileSync(sourceConfigPath, isolatedConfigPath);\n chmodSync(isolatedConfigPath, 0o600);\n }\n\n await bootstrap(isolatedHome, isolatedCachePath);\n return readCompatibleCodexModelCache(isolatedCachePath).contents;\n } finally {\n removeIsolatedCodexHome(isolatedHome);\n }\n}\n\nexport async function ensureCodexModelCache(\n authFilePath: string,\n bootstrap: (codexHome: string, cachePath: string) => Promise<void> = bootstrapCodexModelCache,\n): Promise<string> {\n const codexHome = dirname(authFilePath);\n const configuredCachePath = process.env.NEGOTIUM_CODEX_MODELS_CACHE_FILE;\n if (configuredCachePath) {\n if (!existsSync(configuredCachePath)) {\n throw new Error(`Configured Codex model cache does not exist: ${configuredCachePath}`);\n }\n readCompatibleCodexModelCache(configuredCachePath);\n return configuredCachePath;\n }\n\n // The global Codex CLI owns models_cache.json and may update it to a schema\n // newer than the SDK bundled by Negotium. Snapshot a cache generated for our\n // exact bundled version so later global CLI updates cannot break turns.\n const bundledCachePath = bundledCodexModelCachePath(authFilePath);\n const sharedCachePath = join(codexHome, \"models_cache.json\");\n if (existsSync(sharedCachePath)) {\n try {\n const shared = readCompatibleCodexModelCache(sharedCachePath);\n // Keep model metadata fresh while the global CLI remains compatible.\n writePrivateFileAtomic(bundledCachePath, shared.contents);\n return bundledCachePath;\n } catch {\n // A compatible private snapshot is safer than failing because another\n // process briefly exposed an incomplete shared-cache write.\n }\n }\n\n if (existsSync(bundledCachePath)) {\n try {\n readCompatibleCodexModelCache(bundledCachePath);\n return bundledCachePath;\n } catch {\n // Re-bootstrap below instead of passing a corrupt or version-mismatched\n // private snapshot into this SDK version.\n }\n }\n\n const refreshedContents = await bootstrapIsolatedCodexModelCache(authFilePath, bootstrap);\n writePrivateFileAtomic(bundledCachePath, refreshedContents);\n return bundledCachePath;\n}\n\n/**\n * Codex can resolve model metadata before `features.multi_agent=false`, so a\n * model-advertised v1/v2 value may still register native collaboration tools.\n * Feed Codex an authoritative copy of its own catalog with only that field\n * disabled. Runtime MCP delegation remains available independently.\n */\nexport function writeCodexCatalogWithNativeMultiAgentDisabled(\n authFilePath: string,\n sourcePath: string,\n): string {\n const codexHome = dirname(authFilePath);\n const outputPath = join(codexHome, NEGOTIUM_MODEL_CATALOG);\n\n const parsed = readCodexModelCache(sourcePath).parsed;\n\n const models = (parsed.models as unknown[]).map((model, index): CodexModel => {\n if (!model || typeof model !== \"object\" || Array.isArray(model)) {\n throw new Error(`Codex model cache entry ${index} is invalid: ${sourcePath}`);\n }\n return { ...(model as CodexModel), multi_agent_version: \"disabled\" };\n });\n const contents = `${JSON.stringify({ models }, null, 2)}\\n`;\n writePrivateFileAtomic(outputPath, contents);\n return outputPath;\n}\n",
|
|
7
|
-
"export const NEGOTIUM_VERSION = \"0.
|
|
7
|
+
"export const NEGOTIUM_VERSION = \"0.20.1\";\n"
|
|
8
8
|
],
|
|
9
9
|
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
10
|
+
"debugId": "C595D5173F5CFF9664756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
package/dist/hosted-agent.js
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
RUN_DIR,
|
|
27
27
|
SESSION_COMM_SERVER,
|
|
28
28
|
SESSION_WORKSPACE_DIR,
|
|
29
|
+
SUPPORTED_AGENTS,
|
|
29
30
|
SYSTEM_HEALTH_SERVER,
|
|
30
31
|
TASK_SERVER,
|
|
31
32
|
TOKEN_STATS_SERVER,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
logger,
|
|
42
43
|
resolveFallbackAgent,
|
|
43
44
|
resolveTopicWorkspaceDir
|
|
44
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-myhmb8tn.js";
|
|
45
46
|
import {
|
|
46
47
|
__require
|
|
47
48
|
} from "./chunk-2mx7fq49.js";
|
|
@@ -260,12 +261,248 @@ function referencesRuntimeSecretStorage(value) {
|
|
|
260
261
|
return false;
|
|
261
262
|
}
|
|
262
263
|
|
|
264
|
+
// ../../packages/core/src/agents/explicit-agent-switch.ts
|
|
265
|
+
function escapeRegExp(value) {
|
|
266
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
267
|
+
}
|
|
268
|
+
function agentAliases(agent) {
|
|
269
|
+
switch (agent) {
|
|
270
|
+
case "codex":
|
|
271
|
+
return [
|
|
272
|
+
"codex",
|
|
273
|
+
"\uCF54\uB371\uC2A4",
|
|
274
|
+
"gpt-6-luna",
|
|
275
|
+
"gpt-6-sol",
|
|
276
|
+
"gpt-5.6-luna",
|
|
277
|
+
"gpt-5.6-terra",
|
|
278
|
+
"gpt-5.6-sol",
|
|
279
|
+
"gpt-6-astra"
|
|
280
|
+
];
|
|
281
|
+
case "claude":
|
|
282
|
+
return ["claude", "\uD074\uB85C\uB4DC", "sonnet", "opus", "fable"];
|
|
283
|
+
case "maestro":
|
|
284
|
+
return [
|
|
285
|
+
"maestro",
|
|
286
|
+
"\uB9C8\uC5D0\uC2A4\uD2B8\uB85C",
|
|
287
|
+
"\uBA54\uC2A4\uD2B8\uB85C",
|
|
288
|
+
"deepseek",
|
|
289
|
+
"deepseek-pro",
|
|
290
|
+
"kimi",
|
|
291
|
+
"kimi-pro",
|
|
292
|
+
"kimi-k3",
|
|
293
|
+
"kimi-code",
|
|
294
|
+
"kimi-k2.7-code",
|
|
295
|
+
"\uB525\uC2DC\uD06C",
|
|
296
|
+
"\uD0A4\uBBF8"
|
|
297
|
+
];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function hasExplicitAgentSwitchRequest(prompt, agent) {
|
|
301
|
+
if (!prompt?.trim())
|
|
302
|
+
return false;
|
|
303
|
+
const text = prompt.toLowerCase().replace(/\s+/g, " ").trim();
|
|
304
|
+
const target = `(?:${agentAliases(agent).map(escapeRegExp).join("|")})`;
|
|
305
|
+
const switchVerb = "(?:\uBC14\uAFD4|\uBC14\uAFD4\uC918|\uBCC0\uACBD|\uBCC0\uACBD\uD574|\uC804\uD658|\uC804\uD658\uD574|\uC124\uC815|\uC124\uC815\uD574|\uC368\uC918|\uC0AC\uC6A9|\uAC00|switch|change|set|use)";
|
|
306
|
+
const switchSubject = "(?:agent|runtime|model|\uC5D0\uC774\uC804\uD2B8|\uB7F0\uD0C0\uC784|\uBAA8\uB378)";
|
|
307
|
+
return [
|
|
308
|
+
new RegExp(`^/(?:agent|runtime)\\s+${target}(?:\\s|$)`, "iu"),
|
|
309
|
+
new RegExp(`${target}\\s*(?:\uB85C|\uC73C\uB85C)\\s*.{0,16}${switchVerb}`, "iu"),
|
|
310
|
+
new RegExp(`${switchSubject}.{0,24}${target}.{0,24}${switchVerb}`, "iu"),
|
|
311
|
+
new RegExp(`${switchVerb}.{0,24}${switchSubject}.{0,24}${target}`, "iu"),
|
|
312
|
+
new RegExp(`(?:switch|change|set|use).{0,24}${target}`, "iu")
|
|
313
|
+
].some((pattern) => pattern.test(text));
|
|
314
|
+
}
|
|
315
|
+
function explicitAgentSwitchTargets(prompt) {
|
|
316
|
+
if (!prompt?.trim())
|
|
317
|
+
return [];
|
|
318
|
+
return SUPPORTED_AGENTS.filter((agent) => hasExplicitAgentSwitchRequest(prompt, agent));
|
|
319
|
+
}
|
|
320
|
+
|
|
263
321
|
// ../../packages/core/src/mcp/runtime-spec.ts
|
|
264
322
|
import { createHash, createHmac, timingSafeEqual } from "crypto";
|
|
323
|
+
|
|
324
|
+
// ../../packages/core/src/runtime/actor-topic-scope.ts
|
|
325
|
+
var ACTOR_TOPIC_SCOPE_LIMITS = Object.freeze({
|
|
326
|
+
maxIdsPerList: 200,
|
|
327
|
+
maxIdLength: 128,
|
|
328
|
+
maxSerializedBytes: 8 * 1024
|
|
329
|
+
});
|
|
330
|
+
var SCOPE_KEYS = ["visibleNodeTopicIds", "ownedNodeTopicIds"];
|
|
331
|
+
function idList(value, name) {
|
|
332
|
+
if (!Array.isArray(value))
|
|
333
|
+
return `${name} must be an array of topic ids`;
|
|
334
|
+
if (value.length > ACTOR_TOPIC_SCOPE_LIMITS.maxIdsPerList) {
|
|
335
|
+
return `${name} has ${value.length} ids; at most ${ACTOR_TOPIC_SCOPE_LIMITS.maxIdsPerList} are allowed`;
|
|
336
|
+
}
|
|
337
|
+
const ids = new Set;
|
|
338
|
+
for (const item of value) {
|
|
339
|
+
if (typeof item !== "string")
|
|
340
|
+
return `${name} must contain only strings`;
|
|
341
|
+
const id = item.trim();
|
|
342
|
+
if (!id)
|
|
343
|
+
return `${name} must not contain empty ids`;
|
|
344
|
+
if (id.length > ACTOR_TOPIC_SCOPE_LIMITS.maxIdLength) {
|
|
345
|
+
return `${name} contains an id longer than ${ACTOR_TOPIC_SCOPE_LIMITS.maxIdLength} characters`;
|
|
346
|
+
}
|
|
347
|
+
ids.add(id);
|
|
348
|
+
}
|
|
349
|
+
return [...ids];
|
|
350
|
+
}
|
|
351
|
+
function validateActorTopicScope(value) {
|
|
352
|
+
if (value === undefined)
|
|
353
|
+
return { ok: true, scope: undefined };
|
|
354
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
355
|
+
return {
|
|
356
|
+
ok: false,
|
|
357
|
+
error: "actorTopicScope must be { visibleNodeTopicIds: string[], ownedNodeTopicIds: string[] }"
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const proto = Object.getPrototypeOf(value);
|
|
361
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
362
|
+
return { ok: false, error: "actorTopicScope must be a plain object" };
|
|
363
|
+
}
|
|
364
|
+
const keys = Object.keys(value);
|
|
365
|
+
const unknown = keys.filter((key) => !SCOPE_KEYS.includes(key));
|
|
366
|
+
if (unknown.length || keys.length !== SCOPE_KEYS.length) {
|
|
367
|
+
return {
|
|
368
|
+
ok: false,
|
|
369
|
+
error: unknown.length ? `actorTopicScope has unexpected key(s): ${unknown.join(", ")}` : "actorTopicScope must have both visibleNodeTopicIds and ownedNodeTopicIds"
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
const record = value;
|
|
373
|
+
const visible = idList(record.visibleNodeTopicIds, "actorTopicScope.visibleNodeTopicIds");
|
|
374
|
+
if (typeof visible === "string")
|
|
375
|
+
return { ok: false, error: visible };
|
|
376
|
+
const owned = idList(record.ownedNodeTopicIds, "actorTopicScope.ownedNodeTopicIds");
|
|
377
|
+
if (typeof owned === "string")
|
|
378
|
+
return { ok: false, error: owned };
|
|
379
|
+
const scope = { visibleNodeTopicIds: visible, ownedNodeTopicIds: owned };
|
|
380
|
+
const bytes = Buffer.byteLength(JSON.stringify(scope), "utf-8");
|
|
381
|
+
if (bytes > ACTOR_TOPIC_SCOPE_LIMITS.maxSerializedBytes) {
|
|
382
|
+
return {
|
|
383
|
+
ok: false,
|
|
384
|
+
error: `actorTopicScope is ${bytes} bytes serialized; at most ${ACTOR_TOPIC_SCOPE_LIMITS.maxSerializedBytes} are allowed`
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
return { ok: true, scope };
|
|
388
|
+
}
|
|
389
|
+
function encodeActorTopicScopeArg(scope) {
|
|
390
|
+
const validated = validateActorTopicScope(scope);
|
|
391
|
+
if (!validated.ok)
|
|
392
|
+
throw new Error(validated.error);
|
|
393
|
+
if (!validated.scope)
|
|
394
|
+
throw new Error("actorTopicScope is required");
|
|
395
|
+
return Buffer.from(JSON.stringify(validated.scope), "utf-8").toString("base64url");
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ../../packages/core/src/runtime/remote-session-grant.ts
|
|
399
|
+
var REMOTE_SESSION_GRANT_LIMITS = Object.freeze({
|
|
400
|
+
maxHubUrlLength: 512,
|
|
401
|
+
maxCapabilityLength: 2 * 1024,
|
|
402
|
+
capabilityPrefix: "rsc1."
|
|
403
|
+
});
|
|
404
|
+
var GRANT_KEYS = ["hubUrl", "capability"];
|
|
405
|
+
var LOOPBACK_HOSTS = new Set(["127.0.0.1", "::1", "[::1]", "localhost"]);
|
|
406
|
+
function normalizeHubUrl(raw, name = "remoteSession.hubUrl") {
|
|
407
|
+
if (raw.length > REMOTE_SESSION_GRANT_LIMITS.maxHubUrlLength) {
|
|
408
|
+
return {
|
|
409
|
+
error: `${name} is longer than ${REMOTE_SESSION_GRANT_LIMITS.maxHubUrlLength} characters`
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
let url;
|
|
413
|
+
try {
|
|
414
|
+
url = new URL(raw);
|
|
415
|
+
} catch {
|
|
416
|
+
return { error: `${name} must be an absolute URL` };
|
|
417
|
+
}
|
|
418
|
+
if (url.username || url.password) {
|
|
419
|
+
return { error: `${name} must not carry credentials` };
|
|
420
|
+
}
|
|
421
|
+
if (url.search || url.hash || raw.includes("?") || raw.includes("#")) {
|
|
422
|
+
return { error: `${name} must not carry a query or fragment` };
|
|
423
|
+
}
|
|
424
|
+
if (url.protocol === "http:") {
|
|
425
|
+
if (!LOOPBACK_HOSTS.has(url.hostname)) {
|
|
426
|
+
return { error: `${name} must be https:// or a loopback http:// origin` };
|
|
427
|
+
}
|
|
428
|
+
} else if (url.protocol !== "https:") {
|
|
429
|
+
return { error: `${name} must be https:// or a loopback http:// origin` };
|
|
430
|
+
}
|
|
431
|
+
return { url: url.toString().replace(/\/+$/, "") };
|
|
432
|
+
}
|
|
433
|
+
var MAX_REMOTE_SESSION_REPLY_TOKEN_LENGTH = REMOTE_SESSION_GRANT_LIMITS.maxCapabilityLength;
|
|
434
|
+
function validateRemoteSessionGrant(value) {
|
|
435
|
+
if (value === undefined)
|
|
436
|
+
return { ok: true, grant: undefined };
|
|
437
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
438
|
+
return { ok: false, error: "remoteSession must be { hubUrl: string, capability: string }" };
|
|
439
|
+
}
|
|
440
|
+
const proto = Object.getPrototypeOf(value);
|
|
441
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
442
|
+
return { ok: false, error: "remoteSession must be a plain object" };
|
|
443
|
+
}
|
|
444
|
+
const keys = Object.keys(value);
|
|
445
|
+
const unknown = keys.filter((key) => !GRANT_KEYS.includes(key));
|
|
446
|
+
if (unknown.length || keys.length !== GRANT_KEYS.length) {
|
|
447
|
+
return {
|
|
448
|
+
ok: false,
|
|
449
|
+
error: unknown.length ? `remoteSession has unexpected key(s): ${unknown.join(", ")}` : "remoteSession must have both hubUrl and capability"
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
const record = value;
|
|
453
|
+
if (typeof record.hubUrl !== "string" || !record.hubUrl.trim()) {
|
|
454
|
+
return { ok: false, error: "remoteSession.hubUrl must be a non-empty string" };
|
|
455
|
+
}
|
|
456
|
+
const hubUrl = normalizeHubUrl(record.hubUrl.trim());
|
|
457
|
+
if ("error" in hubUrl)
|
|
458
|
+
return { ok: false, error: hubUrl.error };
|
|
459
|
+
if (typeof record.capability !== "string" || !record.capability.trim()) {
|
|
460
|
+
return { ok: false, error: "remoteSession.capability must be a non-empty string" };
|
|
461
|
+
}
|
|
462
|
+
const capability = record.capability.trim();
|
|
463
|
+
if (capability.length > REMOTE_SESSION_GRANT_LIMITS.maxCapabilityLength) {
|
|
464
|
+
return {
|
|
465
|
+
ok: false,
|
|
466
|
+
error: `remoteSession.capability is ${capability.length} characters; at most ${REMOTE_SESSION_GRANT_LIMITS.maxCapabilityLength} are allowed`
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
if (!capability.startsWith(REMOTE_SESSION_GRANT_LIMITS.capabilityPrefix)) {
|
|
470
|
+
return {
|
|
471
|
+
ok: false,
|
|
472
|
+
error: `remoteSession.capability must start with "${REMOTE_SESSION_GRANT_LIMITS.capabilityPrefix}"`
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
if (!/^rsc1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(capability)) {
|
|
476
|
+
return { ok: false, error: "remoteSession.capability is malformed" };
|
|
477
|
+
}
|
|
478
|
+
return { ok: true, grant: { hubUrl: hubUrl.url, capability } };
|
|
479
|
+
}
|
|
480
|
+
function encodeRemoteSessionGrantArg(grant) {
|
|
481
|
+
const validated = validateRemoteSessionGrant(grant);
|
|
482
|
+
if (!validated.ok)
|
|
483
|
+
throw new Error(validated.error);
|
|
484
|
+
if (!validated.grant)
|
|
485
|
+
throw new Error("remoteSession is required");
|
|
486
|
+
return Buffer.from(JSON.stringify(validated.grant), "utf-8").toString("base64url");
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// ../../packages/core/src/mcp/runtime-spec.ts
|
|
265
490
|
var RUNTIME_MCP_KEY = "runtime";
|
|
266
491
|
var RUNTIME_MCP_BASE_PATH = "/mcp/runtime";
|
|
267
492
|
var TOKEN_TTL_MS = 4 * 60 * 60 * 1000;
|
|
268
493
|
var CLAUDE_MCP_TOOL_TIMEOUT_MS = 600000;
|
|
494
|
+
var MCP_URL_BUDGET_CHARS = 14 * 1024;
|
|
495
|
+
|
|
496
|
+
class McpUrlBudgetExceededError extends Error {
|
|
497
|
+
surface;
|
|
498
|
+
urlLength;
|
|
499
|
+
constructor(surface, urlLength) {
|
|
500
|
+
super(`built-in MCP URL for "${surface}" is ${urlLength} characters; the transport allows at most ${MCP_URL_BUDGET_CHARS}`);
|
|
501
|
+
this.surface = surface;
|
|
502
|
+
this.urlLength = urlLength;
|
|
503
|
+
this.name = "McpUrlBudgetExceededError";
|
|
504
|
+
}
|
|
505
|
+
}
|
|
269
506
|
var runtimePort = NEGOTIUM_PORT;
|
|
270
507
|
function encodeTokenPart(value) {
|
|
271
508
|
return Buffer.from(JSON.stringify(value), "utf-8").toString("base64url");
|
|
@@ -291,18 +528,26 @@ function issueHostedMcpToken(surface, ctx) {
|
|
|
291
528
|
return `${payloadPart}.${signTokenPayload(payloadPart)}`;
|
|
292
529
|
}
|
|
293
530
|
function buildRuntimeMcpSpec(agent, ctx) {
|
|
294
|
-
const token = issueRuntimeMcpToken(ctx);
|
|
295
531
|
const base = `http://127.0.0.1:${runtimePort}${RUNTIME_MCP_BASE_PATH}`;
|
|
296
|
-
const query = `token=${encodeURIComponent(
|
|
532
|
+
const query = `token=${encodeURIComponent(issueRuntimeMcpToken(ctx))}`;
|
|
533
|
+
const url = agent === "codex" ? `${base}/mcp?${query}` : `${base}/sse?${query}`;
|
|
534
|
+
assertMcpUrlWithinBudget(RUNTIME_MCP_KEY, url, ctx.topicId);
|
|
297
535
|
if (agent === "codex")
|
|
298
|
-
return { url
|
|
536
|
+
return { url };
|
|
299
537
|
return {
|
|
300
538
|
type: "sse",
|
|
301
|
-
url
|
|
539
|
+
url,
|
|
302
540
|
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS,
|
|
303
541
|
...agent === "maestro" ? { lifecycle: "turn" } : {}
|
|
304
542
|
};
|
|
305
543
|
}
|
|
544
|
+
function assertMcpUrlWithinBudget(surface, url, topicId) {
|
|
545
|
+
if (url.length <= MCP_URL_BUDGET_CHARS)
|
|
546
|
+
return;
|
|
547
|
+
const error = new McpUrlBudgetExceededError(surface, url.length);
|
|
548
|
+
logger.error({ topicId, surface, urlLength: url.length, budget: MCP_URL_BUDGET_CHARS }, "built-in MCP URL exceeds the transport budget; refusing to mint the token");
|
|
549
|
+
throw error;
|
|
550
|
+
}
|
|
306
551
|
function hostedMcpCacheIdentity(surface, ctx) {
|
|
307
552
|
let semanticContext;
|
|
308
553
|
switch (surface) {
|
|
@@ -333,6 +578,9 @@ function hostedMcpCacheIdentity(surface, ctx) {
|
|
|
333
578
|
case "session-comm":
|
|
334
579
|
semanticContext = {
|
|
335
580
|
userId: ctx.userId,
|
|
581
|
+
actorUserId: ctx.actorUserId ?? null,
|
|
582
|
+
actorTopicScope: ctx.actorTopicScope ?? null,
|
|
583
|
+
remoteSession: ctx.remoteSession ?? null,
|
|
336
584
|
topicTitle: ctx.topicTitle,
|
|
337
585
|
topicId: ctx.topicId ?? null,
|
|
338
586
|
subagentParentTopicId: ctx.subagentParentTopicId ?? null,
|
|
@@ -351,13 +599,15 @@ function buildHostedMcpSpec(agent, surface, ctx) {
|
|
|
351
599
|
const token = issueHostedMcpToken(surface, ctx);
|
|
352
600
|
const base = `http://127.0.0.1:${runtimePort}${RUNTIME_MCP_BASE_PATH}/${surface}`;
|
|
353
601
|
const query = `token=${encodeURIComponent(token)}`;
|
|
602
|
+
const url = agent === "codex" ? `${base}/mcp?${query}` : `${base}/sse?${query}`;
|
|
603
|
+
assertMcpUrlWithinBudget(surface, url, ctx.topicId);
|
|
354
604
|
if (agent === "codex")
|
|
355
|
-
return { url
|
|
356
|
-
const queryBound = surface === "session-comm" && (ctx.silent === true || ctx.peerBridge !== undefined);
|
|
605
|
+
return { url };
|
|
606
|
+
const queryBound = surface === "session-comm" && (ctx.silent === true || ctx.peerBridge !== undefined || ctx.remoteSession !== undefined);
|
|
357
607
|
const lifecycle = queryBound ? "turn" : surface === "session-comm" ? "session" : "process";
|
|
358
608
|
return {
|
|
359
609
|
type: "sse",
|
|
360
|
-
url
|
|
610
|
+
url,
|
|
361
611
|
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS,
|
|
362
612
|
...agent === "maestro" ? {
|
|
363
613
|
lifecycle,
|
|
@@ -1126,6 +1376,9 @@ function initializeApiTopicsSchema() {
|
|
|
1126
1376
|
if (!tableColumns("api_topics").has("subagent_report_mode")) {
|
|
1127
1377
|
db.exec("ALTER TABLE api_topics ADD COLUMN subagent_report_mode TEXT NOT NULL DEFAULT 'auto'");
|
|
1128
1378
|
}
|
|
1379
|
+
if (!tableColumns("api_topics").has("derived_by_user_id")) {
|
|
1380
|
+
db.exec("ALTER TABLE api_topics ADD COLUMN derived_by_user_id TEXT");
|
|
1381
|
+
}
|
|
1129
1382
|
if (!tableColumns("api_topics").has("memory_topic_id")) {
|
|
1130
1383
|
db.exec("ALTER TABLE api_topics ADD COLUMN memory_topic_id TEXT");
|
|
1131
1384
|
}
|
|
@@ -1217,6 +1470,7 @@ function rowToDto(r, participants = getTopicParticipants(r.id), tellTargets) {
|
|
|
1217
1470
|
memoryTopicId: r.memory_topic_id ?? undefined,
|
|
1218
1471
|
memoryKey: r.memory_key ?? undefined,
|
|
1219
1472
|
isFork: r.is_fork !== 0,
|
|
1473
|
+
...r.derived_by_user_id ? { derivedByUserId: r.derived_by_user_id } : {},
|
|
1220
1474
|
...r.is_subagent !== 0 ? { isSubagent: true } : {},
|
|
1221
1475
|
...r.is_subagent !== 0 ? {
|
|
1222
1476
|
subagentTellTargetIds: tellTargets ? tellTargets.get(r.id) ?? [] : listSubagentTellTargetIds(r.id)
|
|
@@ -1300,6 +1554,9 @@ function buildBuiltinMcpServer(surface, ctx, stdio) {
|
|
|
1300
1554
|
const agent = ctx.agent ?? FALLBACK_AGENT;
|
|
1301
1555
|
return buildHostedMcpSpec(agent, surface, {
|
|
1302
1556
|
userId: ctx.userId,
|
|
1557
|
+
...ctx.actorUserId ? { actorUserId: ctx.actorUserId } : {},
|
|
1558
|
+
...ctx.actorTopicScope ? { actorTopicScope: ctx.actorTopicScope } : {},
|
|
1559
|
+
...surface === "session-comm" && ctx.remoteSession ? { remoteSession: ctx.remoteSession } : {},
|
|
1303
1560
|
topicTitle: ctx.session,
|
|
1304
1561
|
...ctx.topicId ? { topicId: ctx.topicId } : {},
|
|
1305
1562
|
...ctx.queryId ? { queryId: ctx.queryId } : {},
|
|
@@ -1395,6 +1652,7 @@ var MCP_CATALOG = {
|
|
|
1395
1652
|
build({
|
|
1396
1653
|
userId,
|
|
1397
1654
|
actorUserId,
|
|
1655
|
+
actorTopicScope,
|
|
1398
1656
|
session,
|
|
1399
1657
|
topicId,
|
|
1400
1658
|
queryId,
|
|
@@ -1410,16 +1668,18 @@ var MCP_CATALOG = {
|
|
|
1410
1668
|
}) {
|
|
1411
1669
|
if (!topicId || !agent)
|
|
1412
1670
|
return null;
|
|
1671
|
+
const switchTargets = explicitAgentSwitchTargets(currentUserPrompt);
|
|
1413
1672
|
return buildRuntimeMcpSpec(agent, {
|
|
1414
1673
|
userId,
|
|
1415
1674
|
...actorUserId ? { actorUserId } : {},
|
|
1675
|
+
...actorTopicScope ? { actorTopicScope } : {},
|
|
1416
1676
|
topicId,
|
|
1417
1677
|
topicTitle: session,
|
|
1418
1678
|
queryId,
|
|
1419
1679
|
cwd: cwd ?? resolveTopicWorkspaceDir(topicId),
|
|
1420
1680
|
agent,
|
|
1421
1681
|
model,
|
|
1422
|
-
|
|
1682
|
+
...switchTargets.length ? { explicitAgentSwitchTargets: switchTargets } : {},
|
|
1423
1683
|
autoContinue,
|
|
1424
1684
|
visualTools,
|
|
1425
1685
|
fileDeliveryTools,
|
|
@@ -1489,6 +1749,9 @@ var MCP_CATALOG = {
|
|
|
1489
1749
|
build(ctx) {
|
|
1490
1750
|
const {
|
|
1491
1751
|
userId,
|
|
1752
|
+
actorUserId,
|
|
1753
|
+
actorTopicScope,
|
|
1754
|
+
remoteSession,
|
|
1492
1755
|
session,
|
|
1493
1756
|
topicId,
|
|
1494
1757
|
subagentParentTopicId,
|
|
@@ -1502,6 +1765,9 @@ var MCP_CATALOG = {
|
|
|
1502
1765
|
const cronSessionId = topicId ? getRegisteredCronSession(topicId, effectiveAgent)?.sessionId : undefined;
|
|
1503
1766
|
const args = [
|
|
1504
1767
|
`--user-id=${userId}`,
|
|
1768
|
+
...actorUserId ? [`--actor-user-id=${actorUserId}`] : [],
|
|
1769
|
+
...actorTopicScope ? [`--actor-topic-scope=${encodeActorTopicScopeArg(actorTopicScope)}`] : [],
|
|
1770
|
+
...remoteSession ? [`--remote-session-grant=${encodeRemoteSessionGrantArg(remoteSession)}`] : [],
|
|
1505
1771
|
`--topic=${session}`,
|
|
1506
1772
|
...topicId ? [`--topic-id=${topicId}`] : [],
|
|
1507
1773
|
...subagentParentTopicId ? [`--subagent-parent-topic-id=${subagentParentTopicId}`] : [],
|
|
@@ -1679,6 +1945,9 @@ function getManagerMcpServers(opts) {
|
|
|
1679
1945
|
const topicId = opts.topicId;
|
|
1680
1946
|
return buildScope("manager", {
|
|
1681
1947
|
userId: opts.userId,
|
|
1948
|
+
actorUserId: opts.actorUserId,
|
|
1949
|
+
actorTopicScope: opts.actorTopicScope,
|
|
1950
|
+
remoteSession: opts.remoteSession,
|
|
1682
1951
|
session: opts.session ?? "General",
|
|
1683
1952
|
topicId,
|
|
1684
1953
|
queryId: opts.queryId,
|
|
@@ -1698,6 +1967,8 @@ function getForumMcpServers(opts) {
|
|
|
1698
1967
|
const {
|
|
1699
1968
|
userId,
|
|
1700
1969
|
actorUserId,
|
|
1970
|
+
actorTopicScope,
|
|
1971
|
+
remoteSession,
|
|
1701
1972
|
vaultUserId,
|
|
1702
1973
|
session,
|
|
1703
1974
|
topicId,
|
|
@@ -1731,6 +2002,8 @@ function getForumMcpServers(opts) {
|
|
|
1731
2002
|
const base = buildScope("forum", {
|
|
1732
2003
|
userId,
|
|
1733
2004
|
actorUserId,
|
|
2005
|
+
actorTopicScope,
|
|
2006
|
+
remoteSession,
|
|
1734
2007
|
vaultUserId,
|
|
1735
2008
|
session,
|
|
1736
2009
|
topicId,
|
|
@@ -1811,6 +2084,9 @@ function getMcpServersForQuery(opts) {
|
|
|
1811
2084
|
if (opts.sessionType === "manager") {
|
|
1812
2085
|
return hideProviderIntrospectionForOtium(mergeHostMcpServers(getManagerMcpServers({
|
|
1813
2086
|
userId: opts.userId || "local",
|
|
2087
|
+
actorUserId: opts.actorUserId,
|
|
2088
|
+
actorTopicScope: opts.actorTopicScope,
|
|
2089
|
+
remoteSession: opts.remoteSession,
|
|
1814
2090
|
session: opts.session,
|
|
1815
2091
|
topicId: opts.topicId,
|
|
1816
2092
|
queryId: opts.queryId,
|
|
@@ -1829,6 +2105,8 @@ function getMcpServersForQuery(opts) {
|
|
|
1829
2105
|
return hideProviderIntrospectionForOtium(getForumMcpServers({
|
|
1830
2106
|
userId: opts.userId || "local",
|
|
1831
2107
|
actorUserId: opts.actorUserId,
|
|
2108
|
+
actorTopicScope: opts.actorTopicScope,
|
|
2109
|
+
remoteSession: opts.remoteSession,
|
|
1832
2110
|
vaultUserId: opts.vaultUserId,
|
|
1833
2111
|
session: opts.session || "default",
|
|
1834
2112
|
topicId: opts.topicId,
|
|
@@ -2726,7 +3004,7 @@ import { tmpdir } from "os";
|
|
|
2726
3004
|
import { dirname as dirname5, join as join3 } from "path";
|
|
2727
3005
|
|
|
2728
3006
|
// ../../packages/core/src/version.ts
|
|
2729
|
-
var NEGOTIUM_VERSION = "0.
|
|
3007
|
+
var NEGOTIUM_VERSION = "0.20.1";
|
|
2730
3008
|
|
|
2731
3009
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
2732
3010
|
var moduleRequire = createRequire(import.meta.url);
|
|
@@ -3455,7 +3733,7 @@ async function createCodexVaultHookBridge(userId) {
|
|
|
3455
3733
|
});
|
|
3456
3734
|
restrictIpcEndpoint(socketPath);
|
|
3457
3735
|
if (IS_WINDOWS2) {
|
|
3458
|
-
const { BINARIES_DIR } = await import("./chunk-
|
|
3736
|
+
const { BINARIES_DIR } = await import("./chunk-zkyp090x.js");
|
|
3459
3737
|
const cached = await ensureCodexWindowsWrapperExe(join5(BINARIES_DIR, "codex-hook-wrapper"));
|
|
3460
3738
|
await copyFile(cached, wrapperPath);
|
|
3461
3739
|
await writeFile2(join5(root, "codex-with-hooks.cfg"), [process.execPath, codexCliScriptPath(), socketPath, token].join(`
|
|
@@ -4769,4 +5047,4 @@ export {
|
|
|
4769
5047
|
buildClaudeDisallowedTools
|
|
4770
5048
|
};
|
|
4771
5049
|
|
|
4772
|
-
//# debugId=
|
|
5050
|
+
//# debugId=1307E2EFD67054A264756E2164756E21
|