@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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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.
|
|
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.
|
|
20
|
-
"@nextclaw/ncp": "0.6.
|
|
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
|
}
|