@nextclaw/nextclaw-ncp-runtime-stdio-client 0.2.13 → 0.2.14-beta.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.
@@ -18,6 +18,7 @@ type StdioRuntimeResolvedConfig = {
18
18
  args: string[];
19
19
  cwd?: string;
20
20
  env?: StdioRuntimeEnv;
21
+ resetSessionMetadataOnPromptTimeout?: string[];
21
22
  startupTimeoutMs: number;
22
23
  probeTimeoutMs: number;
23
24
  requestTimeoutMs: number;
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-runtime-config.utils.d.ts","names":[],"sources":["../src/stdio-runtime-config.utils.ts"],"mappings":";;;cAGa,0BAAA;AAAA,KAWD,eAAA,GAAkB,MAAA;AAAA,KAClB,uBAAA;AAAA,KACA,wBAAA;AAAA,KAEA,mBAAA;EACV,aAAA;EACA,aAAA,GAAgB,uBAAA;EAChB,eAAA,GAAkB,MAAA;EAClB,KAAA,GAAQ,aAAA,CAAc,UAAA;AAAA;AAAA,KAGZ,0BAAA;EACV,WAAA,EAAa,uBAAA;EACb,YAAA,EAAc,wBAAA;EACd,OAAA;EACA,IAAA;EACA,GAAA;EACA,GAAA,GAAM,eAAA;EACN,gBAAA;EACA,cAAA;EACA,gBAAA;AAAA;AAAA,cAkGW,0BAAA;EAAA,iBACkB,MAAA;cAAA,MAAA,GAAQ,MAAA;EAErC,OAAA,QAAc,0BAAA;EAAA,QA6CN,kBAAA;EAAA,QAQA,mBAAA;AAAA;AAAA,iBASM,0BAAA,CAA2B,MAAA;EACzC,aAAA,GAAgB,uBAAA;AAAA,IACd,MAAA;AAAA,iBAaY,0BAAA,CAA2B,MAAA;EACzC,OAAA,GAAU,MAAA;EACV,SAAA,GAAY,eAAA;EACZ,aAAA,GAAgB,uBAAA;AAAA,IACd,MAAA"}
1
+ {"version":3,"file":"stdio-runtime-config.utils.d.ts","names":[],"sources":["../src/stdio-runtime-config.utils.ts"],"mappings":";;;cAGa,0BAAA;AAAA,KAWD,eAAA,GAAkB,MAAA;AAAA,KAClB,uBAAA;AAAA,KACA,wBAAA;AAAA,KAEA,mBAAA;EACV,aAAA;EACA,aAAA,GAAgB,uBAAA;EAChB,eAAA,GAAkB,MAAA;EAClB,KAAA,GAAQ,aAAA,CAAc,UAAA;AAAA;AAAA,KAGZ,0BAAA;EACV,WAAA,EAAa,uBAAA;EACb,YAAA,EAAc,wBAAA;EACd,OAAA;EACA,IAAA;EACA,GAAA;EACA,GAAA,GAAM,eAAA;EACN,mCAAA;EACA,gBAAA;EACA,cAAA;EACA,gBAAA;AAAA;AAAA,cAkGW,0BAAA;EAAA,iBACkB,MAAA;cAAA,MAAA,GAAQ,MAAA;EAErC,OAAA,QAAc,0BAAA;EAAA,QAmDN,kBAAA;EAAA,QAQA,mBAAA;AAAA;AAAA,iBASM,0BAAA,CAA2B,MAAA;EACzC,aAAA,GAAgB,uBAAA;AAAA,IACd,MAAA;AAAA,iBAaY,0BAAA,CAA2B,MAAA;EACzC,OAAA,GAAU,MAAA;EACV,SAAA,GAAY,eAAA;EACZ,aAAA,GAAgB,uBAAA;AAAA,IACd,MAAA"}
@@ -78,6 +78,7 @@ var StdioRuntimeConfigResolver = class {
78
78
  const args = override?.args ?? readStringArray(this.source.args) ?? readStringArray(parseJsonArray(process.env.NEXTCLAW_NARP_STDIO_ARGS)) ?? [];
79
79
  const cwd = override?.cwd ?? readString(this.source.cwd) ?? readString(process.env.NEXTCLAW_NARP_STDIO_CWD);
80
80
  const env = override?.env ?? readStringRecord(this.source.env) ?? readStringRecord(parseJsonObject(process.env.NEXTCLAW_NARP_STDIO_ENV));
81
+ const resetSessionMetadataOnPromptTimeout = readStringArray(this.source.resetSessionMetadataOnPromptTimeout);
81
82
  return {
82
83
  wireDialect,
83
84
  processScope,
@@ -85,6 +86,7 @@ var StdioRuntimeConfigResolver = class {
85
86
  args,
86
87
  ...cwd ? { cwd } : {},
87
88
  ...env ? { env } : {},
89
+ ...resetSessionMetadataOnPromptTimeout ? { resetSessionMetadataOnPromptTimeout } : {},
88
90
  startupTimeoutMs: readPositiveInteger(this.source.startupTimeoutMs) ?? readPositiveInteger(process.env.NEXTCLAW_NARP_STDIO_STARTUP_TIMEOUT_MS) ?? DEFAULT_STARTUP_TIMEOUT_MS,
89
91
  probeTimeoutMs: readPositiveInteger(this.source.probeTimeoutMs) ?? DEFAULT_PROBE_TIMEOUT_MS,
90
92
  requestTimeoutMs: readPositiveInteger(this.source.requestTimeoutMs) ?? DEFAULT_REQUEST_TIMEOUT_MS
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-runtime-config.utils.js","names":[],"sources":["../src/stdio-runtime-config.utils.ts"],"sourcesContent":["import type { OpenAITool, NcpProviderRuntimeRoute } from \"@nextclaw/ncp\";\nimport { createRuntimeChildEnv } from \"@nextclaw/core\";\n\nexport const NARP_STDIO_PROMPT_META_KEY = \"nextclaw_narp\";\nconst DEFAULT_STARTUP_TIMEOUT_MS = 10_000;\nconst DEFAULT_PROBE_TIMEOUT_MS = 3_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 120_000;\nconst DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS = {\n model: \"NEXTCLAW_MODEL\",\n apiBase: \"NEXTCLAW_API_BASE\",\n apiKey: \"NEXTCLAW_API_KEY\",\n headers: \"NEXTCLAW_HEADERS_JSON\",\n} as const;\n\nexport type StdioRuntimeEnv = Record<string, string>;\nexport type StdioRuntimeWireDialect = \"acp\";\nexport type StdioRuntimeProcessScope = \"per-session\";\n\nexport type NarpStdioPromptMeta = {\n correlationId?: string;\n providerRoute?: NcpProviderRuntimeRoute;\n sessionMetadata?: Record<string, unknown>;\n tools?: ReadonlyArray<OpenAITool>;\n};\n\nexport type StdioRuntimeResolvedConfig = {\n wireDialect: StdioRuntimeWireDialect;\n processScope: StdioRuntimeProcessScope;\n command: string;\n args: string[];\n cwd?: string;\n env?: StdioRuntimeEnv;\n startupTimeoutMs: number;\n probeTimeoutMs: number;\n requestTimeoutMs: number;\n};\n\ntype StdioRuntimeCommandOverride = {\n command?: string;\n args?: string[];\n cwd?: string;\n env?: StdioRuntimeEnv;\n};\n\nexport function readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function readPositiveInteger(value: unknown): number | undefined {\n const parsed =\n typeof value === \"number\"\n ? value\n : typeof value === \"string\"\n ? Number.parseInt(value, 10)\n : Number.NaN;\n if (!Number.isFinite(parsed)) {\n return undefined;\n }\n const normalized = Math.trunc(parsed);\n return normalized > 0 ? normalized : undefined;\n}\n\nexport function readStringArray(value: unknown): string[] | undefined {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const output: string[] = [];\n for (const entry of value) {\n const normalized = readString(entry);\n if (!normalized) {\n continue;\n }\n output.push(normalized);\n }\n return output.length > 0 ? output : undefined;\n}\n\nexport function readStringRecord(value: unknown): Record<string, string> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n\n const output: Record<string, string> = {};\n for (const [entryKey, entryValue] of Object.entries(value)) {\n const normalizedValue = readString(entryValue);\n if (!normalizedValue) {\n continue;\n }\n output[entryKey] = normalizedValue;\n }\n return Object.keys(output).length > 0 ? output : undefined;\n}\n\nfunction readCommandOverrides(value: unknown): Record<string, StdioRuntimeCommandOverride> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return {};\n }\n\n const overrides: Record<string, StdioRuntimeCommandOverride> = {};\n for (const [rawCommand, rawOverride] of Object.entries(value)) {\n const commandKey = readString(rawCommand);\n if (!commandKey || !rawOverride || typeof rawOverride !== \"object\" || Array.isArray(rawOverride)) {\n continue;\n }\n const overrideRecord = rawOverride as Record<string, unknown>;\n const command = readString(overrideRecord.command);\n const args = readStringArray(overrideRecord.args);\n const cwd = readString(overrideRecord.cwd);\n const env = readStringRecord(overrideRecord.env);\n if (!command && !args && !cwd && !env) {\n continue;\n }\n overrides[commandKey] = {\n ...(command ? { command } : {}),\n ...(args ? { args } : {}),\n ...(cwd ? { cwd } : {}),\n ...(env ? { env } : {}),\n };\n }\n return overrides;\n}\n\nfunction readCommandOverride(command: string): StdioRuntimeCommandOverride | undefined {\n const rawOverrides = parseJsonObject(process.env.NEXTCLAW_NARP_STDIO_COMMAND_OVERRIDES);\n return readCommandOverrides(rawOverrides)[command];\n}\n\nexport class StdioRuntimeConfigResolver {\n constructor(private readonly source: Record<string, unknown> = {}) {}\n\n resolve = (): StdioRuntimeResolvedConfig => {\n const wireDialect = this.resolveWireDialect();\n const processScope = this.resolveProcessScope();\n const command =\n readString(this.source.command) ??\n readString(process.env.NEXTCLAW_NARP_STDIO_COMMAND);\n if (!command) {\n throw new Error(\"[narp-stdio] missing stdio command\");\n }\n\n const override = readCommandOverride(command);\n const args =\n override?.args ??\n readStringArray(this.source.args) ??\n readStringArray(parseJsonArray(process.env.NEXTCLAW_NARP_STDIO_ARGS)) ??\n [];\n const cwd =\n override?.cwd ??\n readString(this.source.cwd) ??\n readString(process.env.NEXTCLAW_NARP_STDIO_CWD);\n const env =\n override?.env ??\n readStringRecord(this.source.env) ??\n readStringRecord(parseJsonObject(process.env.NEXTCLAW_NARP_STDIO_ENV));\n\n return {\n wireDialect,\n processScope,\n command: override?.command ?? command,\n args,\n ...(cwd ? { cwd } : {}),\n ...(env ? { env } : {}),\n startupTimeoutMs:\n readPositiveInteger(this.source.startupTimeoutMs) ??\n readPositiveInteger(process.env.NEXTCLAW_NARP_STDIO_STARTUP_TIMEOUT_MS) ??\n DEFAULT_STARTUP_TIMEOUT_MS,\n probeTimeoutMs:\n readPositiveInteger(this.source.probeTimeoutMs) ??\n DEFAULT_PROBE_TIMEOUT_MS,\n requestTimeoutMs:\n readPositiveInteger(this.source.requestTimeoutMs) ??\n DEFAULT_REQUEST_TIMEOUT_MS,\n };\n };\n\n private resolveWireDialect = (): StdioRuntimeWireDialect => {\n const wireDialect = readString(this.source.wireDialect) ?? \"acp\";\n if (wireDialect !== \"acp\") {\n throw new Error(`[narp-stdio] unsupported wireDialect \"${wireDialect}\"`);\n }\n return \"acp\";\n };\n\n private resolveProcessScope = (): StdioRuntimeProcessScope => {\n const processScope = readString(this.source.processScope) ?? \"per-session\";\n if (processScope !== \"per-session\") {\n throw new Error(`[narp-stdio] unsupported processScope \"${processScope}\"`);\n }\n return \"per-session\";\n };\n}\n\nexport function buildRuntimeRouteBridgeEnv(params: {\n providerRoute?: NcpProviderRuntimeRoute;\n}): Record<string, string> {\n const { providerRoute } = params;\n if (!providerRoute) {\n return {};\n }\n return {\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.model]: providerRoute.model,\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.apiBase]: providerRoute.apiBase ?? \"\",\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.apiKey]: providerRoute.apiKey ?? \"\",\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.headers]: JSON.stringify(providerRoute.headers ?? {}),\n };\n}\n\nexport function buildStdioRuntimeLaunchEnv(params: {\n baseEnv?: Record<string, string | undefined>;\n configEnv?: StdioRuntimeEnv;\n providerRoute?: NcpProviderRuntimeRoute;\n}): Record<string, string> {\n return {\n ...createRuntimeChildEnv(params.baseEnv ?? process.env, params.configEnv, {\n inheritBaseEnv: true,\n }),\n ...buildRuntimeRouteBridgeEnv({\n providerRoute: params.providerRoute,\n }),\n };\n}\n\nfunction parseJsonArray(value: unknown): unknown {\n if (typeof value !== \"string\" || !value.trim()) {\n return undefined;\n }\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\nfunction parseJsonObject(value: unknown): unknown {\n if (typeof value !== \"string\" || !value.trim()) {\n return undefined;\n }\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stdio-runtime-config.utils.js","names":[],"sources":["../src/stdio-runtime-config.utils.ts"],"sourcesContent":["import type { OpenAITool, NcpProviderRuntimeRoute } from \"@nextclaw/ncp\";\nimport { createRuntimeChildEnv } from \"@nextclaw/core\";\n\nexport const NARP_STDIO_PROMPT_META_KEY = \"nextclaw_narp\";\nconst DEFAULT_STARTUP_TIMEOUT_MS = 10_000;\nconst DEFAULT_PROBE_TIMEOUT_MS = 3_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 120_000;\nconst DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS = {\n model: \"NEXTCLAW_MODEL\",\n apiBase: \"NEXTCLAW_API_BASE\",\n apiKey: \"NEXTCLAW_API_KEY\",\n headers: \"NEXTCLAW_HEADERS_JSON\",\n} as const;\n\nexport type StdioRuntimeEnv = Record<string, string>;\nexport type StdioRuntimeWireDialect = \"acp\";\nexport type StdioRuntimeProcessScope = \"per-session\";\n\nexport type NarpStdioPromptMeta = {\n correlationId?: string;\n providerRoute?: NcpProviderRuntimeRoute;\n sessionMetadata?: Record<string, unknown>;\n tools?: ReadonlyArray<OpenAITool>;\n};\n\nexport type StdioRuntimeResolvedConfig = {\n wireDialect: StdioRuntimeWireDialect;\n processScope: StdioRuntimeProcessScope;\n command: string;\n args: string[];\n cwd?: string;\n env?: StdioRuntimeEnv;\n resetSessionMetadataOnPromptTimeout?: string[];\n startupTimeoutMs: number;\n probeTimeoutMs: number;\n requestTimeoutMs: number;\n};\n\ntype StdioRuntimeCommandOverride = {\n command?: string;\n args?: string[];\n cwd?: string;\n env?: StdioRuntimeEnv;\n};\n\nexport function readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function readPositiveInteger(value: unknown): number | undefined {\n const parsed =\n typeof value === \"number\"\n ? value\n : typeof value === \"string\"\n ? Number.parseInt(value, 10)\n : Number.NaN;\n if (!Number.isFinite(parsed)) {\n return undefined;\n }\n const normalized = Math.trunc(parsed);\n return normalized > 0 ? normalized : undefined;\n}\n\nexport function readStringArray(value: unknown): string[] | undefined {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const output: string[] = [];\n for (const entry of value) {\n const normalized = readString(entry);\n if (!normalized) {\n continue;\n }\n output.push(normalized);\n }\n return output.length > 0 ? output : undefined;\n}\n\nexport function readStringRecord(value: unknown): Record<string, string> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n\n const output: Record<string, string> = {};\n for (const [entryKey, entryValue] of Object.entries(value)) {\n const normalizedValue = readString(entryValue);\n if (!normalizedValue) {\n continue;\n }\n output[entryKey] = normalizedValue;\n }\n return Object.keys(output).length > 0 ? output : undefined;\n}\n\nfunction readCommandOverrides(value: unknown): Record<string, StdioRuntimeCommandOverride> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return {};\n }\n\n const overrides: Record<string, StdioRuntimeCommandOverride> = {};\n for (const [rawCommand, rawOverride] of Object.entries(value)) {\n const commandKey = readString(rawCommand);\n if (!commandKey || !rawOverride || typeof rawOverride !== \"object\" || Array.isArray(rawOverride)) {\n continue;\n }\n const overrideRecord = rawOverride as Record<string, unknown>;\n const command = readString(overrideRecord.command);\n const args = readStringArray(overrideRecord.args);\n const cwd = readString(overrideRecord.cwd);\n const env = readStringRecord(overrideRecord.env);\n if (!command && !args && !cwd && !env) {\n continue;\n }\n overrides[commandKey] = {\n ...(command ? { command } : {}),\n ...(args ? { args } : {}),\n ...(cwd ? { cwd } : {}),\n ...(env ? { env } : {}),\n };\n }\n return overrides;\n}\n\nfunction readCommandOverride(command: string): StdioRuntimeCommandOverride | undefined {\n const rawOverrides = parseJsonObject(process.env.NEXTCLAW_NARP_STDIO_COMMAND_OVERRIDES);\n return readCommandOverrides(rawOverrides)[command];\n}\n\nexport class StdioRuntimeConfigResolver {\n constructor(private readonly source: Record<string, unknown> = {}) {}\n\n resolve = (): StdioRuntimeResolvedConfig => {\n const wireDialect = this.resolveWireDialect();\n const processScope = this.resolveProcessScope();\n const command =\n readString(this.source.command) ??\n readString(process.env.NEXTCLAW_NARP_STDIO_COMMAND);\n if (!command) {\n throw new Error(\"[narp-stdio] missing stdio command\");\n }\n\n const override = readCommandOverride(command);\n const args =\n override?.args ??\n readStringArray(this.source.args) ??\n readStringArray(parseJsonArray(process.env.NEXTCLAW_NARP_STDIO_ARGS)) ??\n [];\n const cwd =\n override?.cwd ??\n readString(this.source.cwd) ??\n readString(process.env.NEXTCLAW_NARP_STDIO_CWD);\n const env =\n override?.env ??\n readStringRecord(this.source.env) ??\n readStringRecord(parseJsonObject(process.env.NEXTCLAW_NARP_STDIO_ENV));\n const resetSessionMetadataOnPromptTimeout = readStringArray(\n this.source.resetSessionMetadataOnPromptTimeout,\n );\n\n return {\n wireDialect,\n processScope,\n command: override?.command ?? command,\n args,\n ...(cwd ? { cwd } : {}),\n ...(env ? { env } : {}),\n ...(resetSessionMetadataOnPromptTimeout\n ? { resetSessionMetadataOnPromptTimeout }\n : {}),\n startupTimeoutMs:\n readPositiveInteger(this.source.startupTimeoutMs) ??\n readPositiveInteger(process.env.NEXTCLAW_NARP_STDIO_STARTUP_TIMEOUT_MS) ??\n DEFAULT_STARTUP_TIMEOUT_MS,\n probeTimeoutMs:\n readPositiveInteger(this.source.probeTimeoutMs) ??\n DEFAULT_PROBE_TIMEOUT_MS,\n requestTimeoutMs:\n readPositiveInteger(this.source.requestTimeoutMs) ??\n DEFAULT_REQUEST_TIMEOUT_MS,\n };\n };\n\n private resolveWireDialect = (): StdioRuntimeWireDialect => {\n const wireDialect = readString(this.source.wireDialect) ?? \"acp\";\n if (wireDialect !== \"acp\") {\n throw new Error(`[narp-stdio] unsupported wireDialect \"${wireDialect}\"`);\n }\n return \"acp\";\n };\n\n private resolveProcessScope = (): StdioRuntimeProcessScope => {\n const processScope = readString(this.source.processScope) ?? \"per-session\";\n if (processScope !== \"per-session\") {\n throw new Error(`[narp-stdio] unsupported processScope \"${processScope}\"`);\n }\n return \"per-session\";\n };\n}\n\nexport function buildRuntimeRouteBridgeEnv(params: {\n providerRoute?: NcpProviderRuntimeRoute;\n}): Record<string, string> {\n const { providerRoute } = params;\n if (!providerRoute) {\n return {};\n }\n return {\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.model]: providerRoute.model,\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.apiBase]: providerRoute.apiBase ?? \"\",\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.apiKey]: providerRoute.apiKey ?? \"\",\n [DEFAULT_RUNTIME_ROUTE_BRIDGE_FIELDS.headers]: JSON.stringify(providerRoute.headers ?? {}),\n };\n}\n\nexport function buildStdioRuntimeLaunchEnv(params: {\n baseEnv?: Record<string, string | undefined>;\n configEnv?: StdioRuntimeEnv;\n providerRoute?: NcpProviderRuntimeRoute;\n}): Record<string, string> {\n return {\n ...createRuntimeChildEnv(params.baseEnv ?? process.env, params.configEnv, {\n inheritBaseEnv: true,\n }),\n ...buildRuntimeRouteBridgeEnv({\n providerRoute: params.providerRoute,\n }),\n };\n}\n\nfunction parseJsonArray(value: unknown): unknown {\n if (typeof value !== \"string\" || !value.trim()) {\n return undefined;\n }\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\nfunction parseJsonObject(value: unknown): unknown {\n if (typeof value !== \"string\" || !value.trim()) {\n return undefined;\n }\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-runtime-probe.utils.d.ts","names":[],"sources":["../src/stdio-runtime-probe.utils.ts"],"mappings":";;;iBAuBsB,iBAAA,CAAkB,MAAA,EAAQ,0BAAA,GAA6B,OAAA"}
1
+ {"version":3,"file":"stdio-runtime-probe.utils.d.ts","names":[],"sources":["../src/stdio-runtime-probe.utils.ts"],"mappings":";;;iBAwBsB,iBAAA,CAAkB,MAAA,EAAQ,0BAAA,GAA6B,OAAA"}
@@ -3,6 +3,7 @@ import { buildSpawnFailureMessage } from "./stdio-runtime-error.utils.js";
3
3
  import { spawn } from "node:child_process";
4
4
  import { Readable, Writable } from "node:stream";
5
5
  import * as acp from "@agentclientprotocol/sdk";
6
+ import { tmpdir } from "node:os";
6
7
  //#region src/stdio-runtime-probe.utils.ts
7
8
  const createProbeClientBridge = () => ({
8
9
  sessionUpdate: async () => void 0,
@@ -37,16 +38,17 @@ async function probeStdioRuntime(config) {
37
38
  });
38
39
  const stream = acp.ndJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout));
39
40
  const connection = new acp.ClientSideConnection(() => createProbeClientBridge(), stream);
41
+ const newSessionParams = {
42
+ cwd: config.cwd ?? tmpdir(),
43
+ mcpServers: []
44
+ };
40
45
  try {
41
46
  const session = await Promise.race([(async () => {
42
47
  await withTimeout(connection.initialize({
43
48
  protocolVersion: acp.PROTOCOL_VERSION,
44
49
  clientCapabilities: {}
45
50
  }), config.probeTimeoutMs, `[narp-stdio] probe timed out initializing stdio runtime`);
46
- return withTimeout(connection.newSession({
47
- cwd: config.cwd ?? process.cwd(),
48
- mcpServers: []
49
- }), config.probeTimeoutMs, `[narp-stdio] probe timed out creating remote session`);
51
+ return withTimeout(connection.newSession(newSessionParams), config.probeTimeoutMs, `[narp-stdio] probe timed out creating remote session`);
50
52
  })(), spawnErrorPromise]);
51
53
  await connection.cancel({ sessionId: session.sessionId }).catch(() => void 0);
52
54
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-runtime-probe.utils.js","names":[],"sources":["../src/stdio-runtime-probe.utils.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { Readable, Writable } from \"node:stream\";\nimport * as acp from \"@agentclientprotocol/sdk\";\nimport {\n buildStdioRuntimeLaunchEnv,\n type StdioRuntimeResolvedConfig,\n} from \"./stdio-runtime-config.utils.js\";\nimport { buildSpawnFailureMessage } from \"./stdio-runtime-error.utils.js\";\n\ntype ProbeClientBridge = {\n sessionUpdate: (params: { sessionId: string; update: unknown }) => Promise<void>;\n requestPermission: () => Promise<{ outcome: { outcome: \"cancelled\" } }>;\n readTextFile: () => Promise<{ content: string }>;\n writeTextFile: () => Promise<Record<string, never>>;\n};\n\nconst createProbeClientBridge = (): ProbeClientBridge => ({\n sessionUpdate: async () => undefined,\n requestPermission: async () => ({ outcome: { outcome: \"cancelled\" } }),\n readTextFile: async () => ({ content: \"\" }),\n writeTextFile: async () => ({}),\n});\n\nexport async function probeStdioRuntime(config: StdioRuntimeResolvedConfig): Promise<void> {\n const child = spawn(config.command, config.args, {\n cwd: config.cwd,\n env: buildStdioRuntimeLaunchEnv({\n configEnv: config.env,\n }),\n stdio: [\"pipe\", \"pipe\", \"pipe\"], windowsHide: true,\n });\n const spawnErrorPromise = new Promise<never>((_, reject) => {\n child.once(\"error\", (error) => {\n reject(new Error(buildSpawnFailureMessage({ command: config.command, cwd: config.cwd, error })));\n });\n });\n\n let stderr = \"\";\n child.stderr.setEncoding(\"utf8\");\n child.stderr.on(\"data\", (chunk: string) => {\n stderr = `${stderr}${chunk}`.slice(-4000);\n });\n\n const stream = acp.ndJsonStream(\n Writable.toWeb(child.stdin),\n Readable.toWeb(child.stdout),\n );\n const connection = new acp.ClientSideConnection(\n () => createProbeClientBridge(),\n stream,\n );\n\n try {\n const session = await Promise.race([\n (async () => {\n await withTimeout(\n connection.initialize({\n protocolVersion: acp.PROTOCOL_VERSION,\n clientCapabilities: {},\n }),\n config.probeTimeoutMs,\n `[narp-stdio] probe timed out initializing stdio runtime`,\n );\n return withTimeout(\n connection.newSession({\n cwd: config.cwd ?? process.cwd(),\n mcpServers: [],\n }),\n config.probeTimeoutMs,\n `[narp-stdio] probe timed out creating remote session`,\n );\n })(),\n spawnErrorPromise,\n ]);\n await connection.cancel({ sessionId: session.sessionId }).catch(() => undefined);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"[narp-stdio] stdio runtime probe failed\";\n throw new Error(`${message}. stderr=${stderr}`.trim());\n } finally {\n child.kill(\"SIGTERM\");\n }\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n let timeoutHandle: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => reject(new Error(message)), timeoutMs);\n });\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n"],"mappings":";;;;;;AAgBA,MAAM,iCAAoD;CACxD,eAAe,YAAY,KAAA;CAC3B,mBAAmB,aAAa,EAAE,SAAS,EAAE,SAAS,aAAa,EAAE;CACrE,cAAc,aAAa,EAAE,SAAS,IAAI;CAC1C,eAAe,aAAa,EAAE;CAC/B;AAED,eAAsB,kBAAkB,QAAmD;CACzF,MAAM,QAAQ,MAAM,OAAO,SAAS,OAAO,MAAM;EAC/C,KAAK,OAAO;EACZ,KAAK,2BAA2B,EAC9B,WAAW,OAAO,KACnB,CAAC;EACF,OAAO;GAAC;GAAQ;GAAQ;GAAO;EAAE,aAAa;EAC/C,CAAC;CACF,MAAM,oBAAoB,IAAI,SAAgB,GAAG,WAAW;AAC1D,QAAM,KAAK,UAAU,UAAU;AAC7B,UAAO,IAAI,MAAM,yBAAyB;IAAE,SAAS,OAAO;IAAS,KAAK,OAAO;IAAK;IAAO,CAAC,CAAC,CAAC;IAChG;GACF;CAEF,IAAI,SAAS;AACb,OAAM,OAAO,YAAY,OAAO;AAChC,OAAM,OAAO,GAAG,SAAS,UAAkB;AACzC,WAAS,GAAG,SAAS,QAAQ,MAAM,KAAM;GACzC;CAEF,MAAM,SAAS,IAAI,aACjB,SAAS,MAAM,MAAM,MAAM,EAC3B,SAAS,MAAM,MAAM,OAAO,CAC7B;CACD,MAAM,aAAa,IAAI,IAAI,2BACnB,yBAAyB,EAC/B,OACD;AAED,KAAI;EACF,MAAM,UAAU,MAAM,QAAQ,KAAK,EAChC,YAAY;AACX,SAAM,YACJ,WAAW,WAAW;IACpB,iBAAiB,IAAI;IACrB,oBAAoB,EAAE;IACvB,CAAC,EACF,OAAO,gBACP,0DACD;AACD,UAAO,YACL,WAAW,WAAW;IACpB,KAAK,OAAO,OAAO,QAAQ,KAAK;IAChC,YAAY,EAAE;IACf,CAAC,EACF,OAAO,gBACP,uDACD;MACC,EACJ,kBACD,CAAC;AACF,QAAM,WAAW,OAAO,EAAE,WAAW,QAAQ,WAAW,CAAC,CAAC,YAAY,KAAA,EAAU;UACzE,OAAO;EACd,MAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU;AAC3C,QAAM,IAAI,MAAM,GAAG,QAAQ,WAAW,SAAS,MAAM,CAAC;WAC9C;AACR,QAAM,KAAK,UAAU;;;AAIzB,eAAe,YACb,SACA,WACA,SACY;CACZ,IAAI;CACJ,MAAM,iBAAiB,IAAI,SAAgB,GAAG,WAAW;AACvD,kBAAgB,iBAAiB,OAAO,IAAI,MAAM,QAAQ,CAAC,EAAE,UAAU;GACvE;AACF,KAAI;AACF,SAAO,MAAM,QAAQ,KAAK,CAAC,SAAS,eAAe,CAAC;WAC5C;AACR,MAAI,cACF,cAAa,cAAc"}
1
+ {"version":3,"file":"stdio-runtime-probe.utils.js","names":[],"sources":["../src/stdio-runtime-probe.utils.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { tmpdir } from \"node:os\";\nimport { Readable, Writable } from \"node:stream\";\nimport * as acp from \"@agentclientprotocol/sdk\";\nimport {\n buildStdioRuntimeLaunchEnv,\n type StdioRuntimeResolvedConfig,\n} from \"./stdio-runtime-config.utils.js\";\nimport { buildSpawnFailureMessage } from \"./stdio-runtime-error.utils.js\";\n\ntype ProbeClientBridge = {\n sessionUpdate: (params: { sessionId: string; update: unknown }) => Promise<void>;\n requestPermission: () => Promise<{ outcome: { outcome: \"cancelled\" } }>;\n readTextFile: () => Promise<{ content: string }>;\n writeTextFile: () => Promise<Record<string, never>>;\n};\n\nconst createProbeClientBridge = (): ProbeClientBridge => ({\n sessionUpdate: async () => undefined,\n requestPermission: async () => ({ outcome: { outcome: \"cancelled\" } }),\n readTextFile: async () => ({ content: \"\" }),\n writeTextFile: async () => ({}),\n});\n\nexport async function probeStdioRuntime(config: StdioRuntimeResolvedConfig): Promise<void> {\n const child = spawn(config.command, config.args, {\n cwd: config.cwd,\n env: buildStdioRuntimeLaunchEnv({\n configEnv: config.env,\n }),\n stdio: [\"pipe\", \"pipe\", \"pipe\"], windowsHide: true,\n });\n const spawnErrorPromise = new Promise<never>((_, reject) => {\n child.once(\"error\", (error) => {\n reject(new Error(buildSpawnFailureMessage({ command: config.command, cwd: config.cwd, error })));\n });\n });\n\n let stderr = \"\";\n child.stderr.setEncoding(\"utf8\");\n child.stderr.on(\"data\", (chunk: string) => {\n stderr = `${stderr}${chunk}`.slice(-4000);\n });\n\n const stream = acp.ndJsonStream(\n Writable.toWeb(child.stdin),\n Readable.toWeb(child.stdout),\n );\n const connection = new acp.ClientSideConnection(\n () => createProbeClientBridge(),\n stream,\n );\n const newSessionParams = {\n cwd: config.cwd ?? tmpdir(),\n mcpServers: [],\n };\n\n try {\n const session = await Promise.race([\n (async () => {\n await withTimeout(\n connection.initialize({\n protocolVersion: acp.PROTOCOL_VERSION,\n clientCapabilities: {},\n }),\n config.probeTimeoutMs,\n `[narp-stdio] probe timed out initializing stdio runtime`,\n );\n return withTimeout(\n connection.newSession(newSessionParams),\n config.probeTimeoutMs,\n `[narp-stdio] probe timed out creating remote session`,\n );\n })(),\n spawnErrorPromise,\n ]);\n await connection.cancel({ sessionId: session.sessionId }).catch(() => undefined);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"[narp-stdio] stdio runtime probe failed\";\n throw new Error(`${message}. stderr=${stderr}`.trim());\n } finally {\n child.kill(\"SIGTERM\");\n }\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n let timeoutHandle: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => reject(new Error(message)), timeoutMs);\n });\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n"],"mappings":";;;;;;;AAiBA,MAAM,iCAAoD;CACxD,eAAe,YAAY,KAAA;CAC3B,mBAAmB,aAAa,EAAE,SAAS,EAAE,SAAS,aAAa,EAAE;CACrE,cAAc,aAAa,EAAE,SAAS,IAAI;CAC1C,eAAe,aAAa,EAAE;CAC/B;AAED,eAAsB,kBAAkB,QAAmD;CACzF,MAAM,QAAQ,MAAM,OAAO,SAAS,OAAO,MAAM;EAC/C,KAAK,OAAO;EACZ,KAAK,2BAA2B,EAC9B,WAAW,OAAO,KACnB,CAAC;EACF,OAAO;GAAC;GAAQ;GAAQ;GAAO;EAAE,aAAa;EAC/C,CAAC;CACF,MAAM,oBAAoB,IAAI,SAAgB,GAAG,WAAW;AAC1D,QAAM,KAAK,UAAU,UAAU;AAC7B,UAAO,IAAI,MAAM,yBAAyB;IAAE,SAAS,OAAO;IAAS,KAAK,OAAO;IAAK;IAAO,CAAC,CAAC,CAAC;IAChG;GACF;CAEF,IAAI,SAAS;AACb,OAAM,OAAO,YAAY,OAAO;AAChC,OAAM,OAAO,GAAG,SAAS,UAAkB;AACzC,WAAS,GAAG,SAAS,QAAQ,MAAM,KAAM;GACzC;CAEF,MAAM,SAAS,IAAI,aACjB,SAAS,MAAM,MAAM,MAAM,EAC3B,SAAS,MAAM,MAAM,OAAO,CAC7B;CACD,MAAM,aAAa,IAAI,IAAI,2BACnB,yBAAyB,EAC/B,OACD;CACD,MAAM,mBAAmB;EACvB,KAAK,OAAO,OAAO,QAAQ;EAC3B,YAAY,EAAE;EACf;AAED,KAAI;EACF,MAAM,UAAU,MAAM,QAAQ,KAAK,EAChC,YAAY;AACX,SAAM,YACJ,WAAW,WAAW;IACpB,iBAAiB,IAAI;IACrB,oBAAoB,EAAE;IACvB,CAAC,EACF,OAAO,gBACP,0DACD;AACD,UAAO,YACL,WAAW,WAAW,iBAAiB,EACvC,OAAO,gBACP,uDACD;MACC,EACJ,kBACD,CAAC;AACF,QAAM,WAAW,OAAO,EAAE,WAAW,QAAQ,WAAW,CAAC,CAAC,YAAY,KAAA,EAAU;UACzE,OAAO;EACd,MAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU;AAC3C,QAAM,IAAI,MAAM,GAAG,QAAQ,WAAW,SAAS,MAAM,CAAC;WAC9C;AACR,QAAM,KAAK,UAAU;;;AAIzB,eAAe,YACb,SACA,WACA,SACY;CACZ,IAAI;CACJ,MAAM,iBAAiB,IAAI,SAAgB,GAAG,WAAW;AACvD,kBAAgB,iBAAiB,OAAO,IAAI,MAAM,QAAQ,CAAC,EAAE,UAAU;GACvE;AACF,KAAI;AACF,SAAO,MAAM,QAAQ,KAAK,CAAC,SAAS,eAAe,CAAC;WAC5C;AACR,MAAI,cACF,cAAa,cAAc"}
@@ -3,7 +3,6 @@ import { NcpAgentConversationStateManager, NcpAgentRunInput, NcpAgentRunOptions,
3
3
 
4
4
  //#region src/stdio-runtime.service.d.ts
5
5
  type StdioRuntimeNcpAgentRuntimeConfig = StdioRuntimeResolvedConfig & {
6
- sessionId: string;
7
6
  stateManager?: NcpAgentConversationStateManager;
8
7
  resolveTools?: (input: NcpAgentRunInput) => ReadonlyArray<OpenAITool> | undefined;
9
8
  resolveProviderRoute?: (input: NcpAgentRunInput) => NcpProviderRuntimeRoute | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-runtime.service.d.ts","names":[],"sources":["../src/stdio-runtime.service.ts"],"mappings":";;;;KA6BY,iCAAA,GAAoC,0BAAA;EAC9C,SAAA;EACA,YAAA,GAAe,gCAAA;EACf,YAAA,IAAgB,KAAA,EAAO,gBAAA,KAAqB,aAAA,CAAc,UAAA;EAC1D,oBAAA,IAAwB,KAAA,EAAO,gBAAA,KAAqB,uBAAA;AAAA;AAAA,cA0yBzC,2BAAA,YAAuC,eAAA;EAAA,iBAGrB,MAAA;EAAA,iBAFZ,OAAA;cAEY,MAAA,EAAQ,iCAAA;EAIrC,GAAA,GACE,IAAA,EAAM,2BAAA,EACN,KAAA,EAAO,gBAAA,EACP,OAAA,GAAU,kBAAA,KACT,cAAA,CAAe,gBAAA;EAclB,OAAA,QAAoB,OAAA;AAAA"}
1
+ {"version":3,"file":"stdio-runtime.service.d.ts","names":[],"sources":["../src/stdio-runtime.service.ts"],"mappings":";;;;KAgCY,iCAAA,GAAoC,0BAAA;EAC9C,YAAA,GAAe,gCAAA;EACf,YAAA,IAAgB,KAAA,EAAO,gBAAA,KAAqB,aAAA,CAAc,UAAA;EAC1D,oBAAA,IAAwB,KAAA,EAAO,gBAAA,KAAqB,uBAAA;AAAA;AAAA,cAq0BzC,2BAAA,YAAuC,eAAA;EAAA,iBAGrB,MAAA;EAAA,iBAFZ,OAAA;cAEY,MAAA,EAAQ,iCAAA;EAIrC,GAAA,GACE,IAAA,EAAM,2BAAA,EACN,KAAA,EAAO,gBAAA,EACP,OAAA,GAAU,kBAAA,KACT,cAAA,CAAe,gBAAA;EAelB,OAAA,QAAoB,OAAA;AAAA"}
@@ -1,5 +1,7 @@
1
- import { NARP_STDIO_PROMPT_META_KEY, buildStdioRuntimeLaunchEnv, readString } from "./stdio-runtime-config.utils.js";
1
+ import { NARP_STDIO_PROMPT_META_KEY, buildStdioRuntimeLaunchEnv } from "./stdio-runtime-config.utils.js";
2
2
  import { buildSpawnFailureMessage, isAbortLikeRuntimeError, normalizeRuntimeError } from "./stdio-runtime-error.utils.js";
3
+ import { SESSION_METADATA_PATCH_KIND, createPromptTimeoutRecoveryEvents } from "./utils/stdio-runtime-recovery.utils.js";
4
+ import { extractPromptText, resolveModelId } from "./utils/stdio-runtime-input.utils.js";
3
5
  import { resolveToolNameFromAcpUpdate } from "./stdio-runtime-tool-name.utils.js";
4
6
  import { randomUUID } from "node:crypto";
5
7
  import { spawn } from "node:child_process";
@@ -8,7 +10,6 @@ import * as acp from "@agentclientprotocol/sdk";
8
10
  import { NcpEventType } from "@nextclaw/ncp";
9
11
  //#region src/stdio-runtime.service.ts
10
12
  const HERMES_ACP_ROUTE_BRIDGE_ENV = "NEXTCLAW_HERMES_ACP_ROUTE_BRIDGE";
11
- const SESSION_METADATA_PATCH_KIND = "session_metadata_patch";
12
13
  var UpdateBuffer = class {
13
14
  updates = [];
14
15
  waiters = /* @__PURE__ */ new Set();
@@ -158,16 +159,21 @@ var StdioRuntimeSession = class {
158
159
  connection = null;
159
160
  promptInFlight = false;
160
161
  remoteSessionId = null;
162
+ remoteSessionCwd = null;
161
163
  clientBridge = new StdioRuntimeClientBridge();
162
164
  stderr = "";
163
165
  pendingProviderRoute;
164
- constructor(config, sessionId) {
166
+ constructor(config) {
165
167
  this.config = config;
166
- this.sessionId = sessionId;
167
168
  }
168
169
  ensureStarted = async (params) => {
169
- this.pendingProviderRoute = params?.providerRoute;
170
- if (this.connection && this.remoteSessionId) return;
170
+ const { cwd, providerRoute } = params;
171
+ this.pendingProviderRoute = providerRoute;
172
+ if (this.connection && this.remoteSessionId) {
173
+ if (this.remoteSessionCwd === cwd) return;
174
+ await this.dispose();
175
+ }
176
+ if (!cwd) throw new Error("[narp-stdio] missing execution cwd for stdio runtime session");
171
177
  const env = buildStdioRuntimeLaunchEnv({
172
178
  configEnv: this.config.env,
173
179
  providerRoute: this.pendingProviderRoute
@@ -201,15 +207,16 @@ var StdioRuntimeSession = class {
201
207
  await withTimeout(this.connection?.initialize({
202
208
  protocolVersion: acp.PROTOCOL_VERSION,
203
209
  clientCapabilities: {}
204
- }) ?? Promise.reject(/* @__PURE__ */ new Error("[narp-stdio] stdio runtime connection not started")), this.config.startupTimeoutMs, `[narp-stdio] timed out initializing stdio runtime for session ${this.sessionId}`);
210
+ }) ?? Promise.reject(/* @__PURE__ */ new Error("[narp-stdio] stdio runtime connection not started")), this.config.startupTimeoutMs, "[narp-stdio] timed out initializing stdio runtime");
205
211
  return withTimeout(this.connection?.newSession({
206
- cwd: this.config.cwd ?? process.cwd(),
212
+ cwd,
207
213
  mcpServers: []
208
- }) ?? Promise.reject(/* @__PURE__ */ new Error("[narp-stdio] stdio runtime connection not started")), this.config.startupTimeoutMs, `[narp-stdio] timed out creating remote session for ${this.sessionId}`);
214
+ }) ?? Promise.reject(/* @__PURE__ */ new Error("[narp-stdio] stdio runtime connection not started")), this.config.startupTimeoutMs, "[narp-stdio] timed out creating remote stdio session");
209
215
  })(), spawnErrorPromise])).sessionId;
216
+ this.remoteSessionCwd = cwd;
210
217
  };
211
218
  runPrompt = async (params) => {
212
- const { meta, modelId, onUpdate, signal, text } = params;
219
+ const { meta, modelId, onUpdate, sessionId, signal, text } = params;
213
220
  if (!this.connection || !this.remoteSessionId) throw new Error("[narp-stdio] stdio runtime connection not started");
214
221
  if (this.promptInFlight) throw new Error("[narp-stdio] concurrent prompt is not supported for one stdio session");
215
222
  this.promptInFlight = true;
@@ -232,7 +239,7 @@ var StdioRuntimeSession = class {
232
239
  text
233
240
  }],
234
241
  _meta: { [NARP_STDIO_PROMPT_META_KEY]: meta }
235
- }), this.config.requestTimeoutMs, `[narp-stdio] prompt timed out for session ${this.sessionId}`);
242
+ }), this.config.requestTimeoutMs, `[narp-stdio] prompt timed out for session ${sessionId}`);
236
243
  } finally {
237
244
  releaseAbort();
238
245
  detach();
@@ -260,20 +267,26 @@ var StdioRuntimeSession = class {
260
267
  };
261
268
  };
262
269
  readStderr = () => this.stderr;
270
+ readPromptTimeoutMetadataResetKeys = () => this.config.resetSessionMetadataOnPromptTimeout;
263
271
  dispose = async () => {
264
272
  await this.cancel();
265
273
  const child = this.child;
266
274
  this.connection = null;
267
275
  this.remoteSessionId = null;
276
+ this.remoteSessionCwd = null;
268
277
  this.child = null;
269
278
  if (!child || child.killed || child.exitCode !== null || child.signalCode !== null) return;
279
+ const exited = new Promise((resolve) => {
280
+ child.once("exit", () => resolve());
281
+ child.once("error", () => resolve());
282
+ });
270
283
  const forceKill = setTimeout(() => {
271
284
  child.kill("SIGKILL");
272
285
  }, 3e3);
273
- child.once("exit", () => {
274
- clearTimeout(forceKill);
275
- });
286
+ forceKill.unref();
276
287
  child.kill("SIGTERM");
288
+ await exited;
289
+ clearTimeout(forceKill);
277
290
  };
278
291
  };
279
292
  var StdioRuntimeRunController = class {
@@ -300,6 +313,7 @@ var StdioRuntimeRunController = class {
300
313
  if (!requestMessage) throw new Error("[narp-stdio] runtime.run requires at least one input message");
301
314
  const assistantMessageId = createAssistantMessageId(requestMessage.id);
302
315
  const promptPromise = this.session.runPrompt({
316
+ sessionId: this.input.sessionId,
303
317
  text: extractPromptText(requestMessage),
304
318
  meta: {
305
319
  ...this.input.correlationId ? { correlationId: this.input.correlationId } : {},
@@ -398,6 +412,14 @@ var StdioRuntimeRunController = class {
398
412
  };
399
413
  emitFailureEvents = async function* (assistantMessageId, error) {
400
414
  const ncpError = normalizeRuntimeError(error, { stderr: this.session.readStderr() });
415
+ for (const recoveryEvent of createPromptTimeoutRecoveryEvents({
416
+ correlationId: this.input.correlationId,
417
+ error,
418
+ messageId: assistantMessageId,
419
+ resetKeys: this.session.readPromptTimeoutMetadataResetKeys(),
420
+ runId: this.runId,
421
+ sessionId: this.input.sessionId
422
+ })) yield* this.emitEvent(recoveryEvent);
401
423
  yield* this.emitEvent({
402
424
  type: NcpEventType.MessageFailed,
403
425
  payload: {
@@ -597,28 +619,19 @@ var StdioRuntimeNcpAgentRuntime = class {
597
619
  session;
598
620
  constructor(config) {
599
621
  this.config = config;
600
- this.session = new StdioRuntimeSession(config, config.sessionId);
622
+ this.session = new StdioRuntimeSession(config);
601
623
  }
602
624
  run = async function* (input, options) {
603
- await this.session.ensureStarted({ providerRoute: this.config.resolveProviderRoute?.(input) });
625
+ await this.session.ensureStarted({
626
+ cwd: input.executionContext?.cwd,
627
+ providerRoute: this.config.resolveProviderRoute?.(input)
628
+ });
604
629
  yield* new StdioRuntimeRunController(this.session, input, this.config.stateManager, this.config.resolveTools, this.config.resolveProviderRoute).execute(options);
605
630
  };
606
631
  dispose = async () => {
607
632
  await this.session.dispose();
608
633
  };
609
634
  };
610
- function extractPromptText(message) {
611
- const text = (message.parts ?? []).map((part) => {
612
- if (part.type === "text" || part.type === "reasoning" || part.type === "rich-text") return part.text ?? "";
613
- return "";
614
- }).join("\n").trim();
615
- return text.length > 0 ? text : "[empty message]";
616
- }
617
- function resolveModelId(params) {
618
- const { metadata, providerRoute } = params;
619
- const modelId = providerRoute?.model ?? readString(metadata?.preferred_model) ?? readString(metadata?.preferredModel) ?? readString(metadata?.model);
620
- return modelId === "__nextclaw_runtime_default__" ? void 0 : modelId;
621
- }
622
635
  function readSessionMetadataPatch(meta) {
623
636
  const narpMeta = isRecord(meta) ? meta[NARP_STDIO_PROMPT_META_KEY] : void 0;
624
637
  const patch = isRecord(narpMeta) ? narpMeta.sessionMetadataPatch : void 0;
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-runtime.service.js","names":[],"sources":["../src/stdio-runtime.service.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { spawn, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { Readable, Writable } from \"node:stream\";\nimport * as acp from \"@agentclientprotocol/sdk\";\nimport {\n NcpEventType,\n type NcpAgentConversationStateManager,\n type NcpAgentRunInput,\n type NcpAgentRunOptions,\n type NcpAgentRuntime,\n type NcpEndpointEvent,\n type NcpProviderRuntimeRoute,\n type OpenAITool,\n} from \"@nextclaw/ncp\";\nimport type { StdioRuntimeResolvedConfig, NarpStdioPromptMeta } from \"./stdio-runtime-config.utils.js\";\nimport {\n NARP_STDIO_PROMPT_META_KEY,\n buildStdioRuntimeLaunchEnv,\n readString,\n} from \"./stdio-runtime-config.utils.js\";\nimport {\n buildSpawnFailureMessage,\n isAbortLikeRuntimeError,\n normalizeRuntimeError,\n} from \"./stdio-runtime-error.utils.js\";\nimport { resolveToolNameFromAcpUpdate } from \"./stdio-runtime-tool-name.utils.js\";\ntype AcpClientUpdate = acp.SessionUpdate;\nconst HERMES_ACP_ROUTE_BRIDGE_ENV = \"NEXTCLAW_HERMES_ACP_ROUTE_BRIDGE\";\nconst SESSION_METADATA_PATCH_KIND = \"session_metadata_patch\";\nexport type StdioRuntimeNcpAgentRuntimeConfig = StdioRuntimeResolvedConfig & {\n sessionId: string;\n stateManager?: NcpAgentConversationStateManager;\n resolveTools?: (input: NcpAgentRunInput) => ReadonlyArray<OpenAITool> | undefined;\n resolveProviderRoute?: (input: NcpAgentRunInput) => NcpProviderRuntimeRoute | undefined;\n};\ntype AcpToolState = {\n toolName: string;\n args?: string;\n completed: boolean;\n};\n\ntype PromptExecutionState = { settled: boolean; error: unknown };\n\nclass UpdateBuffer {\n private readonly updates: AcpClientUpdate[] = [];\n private waiters = new Set<() => void>();\n\n push = (update: AcpClientUpdate): void => {\n this.updates.push(update);\n this.flush();\n };\n\n shift = (): AcpClientUpdate | undefined => this.updates.shift();\n\n hasItems = (): boolean => this.updates.length > 0;\n\n waitForChange = async (): Promise<void> => {\n if (this.updates.length > 0) {\n return;\n }\n await new Promise<void>((resolve) => {\n this.waiters.add(resolve);\n });\n };\n\n notify = (): void => {\n this.flush();\n };\n\n private flush = (): void => {\n if (this.waiters.size === 0) {\n return;\n }\n const waiters = [...this.waiters];\n this.waiters.clear();\n for (const waiter of waiters) {\n waiter();\n }\n };\n}\n\nclass PromptUpdateCollector {\n private readonly parts: Array<\n | { type: \"text\"; text: string }\n | { type: \"reasoning\"; text: string }\n | { type: \"tool-invocation\"; toolCallId: string; toolName: string; state: \"partial-call\" | \"call\"; args: string }\n > = [];\n private readonly toolIndex = new Map<string, number>();\n\n apply = (event: NcpEndpointEvent): void => {\n switch (event.type) {\n case NcpEventType.MessageTextDelta:\n this.appendPart(\"text\", event.payload.delta);\n return;\n case NcpEventType.MessageReasoningDelta:\n this.appendPart(\"reasoning\", event.payload.delta);\n return;\n case NcpEventType.MessageToolCallStart:\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: event.payload.toolName,\n args: \"\",\n state: \"partial-call\",\n });\n return;\n case NcpEventType.MessageToolCallArgs:\n {\n const tool = this.readTool(event.payload.toolCallId);\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: tool.toolName,\n args: event.payload.args,\n state: \"partial-call\",\n });\n }\n return;\n case NcpEventType.MessageToolCallArgsDelta:\n {\n const tool = this.readTool(event.payload.toolCallId);\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: tool.toolName,\n args: `${tool.args}${event.payload.delta}`,\n state: \"partial-call\",\n });\n }\n return;\n case NcpEventType.MessageToolCallEnd:\n {\n const tool = this.readTool(event.payload.toolCallId);\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: tool.toolName,\n args: tool.args,\n state: \"call\",\n });\n }\n return;\n default:\n return;\n }\n };\n\n hasParts = (): boolean => this.parts.length > 0;\n\n buildParts = (): Array<Record<string, unknown>> => structuredClone(this.parts);\n\n private appendPart = (type: \"text\" | \"reasoning\", text: string): void => {\n if (!text) {\n return;\n }\n const last = this.parts.at(-1);\n if (last?.type === type) {\n last.text = `${last.text}${text}`;\n return;\n }\n this.parts.push({ type, text });\n };\n\n private upsertTool = (nextTool: {\n toolCallId: string;\n toolName: string;\n args: string;\n state: \"partial-call\" | \"call\";\n }): void => {\n const existingIndex = this.toolIndex.get(nextTool.toolCallId);\n if (typeof existingIndex === \"number\") {\n const existing = this.parts[existingIndex];\n if (existing?.type !== \"tool-invocation\") {\n return;\n }\n this.parts[existingIndex] = {\n ...existing,\n ...nextTool,\n };\n return;\n }\n\n this.toolIndex.set(nextTool.toolCallId, this.parts.length);\n this.parts.push({\n type: \"tool-invocation\",\n ...nextTool,\n });\n };\n\n private readTool = (toolCallId: string): { toolName: string; args: string } => {\n const index = this.toolIndex.get(toolCallId);\n const part = typeof index === \"number\" ? this.parts[index] : null;\n if (part?.type !== \"tool-invocation\") {\n return { toolName: \"unknown\", args: \"\" };\n }\n return { toolName: part.toolName, args: part.args };\n };\n}\n\nclass StdioRuntimeClientBridge {\n private activeSessionId: string | null = null;\n private updateHandler: ((update: AcpClientUpdate) => void) | null = null;\n\n attach = (params: {\n sessionId: string;\n onUpdate: (update: AcpClientUpdate) => void;\n }): (() => void) => {\n this.activeSessionId = params.sessionId;\n this.updateHandler = params.onUpdate;\n return () => {\n if (this.activeSessionId !== params.sessionId) {\n return;\n }\n this.activeSessionId = null;\n this.updateHandler = null;\n };\n };\n\n sessionUpdate = async (params: { sessionId: string; update: AcpClientUpdate }): Promise<void> => {\n if (params.sessionId !== this.activeSessionId) {\n return;\n }\n this.updateHandler?.(params.update);\n };\n\n requestPermission = async (): Promise<{\n outcome: { outcome: \"cancelled\" };\n }> => ({\n outcome: { outcome: \"cancelled\" },\n });\n\n readTextFile = async (): Promise<{ content: string }> => ({ content: \"\" });\n\n writeTextFile = async (): Promise<Record<string, never>> => ({});\n}\n\nclass StdioRuntimeSession {\n private child: ChildProcessWithoutNullStreams | null = null;\n private connection: acp.ClientSideConnection | null = null;\n private promptInFlight = false;\n private remoteSessionId: string | null = null;\n private readonly clientBridge = new StdioRuntimeClientBridge();\n private stderr = \"\";\n private pendingProviderRoute: NcpProviderRuntimeRoute | undefined;\n\n constructor(\n private readonly config: StdioRuntimeResolvedConfig,\n private readonly sessionId: string,\n ) {}\n\n ensureStarted = async (params?: {\n providerRoute?: NcpProviderRuntimeRoute;\n }): Promise<void> => {\n this.pendingProviderRoute = params?.providerRoute;\n if (this.connection && this.remoteSessionId) {\n return;\n }\n\n const env = buildStdioRuntimeLaunchEnv({\n configEnv: this.config.env,\n providerRoute: this.pendingProviderRoute,\n });\n\n this.child = spawn(this.config.command, this.config.args, {\n cwd: this.config.cwd,\n env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"], windowsHide: true,\n });\n const spawnErrorPromise = new Promise<never>((_, reject) => {\n this.child?.once(\"error\", (error) => {\n reject(\n new Error(\n buildSpawnFailureMessage({\n command: this.config.command,\n cwd: this.config.cwd,\n error,\n }),\n ),\n );\n });\n });\n this.child.stderr.setEncoding(\"utf8\");\n this.child.stderr.on(\"data\", (chunk: string) => {\n this.stderr = `${this.stderr}${chunk}`.slice(-4000);\n });\n\n const stream = acp.ndJsonStream(\n Writable.toWeb(this.child.stdin),\n Readable.toWeb(this.child.stdout),\n );\n this.connection = new acp.ClientSideConnection(() => this.clientBridge, stream);\n\n const session = await Promise.race([\n (async () => {\n await withTimeout(\n this.connection?.initialize({\n protocolVersion: acp.PROTOCOL_VERSION,\n clientCapabilities: {},\n }) ?? Promise.reject(new Error(\"[narp-stdio] stdio runtime connection not started\")),\n this.config.startupTimeoutMs,\n `[narp-stdio] timed out initializing stdio runtime for session ${this.sessionId}`,\n );\n\n return withTimeout(\n this.connection?.newSession({\n cwd: this.config.cwd ?? process.cwd(),\n mcpServers: [],\n }) ?? Promise.reject(new Error(\"[narp-stdio] stdio runtime connection not started\")),\n this.config.startupTimeoutMs,\n `[narp-stdio] timed out creating remote session for ${this.sessionId}`,\n );\n })(),\n spawnErrorPromise,\n ]);\n this.remoteSessionId = session.sessionId;\n };\n\n runPrompt = async (params: {\n text: string;\n meta: NarpStdioPromptMeta;\n modelId?: string;\n signal?: AbortSignal;\n onUpdate: (update: AcpClientUpdate) => void;\n }): Promise<acp.PromptResponse> => {\n const { meta, modelId, onUpdate, signal, text } = params;\n if (!this.connection || !this.remoteSessionId) {\n throw new Error(\"[narp-stdio] stdio runtime connection not started\");\n }\n if (this.promptInFlight) {\n throw new Error(\"[narp-stdio] concurrent prompt is not supported for one stdio session\");\n }\n\n this.promptInFlight = true;\n const detach = this.clientBridge.attach({\n sessionId: this.remoteSessionId,\n onUpdate,\n });\n const releaseAbort = this.bindAbortSignal(signal);\n\n try {\n if (modelId && this.config.env?.[HERMES_ACP_ROUTE_BRIDGE_ENV] !== \"1\") {\n try {\n // Hermes ACP must switch on prompt-scoped providerRoute, not modelId alone.\n await this.connection.unstable_setSessionModel({\n sessionId: this.remoteSessionId,\n modelId,\n });\n } catch {\n // Not all ACP agents implement unstable session model switching.\n }\n }\n\n return await withTimeout(\n this.connection.prompt({\n sessionId: this.remoteSessionId,\n prompt: [{ type: \"text\", text }],\n _meta: {\n [NARP_STDIO_PROMPT_META_KEY]: meta,\n },\n }),\n this.config.requestTimeoutMs,\n `[narp-stdio] prompt timed out for session ${this.sessionId}`,\n );\n } finally {\n releaseAbort();\n detach();\n this.promptInFlight = false;\n }\n };\n\n cancel = async (): Promise<void> => {\n if (!this.connection || !this.remoteSessionId) {\n return;\n }\n try {\n await this.connection.cancel({\n sessionId: this.remoteSessionId,\n });\n } catch {\n // Best effort.\n }\n };\n\n private bindAbortSignal = (signal?: AbortSignal): (() => void) => {\n if (!signal) {\n return () => undefined;\n }\n\n const onAbort = (): void => {\n void this.cancel();\n };\n\n if (signal.aborted) {\n onAbort();\n return () => undefined;\n }\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n return () => {\n signal.removeEventListener(\"abort\", onAbort);\n };\n };\n\n readStderr = (): string => this.stderr;\n\n dispose = async (): Promise<void> => {\n await this.cancel();\n const child = this.child;\n this.connection = null;\n this.remoteSessionId = null;\n this.child = null;\n if (!child || child.killed || child.exitCode !== null || child.signalCode !== null) {\n return;\n }\n\n const forceKill = setTimeout(() => {\n child.kill(\"SIGKILL\");\n }, 3_000);\n child.once(\"exit\", () => {\n clearTimeout(forceKill);\n });\n child.kill(\"SIGTERM\");\n };\n}\n\nclass StdioRuntimeRunController {\n private readonly buffer = new UpdateBuffer();\n private readonly collector = new PromptUpdateCollector();\n private readonly toolStates = new Map<string, AcpToolState>();\n private textStarted = false;\n private reasoningStarted = false;\n private readonly resolvedTools: ReadonlyArray<OpenAITool>;\n private readonly resolvedProviderRoute: NcpProviderRuntimeRoute | undefined;\n private readonly runId: string;\n\n constructor(\n private readonly session: StdioRuntimeSession,\n private readonly input: NcpAgentRunInput,\n private readonly stateManager?: NcpAgentConversationStateManager,\n private readonly resolveTools?: (input: NcpAgentRunInput) => ReadonlyArray<OpenAITool> | undefined,\n private readonly resolveProviderRoute?: (input: NcpAgentRunInput) => NcpProviderRuntimeRoute | undefined,\n ) {\n this.resolvedTools = resolveTools?.(input) ?? [];\n this.resolvedProviderRoute = resolveProviderRoute?.(input);\n this.runId = (input as NcpAgentRunInput & { runId?: string }).runId ?? `narp-stdio:${input.sessionId}:${randomUUID()}`;\n }\n execute = async function* (\n this: StdioRuntimeRunController,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n const requestMessage = this.input.messages.at(-1);\n if (!requestMessage) {\n throw new Error(\"[narp-stdio] runtime.run requires at least one input message\");\n }\n\n const assistantMessageId = createAssistantMessageId(requestMessage.id);\n const promptPromise = this.session.runPrompt({\n text: extractPromptText(requestMessage),\n meta: {\n ...(this.input.correlationId ? { correlationId: this.input.correlationId } : {}),\n ...(this.resolvedProviderRoute ? { providerRoute: this.resolvedProviderRoute } : {}),\n ...(this.input.metadata ? { sessionMetadata: this.input.metadata } : {}),\n ...(this.resolvedTools.length > 0 ? { tools: this.resolvedTools } : {}),\n },\n modelId: resolveModelId({\n providerRoute: this.resolvedProviderRoute,\n metadata: this.input.metadata,\n }),\n signal: options?.signal,\n onUpdate: (update) => this.buffer.push(update),\n });\n const promptState = this.trackPromptState(promptPromise);\n\n yield* this.emitRunStartedEvents(assistantMessageId);\n\n try {\n yield* this.drainPromptUpdates(assistantMessageId, promptState);\n if (this.shouldExitForAbort(options, promptState.error)) {\n return;\n }\n if (promptState.error) throw promptState.error;\n yield* this.emitCompletionEvents(assistantMessageId);\n } catch (error) {\n if (this.shouldExitForAbort(options, error)) {\n return;\n }\n yield* this.emitFailureEvents(assistantMessageId, error);\n }\n };\n private trackPromptState = (\n promptPromise: Promise<acp.PromptResponse>,\n ): PromptExecutionState => {\n const promptState: PromptExecutionState = {\n settled: false,\n error: null,\n };\n\n promptPromise\n .then(() => {\n promptState.settled = true;\n this.buffer.notify();\n })\n .catch((error) => {\n promptState.settled = true;\n promptState.error = error;\n this.buffer.notify();\n });\n\n return promptState;\n };\n private emitRunStartedEvents = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n ): AsyncGenerator<NcpEndpointEvent> {\n yield* this.emitEvent({\n type: NcpEventType.MessageAccepted,\n payload: {\n messageId: assistantMessageId,\n ...(this.input.correlationId ? { correlationId: this.input.correlationId } : {}),\n },\n });\n yield* this.emitEvent({\n type: NcpEventType.RunStarted,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n runId: this.runId,\n },\n });\n };\n private drainPromptUpdates = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n promptState: PromptExecutionState,\n ): AsyncGenerator<NcpEndpointEvent> {\n while (!promptState.settled || this.buffer.hasItems()) {\n const update = this.buffer.shift();\n if (!update) {\n await this.buffer.waitForChange();\n continue;\n }\n for (const event of this.translateUpdate(update, assistantMessageId)) {\n yield* this.emitEvent(event);\n }\n }\n };\n private shouldExitForAbort = (\n options: NcpAgentRunOptions | undefined,\n error: unknown,\n ): boolean => options?.signal?.aborted === true || isAbortLikeRuntimeError(error);\n private emitCompletionEvents = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n ): AsyncGenerator<NcpEndpointEvent> {\n for (const terminalEvent of this.createTerminalEvents(assistantMessageId)) {\n yield* this.emitEvent(terminalEvent);\n }\n\n if (!this.collector.hasParts()) {\n throw new Error(\n `[narp-stdio] ACP prompt completed without any assistant content for session ${this.input.sessionId}. stderr=${this.session.readStderr()}`,\n );\n }\n\n yield* this.emitEvent({\n type: NcpEventType.MessageCompleted,\n payload: {\n sessionId: this.input.sessionId,\n correlationId: this.input.correlationId,\n message: {\n id: assistantMessageId,\n sessionId: this.input.sessionId,\n role: \"assistant\",\n status: \"final\",\n parts: this.collector.buildParts() as never,\n timestamp: new Date().toISOString(),\n },\n },\n });\n yield* this.emitEvent({\n type: NcpEventType.RunFinished,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n runId: this.runId,\n },\n });\n };\n private emitFailureEvents = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n error: unknown,\n ): AsyncGenerator<NcpEndpointEvent> {\n const ncpError = normalizeRuntimeError(error, { stderr: this.session.readStderr() });\n yield* this.emitEvent({\n type: NcpEventType.MessageFailed,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n correlationId: this.input.correlationId,\n error: ncpError,\n },\n });\n yield* this.emitEvent({\n type: NcpEventType.RunError,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n runId: this.runId,\n error: ncpError.message,\n },\n });\n };\n private emitEvent = async function* (\n this: StdioRuntimeRunController,\n event: NcpEndpointEvent,\n ): AsyncGenerator<NcpEndpointEvent> {\n this.collector.apply(event);\n await this.stateManager?.dispatch(event);\n yield event;\n };\n private translateUpdate = (\n update: AcpClientUpdate,\n messageId: string,\n ): NcpEndpointEvent[] => {\n switch (update.sessionUpdate) {\n case \"agent_message_chunk\":\n return this.emitTextDelta(update.content, messageId);\n case \"agent_thought_chunk\":\n return this.emitReasoningDelta(update.content, messageId);\n case \"tool_call\":\n return this.emitToolCallStart(update, messageId);\n case \"tool_call_update\":\n return this.emitToolCallUpdate(update);\n case \"session_info_update\":\n return this.emitSessionInfoUpdate(update, messageId);\n default:\n return [];\n }\n };\n\n private emitSessionInfoUpdate = (\n update: Extract<AcpClientUpdate, { sessionUpdate: \"session_info_update\" }>,\n messageId: string,\n ): NcpEndpointEvent[] => {\n const patch = readSessionMetadataPatch(update._meta);\n if (!patch) {\n return [];\n }\n return [\n {\n type: NcpEventType.RunMetadata,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n runId: this.runId,\n ...(this.input.correlationId ? { correlationId: this.input.correlationId } : {}),\n metadata: {\n kind: SESSION_METADATA_PATCH_KIND,\n sessionMetadataPatch: patch,\n },\n },\n },\n ];\n };\n\n private emitTextDelta = (\n content: { type: string; text?: string },\n messageId: string,\n ): NcpEndpointEvent[] => this.emitContentDelta({\n content,\n messageId,\n started: this.textStarted,\n markStarted: () => {\n this.textStarted = true;\n },\n startType: NcpEventType.MessageTextStart,\n deltaType: NcpEventType.MessageTextDelta,\n });\n\n private emitReasoningDelta = (\n content: { type: string; text?: string },\n messageId: string,\n ): NcpEndpointEvent[] => this.emitContentDelta({\n content,\n messageId,\n started: this.reasoningStarted,\n markStarted: () => {\n this.reasoningStarted = true;\n },\n startType: NcpEventType.MessageReasoningStart,\n deltaType: NcpEventType.MessageReasoningDelta,\n });\n\n private emitContentDelta = (params: {\n content: { type: string; text?: string };\n messageId: string;\n started: boolean;\n markStarted: () => void;\n startType: NcpEventType.MessageTextStart | NcpEventType.MessageReasoningStart;\n deltaType: NcpEventType.MessageTextDelta | NcpEventType.MessageReasoningDelta;\n }): NcpEndpointEvent[] => {\n const { content, deltaType, markStarted, messageId, started, startType } = params;\n if (content.type !== \"text\" || !content.text) {\n return [];\n }\n const events: NcpEndpointEvent[] = [];\n if (!started) {\n markStarted();\n events.push({\n type: startType,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n },\n });\n }\n events.push({\n type: deltaType,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n delta: content.text,\n },\n });\n return events;\n };\n\n private emitToolCallStart = (\n update: Extract<AcpClientUpdate, { sessionUpdate: \"tool_call\" }>,\n messageId: string,\n ): NcpEndpointEvent[] => {\n const toolName = resolveToolName(update);\n const args = serializeToolArgs(update.rawInput);\n this.toolStates.set(update.toolCallId, {\n toolName,\n args,\n completed: false,\n });\n return [\n {\n type: NcpEventType.MessageToolCallStart,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n toolCallId: update.toolCallId,\n toolName,\n },\n },\n {\n type: NcpEventType.MessageToolCallArgs,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n args,\n },\n },\n ];\n };\n\n private emitToolCallUpdate = (\n update: Extract<AcpClientUpdate, { sessionUpdate: \"tool_call_update\" }>,\n ): NcpEndpointEvent[] => {\n const existing = this.toolStates.get(update.toolCallId);\n if (!existing) {\n return [];\n }\n\n const nextArgs = serializeToolArgs(update.rawInput);\n const argsChanged = typeof update.rawInput !== \"undefined\" && nextArgs !== existing.args;\n const events: NcpEndpointEvent[] = [];\n if (argsChanged) {\n existing.args = nextArgs;\n events.push({\n type: NcpEventType.MessageToolCallArgs,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n args: nextArgs,\n },\n });\n }\n\n if (update.status === \"completed\" || update.status === \"failed\") {\n if (!existing.completed) {\n existing.completed = true;\n events.push({\n type: NcpEventType.MessageToolCallEnd,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n },\n });\n }\n if (typeof update.rawOutput !== \"undefined\") {\n events.push({\n type: NcpEventType.MessageToolCallResult,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n content: update.rawOutput,\n },\n });\n }\n }\n return events;\n };\n\n private createTerminalEvents = (messageId: string): NcpEndpointEvent[] => {\n const events: NcpEndpointEvent[] = [];\n if (this.textStarted) {\n events.push({\n type: NcpEventType.MessageTextEnd,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n },\n });\n this.textStarted = false;\n }\n if (this.reasoningStarted) {\n events.push({\n type: NcpEventType.MessageReasoningEnd,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n },\n });\n this.reasoningStarted = false;\n }\n for (const [toolCallId, state] of this.toolStates.entries()) {\n if (state.completed) {\n continue;\n }\n events.push({\n type: NcpEventType.MessageToolCallEnd,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId,\n },\n });\n state.completed = true;\n }\n return events;\n };\n}\n\nexport class StdioRuntimeNcpAgentRuntime implements NcpAgentRuntime {\n private readonly session: StdioRuntimeSession;\n\n constructor(private readonly config: StdioRuntimeNcpAgentRuntimeConfig) {\n this.session = new StdioRuntimeSession(config, config.sessionId);\n }\n\n run = async function* (\n this: StdioRuntimeNcpAgentRuntime,\n input: NcpAgentRunInput,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n await this.session.ensureStarted({\n providerRoute: this.config.resolveProviderRoute?.(input),\n });\n const controller = new StdioRuntimeRunController(\n this.session,\n input,\n this.config.stateManager,\n this.config.resolveTools,\n this.config.resolveProviderRoute,\n );\n yield* controller.execute(options);\n };\n\n dispose = async (): Promise<void> => {\n await this.session.dispose();\n };\n}\n\nfunction extractPromptText(message: { parts?: Array<{ type: string; text?: string }> }): string {\n const text = (message.parts ?? [])\n .map((part) => {\n if (part.type === \"text\" || part.type === \"reasoning\" || part.type === \"rich-text\") {\n return part.text ?? \"\";\n }\n return \"\";\n })\n .join(\"\\n\")\n .trim();\n return text.length > 0 ? text : \"[empty message]\";\n}\n\nfunction resolveModelId(params: {\n providerRoute?: NcpProviderRuntimeRoute;\n metadata?: Record<string, unknown>;\n}): string | undefined {\n const { metadata, providerRoute } = params;\n const modelId =\n providerRoute?.model ??\n readString(metadata?.preferred_model) ??\n readString(metadata?.preferredModel) ??\n readString(metadata?.model);\n return modelId === \"__nextclaw_runtime_default__\" ? undefined : modelId;\n}\n\nfunction readSessionMetadataPatch(meta: unknown): Record<string, unknown> | null {\n const narpMeta = isRecord(meta)\n ? meta[NARP_STDIO_PROMPT_META_KEY]\n : undefined;\n const patch = isRecord(narpMeta)\n ? narpMeta.sessionMetadataPatch\n : undefined;\n return isRecord(patch) && Object.keys(patch).length > 0\n ? structuredClone(patch)\n : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction resolveToolName(\n update: Extract<AcpClientUpdate, { sessionUpdate: \"tool_call\" }>,\n): string {\n return resolveToolNameFromAcpUpdate(update);\n}\n\nfunction createAssistantMessageId(requestMessageId: string): string {\n const normalizedRequestId = requestMessageId.trim() || \"request\";\n return `assistant:${normalizedRequestId}:${randomUUID()}`;\n}\n\nfunction serializeToolArgs(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"undefined\") {\n return \"{}\";\n }\n return JSON.stringify(value);\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n try {\n return await Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n reject(new Error(message));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stdio-runtime.service.js","names":[],"sources":["../src/stdio-runtime.service.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { spawn, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { Readable, Writable } from \"node:stream\";\nimport * as acp from \"@agentclientprotocol/sdk\";\nimport {\n NcpEventType,\n type NcpAgentConversationStateManager,\n type NcpAgentRunInput,\n type NcpAgentRunOptions,\n type NcpAgentRuntime,\n type NcpEndpointEvent,\n type NcpProviderRuntimeRoute,\n type OpenAITool,\n} from \"@nextclaw/ncp\";\nimport type { StdioRuntimeResolvedConfig, NarpStdioPromptMeta } from \"./stdio-runtime-config.utils.js\";\nimport {\n NARP_STDIO_PROMPT_META_KEY,\n buildStdioRuntimeLaunchEnv,\n} from \"./stdio-runtime-config.utils.js\";\nimport {\n buildSpawnFailureMessage,\n isAbortLikeRuntimeError,\n normalizeRuntimeError,\n} from \"./stdio-runtime-error.utils.js\";\nimport {\n createPromptTimeoutRecoveryEvents,\n SESSION_METADATA_PATCH_KIND,\n} from \"./utils/stdio-runtime-recovery.utils.js\";\nimport { extractPromptText, resolveModelId } from \"./utils/stdio-runtime-input.utils.js\";\nimport { resolveToolNameFromAcpUpdate } from \"./stdio-runtime-tool-name.utils.js\";\ntype AcpClientUpdate = acp.SessionUpdate;\nconst HERMES_ACP_ROUTE_BRIDGE_ENV = \"NEXTCLAW_HERMES_ACP_ROUTE_BRIDGE\";\nexport type StdioRuntimeNcpAgentRuntimeConfig = StdioRuntimeResolvedConfig & {\n stateManager?: NcpAgentConversationStateManager;\n resolveTools?: (input: NcpAgentRunInput) => ReadonlyArray<OpenAITool> | undefined;\n resolveProviderRoute?: (input: NcpAgentRunInput) => NcpProviderRuntimeRoute | undefined;\n};\ntype AcpToolState = {\n toolName: string;\n args?: string;\n completed: boolean;\n};\n\ntype PromptExecutionState = { settled: boolean; error: unknown };\n\nclass UpdateBuffer {\n private readonly updates: AcpClientUpdate[] = [];\n private waiters = new Set<() => void>();\n\n push = (update: AcpClientUpdate): void => {\n this.updates.push(update);\n this.flush();\n };\n\n shift = (): AcpClientUpdate | undefined => this.updates.shift();\n\n hasItems = (): boolean => this.updates.length > 0;\n\n waitForChange = async (): Promise<void> => {\n if (this.updates.length > 0) {\n return;\n }\n await new Promise<void>((resolve) => {\n this.waiters.add(resolve);\n });\n };\n\n notify = (): void => {\n this.flush();\n };\n\n private flush = (): void => {\n if (this.waiters.size === 0) {\n return;\n }\n const waiters = [...this.waiters];\n this.waiters.clear();\n for (const waiter of waiters) {\n waiter();\n }\n };\n}\n\nclass PromptUpdateCollector {\n private readonly parts: Array<\n | { type: \"text\"; text: string }\n | { type: \"reasoning\"; text: string }\n | { type: \"tool-invocation\"; toolCallId: string; toolName: string; state: \"partial-call\" | \"call\"; args: string }\n > = [];\n private readonly toolIndex = new Map<string, number>();\n\n apply = (event: NcpEndpointEvent): void => {\n switch (event.type) {\n case NcpEventType.MessageTextDelta:\n this.appendPart(\"text\", event.payload.delta);\n return;\n case NcpEventType.MessageReasoningDelta:\n this.appendPart(\"reasoning\", event.payload.delta);\n return;\n case NcpEventType.MessageToolCallStart:\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: event.payload.toolName,\n args: \"\",\n state: \"partial-call\",\n });\n return;\n case NcpEventType.MessageToolCallArgs:\n {\n const tool = this.readTool(event.payload.toolCallId);\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: tool.toolName,\n args: event.payload.args,\n state: \"partial-call\",\n });\n }\n return;\n case NcpEventType.MessageToolCallArgsDelta:\n {\n const tool = this.readTool(event.payload.toolCallId);\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: tool.toolName,\n args: `${tool.args}${event.payload.delta}`,\n state: \"partial-call\",\n });\n }\n return;\n case NcpEventType.MessageToolCallEnd:\n {\n const tool = this.readTool(event.payload.toolCallId);\n this.upsertTool({\n toolCallId: event.payload.toolCallId,\n toolName: tool.toolName,\n args: tool.args,\n state: \"call\",\n });\n }\n return;\n default:\n return;\n }\n };\n\n hasParts = (): boolean => this.parts.length > 0;\n\n buildParts = (): Array<Record<string, unknown>> => structuredClone(this.parts);\n\n private appendPart = (type: \"text\" | \"reasoning\", text: string): void => {\n if (!text) {\n return;\n }\n const last = this.parts.at(-1);\n if (last?.type === type) {\n last.text = `${last.text}${text}`;\n return;\n }\n this.parts.push({ type, text });\n };\n\n private upsertTool = (nextTool: {\n toolCallId: string;\n toolName: string;\n args: string;\n state: \"partial-call\" | \"call\";\n }): void => {\n const existingIndex = this.toolIndex.get(nextTool.toolCallId);\n if (typeof existingIndex === \"number\") {\n const existing = this.parts[existingIndex];\n if (existing?.type !== \"tool-invocation\") {\n return;\n }\n this.parts[existingIndex] = {\n ...existing,\n ...nextTool,\n };\n return;\n }\n\n this.toolIndex.set(nextTool.toolCallId, this.parts.length);\n this.parts.push({\n type: \"tool-invocation\",\n ...nextTool,\n });\n };\n\n private readTool = (toolCallId: string): { toolName: string; args: string } => {\n const index = this.toolIndex.get(toolCallId);\n const part = typeof index === \"number\" ? this.parts[index] : null;\n if (part?.type !== \"tool-invocation\") {\n return { toolName: \"unknown\", args: \"\" };\n }\n return { toolName: part.toolName, args: part.args };\n };\n}\n\nclass StdioRuntimeClientBridge {\n private activeSessionId: string | null = null;\n private updateHandler: ((update: AcpClientUpdate) => void) | null = null;\n\n attach = (params: {\n sessionId: string;\n onUpdate: (update: AcpClientUpdate) => void;\n }): (() => void) => {\n this.activeSessionId = params.sessionId;\n this.updateHandler = params.onUpdate;\n return () => {\n if (this.activeSessionId !== params.sessionId) {\n return;\n }\n this.activeSessionId = null;\n this.updateHandler = null;\n };\n };\n\n sessionUpdate = async (params: { sessionId: string; update: AcpClientUpdate }): Promise<void> => {\n if (params.sessionId !== this.activeSessionId) {\n return;\n }\n this.updateHandler?.(params.update);\n };\n\n requestPermission = async (): Promise<{\n outcome: { outcome: \"cancelled\" };\n }> => ({\n outcome: { outcome: \"cancelled\" },\n });\n\n readTextFile = async (): Promise<{ content: string }> => ({ content: \"\" });\n\n writeTextFile = async (): Promise<Record<string, never>> => ({});\n}\n\nclass StdioRuntimeSession {\n private child: ChildProcessWithoutNullStreams | null = null;\n private connection: acp.ClientSideConnection | null = null;\n private promptInFlight = false;\n private remoteSessionId: string | null = null;\n private remoteSessionCwd: string | null = null;\n private readonly clientBridge = new StdioRuntimeClientBridge();\n private stderr = \"\";\n private pendingProviderRoute: NcpProviderRuntimeRoute | undefined;\n\n constructor(private readonly config: StdioRuntimeNcpAgentRuntimeConfig) {}\n\n ensureStarted = async (params: {\n cwd?: string;\n providerRoute?: NcpProviderRuntimeRoute;\n }): Promise<void> => {\n const { cwd, providerRoute } = params;\n this.pendingProviderRoute = providerRoute;\n if (this.connection && this.remoteSessionId) {\n if (this.remoteSessionCwd === cwd) {\n return;\n }\n await this.dispose();\n }\n if (!cwd) {\n throw new Error(\"[narp-stdio] missing execution cwd for stdio runtime session\");\n }\n\n const env = buildStdioRuntimeLaunchEnv({\n configEnv: this.config.env,\n providerRoute: this.pendingProviderRoute,\n });\n\n this.child = spawn(this.config.command, this.config.args, {\n cwd: this.config.cwd,\n env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"], windowsHide: true,\n });\n const spawnErrorPromise = new Promise<never>((_, reject) => {\n this.child?.once(\"error\", (error) => {\n reject(\n new Error(\n buildSpawnFailureMessage({\n command: this.config.command,\n cwd: this.config.cwd,\n error,\n }),\n ),\n );\n });\n });\n this.child.stderr.setEncoding(\"utf8\");\n this.child.stderr.on(\"data\", (chunk: string) => {\n this.stderr = `${this.stderr}${chunk}`.slice(-4000);\n });\n\n const stream = acp.ndJsonStream(\n Writable.toWeb(this.child.stdin),\n Readable.toWeb(this.child.stdout),\n );\n this.connection = new acp.ClientSideConnection(() => this.clientBridge, stream);\n\n const session = await Promise.race([\n (async () => {\n await withTimeout(\n this.connection?.initialize({\n protocolVersion: acp.PROTOCOL_VERSION,\n clientCapabilities: {},\n }) ?? Promise.reject(new Error(\"[narp-stdio] stdio runtime connection not started\")),\n this.config.startupTimeoutMs,\n \"[narp-stdio] timed out initializing stdio runtime\",\n );\n\n return withTimeout(\n this.connection?.newSession({\n cwd,\n mcpServers: [],\n }) ?? Promise.reject(new Error(\"[narp-stdio] stdio runtime connection not started\")),\n this.config.startupTimeoutMs,\n \"[narp-stdio] timed out creating remote stdio session\",\n );\n })(),\n spawnErrorPromise,\n ]);\n this.remoteSessionId = session.sessionId;\n this.remoteSessionCwd = cwd;\n };\n\n runPrompt = async (params: {\n sessionId: string;\n text: string;\n meta: NarpStdioPromptMeta;\n modelId?: string;\n signal?: AbortSignal;\n onUpdate: (update: AcpClientUpdate) => void;\n }): Promise<acp.PromptResponse> => {\n const { meta, modelId, onUpdate, sessionId, signal, text } = params;\n if (!this.connection || !this.remoteSessionId) {\n throw new Error(\"[narp-stdio] stdio runtime connection not started\");\n }\n if (this.promptInFlight) {\n throw new Error(\"[narp-stdio] concurrent prompt is not supported for one stdio session\");\n }\n\n this.promptInFlight = true;\n const detach = this.clientBridge.attach({\n sessionId: this.remoteSessionId,\n onUpdate,\n });\n const releaseAbort = this.bindAbortSignal(signal);\n\n try {\n if (modelId && this.config.env?.[HERMES_ACP_ROUTE_BRIDGE_ENV] !== \"1\") {\n try {\n // Hermes ACP must switch on prompt-scoped providerRoute, not modelId alone.\n await this.connection.unstable_setSessionModel({\n sessionId: this.remoteSessionId,\n modelId,\n });\n } catch {\n // Not all ACP agents implement unstable session model switching.\n }\n }\n\n return await withTimeout(\n this.connection.prompt({\n sessionId: this.remoteSessionId,\n prompt: [{ type: \"text\", text }],\n _meta: {\n [NARP_STDIO_PROMPT_META_KEY]: meta,\n },\n }),\n this.config.requestTimeoutMs,\n `[narp-stdio] prompt timed out for session ${sessionId}`,\n );\n } finally {\n releaseAbort();\n detach();\n this.promptInFlight = false;\n }\n };\n\n cancel = async (): Promise<void> => {\n if (!this.connection || !this.remoteSessionId) {\n return;\n }\n try {\n await this.connection.cancel({\n sessionId: this.remoteSessionId,\n });\n } catch {\n // Best effort.\n }\n };\n\n private bindAbortSignal = (signal?: AbortSignal): (() => void) => {\n if (!signal) {\n return () => undefined;\n }\n\n const onAbort = (): void => {\n void this.cancel();\n };\n\n if (signal.aborted) {\n onAbort();\n return () => undefined;\n }\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n return () => {\n signal.removeEventListener(\"abort\", onAbort);\n };\n };\n\n readStderr = (): string => this.stderr;\n\n readPromptTimeoutMetadataResetKeys = (): readonly string[] | undefined =>\n this.config.resetSessionMetadataOnPromptTimeout;\n\n dispose = async (): Promise<void> => {\n await this.cancel();\n const child = this.child;\n this.connection = null;\n this.remoteSessionId = null;\n this.remoteSessionCwd = null;\n this.child = null;\n if (!child || child.killed || child.exitCode !== null || child.signalCode !== null) {\n return;\n }\n\n const exited = new Promise<void>((resolve) => {\n child.once(\"exit\", () => resolve());\n child.once(\"error\", () => resolve());\n });\n const forceKill = setTimeout(() => {\n child.kill(\"SIGKILL\");\n }, 3_000);\n forceKill.unref();\n child.kill(\"SIGTERM\");\n await exited;\n clearTimeout(forceKill);\n };\n}\n\nclass StdioRuntimeRunController {\n private readonly buffer = new UpdateBuffer();\n private readonly collector = new PromptUpdateCollector();\n private readonly toolStates = new Map<string, AcpToolState>();\n private textStarted = false;\n private reasoningStarted = false;\n private readonly resolvedTools: ReadonlyArray<OpenAITool>;\n private readonly resolvedProviderRoute: NcpProviderRuntimeRoute | undefined;\n private readonly runId: string;\n\n constructor(\n private readonly session: StdioRuntimeSession,\n private readonly input: NcpAgentRunInput,\n private readonly stateManager?: NcpAgentConversationStateManager,\n private readonly resolveTools?: (input: NcpAgentRunInput) => ReadonlyArray<OpenAITool> | undefined,\n private readonly resolveProviderRoute?: (input: NcpAgentRunInput) => NcpProviderRuntimeRoute | undefined,\n ) {\n this.resolvedTools = resolveTools?.(input) ?? [];\n this.resolvedProviderRoute = resolveProviderRoute?.(input);\n this.runId = (input as NcpAgentRunInput & { runId?: string }).runId ?? `narp-stdio:${input.sessionId}:${randomUUID()}`;\n }\n execute = async function* (\n this: StdioRuntimeRunController,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n const requestMessage = this.input.messages.at(-1);\n if (!requestMessage) {\n throw new Error(\"[narp-stdio] runtime.run requires at least one input message\");\n }\n\n const assistantMessageId = createAssistantMessageId(requestMessage.id);\n const promptPromise = this.session.runPrompt({\n sessionId: this.input.sessionId,\n text: extractPromptText(requestMessage),\n meta: {\n ...(this.input.correlationId ? { correlationId: this.input.correlationId } : {}),\n ...(this.resolvedProviderRoute ? { providerRoute: this.resolvedProviderRoute } : {}),\n ...(this.input.metadata ? { sessionMetadata: this.input.metadata } : {}),\n ...(this.resolvedTools.length > 0 ? { tools: this.resolvedTools } : {}),\n },\n modelId: resolveModelId({\n providerRoute: this.resolvedProviderRoute,\n metadata: this.input.metadata,\n }),\n signal: options?.signal,\n onUpdate: (update) => this.buffer.push(update),\n });\n const promptState = this.trackPromptState(promptPromise);\n\n yield* this.emitRunStartedEvents(assistantMessageId);\n\n try {\n yield* this.drainPromptUpdates(assistantMessageId, promptState);\n if (this.shouldExitForAbort(options, promptState.error)) {\n return;\n }\n if (promptState.error) throw promptState.error;\n yield* this.emitCompletionEvents(assistantMessageId);\n } catch (error) {\n if (this.shouldExitForAbort(options, error)) {\n return;\n }\n yield* this.emitFailureEvents(assistantMessageId, error);\n }\n };\n private trackPromptState = (\n promptPromise: Promise<acp.PromptResponse>,\n ): PromptExecutionState => {\n const promptState: PromptExecutionState = {\n settled: false,\n error: null,\n };\n\n promptPromise\n .then(() => {\n promptState.settled = true;\n this.buffer.notify();\n })\n .catch((error) => {\n promptState.settled = true;\n promptState.error = error;\n this.buffer.notify();\n });\n\n return promptState;\n };\n private emitRunStartedEvents = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n ): AsyncGenerator<NcpEndpointEvent> {\n yield* this.emitEvent({\n type: NcpEventType.MessageAccepted,\n payload: {\n messageId: assistantMessageId,\n ...(this.input.correlationId ? { correlationId: this.input.correlationId } : {}),\n },\n });\n yield* this.emitEvent({\n type: NcpEventType.RunStarted,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n runId: this.runId,\n },\n });\n };\n private drainPromptUpdates = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n promptState: PromptExecutionState,\n ): AsyncGenerator<NcpEndpointEvent> {\n while (!promptState.settled || this.buffer.hasItems()) {\n const update = this.buffer.shift();\n if (!update) {\n await this.buffer.waitForChange();\n continue;\n }\n for (const event of this.translateUpdate(update, assistantMessageId)) {\n yield* this.emitEvent(event);\n }\n }\n };\n private shouldExitForAbort = (\n options: NcpAgentRunOptions | undefined,\n error: unknown,\n ): boolean => options?.signal?.aborted === true || isAbortLikeRuntimeError(error);\n private emitCompletionEvents = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n ): AsyncGenerator<NcpEndpointEvent> {\n for (const terminalEvent of this.createTerminalEvents(assistantMessageId)) {\n yield* this.emitEvent(terminalEvent);\n }\n\n if (!this.collector.hasParts()) {\n throw new Error(\n `[narp-stdio] ACP prompt completed without any assistant content for session ${this.input.sessionId}. stderr=${this.session.readStderr()}`,\n );\n }\n\n yield* this.emitEvent({\n type: NcpEventType.MessageCompleted,\n payload: {\n sessionId: this.input.sessionId,\n correlationId: this.input.correlationId,\n message: {\n id: assistantMessageId,\n sessionId: this.input.sessionId,\n role: \"assistant\",\n status: \"final\",\n parts: this.collector.buildParts() as never,\n timestamp: new Date().toISOString(),\n },\n },\n });\n yield* this.emitEvent({\n type: NcpEventType.RunFinished,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n runId: this.runId,\n },\n });\n };\n private emitFailureEvents = async function* (\n this: StdioRuntimeRunController,\n assistantMessageId: string,\n error: unknown,\n ): AsyncGenerator<NcpEndpointEvent> {\n const ncpError = normalizeRuntimeError(error, { stderr: this.session.readStderr() });\n for (const recoveryEvent of createPromptTimeoutRecoveryEvents({\n correlationId: this.input.correlationId,\n error,\n messageId: assistantMessageId,\n resetKeys: this.session.readPromptTimeoutMetadataResetKeys(),\n runId: this.runId,\n sessionId: this.input.sessionId,\n })) {\n yield* this.emitEvent(recoveryEvent);\n }\n yield* this.emitEvent({\n type: NcpEventType.MessageFailed,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n correlationId: this.input.correlationId,\n error: ncpError,\n },\n });\n yield* this.emitEvent({\n type: NcpEventType.RunError,\n payload: {\n sessionId: this.input.sessionId,\n messageId: assistantMessageId,\n runId: this.runId,\n error: ncpError.message,\n },\n });\n };\n private emitEvent = async function* (\n this: StdioRuntimeRunController,\n event: NcpEndpointEvent,\n ): AsyncGenerator<NcpEndpointEvent> {\n this.collector.apply(event);\n await this.stateManager?.dispatch(event);\n yield event;\n };\n private translateUpdate = (\n update: AcpClientUpdate,\n messageId: string,\n ): NcpEndpointEvent[] => {\n switch (update.sessionUpdate) {\n case \"agent_message_chunk\":\n return this.emitTextDelta(update.content, messageId);\n case \"agent_thought_chunk\":\n return this.emitReasoningDelta(update.content, messageId);\n case \"tool_call\":\n return this.emitToolCallStart(update, messageId);\n case \"tool_call_update\":\n return this.emitToolCallUpdate(update);\n case \"session_info_update\":\n return this.emitSessionInfoUpdate(update, messageId);\n default:\n return [];\n }\n };\n\n private emitSessionInfoUpdate = (\n update: Extract<AcpClientUpdate, { sessionUpdate: \"session_info_update\" }>,\n messageId: string,\n ): NcpEndpointEvent[] => {\n const patch = readSessionMetadataPatch(update._meta);\n if (!patch) {\n return [];\n }\n return [\n {\n type: NcpEventType.RunMetadata,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n runId: this.runId,\n ...(this.input.correlationId ? { correlationId: this.input.correlationId } : {}),\n metadata: {\n kind: SESSION_METADATA_PATCH_KIND,\n sessionMetadataPatch: patch,\n },\n },\n },\n ];\n };\n\n private emitTextDelta = (\n content: { type: string; text?: string },\n messageId: string,\n ): NcpEndpointEvent[] => this.emitContentDelta({\n content,\n messageId,\n started: this.textStarted,\n markStarted: () => {\n this.textStarted = true;\n },\n startType: NcpEventType.MessageTextStart,\n deltaType: NcpEventType.MessageTextDelta,\n });\n\n private emitReasoningDelta = (\n content: { type: string; text?: string },\n messageId: string,\n ): NcpEndpointEvent[] => this.emitContentDelta({\n content,\n messageId,\n started: this.reasoningStarted,\n markStarted: () => {\n this.reasoningStarted = true;\n },\n startType: NcpEventType.MessageReasoningStart,\n deltaType: NcpEventType.MessageReasoningDelta,\n });\n\n private emitContentDelta = (params: {\n content: { type: string; text?: string };\n messageId: string;\n started: boolean;\n markStarted: () => void;\n startType: NcpEventType.MessageTextStart | NcpEventType.MessageReasoningStart;\n deltaType: NcpEventType.MessageTextDelta | NcpEventType.MessageReasoningDelta;\n }): NcpEndpointEvent[] => {\n const { content, deltaType, markStarted, messageId, started, startType } = params;\n if (content.type !== \"text\" || !content.text) {\n return [];\n }\n const events: NcpEndpointEvent[] = [];\n if (!started) {\n markStarted();\n events.push({\n type: startType,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n },\n });\n }\n events.push({\n type: deltaType,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n delta: content.text,\n },\n });\n return events;\n };\n\n private emitToolCallStart = (\n update: Extract<AcpClientUpdate, { sessionUpdate: \"tool_call\" }>,\n messageId: string,\n ): NcpEndpointEvent[] => {\n const toolName = resolveToolName(update);\n const args = serializeToolArgs(update.rawInput);\n this.toolStates.set(update.toolCallId, {\n toolName,\n args,\n completed: false,\n });\n return [\n {\n type: NcpEventType.MessageToolCallStart,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n toolCallId: update.toolCallId,\n toolName,\n },\n },\n {\n type: NcpEventType.MessageToolCallArgs,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n args,\n },\n },\n ];\n };\n\n private emitToolCallUpdate = (\n update: Extract<AcpClientUpdate, { sessionUpdate: \"tool_call_update\" }>,\n ): NcpEndpointEvent[] => {\n const existing = this.toolStates.get(update.toolCallId);\n if (!existing) {\n return [];\n }\n\n const nextArgs = serializeToolArgs(update.rawInput);\n const argsChanged = typeof update.rawInput !== \"undefined\" && nextArgs !== existing.args;\n const events: NcpEndpointEvent[] = [];\n if (argsChanged) {\n existing.args = nextArgs;\n events.push({\n type: NcpEventType.MessageToolCallArgs,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n args: nextArgs,\n },\n });\n }\n\n if (update.status === \"completed\" || update.status === \"failed\") {\n if (!existing.completed) {\n existing.completed = true;\n events.push({\n type: NcpEventType.MessageToolCallEnd,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n },\n });\n }\n if (typeof update.rawOutput !== \"undefined\") {\n events.push({\n type: NcpEventType.MessageToolCallResult,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId: update.toolCallId,\n content: update.rawOutput,\n },\n });\n }\n }\n return events;\n };\n\n private createTerminalEvents = (messageId: string): NcpEndpointEvent[] => {\n const events: NcpEndpointEvent[] = [];\n if (this.textStarted) {\n events.push({\n type: NcpEventType.MessageTextEnd,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n },\n });\n this.textStarted = false;\n }\n if (this.reasoningStarted) {\n events.push({\n type: NcpEventType.MessageReasoningEnd,\n payload: {\n sessionId: this.input.sessionId,\n messageId,\n },\n });\n this.reasoningStarted = false;\n }\n for (const [toolCallId, state] of this.toolStates.entries()) {\n if (state.completed) {\n continue;\n }\n events.push({\n type: NcpEventType.MessageToolCallEnd,\n payload: {\n sessionId: this.input.sessionId,\n toolCallId,\n },\n });\n state.completed = true;\n }\n return events;\n };\n}\n\nexport class StdioRuntimeNcpAgentRuntime implements NcpAgentRuntime {\n private readonly session: StdioRuntimeSession;\n\n constructor(private readonly config: StdioRuntimeNcpAgentRuntimeConfig) {\n this.session = new StdioRuntimeSession(config);\n }\n\n run = async function* (\n this: StdioRuntimeNcpAgentRuntime,\n input: NcpAgentRunInput,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n await this.session.ensureStarted({\n cwd: input.executionContext?.cwd,\n providerRoute: this.config.resolveProviderRoute?.(input),\n });\n const controller = new StdioRuntimeRunController(\n this.session,\n input,\n this.config.stateManager,\n this.config.resolveTools,\n this.config.resolveProviderRoute,\n );\n yield* controller.execute(options);\n };\n\n dispose = async (): Promise<void> => {\n await this.session.dispose();\n };\n}\n\nfunction readSessionMetadataPatch(meta: unknown): Record<string, unknown> | null {\n const narpMeta = isRecord(meta)\n ? meta[NARP_STDIO_PROMPT_META_KEY]\n : undefined;\n const patch = isRecord(narpMeta)\n ? narpMeta.sessionMetadataPatch\n : undefined;\n return isRecord(patch) && Object.keys(patch).length > 0\n ? structuredClone(patch)\n : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction resolveToolName(\n update: Extract<AcpClientUpdate, { sessionUpdate: \"tool_call\" }>,\n): string {\n return resolveToolNameFromAcpUpdate(update);\n}\n\nfunction createAssistantMessageId(requestMessageId: string): string {\n const normalizedRequestId = requestMessageId.trim() || \"request\";\n return `assistant:${normalizedRequestId}:${randomUUID()}`;\n}\n\nfunction serializeToolArgs(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"undefined\") {\n return \"{}\";\n }\n return JSON.stringify(value);\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n try {\n return await Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n reject(new Error(message));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AA+BA,MAAM,8BAA8B;AAcpC,IAAM,eAAN,MAAmB;CACjB,UAA8C,EAAE;CAChD,0BAAkB,IAAI,KAAiB;CAEvC,QAAQ,WAAkC;AACxC,OAAK,QAAQ,KAAK,OAAO;AACzB,OAAK,OAAO;;CAGd,cAA2C,KAAK,QAAQ,OAAO;CAE/D,iBAA0B,KAAK,QAAQ,SAAS;CAEhD,gBAAgB,YAA2B;AACzC,MAAI,KAAK,QAAQ,SAAS,EACxB;AAEF,QAAM,IAAI,SAAe,YAAY;AACnC,QAAK,QAAQ,IAAI,QAAQ;IACzB;;CAGJ,eAAqB;AACnB,OAAK,OAAO;;CAGd,cAA4B;AAC1B,MAAI,KAAK,QAAQ,SAAS,EACxB;EAEF,MAAM,UAAU,CAAC,GAAG,KAAK,QAAQ;AACjC,OAAK,QAAQ,OAAO;AACpB,OAAK,MAAM,UAAU,QACnB,SAAQ;;;AAKd,IAAM,wBAAN,MAA4B;CAC1B,QAII,EAAE;CACN,4BAA6B,IAAI,KAAqB;CAEtD,SAAS,UAAkC;AACzC,UAAQ,MAAM,MAAd;GACE,KAAK,aAAa;AAChB,SAAK,WAAW,QAAQ,MAAM,QAAQ,MAAM;AAC5C;GACF,KAAK,aAAa;AAChB,SAAK,WAAW,aAAa,MAAM,QAAQ,MAAM;AACjD;GACF,KAAK,aAAa;AAChB,SAAK,WAAW;KACd,YAAY,MAAM,QAAQ;KAC1B,UAAU,MAAM,QAAQ;KACxB,MAAM;KACN,OAAO;KACR,CAAC;AACF;GACF,KAAK,aAAa;IAChB;KACE,MAAM,OAAO,KAAK,SAAS,MAAM,QAAQ,WAAW;AACpD,UAAK,WAAW;MACd,YAAY,MAAM,QAAQ;MAC1B,UAAU,KAAK;MACf,MAAM,MAAM,QAAQ;MACpB,OAAO;MACR,CAAC;;AAEJ;GACF,KAAK,aAAa;IAChB;KACE,MAAM,OAAO,KAAK,SAAS,MAAM,QAAQ,WAAW;AACpD,UAAK,WAAW;MACd,YAAY,MAAM,QAAQ;MAC1B,UAAU,KAAK;MACf,MAAM,GAAG,KAAK,OAAO,MAAM,QAAQ;MACnC,OAAO;MACR,CAAC;;AAEJ;GACF,KAAK,aAAa;IAChB;KACE,MAAM,OAAO,KAAK,SAAS,MAAM,QAAQ,WAAW;AACpD,UAAK,WAAW;MACd,YAAY,MAAM,QAAQ;MAC1B,UAAU,KAAK;MACf,MAAM,KAAK;MACX,OAAO;MACR,CAAC;;AAEJ;GACF,QACE;;;CAIN,iBAA0B,KAAK,MAAM,SAAS;CAE9C,mBAAmD,gBAAgB,KAAK,MAAM;CAE9E,cAAsB,MAA4B,SAAuB;AACvE,MAAI,CAAC,KACH;EAEF,MAAM,OAAO,KAAK,MAAM,GAAG,GAAG;AAC9B,MAAI,MAAM,SAAS,MAAM;AACvB,QAAK,OAAO,GAAG,KAAK,OAAO;AAC3B;;AAEF,OAAK,MAAM,KAAK;GAAE;GAAM;GAAM,CAAC;;CAGjC,cAAsB,aAKV;EACV,MAAM,gBAAgB,KAAK,UAAU,IAAI,SAAS,WAAW;AAC7D,MAAI,OAAO,kBAAkB,UAAU;GACrC,MAAM,WAAW,KAAK,MAAM;AAC5B,OAAI,UAAU,SAAS,kBACrB;AAEF,QAAK,MAAM,iBAAiB;IAC1B,GAAG;IACH,GAAG;IACJ;AACD;;AAGF,OAAK,UAAU,IAAI,SAAS,YAAY,KAAK,MAAM,OAAO;AAC1D,OAAK,MAAM,KAAK;GACd,MAAM;GACN,GAAG;GACJ,CAAC;;CAGJ,YAAoB,eAA2D;EAC7E,MAAM,QAAQ,KAAK,UAAU,IAAI,WAAW;EAC5C,MAAM,OAAO,OAAO,UAAU,WAAW,KAAK,MAAM,SAAS;AAC7D,MAAI,MAAM,SAAS,kBACjB,QAAO;GAAE,UAAU;GAAW,MAAM;GAAI;AAE1C,SAAO;GAAE,UAAU,KAAK;GAAU,MAAM,KAAK;GAAM;;;AAIvD,IAAM,2BAAN,MAA+B;CAC7B,kBAAyC;CACzC,gBAAoE;CAEpE,UAAU,WAGU;AAClB,OAAK,kBAAkB,OAAO;AAC9B,OAAK,gBAAgB,OAAO;AAC5B,eAAa;AACX,OAAI,KAAK,oBAAoB,OAAO,UAClC;AAEF,QAAK,kBAAkB;AACvB,QAAK,gBAAgB;;;CAIzB,gBAAgB,OAAO,WAA0E;AAC/F,MAAI,OAAO,cAAc,KAAK,gBAC5B;AAEF,OAAK,gBAAgB,OAAO,OAAO;;CAGrC,oBAAoB,aAEb,EACL,SAAS,EAAE,SAAS,aAAa,EAClC;CAED,eAAe,aAA2C,EAAE,SAAS,IAAI;CAEzE,gBAAgB,aAA6C,EAAE;;AAGjE,IAAM,sBAAN,MAA0B;CACxB,QAAuD;CACvD,aAAsD;CACtD,iBAAyB;CACzB,kBAAyC;CACzC,mBAA0C;CAC1C,eAAgC,IAAI,0BAA0B;CAC9D,SAAiB;CACjB;CAEA,YAAY,QAA4D;AAA3C,OAAA,SAAA;;CAE7B,gBAAgB,OAAO,WAGF;EACnB,MAAM,EAAE,KAAK,kBAAkB;AAC/B,OAAK,uBAAuB;AAC5B,MAAI,KAAK,cAAc,KAAK,iBAAiB;AAC3C,OAAI,KAAK,qBAAqB,IAC5B;AAEF,SAAM,KAAK,SAAS;;AAEtB,MAAI,CAAC,IACH,OAAM,IAAI,MAAM,+DAA+D;EAGjF,MAAM,MAAM,2BAA2B;GACrC,WAAW,KAAK,OAAO;GACvB,eAAe,KAAK;GACrB,CAAC;AAEF,OAAK,QAAQ,MAAM,KAAK,OAAO,SAAS,KAAK,OAAO,MAAM;GACxD,KAAK,KAAK,OAAO;GACjB;GACA,OAAO;IAAC;IAAQ;IAAQ;IAAO;GAAE,aAAa;GAC/C,CAAC;EACF,MAAM,oBAAoB,IAAI,SAAgB,GAAG,WAAW;AAC1D,QAAK,OAAO,KAAK,UAAU,UAAU;AACnC,WACE,IAAI,MACF,yBAAyB;KACvB,SAAS,KAAK,OAAO;KACrB,KAAK,KAAK,OAAO;KACjB;KACD,CAAC,CACH,CACF;KACD;IACF;AACF,OAAK,MAAM,OAAO,YAAY,OAAO;AACrC,OAAK,MAAM,OAAO,GAAG,SAAS,UAAkB;AAC9C,QAAK,SAAS,GAAG,KAAK,SAAS,QAAQ,MAAM,KAAM;IACnD;EAEF,MAAM,SAAS,IAAI,aACjB,SAAS,MAAM,KAAK,MAAM,MAAM,EAChC,SAAS,MAAM,KAAK,MAAM,OAAO,CAClC;AACD,OAAK,aAAa,IAAI,IAAI,2BAA2B,KAAK,cAAc,OAAO;AAwB/E,OAAK,mBAtBW,MAAM,QAAQ,KAAK,EAChC,YAAY;AACX,SAAM,YACJ,KAAK,YAAY,WAAW;IAC1B,iBAAiB,IAAI;IACrB,oBAAoB,EAAE;IACvB,CAAC,IAAI,QAAQ,uBAAO,IAAI,MAAM,oDAAoD,CAAC,EACpF,KAAK,OAAO,kBACZ,oDACD;AAED,UAAO,YACL,KAAK,YAAY,WAAW;IAC1B;IACA,YAAY,EAAE;IACf,CAAC,IAAI,QAAQ,uBAAO,IAAI,MAAM,oDAAoD,CAAC,EACpF,KAAK,OAAO,kBACZ,uDACD;MACC,EACJ,kBACD,CAAC,EAC6B;AAC/B,OAAK,mBAAmB;;CAG1B,YAAY,OAAO,WAOgB;EACjC,MAAM,EAAE,MAAM,SAAS,UAAU,WAAW,QAAQ,SAAS;AAC7D,MAAI,CAAC,KAAK,cAAc,CAAC,KAAK,gBAC5B,OAAM,IAAI,MAAM,oDAAoD;AAEtE,MAAI,KAAK,eACP,OAAM,IAAI,MAAM,wEAAwE;AAG1F,OAAK,iBAAiB;EACtB,MAAM,SAAS,KAAK,aAAa,OAAO;GACtC,WAAW,KAAK;GAChB;GACD,CAAC;EACF,MAAM,eAAe,KAAK,gBAAgB,OAAO;AAEjD,MAAI;AACF,OAAI,WAAW,KAAK,OAAO,MAAM,iCAAiC,IAChE,KAAI;AAEF,UAAM,KAAK,WAAW,yBAAyB;KAC7C,WAAW,KAAK;KAChB;KACD,CAAC;WACI;AAKV,UAAO,MAAM,YACX,KAAK,WAAW,OAAO;IACrB,WAAW,KAAK;IAChB,QAAQ,CAAC;KAAE,MAAM;KAAQ;KAAM,CAAC;IAChC,OAAO,GACJ,6BAA6B,MAC/B;IACF,CAAC,EACF,KAAK,OAAO,kBACZ,6CAA6C,YAC9C;YACO;AACR,iBAAc;AACd,WAAQ;AACR,QAAK,iBAAiB;;;CAI1B,SAAS,YAA2B;AAClC,MAAI,CAAC,KAAK,cAAc,CAAC,KAAK,gBAC5B;AAEF,MAAI;AACF,SAAM,KAAK,WAAW,OAAO,EAC3B,WAAW,KAAK,iBACjB,CAAC;UACI;;CAKV,mBAA2B,WAAuC;AAChE,MAAI,CAAC,OACH,cAAa,KAAA;EAGf,MAAM,gBAAsB;AACrB,QAAK,QAAQ;;AAGpB,MAAI,OAAO,SAAS;AAClB,YAAS;AACT,gBAAa,KAAA;;AAGf,SAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;AACzD,eAAa;AACX,UAAO,oBAAoB,SAAS,QAAQ;;;CAIhD,mBAA2B,KAAK;CAEhC,2CACE,KAAK,OAAO;CAEd,UAAU,YAA2B;AACnC,QAAM,KAAK,QAAQ;EACnB,MAAM,QAAQ,KAAK;AACnB,OAAK,aAAa;AAClB,OAAK,kBAAkB;AACvB,OAAK,mBAAmB;AACxB,OAAK,QAAQ;AACb,MAAI,CAAC,SAAS,MAAM,UAAU,MAAM,aAAa,QAAQ,MAAM,eAAe,KAC5E;EAGF,MAAM,SAAS,IAAI,SAAe,YAAY;AAC5C,SAAM,KAAK,cAAc,SAAS,CAAC;AACnC,SAAM,KAAK,eAAe,SAAS,CAAC;IACpC;EACF,MAAM,YAAY,iBAAiB;AACjC,SAAM,KAAK,UAAU;KACpB,IAAM;AACT,YAAU,OAAO;AACjB,QAAM,KAAK,UAAU;AACrB,QAAM;AACN,eAAa,UAAU;;;AAI3B,IAAM,4BAAN,MAAgC;CAC9B,SAA0B,IAAI,cAAc;CAC5C,YAA6B,IAAI,uBAAuB;CACxD,6BAA8B,IAAI,KAA2B;CAC7D,cAAsB;CACtB,mBAA2B;CAC3B;CACA;CACA;CAEA,YACE,SACA,OACA,cACA,cACA,sBACA;AALiB,OAAA,UAAA;AACA,OAAA,QAAA;AACA,OAAA,eAAA;AACA,OAAA,eAAA;AACA,OAAA,uBAAA;AAEjB,OAAK,gBAAgB,eAAe,MAAM,IAAI,EAAE;AAChD,OAAK,wBAAwB,uBAAuB,MAAM;AAC1D,OAAK,QAAS,MAAgD,SAAS,cAAc,MAAM,UAAU,GAAG,YAAY;;CAEtH,UAAU,iBAER,SACkC;EAClC,MAAM,iBAAiB,KAAK,MAAM,SAAS,GAAG,GAAG;AACjD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,+DAA+D;EAGjF,MAAM,qBAAqB,yBAAyB,eAAe,GAAG;EACtE,MAAM,gBAAgB,KAAK,QAAQ,UAAU;GAC3C,WAAW,KAAK,MAAM;GACtB,MAAM,kBAAkB,eAAe;GACvC,MAAM;IACJ,GAAI,KAAK,MAAM,gBAAgB,EAAE,eAAe,KAAK,MAAM,eAAe,GAAG,EAAE;IAC/E,GAAI,KAAK,wBAAwB,EAAE,eAAe,KAAK,uBAAuB,GAAG,EAAE;IACnF,GAAI,KAAK,MAAM,WAAW,EAAE,iBAAiB,KAAK,MAAM,UAAU,GAAG,EAAE;IACvE,GAAI,KAAK,cAAc,SAAS,IAAI,EAAE,OAAO,KAAK,eAAe,GAAG,EAAE;IACvE;GACD,SAAS,eAAe;IACtB,eAAe,KAAK;IACpB,UAAU,KAAK,MAAM;IACtB,CAAC;GACF,QAAQ,SAAS;GACjB,WAAW,WAAW,KAAK,OAAO,KAAK,OAAO;GAC/C,CAAC;EACF,MAAM,cAAc,KAAK,iBAAiB,cAAc;AAExD,SAAO,KAAK,qBAAqB,mBAAmB;AAEpD,MAAI;AACF,UAAO,KAAK,mBAAmB,oBAAoB,YAAY;AAC/D,OAAI,KAAK,mBAAmB,SAAS,YAAY,MAAM,CACrD;AAEF,OAAI,YAAY,MAAO,OAAM,YAAY;AACzC,UAAO,KAAK,qBAAqB,mBAAmB;WAC7C,OAAO;AACd,OAAI,KAAK,mBAAmB,SAAS,MAAM,CACzC;AAEF,UAAO,KAAK,kBAAkB,oBAAoB,MAAM;;;CAG5D,oBACE,kBACyB;EACzB,MAAM,cAAoC;GACxC,SAAS;GACT,OAAO;GACR;AAED,gBACG,WAAW;AACV,eAAY,UAAU;AACtB,QAAK,OAAO,QAAQ;IACpB,CACD,OAAO,UAAU;AAChB,eAAY,UAAU;AACtB,eAAY,QAAQ;AACpB,QAAK,OAAO,QAAQ;IACpB;AAEJ,SAAO;;CAET,uBAA+B,iBAE7B,oBACkC;AAClC,SAAO,KAAK,UAAU;GACpB,MAAM,aAAa;GACnB,SAAS;IACP,WAAW;IACX,GAAI,KAAK,MAAM,gBAAgB,EAAE,eAAe,KAAK,MAAM,eAAe,GAAG,EAAE;IAChF;GACF,CAAC;AACF,SAAO,KAAK,UAAU;GACpB,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB,WAAW;IACX,OAAO,KAAK;IACb;GACF,CAAC;;CAEJ,qBAA6B,iBAE3B,oBACA,aACkC;AAClC,SAAO,CAAC,YAAY,WAAW,KAAK,OAAO,UAAU,EAAE;GACrD,MAAM,SAAS,KAAK,OAAO,OAAO;AAClC,OAAI,CAAC,QAAQ;AACX,UAAM,KAAK,OAAO,eAAe;AACjC;;AAEF,QAAK,MAAM,SAAS,KAAK,gBAAgB,QAAQ,mBAAmB,CAClE,QAAO,KAAK,UAAU,MAAM;;;CAIlC,sBACE,SACA,UACY,SAAS,QAAQ,YAAY,QAAQ,wBAAwB,MAAM;CACjF,uBAA+B,iBAE7B,oBACkC;AAClC,OAAK,MAAM,iBAAiB,KAAK,qBAAqB,mBAAmB,CACvE,QAAO,KAAK,UAAU,cAAc;AAGtC,MAAI,CAAC,KAAK,UAAU,UAAU,CAC5B,OAAM,IAAI,MACR,+EAA+E,KAAK,MAAM,UAAU,WAAW,KAAK,QAAQ,YAAY,GACzI;AAGH,SAAO,KAAK,UAAU;GACpB,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB,eAAe,KAAK,MAAM;IAC1B,SAAS;KACP,IAAI;KACJ,WAAW,KAAK,MAAM;KACtB,MAAM;KACN,QAAQ;KACR,OAAO,KAAK,UAAU,YAAY;KAClC,4BAAW,IAAI,MAAM,EAAC,aAAa;KACpC;IACF;GACF,CAAC;AACF,SAAO,KAAK,UAAU;GACpB,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB,WAAW;IACX,OAAO,KAAK;IACb;GACF,CAAC;;CAEJ,oBAA4B,iBAE1B,oBACA,OACkC;EAClC,MAAM,WAAW,sBAAsB,OAAO,EAAE,QAAQ,KAAK,QAAQ,YAAY,EAAE,CAAC;AACpF,OAAK,MAAM,iBAAiB,kCAAkC;GAC5D,eAAe,KAAK,MAAM;GAC1B;GACA,WAAW;GACX,WAAW,KAAK,QAAQ,oCAAoC;GAC5D,OAAO,KAAK;GACZ,WAAW,KAAK,MAAM;GACvB,CAAC,CACA,QAAO,KAAK,UAAU,cAAc;AAEtC,SAAO,KAAK,UAAU;GACpB,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB,WAAW;IACX,eAAe,KAAK,MAAM;IAC1B,OAAO;IACR;GACF,CAAC;AACF,SAAO,KAAK,UAAU;GACpB,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB,WAAW;IACX,OAAO,KAAK;IACZ,OAAO,SAAS;IACjB;GACF,CAAC;;CAEJ,YAAoB,iBAElB,OACkC;AAClC,OAAK,UAAU,MAAM,MAAM;AAC3B,QAAM,KAAK,cAAc,SAAS,MAAM;AACxC,QAAM;;CAER,mBACE,QACA,cACuB;AACvB,UAAQ,OAAO,eAAf;GACE,KAAK,sBACH,QAAO,KAAK,cAAc,OAAO,SAAS,UAAU;GACtD,KAAK,sBACH,QAAO,KAAK,mBAAmB,OAAO,SAAS,UAAU;GAC3D,KAAK,YACH,QAAO,KAAK,kBAAkB,QAAQ,UAAU;GAClD,KAAK,mBACH,QAAO,KAAK,mBAAmB,OAAO;GACxC,KAAK,sBACH,QAAO,KAAK,sBAAsB,QAAQ,UAAU;GACtD,QACE,QAAO,EAAE;;;CAIf,yBACE,QACA,cACuB;EACvB,MAAM,QAAQ,yBAAyB,OAAO,MAAM;AACpD,MAAI,CAAC,MACH,QAAO,EAAE;AAEX,SAAO,CACL;GACE,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB;IACA,OAAO,KAAK;IACZ,GAAI,KAAK,MAAM,gBAAgB,EAAE,eAAe,KAAK,MAAM,eAAe,GAAG,EAAE;IAC/E,UAAU;KACR,MAAM;KACN,sBAAsB;KACvB;IACF;GACF,CACF;;CAGH,iBACE,SACA,cACuB,KAAK,iBAAiB;EAC7C;EACA;EACA,SAAS,KAAK;EACd,mBAAmB;AACjB,QAAK,cAAc;;EAErB,WAAW,aAAa;EACxB,WAAW,aAAa;EACzB,CAAC;CAEF,sBACE,SACA,cACuB,KAAK,iBAAiB;EAC7C;EACA;EACA,SAAS,KAAK;EACd,mBAAmB;AACjB,QAAK,mBAAmB;;EAE1B,WAAW,aAAa;EACxB,WAAW,aAAa;EACzB,CAAC;CAEF,oBAA4B,WAOF;EACxB,MAAM,EAAE,SAAS,WAAW,aAAa,WAAW,SAAS,cAAc;AAC3E,MAAI,QAAQ,SAAS,UAAU,CAAC,QAAQ,KACtC,QAAO,EAAE;EAEX,MAAM,SAA6B,EAAE;AACrC,MAAI,CAAC,SAAS;AACZ,gBAAa;AACb,UAAO,KAAK;IACV,MAAM;IACN,SAAS;KACP,WAAW,KAAK,MAAM;KACtB;KACD;IACF,CAAC;;AAEJ,SAAO,KAAK;GACV,MAAM;GACN,SAAS;IACP,WAAW,KAAK,MAAM;IACtB;IACA,OAAO,QAAQ;IAChB;GACF,CAAC;AACF,SAAO;;CAGT,qBACE,QACA,cACuB;EACvB,MAAM,WAAW,gBAAgB,OAAO;EACxC,MAAM,OAAO,kBAAkB,OAAO,SAAS;AAC/C,OAAK,WAAW,IAAI,OAAO,YAAY;GACrC;GACA;GACA,WAAW;GACZ,CAAC;AACF,SAAO,CACL;GACE,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB;IACA,YAAY,OAAO;IACnB;IACD;GACF,EACD;GACE,MAAM,aAAa;GACnB,SAAS;IACP,WAAW,KAAK,MAAM;IACtB,YAAY,OAAO;IACnB;IACD;GACF,CACF;;CAGH,sBACE,WACuB;EACvB,MAAM,WAAW,KAAK,WAAW,IAAI,OAAO,WAAW;AACvD,MAAI,CAAC,SACH,QAAO,EAAE;EAGX,MAAM,WAAW,kBAAkB,OAAO,SAAS;EACnD,MAAM,cAAc,OAAO,OAAO,aAAa,eAAe,aAAa,SAAS;EACpF,MAAM,SAA6B,EAAE;AACrC,MAAI,aAAa;AACf,YAAS,OAAO;AAChB,UAAO,KAAK;IACV,MAAM,aAAa;IACnB,SAAS;KACP,WAAW,KAAK,MAAM;KACtB,YAAY,OAAO;KACnB,MAAM;KACP;IACF,CAAC;;AAGJ,MAAI,OAAO,WAAW,eAAe,OAAO,WAAW,UAAU;AAC/D,OAAI,CAAC,SAAS,WAAW;AACvB,aAAS,YAAY;AACrB,WAAO,KAAK;KACV,MAAM,aAAa;KACnB,SAAS;MACP,WAAW,KAAK,MAAM;MACtB,YAAY,OAAO;MACpB;KACF,CAAC;;AAEJ,OAAI,OAAO,OAAO,cAAc,YAC9B,QAAO,KAAK;IACV,MAAM,aAAa;IACnB,SAAS;KACP,WAAW,KAAK,MAAM;KACtB,YAAY,OAAO;KACnB,SAAS,OAAO;KACjB;IACF,CAAC;;AAGN,SAAO;;CAGT,wBAAgC,cAA0C;EACxE,MAAM,SAA6B,EAAE;AACrC,MAAI,KAAK,aAAa;AACpB,UAAO,KAAK;IACV,MAAM,aAAa;IACnB,SAAS;KACP,WAAW,KAAK,MAAM;KACtB;KACD;IACF,CAAC;AACF,QAAK,cAAc;;AAErB,MAAI,KAAK,kBAAkB;AACzB,UAAO,KAAK;IACV,MAAM,aAAa;IACnB,SAAS;KACP,WAAW,KAAK,MAAM;KACtB;KACD;IACF,CAAC;AACF,QAAK,mBAAmB;;AAE1B,OAAK,MAAM,CAAC,YAAY,UAAU,KAAK,WAAW,SAAS,EAAE;AAC3D,OAAI,MAAM,UACR;AAEF,UAAO,KAAK;IACV,MAAM,aAAa;IACnB,SAAS;KACP,WAAW,KAAK,MAAM;KACtB;KACD;IACF,CAAC;AACF,SAAM,YAAY;;AAEpB,SAAO;;;AAIX,IAAa,8BAAb,MAAoE;CAClE;CAEA,YAAY,QAA4D;AAA3C,OAAA,SAAA;AAC3B,OAAK,UAAU,IAAI,oBAAoB,OAAO;;CAGhD,MAAM,iBAEJ,OACA,SACkC;AAClC,QAAM,KAAK,QAAQ,cAAc;GAC/B,KAAK,MAAM,kBAAkB;GAC7B,eAAe,KAAK,OAAO,uBAAuB,MAAM;GACzD,CAAC;AAQF,SAPmB,IAAI,0BACrB,KAAK,SACL,OACA,KAAK,OAAO,cACZ,KAAK,OAAO,cACZ,KAAK,OAAO,qBACb,CACiB,QAAQ,QAAQ;;CAGpC,UAAU,YAA2B;AACnC,QAAM,KAAK,QAAQ,SAAS;;;AAIhC,SAAS,yBAAyB,MAA+C;CAC/E,MAAM,WAAW,SAAS,KAAK,GAC3B,KAAK,8BACL,KAAA;CACJ,MAAM,QAAQ,SAAS,SAAS,GAC5B,SAAS,uBACT,KAAA;AACJ,QAAO,SAAS,MAAM,IAAI,OAAO,KAAK,MAAM,CAAC,SAAS,IAClD,gBAAgB,MAAM,GACtB;;AAGN,SAAS,SAAS,OAAkD;AAClE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,gBACP,QACQ;AACR,QAAO,6BAA6B,OAAO;;AAG7C,SAAS,yBAAyB,kBAAkC;AAElE,QAAO,aADqB,iBAAiB,MAAM,IAAI,UACf,GAAG,YAAY;;AAGzD,SAAS,kBAAkB,OAAwB;AACjD,KAAI,OAAO,UAAU,SACnB,QAAO;AAET,KAAI,OAAO,UAAU,YACnB,QAAO;AAET,QAAO,KAAK,UAAU,MAAM;;AAG9B,eAAe,YACb,SACA,WACA,SACY;CACZ,IAAI,gBAAsD;AAC1D,KAAI;AACF,SAAO,MAAM,QAAQ,KAAK,CACxB,SACA,IAAI,SAAY,GAAG,WAAW;AAC5B,mBAAgB,iBAAiB;AAC/B,WAAO,IAAI,MAAM,QAAQ,CAAC;MACzB,UAAU;IACb,CACH,CAAC;WACM;AACR,MAAI,cACF,cAAa,cAAc"}
@@ -0,0 +1,18 @@
1
+ import { readString } from "../stdio-runtime-config.utils.js";
2
+ //#region src/utils/stdio-runtime-input.utils.ts
3
+ function extractPromptText(message) {
4
+ const text = (message.parts ?? []).map((part) => {
5
+ if (part.type === "text" || part.type === "reasoning" || part.type === "rich-text") return part.text ?? "";
6
+ return "";
7
+ }).join("\n").trim();
8
+ return text.length > 0 ? text : "[empty message]";
9
+ }
10
+ function resolveModelId(params) {
11
+ const { metadata, providerRoute } = params;
12
+ const modelId = providerRoute?.model ?? readString(metadata?.preferred_model) ?? readString(metadata?.preferredModel) ?? readString(metadata?.model);
13
+ return modelId === "__nextclaw_runtime_default__" ? void 0 : modelId;
14
+ }
15
+ //#endregion
16
+ export { extractPromptText, resolveModelId };
17
+
18
+ //# sourceMappingURL=stdio-runtime-input.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-runtime-input.utils.js","names":[],"sources":["../../src/utils/stdio-runtime-input.utils.ts"],"sourcesContent":["import type { NcpProviderRuntimeRoute } from \"@nextclaw/ncp\";\nimport { readString } from \"../stdio-runtime-config.utils.js\";\n\nexport function extractPromptText(message: { parts?: Array<{ type: string; text?: string }> }): string {\n const text = (message.parts ?? [])\n .map((part) => {\n if (part.type === \"text\" || part.type === \"reasoning\" || part.type === \"rich-text\") {\n return part.text ?? \"\";\n }\n return \"\";\n })\n .join(\"\\n\")\n .trim();\n return text.length > 0 ? text : \"[empty message]\";\n}\n\nexport function resolveModelId(params: {\n providerRoute?: NcpProviderRuntimeRoute;\n metadata?: Record<string, unknown>;\n}): string | undefined {\n const { metadata, providerRoute } = params;\n const modelId =\n providerRoute?.model ??\n readString(metadata?.preferred_model) ??\n readString(metadata?.preferredModel) ??\n readString(metadata?.model);\n return modelId === \"__nextclaw_runtime_default__\" ? undefined : modelId;\n}\n"],"mappings":";;AAGA,SAAgB,kBAAkB,SAAqE;CACrG,MAAM,QAAQ,QAAQ,SAAS,EAAE,EAC9B,KAAK,SAAS;AACb,MAAI,KAAK,SAAS,UAAU,KAAK,SAAS,eAAe,KAAK,SAAS,YACrE,QAAO,KAAK,QAAQ;AAEtB,SAAO;GACP,CACD,KAAK,KAAK,CACV,MAAM;AACT,QAAO,KAAK,SAAS,IAAI,OAAO;;AAGlC,SAAgB,eAAe,QAGR;CACrB,MAAM,EAAE,UAAU,kBAAkB;CACpC,MAAM,UACJ,eAAe,SACf,WAAW,UAAU,gBAAgB,IACrC,WAAW,UAAU,eAAe,IACpC,WAAW,UAAU,MAAM;AAC7B,QAAO,YAAY,iCAAiC,KAAA,IAAY"}
@@ -0,0 +1,27 @@
1
+ import { NcpEventType } from "@nextclaw/ncp";
2
+ //#region src/utils/stdio-runtime-recovery.utils.ts
3
+ const SESSION_METADATA_PATCH_KIND = "session_metadata_patch";
4
+ function createPromptTimeoutRecoveryEvents(params) {
5
+ const { correlationId, error, messageId, resetKeys, runId, sessionId } = params;
6
+ if (!resetKeys?.length || !isPromptTimeoutError(error)) return [];
7
+ return [{
8
+ type: NcpEventType.RunMetadata,
9
+ payload: {
10
+ sessionId,
11
+ messageId,
12
+ runId,
13
+ ...correlationId ? { correlationId } : {},
14
+ metadata: {
15
+ kind: SESSION_METADATA_PATCH_KIND,
16
+ sessionMetadataPatch: Object.fromEntries(resetKeys.map((key) => [key, null]))
17
+ }
18
+ }
19
+ }];
20
+ }
21
+ function isPromptTimeoutError(error) {
22
+ return (error instanceof Error ? error.message : String(error)).includes("[narp-stdio] prompt timed out");
23
+ }
24
+ //#endregion
25
+ export { SESSION_METADATA_PATCH_KIND, createPromptTimeoutRecoveryEvents };
26
+
27
+ //# sourceMappingURL=stdio-runtime-recovery.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-runtime-recovery.utils.js","names":[],"sources":["../../src/utils/stdio-runtime-recovery.utils.ts"],"sourcesContent":["import { NcpEventType, type NcpEndpointEvent } from \"@nextclaw/ncp\";\n\nexport const SESSION_METADATA_PATCH_KIND = \"session_metadata_patch\";\n\nexport function createPromptTimeoutRecoveryEvents(params: {\n correlationId?: string;\n error: unknown;\n messageId: string;\n resetKeys?: readonly string[];\n runId: string;\n sessionId: string;\n}): NcpEndpointEvent[] {\n const { correlationId, error, messageId, resetKeys, runId, sessionId } = params;\n if (!resetKeys?.length || !isPromptTimeoutError(error)) {\n return [];\n }\n return [\n {\n type: NcpEventType.RunMetadata,\n payload: {\n sessionId,\n messageId,\n runId,\n ...(correlationId ? { correlationId } : {}),\n metadata: {\n kind: SESSION_METADATA_PATCH_KIND,\n sessionMetadataPatch: Object.fromEntries(\n resetKeys.map((key) => [key, null]),\n ),\n },\n },\n },\n ];\n}\n\nfunction isPromptTimeoutError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\"[narp-stdio] prompt timed out\");\n}\n"],"mappings":";;AAEA,MAAa,8BAA8B;AAE3C,SAAgB,kCAAkC,QAO3B;CACrB,MAAM,EAAE,eAAe,OAAO,WAAW,WAAW,OAAO,cAAc;AACzE,KAAI,CAAC,WAAW,UAAU,CAAC,qBAAqB,MAAM,CACpD,QAAO,EAAE;AAEX,QAAO,CACL;EACE,MAAM,aAAa;EACnB,SAAS;GACP;GACA;GACA;GACA,GAAI,gBAAgB,EAAE,eAAe,GAAG,EAAE;GAC1C,UAAU;IACR,MAAM;IACN,sBAAsB,OAAO,YAC3B,UAAU,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC,CACpC;IACF;GACF;EACF,CACF;;AAGH,SAAS,qBAAqB,OAAyB;AAErD,SADgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EACvD,SAAS,gCAAgC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/nextclaw-ncp-runtime-stdio-client",
3
- "version": "0.2.13",
3
+ "version": "0.2.14-beta.1",
4
4
  "private": false,
5
5
  "description": "Optional NCP runtime adapter backed by a protocol-aware stdio agent command.",
6
6
  "type": "module",
@@ -17,8 +17,8 @@
17
17
  ],
18
18
  "dependencies": {
19
19
  "@agentclientprotocol/sdk": "^0.19.0",
20
- "@nextclaw/core": "0.14.4",
21
- "@nextclaw/ncp": "0.6.3"
20
+ "@nextclaw/core": "0.14.5-beta.1",
21
+ "@nextclaw/ncp": "0.6.4-beta.1"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^20.17.6",