@nextclaw/nextclaw-ncp-runtime-codex-sdk 0.1.53 → 0.1.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -18,7 +18,7 @@ type CodexSdkNcpAgentRuntimeConfig = {
18
18
  cliConfig?: CodexOptions["config"];
19
19
  threadOptions?: ThreadOptions;
20
20
  sessionMetadata?: Record<string, unknown>;
21
- setSessionMetadata?: (nextMetadata: Record<string, unknown>) => void;
21
+ setSessionMetadata?: (nextMetadata: Record<string, unknown>) => void | Promise<void>;
22
22
  inputBuilder?: (input: NcpAgentRunInput) => Promise<CodexThreadInput> | CodexThreadInput;
23
23
  liveOutputStream?: CodexLiveOutputStream;
24
24
  resolveAssetContentPath?: CodexAssetContentPathResolver;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;KA+CY,6BAAA;EACV,SAAA;EACA,MAAA;EACA,OAAA;EACA,KAAA;EACA,QAAA;EACA,iBAAA;EACA,GAAA,GAAM,MAAA;EACN,SAAA,GAAY,YAAA;EACZ,aAAA,GAAgB,aAAA;EAChB,eAAA,GAAkB,MAAA;EAClB,kBAAA,IAAsB,YAAA,EAAc,MAAA;EACpC,YAAA,IAAgB,KAAA,EAAO,gBAAA,KAAqB,OAAA,CAAQ,gBAAA,IAAoB,gBAAA;EACxE,gBAAA,GAAmB,qBAAA;EACnB,uBAAA,GAA0B,6BAAA;EAC1B,YAAA,GAAe,gCAAA;AAAA;AAAA,cAkCJ,uBAAA,YAAmC,eAAA;EAAA,iBAQjB,MAAA;EAAA,QAPrB,YAAA;EAAA,iBACS,YAAA;EAAA,iBACA,2BAAA;EAAA,QACT,MAAA;EAAA,QACA,QAAA;EAAA,iBACS,eAAA;cAEY,MAAA,EAAQ,6BAAA;EAQrC,GAAA,GACE,IAAA,EAAM,uBAAA,EACN,KAAA,EAAO,gBAAA,EACP,OAAA,GAAU,kBAAA,KACT,cAAA,CAAe,gBAAA;EAAA,QAmCV,QAAA;EAAA,QAgBA,aAAA;EAAA,QAcA,cAAA;EAAA,QASA,gBAAA;EAAA,QAiDA,iBAAA;EAAA,QAkFA,cAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;KA+CY,6BAAA;EACV,SAAA;EACA,MAAA;EACA,OAAA;EACA,KAAA;EACA,QAAA;EACA,iBAAA;EACA,GAAA,GAAM,MAAA;EACN,SAAA,GAAY,YAAA;EACZ,aAAA,GAAgB,aAAA;EAChB,eAAA,GAAkB,MAAA;EAClB,kBAAA,IAAsB,YAAA,EAAc,MAAA,6BAAmC,OAAA;EACvE,YAAA,IAAgB,KAAA,EAAO,gBAAA,KAAqB,OAAA,CAAQ,gBAAA,IAAoB,gBAAA;EACxE,gBAAA,GAAmB,qBAAA;EACnB,uBAAA,GAA0B,6BAAA;EAC1B,YAAA,GAAe,gCAAA;AAAA;AAAA,cAkCJ,uBAAA,YAAmC,eAAA;EAAA,iBAQjB,MAAA;EAAA,QAPrB,YAAA;EAAA,iBACS,YAAA;EAAA,iBACA,2BAAA;EAAA,QACT,MAAA;EAAA,QACA,QAAA;EAAA,iBACS,eAAA;cAEY,MAAA,EAAQ,6BAAA;EAQrC,GAAA,GACE,IAAA,EAAM,uBAAA,EACN,KAAA,EAAO,gBAAA,EACP,OAAA,GAAU,kBAAA,KACT,cAAA,CAAe,gBAAA;EAAA,QAmCV,QAAA;EAAA,QAgBA,aAAA;EAAA,QAcA,cAAA;EAAA,QASA,gBAAA;EAAA,QAiDA,iBAAA;EAAA,QAkFA,cAAA;AAAA"}
package/dist/index.js CHANGED
@@ -126,7 +126,7 @@ var CodexSdkNcpAgentRuntime = class {
126
126
  const { event, itemTextById, messageId, runId, sessionId, signal, suppressLiveChannels, toolStateById } = params;
127
127
  if (signal?.aborted) throw toAbortError(signal.reason);
128
128
  if (event.type === "thread.started") {
129
- this.updateThreadId(event.thread_id);
129
+ await this.updateThreadId(event.thread_id);
130
130
  return false;
131
131
  }
132
132
  if (event.type === "turn.failed") {
@@ -155,7 +155,7 @@ var CodexSdkNcpAgentRuntime = class {
155
155
  }
156
156
  return false;
157
157
  };
158
- updateThreadId = (nextThreadId) => {
158
+ updateThreadId = async (nextThreadId) => {
159
159
  const normalizedThreadId = nextThreadId.trim();
160
160
  if (!normalizedThreadId || normalizedThreadId === this.threadId) return;
161
161
  this.threadId = normalizedThreadId;
@@ -166,7 +166,7 @@ var CodexSdkNcpAgentRuntime = class {
166
166
  };
167
167
  this.sessionMetadata.codex_thread_id = normalizedThreadId;
168
168
  this.sessionMetadata.session_type = "codex";
169
- this.config.setSessionMetadata?.(nextMetadata);
169
+ await this.config.setSessionMetadata?.(nextMetadata);
170
170
  };
171
171
  };
172
172
  //#endregion
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport type { Codex as CodexClient, CodexOptions, Thread, ThreadOptions } from \"@openai/codex-sdk\";\nimport {\n type NcpAgentConversationStateManager,\n type NcpAgentRunInput,\n type NcpAgentRunOptions,\n type NcpAgentRuntime,\n type NcpEndpointEvent,\n} from \"@nextclaw/ncp\";\nimport type {\n CodexLiveOutputChannel,\n CodexLiveOutputStream,\n} from \"./services/codex-live-output-stream.service.js\";\nimport { CodexLiveOutputEventMergeService } from \"./services/codex-live-output-event-merge.service.js\";\nimport { CodexNcpRunEventEmitter } from \"./services/codex-ncp-run-event-emitter.service.js\";\nimport {\n type ItemTextSnapshot,\n mapCodexItemEvent,\n type ToolSnapshot,\n} from \"./utils/codex-sdk-ncp-event-mapper.utils.js\";\nimport { buildCodexCliEnv } from \"./codex-cli-env.js\";\nimport {\n buildCodexTurnInputFromRunInput,\n type CodexAssetContentPathResolver,\n type CodexThreadInput,\n} from \"./codex-input.utils.js\";\nexport { buildCodexInputBuilder } from \"./codex-input.utils.js\";\nexport type { CodexAssetContentPathResolver } from \"./codex-input.utils.js\";\nexport { buildCodexBridgeModelProviderId } from \"./codex-model-provider.js\";\nexport { ensureCodexOpenAiResponsesBridge } from \"./utils/codex-openai-responses-bridge.utils.js\";\nexport type { CodexOpenAiResponsesBridgeRuntimeConfig } from \"./utils/codex-openai-responses-bridge.utils.js\";\nexport type { CodexOpenAiResponsesBridgeResult } from \"./codex-openai-responses-bridge-shared.utils.js\";\nexport { CodexLiveOutputStream } from \"./services/codex-live-output-stream.service.js\";\nexport type {\n CodexLiveOutputChannel,\n CodexLiveOutputEvent,\n} from \"./services/codex-live-output-stream.service.js\";\n\ntype CodexCtor = new (options: CodexOptions) => CodexClient;\n\ntype CodexLoader = {\n loadCodexConstructor: () => Promise<CodexCtor>;\n};\n\nconst require = createRequire(import.meta.url);\nconst codexLoader = require(\"../codex-sdk-loader.cjs\") as CodexLoader;\n\nexport type CodexSdkNcpAgentRuntimeConfig = {\n sessionId: string;\n apiKey: string;\n apiBase?: string;\n model?: string;\n threadId?: string | null;\n codexPathOverride?: string;\n env?: Record<string, string>;\n cliConfig?: CodexOptions[\"config\"];\n threadOptions?: ThreadOptions;\n sessionMetadata?: Record<string, unknown>;\n setSessionMetadata?: (nextMetadata: Record<string, unknown>) => void;\n inputBuilder?: (input: NcpAgentRunInput) => Promise<CodexThreadInput> | CodexThreadInput;\n liveOutputStream?: CodexLiveOutputStream;\n resolveAssetContentPath?: CodexAssetContentPathResolver;\n stateManager?: NcpAgentConversationStateManager;\n};\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction toAbortError(reason: unknown): Error {\n if (reason instanceof Error) {\n return reason;\n }\n const message = typeof reason === \"string\" && reason.trim() ? reason.trim() : \"operation aborted\";\n const error = new Error(message);\n error.name = \"AbortError\";\n return error;\n}\n\nfunction normalizeThreadOptions(\n options: ThreadOptions | undefined,\n model: string | undefined,\n): ThreadOptions {\n return {\n ...options,\n skipGitRepoCheck: options?.skipGitRepoCheck ?? true,\n ...(model ? { model } : {}),\n };\n}\n\nfunction isItemLifecycleEvent(\n event: Parameters<typeof mapCodexItemEvent>[0][\"event\"] | { type: string },\n): event is Parameters<typeof mapCodexItemEvent>[0][\"event\"] {\n return event.type === \"item.started\" || event.type === \"item.updated\" || event.type === \"item.completed\";\n}\n\nexport class CodexSdkNcpAgentRuntime implements NcpAgentRuntime {\n private codexPromise: Promise<CodexClient> | null = null;\n private readonly eventEmitter: CodexNcpRunEventEmitter;\n private readonly liveOutputEventMergeService = new CodexLiveOutputEventMergeService();\n private thread: Thread | null = null;\n private threadId: string | null;\n private readonly sessionMetadata: Record<string, unknown>;\n\n constructor(private readonly config: CodexSdkNcpAgentRuntimeConfig) {\n this.eventEmitter = new CodexNcpRunEventEmitter(config.stateManager);\n this.threadId = config.threadId?.trim() || null;\n this.sessionMetadata = {\n ...(config.sessionMetadata ? structuredClone(config.sessionMetadata) : {}),\n };\n }\n\n run = async function* (\n this: CodexSdkNcpAgentRuntime,\n input: NcpAgentRunInput,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n const signal = options?.signal;\n const messageId = createId(\"codex-message\");\n const runId = (input as NcpAgentRunInput & { runId?: string }).runId ?? createId(\"codex-run\");\n const itemTextById = new Map<string, ItemTextSnapshot>();\n const toolStateById = new Map<string, ToolSnapshot>();\n\n yield* this.eventEmitter.emitRunStarted(input.sessionId, messageId, runId);\n yield* this.eventEmitter.emitReadyMetadata(input.sessionId, messageId, runId);\n\n const thread = await this.resolveThread();\n const turnInput = await this.buildTurnInput(input);\n this.config.liveOutputStream?.reset();\n const streamed = await thread.runStreamed(turnInput, {\n ...(signal ? { signal } : {}),\n });\n\n try {\n yield* this.streamTurnEvents({\n sessionId: input.sessionId,\n messageId,\n runId,\n streamed,\n signal,\n itemTextById,\n toolStateById,\n });\n } catch (error) {\n if (signal?.aborted) {\n throw toAbortError(signal.reason);\n }\n throw error;\n }\n };\n\n private getCodex = async (): Promise<CodexClient> => {\n if (!this.codexPromise) {\n const env = buildCodexCliEnv(this.config);\n this.codexPromise = codexLoader.loadCodexConstructor().then((Ctor) =>\n new Ctor({\n apiKey: this.config.apiKey,\n baseUrl: this.config.apiBase,\n ...(this.config.codexPathOverride ? { codexPathOverride: this.config.codexPathOverride } : {}),\n ...(env ? { env } : {}),\n ...(this.config.cliConfig ? { config: this.config.cliConfig } : {}),\n }),\n );\n }\n return this.codexPromise;\n };\n\n private resolveThread = async (): Promise<Thread> => {\n if (this.thread) {\n return this.thread;\n }\n\n const codex = await this.getCodex();\n const threadOptions = normalizeThreadOptions(this.config.threadOptions, this.config.model);\n\n this.thread = this.threadId\n ? codex.resumeThread(this.threadId, threadOptions)\n : codex.startThread(threadOptions);\n return this.thread;\n };\n\n private buildTurnInput = async (input: NcpAgentRunInput): Promise<CodexThreadInput> => {\n if (this.config.inputBuilder) {\n return await this.config.inputBuilder(input);\n }\n return await buildCodexTurnInputFromRunInput(input, {\n resolveAssetContentPath: this.config.resolveAssetContentPath,\n });\n };\n\n private streamTurnEvents = async function* (\n this: CodexSdkNcpAgentRuntime,\n params: {\n sessionId: string;\n messageId: string;\n runId: string;\n streamed: Awaited<ReturnType<Thread[\"runStreamed\"]>>;\n signal?: AbortSignal;\n itemTextById: Map<string, ItemTextSnapshot>;\n toolStateById: Map<string, ToolSnapshot>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { itemTextById, messageId, runId, sessionId, signal, streamed, toolStateById } =\n params;\n const liveOutputStream = this.config.liveOutputStream;\n if (liveOutputStream) {\n yield* this.liveOutputEventMergeService.stream({\n ...params,\n liveOutputStream,\n emitEvent: (event) => this.eventEmitter.emitEvent(event),\n emitRunCompleted: (sessionId, messageId, runId) =>\n this.eventEmitter.emitRunCompleted(sessionId, messageId, runId),\n handleThreadEvent: (handlerParams) => this.handleThreadEvent(handlerParams),\n });\n return;\n }\n\n let finished = false;\n for await (const event of streamed.events) {\n const shouldFinish = yield* this.handleThreadEvent({\n sessionId,\n messageId,\n runId,\n event,\n signal,\n itemTextById,\n toolStateById,\n });\n if (shouldFinish) {\n finished = true;\n return;\n }\n }\n\n if (!finished) {\n yield* this.eventEmitter.emitRunCompleted(sessionId, messageId, runId);\n }\n };\n\n private handleThreadEvent = async function* (\n this: CodexSdkNcpAgentRuntime,\n params: {\n sessionId: string;\n messageId: string;\n runId: string;\n event: Awaited<ReturnType<Thread[\"runStreamed\"]>>[\"events\"] extends AsyncGenerator<infer T> ? T : never;\n signal?: AbortSignal;\n itemTextById: Map<string, ItemTextSnapshot>;\n suppressLiveChannels?: Set<CodexLiveOutputChannel>;\n toolStateById: Map<string, ToolSnapshot>;\n },\n ): AsyncGenerator<NcpEndpointEvent, boolean> {\n const {\n event,\n itemTextById,\n messageId,\n runId,\n sessionId,\n signal,\n suppressLiveChannels,\n toolStateById,\n } = params;\n if (signal?.aborted) {\n throw toAbortError(signal.reason);\n }\n\n if (event.type === \"thread.started\") {\n this.updateThreadId(event.thread_id);\n return false;\n }\n\n if (event.type === \"turn.failed\") {\n yield* this.eventEmitter.emitRunError(\n sessionId,\n messageId,\n runId,\n event.error.message,\n );\n return true;\n }\n\n if (event.type === \"error\") {\n yield* this.eventEmitter.emitRunError(\n sessionId,\n messageId,\n runId,\n event.message,\n );\n return true;\n }\n\n if (isItemLifecycleEvent(event)) {\n const suppressedChannel =\n event.item.type === \"agent_message\"\n ? \"text\"\n : event.item.type === \"reasoning\"\n ? \"reasoning\"\n : null;\n if (suppressedChannel && suppressLiveChannels?.has(suppressedChannel)) {\n return false;\n }\n for await (const mappedEvent of mapCodexItemEvent({\n sessionId,\n messageId,\n event,\n itemTextById,\n toolStateById,\n })) {\n yield* this.eventEmitter.emitEvent(mappedEvent);\n }\n return false;\n }\n\n if (event.type === \"turn.completed\") {\n yield* this.eventEmitter.emitRunCompleted(sessionId, messageId, runId);\n return true;\n }\n\n return false;\n };\n\n private updateThreadId = (nextThreadId: string): void => {\n const normalizedThreadId = nextThreadId.trim();\n if (!normalizedThreadId || normalizedThreadId === this.threadId) {\n return;\n }\n this.threadId = normalizedThreadId;\n const nextMetadata = {\n ...this.sessionMetadata,\n session_type: \"codex\",\n codex_thread_id: normalizedThreadId,\n };\n this.sessionMetadata.codex_thread_id = normalizedThreadId;\n this.sessionMetadata.session_type = \"codex\";\n this.config.setSessionMetadata?.(nextMetadata);\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport type { Codex as CodexClient, CodexOptions, Thread, ThreadOptions } from \"@openai/codex-sdk\";\nimport {\n type NcpAgentConversationStateManager,\n type NcpAgentRunInput,\n type NcpAgentRunOptions,\n type NcpAgentRuntime,\n type NcpEndpointEvent,\n} from \"@nextclaw/ncp\";\nimport type {\n CodexLiveOutputChannel,\n CodexLiveOutputStream,\n} from \"./services/codex-live-output-stream.service.js\";\nimport { CodexLiveOutputEventMergeService } from \"./services/codex-live-output-event-merge.service.js\";\nimport { CodexNcpRunEventEmitter } from \"./services/codex-ncp-run-event-emitter.service.js\";\nimport {\n type ItemTextSnapshot,\n mapCodexItemEvent,\n type ToolSnapshot,\n} from \"./utils/codex-sdk-ncp-event-mapper.utils.js\";\nimport { buildCodexCliEnv } from \"./codex-cli-env.js\";\nimport {\n buildCodexTurnInputFromRunInput,\n type CodexAssetContentPathResolver,\n type CodexThreadInput,\n} from \"./codex-input.utils.js\";\nexport { buildCodexInputBuilder } from \"./codex-input.utils.js\";\nexport type { CodexAssetContentPathResolver } from \"./codex-input.utils.js\";\nexport { buildCodexBridgeModelProviderId } from \"./codex-model-provider.js\";\nexport { ensureCodexOpenAiResponsesBridge } from \"./utils/codex-openai-responses-bridge.utils.js\";\nexport type { CodexOpenAiResponsesBridgeRuntimeConfig } from \"./utils/codex-openai-responses-bridge.utils.js\";\nexport type { CodexOpenAiResponsesBridgeResult } from \"./codex-openai-responses-bridge-shared.utils.js\";\nexport { CodexLiveOutputStream } from \"./services/codex-live-output-stream.service.js\";\nexport type {\n CodexLiveOutputChannel,\n CodexLiveOutputEvent,\n} from \"./services/codex-live-output-stream.service.js\";\n\ntype CodexCtor = new (options: CodexOptions) => CodexClient;\n\ntype CodexLoader = {\n loadCodexConstructor: () => Promise<CodexCtor>;\n};\n\nconst require = createRequire(import.meta.url);\nconst codexLoader = require(\"../codex-sdk-loader.cjs\") as CodexLoader;\n\nexport type CodexSdkNcpAgentRuntimeConfig = {\n sessionId: string;\n apiKey: string;\n apiBase?: string;\n model?: string;\n threadId?: string | null;\n codexPathOverride?: string;\n env?: Record<string, string>;\n cliConfig?: CodexOptions[\"config\"];\n threadOptions?: ThreadOptions;\n sessionMetadata?: Record<string, unknown>;\n setSessionMetadata?: (nextMetadata: Record<string, unknown>) => void | Promise<void>;\n inputBuilder?: (input: NcpAgentRunInput) => Promise<CodexThreadInput> | CodexThreadInput;\n liveOutputStream?: CodexLiveOutputStream;\n resolveAssetContentPath?: CodexAssetContentPathResolver;\n stateManager?: NcpAgentConversationStateManager;\n};\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction toAbortError(reason: unknown): Error {\n if (reason instanceof Error) {\n return reason;\n }\n const message = typeof reason === \"string\" && reason.trim() ? reason.trim() : \"operation aborted\";\n const error = new Error(message);\n error.name = \"AbortError\";\n return error;\n}\n\nfunction normalizeThreadOptions(\n options: ThreadOptions | undefined,\n model: string | undefined,\n): ThreadOptions {\n return {\n ...options,\n skipGitRepoCheck: options?.skipGitRepoCheck ?? true,\n ...(model ? { model } : {}),\n };\n}\n\nfunction isItemLifecycleEvent(\n event: Parameters<typeof mapCodexItemEvent>[0][\"event\"] | { type: string },\n): event is Parameters<typeof mapCodexItemEvent>[0][\"event\"] {\n return event.type === \"item.started\" || event.type === \"item.updated\" || event.type === \"item.completed\";\n}\n\nexport class CodexSdkNcpAgentRuntime implements NcpAgentRuntime {\n private codexPromise: Promise<CodexClient> | null = null;\n private readonly eventEmitter: CodexNcpRunEventEmitter;\n private readonly liveOutputEventMergeService = new CodexLiveOutputEventMergeService();\n private thread: Thread | null = null;\n private threadId: string | null;\n private readonly sessionMetadata: Record<string, unknown>;\n\n constructor(private readonly config: CodexSdkNcpAgentRuntimeConfig) {\n this.eventEmitter = new CodexNcpRunEventEmitter(config.stateManager);\n this.threadId = config.threadId?.trim() || null;\n this.sessionMetadata = {\n ...(config.sessionMetadata ? structuredClone(config.sessionMetadata) : {}),\n };\n }\n\n run = async function* (\n this: CodexSdkNcpAgentRuntime,\n input: NcpAgentRunInput,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n const signal = options?.signal;\n const messageId = createId(\"codex-message\");\n const runId = (input as NcpAgentRunInput & { runId?: string }).runId ?? createId(\"codex-run\");\n const itemTextById = new Map<string, ItemTextSnapshot>();\n const toolStateById = new Map<string, ToolSnapshot>();\n\n yield* this.eventEmitter.emitRunStarted(input.sessionId, messageId, runId);\n yield* this.eventEmitter.emitReadyMetadata(input.sessionId, messageId, runId);\n\n const thread = await this.resolveThread();\n const turnInput = await this.buildTurnInput(input);\n this.config.liveOutputStream?.reset();\n const streamed = await thread.runStreamed(turnInput, {\n ...(signal ? { signal } : {}),\n });\n\n try {\n yield* this.streamTurnEvents({\n sessionId: input.sessionId,\n messageId,\n runId,\n streamed,\n signal,\n itemTextById,\n toolStateById,\n });\n } catch (error) {\n if (signal?.aborted) {\n throw toAbortError(signal.reason);\n }\n throw error;\n }\n };\n\n private getCodex = async (): Promise<CodexClient> => {\n if (!this.codexPromise) {\n const env = buildCodexCliEnv(this.config);\n this.codexPromise = codexLoader.loadCodexConstructor().then((Ctor) =>\n new Ctor({\n apiKey: this.config.apiKey,\n baseUrl: this.config.apiBase,\n ...(this.config.codexPathOverride ? { codexPathOverride: this.config.codexPathOverride } : {}),\n ...(env ? { env } : {}),\n ...(this.config.cliConfig ? { config: this.config.cliConfig } : {}),\n }),\n );\n }\n return this.codexPromise;\n };\n\n private resolveThread = async (): Promise<Thread> => {\n if (this.thread) {\n return this.thread;\n }\n\n const codex = await this.getCodex();\n const threadOptions = normalizeThreadOptions(this.config.threadOptions, this.config.model);\n\n this.thread = this.threadId\n ? codex.resumeThread(this.threadId, threadOptions)\n : codex.startThread(threadOptions);\n return this.thread;\n };\n\n private buildTurnInput = async (input: NcpAgentRunInput): Promise<CodexThreadInput> => {\n if (this.config.inputBuilder) {\n return await this.config.inputBuilder(input);\n }\n return await buildCodexTurnInputFromRunInput(input, {\n resolveAssetContentPath: this.config.resolveAssetContentPath,\n });\n };\n\n private streamTurnEvents = async function* (\n this: CodexSdkNcpAgentRuntime,\n params: {\n sessionId: string;\n messageId: string;\n runId: string;\n streamed: Awaited<ReturnType<Thread[\"runStreamed\"]>>;\n signal?: AbortSignal;\n itemTextById: Map<string, ItemTextSnapshot>;\n toolStateById: Map<string, ToolSnapshot>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { itemTextById, messageId, runId, sessionId, signal, streamed, toolStateById } =\n params;\n const liveOutputStream = this.config.liveOutputStream;\n if (liveOutputStream) {\n yield* this.liveOutputEventMergeService.stream({\n ...params,\n liveOutputStream,\n emitEvent: (event) => this.eventEmitter.emitEvent(event),\n emitRunCompleted: (sessionId, messageId, runId) =>\n this.eventEmitter.emitRunCompleted(sessionId, messageId, runId),\n handleThreadEvent: (handlerParams) => this.handleThreadEvent(handlerParams),\n });\n return;\n }\n\n let finished = false;\n for await (const event of streamed.events) {\n const shouldFinish = yield* this.handleThreadEvent({\n sessionId,\n messageId,\n runId,\n event,\n signal,\n itemTextById,\n toolStateById,\n });\n if (shouldFinish) {\n finished = true;\n return;\n }\n }\n\n if (!finished) {\n yield* this.eventEmitter.emitRunCompleted(sessionId, messageId, runId);\n }\n };\n\n private handleThreadEvent = async function* (\n this: CodexSdkNcpAgentRuntime,\n params: {\n sessionId: string;\n messageId: string;\n runId: string;\n event: Awaited<ReturnType<Thread[\"runStreamed\"]>>[\"events\"] extends AsyncGenerator<infer T> ? T : never;\n signal?: AbortSignal;\n itemTextById: Map<string, ItemTextSnapshot>;\n suppressLiveChannels?: Set<CodexLiveOutputChannel>;\n toolStateById: Map<string, ToolSnapshot>;\n },\n ): AsyncGenerator<NcpEndpointEvent, boolean> {\n const {\n event,\n itemTextById,\n messageId,\n runId,\n sessionId,\n signal,\n suppressLiveChannels,\n toolStateById,\n } = params;\n if (signal?.aborted) {\n throw toAbortError(signal.reason);\n }\n\n if (event.type === \"thread.started\") {\n await this.updateThreadId(event.thread_id);\n return false;\n }\n\n if (event.type === \"turn.failed\") {\n yield* this.eventEmitter.emitRunError(\n sessionId,\n messageId,\n runId,\n event.error.message,\n );\n return true;\n }\n\n if (event.type === \"error\") {\n yield* this.eventEmitter.emitRunError(\n sessionId,\n messageId,\n runId,\n event.message,\n );\n return true;\n }\n\n if (isItemLifecycleEvent(event)) {\n const suppressedChannel =\n event.item.type === \"agent_message\"\n ? \"text\"\n : event.item.type === \"reasoning\"\n ? \"reasoning\"\n : null;\n if (suppressedChannel && suppressLiveChannels?.has(suppressedChannel)) {\n return false;\n }\n for await (const mappedEvent of mapCodexItemEvent({\n sessionId,\n messageId,\n event,\n itemTextById,\n toolStateById,\n })) {\n yield* this.eventEmitter.emitEvent(mappedEvent);\n }\n return false;\n }\n\n if (event.type === \"turn.completed\") {\n yield* this.eventEmitter.emitRunCompleted(sessionId, messageId, runId);\n return true;\n }\n\n return false;\n };\n\n private updateThreadId = async (nextThreadId: string): Promise<void> => {\n const normalizedThreadId = nextThreadId.trim();\n if (!normalizedThreadId || normalizedThreadId === this.threadId) {\n return;\n }\n this.threadId = normalizedThreadId;\n const nextMetadata = {\n ...this.sessionMetadata,\n session_type: \"codex\",\n codex_thread_id: normalizedThreadId,\n };\n this.sessionMetadata.codex_thread_id = normalizedThreadId;\n this.sessionMetadata.session_type = \"codex\";\n await this.config.setSessionMetadata?.(nextMetadata);\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/nextclaw-ncp-runtime-codex-sdk",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "private": false,
5
5
  "description": "Optional NCP runtime adapter backed by OpenAI Codex SDK.",
6
6
  "type": "module",
@@ -16,8 +16,8 @@
16
16
  "README.md"
17
17
  ],
18
18
  "dependencies": {
19
- "@openai/codex-sdk": "^0.130.0",
20
- "@nextclaw/ncp": "0.6.2"
19
+ "@openai/codex-sdk": "^0.139.0",
20
+ "@nextclaw/ncp": "0.6.3"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^20.17.6",
@@ -27,7 +27,7 @@
27
27
  "scripts": {
28
28
  "build": "tsdown src/index.ts --dts.sourcemap --clean --target es2022 --no-fixedExtension --unbundle",
29
29
  "lint": "eslint .",
30
- "test": "vitest run src/utils/codex-model-provider.utils.test.ts src/utils/codex-sdk-ncp-event-mapper.utils.test.ts src/services/codex-live-output-stream.service.test.ts src/utils/codex-openai-sse-chunks.utils.test.ts",
30
+ "test": "vitest run src/services/codex-sdk-runtime-thread-metadata.service.test.ts src/utils/codex-model-provider.utils.test.ts src/utils/codex-sdk-ncp-event-mapper.utils.test.ts src/services/codex-live-output-stream.service.test.ts src/utils/codex-openai-sse-chunks.utils.test.ts",
31
31
  "tsc": "tsc -p tsconfig.json"
32
32
  }
33
33
  }