@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
@@ -1,150 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import type {
3
- NativeHookRelayEvent,
4
- NativeHookRelayRegistrationHandle,
5
- } from "autobot/plugin-sdk/agent-harness-runtime";
6
- import type { JsonObject, JsonValue } from "./protocol.js";
7
-
8
- export const CODEX_NATIVE_HOOK_RELAY_EVENTS: readonly NativeHookRelayEvent[] = [
9
- "pre_tool_use",
10
- "post_tool_use",
11
- "permission_request",
12
- "before_agent_finalize",
13
- ] as const;
14
-
15
- type CodexHookEventName = "PreToolUse" | "PostToolUse" | "PermissionRequest" | "Stop";
16
-
17
- const CODEX_HOOK_EVENT_BY_NATIVE_EVENT: Record<NativeHookRelayEvent, CodexHookEventName> = {
18
- pre_tool_use: "PreToolUse",
19
- post_tool_use: "PostToolUse",
20
- permission_request: "PermissionRequest",
21
- before_agent_finalize: "Stop",
22
- };
23
-
24
- const CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT: Record<NativeHookRelayEvent, string> = {
25
- pre_tool_use: "pre_tool_use",
26
- post_tool_use: "post_tool_use",
27
- permission_request: "permission_request",
28
- before_agent_finalize: "stop",
29
- };
30
-
31
- const CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS = [
32
- "/<session-flags>/config.toml",
33
- "<session-flags>/config.toml",
34
- ] as const;
35
-
36
- export function buildCodexNativeHookRelayConfig(params: {
37
- relay: NativeHookRelayRegistrationHandle;
38
- events?: readonly NativeHookRelayEvent[];
39
- hookTimeoutSec?: number;
40
- clearOmittedEvents?: boolean;
41
- }): JsonObject {
42
- const events = params.events?.length ? params.events : CODEX_NATIVE_HOOK_RELAY_EVENTS;
43
- const selectedEvents = new Set<NativeHookRelayEvent>(events);
44
- const config: JsonObject = {
45
- "features.hooks": true,
46
- };
47
- const hookState: JsonObject = {};
48
- for (const event of CODEX_NATIVE_HOOK_RELAY_EVENTS) {
49
- const codexEvent = CODEX_HOOK_EVENT_BY_NATIVE_EVENT[event];
50
- const selected = selectedEvents.has(event);
51
- if (!selected || !params.relay.shouldRelayEvent(event)) {
52
- if (selected || params.clearOmittedEvents) {
53
- config[`hooks.${codexEvent}`] = [] satisfies JsonValue;
54
- }
55
- if (params.clearOmittedEvents) {
56
- for (const sourcePath of CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS) {
57
- hookState[`${sourcePath}:${CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[event]}:0:0`] = {
58
- enabled: false,
59
- } satisfies JsonValue;
60
- }
61
- }
62
- continue;
63
- }
64
- const command = params.relay.commandForEvent(event);
65
- const timeout = normalizeHookTimeoutSec(params.hookTimeoutSec);
66
- config[`hooks.${codexEvent}`] = [
67
- {
68
- hooks: [
69
- {
70
- type: "command",
71
- command,
72
- timeout,
73
- async: false,
74
- statusMessage: "AutoBot native hook relay",
75
- },
76
- ],
77
- },
78
- ] satisfies JsonValue;
79
- const state = {
80
- enabled: true,
81
- trusted_hash: codexCommandHookTrustedHash({
82
- event,
83
- command,
84
- timeout,
85
- statusMessage: "AutoBot native hook relay",
86
- }),
87
- };
88
- for (const sourcePath of CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS) {
89
- hookState[`${sourcePath}:${CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[event]}:0:0`] =
90
- state satisfies JsonValue;
91
- }
92
- }
93
- config["hooks.state"] = hookState;
94
- return config;
95
- }
96
-
97
- export function buildCodexNativeHookRelayDisabledConfig(): JsonObject {
98
- return {
99
- "features.hooks": false,
100
- "hooks.PreToolUse": [],
101
- "hooks.PostToolUse": [],
102
- "hooks.PermissionRequest": [],
103
- "hooks.Stop": [],
104
- };
105
- }
106
-
107
- function normalizeHookTimeoutSec(value: number | undefined): number {
108
- return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.ceil(value) : 5;
109
- }
110
-
111
- function codexCommandHookTrustedHash(params: {
112
- event: NativeHookRelayEvent;
113
- command: string;
114
- timeout: number;
115
- statusMessage: string;
116
- }): string {
117
- // Keep the match-all matcher omitted rather than null. Codex app-server
118
- // converts JSON null to an empty TOML string before hashing, which changes the
119
- // trust identity even though both forms match all tools.
120
- const identity = {
121
- event_name: CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[params.event],
122
- hooks: [
123
- {
124
- async: false,
125
- command: params.command,
126
- statusMessage: params.statusMessage,
127
- timeout: params.timeout,
128
- type: "command",
129
- },
130
- ],
131
- };
132
- const hash = createHash("sha256")
133
- .update(JSON.stringify(sortJsonValue(identity)))
134
- .digest("hex");
135
- return `sha256:${hash}`;
136
- }
137
-
138
- function sortJsonValue(value: JsonValue): JsonValue {
139
- if (!value || typeof value !== "object") {
140
- return value;
141
- }
142
- if (Array.isArray(value)) {
143
- return value.map(sortJsonValue);
144
- }
145
- const sorted: JsonObject = {};
146
- for (const key of Object.keys(value).toSorted()) {
147
- sorted[key] = sortJsonValue(value[key]);
148
- }
149
- return sorted;
150
- }
@@ -1,497 +0,0 @@
1
- import {
2
- CODEX_NATIVE_SUBAGENT_RUN_ID_PREFIX,
3
- CODEX_NATIVE_SUBAGENT_RUNTIME,
4
- CODEX_NATIVE_SUBAGENT_TASK_KIND,
5
- createRunningTaskRun,
6
- finalizeTaskRunByRunId,
7
- recordTaskRunProgressByRunId,
8
- } from "autobot/plugin-sdk/codex-native-task-runtime";
9
- import type {
10
- CodexServerNotification,
11
- CodexSessionSource,
12
- CodexSubAgentThreadSpawnSource,
13
- CodexThread,
14
- CodexThreadStartedNotification,
15
- CodexThreadStatus,
16
- CodexThreadStatusChangedNotification,
17
- JsonObject,
18
- JsonValue,
19
- } from "./protocol.js";
20
- import { isJsonObject } from "./protocol.js";
21
-
22
- export type TaskLifecycleRuntime = {
23
- createRunningTaskRun: typeof createRunningTaskRun;
24
- recordTaskRunProgressByRunId: typeof recordTaskRunProgressByRunId;
25
- finalizeTaskRunByRunId: typeof finalizeTaskRunByRunId;
26
- };
27
-
28
- export type CodexNativeSubagentTaskMirrorParams = {
29
- parentThreadId: string;
30
- requesterSessionKey?: string;
31
- agentId?: string;
32
- now?: () => number;
33
- };
34
-
35
- const defaultRuntime: TaskLifecycleRuntime = {
36
- createRunningTaskRun,
37
- recordTaskRunProgressByRunId,
38
- finalizeTaskRunByRunId,
39
- };
40
-
41
- export class CodexNativeSubagentTaskMirror {
42
- private readonly mirroredThreadIds = new Set<string>();
43
- private readonly terminalRunIds = new Set<string>();
44
- private readonly now: () => number;
45
-
46
- constructor(
47
- private readonly params: CodexNativeSubagentTaskMirrorParams,
48
- private readonly runtime: TaskLifecycleRuntime = defaultRuntime,
49
- ) {
50
- this.now = params.now ?? Date.now;
51
- }
52
-
53
- handleNotification(notification: CodexServerNotification): void {
54
- const params = isJsonObject(notification.params) ? notification.params : undefined;
55
- if (!params) {
56
- return;
57
- }
58
- if (notification.method === "thread/started") {
59
- this.handleThreadStarted(params);
60
- return;
61
- }
62
- if (notification.method === "thread/status/changed") {
63
- this.handleThreadStatusChanged(params);
64
- return;
65
- }
66
- if (notification.method === "item/started" || notification.method === "item/completed") {
67
- this.handleCollabAgentItem(params);
68
- }
69
- }
70
-
71
- private handleThreadStarted(params: JsonObject): void {
72
- const notification = readThreadStartedNotification(params);
73
- if (!notification) {
74
- return;
75
- }
76
- const thread = notification.thread;
77
- const spawn = readSubagentThreadSpawnSource(thread.source, this.params.parentThreadId);
78
- if (!spawn) {
79
- return;
80
- }
81
- const threadId = thread.id.trim();
82
- if (!threadId || this.mirroredThreadIds.has(threadId)) {
83
- return;
84
- }
85
- this.mirroredThreadIds.add(threadId);
86
- const runId = codexNativeSubagentRunId(threadId);
87
- const label =
88
- trimOptional(spawn.agent_nickname) ??
89
- trimOptional(thread.agentNickname) ??
90
- trimOptional(spawn.agent_role) ??
91
- trimOptional(thread.agentRole) ??
92
- "Codex subagent";
93
- const task =
94
- trimOptional(thread.preview) ??
95
- `Codex native subagent${label === "Codex subagent" ? "" : ` ${label}`}`;
96
- const createdAt = secondsToMillis(thread.createdAt) ?? this.now();
97
- this.runtime.createRunningTaskRun({
98
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
99
- taskKind: CODEX_NATIVE_SUBAGENT_TASK_KIND,
100
- sourceId: runId,
101
- requesterSessionKey: this.params.requesterSessionKey,
102
- ...(this.params.requesterSessionKey
103
- ? {
104
- ownerKey: this.params.requesterSessionKey,
105
- scopeKind: "session" as const,
106
- }
107
- : {}),
108
- agentId: this.params.agentId,
109
- runId,
110
- label,
111
- task,
112
- notifyPolicy: "silent",
113
- deliveryStatus: "not_applicable",
114
- preferMetadata: true,
115
- startedAt: createdAt,
116
- lastEventAt: this.now(),
117
- progressSummary: "Codex native subagent started.",
118
- });
119
- this.applyStatus(threadId, thread.status);
120
- }
121
-
122
- private handleThreadStatusChanged(params: JsonObject): void {
123
- const notification = readThreadStatusChangedNotification(params);
124
- if (!notification) {
125
- return;
126
- }
127
- this.applyStatus(notification.threadId, notification.status);
128
- }
129
-
130
- private applyStatus(threadId: string, status: CodexThreadStatus | null | undefined): void {
131
- const statusType = status?.type;
132
- if (!statusType) {
133
- return;
134
- }
135
- const runId = codexNativeSubagentRunId(threadId);
136
- if (this.terminalRunIds.has(runId) && statusType !== "systemError") {
137
- return;
138
- }
139
- const eventAt = this.now();
140
- if (statusType === "active") {
141
- this.runtime.recordTaskRunProgressByRunId({
142
- runId,
143
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
144
- lastEventAt: eventAt,
145
- progressSummary: "Codex native subagent is active.",
146
- });
147
- return;
148
- }
149
- if (statusType === "idle") {
150
- this.terminalRunIds.add(runId);
151
- this.runtime.finalizeTaskRunByRunId({
152
- runId,
153
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
154
- status: "succeeded",
155
- endedAt: eventAt,
156
- lastEventAt: eventAt,
157
- progressSummary: "Codex native subagent is idle.",
158
- terminalSummary: "Codex native subagent finished.",
159
- });
160
- return;
161
- }
162
- if (statusType === "systemError") {
163
- this.terminalRunIds.add(runId);
164
- this.runtime.finalizeTaskRunByRunId({
165
- runId,
166
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
167
- status: "failed",
168
- endedAt: eventAt,
169
- lastEventAt: eventAt,
170
- error: "Codex app-server reported a system error for the native subagent thread.",
171
- progressSummary: "Codex native subagent hit a system error.",
172
- terminalSummary: "Codex native subagent failed.",
173
- });
174
- return;
175
- }
176
- if (statusType === "notLoaded") {
177
- this.runtime.recordTaskRunProgressByRunId({
178
- runId,
179
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
180
- lastEventAt: eventAt,
181
- progressSummary: "Codex native subagent is not loaded.",
182
- });
183
- }
184
- }
185
-
186
- private handleCollabAgentItem(params: JsonObject): void {
187
- const item = isJsonObject(params.item) ? params.item : undefined;
188
- if (!item || readString(item, "type") !== "collabAgentToolCall") {
189
- return;
190
- }
191
- if (readString(item, "senderThreadId") !== this.params.parentThreadId) {
192
- return;
193
- }
194
- const receiverThreadIds = readStringArray(item.receiverThreadIds);
195
- const isSpawnAgentTool = normalizeToolName(readString(item, "tool")) === "spawnagent";
196
- if (isSpawnAgentTool) {
197
- for (const receiverThreadId of receiverThreadIds) {
198
- this.createTaskFromCollabSpawnItem(receiverThreadId, item);
199
- }
200
- }
201
- const agentsStates = readAgentsStates(item.agentsStates);
202
- const toolCallStatus = normalizeCollabToolCallStatus(readString(item, "status"));
203
- const terminalToolCallThreadIds = new Set<string>();
204
- if (isSpawnAgentTool && isBlockedOrFailedCollabToolCallStatus(toolCallStatus)) {
205
- for (const threadId of receiverThreadIds) {
206
- terminalToolCallThreadIds.add(threadId);
207
- }
208
- for (const threadId of agentsStates.keys()) {
209
- terminalToolCallThreadIds.add(threadId);
210
- }
211
- }
212
- const terminalAgentStateThreadIds = new Set<string>();
213
- for (const [threadId, state] of agentsStates) {
214
- const normalizedStatus = normalizeAgentStateStatus(state.status);
215
- if (
216
- terminalToolCallThreadIds.has(threadId) &&
217
- isNonTerminalAgentStateStatus(normalizedStatus)
218
- ) {
219
- continue;
220
- }
221
- this.applyCollabAgentStatus(threadId, normalizedStatus, state.message);
222
- if (isTerminalAgentStateStatus(normalizedStatus)) {
223
- terminalAgentStateThreadIds.add(threadId);
224
- }
225
- }
226
- if (isBlockedOrFailedCollabToolCallStatus(toolCallStatus)) {
227
- for (const threadId of terminalToolCallThreadIds) {
228
- if (terminalAgentStateThreadIds.has(threadId)) {
229
- continue;
230
- }
231
- const state = agentsStates.get(threadId);
232
- this.applyCollabAgentStatus(threadId, toolCallStatus, state?.message);
233
- }
234
- }
235
- }
236
-
237
- private createTaskFromCollabSpawnItem(threadId: string, item: JsonObject): void {
238
- const normalizedThreadId = threadId.trim();
239
- if (!normalizedThreadId || this.mirroredThreadIds.has(normalizedThreadId)) {
240
- return;
241
- }
242
- this.mirroredThreadIds.add(normalizedThreadId);
243
- const prompt = trimOptional(readString(item, "prompt"));
244
- const runId = codexNativeSubagentRunId(normalizedThreadId);
245
- const createdAt = this.now();
246
- this.runtime.createRunningTaskRun({
247
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
248
- taskKind: CODEX_NATIVE_SUBAGENT_TASK_KIND,
249
- sourceId: runId,
250
- requesterSessionKey: this.params.requesterSessionKey,
251
- ...(this.params.requesterSessionKey
252
- ? {
253
- ownerKey: this.params.requesterSessionKey,
254
- scopeKind: "session" as const,
255
- }
256
- : {}),
257
- agentId: this.params.agentId,
258
- runId,
259
- label: "Codex subagent",
260
- task: prompt ?? "Codex native subagent",
261
- notifyPolicy: "silent",
262
- deliveryStatus: "not_applicable",
263
- preferMetadata: true,
264
- startedAt: createdAt,
265
- lastEventAt: createdAt,
266
- progressSummary: "Codex native subagent spawned.",
267
- });
268
- }
269
-
270
- private applyCollabAgentStatus(
271
- threadId: string,
272
- status: string | undefined,
273
- message: string | null | undefined,
274
- ): void {
275
- const normalizedStatus = normalizeAgentStateStatus(status);
276
- if (!normalizedStatus) {
277
- return;
278
- }
279
- const runId = codexNativeSubagentRunId(threadId);
280
- if (this.terminalRunIds.has(runId) && isNonTerminalAgentStateStatus(normalizedStatus)) {
281
- return;
282
- }
283
- const eventAt = this.now();
284
- if (normalizedStatus === "pendingInit" || normalizedStatus === "running") {
285
- this.runtime.recordTaskRunProgressByRunId({
286
- runId,
287
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
288
- lastEventAt: eventAt,
289
- progressSummary:
290
- trimOptional(message) ??
291
- (normalizedStatus === "pendingInit"
292
- ? "Codex native subagent is initializing."
293
- : "Codex native subagent is running."),
294
- });
295
- return;
296
- }
297
- if (normalizedStatus === "completed") {
298
- this.terminalRunIds.add(runId);
299
- this.runtime.finalizeTaskRunByRunId({
300
- runId,
301
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
302
- status: "succeeded",
303
- endedAt: eventAt,
304
- lastEventAt: eventAt,
305
- progressSummary: trimOptional(message) ?? "Codex native subagent completed.",
306
- terminalSummary: trimOptional(message) ?? "Codex native subagent finished.",
307
- });
308
- return;
309
- }
310
- if (normalizedStatus === "blocked") {
311
- this.terminalRunIds.add(runId);
312
- this.runtime.finalizeTaskRunByRunId({
313
- runId,
314
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
315
- status: "succeeded",
316
- endedAt: eventAt,
317
- lastEventAt: eventAt,
318
- progressSummary: trimOptional(message) ?? "Codex native subagent blocked.",
319
- terminalSummary: trimOptional(message) ?? "Codex native subagent blocked.",
320
- terminalOutcome: "blocked",
321
- });
322
- return;
323
- }
324
- this.terminalRunIds.add(runId);
325
- this.runtime.finalizeTaskRunByRunId({
326
- runId,
327
- runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
328
- status:
329
- normalizedStatus === "interrupted" || normalizedStatus === "shutdown"
330
- ? "cancelled"
331
- : "failed",
332
- endedAt: eventAt,
333
- lastEventAt: eventAt,
334
- error: trimOptional(message) ?? `Codex native subagent status: ${normalizedStatus}`,
335
- progressSummary: trimOptional(message) ?? `Codex native subagent ${normalizedStatus}.`,
336
- terminalSummary: trimOptional(message) ?? "Codex native subagent did not complete.",
337
- });
338
- }
339
- }
340
-
341
- export function codexNativeSubagentRunId(threadId: string): string {
342
- return `${CODEX_NATIVE_SUBAGENT_RUN_ID_PREFIX}${threadId.trim()}`;
343
- }
344
-
345
- export function readSubagentThreadSpawnSource(
346
- source: CodexSessionSource | null | undefined,
347
- parentThreadId: string,
348
- ): CodexSubAgentThreadSpawnSource | undefined {
349
- if (!source || typeof source !== "object" || !("subAgent" in source)) {
350
- return undefined;
351
- }
352
- const subAgent = source.subAgent;
353
- if (!subAgent || typeof subAgent !== "object" || !("thread_spawn" in subAgent)) {
354
- return undefined;
355
- }
356
- const spawn = subAgent.thread_spawn;
357
- if (!spawn || typeof spawn !== "object") {
358
- return undefined;
359
- }
360
- return spawn.parent_thread_id === parentThreadId ? spawn : undefined;
361
- }
362
-
363
- function readThreadStartedNotification(
364
- params: JsonObject,
365
- ): CodexThreadStartedNotification | undefined {
366
- const thread = params.thread;
367
- if (!isJsonObject(thread) || typeof thread.id !== "string") {
368
- return undefined;
369
- }
370
- return { thread: thread as CodexThread };
371
- }
372
-
373
- function readThreadStatusChangedNotification(
374
- params: JsonObject,
375
- ): CodexThreadStatusChangedNotification | undefined {
376
- if (typeof params.threadId !== "string") {
377
- return undefined;
378
- }
379
- const status = params.status;
380
- if (!isJsonObject(status) || !isCodexThreadStatusType(status.type)) {
381
- return undefined;
382
- }
383
- return {
384
- threadId: params.threadId,
385
- status: status as CodexThreadStatus,
386
- };
387
- }
388
-
389
- function isCodexThreadStatusType(value: unknown): value is CodexThreadStatus["type"] {
390
- return value === "notLoaded" || value === "idle" || value === "systemError" || value === "active";
391
- }
392
-
393
- function readAgentsStates(
394
- value: JsonValue | undefined,
395
- ): Map<string, { status?: string; message?: string | null }> {
396
- const states = new Map<string, { status?: string; message?: string | null }>();
397
- if (!isJsonObject(value)) {
398
- return states;
399
- }
400
- for (const [threadId, rawState] of Object.entries(value)) {
401
- if (!isJsonObject(rawState)) {
402
- continue;
403
- }
404
- const status = readString(rawState, "status");
405
- const message = readNullableString(rawState, "message");
406
- states.set(threadId, { status, message });
407
- }
408
- return states;
409
- }
410
-
411
- function readStringArray(value: JsonValue | undefined): string[] {
412
- if (!Array.isArray(value)) {
413
- return [];
414
- }
415
- return value.filter((entry): entry is string => typeof entry === "string" && entry.trim() !== "");
416
- }
417
-
418
- function readString(value: JsonObject, key: string): string | undefined {
419
- const entry = value[key];
420
- return typeof entry === "string" ? entry : undefined;
421
- }
422
-
423
- function readNullableString(value: JsonObject, key: string): string | null | undefined {
424
- const entry = value[key];
425
- return typeof entry === "string" || entry === null ? entry : undefined;
426
- }
427
-
428
- function normalizeToolName(value: string | undefined): string | undefined {
429
- return value?.replace(/[^a-z0-9]/giu, "").toLowerCase();
430
- }
431
-
432
- function normalizeCollabToolCallStatus(value: string | undefined): string | undefined {
433
- const key = value?.replace(/[^a-z0-9]/giu, "").toLowerCase();
434
- if (key === "completed" || key === "succeeded" || key === "success") {
435
- return "completed";
436
- }
437
- if (key === "failed" || key === "error" || key === "errored") {
438
- return "failed";
439
- }
440
- if (key === "blocked" || key === "declined") {
441
- return "blocked";
442
- }
443
- if (key === "inprogress" || key === "running") {
444
- return "running";
445
- }
446
- return value?.trim();
447
- }
448
-
449
- function isBlockedOrFailedCollabToolCallStatus(value: string | undefined): boolean {
450
- return value === "failed" || value === "blocked";
451
- }
452
-
453
- function isNonTerminalAgentStateStatus(value: string | undefined): boolean {
454
- return value === "pendingInit" || value === "running";
455
- }
456
-
457
- function isTerminalAgentStateStatus(value: string | undefined): boolean {
458
- return value !== undefined && !isNonTerminalAgentStateStatus(value);
459
- }
460
-
461
- function normalizeAgentStateStatus(value: string | undefined): string | undefined {
462
- const key = value?.replace(/[^a-z0-9]/giu, "").toLowerCase();
463
- if (!key) {
464
- return undefined;
465
- }
466
- if (key === "pendinginit") {
467
- return "pendingInit";
468
- }
469
- if (key === "inprogress" || key === "running") {
470
- return "running";
471
- }
472
- if (key === "completed" || key === "succeeded" || key === "success") {
473
- return "completed";
474
- }
475
- if (key === "interrupted" || key === "cancelled" || key === "canceled" || key === "shutdown") {
476
- return key === "shutdown" ? "shutdown" : "interrupted";
477
- }
478
- if (key === "failed" || key === "error" || key === "systemerror") {
479
- return "failed";
480
- }
481
- if (key === "blocked" || key === "declined") {
482
- return "blocked";
483
- }
484
- return value?.trim();
485
- }
486
-
487
- function secondsToMillis(value: number | null | undefined): number | undefined {
488
- if (typeof value !== "number" || !Number.isFinite(value)) {
489
- return undefined;
490
- }
491
- return value * 1000;
492
- }
493
-
494
- function trimOptional(value: string | null | undefined): string | undefined {
495
- const trimmed = value?.trim();
496
- return trimmed ? trimmed : undefined;
497
- }