@gakr-gakr/codex 0.1.0 → 0.1.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.
Files changed (115) hide show
  1. package/dist/client-DNN2uyJW.js +642 -0
  2. package/dist/client-factory-Bu9OClHJ.js +9 -0
  3. package/dist/command-formatters-BpPOTePl.js +520 -0
  4. package/dist/command-handlers-BBs7Vws9.js +1533 -0
  5. package/dist/compact-CDboBy7o.js +329 -0
  6. package/dist/computer-use-DCZB46Sw.js +367 -0
  7. package/dist/config-CLMSw0p2.js +510 -0
  8. package/dist/doctor-contract-api.js +53 -0
  9. package/dist/harness.js +51 -0
  10. package/dist/index.js +1171 -0
  11. package/dist/media-understanding-provider.js +335 -0
  12. package/dist/models-jLA2SIvd.js +110 -0
  13. package/dist/node-cli-sessions-BLRDs_US.js +1216 -0
  14. package/dist/plugin-activation-CEy_oYpx.js +452 -0
  15. package/dist/prompt-overlay.js +12 -0
  16. package/dist/protocol-C9UWI98H.js +9 -0
  17. package/dist/protocol-validators-BGBspNmF.js +5988 -0
  18. package/dist/provider-catalog.js +84 -0
  19. package/dist/provider-discovery.js +33 -0
  20. package/dist/provider.js +150 -0
  21. package/dist/rate-limit-cache-9LxQdE0K.js +24 -0
  22. package/dist/request-DbSPeTcV.js +89 -0
  23. package/dist/rolldown-runtime-DUslC3ob.js +14 -0
  24. package/dist/run-attempt-BoEwzQCv.js +5463 -0
  25. package/dist/session-binding-e2GFp9VH.js +222 -0
  26. package/dist/shared-client-D7Vy0glq.js +631 -0
  27. package/dist/side-question-BDLuEzFP.js +668 -0
  28. package/dist/test-api.js +49 -0
  29. package/dist/thread-lifecycle-Clo0EHMk.js +1565 -0
  30. package/dist/vision-tools-Cofrv35p.js +1379 -0
  31. package/package.json +16 -1
  32. package/doctor-contract-api.ts +0 -68
  33. package/harness.ts +0 -72
  34. package/index.ts +0 -124
  35. package/media-understanding-provider.ts +0 -521
  36. package/prompt-overlay.ts +0 -21
  37. package/provider-catalog.ts +0 -83
  38. package/provider-discovery.ts +0 -45
  39. package/provider.ts +0 -243
  40. package/src/app-server/app-inventory-cache.ts +0 -324
  41. package/src/app-server/approval-bridge.ts +0 -1211
  42. package/src/app-server/auth-bridge.ts +0 -614
  43. package/src/app-server/capabilities.ts +0 -27
  44. package/src/app-server/client-factory.ts +0 -24
  45. package/src/app-server/client.ts +0 -715
  46. package/src/app-server/compact.ts +0 -512
  47. package/src/app-server/computer-use.ts +0 -683
  48. package/src/app-server/config.ts +0 -1038
  49. package/src/app-server/context-engine-projection.ts +0 -403
  50. package/src/app-server/dynamic-tool-diagnostics.ts +0 -73
  51. package/src/app-server/dynamic-tool-profile.ts +0 -70
  52. package/src/app-server/dynamic-tools.ts +0 -623
  53. package/src/app-server/elicitation-bridge.ts +0 -783
  54. package/src/app-server/event-projector.ts +0 -2065
  55. package/src/app-server/image-payload-sanitizer.ts +0 -167
  56. package/src/app-server/local-runtime-attribution.ts +0 -39
  57. package/src/app-server/managed-binary.ts +0 -193
  58. package/src/app-server/models.ts +0 -172
  59. package/src/app-server/native-hook-relay.ts +0 -150
  60. package/src/app-server/native-subagent-task-mirror.ts +0 -497
  61. package/src/app-server/plugin-activation.ts +0 -283
  62. package/src/app-server/plugin-app-cache-key.ts +0 -74
  63. package/src/app-server/plugin-approval-roundtrip.ts +0 -122
  64. package/src/app-server/plugin-inventory.ts +0 -357
  65. package/src/app-server/plugin-thread-config.ts +0 -455
  66. package/src/app-server/protocol-generated/json/DynamicToolCallParams.json +0 -33
  67. package/src/app-server/protocol-generated/json/v2/ErrorNotification.json +0 -199
  68. package/src/app-server/protocol-generated/json/v2/GetAccountResponse.json +0 -102
  69. package/src/app-server/protocol-generated/json/v2/ModelListResponse.json +0 -227
  70. package/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json +0 -2630
  71. package/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json +0 -2630
  72. package/src/app-server/protocol-generated/json/v2/TurnCompletedNotification.json +0 -1659
  73. package/src/app-server/protocol-generated/json/v2/TurnStartResponse.json +0 -1655
  74. package/src/app-server/protocol-validators.ts +0 -203
  75. package/src/app-server/protocol.ts +0 -520
  76. package/src/app-server/rate-limit-cache.ts +0 -48
  77. package/src/app-server/rate-limits.ts +0 -583
  78. package/src/app-server/request.ts +0 -73
  79. package/src/app-server/run-attempt.ts +0 -4862
  80. package/src/app-server/session-binding.ts +0 -398
  81. package/src/app-server/session-history.ts +0 -44
  82. package/src/app-server/shared-client.ts +0 -289
  83. package/src/app-server/side-question.ts +0 -1009
  84. package/src/app-server/test-support.ts +0 -48
  85. package/src/app-server/thread-lifecycle.ts +0 -959
  86. package/src/app-server/timeout.ts +0 -9
  87. package/src/app-server/tool-progress-normalization.ts +0 -77
  88. package/src/app-server/trajectory.ts +0 -368
  89. package/src/app-server/transcript-mirror.ts +0 -208
  90. package/src/app-server/transport-stdio.ts +0 -107
  91. package/src/app-server/transport-websocket.ts +0 -90
  92. package/src/app-server/transport.ts +0 -117
  93. package/src/app-server/user-input-bridge.ts +0 -316
  94. package/src/app-server/version.ts +0 -4
  95. package/src/app-server/vision-tools.ts +0 -12
  96. package/src/command-account.ts +0 -544
  97. package/src/command-formatters.ts +0 -426
  98. package/src/command-handlers.ts +0 -2021
  99. package/src/command-plugins-management.ts +0 -137
  100. package/src/command-rpc.ts +0 -142
  101. package/src/commands.ts +0 -65
  102. package/src/conversation-binding-data.ts +0 -124
  103. package/src/conversation-binding.ts +0 -561
  104. package/src/conversation-control.ts +0 -303
  105. package/src/conversation-turn-collector.ts +0 -186
  106. package/src/conversation-turn-input.ts +0 -106
  107. package/src/migration/apply.ts +0 -501
  108. package/src/migration/helpers.ts +0 -55
  109. package/src/migration/plan.ts +0 -461
  110. package/src/migration/provider.ts +0 -41
  111. package/src/migration/source.ts +0 -643
  112. package/src/migration/targets.ts +0 -25
  113. package/src/node-cli-sessions.ts +0 -711
  114. package/test-api.ts +0 -95
  115. package/tsconfig.json +0 -16
@@ -0,0 +1,1379 @@
1
+ import { t as isJsonObject } from "./protocol-C9UWI98H.js";
2
+ import { r as formatCodexDisplayText } from "./command-formatters-BpPOTePl.js";
3
+ import { createHash } from "node:crypto";
4
+ import { buildAgentHookContextChannelFields, callGatewayTool, embeddedAgentLog, formatApprovalDisplayPath, hasNativeHookRelayInvocation, invokeNativeHookRelay, runBeforeToolCallHook } from "autobot/plugin-sdk/agent-harness-runtime";
5
+ import { emitTrustedDiagnosticEvent } from "autobot/plugin-sdk/diagnostic-runtime";
6
+ //#region extensions/codex/src/app-server/plugin-approval-roundtrip.ts
7
+ const DEFAULT_CODEX_APPROVAL_TIMEOUT_MS = 12e4;
8
+ const MAX_PLUGIN_APPROVAL_TITLE_LENGTH = 80;
9
+ const MAX_PLUGIN_APPROVAL_DESCRIPTION_LENGTH = 256;
10
+ async function requestPluginApproval(params) {
11
+ const timeoutMs = DEFAULT_CODEX_APPROVAL_TIMEOUT_MS;
12
+ return callGatewayTool("plugin.approval.request", { timeoutMs: timeoutMs + 1e4 }, {
13
+ pluginId: "autobot-codex-app-server",
14
+ title: truncateForGateway(params.title, MAX_PLUGIN_APPROVAL_TITLE_LENGTH),
15
+ description: truncateForGateway(params.description, MAX_PLUGIN_APPROVAL_DESCRIPTION_LENGTH),
16
+ severity: params.severity,
17
+ toolName: params.toolName,
18
+ toolCallId: params.toolCallId,
19
+ agentId: params.paramsForRun.agentId,
20
+ sessionKey: params.paramsForRun.sessionKey,
21
+ turnSourceChannel: params.paramsForRun.messageChannel ?? params.paramsForRun.messageProvider,
22
+ turnSourceTo: params.paramsForRun.currentChannelId,
23
+ turnSourceAccountId: params.paramsForRun.agentAccountId,
24
+ turnSourceThreadId: params.paramsForRun.currentThreadTs,
25
+ timeoutMs,
26
+ twoPhase: true
27
+ }, { expectFinal: false });
28
+ }
29
+ function approvalRequestExplicitlyUnavailable(result) {
30
+ if (result === null || result === void 0 || typeof result !== "object") return false;
31
+ let descriptor;
32
+ try {
33
+ descriptor = Object.getOwnPropertyDescriptor(result, "decision");
34
+ } catch {
35
+ return false;
36
+ }
37
+ return descriptor !== void 0 && "value" in descriptor && descriptor.value === null;
38
+ }
39
+ async function waitForPluginApprovalDecision(params) {
40
+ const waitPromise = callGatewayTool("plugin.approval.waitDecision", { timeoutMs: DEFAULT_CODEX_APPROVAL_TIMEOUT_MS + 1e4 }, { id: params.approvalId });
41
+ if (!params.signal) return (await waitPromise)?.decision;
42
+ let onAbort;
43
+ const abortPromise = new Promise((_, reject) => {
44
+ if (params.signal.aborted) {
45
+ reject(params.signal.reason);
46
+ return;
47
+ }
48
+ onAbort = () => reject(params.signal.reason);
49
+ params.signal.addEventListener("abort", onAbort, { once: true });
50
+ });
51
+ try {
52
+ return (await Promise.race([waitPromise, abortPromise]))?.decision;
53
+ } finally {
54
+ if (onAbort) params.signal.removeEventListener("abort", onAbort);
55
+ }
56
+ }
57
+ function mapExecDecisionToOutcome(decision) {
58
+ if (decision === "allow-once") return "approved-once";
59
+ if (decision === "allow-always") return "approved-session";
60
+ if (decision === null || decision === void 0) return "unavailable";
61
+ return "denied";
62
+ }
63
+ function truncateForGateway(value, maxLength) {
64
+ return value.length <= maxLength ? value : `${value.slice(0, Math.max(0, maxLength - 3))}...`;
65
+ }
66
+ //#endregion
67
+ //#region extensions/codex/src/app-server/approval-bridge.ts
68
+ const PERMISSION_DESCRIPTION_MAX_LENGTH = 700;
69
+ const PERMISSION_SAMPLE_LIMIT = 2;
70
+ const PERMISSION_VALUE_MAX_LENGTH = 48;
71
+ const COMMAND_PREVIEW_WITH_DETAILS_MAX_LENGTH = 80;
72
+ const APPROVAL_PREVIEW_SCAN_MAX_LENGTH = 4096;
73
+ const APPROVAL_PREVIEW_OMITTED = "[preview truncated or unsafe content omitted]";
74
+ const ANSI_OSC_SEQUENCE_RE$1 = new RegExp(String.raw`(?:\u001b]|\u009d)[^\u001b\u009c\u0007]*(?:\u0007|\u001b\\|\u009c)`, "g");
75
+ const ANSI_CONTROL_SEQUENCE_RE$1 = new RegExp(String.raw`(?:\u001b\[[0-?]*[ -/]*[@-~]|\u009b[0-?]*[ -/]*[@-~]|\u001b[@-Z\\-_])`, "g");
76
+ const CONTROL_CHARACTER_RE$1 = new RegExp(String.raw`[\u0000-\u001f\u007f-\u009f]+`, "g");
77
+ const INVISIBLE_FORMATTING_CONTROL_RE$1 = new RegExp(String.raw`[\u00ad\u034f\u061c\u200b-\u200f\u202a-\u202e\u2060-\u206f\ufeff\ufe00-\ufe0f\u{e0100}-\u{e01ef}]`, "gu");
78
+ const DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE$1 = new RegExp(String.raw`(?:\u001b\][^\u001b\u009c\u0007]*|\u009d[^\u001b\u009c\u0007]*|\u001b\[[0-?]*[ -/]*|\u009b[0-?]*[ -/]*|\u001b)$`);
79
+ async function handleCodexAppServerApprovalRequest(params) {
80
+ const requestParams = isJsonObject(params.requestParams) ? params.requestParams : void 0;
81
+ if (!matchesCurrentTurn(requestParams, params.threadId, params.turnId)) return;
82
+ if (!isSupportedAppServerApprovalMethod(params.method)) return unsupportedApprovalResponse();
83
+ const context = buildApprovalContext({
84
+ method: params.method,
85
+ requestParams,
86
+ paramsForRun: params.paramsForRun
87
+ });
88
+ try {
89
+ const policyOutcome = await runAutoBotToolPolicyForApprovalRequest({
90
+ method: params.method,
91
+ requestParams,
92
+ paramsForRun: params.paramsForRun,
93
+ context,
94
+ nativeHookRelay: params.nativeHookRelay,
95
+ signal: params.signal
96
+ });
97
+ if (policyOutcome?.outcome === "denied") {
98
+ emitApprovalEvent(params.paramsForRun, {
99
+ phase: "resolved",
100
+ kind: context.kind,
101
+ status: "denied",
102
+ title: context.title,
103
+ ...context.eventDetails,
104
+ ...approvalEventScope(params.method, "denied"),
105
+ message: policyOutcome.reason
106
+ });
107
+ return buildApprovalResponse(params.method, context.requestParams, "denied");
108
+ }
109
+ const requestResult = await requestPluginApproval({
110
+ paramsForRun: params.paramsForRun,
111
+ title: context.title,
112
+ description: context.description,
113
+ severity: context.severity,
114
+ toolName: context.toolName,
115
+ toolCallId: context.itemId
116
+ });
117
+ const approvalId = requestResult?.id;
118
+ if (!approvalId) {
119
+ emitApprovalEvent(params.paramsForRun, {
120
+ phase: "resolved",
121
+ kind: context.kind,
122
+ status: "unavailable",
123
+ title: context.title,
124
+ ...context.eventDetails,
125
+ ...approvalEventScope(params.method, "denied"),
126
+ message: "Codex app-server approval route unavailable."
127
+ });
128
+ return buildApprovalResponse(params.method, context.requestParams, "denied");
129
+ }
130
+ emitApprovalEvent(params.paramsForRun, {
131
+ phase: "requested",
132
+ kind: context.kind,
133
+ status: "pending",
134
+ title: context.title,
135
+ approvalId,
136
+ approvalSlug: approvalId,
137
+ ...context.eventDetails,
138
+ message: "Codex app-server approval requested."
139
+ });
140
+ const outcome = mapExecDecisionToOutcome(approvalRequestExplicitlyUnavailable(requestResult) ? null : await waitForPluginApprovalDecision({
141
+ approvalId,
142
+ signal: params.signal
143
+ }));
144
+ emitApprovalEvent(params.paramsForRun, {
145
+ phase: "resolved",
146
+ kind: context.kind,
147
+ status: outcome === "denied" ? "denied" : outcome === "unavailable" ? "unavailable" : outcome === "cancelled" ? "failed" : "approved",
148
+ title: context.title,
149
+ approvalId,
150
+ approvalSlug: approvalId,
151
+ ...context.eventDetails,
152
+ ...approvalEventScope(params.method, outcome),
153
+ message: approvalResolutionMessage(outcome)
154
+ });
155
+ return buildApprovalResponse(params.method, context.requestParams, outcome);
156
+ } catch (error) {
157
+ const cancelled = params.signal?.aborted === true;
158
+ emitApprovalEvent(params.paramsForRun, {
159
+ phase: "resolved",
160
+ kind: context.kind,
161
+ status: cancelled ? "failed" : "unavailable",
162
+ title: context.title,
163
+ ...context.eventDetails,
164
+ ...approvalEventScope(params.method, cancelled ? "cancelled" : "denied"),
165
+ message: cancelled ? "Codex app-server approval cancelled because the run stopped." : `Codex app-server approval route failed: ${formatCodexDisplayText(formatErrorMessage$1(error))}`
166
+ });
167
+ return buildApprovalResponse(params.method, context.requestParams, cancelled ? "cancelled" : "denied");
168
+ }
169
+ }
170
+ function buildApprovalResponse(method, requestParams, outcome) {
171
+ if (method === "item/commandExecution/requestApproval") return { decision: commandApprovalDecision(requestParams, outcome) };
172
+ if (method === "item/fileChange/requestApproval") return { decision: fileChangeApprovalDecision(outcome) };
173
+ if (method === "item/permissions/requestApproval") {
174
+ if (outcome === "approved-session" || outcome === "approved-once") return {
175
+ permissions: requestedPermissions(requestParams),
176
+ scope: outcome === "approved-session" ? "session" : "turn"
177
+ };
178
+ return {
179
+ permissions: {},
180
+ scope: "turn"
181
+ };
182
+ }
183
+ return unsupportedApprovalResponse();
184
+ }
185
+ function matchesCurrentTurn(requestParams, threadId, turnId) {
186
+ if (!requestParams) return false;
187
+ const requestThreadId = readString$1(requestParams, "threadId") ?? readString$1(requestParams, "conversationId");
188
+ const requestTurnId = readString$1(requestParams, "turnId");
189
+ return requestThreadId === threadId && requestTurnId === turnId;
190
+ }
191
+ function buildApprovalContext(params) {
192
+ const itemId = readString$1(params.requestParams, "itemId") ?? readString$1(params.requestParams, "callId") ?? readString$1(params.requestParams, "approvalId");
193
+ const commandDetailLines = params.method === "item/commandExecution/requestApproval" ? describeCommandApprovalDetails(params.requestParams) : [];
194
+ const commandPreview = sanitizeApprovalPreview(readDisplayCommandPreview(params.requestParams), commandDetailLines.length > 0 ? COMMAND_PREVIEW_WITH_DETAILS_MAX_LENGTH : 180);
195
+ const reasonPreview = sanitizeApprovalPreview(readStringPreview(params.requestParams, "reason"), 180);
196
+ const command = commandPreview.text;
197
+ const reason = reasonPreview.text;
198
+ const kind = approvalKindForMethod(params.method);
199
+ const permissionLines = params.method === "item/permissions/requestApproval" ? describeRequestedPermissions(params.requestParams) : [];
200
+ const title = kind === "exec" ? "Codex app-server command approval" : params.method === "item/permissions/requestApproval" ? "Codex app-server permission approval" : kind === "plugin" ? "Codex app-server file approval" : "Codex app-server approval";
201
+ const subject = permissionLines[0] ?? (command ? `Command: ${formatApprovalPreviewSubject(command, commandPreview.omitted)}` : commandPreview.omitted ? `Command: ${APPROVAL_PREVIEW_OMITTED}` : reason ? `Reason: ${formatApprovalPreviewSubject(reason, reasonPreview.omitted)}` : reasonPreview.omitted ? `Reason: ${APPROVAL_PREVIEW_OMITTED}` : `Request method: ${params.method}`);
202
+ return {
203
+ kind,
204
+ title,
205
+ description: permissionLines.length > 0 ? joinDescriptionLinesWithinLimit(permissionLines, PERMISSION_DESCRIPTION_MAX_LENGTH) : [
206
+ subject,
207
+ ...commandDetailLines,
208
+ params.paramsForRun.sessionKey && `Session: ${params.paramsForRun.sessionKey}`
209
+ ].filter(Boolean).join("\n"),
210
+ severity: kind === "exec" ? "warning" : "info",
211
+ toolName: kind === "exec" ? "codex_command_approval" : params.method === "item/permissions/requestApproval" ? "codex_permission_approval" : "codex_file_approval",
212
+ itemId,
213
+ requestParams: params.requestParams,
214
+ eventDetails: {
215
+ ...itemId ? { itemId } : {},
216
+ ...command ? { command } : {},
217
+ ...commandPreview.omitted ? { commandPreviewOmitted: true } : {},
218
+ ...reason ? { reason } : {},
219
+ ...reasonPreview.omitted ? { reasonPreviewOmitted: true } : {}
220
+ }
221
+ };
222
+ }
223
+ async function runAutoBotToolPolicyForApprovalRequest(params) {
224
+ const policyRequest = buildAutoBotToolPolicyRequest(params.method, params.requestParams);
225
+ if (!policyRequest) return;
226
+ const cwd = readString$1(params.requestParams, "cwd") ?? params.paramsForRun.workspaceDir;
227
+ const nativeRelayOutcome = await runNativeRelayToolPolicyForApprovalRequest({
228
+ method: params.method,
229
+ requestParams: params.requestParams,
230
+ context: params.context,
231
+ policyRequest,
232
+ nativeHookRelay: params.nativeHookRelay,
233
+ cwd
234
+ });
235
+ if (nativeRelayOutcome?.blocked) return {
236
+ outcome: "denied",
237
+ reason: nativeRelayOutcome.reason
238
+ };
239
+ if (nativeRelayOutcome?.handled) return { outcome: "no-decision" };
240
+ const hookChannelId = buildAgentHookContextChannelFields({
241
+ sessionKey: params.paramsForRun.sessionKey,
242
+ messageChannel: params.paramsForRun.messageChannel,
243
+ messageProvider: params.paramsForRun.messageProvider,
244
+ currentChannelId: params.paramsForRun.currentChannelId,
245
+ messageTo: params.paramsForRun.messageTo
246
+ }).channelId;
247
+ const outcome = await runBeforeToolCallHook({
248
+ toolName: policyRequest.toolName,
249
+ params: policyRequest.params,
250
+ ...params.context.itemId ? { toolCallId: params.context.itemId } : {},
251
+ approvalMode: "report",
252
+ signal: params.signal,
253
+ ctx: {
254
+ ...params.paramsForRun.agentId ? { agentId: params.paramsForRun.agentId } : {},
255
+ ...params.paramsForRun.config ? { config: params.paramsForRun.config } : {},
256
+ ...cwd ? { cwd } : {},
257
+ ...params.paramsForRun.sessionKey ? { sessionKey: params.paramsForRun.sessionKey } : {},
258
+ ...params.paramsForRun.sessionId ? { sessionId: params.paramsForRun.sessionId } : {},
259
+ ...params.paramsForRun.runId ? { runId: params.paramsForRun.runId } : {},
260
+ ...hookChannelId ? { channelId: hookChannelId } : {}
261
+ }
262
+ });
263
+ if (outcome.blocked) return {
264
+ outcome: "denied",
265
+ reason: outcome.reason
266
+ };
267
+ if ("params" in outcome && toolPolicyParamsWereRewritten(policyRequest.params, outcome.params)) return {
268
+ outcome: "denied",
269
+ reason: "AutoBot tool policy rewrote Codex app-server approval params; refusing original request."
270
+ };
271
+ }
272
+ async function runNativeRelayToolPolicyForApprovalRequest(params) {
273
+ if (params.method !== "item/commandExecution/requestApproval" || !params.nativeHookRelay?.allowedEvents.includes("pre_tool_use")) return;
274
+ const payload = buildNativeRelayPreToolUsePayload({
275
+ requestParams: params.requestParams,
276
+ policyRequest: params.policyRequest,
277
+ context: params.context,
278
+ cwd: params.cwd
279
+ });
280
+ if (!payload) return;
281
+ if (hasNativeHookRelayInvocation({
282
+ relayId: params.nativeHookRelay.relayId,
283
+ event: "pre_tool_use",
284
+ toolUseId: params.context.itemId
285
+ })) return { handled: true };
286
+ try {
287
+ const decision = readNativeRelayPreToolUseDecision(await invokeNativeHookRelay({
288
+ provider: "codex",
289
+ relayId: params.nativeHookRelay.relayId,
290
+ event: "pre_tool_use",
291
+ rawPayload: payload
292
+ }));
293
+ if (decision.blocked) return {
294
+ handled: true,
295
+ blocked: true,
296
+ reason: decision.reason
297
+ };
298
+ return { handled: true };
299
+ } catch (error) {
300
+ return {
301
+ handled: true,
302
+ blocked: true,
303
+ reason: `AutoBot native hook relay unavailable for Codex app-server approval: ${formatCodexDisplayText(formatErrorMessage$1(error))}`
304
+ };
305
+ }
306
+ }
307
+ function buildNativeRelayPreToolUsePayload(params) {
308
+ const command = readString$1(params.policyRequest.params, "command");
309
+ if (!command) return;
310
+ const turnId = readString$1(params.requestParams, "turnId");
311
+ return {
312
+ hook_event_name: "PreToolUse",
313
+ autobot_approval_mode: "report",
314
+ tool_name: "exec_command",
315
+ ...params.context.itemId ? { tool_use_id: params.context.itemId } : {},
316
+ ...params.cwd ? { cwd: params.cwd } : {},
317
+ ...turnId ? { turn_id: turnId } : {},
318
+ tool_input: {
319
+ ...params.policyRequest.params,
320
+ command,
321
+ cmd: command
322
+ }
323
+ };
324
+ }
325
+ function readNativeRelayPreToolUseDecision(response) {
326
+ if (!response || response.exitCode !== 0) return {
327
+ blocked: true,
328
+ reason: sanitizeRelayDecisionReason(response?.stderr) || sanitizeRelayDecisionReason(response?.stdout) || "AutoBot native hook relay failed for Codex app-server approval."
329
+ };
330
+ const stdout = response.stdout?.trim();
331
+ if (!stdout) return { blocked: false };
332
+ const parsed = parseRelayJsonResponse(stdout);
333
+ const output = isJsonObject(parsed?.hookSpecificOutput) ? parsed.hookSpecificOutput : void 0;
334
+ if (output?.permissionDecision === "deny") return {
335
+ blocked: true,
336
+ reason: readString$1(output, "permissionDecisionReason") || "AutoBot native hook policy denied Codex app-server approval."
337
+ };
338
+ return {
339
+ blocked: true,
340
+ reason: output ? "AutoBot native hook relay returned a non-deny Codex app-server approval decision." : "AutoBot native hook relay returned an unreadable Codex app-server approval result."
341
+ };
342
+ }
343
+ function parseRelayJsonResponse(text) {
344
+ try {
345
+ const parsed = JSON.parse(text);
346
+ return isJsonObject(parsed) ? parsed : void 0;
347
+ } catch {
348
+ return;
349
+ }
350
+ }
351
+ function sanitizeRelayDecisionReason(value) {
352
+ return sanitizeApprovalPreview(value ? {
353
+ value,
354
+ clipped: false
355
+ } : void 0, 240).text;
356
+ }
357
+ function buildAutoBotToolPolicyRequest(method, requestParams) {
358
+ if (method === "item/commandExecution/requestApproval") {
359
+ const command = readPolicyCommand(requestParams);
360
+ return {
361
+ toolName: "exec",
362
+ params: {
363
+ ...command ? { command } : {},
364
+ ...readString$1(requestParams, "cwd") ? { cwd: readString$1(requestParams, "cwd") } : {},
365
+ approval: requestParams ?? {}
366
+ }
367
+ };
368
+ }
369
+ if (method === "item/fileChange/requestApproval") return {
370
+ toolName: "apply_patch",
371
+ params: requestParams ?? {}
372
+ };
373
+ if (method === "item/permissions/requestApproval") return {
374
+ toolName: "codex_permission_approval",
375
+ params: requestParams ?? {}
376
+ };
377
+ }
378
+ function toolPolicyParamsWereRewritten(original, candidate) {
379
+ if (candidate === original) return false;
380
+ const originalText = stableJsonText(original);
381
+ const candidateText = stableJsonText(candidate);
382
+ return !candidateText || candidateText !== originalText;
383
+ }
384
+ function stableJsonText(value) {
385
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return JSON.stringify(value);
386
+ if (Array.isArray(value)) {
387
+ const items = value.map((item) => stableJsonText(item));
388
+ return items.every((item) => item !== void 0) ? `[${items.join(",")}]` : void 0;
389
+ }
390
+ if (isPlainRecord(value)) {
391
+ const entries = Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, item]) => {
392
+ const text = stableJsonText(item);
393
+ return text === void 0 ? void 0 : `${JSON.stringify(key)}:${text}`;
394
+ });
395
+ return entries.every((entry) => entry !== void 0) ? `{${entries.join(",")}}` : void 0;
396
+ }
397
+ }
398
+ function isPlainRecord(value) {
399
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
400
+ }
401
+ function commandApprovalDecision(requestParams, outcome) {
402
+ if (outcome === "cancelled") return commandRejectionDecision(requestParams, "cancel");
403
+ if (outcome === "denied" || outcome === "unavailable") return commandRejectionDecision(requestParams, "decline");
404
+ if (outcome === "approved-session") {
405
+ if (hasAvailableDecision(requestParams, "acceptForSession")) return "acceptForSession";
406
+ const amendmentDecision = findAvailableCommandAmendmentDecision(requestParams);
407
+ if (amendmentDecision) return amendmentDecision;
408
+ }
409
+ return hasAvailableDecision(requestParams, "accept") ? "accept" : commandRejectionDecision(requestParams, "decline");
410
+ }
411
+ function fileChangeApprovalDecision(outcome) {
412
+ if (outcome === "cancelled") return "cancel";
413
+ if (outcome === "denied" || outcome === "unavailable") return "decline";
414
+ return outcome === "approved-session" ? "acceptForSession" : "accept";
415
+ }
416
+ function requestedPermissions(requestParams) {
417
+ const permissions = isJsonObject(requestParams?.permissions) ? requestParams.permissions : {};
418
+ const granted = {};
419
+ if (isJsonObject(permissions.network)) granted.network = permissions.network;
420
+ if (isJsonObject(permissions.fileSystem)) granted.fileSystem = permissions.fileSystem;
421
+ return granted;
422
+ }
423
+ function unsupportedApprovalResponse() {
424
+ return {
425
+ decision: "decline",
426
+ reason: "AutoBot codex app-server bridge does not grant native approvals yet."
427
+ };
428
+ }
429
+ function describeRequestedPermissions(requestParams) {
430
+ return describePermissionProfile(requestedPermissions(requestParams), "Permissions");
431
+ }
432
+ function describeCommandApprovalDetails(requestParams) {
433
+ const lines = [];
434
+ const additionalPermissions = isJsonObject(requestParams?.additionalPermissions) ? requestParams.additionalPermissions : void 0;
435
+ if (additionalPermissions) lines.push(...describePermissionProfile(additionalPermissions, "Additional permissions"));
436
+ const execpolicySummary = summarizeStringArray(requestParams?.proposedExecpolicyAmendment, "Proposed exec policy", sanitizePermissionScalar);
437
+ if (execpolicySummary) lines.push(execpolicySummary);
438
+ const networkAmendmentSummary = summarizeNetworkPolicyAmendments(requestParams?.proposedNetworkPolicyAmendments);
439
+ if (networkAmendmentSummary) lines.push(networkAmendmentSummary);
440
+ return lines;
441
+ }
442
+ function describePermissionProfile(permissions, label) {
443
+ const lines = [];
444
+ const kinds = [];
445
+ const risks = /* @__PURE__ */ new Set();
446
+ if (isJsonObject(permissions.network)) kinds.push("network");
447
+ if (isJsonObject(permissions.fileSystem)) kinds.push("fileSystem");
448
+ if (kinds.length > 0) lines.push(`${label}: ${kinds.join(", ")}`);
449
+ let networkSummary;
450
+ if (isJsonObject(permissions.network)) {
451
+ const summaries = [summarizeNetworkEnabledPermission(permissions.network, risks), summarizePermissionRecord(permissions.network, risks, [{
452
+ key: "allowHosts",
453
+ label: "allowHosts",
454
+ sanitize: sanitizePermissionHostValue,
455
+ risksFor: permissionHostRisks
456
+ }])].filter((summary) => Boolean(summary));
457
+ networkSummary = summaries.length > 0 ? summaries.join("; ") : void 0;
458
+ }
459
+ let fileSystemSummary;
460
+ if (isJsonObject(permissions.fileSystem)) {
461
+ const summaries = [summarizePermissionRecord(permissions.fileSystem, risks, [
462
+ {
463
+ key: "read",
464
+ label: "read",
465
+ sanitize: sanitizePermissionPathValue,
466
+ risksFor: permissionPathRisks
467
+ },
468
+ {
469
+ key: "write",
470
+ label: "write",
471
+ sanitize: sanitizePermissionPathValue,
472
+ risksFor: permissionPathRisks
473
+ },
474
+ {
475
+ key: "roots",
476
+ label: "roots",
477
+ sanitize: sanitizePermissionPathValue,
478
+ risksFor: permissionPathRisks
479
+ },
480
+ {
481
+ key: "readPaths",
482
+ label: "readPaths",
483
+ sanitize: sanitizePermissionPathValue,
484
+ risksFor: permissionPathRisks
485
+ },
486
+ {
487
+ key: "writePaths",
488
+ label: "writePaths",
489
+ sanitize: sanitizePermissionPathValue,
490
+ risksFor: permissionPathRisks
491
+ }
492
+ ]), summarizeFileSystemEntries(permissions.fileSystem, risks)].filter((summary) => Boolean(summary));
493
+ fileSystemSummary = summaries.length > 0 ? summaries.join("; ") : void 0;
494
+ }
495
+ if (risks.size > 0) lines.push(`High-risk targets: ${[...risks].join(", ")}`);
496
+ if (networkSummary) lines.push(`Network ${networkSummary}`);
497
+ if (fileSystemSummary) lines.push(`File system ${fileSystemSummary}`);
498
+ return lines;
499
+ }
500
+ function summarizeNetworkEnabledPermission(permission, risks) {
501
+ const enabled = permission.enabled;
502
+ if (typeof enabled !== "boolean") return;
503
+ if (enabled) risks.add("network access");
504
+ return `enabled: ${enabled}`;
505
+ }
506
+ function summarizeFileSystemEntries(permission, risks) {
507
+ const entries = permission.entries;
508
+ if (!Array.isArray(entries)) return;
509
+ const samples = [];
510
+ let count = 0;
511
+ for (const entry of entries) {
512
+ const item = isJsonObject(entry) ? entry : void 0;
513
+ const path = typeof item?.path === "string" ? item.path.trim() : "";
514
+ const access = typeof item?.access === "string" ? item.access.trim() : "";
515
+ if (!path || !access) continue;
516
+ count += 1;
517
+ if (access !== "none") for (const risk of permissionPathRisks(path)) risks.add(risk);
518
+ if (samples.length < PERMISSION_SAMPLE_LIMIT) samples.push(`${sanitizePermissionScalar(access)} ${sanitizePermissionPathValue(path)}`);
519
+ }
520
+ if (count === 0) return;
521
+ const remaining = count - samples.length;
522
+ const remainderSuffix = remaining > 0 ? ` (+${remaining} more)` : "";
523
+ return `entries: ${samples.join(", ")}${remainderSuffix}`;
524
+ }
525
+ function summarizePermissionRecord(permission, risks, descriptors) {
526
+ const details = [];
527
+ for (const descriptor of descriptors) {
528
+ const summary = summarizePermissionArray(permission, descriptor, risks);
529
+ if (summary) details.push(summary);
530
+ }
531
+ return details.length > 0 ? details.join("; ") : void 0;
532
+ }
533
+ function summarizePermissionArray(record, descriptor, risks) {
534
+ const values = readStringArray(record, descriptor.key);
535
+ if (values.length === 0) return;
536
+ for (const value of values) for (const risk of descriptor.risksFor(value)) risks.add(risk);
537
+ const sampleValues = values.slice(0, PERMISSION_SAMPLE_LIMIT).map(descriptor.sanitize).filter(Boolean);
538
+ if (sampleValues.length === 0) return `${descriptor.label}: ${values.length}`;
539
+ const remaining = values.length - sampleValues.length;
540
+ const remainderSuffix = remaining > 0 ? ` (+${remaining} more)` : "";
541
+ return `${descriptor.label}: ${sampleValues.join(", ")}${remainderSuffix}`;
542
+ }
543
+ function summarizeStringArray(value, label, sanitize) {
544
+ if (!Array.isArray(value)) return;
545
+ const values = value.filter((entry) => typeof entry === "string").map((entry) => sanitize(entry)).filter(Boolean);
546
+ if (values.length === 0) return;
547
+ const samples = values.slice(0, PERMISSION_SAMPLE_LIMIT);
548
+ const remaining = values.length - samples.length;
549
+ const remainderSuffix = remaining > 0 ? ` (+${remaining} more)` : "";
550
+ return `${label}: ${samples.join(", ")}${remainderSuffix}`;
551
+ }
552
+ function summarizeNetworkPolicyAmendments(value) {
553
+ if (!Array.isArray(value)) return;
554
+ const samples = [];
555
+ let count = 0;
556
+ for (const entry of value) {
557
+ const amendment = isJsonObject(entry) ? entry : void 0;
558
+ const host = typeof amendment?.host === "string" ? amendment.host : "";
559
+ const action = typeof amendment?.action === "string" ? amendment.action : "";
560
+ if (!host || !action) continue;
561
+ count += 1;
562
+ if (samples.length < PERMISSION_SAMPLE_LIMIT) samples.push(`${sanitizePermissionScalar(action)} ${sanitizePermissionHostValue(host)}`);
563
+ }
564
+ if (count === 0) return;
565
+ const remaining = count - samples.length;
566
+ const remainderSuffix = remaining > 0 ? ` (+${remaining} more)` : "";
567
+ return `Proposed network policy: ${samples.join(", ")}${remainderSuffix}`;
568
+ }
569
+ function readStringArray(record, key) {
570
+ const value = record[key];
571
+ return Array.isArray(value) ? value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean) : [];
572
+ }
573
+ function sanitizePermissionHostValue(value) {
574
+ const withoutScheme = sanitizePermissionScalar(value).toLowerCase().replace(/^[a-z][a-z0-9+.-]*:\/\//, "");
575
+ const authority = withoutScheme.split(/[/?#]/, 1)[0] ?? withoutScheme;
576
+ return truncate(authority.includes("@") ? authority.slice(authority.lastIndexOf("@") + 1) : authority, PERMISSION_VALUE_MAX_LENGTH);
577
+ }
578
+ function sanitizePermissionPathValue(value) {
579
+ return truncate(formatApprovalDisplayPath(sanitizePermissionScalar(value)), PERMISSION_VALUE_MAX_LENGTH);
580
+ }
581
+ function sanitizePermissionScalar(value) {
582
+ return sanitizeVisibleScalar(value);
583
+ }
584
+ function permissionHostRisks(value) {
585
+ const normalized = value.trim().toLowerCase();
586
+ const risks = [];
587
+ if (normalized.includes("*")) {
588
+ risks.push("wildcard hosts");
589
+ if (isPrivateNetworkHostPattern(normalized)) risks.push("private-network wildcards");
590
+ }
591
+ return risks;
592
+ }
593
+ function permissionPathRisks(value) {
594
+ const normalized = sanitizePermissionScalar(value);
595
+ const risks = [];
596
+ if (normalized === "/" || normalized === "\\" || /^[A-Za-z]:[\\/]*$/.test(normalized)) risks.push("filesystem root");
597
+ return risks;
598
+ }
599
+ function isPrivateNetworkHostPattern(value) {
600
+ const wildcardStripped = value.toLowerCase().replace(/^\*\./, "");
601
+ if (wildcardStripped === "localhost" || wildcardStripped === "local" || wildcardStripped === "internal" || wildcardStripped === "lan" || wildcardStripped === "home" || wildcardStripped === "corp" || wildcardStripped === "private" || wildcardStripped.endsWith(".local") || wildcardStripped.endsWith(".internal") || wildcardStripped.endsWith(".lan") || wildcardStripped.endsWith(".home") || wildcardStripped.endsWith(".corp") || wildcardStripped.endsWith(".private")) return true;
602
+ if (wildcardStripped.startsWith("10.") || wildcardStripped.startsWith("127.") || wildcardStripped.startsWith("192.168.") || wildcardStripped.startsWith("169.254.")) return true;
603
+ return /^172\.(1[6-9]|2\d|3[0-1])\./.test(wildcardStripped);
604
+ }
605
+ function hasAvailableDecision(requestParams, decision) {
606
+ const available = requestParams?.availableDecisions;
607
+ if (!Array.isArray(available)) return true;
608
+ return available.includes(decision);
609
+ }
610
+ function findAvailableCommandAmendmentDecision(requestParams) {
611
+ const available = requestParams?.availableDecisions;
612
+ if (!Array.isArray(available)) return;
613
+ return available.find((entry) => isJsonObject(entry) && (isJsonObject(entry.acceptWithExecpolicyAmendment) || isJsonObject(entry.applyNetworkPolicyAmendment)));
614
+ }
615
+ function commandRejectionDecision(requestParams, preferred) {
616
+ const available = requestParams?.availableDecisions;
617
+ if (!Array.isArray(available)) return preferred;
618
+ if (available.includes(preferred)) return preferred;
619
+ const alternate = preferred === "decline" ? "cancel" : "decline";
620
+ if (available.includes(alternate)) return alternate;
621
+ return preferred;
622
+ }
623
+ function approvalResolutionMessage(outcome) {
624
+ if (outcome === "approved-session") return "Codex app-server approval granted for the session.";
625
+ if (outcome === "approved-once") return "Codex app-server approval granted for this turn.";
626
+ if (outcome === "cancelled") return "Codex app-server approval cancelled.";
627
+ if (outcome === "unavailable") return "Codex app-server approval unavailable.";
628
+ return "Codex app-server approval denied.";
629
+ }
630
+ function approvalScopeForOutcome(outcome) {
631
+ return outcome === "approved-session" ? "session" : "turn";
632
+ }
633
+ function approvalEventScope(method, outcome) {
634
+ return method === "item/permissions/requestApproval" ? { scope: approvalScopeForOutcome(outcome) } : {};
635
+ }
636
+ function approvalKindForMethod(method) {
637
+ if (method.includes("commandExecution") || method.includes("execCommand")) return "exec";
638
+ if (method.includes("fileChange") || method.includes("Patch") || method.includes("permissions")) return "plugin";
639
+ return "unknown";
640
+ }
641
+ function isSupportedAppServerApprovalMethod(method) {
642
+ return method === "item/commandExecution/requestApproval" || method === "item/fileChange/requestApproval" || method === "item/permissions/requestApproval";
643
+ }
644
+ function emitApprovalEvent(params, data) {
645
+ params.onAgentEvent?.({
646
+ stream: "approval",
647
+ data
648
+ });
649
+ }
650
+ function readDisplayCommandPreview(record) {
651
+ const actionCommand = readCommandActionsPreview(record);
652
+ if (actionCommand) return actionCommand;
653
+ return readCommandPreview(record);
654
+ }
655
+ function readPolicyCommand(record) {
656
+ const command = record?.command;
657
+ if (typeof command === "string") return command;
658
+ if (Array.isArray(command) && command.every((part) => typeof part === "string")) return command.join(" ");
659
+ const actionCommands = readCommandActions(record);
660
+ if (actionCommands.length > 0) return actionCommands.join(" && ");
661
+ }
662
+ function readCommandActions(record) {
663
+ const actions = record?.commandActions;
664
+ if (!Array.isArray(actions)) return [];
665
+ return actions.map((action) => isJsonObject(action) ? readString$1(action, "command") : void 0).filter((command) => Boolean(command));
666
+ }
667
+ function readCommandActionsPreview(record) {
668
+ let source;
669
+ for (const command of readCommandActions(record)) {
670
+ source = appendPreviewPart(source, command, " && ");
671
+ if (source.clipped) break;
672
+ }
673
+ return source;
674
+ }
675
+ function readCommandPreview(record) {
676
+ const command = record?.command;
677
+ if (typeof command === "string") return previewSource(command);
678
+ if (!Array.isArray(command)) return;
679
+ let source;
680
+ for (const part of command) {
681
+ if (typeof part !== "string") return;
682
+ source = appendPreviewPart(source, part, " ");
683
+ if (source.clipped) break;
684
+ }
685
+ return source;
686
+ }
687
+ function readStringPreview(record, key) {
688
+ const value = readString$1(record, key);
689
+ return value === void 0 ? void 0 : previewSource(value);
690
+ }
691
+ function readString$1(record, key) {
692
+ const value = record?.[key];
693
+ return typeof value === "string" ? value : void 0;
694
+ }
695
+ function truncate(value, maxLength) {
696
+ return value.length <= maxLength ? value : `${value.slice(0, Math.max(0, maxLength - 3))}...`;
697
+ }
698
+ function previewSource(value) {
699
+ return {
700
+ value: value.slice(0, APPROVAL_PREVIEW_SCAN_MAX_LENGTH),
701
+ clipped: value.length > APPROVAL_PREVIEW_SCAN_MAX_LENGTH
702
+ };
703
+ }
704
+ function appendPreviewPart(source, part, separator) {
705
+ const value = `${source?.value ? `${source.value}${separator}` : ""}${part}`;
706
+ const clipped = source?.clipped === true || value.length > APPROVAL_PREVIEW_SCAN_MAX_LENGTH;
707
+ return {
708
+ value: value.slice(0, APPROVAL_PREVIEW_SCAN_MAX_LENGTH),
709
+ clipped
710
+ };
711
+ }
712
+ function sanitizeApprovalPreview(source, maxLength) {
713
+ if (!source || !source.value) return { omitted: false };
714
+ const sanitized = sanitizeVisibleScalar(source.value.replace(DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE$1, ""));
715
+ if (!sanitized) return { omitted: true };
716
+ return {
717
+ text: formatCodexDisplayText(truncate(sanitized, maxLength)),
718
+ omitted: source.clipped
719
+ };
720
+ }
721
+ function sanitizeVisibleScalar(value) {
722
+ return value.replace(ANSI_OSC_SEQUENCE_RE$1, "").replace(ANSI_CONTROL_SEQUENCE_RE$1, "").replace(INVISIBLE_FORMATTING_CONTROL_RE$1, " ").replace(CONTROL_CHARACTER_RE$1, " ").replace(/\s+/g, " ").trim();
723
+ }
724
+ function formatApprovalPreviewSubject(text, omitted) {
725
+ return omitted ? `${text} ${APPROVAL_PREVIEW_OMITTED}` : text;
726
+ }
727
+ function joinDescriptionLinesWithinLimit(lines, maxLength) {
728
+ let description = "";
729
+ for (const line of lines) {
730
+ const prefix = description ? "\n" : "";
731
+ const next = `${description}${prefix}${line}`;
732
+ if (next.length <= maxLength) {
733
+ description = next;
734
+ continue;
735
+ }
736
+ const remaining = maxLength - description.length - prefix.length;
737
+ if (remaining < 3) break;
738
+ description += `${prefix}${truncate(line, remaining)}`;
739
+ break;
740
+ }
741
+ return description;
742
+ }
743
+ function formatErrorMessage$1(error) {
744
+ return error instanceof Error ? error.message : String(error);
745
+ }
746
+ //#endregion
747
+ //#region extensions/codex/src/app-server/dynamic-tool-diagnostics.ts
748
+ function emitDynamicToolStartedDiagnostic(params) {
749
+ emitTrustedDiagnosticEvent({
750
+ type: "tool.execution.started",
751
+ runId: params.runId,
752
+ sessionId: params.sessionId,
753
+ sessionKey: params.sessionKey,
754
+ toolName: params.call.tool,
755
+ toolCallId: params.call.callId
756
+ });
757
+ }
758
+ function emitDynamicToolErrorDiagnostic(params) {
759
+ emitTrustedDiagnosticEvent({
760
+ type: "tool.execution.error",
761
+ runId: params.runId,
762
+ sessionId: params.sessionId,
763
+ sessionKey: params.sessionKey,
764
+ toolName: params.call.tool,
765
+ toolCallId: params.call.callId,
766
+ durationMs: params.durationMs,
767
+ errorCategory: "codex_dynamic_tool_error"
768
+ });
769
+ }
770
+ function emitDynamicToolTerminalDiagnostic(params) {
771
+ const terminalType = params.response.diagnosticTerminalType ?? (params.response.success ? "completed" : "error");
772
+ if (terminalType === "completed") {
773
+ emitTrustedDiagnosticEvent({
774
+ type: "tool.execution.completed",
775
+ runId: params.runId,
776
+ sessionId: params.sessionId,
777
+ sessionKey: params.sessionKey,
778
+ toolName: params.call.tool,
779
+ toolCallId: params.call.callId,
780
+ durationMs: params.durationMs
781
+ });
782
+ return;
783
+ }
784
+ if (terminalType === "blocked") {
785
+ emitTrustedDiagnosticEvent({
786
+ type: "tool.execution.blocked",
787
+ runId: params.runId,
788
+ sessionId: params.sessionId,
789
+ sessionKey: params.sessionKey,
790
+ toolName: params.call.tool,
791
+ toolCallId: params.call.callId,
792
+ deniedReason: "plugin-before-tool-call",
793
+ reason: "Tool call blocked"
794
+ });
795
+ return;
796
+ }
797
+ emitDynamicToolErrorDiagnostic(params);
798
+ }
799
+ //#endregion
800
+ //#region extensions/codex/src/app-server/elicitation-bridge.ts
801
+ const MCP_TOOL_APPROVAL_KIND = "mcp_tool_call";
802
+ const MCP_TOOL_APPROVAL_KIND_KEY = "codex_approval_kind";
803
+ const MCP_TOOL_APPROVAL_CONNECTOR_NAME_KEY = "connector_name";
804
+ const MCP_TOOL_APPROVAL_TOOL_TITLE_KEY = "tool_title";
805
+ const MCP_TOOL_APPROVAL_TOOL_DESCRIPTION_KEY = "tool_description";
806
+ const MCP_TOOL_APPROVAL_TOOL_PARAMS_DISPLAY_KEY = "tool_params_display";
807
+ const MCP_TOOL_APPROVAL_SOURCE_KEY = "source";
808
+ const MCP_TOOL_APPROVAL_CONNECTOR_SOURCE = "connector";
809
+ const CODEX_APPS_SERVER_NAME = "codex_apps";
810
+ const PLUGIN_APP_ID_META_KEYS = [
811
+ "app_id",
812
+ "appId",
813
+ "codex_app_id",
814
+ "codexAppId"
815
+ ];
816
+ const PLUGIN_CONNECTOR_ID_META_KEYS = ["connector_id", "connectorId"];
817
+ const PLUGIN_NAME_META_KEYS = [
818
+ "plugin_name",
819
+ "pluginName",
820
+ "codex_plugin_name",
821
+ "codexPluginName"
822
+ ];
823
+ const PLUGIN_CONFIG_KEY_META_KEYS = [
824
+ "config_key",
825
+ "configKey",
826
+ "codex_config_key"
827
+ ];
828
+ const PLUGIN_MARKETPLACE_NAME_META_KEYS = [
829
+ "marketplace_name",
830
+ "marketplaceName",
831
+ "codex_marketplace_name",
832
+ "codexMarketplaceName"
833
+ ];
834
+ const MAX_DISPLAY_PARAM_ENTRIES = 8;
835
+ const MAX_DISPLAY_PARAM_VALUE_LENGTH = 120;
836
+ const MAX_DISPLAY_VALUE_ARRAY_ITEMS = 8;
837
+ const MAX_DISPLAY_VALUE_OBJECT_KEYS = 8;
838
+ const MAX_DISPLAY_VALUE_DEPTH = 3;
839
+ const DISPLAY_TEXT_SCAN_MAX_LENGTH = 4096;
840
+ const ANSI_OSC_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b]|\u009d)[^\u001b\u009c\u0007]*(?:\u0007|\u001b\\|\u009c)`, "g");
841
+ const ANSI_CONTROL_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b\[[0-?]*[ -/]*[@-~]|\u009b[0-?]*[ -/]*[@-~]|\u001b[@-Z\\-_])`, "g");
842
+ const CONTROL_CHARACTER_RE = new RegExp(String.raw`[\u0000-\u001f\u007f-\u009f]+`, "g");
843
+ const INVISIBLE_FORMATTING_CONTROL_RE = new RegExp(String.raw`[\u00ad\u034f\u061c\u200b-\u200f\u202a-\u202e\u2060-\u206f\ufeff\ufe00-\ufe0f\u{e0100}-\u{e01ef}]`, "gu");
844
+ const DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE = new RegExp(String.raw`(?:\u001b\][^\u001b\u009c\u0007]*|\u009d[^\u001b\u009c\u0007]*|\u001b\[[0-?]*[ -/]*|\u009b[0-?]*[ -/]*|\u001b)$`);
845
+ async function handleCodexAppServerElicitationRequest(params) {
846
+ const requestParams = isJsonObject(params.requestParams) ? params.requestParams : void 0;
847
+ if (!requestParams) return;
848
+ if (!matchesCurrentThread(requestParams, params.threadId)) return;
849
+ if (turnIdMismatches(requestParams, params.turnId)) return;
850
+ const pluginResolution = resolvePluginElicitation({
851
+ requestParams,
852
+ pluginAppPolicyContext: params.pluginAppPolicyContext
853
+ });
854
+ if (pluginResolution.kind !== "not_plugin") {
855
+ if (pluginResolution.kind === "decline") {
856
+ logPluginElicitationDecline(pluginResolution.reason, requestParams);
857
+ return declineElicitationResponse();
858
+ }
859
+ if (!hasExactTurnId(requestParams, params.turnId)) {
860
+ logPluginElicitationDecline("missing_active_turn", requestParams);
861
+ return declineElicitationResponse();
862
+ }
863
+ return buildPluginPolicyElicitationResponse(pluginResolution.entry, requestParams);
864
+ }
865
+ const approvalPrompt = readBridgeableApprovalElicitation(requestParams);
866
+ if (!approvalPrompt) return;
867
+ const outcome = await requestPluginApprovalOutcome({
868
+ paramsForRun: params.paramsForRun,
869
+ title: approvalPrompt.title,
870
+ description: approvalPrompt.description,
871
+ signal: params.signal
872
+ });
873
+ return buildElicitationResponse(approvalPrompt.requestedSchema, approvalPrompt.meta, outcome);
874
+ }
875
+ function matchesCurrentThread(requestParams, threadId) {
876
+ if (!requestParams) return false;
877
+ return readString(requestParams, "threadId") === threadId;
878
+ }
879
+ function turnIdMismatches(requestParams, turnId) {
880
+ const rawTurnId = requestParams?.turnId;
881
+ return rawTurnId !== null && rawTurnId !== void 0 && rawTurnId !== turnId;
882
+ }
883
+ function hasExactTurnId(requestParams, turnId) {
884
+ return requestParams?.turnId === turnId;
885
+ }
886
+ function resolvePluginElicitation(params) {
887
+ const requestParams = params.requestParams;
888
+ if (!requestParams) return { kind: "not_plugin" };
889
+ const meta = isJsonObject(requestParams["_meta"]) ? requestParams["_meta"] : {};
890
+ const context = params.pluginAppPolicyContext;
891
+ const entries = context ? Object.values(context.apps) : [];
892
+ const appId = readFirstString(meta, PLUGIN_APP_ID_META_KEYS) ?? readFirstString(requestParams, PLUGIN_APP_ID_META_KEYS);
893
+ const connectorId = readFirstString(meta, PLUGIN_CONNECTOR_ID_META_KEYS);
894
+ const isCodexConnectorApproval = isCodexConnectorApprovalElicitation(requestParams, meta);
895
+ if (isCodexConnectorApproval && appId && connectorId && appId !== connectorId) return {
896
+ kind: "decline",
897
+ reason: "app_id_connector_id_mismatch"
898
+ };
899
+ if (appId) {
900
+ if (!context) return {
901
+ kind: "decline",
902
+ reason: "missing_policy_context"
903
+ };
904
+ const entry = context.apps[appId];
905
+ return uniquePluginMatch(entry ? [entry] : [], "app_id");
906
+ }
907
+ if (isCodexConnectorApproval && connectorId) {
908
+ if (!context) return {
909
+ kind: "decline",
910
+ reason: "missing_policy_context"
911
+ };
912
+ const entry = context.apps[connectorId];
913
+ return uniquePluginMatch(entry ? [entry] : [], "connector_id");
914
+ }
915
+ const serverName = readString(requestParams, "serverName");
916
+ if (serverName && context) {
917
+ const matches = entries.filter((entry) => entry.mcpServerNames.includes(serverName));
918
+ if (matches.length > 0) return uniquePluginMatch(matches, "server_name");
919
+ }
920
+ const metadataResolution = resolvePluginStableMetadataMatch({
921
+ meta,
922
+ requestParams,
923
+ entries,
924
+ context
925
+ });
926
+ if (metadataResolution.kind !== "not_plugin") return metadataResolution;
927
+ if (context && hasDisplayNameOnlyPluginMatch(meta, entries)) return {
928
+ kind: "decline",
929
+ reason: "display_name_only"
930
+ };
931
+ return { kind: "not_plugin" };
932
+ }
933
+ function isCodexConnectorApprovalElicitation(requestParams, meta) {
934
+ return readString(requestParams, "serverName") === CODEX_APPS_SERVER_NAME && readString(meta, MCP_TOOL_APPROVAL_KIND_KEY) === MCP_TOOL_APPROVAL_KIND && readString(meta, MCP_TOOL_APPROVAL_SOURCE_KEY) === MCP_TOOL_APPROVAL_CONNECTOR_SOURCE;
935
+ }
936
+ function resolvePluginStableMetadataMatch(params) {
937
+ const pluginName = readFirstString(params.meta, PLUGIN_NAME_META_KEYS) ?? readFirstString(params.requestParams, PLUGIN_NAME_META_KEYS);
938
+ const configKey = readFirstString(params.meta, PLUGIN_CONFIG_KEY_META_KEYS) ?? readFirstString(params.requestParams, PLUGIN_CONFIG_KEY_META_KEYS);
939
+ const marketplaceName = readFirstString(params.meta, PLUGIN_MARKETPLACE_NAME_META_KEYS) ?? readFirstString(params.requestParams, PLUGIN_MARKETPLACE_NAME_META_KEYS);
940
+ if (!pluginName && !configKey) return { kind: "not_plugin" };
941
+ if (!params.context) return {
942
+ kind: "decline",
943
+ reason: "missing_policy_context"
944
+ };
945
+ return uniquePluginMatch(params.entries.filter((entry) => {
946
+ if (marketplaceName && entry.marketplaceName !== marketplaceName) return false;
947
+ if (pluginName && entry.pluginName !== pluginName) return false;
948
+ if (configKey && entry.configKey !== configKey) return false;
949
+ return true;
950
+ }), "metadata");
951
+ }
952
+ function uniquePluginMatch(matches, source) {
953
+ if (matches.length === 1 && matches[0]) return {
954
+ kind: "matched",
955
+ entry: matches[0]
956
+ };
957
+ return {
958
+ kind: "decline",
959
+ reason: matches.length === 0 ? `${source}_not_enabled` : `${source}_ambiguous`
960
+ };
961
+ }
962
+ function hasDisplayNameOnlyPluginMatch(meta, entries) {
963
+ const connectorName = readString(meta, MCP_TOOL_APPROVAL_CONNECTOR_NAME_KEY);
964
+ if (!connectorName) return false;
965
+ const normalized = normalizePluginIdentityText(connectorName);
966
+ return entries.some((entry) => normalizePluginIdentityText(entry.pluginName) === normalized || normalizePluginIdentityText(entry.configKey) === normalized);
967
+ }
968
+ function normalizePluginIdentityText(value) {
969
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "");
970
+ }
971
+ function buildPluginPolicyElicitationResponse(entry, requestParams) {
972
+ if (!entry.allowDestructiveActions) {
973
+ logPluginElicitationDecline("destructive_actions_disabled", requestParams);
974
+ return declineElicitationResponse();
975
+ }
976
+ if (readString(requestParams, "mode") !== "form" || !isJsonObject(requestParams.requestedSchema)) {
977
+ logPluginElicitationDecline("unsupported_schema", requestParams);
978
+ return declineElicitationResponse();
979
+ }
980
+ const meta = isJsonObject(requestParams["_meta"]) ? requestParams["_meta"] : {};
981
+ const response = buildElicitationResponse(requestParams.requestedSchema, meta, "approved-once");
982
+ if (isJsonObject(response) && response.action === "accept") return response;
983
+ logPluginElicitationDecline("unmappable_schema", requestParams);
984
+ return declineElicitationResponse();
985
+ }
986
+ function declineElicitationResponse() {
987
+ return {
988
+ action: "decline",
989
+ content: null,
990
+ _meta: null
991
+ };
992
+ }
993
+ function logPluginElicitationDecline(reason, requestParams) {
994
+ embeddedAgentLog.debug("codex plugin elicitation declined", {
995
+ reason,
996
+ serverName: readString(requestParams, "serverName"),
997
+ mode: readString(requestParams, "mode")
998
+ });
999
+ }
1000
+ function readBridgeableApprovalElicitation(requestParams) {
1001
+ if (!requestParams || readString(requestParams, "mode") !== "form" || !isJsonObject(requestParams["_meta"]) || requestParams["_meta"][MCP_TOOL_APPROVAL_KIND_KEY] !== MCP_TOOL_APPROVAL_KIND || !isJsonObject(requestParams.requestedSchema)) return;
1002
+ const requestedSchema = requestParams.requestedSchema;
1003
+ if (readString(requestedSchema, "type") !== "object" || !isJsonObject(requestedSchema.properties)) return;
1004
+ const title = sanitizeDisplayText(readString(requestParams, "message") ?? "") || "Codex MCP tool approval";
1005
+ return {
1006
+ title,
1007
+ description: buildApprovalDescription({
1008
+ title,
1009
+ meta: requestParams["_meta"],
1010
+ requestedSchema,
1011
+ serverName: sanitizeOptionalDisplayText(readString(requestParams, "serverName"))
1012
+ }),
1013
+ requestedSchema,
1014
+ meta: requestParams["_meta"]
1015
+ };
1016
+ }
1017
+ function buildApprovalDescription(params) {
1018
+ const connectorName = sanitizeOptionalDisplayText(readString(params.meta, MCP_TOOL_APPROVAL_CONNECTOR_NAME_KEY));
1019
+ const toolTitle = sanitizeOptionalDisplayText(readString(params.meta, MCP_TOOL_APPROVAL_TOOL_TITLE_KEY));
1020
+ const toolDescription = sanitizeOptionalDisplayText(readString(params.meta, MCP_TOOL_APPROVAL_TOOL_DESCRIPTION_KEY));
1021
+ const summaryLines = [
1022
+ connectorName && `App: ${connectorName}`,
1023
+ toolTitle && `Tool: ${toolTitle}`,
1024
+ params.serverName && `MCP server: ${params.serverName}`,
1025
+ toolDescription
1026
+ ].filter((line) => Boolean(line));
1027
+ const paramLines = readDisplayParamLines(params.meta);
1028
+ const propertyLines = readPropertyDescriptionLines(params.requestedSchema);
1029
+ return [
1030
+ params.title,
1031
+ summaryLines.join("\n"),
1032
+ paramLines.length > 0 ? ["Parameters:", ...paramLines].join("\n") : "",
1033
+ propertyLines.length > 0 ? ["Fields:", ...propertyLines].join("\n") : ""
1034
+ ].filter(Boolean).join("\n\n");
1035
+ }
1036
+ function readPropertyDescriptionLines(requestedSchema) {
1037
+ const properties = isJsonObject(requestedSchema.properties) ? requestedSchema.properties : {};
1038
+ return Object.entries(properties).map(([name, value]) => {
1039
+ const schema = isJsonObject(value) ? value : void 0;
1040
+ if (!schema) return;
1041
+ const propTitle = sanitizeDisplayText(readString(schema, "title") ?? "") || sanitizeDisplayText(name) || "field";
1042
+ const description = sanitizeOptionalDisplayText(readString(schema, "description"));
1043
+ return description ? `- ${propTitle}: ${description}` : `- ${propTitle}`;
1044
+ }).filter((line) => Boolean(line));
1045
+ }
1046
+ function readDisplayParamLines(meta) {
1047
+ const displayParams = meta[MCP_TOOL_APPROVAL_TOOL_PARAMS_DISPLAY_KEY];
1048
+ if (!Array.isArray(displayParams)) return [];
1049
+ const lines = displayParams.slice(0, MAX_DISPLAY_PARAM_ENTRIES).map((entry) => {
1050
+ const param = isJsonObject(entry) ? entry : void 0;
1051
+ if (!param) return;
1052
+ const name = sanitizeOptionalDisplayText(readString(param, "display_name")) ?? sanitizeOptionalDisplayText(readString(param, "name"));
1053
+ if (!name) return;
1054
+ return `- ${name}: ${formatDisplayParamValue(param.value)}`;
1055
+ }).filter((line) => Boolean(line));
1056
+ const remaining = displayParams.length - MAX_DISPLAY_PARAM_ENTRIES;
1057
+ return remaining > 0 ? [...lines, `- Additional parameters: ${remaining} more`] : lines;
1058
+ }
1059
+ function formatDisplayParamValue(value) {
1060
+ return truncateDisplayText(sanitizeDisplayText(typeof value === "string" ? value : formatDisplayJsonValue(value ?? null)), MAX_DISPLAY_PARAM_VALUE_LENGTH);
1061
+ }
1062
+ function formatDisplayJsonValue(value, depth = MAX_DISPLAY_VALUE_DEPTH) {
1063
+ if (value === null) return "null";
1064
+ if (typeof value === "string") return JSON.stringify(truncateDisplayText(sanitizeDisplayText(value), 80));
1065
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
1066
+ if (Array.isArray(value)) {
1067
+ if (depth <= 0) return "[truncated]";
1068
+ const parts = [];
1069
+ const limit = Math.min(value.length, MAX_DISPLAY_VALUE_ARRAY_ITEMS);
1070
+ for (let i = 0; i < limit; i += 1) parts.push(formatDisplayJsonValue(value[i] ?? null, depth - 1));
1071
+ if (value.length > MAX_DISPLAY_VALUE_ARRAY_ITEMS) parts.push("...");
1072
+ return `[${parts.join(",")}]`;
1073
+ }
1074
+ if (typeof value === "object") {
1075
+ if (depth <= 0) return "{truncated}";
1076
+ const parts = [];
1077
+ let count = 0;
1078
+ let truncated = false;
1079
+ for (const key in value) {
1080
+ if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
1081
+ if (count >= MAX_DISPLAY_VALUE_OBJECT_KEYS) {
1082
+ truncated = true;
1083
+ break;
1084
+ }
1085
+ const safeKey = truncateDisplayText(sanitizeDisplayText(key), 80);
1086
+ parts.push(`${JSON.stringify(safeKey)}:${formatDisplayJsonValue(value[key] ?? null, depth - 1)}`);
1087
+ count += 1;
1088
+ }
1089
+ if (truncated) parts.push("...");
1090
+ return `{${parts.join(",")}}`;
1091
+ }
1092
+ return "null";
1093
+ }
1094
+ function sanitizeOptionalDisplayText(value) {
1095
+ return (value === void 0 ? "" : sanitizeDisplayText(value)) || void 0;
1096
+ }
1097
+ function sanitizeDisplayText(value) {
1098
+ const scanned = value.slice(0, DISPLAY_TEXT_SCAN_MAX_LENGTH);
1099
+ const clipped = value.length > DISPLAY_TEXT_SCAN_MAX_LENGTH;
1100
+ const sanitized = scanned.replace(ANSI_OSC_SEQUENCE_RE, "").replace(ANSI_CONTROL_SEQUENCE_RE, "").replace(DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE, "").replace(INVISIBLE_FORMATTING_CONTROL_RE, " ").replace(CONTROL_CHARACTER_RE, " ").replace(/\s+/g, " ").trim();
1101
+ const escaped = sanitized ? formatCodexDisplayText(sanitized) : "";
1102
+ return clipped && escaped ? `${escaped}...` : escaped;
1103
+ }
1104
+ function truncateDisplayText(value, maxLength) {
1105
+ return value.length <= maxLength ? value : `${value.slice(0, Math.max(0, maxLength - 3))}...`;
1106
+ }
1107
+ async function requestPluginApprovalOutcome(params) {
1108
+ try {
1109
+ const requestResult = await requestPluginApproval({
1110
+ paramsForRun: params.paramsForRun,
1111
+ title: params.title,
1112
+ description: params.description,
1113
+ severity: "warning",
1114
+ toolName: "codex_mcp_tool_approval"
1115
+ });
1116
+ const approvalId = requestResult?.id;
1117
+ if (!approvalId) return "unavailable";
1118
+ return mapExecDecisionToOutcome(approvalRequestExplicitlyUnavailable(requestResult) ? null : await waitForPluginApprovalDecision({
1119
+ approvalId,
1120
+ signal: params.signal
1121
+ }));
1122
+ } catch {
1123
+ return params.signal?.aborted ? "cancelled" : "denied";
1124
+ }
1125
+ }
1126
+ function buildElicitationResponse(requestedSchema, meta, outcome) {
1127
+ if (outcome === "cancelled") return {
1128
+ action: "cancel",
1129
+ content: null,
1130
+ _meta: null
1131
+ };
1132
+ if (outcome === "denied" || outcome === "unavailable") return {
1133
+ action: "decline",
1134
+ content: null,
1135
+ _meta: null
1136
+ };
1137
+ const content = buildAcceptedContent(requestedSchema, meta, outcome);
1138
+ if (!content) {
1139
+ if (hasNoSchemaProperties(requestedSchema)) return {
1140
+ action: "accept",
1141
+ content: null,
1142
+ _meta: buildAcceptedMeta(meta, outcome)
1143
+ };
1144
+ embeddedAgentLog.warn("codex MCP approval elicitation approved without a mappable response", {
1145
+ approvalKind: meta[MCP_TOOL_APPROVAL_KIND_KEY],
1146
+ fields: Object.keys(requestedSchema.properties ?? {}),
1147
+ outcome
1148
+ });
1149
+ return {
1150
+ action: "decline",
1151
+ content: null,
1152
+ _meta: null
1153
+ };
1154
+ }
1155
+ return {
1156
+ action: "accept",
1157
+ content,
1158
+ _meta: buildAcceptedMeta(meta, outcome)
1159
+ };
1160
+ }
1161
+ function buildAcceptedContent(requestedSchema, meta, outcome) {
1162
+ const properties = isJsonObject(requestedSchema.properties) ? requestedSchema.properties : void 0;
1163
+ if (!properties) return;
1164
+ const required = Array.isArray(requestedSchema.required) ? new Set(requestedSchema.required.filter((entry) => typeof entry === "string")) : /* @__PURE__ */ new Set();
1165
+ const content = {};
1166
+ let sawApprovalField = false;
1167
+ for (const [name, value] of Object.entries(properties)) {
1168
+ const schema = isJsonObject(value) ? value : void 0;
1169
+ if (!schema) continue;
1170
+ const property = {
1171
+ name,
1172
+ schema,
1173
+ required: required.has(name)
1174
+ };
1175
+ const next = readApprovalFieldValue(property, outcome) ?? readPersistFieldValue(property, meta, outcome) ?? readFallbackFieldValue(property, outcome);
1176
+ if (next === void 0) {
1177
+ if (isApprovalField(property)) sawApprovalField = true;
1178
+ if (property.required) return;
1179
+ continue;
1180
+ }
1181
+ if (isApprovalField(property)) sawApprovalField = true;
1182
+ content[name] = next;
1183
+ }
1184
+ return sawApprovalField ? content : void 0;
1185
+ }
1186
+ function readApprovalFieldValue(property, outcome) {
1187
+ if (!isApprovalField(property)) return;
1188
+ if (readString(property.schema, "type") === "boolean") return true;
1189
+ const options = readEnumOptions(property.schema);
1190
+ if (options.length === 0) return;
1191
+ const sessionChoice = options.find((option) => isSessionApprovalOption(option));
1192
+ const acceptChoice = options.find((option) => isPositiveApprovalOption(option));
1193
+ if (outcome === "approved-session") return sessionChoice?.value ?? acceptChoice?.value;
1194
+ return acceptChoice?.value ?? sessionChoice?.value;
1195
+ }
1196
+ function readPersistFieldValue(property, meta, outcome) {
1197
+ if (!isPersistField(property) || outcome !== "approved-session") return;
1198
+ const persistHints = readPersistHints(meta);
1199
+ const options = readEnumOptions(property.schema);
1200
+ if (options.length === 0) return;
1201
+ const preferred = choosePersistHint(persistHints);
1202
+ if (preferred) return options.find((option) => option.value === preferred || option.label === preferred)?.value;
1203
+ }
1204
+ function readDefaultValue(schema) {
1205
+ return schema.default;
1206
+ }
1207
+ function readFallbackFieldValue(property, outcome) {
1208
+ if (outcome === "approved-once" && isPersistField(property)) return;
1209
+ return readDefaultValue(property.schema);
1210
+ }
1211
+ function isApprovalField(property) {
1212
+ const haystack = propertyText(property).toLowerCase();
1213
+ return /\b(approve|approval|allow|accept|decision)\b/.test(haystack);
1214
+ }
1215
+ function isPersistField(property) {
1216
+ const haystack = propertyText(property).toLowerCase();
1217
+ return /\b(persist|session|always|scope)\b/.test(haystack);
1218
+ }
1219
+ function propertyText(property) {
1220
+ return [
1221
+ property.name,
1222
+ readString(property.schema, "title"),
1223
+ readString(property.schema, "description")
1224
+ ].filter(Boolean).join(" ");
1225
+ }
1226
+ function readPersistHints(meta) {
1227
+ const raw = meta.persist;
1228
+ if (typeof raw === "string") return [raw];
1229
+ if (Array.isArray(raw)) return raw.filter((entry) => typeof entry === "string");
1230
+ return ["session", "always"];
1231
+ }
1232
+ function buildAcceptedMeta(meta, outcome) {
1233
+ if (outcome !== "approved-session") return null;
1234
+ const persist = choosePersistHint(readPersistHints(meta));
1235
+ return persist ? { persist } : null;
1236
+ }
1237
+ function choosePersistHint(persistHints) {
1238
+ if (persistHints.includes("always")) return "always";
1239
+ if (persistHints.includes("session")) return "session";
1240
+ }
1241
+ function hasNoSchemaProperties(requestedSchema) {
1242
+ const properties = isJsonObject(requestedSchema.properties) ? requestedSchema.properties : {};
1243
+ return Object.keys(properties).length === 0;
1244
+ }
1245
+ function readEnumOptions(schema) {
1246
+ if (Array.isArray(schema.enum)) {
1247
+ const values = schema.enum.filter((entry) => typeof entry === "string");
1248
+ const labels = Array.isArray(schema.enumNames) ? schema.enumNames.filter((entry) => typeof entry === "string") : [];
1249
+ return values.map((value, index) => ({
1250
+ value,
1251
+ label: labels[index] ?? value
1252
+ }));
1253
+ }
1254
+ if (Array.isArray(schema.oneOf)) return schema.oneOf.map((entry) => {
1255
+ const option = isJsonObject(entry) ? entry : void 0;
1256
+ const value = readString(option, "const");
1257
+ if (!value) return;
1258
+ return {
1259
+ value,
1260
+ label: readString(option, "title") ?? value
1261
+ };
1262
+ }).filter((entry) => Boolean(entry));
1263
+ return [];
1264
+ }
1265
+ function isPositiveApprovalOption(option) {
1266
+ const haystack = `${option.value} ${option.label}`.toLowerCase();
1267
+ return /\b(allow|approve|accept|yes|continue|proceed|true)\b/.test(haystack);
1268
+ }
1269
+ function isSessionApprovalOption(option) {
1270
+ const haystack = `${option.value} ${option.label}`.toLowerCase();
1271
+ return /\b(session|always|persistent)\b/.test(haystack) && /\b(allow|approve|accept)\b/.test(haystack);
1272
+ }
1273
+ function readString(record, key) {
1274
+ const value = record?.[key];
1275
+ return typeof value === "string" && value.trim() ? value : void 0;
1276
+ }
1277
+ function readFirstString(record, keys) {
1278
+ for (const key of keys) {
1279
+ const value = readString(record, key);
1280
+ if (value) return value;
1281
+ }
1282
+ }
1283
+ //#endregion
1284
+ //#region extensions/codex/src/app-server/native-hook-relay.ts
1285
+ const CODEX_NATIVE_HOOK_RELAY_EVENTS = [
1286
+ "pre_tool_use",
1287
+ "post_tool_use",
1288
+ "permission_request",
1289
+ "before_agent_finalize"
1290
+ ];
1291
+ const CODEX_HOOK_EVENT_BY_NATIVE_EVENT = {
1292
+ pre_tool_use: "PreToolUse",
1293
+ post_tool_use: "PostToolUse",
1294
+ permission_request: "PermissionRequest",
1295
+ before_agent_finalize: "Stop"
1296
+ };
1297
+ const CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT = {
1298
+ pre_tool_use: "pre_tool_use",
1299
+ post_tool_use: "post_tool_use",
1300
+ permission_request: "permission_request",
1301
+ before_agent_finalize: "stop"
1302
+ };
1303
+ const CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS = ["/<session-flags>/config.toml", "<session-flags>/config.toml"];
1304
+ function buildCodexNativeHookRelayConfig(params) {
1305
+ const events = params.events?.length ? params.events : CODEX_NATIVE_HOOK_RELAY_EVENTS;
1306
+ const selectedEvents = new Set(events);
1307
+ const config = { "features.hooks": true };
1308
+ const hookState = {};
1309
+ for (const event of CODEX_NATIVE_HOOK_RELAY_EVENTS) {
1310
+ const codexEvent = CODEX_HOOK_EVENT_BY_NATIVE_EVENT[event];
1311
+ const selected = selectedEvents.has(event);
1312
+ if (!selected || !params.relay.shouldRelayEvent(event)) {
1313
+ if (selected || params.clearOmittedEvents) config[`hooks.${codexEvent}`] = [];
1314
+ if (params.clearOmittedEvents) for (const sourcePath of CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS) hookState[`${sourcePath}:${CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[event]}:0:0`] = { enabled: false };
1315
+ continue;
1316
+ }
1317
+ const command = params.relay.commandForEvent(event);
1318
+ const timeout = normalizeHookTimeoutSec(params.hookTimeoutSec);
1319
+ config[`hooks.${codexEvent}`] = [{ hooks: [{
1320
+ type: "command",
1321
+ command,
1322
+ timeout,
1323
+ async: false,
1324
+ statusMessage: "AutoBot native hook relay"
1325
+ }] }];
1326
+ const state = {
1327
+ enabled: true,
1328
+ trusted_hash: codexCommandHookTrustedHash({
1329
+ event,
1330
+ command,
1331
+ timeout,
1332
+ statusMessage: "AutoBot native hook relay"
1333
+ })
1334
+ };
1335
+ for (const sourcePath of CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS) hookState[`${sourcePath}:${CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[event]}:0:0`] = state;
1336
+ }
1337
+ config["hooks.state"] = hookState;
1338
+ return config;
1339
+ }
1340
+ function buildCodexNativeHookRelayDisabledConfig() {
1341
+ return {
1342
+ "features.hooks": false,
1343
+ "hooks.PreToolUse": [],
1344
+ "hooks.PostToolUse": [],
1345
+ "hooks.PermissionRequest": [],
1346
+ "hooks.Stop": []
1347
+ };
1348
+ }
1349
+ function normalizeHookTimeoutSec(value) {
1350
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.ceil(value) : 5;
1351
+ }
1352
+ function codexCommandHookTrustedHash(params) {
1353
+ const identity = {
1354
+ event_name: CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[params.event],
1355
+ hooks: [{
1356
+ async: false,
1357
+ command: params.command,
1358
+ statusMessage: params.statusMessage,
1359
+ timeout: params.timeout,
1360
+ type: "command"
1361
+ }]
1362
+ };
1363
+ return `sha256:${createHash("sha256").update(JSON.stringify(sortJsonValue(identity))).digest("hex")}`;
1364
+ }
1365
+ function sortJsonValue(value) {
1366
+ if (!value || typeof value !== "object") return value;
1367
+ if (Array.isArray(value)) return value.map(sortJsonValue);
1368
+ const sorted = {};
1369
+ for (const key of Object.keys(value).toSorted()) sorted[key] = sortJsonValue(value[key]);
1370
+ return sorted;
1371
+ }
1372
+ //#endregion
1373
+ //#region extensions/codex/src/app-server/vision-tools.ts
1374
+ function filterToolsForVisionInputs(tools, params) {
1375
+ if (!params.modelHasVision || !params.hasInboundImages) return tools;
1376
+ return tools.filter((tool) => tool.name !== "image");
1377
+ }
1378
+ //#endregion
1379
+ export { handleCodexAppServerElicitationRequest as a, emitDynamicToolTerminalDiagnostic as c, buildCodexNativeHookRelayDisabledConfig as i, handleCodexAppServerApprovalRequest as l, CODEX_NATIVE_HOOK_RELAY_EVENTS as n, emitDynamicToolErrorDiagnostic as o, buildCodexNativeHookRelayConfig as r, emitDynamicToolStartedDiagnostic as s, filterToolsForVisionInputs as t };