@bitkyc08/opencodex 2.52.0 → 2.53.0
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/gui/dist/assets/index-BBOZWGB6.css +1 -0
- package/gui/dist/assets/index-BlO4Yl6q.js +128 -0
- package/gui/dist/index.html +2 -2
- package/native/remote-workspace-helper/Cargo.lock +130 -0
- package/native/remote-workspace-helper/Cargo.toml +24 -0
- package/native/remote-workspace-helper/src/main.rs +49 -0
- package/native/remote-workspace-helper/src/protocol.rs +246 -0
- package/native/remote-workspace-helper/src/sandbox/macos.rs +19 -0
- package/native/remote-workspace-helper/src/sandbox/mod.rs +77 -0
- package/native/remote-workspace-helper/src/sandbox/windows.rs +15 -0
- package/package.json +6 -1
- package/src/adapters/anthropic-image-normalize.ts +30 -2
- package/src/adapters/anthropic.ts +1 -1
- package/src/adapters/base.ts +8 -2
- package/src/adapters/cursor/cursor-errors.ts +12 -0
- package/src/adapters/cursor/thread-continuity.ts +93 -0
- package/src/adapters/cursor.ts +104 -73
- package/src/adapters/devin/cloud-direct/chat.ts +312 -23
- package/src/adapters/devin/cloud-direct/metadata.ts +31 -2
- package/src/adapters/devin/live-models.ts +70 -3
- package/src/adapters/devin.ts +281 -21
- package/src/adapters/google-wire-compiler.ts +14 -6
- package/src/adapters/google.ts +22 -8
- package/src/adapters/kiro/adapter.ts +316 -0
- package/src/adapters/kiro/conversation.ts +136 -0
- package/src/adapters/kiro/payload.ts +432 -0
- package/src/adapters/kiro/reasoning.ts +56 -0
- package/src/adapters/kiro/stream.ts +1153 -0
- package/src/adapters/kiro/usage.ts +223 -0
- package/src/adapters/kiro/wire.ts +76 -0
- package/src/adapters/kiro.ts +8 -2319
- package/src/adapters/mimo-free.ts +1 -1
- package/src/adapters/openai-chat-images.ts +101 -0
- package/src/adapters/openai-chat.ts +201 -181
- package/src/adapters/openai-responses.ts +92 -224
- package/src/adapters/registry.ts +0 -7
- package/src/adapters/run-turn-queue.ts +13 -6
- package/src/bridge.ts +14 -15
- package/src/chat/inbound.ts +29 -4
- package/src/chat/outbound.ts +145 -107
- package/src/claude/desktop-profile.ts +4 -6
- package/src/cli/account-api.ts +14 -0
- package/src/cli/account-extended.ts +1 -1
- package/src/cli/account-history.ts +60 -0
- package/src/cli/account-main.ts +80 -0
- package/src/cli/account.ts +11 -3
- package/src/cli/capabilities.ts +113 -0
- package/src/cli/catalog.ts +109 -0
- package/src/cli/dispatch.ts +9 -0
- package/src/cli/help.ts +2 -0
- package/src/cli/index.ts +2 -2
- package/src/cli/observe.ts +28 -1
- package/src/cli/opencode.ts +42 -8
- package/src/cli/provider-runtime.ts +11 -1
- package/src/cli/provider.ts +22 -2
- package/src/cli/registry.ts +21 -0
- package/src/cli/remote-workspace.ts +154 -0
- package/src/cli/status.ts +39 -7
- package/src/cli/usage-report.ts +14 -2
- package/src/client/hub-client.ts +34 -0
- package/src/client/hub-state.ts +9 -1
- package/src/codex/account-store.ts +78 -0
- package/src/codex/auth-api.ts +81 -54
- package/src/codex/auth-context.ts +45 -16
- package/src/codex/catalog/effort.ts +1 -1
- package/src/codex/catalog/metadata.ts +3 -6
- package/src/codex/catalog/native-models.ts +4 -4
- package/src/codex/catalog/parsing.ts +2 -20
- package/src/codex/catalog/provider-fetch.ts +10 -1
- package/src/codex/catalog/remote.ts +233 -0
- package/src/codex/catalog/sync.ts +403 -35
- package/src/codex/convergence.ts +1 -1
- package/src/codex/history-manifest.ts +36 -0
- package/src/codex/history-provider.ts +32 -5
- package/src/codex/inject.ts +9 -0
- package/src/codex/main-account.ts +113 -0
- package/src/codex/main-device-reauth-api.ts +89 -0
- package/src/codex/main-device-reauth.ts +217 -0
- package/src/codex/native-residue.ts +9 -2
- package/src/codex/quota-auto-refresh.ts +3 -2
- package/src/codex/quota-capacity.ts +98 -0
- package/src/codex/quota-history.ts +160 -0
- package/src/codex/quota-types.ts +8 -0
- package/src/codex/quota.ts +118 -91
- package/src/codex/refresh.ts +2 -1
- package/src/codex/routing.ts +90 -17
- package/src/codex/sync.ts +33 -4
- package/src/combos/request.ts +19 -1
- package/src/config/multi-agent-surface.ts +61 -0
- package/src/config/provider-validation.ts +176 -0
- package/src/config.ts +213 -11
- package/src/generated/compatibility-version.json +436 -168
- package/src/images/loop.ts +119 -36
- package/src/lib/admission.ts +12 -6
- package/src/lib/redact.ts +7 -0
- package/src/lib/translator-budget.ts +4 -3
- package/src/lib/windows-atomic-replace.ts +1 -0
- package/src/lib/windows-elevation.ts +1 -1
- package/src/oauth/chatgpt-device.ts +62 -5
- package/src/oauth/devin/cli-import.ts +130 -0
- package/src/oauth/devin.ts +63 -8
- package/src/oauth/index.ts +29 -14
- package/src/oauth/kiro.ts +18 -6
- package/src/oauth/login-cli.ts +9 -1
- package/src/oauth/meta-muse-device.ts +464 -0
- package/src/oauth/meta-muse.ts +123 -32
- package/src/oauth/pool-kernel.ts +9 -0
- package/src/oauth/pool-settings-capability.ts +2 -2
- package/src/oauth/store.ts +57 -0
- package/src/oauth/types.ts +31 -0
- package/src/providers/derive.ts +13 -3
- package/src/providers/devin-cli-authmode-migration.ts +57 -35
- package/src/providers/devin-provider-merge-migration.ts +240 -0
- package/src/providers/muse-key-quota.ts +117 -0
- package/src/providers/muse-subscription-usage.ts +14 -2
- package/src/providers/openai-sidecar.ts +25 -3
- package/src/providers/opencode-zen-rate-limit.ts +58 -0
- package/src/providers/provider-id-rewrite.ts +20 -5
- package/src/providers/quota-types.ts +12 -0
- package/src/providers/quota.ts +143 -102
- package/src/providers/reasoning-metadata.ts +543 -0
- package/src/providers/registry.ts +80 -49
- package/src/reasoning-effort.ts +26 -2
- package/src/remote/hub-usage.ts +32 -0
- package/src/remote-control/index.ts +192 -41
- package/src/remote-control/workspace-activation.ts +9 -0
- package/src/remote-control/workspace-agent-connection.ts +366 -0
- package/src/remote-control/workspace-claude-runtime.ts +243 -0
- package/src/remote-control/workspace-codex-runtime.ts +531 -0
- package/src/remote-control/workspace-codex-sandbox.ts +115 -0
- package/src/remote-control/workspace-command-runner.ts +748 -0
- package/src/remote-control/workspace-coordinator.ts +231 -0
- package/src/remote-control/workspace-device.ts +585 -0
- package/src/remote-control/workspace-executable.ts +43 -0
- package/src/remote-control/workspace-executor.ts +397 -0
- package/src/remote-control/workspace-hub.ts +519 -0
- package/src/remote-control/workspace-pi-runtime.ts +382 -0
- package/src/remote-control/workspace-process.ts +129 -0
- package/src/remote-control/workspace-rpc.ts +304 -0
- package/src/remote-control/workspace-runtime.ts +60 -0
- package/src/remote-control/workspace-secret-store.ts +39 -0
- package/src/remote-control/workspace-sessions.ts +799 -0
- package/src/remote-control/workspace-tool-bridge.ts +192 -0
- package/src/responses/code-mode-helper-compat.ts +22 -3
- package/src/responses/hosted-tool-policy.ts +0 -1
- package/src/responses/muse-tool-name-alias.ts +379 -0
- package/src/responses/plaintext-v2-agent-messages.ts +902 -0
- package/src/router.ts +7 -0
- package/src/routing/compatibility/behavior.ts +0 -1
- package/src/server/audio-client.ts +64 -0
- package/src/server/audio-dictation.ts +91 -0
- package/src/server/audio-live.ts +185 -0
- package/src/server/audio-transcriptions.ts +183 -0
- package/src/server/audio-upstream.ts +153 -0
- package/src/server/auth-cors.ts +61 -2
- package/src/server/chat-completions.ts +1 -1
- package/src/server/chat-native-sse.ts +92 -48
- package/src/server/chat-native.ts +37 -15
- package/src/server/hub-usage.ts +57 -0
- package/src/server/images.ts +4 -0
- package/src/server/index.ts +722 -57
- package/src/server/lifecycle.ts +5 -6
- package/src/server/live-call-bindings.ts +60 -0
- package/src/server/live.ts +12 -1
- package/src/server/management/agent-settings-routes.ts +25 -4
- package/src/server/management/api-access.ts +37 -0
- package/src/server/management/api-key-usage.ts +7 -2
- package/src/server/management/config-routes.ts +1 -18
- package/src/server/management/context.ts +15 -0
- package/src/server/management/logs-usage-routes.ts +2 -0
- package/src/server/management/oauth-account-routes.ts +39 -12
- package/src/server/management/provider-routes.ts +125 -2
- package/src/server/management/remote-workspace-routes.ts +140 -0
- package/src/server/management/route-registry.ts +15 -0
- package/src/server/management/usage-aggregate-cache.ts +14 -15
- package/src/server/management/usage-summary-cache.ts +2 -0
- package/src/server/management-api.ts +23 -0
- package/src/server/ports.ts +17 -0
- package/src/server/relay-eager.ts +4 -1
- package/src/server/relay.ts +70 -10
- package/src/server/request-decompress.ts +6 -3
- package/src/server/responses/agent-task-recovery.ts +25 -32
- package/src/server/responses/codex-auth-error.ts +11 -0
- package/src/server/responses/codex-ws-exchange.ts +52 -3
- package/src/server/responses/codex-ws-wire.ts +55 -0
- package/src/server/responses/compact.ts +9 -1
- package/src/server/responses/core.ts +337 -73
- package/src/server/responses/encrypted-payload.ts +45 -2
- package/src/server/responses/ws-upstream.ts +4 -1
- package/src/server/responses-self-named-namespace-scrub.ts +1 -3
- package/src/server/responses-undeclared-tool-guard.ts +1 -1
- package/src/server/search.ts +3 -0
- package/src/server/sse-payload-rewrite.ts +136 -51
- package/src/server/ws-bridge.ts +35 -1
- package/src/service/cli.ts +372 -0
- package/src/service/diagnostics.ts +340 -0
- package/src/service/guards.ts +303 -0
- package/src/service/health.ts +222 -0
- package/src/service/launchd.ts +853 -0
- package/src/service/orchestration.ts +617 -0
- package/src/service/repair.ts +334 -0
- package/src/service/state.ts +363 -0
- package/src/service/systemd.ts +229 -0
- package/src/service/windows-ops.ts +690 -0
- package/src/service/windows-scheduler.ts +769 -0
- package/src/service/windows-taskxml.ts +613 -0
- package/src/service.ts +22 -5550
- package/src/storage/cleanup/db.ts +258 -0
- package/src/storage/cleanup/execute.ts +358 -0
- package/src/storage/cleanup/paths.ts +189 -0
- package/src/storage/cleanup/pending.ts +140 -0
- package/src/storage/cleanup/preview.ts +292 -0
- package/src/storage/cleanup/reconcile.ts +347 -0
- package/src/storage/cleanup/restore.ts +932 -0
- package/src/storage/cleanup/satellite.ts +474 -0
- package/src/storage/cleanup/staging.ts +129 -0
- package/src/storage/cleanup/types.ts +98 -0
- package/src/storage/cleanup.ts +49 -3127
- package/src/types/accounts.ts +2 -0
- package/src/types/config.ts +13 -12
- package/src/types/provider.ts +37 -0
- package/src/types/request.ts +2 -0
- package/src/types/tools.ts +17 -5
- package/src/types.ts +1 -0
- package/src/usage/expected-prices.ts +127 -0
- package/src/usage/log.ts +58 -1
- package/src/vision/eligibility.ts +13 -2
- package/src/web-search/loop.ts +56 -3
- package/gui/dist/assets/index-CWXut3rG.js +0 -115
- package/gui/dist/assets/index-EdoPnm9_.css +0 -1
- package/src/adapters/devin-cli/acp.ts +0 -204
- package/src/adapters/devin-cli/adapter.ts +0 -345
- package/src/adapters/devin-cli/binary.ts +0 -69
- package/src/adapters/devin-cli/models.ts +0 -57
- package/src/oauth/devin-cli.ts +0 -149
- package/src/server/responses-reasoning-summary-rewrite.ts +0 -178
|
@@ -0,0 +1,902 @@
|
|
|
1
|
+
const COLLABORATION_NAMESPACE = "collaboration";
|
|
2
|
+
export const PLAINTEXT_V2_COLLABORATION_NAMESPACE = "collaboration-optimize";
|
|
3
|
+
const COLLABORATION_NAME_PREFIX = `${COLLABORATION_NAMESPACE}__`;
|
|
4
|
+
const COLLABORATION_DOTTED_NAME_PREFIX = `${COLLABORATION_NAMESPACE}.`;
|
|
5
|
+
const PLAINTEXT_V2_COLLABORATION_NAME_PREFIX = `${PLAINTEXT_V2_COLLABORATION_NAMESPACE}__`;
|
|
6
|
+
const PLAINTEXT_V2_COLLABORATION_DOTTED_NAME_PREFIX = `${PLAINTEXT_V2_COLLABORATION_NAMESPACE}.`;
|
|
7
|
+
|
|
8
|
+
const PLAINTEXT_V2_AGENT_MESSAGE_TOOLS = new Set([
|
|
9
|
+
"spawn_agent",
|
|
10
|
+
"send_message",
|
|
11
|
+
"followup_task",
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
const PLAINTEXT_V2_AGENT_MESSAGE_TOOL_ALIASES = new Map<string, string>([
|
|
15
|
+
["spawn_agent", "start_delegated_task"],
|
|
16
|
+
["send_message", "deliver_delegated_message"],
|
|
17
|
+
["followup_task", "continue_delegated_task"],
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const PLAINTEXT_V2_AGENT_MESSAGE_TOOL_NAMES = new Map<string, string>(
|
|
21
|
+
[...PLAINTEXT_V2_AGENT_MESSAGE_TOOL_ALIASES].map(([name, alias]) => [alias, name]),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export function shouldPreparePlaintextV2AgentMessages(args: {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
inboundWire: string;
|
|
27
|
+
canonicalChatGpt: boolean;
|
|
28
|
+
requestBody: unknown;
|
|
29
|
+
}): boolean {
|
|
30
|
+
return args.enabled
|
|
31
|
+
&& args.inboundWire === "responses"
|
|
32
|
+
&& args.canonicalChatGpt
|
|
33
|
+
&& hasPlaintextV2CollaborationCatalog(args.requestBody);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
37
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function responseToolCatalogs(body: Record<string, unknown>): unknown[][] {
|
|
41
|
+
const catalogs: unknown[][] = [];
|
|
42
|
+
if (Array.isArray(body.tools)) catalogs.push(body.tools);
|
|
43
|
+
if (!Array.isArray(body.input)) return catalogs;
|
|
44
|
+
for (const item of body.input) {
|
|
45
|
+
if (
|
|
46
|
+
isPlainObject(item)
|
|
47
|
+
&& item.type === "additional_tools"
|
|
48
|
+
&& Array.isArray(item.tools)
|
|
49
|
+
) {
|
|
50
|
+
catalogs.push(item.tools);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return catalogs;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function collaborationCatalogInfo(catalogs: readonly unknown[][]): {
|
|
57
|
+
hasV2Catalog: boolean;
|
|
58
|
+
toolNames: Set<string>;
|
|
59
|
+
aliasedAgentMessageToolNames: Set<string>;
|
|
60
|
+
} {
|
|
61
|
+
let hasV2Catalog = false;
|
|
62
|
+
const toolNames = new Set<string>();
|
|
63
|
+
const aliasedAgentMessageToolNames = new Set<string>();
|
|
64
|
+
for (const tools of catalogs) {
|
|
65
|
+
for (const tool of tools) {
|
|
66
|
+
if (
|
|
67
|
+
!isPlainObject(tool)
|
|
68
|
+
|| tool.type !== "namespace"
|
|
69
|
+
|| tool.name !== COLLABORATION_NAMESPACE
|
|
70
|
+
|| !Array.isArray(tool.tools)
|
|
71
|
+
) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
for (const child of tool.tools) {
|
|
75
|
+
if (
|
|
76
|
+
isPlainObject(child)
|
|
77
|
+
&& (child.type === "function" || child.type === "custom")
|
|
78
|
+
&& typeof child.name === "string"
|
|
79
|
+
) {
|
|
80
|
+
toolNames.add(child.name);
|
|
81
|
+
if (
|
|
82
|
+
child.type === "function"
|
|
83
|
+
&& PLAINTEXT_V2_AGENT_MESSAGE_TOOL_ALIASES.has(child.name)
|
|
84
|
+
) {
|
|
85
|
+
aliasedAgentMessageToolNames.add(child.name);
|
|
86
|
+
}
|
|
87
|
+
if (child.type === "function" && child.name === "spawn_agent") hasV2Catalog = true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { hasV2Catalog, toolNames, aliasedAgentMessageToolNames };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function hasPlaintextV2CollaborationCatalog(body: unknown): boolean {
|
|
96
|
+
if (!isPlainObject(body)) return false;
|
|
97
|
+
return Array.isArray(body.tools) && collaborationCatalogInfo([body.tools]).hasV2Catalog;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function hasOptimizedNamespaceConflict(catalogs: readonly unknown[][]): boolean {
|
|
101
|
+
const pending = [...catalogs];
|
|
102
|
+
while (pending.length > 0) {
|
|
103
|
+
const tools = pending.pop()!;
|
|
104
|
+
for (const tool of tools) {
|
|
105
|
+
if (!isPlainObject(tool)) continue;
|
|
106
|
+
if (
|
|
107
|
+
typeof tool.name === "string"
|
|
108
|
+
&& (
|
|
109
|
+
tool.name === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
110
|
+
|| tool.name.startsWith(PLAINTEXT_V2_COLLABORATION_NAME_PREFIX)
|
|
111
|
+
|| tool.name.startsWith(PLAINTEXT_V2_COLLABORATION_DOTTED_NAME_PREFIX)
|
|
112
|
+
)
|
|
113
|
+
) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (tool.type === "namespace" && Array.isArray(tool.tools)) pending.push(tool.tools);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function isToolIdentity(value: Record<string, unknown>): boolean {
|
|
123
|
+
return value.type === "function"
|
|
124
|
+
|| value.type === "custom"
|
|
125
|
+
|| value.type === "function_call"
|
|
126
|
+
|| value.type === "custom_tool_call";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isOptimizedToolIdentity(value: unknown): boolean {
|
|
130
|
+
if (!isPlainObject(value)) return false;
|
|
131
|
+
if (
|
|
132
|
+
isToolIdentity(value)
|
|
133
|
+
&& (
|
|
134
|
+
value.namespace === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
135
|
+
|| (
|
|
136
|
+
typeof value.name === "string"
|
|
137
|
+
&& (
|
|
138
|
+
value.name === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
139
|
+
|| value.name.startsWith(PLAINTEXT_V2_COLLABORATION_NAME_PREFIX)
|
|
140
|
+
|| value.name.startsWith(PLAINTEXT_V2_COLLABORATION_DOTTED_NAME_PREFIX)
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
return value.type === "namespace" && value.name === PLAINTEXT_V2_COLLABORATION_NAMESPACE;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function hasOptimizedReferenceConflict(body: Record<string, unknown>): boolean {
|
|
151
|
+
if (isOptimizedToolIdentity(body.tool_choice)) return true;
|
|
152
|
+
if (
|
|
153
|
+
isPlainObject(body.tool_choice)
|
|
154
|
+
&& Array.isArray(body.tool_choice.tools)
|
|
155
|
+
&& body.tool_choice.tools.some(isOptimizedToolIdentity)
|
|
156
|
+
) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
if (!Array.isArray(body.input)) return false;
|
|
160
|
+
return body.input.some(item => (
|
|
161
|
+
isPlainObject(item)
|
|
162
|
+
&& (item.type === "function_call" || item.type === "custom_tool_call")
|
|
163
|
+
&& isOptimizedToolIdentity(item)
|
|
164
|
+
));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function hasToolSearchCollaborationConflict(body: Record<string, unknown>): boolean {
|
|
168
|
+
if (!Array.isArray(body.input)) return false;
|
|
169
|
+
for (const item of body.input) {
|
|
170
|
+
if (!isPlainObject(item) || item.type !== "tool_search_output" || !Array.isArray(item.tools)) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const pending = [item.tools];
|
|
174
|
+
while (pending.length > 0) {
|
|
175
|
+
const tools = pending.pop()!;
|
|
176
|
+
for (const tool of tools) {
|
|
177
|
+
if (!isPlainObject(tool)) continue;
|
|
178
|
+
if (
|
|
179
|
+
typeof tool.name === "string"
|
|
180
|
+
&& (tool.name === COLLABORATION_NAMESPACE
|
|
181
|
+
|| tool.name === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
182
|
+
|| tool.name.startsWith(COLLABORATION_NAME_PREFIX)
|
|
183
|
+
|| tool.name.startsWith(COLLABORATION_DOTTED_NAME_PREFIX)
|
|
184
|
+
|| tool.name.startsWith(PLAINTEXT_V2_COLLABORATION_NAME_PREFIX)
|
|
185
|
+
|| tool.name.startsWith(PLAINTEXT_V2_COLLABORATION_DOTTED_NAME_PREFIX))
|
|
186
|
+
) {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
if (tool.type === "namespace" && Array.isArray(tool.tools)) pending.push(tool.tools);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function hasAgentMessageEncryptionMarker(tool: Record<string, unknown>): boolean {
|
|
197
|
+
return tool.type === "function"
|
|
198
|
+
&& typeof tool.name === "string"
|
|
199
|
+
&& PLAINTEXT_V2_AGENT_MESSAGE_TOOLS.has(tool.name)
|
|
200
|
+
&& isPlainObject(tool.parameters)
|
|
201
|
+
&& isPlainObject(tool.parameters.properties)
|
|
202
|
+
&& isPlainObject(tool.parameters.properties.message)
|
|
203
|
+
&& tool.parameters.properties.message.encrypted === true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function rewriteAgentMessageToolDeclaration(tool: Record<string, unknown>): Record<string, unknown> {
|
|
207
|
+
const alias = tool.type === "function" && typeof tool.name === "string"
|
|
208
|
+
? PLAINTEXT_V2_AGENT_MESSAGE_TOOL_ALIASES.get(tool.name)
|
|
209
|
+
: undefined;
|
|
210
|
+
if (!alias) return tool;
|
|
211
|
+
|
|
212
|
+
let rewritten: Record<string, unknown> = { ...tool, name: alias };
|
|
213
|
+
if (
|
|
214
|
+
hasAgentMessageEncryptionMarker(tool)
|
|
215
|
+
&& isPlainObject(tool.parameters)
|
|
216
|
+
&& isPlainObject(tool.parameters.properties)
|
|
217
|
+
&& isPlainObject(tool.parameters.properties.message)
|
|
218
|
+
) {
|
|
219
|
+
const { encrypted: _encrypted, ...messageSchema } = tool.parameters.properties.message;
|
|
220
|
+
rewritten = {
|
|
221
|
+
...rewritten,
|
|
222
|
+
parameters: {
|
|
223
|
+
...tool.parameters,
|
|
224
|
+
properties: {
|
|
225
|
+
...tool.parameters.properties,
|
|
226
|
+
message: messageSchema,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
return rewritten;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function hasPrivateToolName(name: string): boolean {
|
|
235
|
+
return name === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
236
|
+
|| name.startsWith(PLAINTEXT_V2_COLLABORATION_NAME_PREFIX)
|
|
237
|
+
|| name.startsWith(PLAINTEXT_V2_COLLABORATION_DOTTED_NAME_PREFIX)
|
|
238
|
+
|| PLAINTEXT_V2_AGENT_MESSAGE_TOOL_NAMES.has(name.split(/__|\./).at(-1)!);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function hasAgentMessageToolAliasCatalogConflict(
|
|
242
|
+
body: Record<string, unknown>,
|
|
243
|
+
catalogs: readonly unknown[][],
|
|
244
|
+
): boolean {
|
|
245
|
+
const pending = [...catalogs];
|
|
246
|
+
if (Array.isArray(body.input)) {
|
|
247
|
+
for (const item of body.input) {
|
|
248
|
+
if (
|
|
249
|
+
isPlainObject(item)
|
|
250
|
+
&& item.type === "tool_search_output"
|
|
251
|
+
&& Array.isArray(item.tools)
|
|
252
|
+
) {
|
|
253
|
+
pending.push(item.tools);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
while (pending.length > 0) {
|
|
258
|
+
const tools = pending.pop()!;
|
|
259
|
+
for (const tool of tools) {
|
|
260
|
+
if (!isPlainObject(tool)) continue;
|
|
261
|
+
if (
|
|
262
|
+
typeof tool.name === "string"
|
|
263
|
+
&& hasPrivateToolName(tool.name)
|
|
264
|
+
) {
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
if (tool.type === "namespace" && Array.isArray(tool.tools)) pending.push(tool.tools);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function hasAgentMessageToolAliasReference(value: unknown): boolean {
|
|
274
|
+
if (!isPlainObject(value) || !isToolIdentity(value) || typeof value.name !== "string") {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
if (hasPrivateToolName(value.name)) return true;
|
|
278
|
+
for (const prefix of [COLLABORATION_NAME_PREFIX, COLLABORATION_DOTTED_NAME_PREFIX]) {
|
|
279
|
+
if (
|
|
280
|
+
value.name.startsWith(prefix)
|
|
281
|
+
&& PLAINTEXT_V2_AGENT_MESSAGE_TOOL_NAMES.has(value.name.slice(prefix.length))
|
|
282
|
+
) {
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function hasAgentMessageToolAliasReferenceConflict(body: Record<string, unknown>): boolean {
|
|
290
|
+
if (hasAgentMessageToolAliasReference(body.tool_choice)) return true;
|
|
291
|
+
if (
|
|
292
|
+
isPlainObject(body.tool_choice)
|
|
293
|
+
&& Array.isArray(body.tool_choice.tools)
|
|
294
|
+
&& body.tool_choice.tools.some(hasAgentMessageToolAliasReference)
|
|
295
|
+
) {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
if (!Array.isArray(body.input)) return false;
|
|
299
|
+
return body.input.some(item => (
|
|
300
|
+
isPlainObject(item)
|
|
301
|
+
&& (item.type === "function_call" || item.type === "custom_tool_call")
|
|
302
|
+
&& hasAgentMessageToolAliasReference(item)
|
|
303
|
+
));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function hasFlattenedCollaborationDeclarationConflict(
|
|
307
|
+
catalogs: readonly unknown[][],
|
|
308
|
+
collaborationToolNames: ReadonlySet<string>,
|
|
309
|
+
): boolean {
|
|
310
|
+
const qualifiedNames = new Set(
|
|
311
|
+
[...collaborationToolNames].flatMap(name => [
|
|
312
|
+
`${COLLABORATION_NAME_PREFIX}${name}`,
|
|
313
|
+
`${COLLABORATION_DOTTED_NAME_PREFIX}${name}`,
|
|
314
|
+
]),
|
|
315
|
+
);
|
|
316
|
+
const pending = catalogs.map(tools => ({ tools, collaborationNamespace: false }));
|
|
317
|
+
while (pending.length > 0) {
|
|
318
|
+
const { tools, collaborationNamespace } = pending.pop()!;
|
|
319
|
+
for (const tool of tools) {
|
|
320
|
+
if (!isPlainObject(tool)) continue;
|
|
321
|
+
if (
|
|
322
|
+
!collaborationNamespace
|
|
323
|
+
&& (tool.type === "function" || tool.type === "custom")
|
|
324
|
+
&& typeof tool.name === "string"
|
|
325
|
+
&& qualifiedNames.has(tool.name)
|
|
326
|
+
) {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
if (tool.type === "namespace" && Array.isArray(tool.tools)) {
|
|
330
|
+
pending.push({
|
|
331
|
+
tools: tool.tools,
|
|
332
|
+
collaborationNamespace: tool.name === COLLABORATION_NAMESPACE,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function rewriteToolCatalog(tools: unknown[]): {
|
|
341
|
+
tools: unknown[];
|
|
342
|
+
namespaceAliased: boolean;
|
|
343
|
+
} {
|
|
344
|
+
let namespaceAliased = false;
|
|
345
|
+
let changed = false;
|
|
346
|
+
const rewritten = tools.map(tool => {
|
|
347
|
+
if (
|
|
348
|
+
!isPlainObject(tool)
|
|
349
|
+
|| tool.type !== "namespace"
|
|
350
|
+
|| tool.name !== COLLABORATION_NAMESPACE
|
|
351
|
+
|| !Array.isArray(tool.tools)
|
|
352
|
+
) {
|
|
353
|
+
return tool;
|
|
354
|
+
}
|
|
355
|
+
const childTools = tool.tools.map(child => (
|
|
356
|
+
isPlainObject(child) ? rewriteAgentMessageToolDeclaration(child) : child
|
|
357
|
+
));
|
|
358
|
+
namespaceAliased = true;
|
|
359
|
+
changed = true;
|
|
360
|
+
return {
|
|
361
|
+
...tool,
|
|
362
|
+
name: PLAINTEXT_V2_COLLABORATION_NAMESPACE,
|
|
363
|
+
tools: childTools,
|
|
364
|
+
};
|
|
365
|
+
});
|
|
366
|
+
return { tools: changed ? rewritten : tools, namespaceAliased };
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function aliasCollaborationReference(
|
|
370
|
+
value: unknown,
|
|
371
|
+
collaborationToolNames: ReadonlySet<string>,
|
|
372
|
+
): unknown {
|
|
373
|
+
if (!isPlainObject(value)) return value;
|
|
374
|
+
const type = value.type;
|
|
375
|
+
const canCarryNamespace = isToolIdentity(value);
|
|
376
|
+
if (canCarryNamespace && value.namespace !== undefined && value.namespace !== COLLABORATION_NAMESPACE) return value;
|
|
377
|
+
let rewritten = value;
|
|
378
|
+
if (canCarryNamespace && value.namespace === COLLABORATION_NAMESPACE) {
|
|
379
|
+
const name = (type === "function" || type === "function_call") && typeof value.name === "string"
|
|
380
|
+
? PLAINTEXT_V2_AGENT_MESSAGE_TOOL_ALIASES.get(value.name) ?? value.name
|
|
381
|
+
: value.name;
|
|
382
|
+
rewritten = { ...rewritten, namespace: PLAINTEXT_V2_COLLABORATION_NAMESPACE, name };
|
|
383
|
+
}
|
|
384
|
+
if (type === "namespace" && value.name === COLLABORATION_NAMESPACE) {
|
|
385
|
+
rewritten = { ...rewritten, name: PLAINTEXT_V2_COLLABORATION_NAMESPACE };
|
|
386
|
+
} else if (
|
|
387
|
+
canCarryNamespace
|
|
388
|
+
&& typeof value.name === "string"
|
|
389
|
+
&& value.name.startsWith(COLLABORATION_NAME_PREFIX)
|
|
390
|
+
&& collaborationToolNames.has(value.name.slice(COLLABORATION_NAME_PREFIX.length))
|
|
391
|
+
) {
|
|
392
|
+
const childName = value.name.slice(COLLABORATION_NAME_PREFIX.length);
|
|
393
|
+
rewritten = {
|
|
394
|
+
...rewritten,
|
|
395
|
+
name: `${PLAINTEXT_V2_COLLABORATION_NAME_PREFIX}${
|
|
396
|
+
(type === "function" || type === "function_call")
|
|
397
|
+
? PLAINTEXT_V2_AGENT_MESSAGE_TOOL_ALIASES.get(childName) ?? childName
|
|
398
|
+
: childName
|
|
399
|
+
}`,
|
|
400
|
+
};
|
|
401
|
+
} else if (
|
|
402
|
+
canCarryNamespace
|
|
403
|
+
&& typeof value.name === "string"
|
|
404
|
+
&& value.name.startsWith(COLLABORATION_DOTTED_NAME_PREFIX)
|
|
405
|
+
&& collaborationToolNames.has(value.name.slice(COLLABORATION_DOTTED_NAME_PREFIX.length))
|
|
406
|
+
) {
|
|
407
|
+
const childName = value.name.slice(COLLABORATION_DOTTED_NAME_PREFIX.length);
|
|
408
|
+
rewritten = {
|
|
409
|
+
...rewritten,
|
|
410
|
+
name: `${PLAINTEXT_V2_COLLABORATION_DOTTED_NAME_PREFIX}${
|
|
411
|
+
(type === "function" || type === "function_call")
|
|
412
|
+
? PLAINTEXT_V2_AGENT_MESSAGE_TOOL_ALIASES.get(childName) ?? childName
|
|
413
|
+
: childName
|
|
414
|
+
}`,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
return rewritten;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function aliasCollaborationToolChoice(
|
|
421
|
+
toolChoice: unknown,
|
|
422
|
+
collaborationToolNames: ReadonlySet<string>,
|
|
423
|
+
): unknown {
|
|
424
|
+
if (!isPlainObject(toolChoice)) return toolChoice;
|
|
425
|
+
let rewritten = aliasCollaborationReference(
|
|
426
|
+
toolChoice,
|
|
427
|
+
collaborationToolNames,
|
|
428
|
+
) as Record<string, unknown>;
|
|
429
|
+
if (!Array.isArray(toolChoice.tools)) return rewritten;
|
|
430
|
+
let toolsChanged = false;
|
|
431
|
+
const tools = toolChoice.tools.map(tool => {
|
|
432
|
+
const aliased = aliasCollaborationReference(tool, collaborationToolNames);
|
|
433
|
+
toolsChanged ||= aliased !== tool;
|
|
434
|
+
return aliased;
|
|
435
|
+
});
|
|
436
|
+
if (toolsChanged) rewritten = { ...rewritten, tools };
|
|
437
|
+
return rewritten;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Prepare v2 collaboration tools for plaintext messages on the canonical ChatGPT wire.
|
|
442
|
+
*
|
|
443
|
+
* ChatGPT reserves both `collaboration` and the three message-tool names. The request therefore
|
|
444
|
+
* uses fixed, request-scoped aliases for both, then restores every identity before Codex sees it.
|
|
445
|
+
*/
|
|
446
|
+
export function preparePlaintextV2AgentMessages(body: unknown): {
|
|
447
|
+
body: unknown;
|
|
448
|
+
namespaceAliased: boolean;
|
|
449
|
+
toolNames: ReadonlySet<string>;
|
|
450
|
+
aliasedAgentMessageToolNames: ReadonlySet<string>;
|
|
451
|
+
} {
|
|
452
|
+
if (!isPlainObject(body)) {
|
|
453
|
+
return {
|
|
454
|
+
body,
|
|
455
|
+
namespaceAliased: false,
|
|
456
|
+
toolNames: new Set(),
|
|
457
|
+
aliasedAgentMessageToolNames: new Set(),
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
const catalogs = responseToolCatalogs(body);
|
|
461
|
+
const catalogInfo = collaborationCatalogInfo(catalogs);
|
|
462
|
+
if (
|
|
463
|
+
!hasPlaintextV2CollaborationCatalog(body)
|
|
464
|
+
|| hasOptimizedNamespaceConflict(catalogs)
|
|
465
|
+
|| hasOptimizedReferenceConflict(body)
|
|
466
|
+
|| hasToolSearchCollaborationConflict(body)
|
|
467
|
+
|| hasFlattenedCollaborationDeclarationConflict(catalogs, catalogInfo.toolNames)
|
|
468
|
+
|| hasAgentMessageToolAliasCatalogConflict(body, catalogs)
|
|
469
|
+
|| hasAgentMessageToolAliasReferenceConflict(body)
|
|
470
|
+
) {
|
|
471
|
+
return {
|
|
472
|
+
body,
|
|
473
|
+
namespaceAliased: false,
|
|
474
|
+
toolNames: new Set(),
|
|
475
|
+
aliasedAgentMessageToolNames: new Set(),
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
let namespaceAliased = false;
|
|
480
|
+
let tools = body.tools;
|
|
481
|
+
if (Array.isArray(body.tools)) {
|
|
482
|
+
const rewritten = rewriteToolCatalog(body.tools);
|
|
483
|
+
tools = rewritten.tools;
|
|
484
|
+
namespaceAliased ||= rewritten.namespaceAliased;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
let input = body.input;
|
|
488
|
+
if (Array.isArray(body.input)) {
|
|
489
|
+
let inputChanged = false;
|
|
490
|
+
const rewrittenInput = body.input.map(item => {
|
|
491
|
+
if (
|
|
492
|
+
!isPlainObject(item)
|
|
493
|
+
|| item.type !== "additional_tools"
|
|
494
|
+
|| !Array.isArray(item.tools)
|
|
495
|
+
) {
|
|
496
|
+
return item;
|
|
497
|
+
}
|
|
498
|
+
const rewritten = rewriteToolCatalog(item.tools);
|
|
499
|
+
namespaceAliased ||= rewritten.namespaceAliased;
|
|
500
|
+
if (rewritten.tools === item.tools) return item;
|
|
501
|
+
inputChanged = true;
|
|
502
|
+
return { ...item, tools: rewritten.tools };
|
|
503
|
+
});
|
|
504
|
+
if (inputChanged) input = rewrittenInput;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
let toolChoice = body.tool_choice;
|
|
508
|
+
if (namespaceAliased) {
|
|
509
|
+
toolChoice = aliasCollaborationToolChoice(body.tool_choice, catalogInfo.toolNames);
|
|
510
|
+
if (Array.isArray(input)) {
|
|
511
|
+
let inputChanged = false;
|
|
512
|
+
const aliasedInput = input.map(item => {
|
|
513
|
+
if (!isPlainObject(item)) return item;
|
|
514
|
+
if (item.type !== "function_call" && item.type !== "custom_tool_call") return item;
|
|
515
|
+
const aliased = aliasCollaborationReference(item, catalogInfo.toolNames);
|
|
516
|
+
inputChanged ||= aliased !== item;
|
|
517
|
+
return aliased;
|
|
518
|
+
});
|
|
519
|
+
if (inputChanged) input = aliasedInput;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (!namespaceAliased || (tools === body.tools && input === body.input && toolChoice === body.tool_choice)) {
|
|
524
|
+
return {
|
|
525
|
+
body,
|
|
526
|
+
namespaceAliased: false,
|
|
527
|
+
toolNames: new Set(),
|
|
528
|
+
aliasedAgentMessageToolNames: new Set(),
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
body: {
|
|
533
|
+
...body,
|
|
534
|
+
...(tools !== body.tools ? { tools } : {}),
|
|
535
|
+
...(input !== body.input ? { input } : {}),
|
|
536
|
+
...(toolChoice !== body.tool_choice ? { tool_choice: toolChoice } : {}),
|
|
537
|
+
},
|
|
538
|
+
namespaceAliased,
|
|
539
|
+
toolNames: new Set(catalogInfo.toolNames),
|
|
540
|
+
aliasedAgentMessageToolNames: new Set(catalogInfo.aliasedAgentMessageToolNames),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const MAX_RESTORED_TOOL_IDENTITIES = 10_000;
|
|
545
|
+
export const PLAINTEXT_V2_AGENT_MESSAGE_RESTORE_OVERFLOW_MESSAGE =
|
|
546
|
+
"plaintext V2 agent-message response could not be restored within safe identity limits";
|
|
547
|
+
|
|
548
|
+
export class PlaintextV2AgentMessageRestoreOverflowError extends Error {
|
|
549
|
+
constructor() {
|
|
550
|
+
super(PLAINTEXT_V2_AGENT_MESSAGE_RESTORE_OVERFLOW_MESSAGE);
|
|
551
|
+
this.name = "PlaintextV2AgentMessageRestoreOverflowError";
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
type RestoreOutcome = {
|
|
556
|
+
value: unknown;
|
|
557
|
+
changed: boolean;
|
|
558
|
+
overflow: boolean;
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
type RestoreContext = {
|
|
562
|
+
toolNames: ReadonlySet<string>;
|
|
563
|
+
aliasedAgentMessageToolNames: ReadonlySet<string>;
|
|
564
|
+
remainingIdentities: number;
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
const unchanged = (value: unknown): RestoreOutcome => ({ value, changed: false, overflow: false });
|
|
568
|
+
|
|
569
|
+
function reserveIdentities(context: RestoreContext, count: number): boolean {
|
|
570
|
+
if (count > context.remainingIdentities) return false;
|
|
571
|
+
context.remainingIdentities -= count;
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function declaredChildName(
|
|
576
|
+
name: unknown,
|
|
577
|
+
toolNames: ReadonlySet<string>,
|
|
578
|
+
aliasedAgentMessageToolNames: ReadonlySet<string>,
|
|
579
|
+
allowAgentMessageAlias: boolean,
|
|
580
|
+
): string | undefined {
|
|
581
|
+
if (typeof name !== "string") return undefined;
|
|
582
|
+
if (allowAgentMessageAlias) {
|
|
583
|
+
const restoredName = PLAINTEXT_V2_AGENT_MESSAGE_TOOL_NAMES.get(name);
|
|
584
|
+
if (restoredName) {
|
|
585
|
+
return aliasedAgentMessageToolNames.has(restoredName) && toolNames.has(restoredName)
|
|
586
|
+
? restoredName
|
|
587
|
+
: undefined;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (toolNames.has(name)) return name;
|
|
591
|
+
for (const prefix of [
|
|
592
|
+
PLAINTEXT_V2_COLLABORATION_NAME_PREFIX,
|
|
593
|
+
PLAINTEXT_V2_COLLABORATION_DOTTED_NAME_PREFIX,
|
|
594
|
+
]) {
|
|
595
|
+
if (!name.startsWith(prefix)) continue;
|
|
596
|
+
const childName = name.slice(prefix.length);
|
|
597
|
+
const restoredAlias = allowAgentMessageAlias
|
|
598
|
+
? PLAINTEXT_V2_AGENT_MESSAGE_TOOL_NAMES.get(childName)
|
|
599
|
+
: undefined;
|
|
600
|
+
if (restoredAlias && !aliasedAgentMessageToolNames.has(restoredAlias)) return undefined;
|
|
601
|
+
const restoredChildName = restoredAlias ?? childName;
|
|
602
|
+
return toolNames.has(restoredChildName) ? restoredChildName : undefined;
|
|
603
|
+
}
|
|
604
|
+
return undefined;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function restoreToolIdentity(
|
|
608
|
+
value: unknown,
|
|
609
|
+
context: RestoreContext,
|
|
610
|
+
allowNamespaceDeclaration = false,
|
|
611
|
+
namespaceMember = false,
|
|
612
|
+
): RestoreOutcome {
|
|
613
|
+
if (!isPlainObject(value)) return unchanged(value);
|
|
614
|
+
if (!reserveIdentities(context, 1)) return { ...unchanged(value), overflow: true };
|
|
615
|
+
|
|
616
|
+
if (
|
|
617
|
+
allowNamespaceDeclaration
|
|
618
|
+
&& value.type === "namespace"
|
|
619
|
+
&& value.name === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
620
|
+
) {
|
|
621
|
+
if (value.tools !== undefined && !Array.isArray(value.tools)) return { ...unchanged(value), overflow: true };
|
|
622
|
+
const children = restoreIdentityList(value.tools, context, false, true);
|
|
623
|
+
if (children.overflow) return { ...unchanged(value), overflow: true };
|
|
624
|
+
return {
|
|
625
|
+
value: {
|
|
626
|
+
...value,
|
|
627
|
+
name: COLLABORATION_NAMESPACE,
|
|
628
|
+
...(children.changed ? { tools: children.value } : {}),
|
|
629
|
+
},
|
|
630
|
+
changed: true,
|
|
631
|
+
overflow: false,
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const identityType = value.type;
|
|
636
|
+
if (
|
|
637
|
+
identityType !== "function"
|
|
638
|
+
&& identityType !== "custom"
|
|
639
|
+
&& identityType !== "function_call"
|
|
640
|
+
&& identityType !== "custom_tool_call"
|
|
641
|
+
&& identityType !== "response.function_call_arguments.done"
|
|
642
|
+
) {
|
|
643
|
+
return unchanged(value);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if (value.namespace !== undefined && value.namespace !== null && typeof value.namespace !== "string") {
|
|
647
|
+
return { ...unchanged(value), overflow: true };
|
|
648
|
+
}
|
|
649
|
+
const allowAgentMessageAlias = (
|
|
650
|
+
identityType === "function"
|
|
651
|
+
|| identityType === "function_call"
|
|
652
|
+
|| identityType === "response.function_call_arguments.done"
|
|
653
|
+
) && (
|
|
654
|
+
value.namespace === undefined
|
|
655
|
+
|| value.namespace === null
|
|
656
|
+
|| value.namespace === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
657
|
+
);
|
|
658
|
+
if (value.namespace !== undefined && value.namespace !== null && value.namespace !== PLAINTEXT_V2_COLLABORATION_NAMESPACE) {
|
|
659
|
+
return unchanged(value);
|
|
660
|
+
}
|
|
661
|
+
const childName = declaredChildName(
|
|
662
|
+
value.name,
|
|
663
|
+
context.toolNames,
|
|
664
|
+
context.aliasedAgentMessageToolNames,
|
|
665
|
+
allowAgentMessageAlias,
|
|
666
|
+
);
|
|
667
|
+
if (!childName) {
|
|
668
|
+
const privateIdentity = value.namespace === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
669
|
+
|| (typeof value.name === "string" && hasPrivateToolName(value.name));
|
|
670
|
+
return { ...unchanged(value), overflow: privateIdentity };
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const privateIdentity = value.namespace === PLAINTEXT_V2_COLLABORATION_NAMESPACE
|
|
674
|
+
|| (typeof value.name === "string" && hasPrivateToolName(value.name));
|
|
675
|
+
if (!privateIdentity) return unchanged(value);
|
|
676
|
+
// Codex dispatches by the namespace/name pair; qualified names are literal
|
|
677
|
+
// names there. Only namespace member declarations inherit their container.
|
|
678
|
+
return {
|
|
679
|
+
value: {
|
|
680
|
+
...value,
|
|
681
|
+
name: childName,
|
|
682
|
+
...(!namespaceMember || value.namespace !== undefined ? { namespace: COLLABORATION_NAMESPACE } : {}),
|
|
683
|
+
},
|
|
684
|
+
changed: true,
|
|
685
|
+
overflow: false,
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
function restoreIdentityList(
|
|
690
|
+
values: unknown,
|
|
691
|
+
context: RestoreContext,
|
|
692
|
+
allowNamespaceDeclaration: boolean,
|
|
693
|
+
namespaceMember = false,
|
|
694
|
+
): RestoreOutcome {
|
|
695
|
+
if (!Array.isArray(values)) return unchanged(values);
|
|
696
|
+
if (values.length > context.remainingIdentities) {
|
|
697
|
+
return { ...unchanged(values), overflow: true };
|
|
698
|
+
}
|
|
699
|
+
let restored: unknown[] | undefined;
|
|
700
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
701
|
+
const result = restoreToolIdentity(values[index], context, allowNamespaceDeclaration, namespaceMember);
|
|
702
|
+
if (result.overflow) return { ...unchanged(values), overflow: true };
|
|
703
|
+
if (!result.changed) continue;
|
|
704
|
+
restored ??= values.slice();
|
|
705
|
+
restored[index] = result.value;
|
|
706
|
+
}
|
|
707
|
+
return restored
|
|
708
|
+
? { value: restored, changed: true, overflow: false }
|
|
709
|
+
: unchanged(values);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function restoreToolChoice(value: unknown, context: RestoreContext): RestoreOutcome {
|
|
713
|
+
if (isPlainObject(value) && value.tools !== undefined && !Array.isArray(value.tools)) {
|
|
714
|
+
return { ...unchanged(value), overflow: true };
|
|
715
|
+
}
|
|
716
|
+
const direct = restoreToolIdentity(value, context, true);
|
|
717
|
+
if (direct.overflow || !isPlainObject(value) || !Array.isArray(value.tools)) return direct;
|
|
718
|
+
const tools = restoreIdentityList(value.tools, context, true);
|
|
719
|
+
if (tools.overflow) return { ...unchanged(value), overflow: true };
|
|
720
|
+
if (!tools.changed) return direct;
|
|
721
|
+
const base = direct.value as Record<string, unknown>;
|
|
722
|
+
return { value: { ...base, tools: tools.value }, changed: true, overflow: false };
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function restoreResponseSnapshot(value: unknown, context: RestoreContext): RestoreOutcome {
|
|
726
|
+
if (!isPlainObject(value)) return unchanged(value);
|
|
727
|
+
if ((value.output !== undefined && !Array.isArray(value.output))
|
|
728
|
+
|| (value.tools !== undefined && !Array.isArray(value.tools))) {
|
|
729
|
+
return { ...unchanged(value), overflow: true };
|
|
730
|
+
}
|
|
731
|
+
const output = restoreIdentityList(value.output, context, false);
|
|
732
|
+
if (output.overflow) return { ...unchanged(value), overflow: true };
|
|
733
|
+
const tools = restoreIdentityList(value.tools, context, true);
|
|
734
|
+
if (tools.overflow) return { ...unchanged(value), overflow: true };
|
|
735
|
+
const toolChoice = restoreToolChoice(value.tool_choice, context);
|
|
736
|
+
if (toolChoice.overflow) return { ...unchanged(value), overflow: true };
|
|
737
|
+
if (!output.changed && !tools.changed && !toolChoice.changed) return unchanged(value);
|
|
738
|
+
return {
|
|
739
|
+
value: {
|
|
740
|
+
...value,
|
|
741
|
+
...(output.changed ? { output: output.value } : {}),
|
|
742
|
+
...(tools.changed ? { tools: tools.value } : {}),
|
|
743
|
+
...(toolChoice.changed ? { tool_choice: toolChoice.value } : {}),
|
|
744
|
+
},
|
|
745
|
+
changed: true,
|
|
746
|
+
overflow: false,
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Restore request-scoped collaboration aliases only at documented Responses identity positions.
|
|
752
|
+
* Tool arguments, tool results, and extension metadata are deliberately opaque.
|
|
753
|
+
*/
|
|
754
|
+
export function restorePlaintextV2AgentMessageCalls(
|
|
755
|
+
value: unknown,
|
|
756
|
+
toolNames: ReadonlySet<string>,
|
|
757
|
+
aliasedAgentMessageToolNames: ReadonlySet<string> = toolNames,
|
|
758
|
+
): { value: unknown; changed: boolean; overflowed: boolean } {
|
|
759
|
+
if (toolNames.size === 0 || !isPlainObject(value)) {
|
|
760
|
+
return { value, changed: false, overflowed: false };
|
|
761
|
+
}
|
|
762
|
+
const context: RestoreContext = {
|
|
763
|
+
toolNames,
|
|
764
|
+
aliasedAgentMessageToolNames,
|
|
765
|
+
remainingIdentities: MAX_RESTORED_TOOL_IDENTITIES,
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
const rootIdentity = restoreToolIdentity(value, context);
|
|
769
|
+
if (rootIdentity.overflow) return { value, changed: false, overflowed: true };
|
|
770
|
+
const root = rootIdentity.value as Record<string, unknown>;
|
|
771
|
+
const item = restoreToolIdentity(root.item, context);
|
|
772
|
+
if (item.overflow) return { value, changed: false, overflowed: true };
|
|
773
|
+
const response = restoreResponseSnapshot(root.response, context);
|
|
774
|
+
if (response.overflow) return { value, changed: false, overflowed: true };
|
|
775
|
+
const snapshot = restoreResponseSnapshot(root, context);
|
|
776
|
+
if (snapshot.overflow) return { value, changed: false, overflowed: true };
|
|
777
|
+
|
|
778
|
+
let restored = snapshot.value as Record<string, unknown>;
|
|
779
|
+
let changed = rootIdentity.changed || snapshot.changed;
|
|
780
|
+
if (item.changed) {
|
|
781
|
+
restored = { ...restored, item: item.value };
|
|
782
|
+
changed = true;
|
|
783
|
+
}
|
|
784
|
+
if (response.changed) {
|
|
785
|
+
restored = { ...restored, response: response.value };
|
|
786
|
+
changed = true;
|
|
787
|
+
}
|
|
788
|
+
return changed
|
|
789
|
+
? { value: restored, changed: true, overflowed: false }
|
|
790
|
+
: { value, changed: false, overflowed: false };
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
export function restorePlaintextV2AgentMessageCallsInJsonResult(
|
|
794
|
+
payload: string,
|
|
795
|
+
toolNames: ReadonlySet<string>,
|
|
796
|
+
aliasedAgentMessageToolNames: ReadonlySet<string> = toolNames,
|
|
797
|
+
): { value: string; changed: boolean; overflowed: boolean } {
|
|
798
|
+
if (toolNames.size === 0 || payload === "[DONE]") {
|
|
799
|
+
return { value: payload, changed: false, overflowed: false };
|
|
800
|
+
}
|
|
801
|
+
let value: unknown;
|
|
802
|
+
try {
|
|
803
|
+
value = JSON.parse(payload);
|
|
804
|
+
} catch {
|
|
805
|
+
return { value: payload, changed: false, overflowed: true };
|
|
806
|
+
}
|
|
807
|
+
if (!isPlainObject(value)) return { value: payload, changed: false, overflowed: true };
|
|
808
|
+
const restored = restorePlaintextV2AgentMessageCalls(
|
|
809
|
+
value,
|
|
810
|
+
toolNames,
|
|
811
|
+
aliasedAgentMessageToolNames,
|
|
812
|
+
);
|
|
813
|
+
if (restored.overflowed) return { value: payload, changed: false, overflowed: true };
|
|
814
|
+
return restored.changed
|
|
815
|
+
? { value: JSON.stringify(restored.value), changed: true, overflowed: false }
|
|
816
|
+
: { value: payload, changed: false, overflowed: false };
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
export function restorePlaintextV2AgentMessageCallsInJson(
|
|
820
|
+
payload: string,
|
|
821
|
+
toolNames: ReadonlySet<string>,
|
|
822
|
+
aliasedAgentMessageToolNames: ReadonlySet<string> = toolNames,
|
|
823
|
+
): string {
|
|
824
|
+
const restored = restorePlaintextV2AgentMessageCallsInJsonResult(
|
|
825
|
+
payload,
|
|
826
|
+
toolNames,
|
|
827
|
+
aliasedAgentMessageToolNames,
|
|
828
|
+
);
|
|
829
|
+
if (restored.overflowed) throw new PlaintextV2AgentMessageRestoreOverflowError();
|
|
830
|
+
return restored.value;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
export function createPlaintextV2AgentMessageCallRestoreRewrite(
|
|
834
|
+
toolNames: ReadonlySet<string>,
|
|
835
|
+
aliasedAgentMessageToolNames: ReadonlySet<string> = toolNames,
|
|
836
|
+
): (payload: string) => string {
|
|
837
|
+
type Binding = { namespace: string; name: string; keys: Set<string> };
|
|
838
|
+
const bindings = new Map<string, Binding>();
|
|
839
|
+
let refused = false;
|
|
840
|
+
return payload => {
|
|
841
|
+
if (refused) throw new PlaintextV2AgentMessageRestoreOverflowError();
|
|
842
|
+
try {
|
|
843
|
+
const restored = restorePlaintextV2AgentMessageCallsInJson(payload, toolNames, aliasedAgentMessageToolNames);
|
|
844
|
+
if (payload === "[DONE]" || toolNames.size === 0) return restored;
|
|
845
|
+
const value = JSON.parse(restored) as Record<string, unknown>;
|
|
846
|
+
const bind = (item: unknown, outputIndex?: unknown): void => {
|
|
847
|
+
if (!isPlainObject(item) || typeof item.name !== "string") return;
|
|
848
|
+
if (item.type !== "function_call" && item.type !== "response.function_call_arguments.done") return;
|
|
849
|
+
let namespace = typeof item.namespace === "string" ? item.namespace : "";
|
|
850
|
+
let name = item.name;
|
|
851
|
+
for (const separator of ["__", "."]) {
|
|
852
|
+
const prefix = `${COLLABORATION_NAMESPACE}${separator}`;
|
|
853
|
+
if (name.startsWith(prefix) && (!namespace || namespace === COLLABORATION_NAMESPACE)) {
|
|
854
|
+
namespace = COLLABORATION_NAMESPACE;
|
|
855
|
+
name = name.slice(prefix.length);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
const keys = [
|
|
859
|
+
typeof item.id === "string" ? `id:${item.id}` : undefined,
|
|
860
|
+
typeof item.item_id === "string" ? `id:${item.item_id}` : undefined,
|
|
861
|
+
typeof item.call_id === "string" ? `call:${item.call_id}` : undefined,
|
|
862
|
+
typeof outputIndex === "number" ? `index:${outputIndex}` : undefined,
|
|
863
|
+
].filter((key): key is string => key !== undefined);
|
|
864
|
+
const groups = [...new Set(keys.flatMap(key => {
|
|
865
|
+
const prior = bindings.get(key);
|
|
866
|
+
return prior ? [prior] : [];
|
|
867
|
+
}))];
|
|
868
|
+
for (const group of groups) {
|
|
869
|
+
if (group.name !== name || (group.namespace && namespace && group.namespace !== namespace)) {
|
|
870
|
+
throw new PlaintextV2AgentMessageRestoreOverflowError();
|
|
871
|
+
}
|
|
872
|
+
namespace ||= group.namespace;
|
|
873
|
+
}
|
|
874
|
+
// All coordinates for a call share the same refined identity, including
|
|
875
|
+
// coordinates omitted by this particular sparse event. Merge smaller groups
|
|
876
|
+
// into the largest to bound repeated cross-coordinate refinement work.
|
|
877
|
+
groups.sort((left, right) => right.keys.size - left.keys.size);
|
|
878
|
+
const binding: Binding = groups[0] ?? { namespace, name, keys: new Set() };
|
|
879
|
+
binding.namespace = namespace;
|
|
880
|
+
for (const group of groups.slice(1)) {
|
|
881
|
+
for (const key of group.keys) {
|
|
882
|
+
binding.keys.add(key);
|
|
883
|
+
bindings.set(key, binding);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
for (const key of keys) {
|
|
887
|
+
if (!bindings.has(key) && bindings.size >= MAX_RESTORED_TOOL_IDENTITIES) throw new PlaintextV2AgentMessageRestoreOverflowError();
|
|
888
|
+
binding.keys.add(key);
|
|
889
|
+
bindings.set(key, binding);
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
bind(value, value.output_index);
|
|
893
|
+
bind(value.item, value.output_index);
|
|
894
|
+
const response = isPlainObject(value.response) ? value.response : value;
|
|
895
|
+
if (Array.isArray(response.output)) response.output.forEach((item, index) => bind(item, index));
|
|
896
|
+
return restored;
|
|
897
|
+
} catch (error) {
|
|
898
|
+
refused = true;
|
|
899
|
+
throw error;
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
}
|