poe-code 3.0.174 → 3.0.175

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4645,10 +4645,10 @@ function renderTableTerminal(options) {
4645
4645
  }
4646
4646
  function renderTableMarkdown(options) {
4647
4647
  const { columns, rows } = options;
4648
- const header = `| ${columns.map((c) => c.title).join(" | ")} |`;
4649
- const separator = `| ${columns.map((c) => c.alignment === "right" ? "---:" : ":---").join(" | ")} |`;
4648
+ const header = `| ${columns.map((c2) => c2.title).join(" | ")} |`;
4649
+ const separator = `| ${columns.map((c2) => c2.alignment === "right" ? "---:" : ":---").join(" | ")} |`;
4650
4650
  const dataRows = rows.map(
4651
- (row) => `| ${columns.map((c) => stripAnsi2(row[c.name] ?? "").replace(/\|/g, "\\|")).join(" | ")} |`
4651
+ (row) => `| ${columns.map((c2) => stripAnsi2(row[c2.name] ?? "").replace(/\|/g, "\\|")).join(" | ")} |`
4652
4652
  );
4653
4653
  return [header, separator, ...dataRows].join("\n");
4654
4654
  }
@@ -8239,6 +8239,42 @@ var init_dashboard2 = __esm({
8239
8239
  }
8240
8240
  });
8241
8241
 
8242
+ // node_modules/fast-string-truncated-width/dist/utils.js
8243
+ var init_utils = __esm({
8244
+ "node_modules/fast-string-truncated-width/dist/utils.js"() {
8245
+ }
8246
+ });
8247
+
8248
+ // node_modules/fast-string-truncated-width/dist/index.js
8249
+ var EMOJI_RE, MODIFIER_RE;
8250
+ var init_dist = __esm({
8251
+ "node_modules/fast-string-truncated-width/dist/index.js"() {
8252
+ init_utils();
8253
+ EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
8254
+ MODIFIER_RE = new RegExp("\\p{M}+", "gu");
8255
+ }
8256
+ });
8257
+
8258
+ // node_modules/fast-string-width/dist/index.js
8259
+ var init_dist2 = __esm({
8260
+ "node_modules/fast-string-width/dist/index.js"() {
8261
+ init_dist();
8262
+ }
8263
+ });
8264
+
8265
+ // node_modules/fast-wrap-ansi/lib/main.js
8266
+ var ANSI_ESCAPE_BELL, ANSI_CSI, ANSI_OSC, ANSI_ESCAPE_LINK, GROUP_REGEX;
8267
+ var init_main = __esm({
8268
+ "node_modules/fast-wrap-ansi/lib/main.js"() {
8269
+ init_dist2();
8270
+ ANSI_ESCAPE_BELL = "\x07";
8271
+ ANSI_CSI = "[";
8272
+ ANSI_OSC = "]";
8273
+ ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
8274
+ GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
8275
+ }
8276
+ });
8277
+
8242
8278
  // node_modules/sisteransi/src/index.js
8243
8279
  var require_src = __commonJS({
8244
8280
  "node_modules/sisteransi/src/index.js"(exports, module) {
@@ -8247,16 +8283,16 @@ var require_src = __commonJS({
8247
8283
  var CSI = `${ESC}[`;
8248
8284
  var beep = "\x07";
8249
8285
  var cursor = {
8250
- to(x, y) {
8251
- if (!y) return `${CSI}${x + 1}G`;
8252
- return `${CSI}${y + 1};${x + 1}H`;
8286
+ to(x, y2) {
8287
+ if (!y2) return `${CSI}${x + 1}G`;
8288
+ return `${CSI}${y2 + 1};${x + 1}H`;
8253
8289
  },
8254
- move(x, y) {
8290
+ move(x, y2) {
8255
8291
  let ret = "";
8256
8292
  if (x < 0) ret += `${CSI}${-x}D`;
8257
8293
  else if (x > 0) ret += `${CSI}${x}C`;
8258
- if (y < 0) ret += `${CSI}${-y}A`;
8259
- else if (y > 0) ret += `${CSI}${y}B`;
8294
+ if (y2 < 0) ret += `${CSI}${-y2}A`;
8295
+ else if (y2 > 0) ret += `${CSI}${y2}B`;
8260
8296
  return ret;
8261
8297
  },
8262
8298
  up: (count = 1) => `${CSI}${count}A`,
@@ -8296,30 +8332,24 @@ var require_src = __commonJS({
8296
8332
  });
8297
8333
 
8298
8334
  // node_modules/@clack/core/dist/index.mjs
8299
- import { stdout as R, stdin as q } from "node:process";
8300
- import * as k from "node:readline";
8301
- import ot from "node:readline";
8302
- import { ReadStream as J } from "node:tty";
8303
- function Ct(t) {
8304
- return t === z;
8305
- }
8306
- var import_sisteransi, P, ct, pt, ft, j, Q, dt, U, et, At, _, bt, z;
8307
- var init_dist = __esm({
8335
+ import { styleText as y } from "node:util";
8336
+ import { stdout as S, stdin as $ } from "node:process";
8337
+ import * as _ from "node:readline";
8338
+ import P from "node:readline";
8339
+ import { ReadStream as D } from "node:tty";
8340
+ function q(r) {
8341
+ return r === C;
8342
+ }
8343
+ var import_sisteransi, E, G, u, Y, C;
8344
+ var init_dist3 = __esm({
8308
8345
  "node_modules/@clack/core/dist/index.mjs"() {
8346
+ init_main();
8309
8347
  import_sisteransi = __toESM(require_src(), 1);
8310
- P = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
8311
- ct = new RegExp("\\p{M}+", "gu");
8312
- pt = { limit: 1 / 0, ellipsis: "" };
8313
- ft = { limit: 1 / 0, ellipsis: "", ellipsisWidth: 0 };
8314
- j = "\x07";
8315
- Q = "[";
8316
- dt = "]";
8317
- U = `${dt}8;;`;
8318
- et = new RegExp(`(?:\\${Q}(?<code>\\d+)m|\\${U}(?<uri>.*)${j})`, "y");
8319
- At = ["up", "down", "left", "right", "space", "enter", "cancel"];
8320
- _ = { actions: new Set(At), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]), messages: { cancel: "Canceled", error: "Something went wrong" }, withGuide: true };
8321
- bt = globalThis.process.platform.startsWith("win");
8322
- z = /* @__PURE__ */ Symbol("clack:cancel");
8348
+ E = ["up", "down", "left", "right", "space", "enter", "cancel"];
8349
+ G = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
8350
+ u = { actions: new Set(E), aliases: /* @__PURE__ */ new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["", "cancel"], ["escape", "cancel"]]), messages: { cancel: "Canceled", error: "Something went wrong" }, withGuide: true, date: { monthNames: [...G], messages: { required: "Please enter a valid date", invalidMonth: "There are only 12 months in a year", invalidDay: (r, t) => `There are only ${r} days in ${t}`, afterMin: (r) => `Date must be on or after ${r.toISOString().slice(0, 10)}`, beforeMax: (r) => `Date must be on or before ${r.toISOString().slice(0, 10)}` } } };
8351
+ Y = globalThis.process.platform.startsWith("win");
8352
+ C = /* @__PURE__ */ Symbol("clack:cancel");
8323
8353
  }
8324
8354
  });
8325
8355
 
@@ -8336,7 +8366,7 @@ function cancel(msg = "") {
8336
8366
  var init_cancel = __esm({
8337
8367
  "packages/design-system/src/prompts/primitives/cancel.ts"() {
8338
8368
  "use strict";
8339
- init_dist();
8369
+ init_dist3();
8340
8370
  init_output_format();
8341
8371
  }
8342
8372
  });
@@ -8584,7 +8614,7 @@ async function confirm2(opts) {
8584
8614
  }
8585
8615
  async function confirmOrCancel(opts) {
8586
8616
  const result = await confirm2(opts);
8587
- if (Ct(result)) {
8617
+ if (q(result)) {
8588
8618
  cancel("Operation cancelled.");
8589
8619
  throw new PromptCancelledError();
8590
8620
  }
@@ -8738,6 +8768,126 @@ var init_src6 = __esm({
8738
8768
  }
8739
8769
  });
8740
8770
 
8771
+ // packages/agent-spawn/src/acp/session-update-converter.ts
8772
+ function createToolRenderState() {
8773
+ return {
8774
+ startedToolCalls: /* @__PURE__ */ new Set(),
8775
+ toolCallKinds: /* @__PURE__ */ new Map(),
8776
+ toolCallTitles: /* @__PURE__ */ new Map()
8777
+ };
8778
+ }
8779
+ function toRenderKind(kind) {
8780
+ if (kind === "execute") return "exec";
8781
+ if (kind === "write") return "edit";
8782
+ if (kind === "read") return "read";
8783
+ return "other";
8784
+ }
8785
+ function toToolTitle(title, locations) {
8786
+ if (locations && locations.length > 0 && locations[0].path) {
8787
+ return locations[0].path;
8788
+ }
8789
+ return title;
8790
+ }
8791
+ function toToolOutput(value) {
8792
+ if (typeof value === "string") return value;
8793
+ if (value === void 0 || value === null) return "";
8794
+ try {
8795
+ return JSON.stringify(value);
8796
+ } catch {
8797
+ return String(value);
8798
+ }
8799
+ }
8800
+ function extractToolOutputText(update) {
8801
+ const raw = toToolOutput(update.rawOutput);
8802
+ if (raw) return raw;
8803
+ if (!update.content) return "";
8804
+ return update.content.filter((c2) => c2.type === "text" && c2.text).map((c2) => c2.text).join("");
8805
+ }
8806
+ function sessionUpdateToEvents(update, state) {
8807
+ if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
8808
+ return [{ event: "agent_message", text: update.content.text }];
8809
+ }
8810
+ if (update.sessionUpdate === "agent_thought_chunk" && update.content.type === "text") {
8811
+ return [{ event: "reasoning", text: update.content.text }];
8812
+ }
8813
+ if (update.sessionUpdate === "usage_update") {
8814
+ const cachedTokens = Math.max(0, update.size - update.used);
8815
+ const usage = {
8816
+ event: "usage",
8817
+ inputTokens: update.used,
8818
+ outputTokens: 0
8819
+ };
8820
+ if (cachedTokens > 0) {
8821
+ usage.cachedTokens = cachedTokens;
8822
+ }
8823
+ if (update.cost && update.cost.currency === "USD") {
8824
+ usage.costUsd = update.cost.amount;
8825
+ }
8826
+ return [usage];
8827
+ }
8828
+ if (update.sessionUpdate === "tool_call") {
8829
+ const renderKind = toRenderKind(update.kind);
8830
+ const title = toToolTitle(update.title, update.locations);
8831
+ state.toolCallKinds.set(update.toolCallId, renderKind);
8832
+ state.toolCallTitles.set(update.toolCallId, title);
8833
+ if (state.startedToolCalls.has(update.toolCallId)) {
8834
+ return [];
8835
+ }
8836
+ state.startedToolCalls.add(update.toolCallId);
8837
+ return [{
8838
+ event: "tool_start",
8839
+ kind: renderKind,
8840
+ title,
8841
+ id: update.toolCallId
8842
+ }];
8843
+ }
8844
+ if (update.sessionUpdate === "tool_call_update") {
8845
+ const renderKind = toRenderKind(update.kind ?? void 0) || state.toolCallKinds.get(update.toolCallId) || "other";
8846
+ state.toolCallKinds.set(update.toolCallId, renderKind);
8847
+ const events = [];
8848
+ const toolTitle = toToolTitle(
8849
+ state.toolCallTitles.get(update.toolCallId) ?? update.toolCallId,
8850
+ update.locations
8851
+ );
8852
+ state.toolCallTitles.set(update.toolCallId, toolTitle);
8853
+ const status = update.status;
8854
+ const shouldStart = !state.startedToolCalls.has(update.toolCallId) && (status === "pending" || status === "in_progress");
8855
+ if (shouldStart) {
8856
+ state.startedToolCalls.add(update.toolCallId);
8857
+ events.push({
8858
+ event: "tool_start",
8859
+ kind: renderKind,
8860
+ title: toolTitle,
8861
+ id: update.toolCallId
8862
+ });
8863
+ }
8864
+ if (status === "completed" || status === "failed" || status === "cancelled") {
8865
+ if (!state.startedToolCalls.has(update.toolCallId)) {
8866
+ state.startedToolCalls.add(update.toolCallId);
8867
+ events.push({
8868
+ event: "tool_start",
8869
+ kind: renderKind,
8870
+ title: toolTitle,
8871
+ id: update.toolCallId
8872
+ });
8873
+ }
8874
+ events.push({
8875
+ event: "tool_complete",
8876
+ kind: renderKind,
8877
+ path: extractToolOutputText(update),
8878
+ id: update.toolCallId
8879
+ });
8880
+ }
8881
+ return events;
8882
+ }
8883
+ return [];
8884
+ }
8885
+ var init_session_update_converter = __esm({
8886
+ "packages/agent-spawn/src/acp/session-update-converter.ts"() {
8887
+ "use strict";
8888
+ }
8889
+ });
8890
+
8741
8891
  // packages/agent-spawn/src/acp/renderer.ts
8742
8892
  function writeLine2(line) {
8743
8893
  process.stdout.write(`${line}
@@ -8828,2147 +8978,2042 @@ var init_renderer2 = __esm({
8828
8978
  "packages/agent-spawn/src/acp/renderer.ts"() {
8829
8979
  "use strict";
8830
8980
  init_src6();
8981
+ init_session_update_converter();
8831
8982
  }
8832
8983
  });
8833
8984
 
8834
- // packages/agent-spawn/src/acp/replay.ts
8835
- import path9 from "node:path";
8836
- import { homedir as homedir2 } from "node:os";
8837
- import { open, readdir } from "node:fs/promises";
8838
- import { createInterface as createInterface2 } from "node:readline";
8839
- var init_replay = __esm({
8840
- "packages/agent-spawn/src/acp/replay.ts"() {
8985
+ // packages/poe-acp-client/src/types.ts
8986
+ function isObjectRecord(value) {
8987
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8988
+ }
8989
+ function isAcpErrorCode(value) {
8990
+ return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
8991
+ }
8992
+ function isAcpError(value) {
8993
+ if (value instanceof AcpError) {
8994
+ return true;
8995
+ }
8996
+ if (!isObjectRecord(value)) {
8997
+ return false;
8998
+ }
8999
+ if (!isAcpErrorCode(value.code) || typeof value.message !== "string") {
9000
+ return false;
9001
+ }
9002
+ return value.data === void 0 || Object.prototype.hasOwnProperty.call(value, "data");
9003
+ }
9004
+ var ACP_ERROR_CODE_PARSE, ACP_ERROR_CODE_INVALID_REQUEST, ACP_ERROR_CODE_METHOD_NOT_FOUND, ACP_ERROR_CODE_INVALID_PARAMS, ACP_ERROR_CODE_INTERNAL, ACP_ERROR_CODE_RESOURCE_NOT_FOUND, AcpError;
9005
+ var init_types3 = __esm({
9006
+ "packages/poe-acp-client/src/types.ts"() {
8841
9007
  "use strict";
8842
- init_renderer2();
9008
+ ACP_ERROR_CODE_PARSE = -32700;
9009
+ ACP_ERROR_CODE_INVALID_REQUEST = -32600;
9010
+ ACP_ERROR_CODE_METHOD_NOT_FOUND = -32601;
9011
+ ACP_ERROR_CODE_INVALID_PARAMS = -32602;
9012
+ ACP_ERROR_CODE_INTERNAL = -32603;
9013
+ ACP_ERROR_CODE_RESOURCE_NOT_FOUND = -32002;
9014
+ AcpError = class extends Error {
9015
+ code;
9016
+ data;
9017
+ constructor(code, message2, data) {
9018
+ super(message2);
9019
+ this.name = "AcpError";
9020
+ this.code = code;
9021
+ if (data !== void 0) {
9022
+ this.data = data;
9023
+ }
9024
+ }
9025
+ };
8843
9026
  }
8844
9027
  });
8845
9028
 
8846
- // packages/agent-spawn/src/adapters/utils.ts
8847
- function truncate2(text4, maxLength) {
8848
- if (text4.length <= maxLength) return text4;
8849
- if (maxLength <= 3) return text4.slice(0, maxLength);
8850
- return `${text4.slice(0, maxLength - 3)}...`;
9029
+ // packages/poe-acp-client/src/jsonrpc-message-layer.ts
9030
+ function isObjectRecord2(value) {
9031
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8851
9032
  }
8852
- function isNonEmptyString(value) {
8853
- return typeof value === "string" && value.length > 0;
9033
+ function hasOwn2(value, property) {
9034
+ return Object.prototype.hasOwnProperty.call(value, property);
8854
9035
  }
8855
- function extractThreadId(value) {
8856
- if (!value || typeof value !== "object") return;
8857
- const obj = value;
8858
- const maybeThreadId = isNonEmptyString(obj.thread_id) && obj.thread_id || isNonEmptyString(obj.threadId) && obj.threadId || isNonEmptyString(obj.threadID) && obj.threadID || isNonEmptyString(obj.session_id) && obj.session_id || isNonEmptyString(obj.sessionId) && obj.sessionId || isNonEmptyString(obj.sessionID) && obj.sessionID;
8859
- return maybeThreadId || void 0;
9036
+ function isRequestId(value) {
9037
+ return value === null || typeof value === "string" || typeof value === "number";
8860
9038
  }
8861
- var init_utils = __esm({
8862
- "packages/agent-spawn/src/adapters/utils.ts"() {
8863
- "use strict";
9039
+ function toRequestId(value) {
9040
+ return isRequestId(value) ? value : null;
9041
+ }
9042
+ function parseError() {
9043
+ return new AcpError(ACP_ERROR_CODE_PARSE, "Parse error");
9044
+ }
9045
+ function invalidRequest() {
9046
+ return new AcpError(ACP_ERROR_CODE_INVALID_REQUEST, "Invalid Request");
9047
+ }
9048
+ function methodNotFound(method) {
9049
+ return new AcpError(
9050
+ ACP_ERROR_CODE_METHOD_NOT_FOUND,
9051
+ `Method not found: "${method}"`
9052
+ );
9053
+ }
9054
+ function internalError(message2) {
9055
+ return new AcpError(ACP_ERROR_CODE_INTERNAL, message2);
9056
+ }
9057
+ function isJsonRpcErrorObject(value) {
9058
+ if (!isObjectRecord2(value)) {
9059
+ return false;
8864
9060
  }
8865
- });
8866
-
8867
- // packages/agent-spawn/src/adapters/claude.ts
8868
- function extractTitle(name, input) {
8869
- const keys = TITLE_KEYS[name];
8870
- if (keys && input && typeof input === "object") {
8871
- const obj = input;
8872
- for (const key of keys) {
8873
- const value = obj[key];
8874
- if (typeof value === "string" && value.length > 0) {
8875
- return truncate2(value, 80);
8876
- }
8877
- }
9061
+ if (!isAcpErrorCode(value.code) || typeof value.message !== "string") {
9062
+ return false;
8878
9063
  }
8879
- return name;
9064
+ return value.data === void 0 || hasOwn2(value, "data");
8880
9065
  }
8881
- async function* adaptClaude(lines) {
8882
- const toolKindsById = /* @__PURE__ */ new Map();
8883
- let emittedSessionStart = false;
8884
- for await (const rawLine of lines) {
8885
- const line = rawLine.trim();
8886
- if (!line) continue;
8887
- const firstChar = line[0];
8888
- if (firstChar !== "{" && firstChar !== "[") {
8889
- continue;
8890
- }
8891
- let event;
8892
- try {
8893
- event = JSON.parse(line);
8894
- } catch (error2) {
8895
- const stack = error2 instanceof Error ? error2.stack : void 0;
8896
- yield {
8897
- event: "error",
8898
- message: `[adaptClaude] Malformed JSON line: ${truncate2(line, 200)}`,
8899
- stack
8900
- };
8901
- continue;
8902
- }
8903
- const eventType = event.type;
8904
- if (!isNonEmptyString(eventType)) continue;
8905
- if (!emittedSessionStart) {
8906
- const threadId = extractThreadId(event);
8907
- emittedSessionStart = true;
8908
- yield { event: "session_start", threadId };
8909
- }
8910
- if (eventType === "result") {
8911
- const usage = event.usage ?? {};
8912
- const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : typeof event.input_tokens === "number" ? event.input_tokens : typeof event.num_input_tokens === "number" ? event.num_input_tokens : 0;
8913
- const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : typeof event.output_tokens === "number" ? event.output_tokens : typeof event.num_output_tokens === "number" ? event.num_output_tokens : 0;
8914
- const costUsd = typeof usage.cost_usd === "number" ? usage.cost_usd : typeof event.cost_usd === "number" ? event.cost_usd : void 0;
8915
- yield { event: "usage", inputTokens, outputTokens, costUsd };
8916
- continue;
8917
- }
8918
- if (eventType !== "assistant" && eventType !== "user") continue;
8919
- const message2 = event.message ?? null;
8920
- if (!message2 || typeof message2 !== "object") continue;
8921
- const content = message2.content ?? null;
8922
- if (!Array.isArray(content)) continue;
8923
- for (const block of content) {
8924
- const item = block;
8925
- if (!item || typeof item !== "object") continue;
8926
- const blockType = item.type;
8927
- if (!isNonEmptyString(blockType)) continue;
8928
- if (eventType === "assistant") {
8929
- if (blockType === "text" && isNonEmptyString(item.text)) {
8930
- yield {
8931
- event: "agent_message",
8932
- text: item.text
8933
- };
8934
- continue;
8935
- }
8936
- if (blockType === "tool_use" && isNonEmptyString(item.id) && isNonEmptyString(item.name)) {
8937
- const kind = TOOL_KIND_MAP[item.name] ?? "other";
8938
- toolKindsById.set(item.id, kind);
8939
- yield {
8940
- event: "tool_start",
8941
- id: item.id,
8942
- kind,
8943
- title: extractTitle(item.name, item.input),
8944
- input: item.input
8945
- };
8946
- }
8947
- continue;
8948
- }
8949
- if (eventType === "user") {
8950
- if (!isNonEmptyString(item.tool_use_id)) continue;
8951
- if (blockType !== "tool_result") continue;
8952
- const kind = toolKindsById.get(item.tool_use_id);
8953
- toolKindsById.delete(item.tool_use_id);
8954
- let path54;
8955
- if (typeof item.content === "string") {
8956
- path54 = item.content;
8957
- } else {
8958
- try {
8959
- path54 = JSON.stringify(item.content);
8960
- } catch {
8961
- path54 = String(item.content);
8962
- }
8963
- }
8964
- yield {
8965
- event: "tool_complete",
8966
- id: item.tool_use_id,
8967
- kind,
8968
- path: path54
8969
- };
9066
+ function toResponseError(error2) {
9067
+ return new AcpError(error2.code, error2.message, error2.data);
9068
+ }
9069
+ function toDispatchError(error2) {
9070
+ if (error2 instanceof AcpError) {
9071
+ return error2;
9072
+ }
9073
+ if (isAcpError(error2)) {
9074
+ return new AcpError(error2.code, error2.message, error2.data);
9075
+ }
9076
+ if (error2 instanceof Error && error2.message.length > 0) {
9077
+ return internalError(error2.message);
9078
+ }
9079
+ return internalError("Internal error");
9080
+ }
9081
+ function chunkToString(chunk) {
9082
+ if (typeof chunk === "string") {
9083
+ return chunk;
9084
+ }
9085
+ if (chunk instanceof Uint8Array) {
9086
+ return Buffer.from(chunk).toString("utf8");
9087
+ }
9088
+ return String(chunk);
9089
+ }
9090
+ function normalizeLine(line) {
9091
+ return line.endsWith("\r") ? line.slice(0, -1) : line;
9092
+ }
9093
+ async function* readLines(stream) {
9094
+ let buffer = "";
9095
+ for await (const chunk of stream) {
9096
+ buffer += chunkToString(chunk);
9097
+ while (true) {
9098
+ const newlineIndex = buffer.indexOf("\n");
9099
+ if (newlineIndex === -1) {
9100
+ break;
8970
9101
  }
9102
+ const line = buffer.slice(0, newlineIndex);
9103
+ buffer = buffer.slice(newlineIndex + 1);
9104
+ yield normalizeLine(line);
8971
9105
  }
8972
9106
  }
9107
+ if (buffer.length > 0) {
9108
+ yield normalizeLine(buffer);
9109
+ }
8973
9110
  }
8974
- var TOOL_KIND_MAP, TITLE_KEYS;
8975
- var init_claude = __esm({
8976
- "packages/agent-spawn/src/adapters/claude.ts"() {
8977
- "use strict";
8978
- init_utils();
8979
- TOOL_KIND_MAP = {
8980
- Read: "read",
8981
- Write: "edit",
8982
- Edit: "edit",
8983
- NotebookEdit: "edit",
8984
- Bash: "exec",
8985
- Glob: "search",
8986
- Grep: "search",
8987
- Task: "think"
9111
+ function createResponseMessage(id, result) {
9112
+ return {
9113
+ jsonrpc: "2.0",
9114
+ id,
9115
+ result: result === void 0 ? null : result
9116
+ };
9117
+ }
9118
+ function createJsonRpcErrorResponse(id, error2) {
9119
+ const response = {
9120
+ jsonrpc: "2.0",
9121
+ id,
9122
+ error: {
9123
+ code: error2.code,
9124
+ message: error2.message
9125
+ }
9126
+ };
9127
+ if (error2.data !== void 0) {
9128
+ response.error.data = error2.data;
9129
+ }
9130
+ return response;
9131
+ }
9132
+ function serializeJsonRpcMessage(message2) {
9133
+ return `${JSON.stringify(message2)}
9134
+ `;
9135
+ }
9136
+ function parseJsonRpcMessage(line) {
9137
+ let parsed;
9138
+ try {
9139
+ parsed = JSON.parse(line);
9140
+ } catch {
9141
+ return {
9142
+ type: "invalid",
9143
+ id: null,
9144
+ error: parseError()
8988
9145
  };
8989
- TITLE_KEYS = {
8990
- Bash: ["command"],
8991
- Read: ["file_path"],
8992
- Write: ["file_path"],
8993
- Edit: ["file_path"],
8994
- NotebookEdit: ["notebook_path"],
8995
- Glob: ["pattern"],
8996
- Grep: ["pattern"],
8997
- Task: ["description", "prompt"]
9146
+ }
9147
+ if (!isObjectRecord2(parsed)) {
9148
+ return {
9149
+ type: "invalid",
9150
+ id: null,
9151
+ error: invalidRequest()
8998
9152
  };
8999
9153
  }
9000
- });
9001
-
9002
- // packages/agent-spawn/src/adapters/codex.ts
9003
- async function* adaptCodex(lines) {
9004
- const toolTitleById = /* @__PURE__ */ new Map();
9005
- const toolKindById = /* @__PURE__ */ new Map();
9006
- for await (const rawLine of lines) {
9007
- const line = rawLine.trim();
9008
- if (!line) continue;
9009
- let event;
9010
- try {
9011
- event = JSON.parse(line);
9012
- } catch (error2) {
9013
- const stack = error2 instanceof Error ? error2.stack : void 0;
9014
- yield {
9015
- event: "error",
9016
- message: `[adaptCodex] Malformed JSON line: ${truncate2(line, 200)}`,
9017
- stack
9154
+ const id = toRequestId(parsed.id);
9155
+ if (parsed.jsonrpc !== "2.0") {
9156
+ return {
9157
+ type: "invalid",
9158
+ id,
9159
+ error: invalidRequest()
9160
+ };
9161
+ }
9162
+ const hasMethod = hasOwn2(parsed, "method");
9163
+ const hasId = hasOwn2(parsed, "id");
9164
+ if (hasMethod) {
9165
+ if (typeof parsed.method !== "string") {
9166
+ return {
9167
+ type: "invalid",
9168
+ id,
9169
+ error: invalidRequest()
9018
9170
  };
9019
- continue;
9020
- }
9021
- const eventType = event.type;
9022
- if (!isNonEmptyString(eventType)) continue;
9023
- if (eventType === "thread.started") {
9024
- const maybeThreadId = extractThreadId(event);
9025
- yield { event: "session_start", threadId: maybeThreadId };
9026
- continue;
9027
9171
  }
9028
- if (eventType === "turn.started") {
9029
- continue;
9172
+ if (hasId) {
9173
+ if (!isRequestId(parsed.id)) {
9174
+ return {
9175
+ type: "invalid",
9176
+ id: null,
9177
+ error: invalidRequest()
9178
+ };
9179
+ }
9180
+ const request = {
9181
+ jsonrpc: "2.0",
9182
+ id: parsed.id,
9183
+ method: parsed.method
9184
+ };
9185
+ if (hasOwn2(parsed, "params")) {
9186
+ request.params = parsed.params;
9187
+ }
9188
+ return { type: "request", message: request };
9030
9189
  }
9031
- if (eventType === "turn.completed") {
9032
- const usage = event.usage ?? {};
9033
- const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : 0;
9034
- const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : 0;
9035
- const cachedTokens = typeof usage.cached_input_tokens === "number" ? usage.cached_input_tokens : 0;
9036
- yield { event: "usage", inputTokens, outputTokens, cachedTokens };
9037
- continue;
9038
- }
9039
- if (eventType === "turn.failed") {
9040
- const message2 = extractErrorMessage(event) ?? "Turn failed";
9041
- yield { event: "error", message: message2 };
9042
- continue;
9043
- }
9044
- const item = event.item ?? null;
9045
- if (!item || typeof item !== "object") continue;
9046
- const itemType = item.type;
9047
- if (!isNonEmptyString(itemType)) continue;
9048
- if (eventType === "item.started") {
9049
- if (!isNonEmptyString(item.id)) continue;
9050
- let kind;
9051
- let title;
9052
- if (itemType === "command_execution") {
9053
- kind = "exec";
9054
- title = truncate2(isNonEmptyString(item.command) ? item.command : "", 80);
9055
- } else if (itemType === "file_edit") {
9056
- kind = "edit";
9057
- title = isNonEmptyString(item.path) ? item.path : "";
9058
- } else if (itemType === "thinking") {
9059
- kind = "think";
9060
- title = "thinking...";
9061
- } else if (itemType === "mcp_tool_call") {
9062
- const server = isNonEmptyString(item.server) ? item.server : "unknown";
9063
- const tool = isNonEmptyString(item.tool) ? item.tool : "unknown";
9064
- kind = "other";
9065
- title = `${server}.${tool}`;
9066
- }
9067
- if (kind && title !== void 0) {
9068
- toolTitleById.set(item.id, title);
9069
- toolKindById.set(item.id, kind);
9070
- yield { event: "tool_start", id: item.id, kind, title };
9071
- }
9072
- continue;
9073
- }
9074
- if (eventType === "item.completed") {
9075
- if (itemType === "agent_message") {
9076
- if (!isNonEmptyString(item.text)) continue;
9077
- yield { event: "agent_message", text: item.text };
9078
- continue;
9079
- }
9080
- if (itemType === "reasoning") {
9081
- const text4 = isNonEmptyString(item.text) ? item.text : isNonEmptyString(item.content) ? item.content : isNonEmptyString(item.summary) ? item.summary : void 0;
9082
- if (!text4) continue;
9083
- yield { event: "reasoning", text: text4 };
9084
- continue;
9085
- }
9086
- if (!isNonEmptyString(item.id)) continue;
9087
- if (itemType === "command_execution" || itemType === "file_edit" || itemType === "mcp_tool_call") {
9088
- const kindFromStart = toolKindById.get(item.id);
9089
- const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
9090
- const titleFromEvent = isNonEmptyString(item.path) ? item.path : itemType === "mcp_tool_call" ? `${isNonEmptyString(item.server) ? item.server : "unknown"}.${isNonEmptyString(item.tool) ? item.tool : "unknown"}` : void 0;
9091
- const path54 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
9092
- toolTitleById.delete(item.id);
9093
- toolKindById.delete(item.id);
9094
- yield { event: "tool_complete", id: item.id, kind, path: path54 };
9095
- }
9190
+ const notification = {
9191
+ jsonrpc: "2.0",
9192
+ method: parsed.method
9193
+ };
9194
+ if (hasOwn2(parsed, "params")) {
9195
+ notification.params = parsed.params;
9096
9196
  }
9197
+ return {
9198
+ type: "notification",
9199
+ message: notification
9200
+ };
9097
9201
  }
9098
- }
9099
- function extractErrorMessage(event) {
9100
- if (isNonEmptyString(event.message)) return event.message;
9101
- const error2 = event.error;
9102
- if (isNonEmptyString(error2)) return error2;
9103
- if (typeof error2 === "object" && error2 !== null) {
9104
- const errorObj = error2;
9105
- if (isNonEmptyString(errorObj.message)) return errorObj.message;
9202
+ if (!hasId || !isRequestId(parsed.id)) {
9203
+ return {
9204
+ type: "invalid",
9205
+ id,
9206
+ error: invalidRequest()
9207
+ };
9106
9208
  }
9107
- if (isNonEmptyString(event.reason)) return event.reason;
9108
- return void 0;
9109
- }
9110
- var init_codex3 = __esm({
9111
- "packages/agent-spawn/src/adapters/codex.ts"() {
9112
- "use strict";
9113
- init_utils();
9209
+ const hasResult = hasOwn2(parsed, "result");
9210
+ const hasError = hasOwn2(parsed, "error");
9211
+ if (hasResult === hasError) {
9212
+ return {
9213
+ type: "invalid",
9214
+ id: parsed.id,
9215
+ error: invalidRequest()
9216
+ };
9114
9217
  }
9115
- });
9116
-
9117
- // packages/agent-spawn/src/adapters/kimi.ts
9118
- async function* adaptKimi(lines) {
9119
- let emittedSessionStart = false;
9120
- for await (const rawLine of lines) {
9121
- const line = rawLine.trim();
9122
- if (!line) continue;
9123
- let event;
9124
- try {
9125
- event = JSON.parse(line);
9126
- } catch (error2) {
9127
- const stack = error2 instanceof Error ? error2.stack : void 0;
9128
- yield {
9129
- event: "error",
9130
- message: `[adaptKimi] Malformed JSON line: ${truncate2(line, 200)}`,
9131
- stack
9132
- };
9133
- continue;
9134
- }
9135
- if (!event || typeof event !== "object") continue;
9136
- if (!emittedSessionStart) {
9137
- const threadId = extractThreadId(event);
9138
- if (threadId) {
9139
- emittedSessionStart = true;
9140
- yield { event: "session_start", threadId };
9218
+ if (hasResult) {
9219
+ return {
9220
+ type: "response",
9221
+ message: {
9222
+ jsonrpc: "2.0",
9223
+ id: parsed.id,
9224
+ result: parsed.result
9141
9225
  }
9142
- }
9143
- const role = event.role;
9144
- if (!isNonEmptyString(role) || role !== "assistant") continue;
9145
- const content = event.content;
9146
- if (!isNonEmptyString(content)) continue;
9147
- yield { event: "agent_message", text: content };
9226
+ };
9148
9227
  }
9149
- }
9150
- var init_kimi3 = __esm({
9151
- "packages/agent-spawn/src/adapters/kimi.ts"() {
9152
- "use strict";
9153
- init_utils();
9228
+ if (!isJsonRpcErrorObject(parsed.error)) {
9229
+ return {
9230
+ type: "invalid",
9231
+ id: parsed.id,
9232
+ error: invalidRequest()
9233
+ };
9154
9234
  }
9155
- });
9156
-
9157
- // packages/agent-spawn/src/adapters/native.ts
9158
- async function* adaptNative(lines) {
9159
- for await (const rawLine of lines) {
9160
- const line = rawLine.trim();
9161
- if (!line) continue;
9162
- let event;
9163
- try {
9164
- event = JSON.parse(line);
9165
- } catch (error2) {
9166
- const stack = error2 instanceof Error ? error2.stack : void 0;
9167
- yield {
9168
- event: "error",
9169
- message: `[adaptNative] Malformed JSON line: ${truncate2(line, 200)}`,
9170
- stack
9171
- };
9172
- continue;
9173
- }
9174
- const maybeEventType = event?.event;
9175
- if (!isNonEmptyString(maybeEventType)) {
9176
- yield {
9177
- event: "error",
9178
- message: `[adaptNative] Line missing string "event" field: ${truncate2(line, 200)}`
9179
- };
9180
- continue;
9235
+ return {
9236
+ type: "response",
9237
+ message: {
9238
+ jsonrpc: "2.0",
9239
+ id: parsed.id,
9240
+ error: parsed.error
9181
9241
  }
9182
- yield event;
9183
- }
9242
+ };
9184
9243
  }
9185
- var init_native = __esm({
9186
- "packages/agent-spawn/src/adapters/native.ts"() {
9244
+ var JsonRpcMessageLayer;
9245
+ var init_jsonrpc_message_layer = __esm({
9246
+ "packages/poe-acp-client/src/jsonrpc-message-layer.ts"() {
9187
9247
  "use strict";
9188
- init_utils();
9189
- }
9190
- });
9191
-
9192
- // packages/agent-spawn/src/adapters/opencode.ts
9193
- function guessToolKind(toolName) {
9194
- const normalized = toolName.toLowerCase();
9195
- if (normalized === "bash" || normalized === "shell" || normalized === "sh") return "exec";
9196
- if (normalized.includes("read")) return "read";
9197
- if (normalized.includes("write") || normalized.includes("edit") || normalized.includes("patch")) {
9198
- return "edit";
9199
- }
9200
- if (normalized.includes("search") || normalized.includes("grep") || normalized.includes("glob") || normalized.includes("find")) {
9201
- return "search";
9202
- }
9203
- if (normalized.includes("think") || normalized.includes("task")) return "think";
9204
- return "other";
9205
- }
9206
- function safeStringify(value) {
9207
- if (typeof value === "string") return value;
9208
- try {
9209
- return JSON.stringify(value);
9210
- } catch {
9211
- return String(value);
9212
- }
9213
- }
9214
- async function* adaptOpenCode(lines) {
9215
- let emittedSessionStart = false;
9216
- const toolKindById = /* @__PURE__ */ new Map();
9217
- for await (const rawLine of lines) {
9218
- const line = rawLine.trim();
9219
- if (!line) continue;
9220
- let event;
9221
- try {
9222
- event = JSON.parse(line);
9223
- } catch (error2) {
9224
- const stack = error2 instanceof Error ? error2.stack : void 0;
9225
- yield {
9226
- event: "error",
9227
- message: `[adaptOpenCode] Malformed JSON line: ${truncate2(line, 200)}`,
9228
- stack
9229
- };
9230
- continue;
9231
- }
9232
- if (!event || typeof event !== "object") continue;
9233
- const sessionID = extractThreadId(event);
9234
- if (!emittedSessionStart && isNonEmptyString(sessionID)) {
9235
- emittedSessionStart = true;
9236
- yield { event: "session_start", threadId: sessionID };
9237
- }
9238
- const eventType = event.type;
9239
- if (!isNonEmptyString(eventType)) continue;
9240
- if (eventType === "text") {
9241
- const part = event.part ?? null;
9242
- if (!part || typeof part !== "object") continue;
9243
- if (!isNonEmptyString(part.text)) continue;
9244
- yield { event: "agent_message", text: part.text };
9245
- continue;
9246
- }
9247
- if (eventType === "tool_use") {
9248
- const part = event.part ?? null;
9249
- if (!part || typeof part !== "object") continue;
9250
- if (!isNonEmptyString(part.callID) || !isNonEmptyString(part.tool)) continue;
9251
- const state = part.state ?? null;
9252
- if (!state || typeof state !== "object") continue;
9253
- const kind = guessToolKind(part.tool);
9254
- const status = state.status;
9255
- const terminal = status === "completed" || status === "failed";
9256
- if (!toolKindById.has(part.callID)) {
9257
- toolKindById.set(part.callID, kind);
9258
- let title = part.tool;
9259
- const maybeInput = state.input;
9260
- if (kind === "exec" && maybeInput && typeof maybeInput === "object") {
9261
- const command = maybeInput.command;
9262
- if (isNonEmptyString(command)) {
9263
- title = truncate2(command, 80);
9264
- }
9265
- }
9266
- yield {
9267
- event: "tool_start",
9268
- id: part.callID,
9269
- kind,
9270
- title,
9271
- input: state.input
9248
+ init_types3();
9249
+ JsonRpcMessageLayer = class {
9250
+ input;
9251
+ output;
9252
+ requestHandlers = /* @__PURE__ */ new Map();
9253
+ notificationHandlers = /* @__PURE__ */ new Map();
9254
+ pending = /* @__PURE__ */ new Map();
9255
+ nextRequestId;
9256
+ disposed = false;
9257
+ constructor(options) {
9258
+ this.input = options.input;
9259
+ this.output = options.output;
9260
+ this.nextRequestId = options.firstRequestId ?? 1;
9261
+ if (!Number.isFinite(this.nextRequestId)) {
9262
+ throw new Error("firstRequestId must be a finite number");
9263
+ }
9264
+ void this.consumeInput();
9265
+ }
9266
+ onRequest(method, handler) {
9267
+ this.requestHandlers.set(method, handler);
9268
+ }
9269
+ onNotification(method, handler) {
9270
+ this.notificationHandlers.set(method, handler);
9271
+ }
9272
+ pendingRequestCount() {
9273
+ return this.pending.size;
9274
+ }
9275
+ sendNotification(method, params) {
9276
+ const notification = {
9277
+ jsonrpc: "2.0",
9278
+ method
9272
9279
  };
9280
+ if (params !== void 0) {
9281
+ notification.params = params;
9282
+ }
9283
+ this.sendMessage(notification);
9273
9284
  }
9274
- if (terminal) {
9275
- const kindFromStart = toolKindById.get(part.callID) ?? kind;
9276
- toolKindById.delete(part.callID);
9277
- yield {
9278
- event: "tool_complete",
9279
- id: part.callID,
9280
- kind: kindFromStart,
9281
- path: safeStringify(state.output)
9285
+ sendRequest(method, params, options = {}) {
9286
+ if (this.disposed) {
9287
+ throw new Error("JSON-RPC message layer is disposed");
9288
+ }
9289
+ const id = options.id === void 0 ? this.nextRequestId++ : options.id;
9290
+ if (this.pending.has(id)) {
9291
+ throw new Error(`A request with id ${JSON.stringify(id)} is already pending`);
9292
+ }
9293
+ const request = {
9294
+ jsonrpc: "2.0",
9295
+ id,
9296
+ method
9282
9297
  };
9298
+ if (params !== void 0) {
9299
+ request.params = params;
9300
+ }
9301
+ return new Promise((resolve2, reject) => {
9302
+ this.pending.set(id, {
9303
+ method,
9304
+ resolve: resolve2,
9305
+ reject
9306
+ });
9307
+ try {
9308
+ this.sendMessage(request);
9309
+ } catch (error2) {
9310
+ this.pending.delete(id);
9311
+ reject(error2);
9312
+ }
9313
+ });
9314
+ }
9315
+ dispose(reason = new Error("JSON-RPC message layer disposed")) {
9316
+ if (this.disposed) {
9317
+ return;
9318
+ }
9319
+ this.disposed = true;
9320
+ this.rejectAllPending(reason);
9321
+ }
9322
+ async consumeInput() {
9323
+ try {
9324
+ for await (const line of readLines(this.input)) {
9325
+ if (this.disposed || line.length === 0) {
9326
+ continue;
9327
+ }
9328
+ await this.handleIncomingLine(line);
9329
+ }
9330
+ if (!this.disposed) {
9331
+ this.dispose(new Error("JSON-RPC input stream closed"));
9332
+ }
9333
+ } catch (error2) {
9334
+ if (!this.disposed) {
9335
+ this.dispose(
9336
+ error2 instanceof Error ? error2 : new Error(`JSON-RPC input stream failed: ${String(error2)}`)
9337
+ );
9338
+ }
9339
+ }
9340
+ }
9341
+ async handleIncomingLine(line) {
9342
+ const parsed = parseJsonRpcMessage(line);
9343
+ if (parsed.type === "invalid") {
9344
+ this.sendMessage(createJsonRpcErrorResponse(parsed.id, parsed.error));
9345
+ return;
9346
+ }
9347
+ if (parsed.type === "response") {
9348
+ this.handleResponse(parsed.message);
9349
+ return;
9350
+ }
9351
+ if (parsed.type === "notification") {
9352
+ await this.handleNotification(parsed.message);
9353
+ return;
9354
+ }
9355
+ await this.handleRequest(parsed.message);
9356
+ }
9357
+ handleResponse(message2) {
9358
+ const pending = this.pending.get(message2.id);
9359
+ if (!pending) {
9360
+ return;
9361
+ }
9362
+ this.pending.delete(message2.id);
9363
+ if ("error" in message2) {
9364
+ pending.reject(toResponseError(message2.error));
9365
+ return;
9366
+ }
9367
+ pending.resolve(message2.result);
9368
+ }
9369
+ async handleRequest(message2) {
9370
+ const handler = this.requestHandlers.get(message2.method);
9371
+ if (!handler) {
9372
+ this.sendMessage(createJsonRpcErrorResponse(message2.id, methodNotFound(message2.method)));
9373
+ return;
9374
+ }
9375
+ try {
9376
+ const result = await handler(message2.params, {
9377
+ id: message2.id,
9378
+ method: message2.method
9379
+ });
9380
+ this.sendMessage(createResponseMessage(message2.id, result));
9381
+ } catch (error2) {
9382
+ this.sendMessage(createJsonRpcErrorResponse(message2.id, toDispatchError(error2)));
9383
+ }
9384
+ }
9385
+ async handleNotification(message2) {
9386
+ const handler = this.notificationHandlers.get(message2.method);
9387
+ if (!handler) {
9388
+ return;
9389
+ }
9390
+ try {
9391
+ await handler(message2.params, { method: message2.method });
9392
+ } catch {
9393
+ }
9394
+ }
9395
+ sendMessage(message2) {
9396
+ if (this.disposed) {
9397
+ throw new Error("JSON-RPC message layer is disposed");
9398
+ }
9399
+ this.output.write(serializeJsonRpcMessage(message2));
9400
+ }
9401
+ rejectAllPending(error2) {
9402
+ for (const pending of this.pending.values()) {
9403
+ pending.reject(error2);
9404
+ }
9405
+ this.pending.clear();
9283
9406
  }
9284
- continue;
9285
- }
9286
- if (eventType === "step_finish") {
9287
- const part = event.part ?? null;
9288
- if (!part || typeof part !== "object") continue;
9289
- const tokens = part.tokens ?? null;
9290
- if (!tokens || typeof tokens !== "object") continue;
9291
- const inputTokens = typeof tokens.input === "number" ? tokens.input : 0;
9292
- const outputTokens = typeof tokens.output === "number" ? tokens.output : 0;
9293
- const cache = tokens.cache ?? null;
9294
- const cachedTokens = cache && typeof cache === "object" && typeof cache.read === "number" ? cache.read : void 0;
9295
- if (inputTokens === 0 && outputTokens === 0 && cachedTokens === void 0) continue;
9296
- yield { event: "usage", inputTokens, outputTokens, cachedTokens };
9297
- continue;
9298
- }
9299
- }
9300
- }
9301
- var init_opencode3 = __esm({
9302
- "packages/agent-spawn/src/adapters/opencode.ts"() {
9303
- "use strict";
9304
- init_utils();
9305
- }
9306
- });
9307
-
9308
- // packages/agent-spawn/src/adapters/index.ts
9309
- function getAdapter(type) {
9310
- const adapter = adapters[type];
9311
- if (!adapter) {
9312
- throw new Error(`Unknown adapter "${String(type)}".`);
9313
- }
9314
- return adapter;
9315
- }
9316
- var adapters;
9317
- var init_adapters = __esm({
9318
- "packages/agent-spawn/src/adapters/index.ts"() {
9319
- "use strict";
9320
- init_claude();
9321
- init_codex3();
9322
- init_kimi3();
9323
- init_native();
9324
- init_opencode3();
9325
- init_codex3();
9326
- init_claude();
9327
- init_kimi3();
9328
- init_native();
9329
- init_opencode3();
9330
- adapters = {
9331
- codex: adaptCodex,
9332
- claude: adaptClaude,
9333
- kimi: adaptKimi,
9334
- native: adaptNative,
9335
- opencode: adaptOpenCode
9336
9407
  };
9337
9408
  }
9338
9409
  });
9339
9410
 
9340
- // packages/agent-spawn/src/acp/line-reader.ts
9341
- function chunkToString(chunk) {
9342
- if (typeof chunk === "string") return chunk;
9343
- if (chunk instanceof Uint8Array) return Buffer.from(chunk).toString("utf8");
9344
- return String(chunk);
9345
- }
9346
- async function* readLines(stream) {
9347
- let buffer = "";
9348
- for await (const chunk of stream) {
9349
- buffer += chunkToString(chunk);
9350
- while (true) {
9351
- const newlineIndex = buffer.indexOf("\n");
9352
- if (newlineIndex === -1) break;
9353
- yield buffer.slice(0, newlineIndex);
9354
- buffer = buffer.slice(newlineIndex + 1);
9355
- }
9356
- }
9357
- if (buffer.length > 0) {
9358
- yield buffer;
9411
+ // packages/poe-acp-client/src/acp-transport.ts
9412
+ import {
9413
+ spawn as spawnChildProcess3
9414
+ } from "node:child_process";
9415
+ function assertExtensionMethod(method) {
9416
+ if (!method.startsWith("_")) {
9417
+ throw new Error('Extension method must start with "_"');
9359
9418
  }
9360
9419
  }
9361
- var init_line_reader = __esm({
9362
- "packages/agent-spawn/src/acp/line-reader.ts"() {
9420
+ var AcpTransport;
9421
+ var init_acp_transport = __esm({
9422
+ "packages/poe-acp-client/src/acp-transport.ts"() {
9363
9423
  "use strict";
9364
- }
9365
- });
9366
-
9367
- // packages/agent-spawn/src/acp/spawn.ts
9368
- import { spawn as spawnChildProcess3 } from "node:child_process";
9369
- function createAbortError2() {
9370
- const error2 = new Error("Agent spawn aborted");
9371
- error2.name = "AbortError";
9372
- return error2;
9424
+ init_jsonrpc_message_layer();
9425
+ AcpTransport = class {
9426
+ closed;
9427
+ command;
9428
+ child;
9429
+ layer;
9430
+ stderrChunks = [];
9431
+ resolveClosed = null;
9432
+ closeEvent = null;
9433
+ closeReason = null;
9434
+ constructor(options) {
9435
+ const {
9436
+ command,
9437
+ args = [],
9438
+ cwd,
9439
+ env,
9440
+ firstRequestId,
9441
+ spawn: spawn9 = spawnChildProcess3
9442
+ } = options;
9443
+ this.command = command;
9444
+ this.closed = new Promise((resolve2) => {
9445
+ this.resolveClosed = resolve2;
9446
+ });
9447
+ this.child = spawn9(command, [...args], {
9448
+ cwd,
9449
+ env,
9450
+ stdio: ["pipe", "pipe", "pipe"]
9451
+ });
9452
+ this.child.stderr.setEncoding("utf8");
9453
+ this.child.stderr.on("data", (chunk) => {
9454
+ this.stderrChunks.push(String(chunk));
9455
+ });
9456
+ this.child.stdin.on("error", (error2) => {
9457
+ const reason = error2 instanceof Error ? error2 : new Error(String(error2));
9458
+ this.close(reason, this.child.exitCode ?? null, this.child.signalCode ?? null);
9459
+ });
9460
+ this.layer = new JsonRpcMessageLayer({
9461
+ input: this.child.stdout,
9462
+ output: this.child.stdin,
9463
+ firstRequestId
9464
+ });
9465
+ this.child.once("error", (error2) => {
9466
+ const reason = error2 instanceof Error ? error2 : new Error(String(error2));
9467
+ this.close(reason, this.child.exitCode ?? null, this.child.signalCode ?? null);
9468
+ });
9469
+ this.child.once("close", (code, signal) => {
9470
+ const reason = this.closeReason ?? new Error(
9471
+ `ACP transport closed (command "${this.command}", code: ${code ?? "null"}${signal ? `, signal: ${signal}` : ""})`
9472
+ );
9473
+ this.close(reason, code ?? null, signal ?? null);
9474
+ });
9475
+ }
9476
+ sendRequest(method, params, options = {}) {
9477
+ return this.layer.sendRequest(method, params, options);
9478
+ }
9479
+ sendExtRequest(method, params, options = {}) {
9480
+ assertExtensionMethod(method);
9481
+ return this.layer.sendRequest(method, params, options);
9482
+ }
9483
+ sendNotification(method, params) {
9484
+ this.layer.sendNotification(method, params);
9485
+ }
9486
+ sendExtNotification(method, params) {
9487
+ assertExtensionMethod(method);
9488
+ this.layer.sendNotification(method, params);
9489
+ }
9490
+ onRequest(method, handler) {
9491
+ this.layer.onRequest(method, handler);
9492
+ }
9493
+ onExtRequest(method, handler) {
9494
+ assertExtensionMethod(method);
9495
+ this.layer.onRequest(method, handler);
9496
+ }
9497
+ onNotification(method, handler) {
9498
+ this.layer.onNotification(method, handler);
9499
+ }
9500
+ onExtNotification(method, handler) {
9501
+ assertExtensionMethod(method);
9502
+ this.layer.onNotification(method, handler);
9503
+ }
9504
+ getStderrOutput() {
9505
+ return this.stderrChunks.join("");
9506
+ }
9507
+ pendingRequestCount() {
9508
+ return this.layer.pendingRequestCount();
9509
+ }
9510
+ dispose(reason = new Error("ACP transport disposed")) {
9511
+ if (this.closeEvent !== null) {
9512
+ return;
9513
+ }
9514
+ this.closeReason = reason;
9515
+ this.layer.dispose(reason);
9516
+ if (!this.child.stdin.destroyed && !this.child.stdin.writableEnded) {
9517
+ this.child.stdin.end();
9518
+ }
9519
+ if (this.child.exitCode !== null || this.child.signalCode !== null) {
9520
+ this.close(reason, this.child.exitCode, this.child.signalCode);
9521
+ return;
9522
+ }
9523
+ const killed = this.child.kill();
9524
+ if (!killed) {
9525
+ this.close(reason, this.child.exitCode, this.child.signalCode);
9526
+ }
9527
+ }
9528
+ close(reason, code, signal) {
9529
+ if (this.closeEvent !== null) {
9530
+ return;
9531
+ }
9532
+ this.layer.dispose(reason);
9533
+ this.closeEvent = {
9534
+ code,
9535
+ signal,
9536
+ reason,
9537
+ stderr: this.getStderrOutput()
9538
+ };
9539
+ this.resolveClosed?.(this.closeEvent);
9540
+ this.resolveClosed = null;
9541
+ }
9542
+ };
9543
+ }
9544
+ });
9545
+
9546
+ // packages/poe-acp-client/src/acp-client.ts
9547
+ import { isAbsolute } from "node:path";
9548
+ function toError(reason) {
9549
+ return reason instanceof Error ? reason : new Error(String(reason));
9373
9550
  }
9374
- function createActivityTimeoutError2(timeoutMs) {
9375
- const error2 = new Error(
9376
- `Agent spawn timed out after ${timeoutMs / 1e3}s of inactivity`
9551
+ function invalidParams(message2) {
9552
+ return new AcpError(
9553
+ ACP_ERROR_CODE_INVALID_PARAMS,
9554
+ `Invalid params: ${message2}`
9377
9555
  );
9378
- error2.name = "ActivityTimeoutError";
9379
- return error2;
9380
9556
  }
9381
- function isAcpEvent(value) {
9382
- return !!value && typeof value === "object" && "event" in value;
9383
- }
9384
- function getDefaultArgsPosition2(config) {
9385
- return config.defaultArgsPosition ?? "afterPrompt";
9557
+ function resourceNotFound(resource) {
9558
+ return new AcpError(
9559
+ ACP_ERROR_CODE_RESOURCE_NOT_FOUND,
9560
+ `Resource not found: ${resource}`
9561
+ );
9386
9562
  }
9387
- function getMcpArgsPosition2(config) {
9388
- if (config.mcpArgsPosition) {
9389
- return config.mcpArgsPosition;
9563
+ function assertAbsolutePath(path54) {
9564
+ if (!isAbsolute(path54)) {
9565
+ throw invalidParams('"path" must be an absolute path');
9390
9566
  }
9391
- return config.mcpArgsBeforeCommand ? "beforeCommand" : "afterCommand";
9392
9567
  }
9393
- function spawnStreaming(options) {
9394
- if (options.signal?.aborted) {
9395
- throw createAbortError2();
9396
- }
9397
- const { agentId, binaryName, spawnConfig } = resolveConfig(options.agentId);
9398
- if (spawnConfig === void 0) {
9399
- throw new Error(`Agent "${agentId}" has no spawn config.`);
9400
- }
9401
- if (spawnConfig.kind !== "cli") {
9402
- throw new Error(`Agent "${agentId}" does not support CLI spawn.`);
9403
- }
9404
- if (!binaryName) {
9405
- throw new Error(`Agent "${agentId}" has no binaryName.`);
9406
- }
9407
- const mcpArgs = getMcpArgs(spawnConfig, options.mcpServers);
9408
- const mcpEnvVars = getMcpEnv(spawnConfig, options.mcpServers);
9409
- const defaultArgsPosition = getDefaultArgsPosition2(spawnConfig);
9410
- const mcpArgsPosition = getMcpArgsPosition2(spawnConfig);
9411
- const args = [];
9412
- if (mcpArgsPosition === "beforeCommand") {
9413
- args.push(...mcpArgs);
9414
- }
9415
- if (defaultArgsPosition === "beforePrompt") {
9416
- args.push(...spawnConfig.defaultArgs);
9417
- }
9418
- if (mcpArgsPosition === "beforePrompt") {
9419
- args.push(...mcpArgs);
9420
- }
9421
- args.push(spawnConfig.promptFlag);
9422
- const useStdin = !!options.useStdin && !!spawnConfig.stdinMode;
9423
- if (!useStdin || !spawnConfig.stdinMode?.omitPrompt) {
9424
- args.push(options.prompt);
9425
- }
9426
- if (options.model && spawnConfig.modelFlag) {
9427
- let model = spawnConfig.modelStripProviderPrefix ? stripModelNamespace(options.model) : options.model;
9428
- if (spawnConfig.modelTransform) model = spawnConfig.modelTransform(model);
9429
- args.push(spawnConfig.modelFlag, model);
9430
- }
9431
- if (defaultArgsPosition === "afterPrompt") {
9432
- args.push(...spawnConfig.defaultArgs);
9433
- }
9434
- if (mcpArgsPosition === "afterCommand") {
9435
- args.push(...mcpArgs);
9568
+ function assertOneBasedLineNumber(line) {
9569
+ if (line === null || line === void 0) {
9570
+ return;
9436
9571
  }
9437
- const modeResolved = resolveModeConfig(spawnConfig.modes[options.mode ?? "yolo"]);
9438
- args.push(...modeResolved.args);
9439
- if (useStdin) {
9440
- args.push(...spawnConfig.stdinMode.extraArgs);
9572
+ if (!Number.isInteger(line) || line < 1) {
9573
+ throw invalidParams('"line" must be a 1-based integer');
9441
9574
  }
9442
- if (options.args && options.args.length > 0) {
9443
- args.push(...options.args);
9575
+ }
9576
+ function assertExtensionMethod2(method) {
9577
+ if (!method.startsWith("_")) {
9578
+ throw new Error('Extension method must start with "_"');
9444
9579
  }
9445
- const envOverrides = { ...mcpEnvVars, ...modeResolved.env };
9446
- const child = spawnChildProcess3(binaryName, args, {
9447
- cwd: options.cwd,
9448
- stdio: ["pipe", "pipe", "pipe"],
9449
- env: Object.keys(envOverrides).length > 0 ? { ...process.env, ...envOverrides } : void 0
9450
- });
9451
- let aborted = false;
9452
- let timedOut = false;
9453
- const onAbort = () => {
9454
- aborted = true;
9455
- child.kill("SIGTERM");
9580
+ }
9581
+ function isInjectedTransportOptions(options) {
9582
+ return "transport" in options;
9583
+ }
9584
+ function createAsyncQueue() {
9585
+ const values = [];
9586
+ const waiters = [];
9587
+ let closed = false;
9588
+ let failure = null;
9589
+ const resolveOne = (value) => {
9590
+ const waiter = waiters.shift();
9591
+ if (!waiter) {
9592
+ return false;
9593
+ }
9594
+ waiter.resolve({ done: false, value });
9595
+ return true;
9456
9596
  };
9457
- options.signal?.addEventListener("abort", onAbort, { once: true });
9458
- let activityTimer;
9459
- const resetActivityTimer = options.activityTimeoutMs ? () => {
9460
- if (activityTimer) clearTimeout(activityTimer);
9461
- activityTimer = setTimeout(() => {
9462
- timedOut = true;
9463
- child.kill("SIGTERM");
9464
- }, options.activityTimeoutMs);
9465
- } : void 0;
9466
- resetActivityTimer?.();
9467
- const result = { stdout: "", stderr: "", exitCode: 1 };
9468
- child.stderr.setEncoding("utf8");
9469
- child.stderr.on("data", (chunk) => {
9470
- result.stderr += chunk;
9471
- resetActivityTimer?.();
9472
- });
9473
- if (useStdin) {
9474
- child.stdin.write(options.prompt);
9475
- }
9476
- child.stdin.end();
9477
- const adapter = getAdapter(spawnConfig.adapter);
9478
- const events = (async function* () {
9479
- for await (const output of adapter(readLines(child.stdout))) {
9480
- if (!isAcpEvent(output)) continue;
9481
- resetActivityTimer?.();
9482
- yield output;
9483
- }
9484
- })();
9485
- const done = new Promise((resolve2, reject) => {
9486
- child.on("error", (error2) => {
9487
- options.signal?.removeEventListener("abort", onAbort);
9488
- if (activityTimer) clearTimeout(activityTimer);
9489
- if (aborted) {
9490
- reject(createAbortError2());
9597
+ const iterator = {
9598
+ push(value) {
9599
+ if (closed || failure) {
9491
9600
  return;
9492
9601
  }
9493
- reject(error2);
9494
- });
9495
- child.on("close", (code) => {
9496
- options.signal?.removeEventListener("abort", onAbort);
9497
- if (activityTimer) clearTimeout(activityTimer);
9498
- if (aborted) {
9499
- reject(createAbortError2());
9602
+ if (!resolveOne(value)) {
9603
+ values.push(value);
9604
+ }
9605
+ },
9606
+ complete() {
9607
+ if (closed || failure) {
9500
9608
  return;
9501
9609
  }
9502
- if (timedOut) {
9503
- reject(createActivityTimeoutError2(options.activityTimeoutMs));
9610
+ closed = true;
9611
+ while (waiters.length > 0) {
9612
+ waiters.shift()?.resolve({ done: true, value: void 0 });
9613
+ }
9614
+ },
9615
+ fail(error2) {
9616
+ if (closed || failure) {
9504
9617
  return;
9505
9618
  }
9506
- result.exitCode = code ?? 1;
9507
- resolve2(result);
9508
- });
9509
- });
9510
- return { events, done };
9511
- }
9512
- var init_spawn2 = __esm({
9513
- "packages/agent-spawn/src/acp/spawn.ts"() {
9514
- "use strict";
9515
- init_adapters();
9516
- init_line_reader();
9517
- init_resolve_config();
9518
- init_mcp_args();
9519
- init_model_utils();
9520
- init_types2();
9521
- }
9522
- });
9523
-
9524
- // packages/poe-acp-client/src/types.ts
9525
- function isObjectRecord(value) {
9526
- return typeof value === "object" && value !== null && !Array.isArray(value);
9527
- }
9528
- function isAcpErrorCode(value) {
9529
- return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
9530
- }
9531
- function isAcpError(value) {
9532
- if (value instanceof AcpError) {
9533
- return true;
9534
- }
9535
- if (!isObjectRecord(value)) {
9536
- return false;
9537
- }
9538
- if (!isAcpErrorCode(value.code) || typeof value.message !== "string") {
9539
- return false;
9540
- }
9541
- return value.data === void 0 || Object.prototype.hasOwnProperty.call(value, "data");
9542
- }
9543
- var ACP_ERROR_CODE_PARSE, ACP_ERROR_CODE_INVALID_REQUEST, ACP_ERROR_CODE_METHOD_NOT_FOUND, ACP_ERROR_CODE_INVALID_PARAMS, ACP_ERROR_CODE_INTERNAL, ACP_ERROR_CODE_RESOURCE_NOT_FOUND, AcpError;
9544
- var init_types3 = __esm({
9545
- "packages/poe-acp-client/src/types.ts"() {
9546
- "use strict";
9547
- ACP_ERROR_CODE_PARSE = -32700;
9548
- ACP_ERROR_CODE_INVALID_REQUEST = -32600;
9549
- ACP_ERROR_CODE_METHOD_NOT_FOUND = -32601;
9550
- ACP_ERROR_CODE_INVALID_PARAMS = -32602;
9551
- ACP_ERROR_CODE_INTERNAL = -32603;
9552
- ACP_ERROR_CODE_RESOURCE_NOT_FOUND = -32002;
9553
- AcpError = class extends Error {
9554
- code;
9555
- data;
9556
- constructor(code, message2, data) {
9557
- super(message2);
9558
- this.name = "AcpError";
9559
- this.code = code;
9560
- if (data !== void 0) {
9561
- this.data = data;
9562
- }
9619
+ failure = error2;
9620
+ while (waiters.length > 0) {
9621
+ waiters.shift()?.reject(error2);
9563
9622
  }
9564
- };
9565
- }
9566
- });
9567
-
9568
- // packages/poe-acp-client/src/jsonrpc-message-layer.ts
9569
- function isObjectRecord2(value) {
9570
- return typeof value === "object" && value !== null && !Array.isArray(value);
9571
- }
9572
- function hasOwn2(value, property) {
9573
- return Object.prototype.hasOwnProperty.call(value, property);
9574
- }
9575
- function isRequestId(value) {
9576
- return value === null || typeof value === "string" || typeof value === "number";
9577
- }
9578
- function toRequestId(value) {
9579
- return isRequestId(value) ? value : null;
9580
- }
9581
- function parseError() {
9582
- return new AcpError(ACP_ERROR_CODE_PARSE, "Parse error");
9583
- }
9584
- function invalidRequest() {
9585
- return new AcpError(ACP_ERROR_CODE_INVALID_REQUEST, "Invalid Request");
9586
- }
9587
- function methodNotFound(method) {
9588
- return new AcpError(
9589
- ACP_ERROR_CODE_METHOD_NOT_FOUND,
9590
- `Method not found: "${method}"`
9591
- );
9592
- }
9593
- function internalError(message2) {
9594
- return new AcpError(ACP_ERROR_CODE_INTERNAL, message2);
9595
- }
9596
- function isJsonRpcErrorObject(value) {
9597
- if (!isObjectRecord2(value)) {
9598
- return false;
9599
- }
9600
- if (!isAcpErrorCode(value.code) || typeof value.message !== "string") {
9601
- return false;
9602
- }
9603
- return value.data === void 0 || hasOwn2(value, "data");
9604
- }
9605
- function toResponseError(error2) {
9606
- return new AcpError(error2.code, error2.message, error2.data);
9607
- }
9608
- function toDispatchError(error2) {
9609
- if (error2 instanceof AcpError) {
9610
- return error2;
9611
- }
9612
- if (isAcpError(error2)) {
9613
- return new AcpError(error2.code, error2.message, error2.data);
9614
- }
9615
- if (error2 instanceof Error && error2.message.length > 0) {
9616
- return internalError(error2.message);
9617
- }
9618
- return internalError("Internal error");
9619
- }
9620
- function chunkToString2(chunk) {
9621
- if (typeof chunk === "string") {
9622
- return chunk;
9623
- }
9624
- if (chunk instanceof Uint8Array) {
9625
- return Buffer.from(chunk).toString("utf8");
9626
- }
9627
- return String(chunk);
9628
- }
9629
- function normalizeLine(line) {
9630
- return line.endsWith("\r") ? line.slice(0, -1) : line;
9631
- }
9632
- async function* readLines2(stream) {
9633
- let buffer = "";
9634
- for await (const chunk of stream) {
9635
- buffer += chunkToString2(chunk);
9636
- while (true) {
9637
- const newlineIndex = buffer.indexOf("\n");
9638
- if (newlineIndex === -1) {
9639
- break;
9623
+ },
9624
+ async next() {
9625
+ if (values.length > 0) {
9626
+ const value = values.shift();
9627
+ return { done: false, value };
9640
9628
  }
9641
- const line = buffer.slice(0, newlineIndex);
9642
- buffer = buffer.slice(newlineIndex + 1);
9643
- yield normalizeLine(line);
9644
- }
9645
- }
9646
- if (buffer.length > 0) {
9647
- yield normalizeLine(buffer);
9648
- }
9649
- }
9650
- function createResponseMessage(id, result) {
9651
- return {
9652
- jsonrpc: "2.0",
9653
- id,
9654
- result: result === void 0 ? null : result
9655
- };
9656
- }
9657
- function createJsonRpcErrorResponse(id, error2) {
9658
- const response = {
9659
- jsonrpc: "2.0",
9660
- id,
9661
- error: {
9662
- code: error2.code,
9663
- message: error2.message
9629
+ if (failure) {
9630
+ throw failure;
9631
+ }
9632
+ if (closed) {
9633
+ return { done: true, value: void 0 };
9634
+ }
9635
+ return new Promise((resolve2, reject) => {
9636
+ waiters.push({ resolve: resolve2, reject });
9637
+ });
9638
+ },
9639
+ async return() {
9640
+ iterator.complete();
9641
+ return { done: true, value: void 0 };
9642
+ },
9643
+ async throw(error2) {
9644
+ const normalizedError = toError(error2);
9645
+ iterator.fail(normalizedError);
9646
+ throw normalizedError;
9647
+ },
9648
+ [Symbol.asyncIterator]() {
9649
+ return iterator;
9664
9650
  }
9665
9651
  };
9666
- if (error2.data !== void 0) {
9667
- response.error.data = error2.data;
9668
- }
9669
- return response;
9670
- }
9671
- function serializeJsonRpcMessage(message2) {
9672
- return `${JSON.stringify(message2)}
9673
- `;
9652
+ return iterator;
9674
9653
  }
9675
- function parseJsonRpcMessage(line) {
9676
- let parsed;
9677
- try {
9678
- parsed = JSON.parse(line);
9679
- } catch {
9680
- return {
9681
- type: "invalid",
9682
- id: null,
9683
- error: parseError()
9684
- };
9685
- }
9686
- if (!isObjectRecord2(parsed)) {
9687
- return {
9688
- type: "invalid",
9689
- id: null,
9690
- error: invalidRequest()
9691
- };
9692
- }
9693
- const id = toRequestId(parsed.id);
9694
- if (parsed.jsonrpc !== "2.0") {
9695
- return {
9696
- type: "invalid",
9697
- id,
9698
- error: invalidRequest()
9699
- };
9700
- }
9701
- const hasMethod = hasOwn2(parsed, "method");
9702
- const hasId = hasOwn2(parsed, "id");
9703
- if (hasMethod) {
9704
- if (typeof parsed.method !== "string") {
9705
- return {
9706
- type: "invalid",
9707
- id,
9708
- error: invalidRequest()
9709
- };
9710
- }
9711
- if (hasId) {
9712
- if (!isRequestId(parsed.id)) {
9713
- return {
9714
- type: "invalid",
9715
- id: null,
9716
- error: invalidRequest()
9717
- };
9718
- }
9719
- const request = {
9720
- jsonrpc: "2.0",
9721
- id: parsed.id,
9722
- method: parsed.method
9723
- };
9724
- if (hasOwn2(parsed, "params")) {
9725
- request.params = parsed.params;
9726
- }
9727
- return { type: "request", message: request };
9728
- }
9729
- const notification = {
9730
- jsonrpc: "2.0",
9731
- method: parsed.method
9732
- };
9733
- if (hasOwn2(parsed, "params")) {
9734
- notification.params = parsed.params;
9735
- }
9736
- return {
9737
- type: "notification",
9738
- message: notification
9739
- };
9740
- }
9741
- if (!hasId || !isRequestId(parsed.id)) {
9742
- return {
9743
- type: "invalid",
9744
- id,
9745
- error: invalidRequest()
9746
- };
9747
- }
9748
- const hasResult = hasOwn2(parsed, "result");
9749
- const hasError = hasOwn2(parsed, "error");
9750
- if (hasResult === hasError) {
9751
- return {
9752
- type: "invalid",
9753
- id: parsed.id,
9754
- error: invalidRequest()
9755
- };
9756
- }
9757
- if (hasResult) {
9758
- return {
9759
- type: "response",
9760
- message: {
9761
- jsonrpc: "2.0",
9762
- id: parsed.id,
9763
- result: parsed.result
9764
- }
9765
- };
9766
- }
9767
- if (!isJsonRpcErrorObject(parsed.error)) {
9768
- return {
9769
- type: "invalid",
9770
- id: parsed.id,
9771
- error: invalidRequest()
9772
- };
9773
- }
9774
- return {
9775
- type: "response",
9776
- message: {
9777
- jsonrpc: "2.0",
9778
- id: parsed.id,
9779
- error: parsed.error
9780
- }
9781
- };
9782
- }
9783
- var JsonRpcMessageLayer;
9784
- var init_jsonrpc_message_layer = __esm({
9785
- "packages/poe-acp-client/src/jsonrpc-message-layer.ts"() {
9654
+ var AcpClient;
9655
+ var init_acp_client = __esm({
9656
+ "packages/poe-acp-client/src/acp-client.ts"() {
9786
9657
  "use strict";
9658
+ init_acp_transport();
9787
9659
  init_types3();
9788
- JsonRpcMessageLayer = class {
9789
- input;
9790
- output;
9791
- requestHandlers = /* @__PURE__ */ new Map();
9792
- notificationHandlers = /* @__PURE__ */ new Map();
9793
- pending = /* @__PURE__ */ new Map();
9794
- nextRequestId;
9660
+ AcpClient = class {
9661
+ transport;
9662
+ clientProtocolVersion;
9663
+ clientCapabilities;
9664
+ clientInfo;
9665
+ skipAuth;
9666
+ permissionHandler;
9667
+ fsHandler;
9668
+ terminalHandler;
9669
+ activePromptUpdates = /* @__PURE__ */ new Map();
9670
+ trackedTerminalIds = /* @__PURE__ */ new Map();
9671
+ hasRegisteredFsReadHandler = false;
9672
+ hasRegisteredFsWriteHandler = false;
9673
+ hasRegisteredTerminalHandlers = false;
9795
9674
  disposed = false;
9675
+ lifecycleState = "uninitialized";
9676
+ negotiatedVersion = null;
9677
+ availableAuthMethods = [];
9678
+ negotiatedAgentCapabilities;
9679
+ negotiatedAgentInfo;
9796
9680
  constructor(options) {
9797
- this.input = options.input;
9798
- this.output = options.output;
9799
- this.nextRequestId = options.firstRequestId ?? 1;
9800
- if (!Number.isFinite(this.nextRequestId)) {
9801
- throw new Error("firstRequestId must be a finite number");
9802
- }
9803
- void this.consumeInput();
9681
+ this.transport = isInjectedTransportOptions(options) ? options.transport : new AcpTransport({
9682
+ command: options.command,
9683
+ args: options.args,
9684
+ cwd: options.cwd,
9685
+ env: options.env,
9686
+ firstRequestId: options.firstRequestId,
9687
+ spawn: options.spawn
9688
+ });
9689
+ this.clientProtocolVersion = options.protocolVersion ?? 1;
9690
+ this.clientCapabilities = options.clientCapabilities;
9691
+ this.clientInfo = options.clientInfo;
9692
+ this.skipAuth = options.skipAuth ?? false;
9693
+ this.permissionHandler = options.handlers?.permission ?? options.permissionHandler;
9694
+ this.fsHandler = options.handlers?.fs ?? options.fsHandler;
9695
+ this.terminalHandler = options.handlers?.terminal ?? options.terminalHandler;
9696
+ const autoApprove = options.autoApprove === true && !this.permissionHandler;
9697
+ this.transport.onRequest(
9698
+ "session/request_permission",
9699
+ async (params) => {
9700
+ if (this.permissionHandler) {
9701
+ const outcome = await this.permissionHandler({
9702
+ toolCall: params.toolCall,
9703
+ options: params.options
9704
+ });
9705
+ return { outcome };
9706
+ }
9707
+ if (autoApprove) {
9708
+ const allow = params.options.find((o) => o.kind === "allow_always") ?? params.options.find((o) => o.kind === "allow_once");
9709
+ if (allow) {
9710
+ return { outcome: { outcome: "selected", optionId: allow.optionId } };
9711
+ }
9712
+ }
9713
+ return { outcome: { outcome: "cancelled" } };
9714
+ }
9715
+ );
9716
+ this.registerCapabilityHandlers(this.clientCapabilities);
9717
+ this.transport.onNotification("session/update", (params) => {
9718
+ this.handleSessionUpdateNotification(params);
9719
+ });
9804
9720
  }
9805
- onRequest(method, handler) {
9806
- this.requestHandlers.set(method, handler);
9721
+ get state() {
9722
+ return this.lifecycleState;
9807
9723
  }
9808
- onNotification(method, handler) {
9809
- this.notificationHandlers.set(method, handler);
9724
+ get negotiatedProtocolVersion() {
9725
+ return this.negotiatedVersion;
9810
9726
  }
9811
- pendingRequestCount() {
9812
- return this.pending.size;
9727
+ get authMethods() {
9728
+ return [...this.availableAuthMethods];
9813
9729
  }
9814
- sendNotification(method, params) {
9815
- const notification = {
9816
- jsonrpc: "2.0",
9817
- method
9818
- };
9819
- if (params !== void 0) {
9820
- notification.params = params;
9821
- }
9822
- this.sendMessage(notification);
9730
+ get agentCapabilities() {
9731
+ return this.negotiatedAgentCapabilities;
9823
9732
  }
9824
- sendRequest(method, params, options = {}) {
9825
- if (this.disposed) {
9826
- throw new Error("JSON-RPC message layer is disposed");
9827
- }
9828
- const id = options.id === void 0 ? this.nextRequestId++ : options.id;
9829
- if (this.pending.has(id)) {
9830
- throw new Error(`A request with id ${JSON.stringify(id)} is already pending`);
9733
+ get agentInfo() {
9734
+ return this.negotiatedAgentInfo;
9735
+ }
9736
+ get closed() {
9737
+ return this.transport.closed;
9738
+ }
9739
+ async initialize(clientCapabilities) {
9740
+ if (this.lifecycleState !== "uninitialized") {
9741
+ throw new Error("initialize() can only be called once.");
9831
9742
  }
9832
- const request = {
9833
- jsonrpc: "2.0",
9834
- id,
9835
- method
9836
- };
9837
- if (params !== void 0) {
9838
- request.params = params;
9743
+ if (clientCapabilities !== void 0) {
9744
+ this.clientCapabilities = clientCapabilities;
9745
+ this.registerCapabilityHandlers(clientCapabilities);
9839
9746
  }
9840
- return new Promise((resolve2, reject) => {
9841
- this.pending.set(id, {
9842
- method,
9843
- resolve: resolve2,
9844
- reject
9845
- });
9846
- try {
9847
- this.sendMessage(request);
9848
- } catch (error2) {
9849
- this.pending.delete(id);
9850
- reject(error2);
9851
- }
9747
+ const response = await this.transport.sendRequest("initialize", {
9748
+ protocolVersion: this.clientProtocolVersion,
9749
+ clientInfo: this.clientInfo,
9750
+ clientCapabilities: this.clientCapabilities
9852
9751
  });
9752
+ const negotiatedProtocolVersion = Math.min(
9753
+ this.clientProtocolVersion,
9754
+ response.protocolVersion
9755
+ );
9756
+ this.negotiatedVersion = negotiatedProtocolVersion;
9757
+ this.negotiatedAgentCapabilities = response.agentCapabilities;
9758
+ this.negotiatedAgentInfo = response.agentInfo;
9759
+ this.availableAuthMethods = response.authMethods ? [...response.authMethods] : [];
9760
+ const requiresAuth = this.availableAuthMethods.length > 0 && !this.skipAuth;
9761
+ this.lifecycleState = requiresAuth ? "initialized" : "ready";
9762
+ return {
9763
+ protocolVersion: negotiatedProtocolVersion,
9764
+ ...this.negotiatedAgentCapabilities !== void 0 ? { agentCapabilities: this.negotiatedAgentCapabilities } : {},
9765
+ ...this.negotiatedAgentInfo !== void 0 ? { agentInfo: this.negotiatedAgentInfo } : {},
9766
+ ...this.availableAuthMethods.length > 0 ? { authMethods: this.authMethods } : {}
9767
+ };
9853
9768
  }
9854
- dispose(reason = new Error("JSON-RPC message layer disposed")) {
9855
- if (this.disposed) {
9856
- return;
9769
+ async authenticate(methodId) {
9770
+ if (this.lifecycleState === "uninitialized") {
9771
+ throw new Error("Cannot authenticate before initialize().");
9857
9772
  }
9858
- this.disposed = true;
9859
- this.rejectAllPending(reason);
9860
- }
9861
- async consumeInput() {
9862
- try {
9863
- for await (const line of readLines2(this.input)) {
9864
- if (this.disposed || line.length === 0) {
9865
- continue;
9866
- }
9867
- await this.handleIncomingLine(line);
9868
- }
9869
- if (!this.disposed) {
9870
- this.dispose(new Error("JSON-RPC input stream closed"));
9871
- }
9872
- } catch (error2) {
9873
- if (!this.disposed) {
9874
- this.dispose(
9875
- error2 instanceof Error ? error2 : new Error(`JSON-RPC input stream failed: ${String(error2)}`)
9876
- );
9877
- }
9878
- }
9879
- }
9880
- async handleIncomingLine(line) {
9881
- const parsed = parseJsonRpcMessage(line);
9882
- if (parsed.type === "invalid") {
9883
- this.sendMessage(createJsonRpcErrorResponse(parsed.id, parsed.error));
9884
- return;
9885
- }
9886
- if (parsed.type === "response") {
9887
- this.handleResponse(parsed.message);
9888
- return;
9889
- }
9890
- if (parsed.type === "notification") {
9891
- await this.handleNotification(parsed.message);
9892
- return;
9893
- }
9894
- await this.handleRequest(parsed.message);
9895
- }
9896
- handleResponse(message2) {
9897
- const pending = this.pending.get(message2.id);
9898
- if (!pending) {
9899
- return;
9900
- }
9901
- this.pending.delete(message2.id);
9902
- if ("error" in message2) {
9903
- pending.reject(toResponseError(message2.error));
9904
- return;
9905
- }
9906
- pending.resolve(message2.result);
9907
- }
9908
- async handleRequest(message2) {
9909
- const handler = this.requestHandlers.get(message2.method);
9910
- if (!handler) {
9911
- this.sendMessage(createJsonRpcErrorResponse(message2.id, methodNotFound(message2.method)));
9912
- return;
9913
- }
9914
- try {
9915
- const result = await handler(message2.params, {
9916
- id: message2.id,
9917
- method: message2.method
9918
- });
9919
- this.sendMessage(createResponseMessage(message2.id, result));
9920
- } catch (error2) {
9921
- this.sendMessage(createJsonRpcErrorResponse(message2.id, toDispatchError(error2)));
9922
- }
9923
- }
9924
- async handleNotification(message2) {
9925
- const handler = this.notificationHandlers.get(message2.method);
9926
- if (!handler) {
9927
- return;
9928
- }
9929
- try {
9930
- await handler(message2.params, { method: message2.method });
9931
- } catch {
9932
- }
9933
- }
9934
- sendMessage(message2) {
9935
- if (this.disposed) {
9936
- throw new Error("JSON-RPC message layer is disposed");
9773
+ if (this.lifecycleState === "ready") {
9774
+ throw new Error("Authentication is not required for this agent.");
9937
9775
  }
9938
- this.output.write(serializeJsonRpcMessage(message2));
9939
- }
9940
- rejectAllPending(error2) {
9941
- for (const pending of this.pending.values()) {
9942
- pending.reject(error2);
9776
+ if (!this.availableAuthMethods.some((authMethod) => authMethod.id === methodId)) {
9777
+ throw new Error(`Unknown auth method "${methodId}".`);
9943
9778
  }
9944
- this.pending.clear();
9779
+ const response = await this.transport.sendRequest("authenticate", {
9780
+ methodId
9781
+ });
9782
+ this.lifecycleState = "ready";
9783
+ return response;
9945
9784
  }
9946
- };
9947
- }
9948
- });
9949
-
9950
- // packages/poe-acp-client/src/acp-transport.ts
9951
- import {
9952
- spawn as spawnChildProcess4
9953
- } from "node:child_process";
9954
- function assertExtensionMethod(method) {
9955
- if (!method.startsWith("_")) {
9956
- throw new Error('Extension method must start with "_"');
9957
- }
9958
- }
9959
- var AcpTransport;
9960
- var init_acp_transport = __esm({
9961
- "packages/poe-acp-client/src/acp-transport.ts"() {
9962
- "use strict";
9963
- init_jsonrpc_message_layer();
9964
- AcpTransport = class {
9965
- closed;
9966
- command;
9967
- child;
9968
- layer;
9969
- stderrChunks = [];
9970
- resolveClosed = null;
9971
- closeEvent = null;
9972
- closeReason = null;
9973
- constructor(options) {
9974
- const {
9975
- command,
9976
- args = [],
9785
+ async newSession(cwd, mcpServers) {
9786
+ this.assertReady("session/new");
9787
+ this.assertMcpServerCapabilitySupport(mcpServers);
9788
+ return this.transport.sendRequest("session/new", {
9977
9789
  cwd,
9978
- env,
9979
- firstRequestId,
9980
- spawn: spawn9 = spawnChildProcess4
9981
- } = options;
9982
- this.command = command;
9983
- this.closed = new Promise((resolve2) => {
9984
- this.resolveClosed = resolve2;
9790
+ mcpServers
9985
9791
  });
9986
- this.child = spawn9(command, [...args], {
9792
+ }
9793
+ async loadSession(sessionId, cwd, mcpServers) {
9794
+ this.assertReady("session/load");
9795
+ if (this.negotiatedAgentCapabilities?.loadSession !== true) {
9796
+ throw new Error(
9797
+ 'Cannot call "session/load" because the agent does not support session loading.'
9798
+ );
9799
+ }
9800
+ this.assertMcpServerCapabilitySupport(mcpServers);
9801
+ return this.transport.sendRequest("session/load", {
9802
+ sessionId,
9987
9803
  cwd,
9988
- env,
9989
- stdio: ["pipe", "pipe", "pipe"]
9990
- });
9991
- this.child.stderr.setEncoding("utf8");
9992
- this.child.stderr.on("data", (chunk) => {
9993
- this.stderrChunks.push(String(chunk));
9994
- });
9995
- this.child.stdin.on("error", (error2) => {
9996
- const reason = error2 instanceof Error ? error2 : new Error(String(error2));
9997
- this.close(reason, this.child.exitCode ?? null, this.child.signalCode ?? null);
9804
+ mcpServers
9998
9805
  });
9999
- this.layer = new JsonRpcMessageLayer({
10000
- input: this.child.stdout,
10001
- output: this.child.stdin,
10002
- firstRequestId
9806
+ }
9807
+ async cancelSession(sessionId) {
9808
+ this.assertReady("session/cancel");
9809
+ const payload = { sessionId };
9810
+ this.transport.sendNotification("session/cancel", payload);
9811
+ }
9812
+ async setMode(sessionId, modeId) {
9813
+ this.assertReady("session/set_mode");
9814
+ return this.transport.sendRequest("session/set_mode", {
9815
+ sessionId,
9816
+ modeId
10003
9817
  });
10004
- this.child.once("error", (error2) => {
10005
- const reason = error2 instanceof Error ? error2 : new Error(String(error2));
10006
- this.close(reason, this.child.exitCode ?? null, this.child.signalCode ?? null);
9818
+ }
9819
+ async setConfigOption(sessionId, configId, value) {
9820
+ this.assertReady("session/set_config_option");
9821
+ const response = await this.transport.sendRequest("session/set_config_option", {
9822
+ sessionId,
9823
+ configId,
9824
+ value
10007
9825
  });
10008
- this.child.once("close", (code, signal) => {
10009
- const reason = this.closeReason ?? new Error(
10010
- `ACP transport closed (command "${this.command}", code: ${code ?? "null"}${signal ? `, signal: ${signal}` : ""})`
9826
+ return response.configOptions;
9827
+ }
9828
+ prompt(sessionId, content) {
9829
+ this.assertReady("session/prompt");
9830
+ this.assertPromptContentCapabilitySupport(content);
9831
+ if (this.activePromptUpdates.has(sessionId)) {
9832
+ throw new Error(
9833
+ `Cannot call "session/prompt" while another prompt is in progress for session "${sessionId}".`
10011
9834
  );
10012
- this.close(reason, code ?? null, signal ?? null);
9835
+ }
9836
+ const updates = createAsyncQueue();
9837
+ this.activePromptUpdates.set(sessionId, updates);
9838
+ let requestPromise;
9839
+ try {
9840
+ requestPromise = this.transport.sendRequest("session/prompt", {
9841
+ sessionId,
9842
+ prompt: content
9843
+ });
9844
+ } catch (error2) {
9845
+ const normalizedError = toError(error2);
9846
+ this.activePromptUpdates.delete(sessionId);
9847
+ updates.fail(normalizedError);
9848
+ throw normalizedError;
9849
+ }
9850
+ const response = requestPromise.then((promptResponse) => {
9851
+ this.activePromptUpdates.delete(sessionId);
9852
+ updates.complete();
9853
+ return promptResponse;
9854
+ }).catch((error2) => {
9855
+ const normalizedError = toError(error2);
9856
+ this.activePromptUpdates.delete(sessionId);
9857
+ updates.fail(normalizedError);
9858
+ throw normalizedError;
10013
9859
  });
9860
+ return {
9861
+ response,
9862
+ [Symbol.asyncIterator]() {
9863
+ return updates;
9864
+ }
9865
+ };
10014
9866
  }
10015
- sendRequest(method, params, options = {}) {
10016
- return this.layer.sendRequest(method, params, options);
10017
- }
10018
- sendExtRequest(method, params, options = {}) {
10019
- assertExtensionMethod(method);
10020
- return this.layer.sendRequest(method, params, options);
10021
- }
10022
- sendNotification(method, params) {
10023
- this.layer.sendNotification(method, params);
10024
- }
10025
- sendExtNotification(method, params) {
10026
- assertExtensionMethod(method);
10027
- this.layer.sendNotification(method, params);
9867
+ async sendExtRequest(method, params, options = {}) {
9868
+ assertExtensionMethod2(method);
9869
+ return this.transport.sendRequest(method, params, options);
10028
9870
  }
10029
- onRequest(method, handler) {
10030
- this.layer.onRequest(method, handler);
9871
+ async sendExtNotification(method, params) {
9872
+ assertExtensionMethod2(method);
9873
+ this.transport.sendNotification(method, params);
10031
9874
  }
10032
9875
  onExtRequest(method, handler) {
10033
- assertExtensionMethod(method);
10034
- this.layer.onRequest(method, handler);
10035
- }
10036
- onNotification(method, handler) {
10037
- this.layer.onNotification(method, handler);
9876
+ assertExtensionMethod2(method);
9877
+ this.transport.onRequest(method, handler);
10038
9878
  }
10039
9879
  onExtNotification(method, handler) {
10040
- assertExtensionMethod(method);
10041
- this.layer.onNotification(method, handler);
10042
- }
10043
- getStderrOutput() {
10044
- return this.stderrChunks.join("");
9880
+ assertExtensionMethod2(method);
9881
+ this.transport.onNotification(method, handler);
10045
9882
  }
10046
- pendingRequestCount() {
10047
- return this.layer.pendingRequestCount();
9883
+ async dispose() {
9884
+ if (this.disposed) {
9885
+ if (this.transport.closed) {
9886
+ await this.transport.closed;
9887
+ }
9888
+ return;
9889
+ }
9890
+ this.disposed = true;
9891
+ const disposeReason = new Error("ACP client disposed");
9892
+ for (const updates of this.activePromptUpdates.values()) {
9893
+ updates.fail(disposeReason);
9894
+ }
9895
+ this.activePromptUpdates.clear();
9896
+ if (typeof this.transport.dispose === "function") {
9897
+ this.transport.dispose(disposeReason);
9898
+ }
9899
+ if (this.transport.closed) {
9900
+ await this.transport.closed;
9901
+ }
10048
9902
  }
10049
- dispose(reason = new Error("ACP transport disposed")) {
10050
- if (this.closeEvent !== null) {
9903
+ assertReady(operation) {
9904
+ if (this.lifecycleState === "ready") {
10051
9905
  return;
10052
9906
  }
10053
- this.closeReason = reason;
10054
- this.layer.dispose(reason);
10055
- if (!this.child.stdin.destroyed && !this.child.stdin.writableEnded) {
10056
- this.child.stdin.end();
9907
+ if (this.lifecycleState === "uninitialized") {
9908
+ throw new Error(`Cannot call "${operation}" before initialize().`);
10057
9909
  }
10058
- if (this.child.exitCode !== null || this.child.signalCode !== null) {
10059
- this.close(reason, this.child.exitCode, this.child.signalCode);
9910
+ throw new Error(`Cannot call "${operation}" before authentication completes.`);
9911
+ }
9912
+ registerCapabilityHandlers(capabilities) {
9913
+ if (!this.hasRegisteredFsReadHandler && capabilities?.fs?.readTextFile === true && this.fsHandler?.readTextFile) {
9914
+ const readTextFile = this.fsHandler.readTextFile;
9915
+ this.transport.onRequest(
9916
+ "fs/read_text_file",
9917
+ async (params) => {
9918
+ assertAbsolutePath(params.path);
9919
+ assertOneBasedLineNumber(params.line);
9920
+ const content = await readTextFile({
9921
+ sessionId: params.sessionId,
9922
+ path: params.path,
9923
+ line: params.line,
9924
+ limit: params.limit
9925
+ });
9926
+ return { content };
9927
+ }
9928
+ );
9929
+ this.hasRegisteredFsReadHandler = true;
9930
+ }
9931
+ if (!this.hasRegisteredFsWriteHandler && capabilities?.fs?.writeTextFile === true && this.fsHandler?.writeTextFile) {
9932
+ const writeTextFile = this.fsHandler.writeTextFile;
9933
+ this.transport.onRequest(
9934
+ "fs/write_text_file",
9935
+ async (params) => {
9936
+ assertAbsolutePath(params.path);
9937
+ await writeTextFile({
9938
+ sessionId: params.sessionId,
9939
+ path: params.path,
9940
+ content: params.content
9941
+ });
9942
+ return {};
9943
+ }
9944
+ );
9945
+ this.hasRegisteredFsWriteHandler = true;
9946
+ }
9947
+ if (!this.hasRegisteredTerminalHandlers && capabilities?.terminal === true && this.terminalHandler) {
9948
+ const terminalHandler = this.terminalHandler;
9949
+ this.transport.onRequest(
9950
+ "terminal/create",
9951
+ async (params) => {
9952
+ const terminalId = await terminalHandler.create({
9953
+ sessionId: params.sessionId,
9954
+ command: params.command,
9955
+ args: params.args,
9956
+ cwd: params.cwd,
9957
+ env: params.env,
9958
+ outputByteLimit: params.outputByteLimit
9959
+ });
9960
+ this.trackTerminal(params.sessionId, terminalId);
9961
+ return { terminalId };
9962
+ }
9963
+ );
9964
+ this.transport.onRequest(
9965
+ "terminal/output",
9966
+ async (params) => {
9967
+ this.assertKnownTerminal(params.sessionId, params.terminalId);
9968
+ return terminalHandler.output({
9969
+ sessionId: params.sessionId,
9970
+ terminalId: params.terminalId
9971
+ });
9972
+ }
9973
+ );
9974
+ this.transport.onRequest(
9975
+ "terminal/wait_for_exit",
9976
+ async (params) => {
9977
+ this.assertKnownTerminal(params.sessionId, params.terminalId);
9978
+ return terminalHandler.waitForExit({
9979
+ sessionId: params.sessionId,
9980
+ terminalId: params.terminalId
9981
+ });
9982
+ }
9983
+ );
9984
+ this.transport.onRequest(
9985
+ "terminal/kill",
9986
+ async (params) => {
9987
+ this.assertKnownTerminal(params.sessionId, params.terminalId);
9988
+ await terminalHandler.kill({
9989
+ sessionId: params.sessionId,
9990
+ terminalId: params.terminalId
9991
+ });
9992
+ return {};
9993
+ }
9994
+ );
9995
+ this.transport.onRequest(
9996
+ "terminal/release",
9997
+ async (params) => {
9998
+ this.assertKnownTerminal(params.sessionId, params.terminalId);
9999
+ await terminalHandler.release({
10000
+ sessionId: params.sessionId,
10001
+ terminalId: params.terminalId
10002
+ });
10003
+ this.untrackTerminal(params.sessionId, params.terminalId);
10004
+ return {};
10005
+ }
10006
+ );
10007
+ this.hasRegisteredTerminalHandlers = true;
10008
+ }
10009
+ }
10010
+ assertMcpServerCapabilitySupport(mcpServers) {
10011
+ const mcpCapabilities = this.negotiatedAgentCapabilities?.mcpCapabilities;
10012
+ for (const mcpServer of mcpServers) {
10013
+ if (!("type" in mcpServer)) {
10014
+ continue;
10015
+ }
10016
+ if (mcpServer.type === "http" && mcpCapabilities?.http !== true) {
10017
+ throw new Error('Agent does not support MCP server type "http".');
10018
+ }
10019
+ if (mcpServer.type === "sse" && mcpCapabilities?.sse !== true) {
10020
+ throw new Error('Agent does not support MCP server type "sse".');
10021
+ }
10022
+ }
10023
+ }
10024
+ handleSessionUpdateNotification(notification) {
10025
+ const activePrompt = this.activePromptUpdates.get(notification.sessionId);
10026
+ if (!activePrompt) {
10060
10027
  return;
10061
10028
  }
10062
- const killed = this.child.kill();
10063
- if (!killed) {
10064
- this.close(reason, this.child.exitCode, this.child.signalCode);
10029
+ activePrompt.push({
10030
+ jsonrpc: "2.0",
10031
+ method: "session/update",
10032
+ params: notification
10033
+ });
10034
+ }
10035
+ trackTerminal(sessionId, terminalId) {
10036
+ const sessionTerminals = this.trackedTerminalIds.get(sessionId);
10037
+ if (sessionTerminals) {
10038
+ sessionTerminals.add(terminalId);
10039
+ return;
10065
10040
  }
10041
+ this.trackedTerminalIds.set(sessionId, /* @__PURE__ */ new Set([terminalId]));
10066
10042
  }
10067
- close(reason, code, signal) {
10068
- if (this.closeEvent !== null) {
10043
+ assertKnownTerminal(sessionId, terminalId) {
10044
+ const sessionTerminals = this.trackedTerminalIds.get(sessionId);
10045
+ if (sessionTerminals?.has(terminalId) === true) {
10069
10046
  return;
10070
10047
  }
10071
- this.layer.dispose(reason);
10072
- this.closeEvent = {
10073
- code,
10074
- signal,
10075
- reason,
10076
- stderr: this.getStderrOutput()
10077
- };
10078
- this.resolveClosed?.(this.closeEvent);
10079
- this.resolveClosed = null;
10048
+ throw resourceNotFound(`terminal "${terminalId}"`);
10049
+ }
10050
+ untrackTerminal(sessionId, terminalId) {
10051
+ const sessionTerminals = this.trackedTerminalIds.get(sessionId);
10052
+ if (!sessionTerminals) {
10053
+ return;
10054
+ }
10055
+ sessionTerminals.delete(terminalId);
10056
+ if (sessionTerminals.size === 0) {
10057
+ this.trackedTerminalIds.delete(sessionId);
10058
+ }
10059
+ }
10060
+ assertPromptContentCapabilitySupport(content) {
10061
+ const promptCapabilities = this.negotiatedAgentCapabilities?.promptCapabilities;
10062
+ for (const block of content) {
10063
+ if (block.type === "image" && promptCapabilities?.image !== true) {
10064
+ throw new Error('Agent does not support prompt content type "image".');
10065
+ }
10066
+ if (block.type === "audio" && promptCapabilities?.audio !== true) {
10067
+ throw new Error('Agent does not support prompt content type "audio".');
10068
+ }
10069
+ if (block.type === "resource" && promptCapabilities?.embeddedContext !== true) {
10070
+ throw new Error('Agent does not support prompt content type "resource".');
10071
+ }
10072
+ }
10080
10073
  }
10081
10074
  };
10082
10075
  }
10083
10076
  });
10084
10077
 
10085
- // packages/poe-acp-client/src/acp-client.ts
10086
- import { isAbsolute } from "node:path";
10087
- function toError(reason) {
10088
- return reason instanceof Error ? reason : new Error(String(reason));
10089
- }
10090
- function invalidParams(message2) {
10091
- return new AcpError(
10092
- ACP_ERROR_CODE_INVALID_PARAMS,
10093
- `Invalid params: ${message2}`
10094
- );
10095
- }
10096
- function resourceNotFound(resource) {
10097
- return new AcpError(
10098
- ACP_ERROR_CODE_RESOURCE_NOT_FOUND,
10099
- `Resource not found: ${resource}`
10100
- );
10101
- }
10102
- function assertAbsolutePath(path54) {
10103
- if (!isAbsolute(path54)) {
10104
- throw invalidParams('"path" must be an absolute path');
10105
- }
10106
- }
10107
- function assertOneBasedLineNumber(line) {
10108
- if (line === null || line === void 0) {
10109
- return;
10110
- }
10111
- if (!Number.isInteger(line) || line < 1) {
10112
- throw invalidParams('"line" must be a 1-based integer');
10078
+ // packages/poe-acp-client/src/jsonrpc.ts
10079
+ var init_jsonrpc = __esm({
10080
+ "packages/poe-acp-client/src/jsonrpc.ts"() {
10081
+ "use strict";
10113
10082
  }
10114
- }
10115
- function assertExtensionMethod2(method) {
10116
- if (!method.startsWith("_")) {
10117
- throw new Error('Extension method must start with "_"');
10083
+ });
10084
+
10085
+ // packages/poe-acp-client/src/stream-helpers.ts
10086
+ async function extractUsageFromSessionUpdateStream(stream) {
10087
+ const updates = [];
10088
+ for await (const entry of stream) {
10089
+ const update = toSessionUpdate(entry);
10090
+ if (update.sessionUpdate === "usage_update") {
10091
+ updates.push(update);
10092
+ }
10118
10093
  }
10094
+ return updates;
10119
10095
  }
10120
- function isInjectedTransportOptions(options) {
10121
- return "transport" in options;
10122
- }
10123
- function createAsyncQueue() {
10124
- const values = [];
10125
- const waiters = [];
10126
- let closed = false;
10127
- let failure = null;
10128
- const resolveOne = (value) => {
10129
- const waiter = waiters.shift();
10130
- if (!waiter) {
10131
- return false;
10132
- }
10133
- waiter.resolve({ done: false, value });
10134
- return true;
10135
- };
10136
- const iterator = {
10137
- push(value) {
10138
- if (closed || failure) {
10139
- return;
10096
+ async function extractToolCallSummariesFromSessionUpdateStream(stream) {
10097
+ const summaries = /* @__PURE__ */ new Map();
10098
+ for await (const entry of stream) {
10099
+ const update = toSessionUpdate(entry);
10100
+ if (update.sessionUpdate === "tool_call") {
10101
+ const summary = {
10102
+ toolCallId: update.toolCallId,
10103
+ title: update.title
10104
+ };
10105
+ if (update.kind !== void 0) {
10106
+ summary.kind = update.kind;
10140
10107
  }
10141
- if (!resolveOne(value)) {
10142
- values.push(value);
10108
+ if (update.status !== void 0) {
10109
+ summary.status = update.status;
10143
10110
  }
10144
- },
10145
- complete() {
10146
- if (closed || failure) {
10147
- return;
10111
+ if (update.rawInput !== void 0) {
10112
+ summary.rawInput = update.rawInput;
10148
10113
  }
10149
- closed = true;
10150
- while (waiters.length > 0) {
10151
- waiters.shift()?.resolve({ done: true, value: void 0 });
10114
+ if (update.rawOutput !== void 0) {
10115
+ summary.rawOutput = update.rawOutput;
10152
10116
  }
10153
- },
10154
- fail(error2) {
10155
- if (closed || failure) {
10156
- return;
10117
+ summaries.set(update.toolCallId, summary);
10118
+ continue;
10119
+ }
10120
+ if (update.sessionUpdate === "tool_call_update") {
10121
+ const existing = summaries.get(update.toolCallId);
10122
+ const summary = existing ?? {
10123
+ toolCallId: update.toolCallId,
10124
+ title: toTitle(update.title, update.toolCallId)
10125
+ };
10126
+ if (update.title !== null && update.title !== void 0 && update.title.length > 0) {
10127
+ summary.title = update.title;
10157
10128
  }
10158
- failure = error2;
10159
- while (waiters.length > 0) {
10160
- waiters.shift()?.reject(error2);
10129
+ if (update.kind !== null && update.kind !== void 0) {
10130
+ summary.kind = update.kind;
10161
10131
  }
10162
- },
10163
- async next() {
10164
- if (values.length > 0) {
10165
- const value = values.shift();
10166
- return { done: false, value };
10132
+ if (update.status !== null && update.status !== void 0) {
10133
+ summary.status = update.status;
10167
10134
  }
10168
- if (failure) {
10169
- throw failure;
10135
+ if (update.rawInput !== void 0) {
10136
+ summary.rawInput = update.rawInput;
10170
10137
  }
10171
- if (closed) {
10172
- return { done: true, value: void 0 };
10138
+ if (update.rawOutput !== void 0) {
10139
+ summary.rawOutput = update.rawOutput;
10173
10140
  }
10174
- return new Promise((resolve2, reject) => {
10175
- waiters.push({ resolve: resolve2, reject });
10176
- });
10177
- },
10178
- async return() {
10179
- iterator.complete();
10180
- return { done: true, value: void 0 };
10181
- },
10182
- async throw(error2) {
10183
- const normalizedError = toError(error2);
10184
- iterator.fail(normalizedError);
10185
- throw normalizedError;
10186
- },
10187
- [Symbol.asyncIterator]() {
10188
- return iterator;
10141
+ summaries.set(update.toolCallId, summary);
10189
10142
  }
10190
- };
10191
- return iterator;
10143
+ }
10144
+ return Array.from(summaries.values());
10192
10145
  }
10193
- var AcpClient;
10194
- var init_acp_client = __esm({
10195
- "packages/poe-acp-client/src/acp-client.ts"() {
10146
+ function toSessionUpdate(entry) {
10147
+ if (isSessionUpdateNotification(entry)) {
10148
+ return entry.params.update;
10149
+ }
10150
+ return entry;
10151
+ }
10152
+ function isSessionUpdateNotification(entry) {
10153
+ return typeof entry.jsonrpc === "string" && entry.method === "session/update";
10154
+ }
10155
+ function toTitle(value, fallback) {
10156
+ if (typeof value === "string" && value.length > 0) {
10157
+ return value;
10158
+ }
10159
+ return fallback;
10160
+ }
10161
+ var init_stream_helpers = __esm({
10162
+ "packages/poe-acp-client/src/stream-helpers.ts"() {
10196
10163
  "use strict";
10197
- init_acp_transport();
10198
- init_types3();
10199
- AcpClient = class {
10200
- transport;
10201
- clientProtocolVersion;
10202
- clientCapabilities;
10203
- clientInfo;
10204
- skipAuth;
10205
- permissionHandler;
10206
- fsHandler;
10207
- terminalHandler;
10208
- activePromptUpdates = /* @__PURE__ */ new Map();
10209
- trackedTerminalIds = /* @__PURE__ */ new Map();
10210
- hasRegisteredFsReadHandler = false;
10211
- hasRegisteredFsWriteHandler = false;
10212
- hasRegisteredTerminalHandlers = false;
10213
- disposed = false;
10214
- lifecycleState = "uninitialized";
10215
- negotiatedVersion = null;
10216
- availableAuthMethods = [];
10217
- negotiatedAgentCapabilities;
10218
- negotiatedAgentInfo;
10219
- constructor(options) {
10220
- this.transport = isInjectedTransportOptions(options) ? options.transport : new AcpTransport({
10221
- command: options.command,
10222
- args: options.args,
10223
- cwd: options.cwd,
10224
- env: options.env,
10225
- firstRequestId: options.firstRequestId,
10226
- spawn: options.spawn
10227
- });
10228
- this.clientProtocolVersion = options.protocolVersion ?? 1;
10229
- this.clientCapabilities = options.clientCapabilities;
10230
- this.clientInfo = options.clientInfo;
10231
- this.skipAuth = options.skipAuth ?? false;
10232
- this.permissionHandler = options.handlers?.permission ?? options.permissionHandler;
10233
- this.fsHandler = options.handlers?.fs ?? options.fsHandler;
10234
- this.terminalHandler = options.handlers?.terminal ?? options.terminalHandler;
10235
- const autoApprove = options.autoApprove === true && !this.permissionHandler;
10236
- this.transport.onRequest(
10237
- "session/request_permission",
10238
- async (params) => {
10239
- if (this.permissionHandler) {
10240
- const outcome = await this.permissionHandler({
10241
- toolCall: params.toolCall,
10242
- options: params.options
10243
- });
10244
- return { outcome };
10245
- }
10246
- if (autoApprove) {
10247
- const allow = params.options.find((o) => o.kind === "allow_always") ?? params.options.find((o) => o.kind === "allow_once");
10248
- if (allow) {
10249
- return { outcome: { outcome: "selected", optionId: allow.optionId } };
10250
- }
10251
- }
10252
- return { outcome: { outcome: "cancelled" } };
10253
- }
10254
- );
10255
- this.registerCapabilityHandlers(this.clientCapabilities);
10256
- this.transport.onNotification("session/update", (params) => {
10257
- this.handleSessionUpdateNotification(params);
10258
- });
10259
- }
10260
- get state() {
10261
- return this.lifecycleState;
10262
- }
10263
- get negotiatedProtocolVersion() {
10264
- return this.negotiatedVersion;
10265
- }
10266
- get authMethods() {
10267
- return [...this.availableAuthMethods];
10268
- }
10269
- get agentCapabilities() {
10270
- return this.negotiatedAgentCapabilities;
10271
- }
10272
- get agentInfo() {
10273
- return this.negotiatedAgentInfo;
10274
- }
10275
- get closed() {
10276
- return this.transport.closed;
10277
- }
10278
- async initialize(clientCapabilities) {
10279
- if (this.lifecycleState !== "uninitialized") {
10280
- throw new Error("initialize() can only be called once.");
10281
- }
10282
- if (clientCapabilities !== void 0) {
10283
- this.clientCapabilities = clientCapabilities;
10284
- this.registerCapabilityHandlers(clientCapabilities);
10285
- }
10286
- const response = await this.transport.sendRequest("initialize", {
10287
- protocolVersion: this.clientProtocolVersion,
10288
- clientInfo: this.clientInfo,
10289
- clientCapabilities: this.clientCapabilities
10290
- });
10291
- const negotiatedProtocolVersion = Math.min(
10292
- this.clientProtocolVersion,
10293
- response.protocolVersion
10294
- );
10295
- this.negotiatedVersion = negotiatedProtocolVersion;
10296
- this.negotiatedAgentCapabilities = response.agentCapabilities;
10297
- this.negotiatedAgentInfo = response.agentInfo;
10298
- this.availableAuthMethods = response.authMethods ? [...response.authMethods] : [];
10299
- const requiresAuth = this.availableAuthMethods.length > 0 && !this.skipAuth;
10300
- this.lifecycleState = requiresAuth ? "initialized" : "ready";
10301
- return {
10302
- protocolVersion: negotiatedProtocolVersion,
10303
- ...this.negotiatedAgentCapabilities !== void 0 ? { agentCapabilities: this.negotiatedAgentCapabilities } : {},
10304
- ...this.negotiatedAgentInfo !== void 0 ? { agentInfo: this.negotiatedAgentInfo } : {},
10305
- ...this.availableAuthMethods.length > 0 ? { authMethods: this.authMethods } : {}
10306
- };
10164
+ }
10165
+ });
10166
+
10167
+ // packages/poe-acp-client/src/run-report.ts
10168
+ import * as fsPromises from "node:fs/promises";
10169
+ import { homedir as homedir2 } from "node:os";
10170
+ import { join } from "node:path";
10171
+ async function generateRunReportFromSessionUpdateStream(stream, options = {}) {
10172
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
10173
+ const bufferedEntries = [];
10174
+ let runIdFromStream;
10175
+ for await (const entry of stream) {
10176
+ bufferedEntries.push(entry);
10177
+ if (runIdFromStream) {
10178
+ continue;
10179
+ }
10180
+ if (isSessionUpdateNotification2(entry)) {
10181
+ const sessionId = toNonEmptyString(entry.params.sessionId);
10182
+ if (sessionId) {
10183
+ runIdFromStream = sessionId;
10307
10184
  }
10308
- async authenticate(methodId) {
10309
- if (this.lifecycleState === "uninitialized") {
10310
- throw new Error("Cannot authenticate before initialize().");
10311
- }
10312
- if (this.lifecycleState === "ready") {
10313
- throw new Error("Authentication is not required for this agent.");
10314
- }
10315
- if (!this.availableAuthMethods.some((authMethod) => authMethod.id === methodId)) {
10316
- throw new Error(`Unknown auth method "${methodId}".`);
10317
- }
10318
- const response = await this.transport.sendRequest("authenticate", {
10319
- methodId
10320
- });
10321
- this.lifecycleState = "ready";
10322
- return response;
10323
- }
10324
- async newSession(cwd, mcpServers) {
10325
- this.assertReady("session/new");
10326
- this.assertMcpServerCapabilitySupport(mcpServers);
10327
- return this.transport.sendRequest("session/new", {
10328
- cwd,
10329
- mcpServers
10330
- });
10331
- }
10332
- async loadSession(sessionId, cwd, mcpServers) {
10333
- this.assertReady("session/load");
10334
- if (this.negotiatedAgentCapabilities?.loadSession !== true) {
10335
- throw new Error(
10336
- 'Cannot call "session/load" because the agent does not support session loading.'
10337
- );
10338
- }
10339
- this.assertMcpServerCapabilitySupport(mcpServers);
10340
- return this.transport.sendRequest("session/load", {
10341
- sessionId,
10342
- cwd,
10343
- mcpServers
10344
- });
10345
- }
10346
- async cancelSession(sessionId) {
10347
- this.assertReady("session/cancel");
10348
- const payload = { sessionId };
10349
- this.transport.sendNotification("session/cancel", payload);
10350
- }
10351
- async setMode(sessionId, modeId) {
10352
- this.assertReady("session/set_mode");
10353
- return this.transport.sendRequest("session/set_mode", {
10354
- sessionId,
10355
- modeId
10356
- });
10357
- }
10358
- async setConfigOption(sessionId, configId, value) {
10359
- this.assertReady("session/set_config_option");
10360
- const response = await this.transport.sendRequest("session/set_config_option", {
10361
- sessionId,
10362
- configId,
10363
- value
10364
- });
10365
- return response.configOptions;
10366
- }
10367
- prompt(sessionId, content) {
10368
- this.assertReady("session/prompt");
10369
- this.assertPromptContentCapabilitySupport(content);
10370
- if (this.activePromptUpdates.has(sessionId)) {
10371
- throw new Error(
10372
- `Cannot call "session/prompt" while another prompt is in progress for session "${sessionId}".`
10373
- );
10374
- }
10375
- const updates = createAsyncQueue();
10376
- this.activePromptUpdates.set(sessionId, updates);
10377
- let requestPromise;
10378
- try {
10379
- requestPromise = this.transport.sendRequest("session/prompt", {
10380
- sessionId,
10381
- prompt: content
10382
- });
10383
- } catch (error2) {
10384
- const normalizedError = toError(error2);
10385
- this.activePromptUpdates.delete(sessionId);
10386
- updates.fail(normalizedError);
10387
- throw normalizedError;
10388
- }
10389
- const response = requestPromise.then((promptResponse) => {
10390
- this.activePromptUpdates.delete(sessionId);
10391
- updates.complete();
10392
- return promptResponse;
10393
- }).catch((error2) => {
10394
- const normalizedError = toError(error2);
10395
- this.activePromptUpdates.delete(sessionId);
10396
- updates.fail(normalizedError);
10397
- throw normalizedError;
10398
- });
10399
- return {
10400
- response,
10401
- [Symbol.asyncIterator]() {
10402
- return updates;
10403
- }
10404
- };
10405
- }
10406
- async sendExtRequest(method, params, options = {}) {
10407
- assertExtensionMethod2(method);
10408
- return this.transport.sendRequest(method, params, options);
10409
- }
10410
- async sendExtNotification(method, params) {
10411
- assertExtensionMethod2(method);
10412
- this.transport.sendNotification(method, params);
10413
- }
10414
- onExtRequest(method, handler) {
10415
- assertExtensionMethod2(method);
10416
- this.transport.onRequest(method, handler);
10417
- }
10418
- onExtNotification(method, handler) {
10419
- assertExtensionMethod2(method);
10420
- this.transport.onNotification(method, handler);
10421
- }
10422
- async dispose() {
10423
- if (this.disposed) {
10424
- if (this.transport.closed) {
10425
- await this.transport.closed;
10426
- }
10427
- return;
10428
- }
10429
- this.disposed = true;
10430
- const disposeReason = new Error("ACP client disposed");
10431
- for (const updates of this.activePromptUpdates.values()) {
10432
- updates.fail(disposeReason);
10433
- }
10434
- this.activePromptUpdates.clear();
10435
- if (typeof this.transport.dispose === "function") {
10436
- this.transport.dispose(disposeReason);
10437
- }
10438
- if (this.transport.closed) {
10439
- await this.transport.closed;
10440
- }
10185
+ }
10186
+ }
10187
+ const runId = toNonEmptyString(options.runId) ?? runIdFromStream;
10188
+ if (!runId) {
10189
+ throw new Error("Run id is required via options.runId or session/update stream items");
10190
+ }
10191
+ const startTime = normalizeTime(options.startTime, now);
10192
+ const endTime = normalizeTime(options.endTime, now);
10193
+ const toolCalls = await extractToolCallSummariesFromSessionUpdateStream(bufferedEntries);
10194
+ const usageUpdates = await extractUsageFromSessionUpdateStream(bufferedEntries);
10195
+ const usage = summarizeUsage(usageUpdates);
10196
+ const errors = collectErrors(toolCalls, options.errors);
10197
+ const exitStatus = options.exitStatus ?? (errors.length > 0 ? "failed" : "success");
10198
+ return {
10199
+ runId,
10200
+ startTime,
10201
+ endTime,
10202
+ exitStatus,
10203
+ toolCalls,
10204
+ usage,
10205
+ errors
10206
+ };
10207
+ }
10208
+ function isSessionUpdateNotification2(entry) {
10209
+ return typeof entry.jsonrpc === "string" && entry.method === "session/update";
10210
+ }
10211
+ function normalizeTime(value, now) {
10212
+ if (value instanceof Date) {
10213
+ return value.toISOString();
10214
+ }
10215
+ if (typeof value === "string" && value.length > 0) {
10216
+ const parsed = new Date(value);
10217
+ if (!Number.isNaN(parsed.getTime())) {
10218
+ return parsed.toISOString();
10219
+ }
10220
+ }
10221
+ return now().toISOString();
10222
+ }
10223
+ function summarizeUsage(updates) {
10224
+ let used = 0;
10225
+ let size = 0;
10226
+ let cost;
10227
+ for (const update of updates) {
10228
+ used += update.used;
10229
+ size += update.size;
10230
+ if (update.cost !== void 0) {
10231
+ cost = update.cost;
10232
+ }
10233
+ }
10234
+ const usage = {
10235
+ used,
10236
+ size,
10237
+ updates: updates.length
10238
+ };
10239
+ if (cost !== void 0) {
10240
+ usage.cost = cost;
10241
+ }
10242
+ return usage;
10243
+ }
10244
+ function collectErrors(toolCalls, additionalErrors) {
10245
+ const errors = [];
10246
+ for (const toolCall of toolCalls) {
10247
+ if (toolCall.status !== "failed") {
10248
+ continue;
10249
+ }
10250
+ errors.push({
10251
+ toolCallId: toolCall.toolCallId,
10252
+ message: toErrorMessage(toolCall)
10253
+ });
10254
+ }
10255
+ if (additionalErrors) {
10256
+ for (const message2 of additionalErrors) {
10257
+ const text4 = toNonEmptyString(message2);
10258
+ if (text4) {
10259
+ errors.push({ message: text4 });
10441
10260
  }
10442
- assertReady(operation) {
10443
- if (this.lifecycleState === "ready") {
10444
- return;
10445
- }
10446
- if (this.lifecycleState === "uninitialized") {
10447
- throw new Error(`Cannot call "${operation}" before initialize().`);
10448
- }
10449
- throw new Error(`Cannot call "${operation}" before authentication completes.`);
10261
+ }
10262
+ }
10263
+ return errors;
10264
+ }
10265
+ function toErrorMessage(toolCall) {
10266
+ if (typeof toolCall.rawOutput === "string" && toolCall.rawOutput.length > 0) {
10267
+ return toolCall.rawOutput;
10268
+ }
10269
+ if (toolCall.rawOutput instanceof Error && toolCall.rawOutput.message.length > 0) {
10270
+ return toolCall.rawOutput.message;
10271
+ }
10272
+ if (toolCall.rawOutput !== void 0 && toolCall.rawOutput !== null) {
10273
+ const encoded = trySerialize(toolCall.rawOutput);
10274
+ if (encoded) {
10275
+ return encoded;
10276
+ }
10277
+ }
10278
+ return `${toolCall.title} failed`;
10279
+ }
10280
+ function trySerialize(value) {
10281
+ try {
10282
+ const serialized = JSON.stringify(value);
10283
+ if (typeof serialized === "string" && serialized.length > 0) {
10284
+ return serialized;
10285
+ }
10286
+ } catch {
10287
+ return void 0;
10288
+ }
10289
+ return void 0;
10290
+ }
10291
+ function toNonEmptyString(value) {
10292
+ if (typeof value !== "string" || value.length === 0) {
10293
+ return void 0;
10294
+ }
10295
+ return value;
10296
+ }
10297
+ var init_run_report = __esm({
10298
+ "packages/poe-acp-client/src/run-report.ts"() {
10299
+ "use strict";
10300
+ init_stream_helpers();
10301
+ }
10302
+ });
10303
+
10304
+ // packages/poe-acp-client/src/index.ts
10305
+ var init_src7 = __esm({
10306
+ "packages/poe-acp-client/src/index.ts"() {
10307
+ "use strict";
10308
+ init_acp_client();
10309
+ init_acp_transport();
10310
+ init_types3();
10311
+ init_jsonrpc_message_layer();
10312
+ init_jsonrpc();
10313
+ init_run_report();
10314
+ init_stream_helpers();
10315
+ }
10316
+ });
10317
+
10318
+ // packages/agent-spawn/src/acp/replay.ts
10319
+ import path9 from "node:path";
10320
+ import { homedir as homedir3 } from "node:os";
10321
+ import { open, readdir } from "node:fs/promises";
10322
+ import { createInterface as createInterface2 } from "node:readline";
10323
+ var init_replay = __esm({
10324
+ "packages/agent-spawn/src/acp/replay.ts"() {
10325
+ "use strict";
10326
+ init_src7();
10327
+ init_renderer2();
10328
+ }
10329
+ });
10330
+
10331
+ // packages/agent-spawn/src/adapters/utils.ts
10332
+ function truncate2(text4, maxLength) {
10333
+ if (text4.length <= maxLength) return text4;
10334
+ if (maxLength <= 3) return text4.slice(0, maxLength);
10335
+ return `${text4.slice(0, maxLength - 3)}...`;
10336
+ }
10337
+ function isNonEmptyString(value) {
10338
+ return typeof value === "string" && value.length > 0;
10339
+ }
10340
+ function extractThreadId(value) {
10341
+ if (!value || typeof value !== "object") return;
10342
+ const obj = value;
10343
+ const maybeThreadId = isNonEmptyString(obj.thread_id) && obj.thread_id || isNonEmptyString(obj.threadId) && obj.threadId || isNonEmptyString(obj.threadID) && obj.threadID || isNonEmptyString(obj.session_id) && obj.session_id || isNonEmptyString(obj.sessionId) && obj.sessionId || isNonEmptyString(obj.sessionID) && obj.sessionID;
10344
+ return maybeThreadId || void 0;
10345
+ }
10346
+ var init_utils2 = __esm({
10347
+ "packages/agent-spawn/src/adapters/utils.ts"() {
10348
+ "use strict";
10349
+ }
10350
+ });
10351
+
10352
+ // packages/agent-spawn/src/adapters/claude.ts
10353
+ function extractTitle(name, input) {
10354
+ const keys = TITLE_KEYS[name];
10355
+ if (keys && input && typeof input === "object") {
10356
+ const obj = input;
10357
+ for (const key of keys) {
10358
+ const value = obj[key];
10359
+ if (typeof value === "string" && value.length > 0) {
10360
+ return truncate2(value, 80);
10450
10361
  }
10451
- registerCapabilityHandlers(capabilities) {
10452
- if (!this.hasRegisteredFsReadHandler && capabilities?.fs?.readTextFile === true && this.fsHandler?.readTextFile) {
10453
- const readTextFile = this.fsHandler.readTextFile;
10454
- this.transport.onRequest(
10455
- "fs/read_text_file",
10456
- async (params) => {
10457
- assertAbsolutePath(params.path);
10458
- assertOneBasedLineNumber(params.line);
10459
- const content = await readTextFile({
10460
- sessionId: params.sessionId,
10461
- path: params.path,
10462
- line: params.line,
10463
- limit: params.limit
10464
- });
10465
- return { content };
10466
- }
10467
- );
10468
- this.hasRegisteredFsReadHandler = true;
10469
- }
10470
- if (!this.hasRegisteredFsWriteHandler && capabilities?.fs?.writeTextFile === true && this.fsHandler?.writeTextFile) {
10471
- const writeTextFile = this.fsHandler.writeTextFile;
10472
- this.transport.onRequest(
10473
- "fs/write_text_file",
10474
- async (params) => {
10475
- assertAbsolutePath(params.path);
10476
- await writeTextFile({
10477
- sessionId: params.sessionId,
10478
- path: params.path,
10479
- content: params.content
10480
- });
10481
- return {};
10482
- }
10483
- );
10484
- this.hasRegisteredFsWriteHandler = true;
10362
+ }
10363
+ }
10364
+ return name;
10365
+ }
10366
+ async function* adaptClaude(lines) {
10367
+ const toolKindsById = /* @__PURE__ */ new Map();
10368
+ let emittedSessionStart = false;
10369
+ for await (const rawLine of lines) {
10370
+ const line = rawLine.trim();
10371
+ if (!line) continue;
10372
+ const firstChar = line[0];
10373
+ if (firstChar !== "{" && firstChar !== "[") {
10374
+ continue;
10375
+ }
10376
+ let event;
10377
+ try {
10378
+ event = JSON.parse(line);
10379
+ } catch (error2) {
10380
+ const stack = error2 instanceof Error ? error2.stack : void 0;
10381
+ yield {
10382
+ event: "error",
10383
+ message: `[adaptClaude] Malformed JSON line: ${truncate2(line, 200)}`,
10384
+ stack
10385
+ };
10386
+ continue;
10387
+ }
10388
+ const eventType = event.type;
10389
+ if (!isNonEmptyString(eventType)) continue;
10390
+ if (!emittedSessionStart) {
10391
+ const threadId = extractThreadId(event);
10392
+ emittedSessionStart = true;
10393
+ yield { event: "session_start", threadId };
10394
+ }
10395
+ if (eventType === "result") {
10396
+ const usage = event.usage ?? {};
10397
+ const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : typeof event.input_tokens === "number" ? event.input_tokens : typeof event.num_input_tokens === "number" ? event.num_input_tokens : 0;
10398
+ const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : typeof event.output_tokens === "number" ? event.output_tokens : typeof event.num_output_tokens === "number" ? event.num_output_tokens : 0;
10399
+ const costUsd = typeof usage.cost_usd === "number" ? usage.cost_usd : typeof event.cost_usd === "number" ? event.cost_usd : void 0;
10400
+ yield { event: "usage", inputTokens, outputTokens, costUsd };
10401
+ continue;
10402
+ }
10403
+ if (eventType !== "assistant" && eventType !== "user") continue;
10404
+ const message2 = event.message ?? null;
10405
+ if (!message2 || typeof message2 !== "object") continue;
10406
+ const content = message2.content ?? null;
10407
+ if (!Array.isArray(content)) continue;
10408
+ for (const block of content) {
10409
+ const item = block;
10410
+ if (!item || typeof item !== "object") continue;
10411
+ const blockType = item.type;
10412
+ if (!isNonEmptyString(blockType)) continue;
10413
+ if (eventType === "assistant") {
10414
+ if (blockType === "text" && isNonEmptyString(item.text)) {
10415
+ yield {
10416
+ event: "agent_message",
10417
+ text: item.text
10418
+ };
10419
+ continue;
10485
10420
  }
10486
- if (!this.hasRegisteredTerminalHandlers && capabilities?.terminal === true && this.terminalHandler) {
10487
- const terminalHandler = this.terminalHandler;
10488
- this.transport.onRequest(
10489
- "terminal/create",
10490
- async (params) => {
10491
- const terminalId = await terminalHandler.create({
10492
- sessionId: params.sessionId,
10493
- command: params.command,
10494
- args: params.args,
10495
- cwd: params.cwd,
10496
- env: params.env,
10497
- outputByteLimit: params.outputByteLimit
10498
- });
10499
- this.trackTerminal(params.sessionId, terminalId);
10500
- return { terminalId };
10501
- }
10502
- );
10503
- this.transport.onRequest(
10504
- "terminal/output",
10505
- async (params) => {
10506
- this.assertKnownTerminal(params.sessionId, params.terminalId);
10507
- return terminalHandler.output({
10508
- sessionId: params.sessionId,
10509
- terminalId: params.terminalId
10510
- });
10511
- }
10512
- );
10513
- this.transport.onRequest(
10514
- "terminal/wait_for_exit",
10515
- async (params) => {
10516
- this.assertKnownTerminal(params.sessionId, params.terminalId);
10517
- return terminalHandler.waitForExit({
10518
- sessionId: params.sessionId,
10519
- terminalId: params.terminalId
10520
- });
10521
- }
10522
- );
10523
- this.transport.onRequest(
10524
- "terminal/kill",
10525
- async (params) => {
10526
- this.assertKnownTerminal(params.sessionId, params.terminalId);
10527
- await terminalHandler.kill({
10528
- sessionId: params.sessionId,
10529
- terminalId: params.terminalId
10530
- });
10531
- return {};
10532
- }
10533
- );
10534
- this.transport.onRequest(
10535
- "terminal/release",
10536
- async (params) => {
10537
- this.assertKnownTerminal(params.sessionId, params.terminalId);
10538
- await terminalHandler.release({
10539
- sessionId: params.sessionId,
10540
- terminalId: params.terminalId
10541
- });
10542
- this.untrackTerminal(params.sessionId, params.terminalId);
10543
- return {};
10544
- }
10545
- );
10546
- this.hasRegisteredTerminalHandlers = true;
10421
+ if (blockType === "tool_use" && isNonEmptyString(item.id) && isNonEmptyString(item.name)) {
10422
+ const kind = TOOL_KIND_MAP[item.name] ?? "other";
10423
+ toolKindsById.set(item.id, kind);
10424
+ yield {
10425
+ event: "tool_start",
10426
+ id: item.id,
10427
+ kind,
10428
+ title: extractTitle(item.name, item.input),
10429
+ input: item.input
10430
+ };
10547
10431
  }
10432
+ continue;
10548
10433
  }
10549
- assertMcpServerCapabilitySupport(mcpServers) {
10550
- const mcpCapabilities = this.negotiatedAgentCapabilities?.mcpCapabilities;
10551
- for (const mcpServer of mcpServers) {
10552
- if (!("type" in mcpServer)) {
10553
- continue;
10554
- }
10555
- if (mcpServer.type === "http" && mcpCapabilities?.http !== true) {
10556
- throw new Error('Agent does not support MCP server type "http".');
10557
- }
10558
- if (mcpServer.type === "sse" && mcpCapabilities?.sse !== true) {
10559
- throw new Error('Agent does not support MCP server type "sse".');
10434
+ if (eventType === "user") {
10435
+ if (!isNonEmptyString(item.tool_use_id)) continue;
10436
+ if (blockType !== "tool_result") continue;
10437
+ const kind = toolKindsById.get(item.tool_use_id);
10438
+ toolKindsById.delete(item.tool_use_id);
10439
+ let path54;
10440
+ if (typeof item.content === "string") {
10441
+ path54 = item.content;
10442
+ } else {
10443
+ try {
10444
+ path54 = JSON.stringify(item.content);
10445
+ } catch {
10446
+ path54 = String(item.content);
10560
10447
  }
10561
10448
  }
10449
+ yield {
10450
+ event: "tool_complete",
10451
+ id: item.tool_use_id,
10452
+ kind,
10453
+ path: path54
10454
+ };
10562
10455
  }
10563
- handleSessionUpdateNotification(notification) {
10564
- const activePrompt = this.activePromptUpdates.get(notification.sessionId);
10565
- if (!activePrompt) {
10566
- return;
10567
- }
10568
- activePrompt.push({
10569
- jsonrpc: "2.0",
10570
- method: "session/update",
10571
- params: notification
10572
- });
10456
+ }
10457
+ }
10458
+ }
10459
+ var TOOL_KIND_MAP, TITLE_KEYS;
10460
+ var init_claude = __esm({
10461
+ "packages/agent-spawn/src/adapters/claude.ts"() {
10462
+ "use strict";
10463
+ init_utils2();
10464
+ TOOL_KIND_MAP = {
10465
+ Read: "read",
10466
+ Write: "edit",
10467
+ Edit: "edit",
10468
+ NotebookEdit: "edit",
10469
+ Bash: "exec",
10470
+ Glob: "search",
10471
+ Grep: "search",
10472
+ Task: "think"
10473
+ };
10474
+ TITLE_KEYS = {
10475
+ Bash: ["command"],
10476
+ Read: ["file_path"],
10477
+ Write: ["file_path"],
10478
+ Edit: ["file_path"],
10479
+ NotebookEdit: ["notebook_path"],
10480
+ Glob: ["pattern"],
10481
+ Grep: ["pattern"],
10482
+ Task: ["description", "prompt"]
10483
+ };
10484
+ }
10485
+ });
10486
+
10487
+ // packages/agent-spawn/src/adapters/codex.ts
10488
+ async function* adaptCodex(lines) {
10489
+ const toolTitleById = /* @__PURE__ */ new Map();
10490
+ const toolKindById = /* @__PURE__ */ new Map();
10491
+ for await (const rawLine of lines) {
10492
+ const line = rawLine.trim();
10493
+ if (!line) continue;
10494
+ let event;
10495
+ try {
10496
+ event = JSON.parse(line);
10497
+ } catch (error2) {
10498
+ const stack = error2 instanceof Error ? error2.stack : void 0;
10499
+ yield {
10500
+ event: "error",
10501
+ message: `[adaptCodex] Malformed JSON line: ${truncate2(line, 200)}`,
10502
+ stack
10503
+ };
10504
+ continue;
10505
+ }
10506
+ const eventType = event.type;
10507
+ if (!isNonEmptyString(eventType)) continue;
10508
+ if (eventType === "thread.started") {
10509
+ const maybeThreadId = extractThreadId(event);
10510
+ yield { event: "session_start", threadId: maybeThreadId };
10511
+ continue;
10512
+ }
10513
+ if (eventType === "turn.started") {
10514
+ continue;
10515
+ }
10516
+ if (eventType === "turn.completed") {
10517
+ const usage = event.usage ?? {};
10518
+ const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : 0;
10519
+ const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : 0;
10520
+ const cachedTokens = typeof usage.cached_input_tokens === "number" ? usage.cached_input_tokens : 0;
10521
+ yield { event: "usage", inputTokens, outputTokens, cachedTokens };
10522
+ continue;
10523
+ }
10524
+ if (eventType === "turn.failed") {
10525
+ const message2 = extractErrorMessage(event) ?? "Turn failed";
10526
+ yield { event: "error", message: message2 };
10527
+ continue;
10528
+ }
10529
+ const item = event.item ?? null;
10530
+ if (!item || typeof item !== "object") continue;
10531
+ const itemType = item.type;
10532
+ if (!isNonEmptyString(itemType)) continue;
10533
+ if (eventType === "item.started") {
10534
+ if (!isNonEmptyString(item.id)) continue;
10535
+ let kind;
10536
+ let title;
10537
+ if (itemType === "command_execution") {
10538
+ kind = "exec";
10539
+ title = truncate2(isNonEmptyString(item.command) ? item.command : "", 80);
10540
+ } else if (itemType === "file_edit") {
10541
+ kind = "edit";
10542
+ title = isNonEmptyString(item.path) ? item.path : "";
10543
+ } else if (itemType === "thinking") {
10544
+ kind = "think";
10545
+ title = "thinking...";
10546
+ } else if (itemType === "mcp_tool_call") {
10547
+ const server = isNonEmptyString(item.server) ? item.server : "unknown";
10548
+ const tool = isNonEmptyString(item.tool) ? item.tool : "unknown";
10549
+ kind = "other";
10550
+ title = `${server}.${tool}`;
10573
10551
  }
10574
- trackTerminal(sessionId, terminalId) {
10575
- const sessionTerminals = this.trackedTerminalIds.get(sessionId);
10576
- if (sessionTerminals) {
10577
- sessionTerminals.add(terminalId);
10578
- return;
10579
- }
10580
- this.trackedTerminalIds.set(sessionId, /* @__PURE__ */ new Set([terminalId]));
10552
+ if (kind && title !== void 0) {
10553
+ toolTitleById.set(item.id, title);
10554
+ toolKindById.set(item.id, kind);
10555
+ yield { event: "tool_start", id: item.id, kind, title };
10581
10556
  }
10582
- assertKnownTerminal(sessionId, terminalId) {
10583
- const sessionTerminals = this.trackedTerminalIds.get(sessionId);
10584
- if (sessionTerminals?.has(terminalId) === true) {
10585
- return;
10586
- }
10587
- throw resourceNotFound(`terminal "${terminalId}"`);
10557
+ continue;
10558
+ }
10559
+ if (eventType === "item.completed") {
10560
+ if (itemType === "agent_message") {
10561
+ if (!isNonEmptyString(item.text)) continue;
10562
+ yield { event: "agent_message", text: item.text };
10563
+ continue;
10588
10564
  }
10589
- untrackTerminal(sessionId, terminalId) {
10590
- const sessionTerminals = this.trackedTerminalIds.get(sessionId);
10591
- if (!sessionTerminals) {
10592
- return;
10593
- }
10594
- sessionTerminals.delete(terminalId);
10595
- if (sessionTerminals.size === 0) {
10596
- this.trackedTerminalIds.delete(sessionId);
10597
- }
10565
+ if (itemType === "reasoning") {
10566
+ const text4 = isNonEmptyString(item.text) ? item.text : isNonEmptyString(item.content) ? item.content : isNonEmptyString(item.summary) ? item.summary : void 0;
10567
+ if (!text4) continue;
10568
+ yield { event: "reasoning", text: text4 };
10569
+ continue;
10598
10570
  }
10599
- assertPromptContentCapabilitySupport(content) {
10600
- const promptCapabilities = this.negotiatedAgentCapabilities?.promptCapabilities;
10601
- for (const block of content) {
10602
- if (block.type === "image" && promptCapabilities?.image !== true) {
10603
- throw new Error('Agent does not support prompt content type "image".');
10604
- }
10605
- if (block.type === "audio" && promptCapabilities?.audio !== true) {
10606
- throw new Error('Agent does not support prompt content type "audio".');
10607
- }
10608
- if (block.type === "resource" && promptCapabilities?.embeddedContext !== true) {
10609
- throw new Error('Agent does not support prompt content type "resource".');
10610
- }
10611
- }
10571
+ if (!isNonEmptyString(item.id)) continue;
10572
+ if (itemType === "command_execution" || itemType === "file_edit" || itemType === "mcp_tool_call") {
10573
+ const kindFromStart = toolKindById.get(item.id);
10574
+ const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
10575
+ const titleFromEvent = isNonEmptyString(item.path) ? item.path : itemType === "mcp_tool_call" ? `${isNonEmptyString(item.server) ? item.server : "unknown"}.${isNonEmptyString(item.tool) ? item.tool : "unknown"}` : void 0;
10576
+ const path54 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
10577
+ toolTitleById.delete(item.id);
10578
+ toolKindById.delete(item.id);
10579
+ yield { event: "tool_complete", id: item.id, kind, path: path54 };
10612
10580
  }
10613
- };
10581
+ }
10582
+ }
10583
+ }
10584
+ function extractErrorMessage(event) {
10585
+ if (isNonEmptyString(event.message)) return event.message;
10586
+ const error2 = event.error;
10587
+ if (isNonEmptyString(error2)) return error2;
10588
+ if (typeof error2 === "object" && error2 !== null) {
10589
+ const errorObj = error2;
10590
+ if (isNonEmptyString(errorObj.message)) return errorObj.message;
10591
+ }
10592
+ if (isNonEmptyString(event.reason)) return event.reason;
10593
+ return void 0;
10594
+ }
10595
+ var init_codex3 = __esm({
10596
+ "packages/agent-spawn/src/adapters/codex.ts"() {
10597
+ "use strict";
10598
+ init_utils2();
10614
10599
  }
10615
10600
  });
10616
10601
 
10617
- // packages/poe-acp-client/src/jsonrpc.ts
10618
- var init_jsonrpc = __esm({
10619
- "packages/poe-acp-client/src/jsonrpc.ts"() {
10602
+ // packages/agent-spawn/src/adapters/kimi.ts
10603
+ async function* adaptKimi(lines) {
10604
+ let emittedSessionStart = false;
10605
+ for await (const rawLine of lines) {
10606
+ const line = rawLine.trim();
10607
+ if (!line) continue;
10608
+ let event;
10609
+ try {
10610
+ event = JSON.parse(line);
10611
+ } catch (error2) {
10612
+ const stack = error2 instanceof Error ? error2.stack : void 0;
10613
+ yield {
10614
+ event: "error",
10615
+ message: `[adaptKimi] Malformed JSON line: ${truncate2(line, 200)}`,
10616
+ stack
10617
+ };
10618
+ continue;
10619
+ }
10620
+ if (!event || typeof event !== "object") continue;
10621
+ if (!emittedSessionStart) {
10622
+ const threadId = extractThreadId(event);
10623
+ if (threadId) {
10624
+ emittedSessionStart = true;
10625
+ yield { event: "session_start", threadId };
10626
+ }
10627
+ }
10628
+ const role = event.role;
10629
+ if (!isNonEmptyString(role) || role !== "assistant") continue;
10630
+ const content = event.content;
10631
+ if (!isNonEmptyString(content)) continue;
10632
+ yield { event: "agent_message", text: content };
10633
+ }
10634
+ }
10635
+ var init_kimi3 = __esm({
10636
+ "packages/agent-spawn/src/adapters/kimi.ts"() {
10620
10637
  "use strict";
10638
+ init_utils2();
10621
10639
  }
10622
10640
  });
10623
10641
 
10624
- // packages/poe-acp-client/src/stream-helpers.ts
10625
- async function extractUsageFromSessionUpdateStream(stream) {
10626
- const updates = [];
10627
- for await (const entry of stream) {
10628
- const update = toSessionUpdate(entry);
10629
- if (update.sessionUpdate === "usage_update") {
10630
- updates.push(update);
10642
+ // packages/agent-spawn/src/adapters/native.ts
10643
+ async function* adaptNative(lines) {
10644
+ for await (const rawLine of lines) {
10645
+ const line = rawLine.trim();
10646
+ if (!line) continue;
10647
+ let event;
10648
+ try {
10649
+ event = JSON.parse(line);
10650
+ } catch (error2) {
10651
+ const stack = error2 instanceof Error ? error2.stack : void 0;
10652
+ yield {
10653
+ event: "error",
10654
+ message: `[adaptNative] Malformed JSON line: ${truncate2(line, 200)}`,
10655
+ stack
10656
+ };
10657
+ continue;
10658
+ }
10659
+ const maybeEventType = event?.event;
10660
+ if (!isNonEmptyString(maybeEventType)) {
10661
+ yield {
10662
+ event: "error",
10663
+ message: `[adaptNative] Line missing string "event" field: ${truncate2(line, 200)}`
10664
+ };
10665
+ continue;
10631
10666
  }
10667
+ yield event;
10632
10668
  }
10633
- return updates;
10634
10669
  }
10635
- async function extractToolCallSummariesFromSessionUpdateStream(stream) {
10636
- const summaries = /* @__PURE__ */ new Map();
10637
- for await (const entry of stream) {
10638
- const update = toSessionUpdate(entry);
10639
- if (update.sessionUpdate === "tool_call") {
10640
- const summary = {
10641
- toolCallId: update.toolCallId,
10642
- title: update.title
10670
+ var init_native = __esm({
10671
+ "packages/agent-spawn/src/adapters/native.ts"() {
10672
+ "use strict";
10673
+ init_utils2();
10674
+ }
10675
+ });
10676
+
10677
+ // packages/agent-spawn/src/adapters/opencode.ts
10678
+ function guessToolKind(toolName) {
10679
+ const normalized = toolName.toLowerCase();
10680
+ if (normalized === "bash" || normalized === "shell" || normalized === "sh") return "exec";
10681
+ if (normalized.includes("read")) return "read";
10682
+ if (normalized.includes("write") || normalized.includes("edit") || normalized.includes("patch")) {
10683
+ return "edit";
10684
+ }
10685
+ if (normalized.includes("search") || normalized.includes("grep") || normalized.includes("glob") || normalized.includes("find")) {
10686
+ return "search";
10687
+ }
10688
+ if (normalized.includes("think") || normalized.includes("task")) return "think";
10689
+ return "other";
10690
+ }
10691
+ function safeStringify(value) {
10692
+ if (typeof value === "string") return value;
10693
+ try {
10694
+ return JSON.stringify(value);
10695
+ } catch {
10696
+ return String(value);
10697
+ }
10698
+ }
10699
+ async function* adaptOpenCode(lines) {
10700
+ let emittedSessionStart = false;
10701
+ const toolKindById = /* @__PURE__ */ new Map();
10702
+ for await (const rawLine of lines) {
10703
+ const line = rawLine.trim();
10704
+ if (!line) continue;
10705
+ let event;
10706
+ try {
10707
+ event = JSON.parse(line);
10708
+ } catch (error2) {
10709
+ const stack = error2 instanceof Error ? error2.stack : void 0;
10710
+ yield {
10711
+ event: "error",
10712
+ message: `[adaptOpenCode] Malformed JSON line: ${truncate2(line, 200)}`,
10713
+ stack
10643
10714
  };
10644
- if (update.kind !== void 0) {
10645
- summary.kind = update.kind;
10646
- }
10647
- if (update.status !== void 0) {
10648
- summary.status = update.status;
10649
- }
10650
- if (update.rawInput !== void 0) {
10651
- summary.rawInput = update.rawInput;
10715
+ continue;
10716
+ }
10717
+ if (!event || typeof event !== "object") continue;
10718
+ const sessionID = extractThreadId(event);
10719
+ if (!emittedSessionStart && isNonEmptyString(sessionID)) {
10720
+ emittedSessionStart = true;
10721
+ yield { event: "session_start", threadId: sessionID };
10722
+ }
10723
+ const eventType = event.type;
10724
+ if (!isNonEmptyString(eventType)) continue;
10725
+ if (eventType === "text") {
10726
+ const part = event.part ?? null;
10727
+ if (!part || typeof part !== "object") continue;
10728
+ if (!isNonEmptyString(part.text)) continue;
10729
+ yield { event: "agent_message", text: part.text };
10730
+ continue;
10731
+ }
10732
+ if (eventType === "tool_use") {
10733
+ const part = event.part ?? null;
10734
+ if (!part || typeof part !== "object") continue;
10735
+ if (!isNonEmptyString(part.callID) || !isNonEmptyString(part.tool)) continue;
10736
+ const state = part.state ?? null;
10737
+ if (!state || typeof state !== "object") continue;
10738
+ const kind = guessToolKind(part.tool);
10739
+ const status = state.status;
10740
+ const terminal = status === "completed" || status === "failed";
10741
+ if (!toolKindById.has(part.callID)) {
10742
+ toolKindById.set(part.callID, kind);
10743
+ let title = part.tool;
10744
+ const maybeInput = state.input;
10745
+ if (kind === "exec" && maybeInput && typeof maybeInput === "object") {
10746
+ const command = maybeInput.command;
10747
+ if (isNonEmptyString(command)) {
10748
+ title = truncate2(command, 80);
10749
+ }
10750
+ }
10751
+ yield {
10752
+ event: "tool_start",
10753
+ id: part.callID,
10754
+ kind,
10755
+ title,
10756
+ input: state.input
10757
+ };
10652
10758
  }
10653
- if (update.rawOutput !== void 0) {
10654
- summary.rawOutput = update.rawOutput;
10759
+ if (terminal) {
10760
+ const kindFromStart = toolKindById.get(part.callID) ?? kind;
10761
+ toolKindById.delete(part.callID);
10762
+ yield {
10763
+ event: "tool_complete",
10764
+ id: part.callID,
10765
+ kind: kindFromStart,
10766
+ path: safeStringify(state.output)
10767
+ };
10655
10768
  }
10656
- summaries.set(update.toolCallId, summary);
10657
10769
  continue;
10658
10770
  }
10659
- if (update.sessionUpdate === "tool_call_update") {
10660
- const existing = summaries.get(update.toolCallId);
10661
- const summary = existing ?? {
10662
- toolCallId: update.toolCallId,
10663
- title: toTitle(update.title, update.toolCallId)
10664
- };
10665
- if (update.title !== null && update.title !== void 0 && update.title.length > 0) {
10666
- summary.title = update.title;
10667
- }
10668
- if (update.kind !== null && update.kind !== void 0) {
10669
- summary.kind = update.kind;
10670
- }
10671
- if (update.status !== null && update.status !== void 0) {
10672
- summary.status = update.status;
10673
- }
10674
- if (update.rawInput !== void 0) {
10675
- summary.rawInput = update.rawInput;
10676
- }
10677
- if (update.rawOutput !== void 0) {
10678
- summary.rawOutput = update.rawOutput;
10679
- }
10680
- summaries.set(update.toolCallId, summary);
10771
+ if (eventType === "step_finish") {
10772
+ const part = event.part ?? null;
10773
+ if (!part || typeof part !== "object") continue;
10774
+ const tokens = part.tokens ?? null;
10775
+ if (!tokens || typeof tokens !== "object") continue;
10776
+ const inputTokens = typeof tokens.input === "number" ? tokens.input : 0;
10777
+ const outputTokens = typeof tokens.output === "number" ? tokens.output : 0;
10778
+ const cache = tokens.cache ?? null;
10779
+ const cachedTokens = cache && typeof cache === "object" && typeof cache.read === "number" ? cache.read : void 0;
10780
+ if (inputTokens === 0 && outputTokens === 0 && cachedTokens === void 0) continue;
10781
+ yield { event: "usage", inputTokens, outputTokens, cachedTokens };
10782
+ continue;
10681
10783
  }
10682
10784
  }
10683
- return Array.from(summaries.values());
10684
10785
  }
10685
- function toSessionUpdate(entry) {
10686
- if (isSessionUpdateNotification(entry)) {
10687
- return entry.params.update;
10786
+ var init_opencode3 = __esm({
10787
+ "packages/agent-spawn/src/adapters/opencode.ts"() {
10788
+ "use strict";
10789
+ init_utils2();
10688
10790
  }
10689
- return entry;
10690
- }
10691
- function isSessionUpdateNotification(entry) {
10692
- return typeof entry.jsonrpc === "string" && entry.method === "session/update";
10693
- }
10694
- function toTitle(value, fallback) {
10695
- if (typeof value === "string" && value.length > 0) {
10696
- return value;
10791
+ });
10792
+
10793
+ // packages/agent-spawn/src/adapters/index.ts
10794
+ function getAdapter(type) {
10795
+ const adapter = adapters[type];
10796
+ if (!adapter) {
10797
+ throw new Error(`Unknown adapter "${String(type)}".`);
10697
10798
  }
10698
- return fallback;
10799
+ return adapter;
10699
10800
  }
10700
- var init_stream_helpers = __esm({
10701
- "packages/poe-acp-client/src/stream-helpers.ts"() {
10801
+ var adapters;
10802
+ var init_adapters = __esm({
10803
+ "packages/agent-spawn/src/adapters/index.ts"() {
10702
10804
  "use strict";
10805
+ init_claude();
10806
+ init_codex3();
10807
+ init_kimi3();
10808
+ init_native();
10809
+ init_opencode3();
10810
+ init_codex3();
10811
+ init_claude();
10812
+ init_kimi3();
10813
+ init_native();
10814
+ init_opencode3();
10815
+ adapters = {
10816
+ codex: adaptCodex,
10817
+ claude: adaptClaude,
10818
+ kimi: adaptKimi,
10819
+ native: adaptNative,
10820
+ opencode: adaptOpenCode
10821
+ };
10703
10822
  }
10704
10823
  });
10705
10824
 
10706
- // packages/poe-acp-client/src/run-report.ts
10707
- import * as fsPromises from "node:fs/promises";
10708
- import { homedir as homedir3 } from "node:os";
10709
- import { join } from "node:path";
10710
- async function generateRunReportFromSessionUpdateStream(stream, options = {}) {
10711
- const now = options.now ?? (() => /* @__PURE__ */ new Date());
10712
- const bufferedEntries = [];
10713
- let runIdFromStream;
10714
- for await (const entry of stream) {
10715
- bufferedEntries.push(entry);
10716
- if (runIdFromStream) {
10717
- continue;
10718
- }
10719
- if (isSessionUpdateNotification2(entry)) {
10720
- const sessionId = toNonEmptyString(entry.params.sessionId);
10721
- if (sessionId) {
10722
- runIdFromStream = sessionId;
10723
- }
10825
+ // packages/agent-spawn/src/acp/line-reader.ts
10826
+ function chunkToString2(chunk) {
10827
+ if (typeof chunk === "string") return chunk;
10828
+ if (chunk instanceof Uint8Array) return Buffer.from(chunk).toString("utf8");
10829
+ return String(chunk);
10830
+ }
10831
+ async function* readLines2(stream) {
10832
+ let buffer = "";
10833
+ for await (const chunk of stream) {
10834
+ buffer += chunkToString2(chunk);
10835
+ while (true) {
10836
+ const newlineIndex = buffer.indexOf("\n");
10837
+ if (newlineIndex === -1) break;
10838
+ yield buffer.slice(0, newlineIndex);
10839
+ buffer = buffer.slice(newlineIndex + 1);
10724
10840
  }
10725
10841
  }
10726
- const runId = toNonEmptyString(options.runId) ?? runIdFromStream;
10727
- if (!runId) {
10728
- throw new Error("Run id is required via options.runId or session/update stream items");
10842
+ if (buffer.length > 0) {
10843
+ yield buffer;
10729
10844
  }
10730
- const startTime = normalizeTime(options.startTime, now);
10731
- const endTime = normalizeTime(options.endTime, now);
10732
- const toolCalls = await extractToolCallSummariesFromSessionUpdateStream(bufferedEntries);
10733
- const usageUpdates = await extractUsageFromSessionUpdateStream(bufferedEntries);
10734
- const usage = summarizeUsage(usageUpdates);
10735
- const errors = collectErrors(toolCalls, options.errors);
10736
- const exitStatus = options.exitStatus ?? (errors.length > 0 ? "failed" : "success");
10737
- return {
10738
- runId,
10739
- startTime,
10740
- endTime,
10741
- exitStatus,
10742
- toolCalls,
10743
- usage,
10744
- errors
10745
- };
10746
- }
10747
- function isSessionUpdateNotification2(entry) {
10748
- return typeof entry.jsonrpc === "string" && entry.method === "session/update";
10749
10845
  }
10750
- function normalizeTime(value, now) {
10751
- if (value instanceof Date) {
10752
- return value.toISOString();
10753
- }
10754
- if (typeof value === "string" && value.length > 0) {
10755
- const parsed = new Date(value);
10756
- if (!Number.isNaN(parsed.getTime())) {
10757
- return parsed.toISOString();
10758
- }
10846
+ var init_line_reader = __esm({
10847
+ "packages/agent-spawn/src/acp/line-reader.ts"() {
10848
+ "use strict";
10759
10849
  }
10760
- return now().toISOString();
10850
+ });
10851
+
10852
+ // packages/agent-spawn/src/acp/spawn.ts
10853
+ import { spawn as spawnChildProcess4 } from "node:child_process";
10854
+ function createAbortError2() {
10855
+ const error2 = new Error("Agent spawn aborted");
10856
+ error2.name = "AbortError";
10857
+ return error2;
10761
10858
  }
10762
- function summarizeUsage(updates) {
10763
- let used = 0;
10764
- let size = 0;
10765
- let cost;
10766
- for (const update of updates) {
10767
- used += update.used;
10768
- size += update.size;
10769
- if (update.cost !== void 0) {
10770
- cost = update.cost;
10771
- }
10772
- }
10773
- const usage = {
10774
- used,
10775
- size,
10776
- updates: updates.length
10777
- };
10778
- if (cost !== void 0) {
10779
- usage.cost = cost;
10780
- }
10781
- return usage;
10859
+ function createActivityTimeoutError2(timeoutMs) {
10860
+ const error2 = new Error(
10861
+ `Agent spawn timed out after ${timeoutMs / 1e3}s of inactivity`
10862
+ );
10863
+ error2.name = "ActivityTimeoutError";
10864
+ return error2;
10782
10865
  }
10783
- function collectErrors(toolCalls, additionalErrors) {
10784
- const errors = [];
10785
- for (const toolCall of toolCalls) {
10786
- if (toolCall.status !== "failed") {
10787
- continue;
10788
- }
10789
- errors.push({
10790
- toolCallId: toolCall.toolCallId,
10791
- message: toErrorMessage(toolCall)
10792
- });
10793
- }
10794
- if (additionalErrors) {
10795
- for (const message2 of additionalErrors) {
10796
- const text4 = toNonEmptyString(message2);
10797
- if (text4) {
10798
- errors.push({ message: text4 });
10799
- }
10800
- }
10801
- }
10802
- return errors;
10866
+ function isAcpEvent(value) {
10867
+ return !!value && typeof value === "object" && "event" in value;
10803
10868
  }
10804
- function toErrorMessage(toolCall) {
10805
- if (typeof toolCall.rawOutput === "string" && toolCall.rawOutput.length > 0) {
10806
- return toolCall.rawOutput;
10869
+ function getDefaultArgsPosition2(config) {
10870
+ return config.defaultArgsPosition ?? "afterPrompt";
10871
+ }
10872
+ function getMcpArgsPosition2(config) {
10873
+ if (config.mcpArgsPosition) {
10874
+ return config.mcpArgsPosition;
10807
10875
  }
10808
- if (toolCall.rawOutput instanceof Error && toolCall.rawOutput.message.length > 0) {
10809
- return toolCall.rawOutput.message;
10876
+ return config.mcpArgsBeforeCommand ? "beforeCommand" : "afterCommand";
10877
+ }
10878
+ function spawnStreaming(options) {
10879
+ if (options.signal?.aborted) {
10880
+ throw createAbortError2();
10810
10881
  }
10811
- if (toolCall.rawOutput !== void 0 && toolCall.rawOutput !== null) {
10812
- const encoded = trySerialize(toolCall.rawOutput);
10813
- if (encoded) {
10814
- return encoded;
10815
- }
10882
+ const { agentId, binaryName, spawnConfig } = resolveConfig(options.agentId);
10883
+ if (spawnConfig === void 0) {
10884
+ throw new Error(`Agent "${agentId}" has no spawn config.`);
10816
10885
  }
10817
- return `${toolCall.title} failed`;
10818
- }
10819
- function trySerialize(value) {
10820
- try {
10821
- const serialized = JSON.stringify(value);
10822
- if (typeof serialized === "string" && serialized.length > 0) {
10823
- return serialized;
10824
- }
10825
- } catch {
10826
- return void 0;
10886
+ if (spawnConfig.kind !== "cli") {
10887
+ throw new Error(`Agent "${agentId}" does not support CLI spawn.`);
10827
10888
  }
10828
- return void 0;
10829
- }
10830
- function toNonEmptyString(value) {
10831
- if (typeof value !== "string" || value.length === 0) {
10832
- return void 0;
10889
+ if (!binaryName) {
10890
+ throw new Error(`Agent "${agentId}" has no binaryName.`);
10833
10891
  }
10834
- return value;
10835
- }
10836
- var init_run_report = __esm({
10837
- "packages/poe-acp-client/src/run-report.ts"() {
10838
- "use strict";
10839
- init_stream_helpers();
10892
+ const mcpArgs = getMcpArgs(spawnConfig, options.mcpServers);
10893
+ const mcpEnvVars = getMcpEnv(spawnConfig, options.mcpServers);
10894
+ const defaultArgsPosition = getDefaultArgsPosition2(spawnConfig);
10895
+ const mcpArgsPosition = getMcpArgsPosition2(spawnConfig);
10896
+ const args = [];
10897
+ if (mcpArgsPosition === "beforeCommand") {
10898
+ args.push(...mcpArgs);
10840
10899
  }
10841
- });
10842
-
10843
- // packages/poe-acp-client/src/index.ts
10844
- var init_src7 = __esm({
10845
- "packages/poe-acp-client/src/index.ts"() {
10846
- "use strict";
10847
- init_acp_client();
10848
- init_acp_transport();
10849
- init_types3();
10850
- init_jsonrpc_message_layer();
10851
- init_jsonrpc();
10852
- init_run_report();
10853
- init_stream_helpers();
10900
+ if (defaultArgsPosition === "beforePrompt") {
10901
+ args.push(...spawnConfig.defaultArgs);
10854
10902
  }
10855
- });
10856
-
10857
- // packages/agent-spawn/src/acp/spawn-acp.ts
10858
- function toRenderKind(kind) {
10859
- if (kind === "execute") return "exec";
10860
- if (kind === "write") return "edit";
10861
- if (kind === "read") return "read";
10862
- return "other";
10863
- }
10864
- function toToolTitle(title, locations) {
10865
- if (locations && locations.length > 0 && locations[0].path) {
10866
- return locations[0].path;
10903
+ if (mcpArgsPosition === "beforePrompt") {
10904
+ args.push(...mcpArgs);
10867
10905
  }
10868
- return title;
10869
- }
10870
- function toToolOutput(value) {
10871
- if (typeof value === "string") return value;
10872
- if (value === void 0 || value === null) return "";
10873
- try {
10874
- return JSON.stringify(value);
10875
- } catch {
10876
- return String(value);
10906
+ args.push(spawnConfig.promptFlag);
10907
+ const useStdin = !!options.useStdin && !!spawnConfig.stdinMode;
10908
+ if (!useStdin || !spawnConfig.stdinMode?.omitPrompt) {
10909
+ args.push(options.prompt);
10877
10910
  }
10878
- }
10879
- function extractToolOutputText(update) {
10880
- const raw = toToolOutput(update.rawOutput);
10881
- if (raw) return raw;
10882
- if (!update.content) return "";
10883
- return update.content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("");
10884
- }
10885
- function toEventsFromSessionUpdate(notification, state) {
10886
- const update = notification.params.update;
10887
- if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
10888
- return [{ event: "agent_message", text: update.content.text }];
10911
+ if (options.model && spawnConfig.modelFlag) {
10912
+ let model = spawnConfig.modelStripProviderPrefix ? stripModelNamespace(options.model) : options.model;
10913
+ if (spawnConfig.modelTransform) model = spawnConfig.modelTransform(model);
10914
+ args.push(spawnConfig.modelFlag, model);
10889
10915
  }
10890
- if (update.sessionUpdate === "agent_thought_chunk" && update.content.type === "text") {
10891
- return [{ event: "reasoning", text: update.content.text }];
10916
+ if (defaultArgsPosition === "afterPrompt") {
10917
+ args.push(...spawnConfig.defaultArgs);
10892
10918
  }
10893
- if (update.sessionUpdate === "usage_update") {
10894
- const cachedTokens = Math.max(0, update.size - update.used);
10895
- const usage = {
10896
- event: "usage",
10897
- inputTokens: update.used,
10898
- outputTokens: 0
10899
- };
10900
- if (cachedTokens > 0) {
10901
- usage.cachedTokens = cachedTokens;
10902
- }
10903
- if (update.cost && update.cost.currency === "USD") {
10904
- usage.costUsd = update.cost.amount;
10905
- }
10906
- return [usage];
10919
+ if (mcpArgsPosition === "afterCommand") {
10920
+ args.push(...mcpArgs);
10907
10921
  }
10908
- if (update.sessionUpdate === "tool_call") {
10909
- const renderKind = toRenderKind(update.kind);
10910
- const title = toToolTitle(update.title, update.locations);
10911
- state.toolCallKinds.set(update.toolCallId, renderKind);
10912
- state.toolCallTitles.set(update.toolCallId, title);
10913
- if (state.startedToolCalls.has(update.toolCallId)) {
10914
- return [];
10915
- }
10916
- state.startedToolCalls.add(update.toolCallId);
10917
- return [{
10918
- event: "tool_start",
10919
- kind: renderKind,
10920
- title,
10921
- id: update.toolCallId
10922
- }];
10922
+ const modeResolved = resolveModeConfig(spawnConfig.modes[options.mode ?? "yolo"]);
10923
+ args.push(...modeResolved.args);
10924
+ if (useStdin) {
10925
+ args.push(...spawnConfig.stdinMode.extraArgs);
10923
10926
  }
10924
- if (update.sessionUpdate === "tool_call_update") {
10925
- const renderKind = toRenderKind(update.kind ?? void 0) || state.toolCallKinds.get(update.toolCallId) || "other";
10926
- state.toolCallKinds.set(update.toolCallId, renderKind);
10927
- const events = [];
10928
- const toolTitle = toToolTitle(
10929
- state.toolCallTitles.get(update.toolCallId) ?? update.toolCallId,
10930
- update.locations
10931
- );
10932
- state.toolCallTitles.set(update.toolCallId, toolTitle);
10933
- const status = update.status;
10934
- const shouldStart = !state.startedToolCalls.has(update.toolCallId) && (status === "pending" || status === "in_progress");
10935
- if (shouldStart) {
10936
- state.startedToolCalls.add(update.toolCallId);
10937
- events.push({
10938
- event: "tool_start",
10939
- kind: renderKind,
10940
- title: toolTitle,
10941
- id: update.toolCallId
10942
- });
10927
+ if (options.args && options.args.length > 0) {
10928
+ args.push(...options.args);
10929
+ }
10930
+ const envOverrides = { ...mcpEnvVars, ...modeResolved.env };
10931
+ const child = spawnChildProcess4(binaryName, args, {
10932
+ cwd: options.cwd,
10933
+ stdio: ["pipe", "pipe", "pipe"],
10934
+ env: Object.keys(envOverrides).length > 0 ? { ...process.env, ...envOverrides } : void 0
10935
+ });
10936
+ let aborted = false;
10937
+ let timedOut = false;
10938
+ const onAbort = () => {
10939
+ aborted = true;
10940
+ child.kill("SIGTERM");
10941
+ };
10942
+ options.signal?.addEventListener("abort", onAbort, { once: true });
10943
+ let activityTimer;
10944
+ const resetActivityTimer = options.activityTimeoutMs ? () => {
10945
+ if (activityTimer) clearTimeout(activityTimer);
10946
+ activityTimer = setTimeout(() => {
10947
+ timedOut = true;
10948
+ child.kill("SIGTERM");
10949
+ }, options.activityTimeoutMs);
10950
+ } : void 0;
10951
+ resetActivityTimer?.();
10952
+ const result = { stdout: "", stderr: "", exitCode: 1 };
10953
+ child.stderr.setEncoding("utf8");
10954
+ child.stderr.on("data", (chunk) => {
10955
+ result.stderr += chunk;
10956
+ resetActivityTimer?.();
10957
+ });
10958
+ if (useStdin) {
10959
+ child.stdin.write(options.prompt);
10960
+ }
10961
+ child.stdin.end();
10962
+ const adapter = getAdapter(spawnConfig.adapter);
10963
+ const events = (async function* () {
10964
+ for await (const output of adapter(readLines2(child.stdout))) {
10965
+ if (!isAcpEvent(output)) continue;
10966
+ resetActivityTimer?.();
10967
+ yield output;
10943
10968
  }
10944
- if (status === "completed" || status === "failed" || status === "cancelled") {
10945
- if (!state.startedToolCalls.has(update.toolCallId)) {
10946
- state.startedToolCalls.add(update.toolCallId);
10947
- events.push({
10948
- event: "tool_start",
10949
- kind: renderKind,
10950
- title: toolTitle,
10951
- id: update.toolCallId
10952
- });
10969
+ })();
10970
+ const done = new Promise((resolve2, reject) => {
10971
+ child.on("error", (error2) => {
10972
+ options.signal?.removeEventListener("abort", onAbort);
10973
+ if (activityTimer) clearTimeout(activityTimer);
10974
+ if (aborted) {
10975
+ reject(createAbortError2());
10976
+ return;
10953
10977
  }
10954
- events.push({
10955
- event: "tool_complete",
10956
- kind: renderKind,
10957
- path: extractToolOutputText(update),
10958
- id: update.toolCallId
10959
- });
10960
- }
10961
- return events;
10962
- }
10963
- return [];
10978
+ reject(error2);
10979
+ });
10980
+ child.on("close", (code) => {
10981
+ options.signal?.removeEventListener("abort", onAbort);
10982
+ if (activityTimer) clearTimeout(activityTimer);
10983
+ if (aborted) {
10984
+ reject(createAbortError2());
10985
+ return;
10986
+ }
10987
+ if (timedOut) {
10988
+ reject(createActivityTimeoutError2(options.activityTimeoutMs));
10989
+ return;
10990
+ }
10991
+ result.exitCode = code ?? 1;
10992
+ resolve2(result);
10993
+ });
10994
+ });
10995
+ return { events, done };
10964
10996
  }
10997
+ var init_spawn2 = __esm({
10998
+ "packages/agent-spawn/src/acp/spawn.ts"() {
10999
+ "use strict";
11000
+ init_adapters();
11001
+ init_line_reader();
11002
+ init_resolve_config();
11003
+ init_mcp_args();
11004
+ init_model_utils();
11005
+ init_types2();
11006
+ }
11007
+ });
11008
+
11009
+ // packages/agent-spawn/src/acp/spawn-acp.ts
10965
11010
  function toAcpMcpServers(servers) {
10966
11011
  if (!servers) return [];
10967
11012
  return Object.entries(servers).map(([name, server]) => ({
10968
11013
  name,
10969
11014
  command: server.command,
10970
11015
  args: server.args ?? [],
10971
- env: server.env ? Object.entries(server.env).map(([k2, v]) => ({ name: k2, value: v })) : []
11016
+ env: server.env ? Object.entries(server.env).map(([k, v]) => ({ name: k, value: v })) : []
10972
11017
  }));
10973
11018
  }
10974
11019
  function createAbortError3() {
@@ -11009,11 +11054,7 @@ function spawnAcp(options) {
11009
11054
  void client.dispose();
11010
11055
  };
11011
11056
  options.signal?.addEventListener("abort", onAbort, { once: true });
11012
- const toolState = {
11013
- startedToolCalls: /* @__PURE__ */ new Set(),
11014
- toolCallKinds: /* @__PURE__ */ new Map(),
11015
- toolCallTitles: /* @__PURE__ */ new Map()
11016
- };
11057
+ const toolState = createToolRenderState();
11017
11058
  let sessionId = "";
11018
11059
  let assistantText = "";
11019
11060
  let lastToolOutput = "";
@@ -11069,7 +11110,11 @@ function spawnAcp(options) {
11069
11110
  if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
11070
11111
  assistantText += update.content.text;
11071
11112
  }
11072
- for (const event of toEventsFromSessionUpdate(notification, toolState)) {
11113
+ const events2 = sessionUpdateToEvents(update, toolState);
11114
+ if (events2.length > 0) {
11115
+ events2[0]._meta = { ...events2[0]._meta ?? {}, raw: update };
11116
+ }
11117
+ for (const event of events2) {
11073
11118
  if (event.event === "tool_complete") {
11074
11119
  const output = event.path;
11075
11120
  if (output) {
@@ -11128,6 +11173,7 @@ var init_spawn_acp = __esm({
11128
11173
  init_src2();
11129
11174
  init_src7();
11130
11175
  init_configs();
11176
+ init_session_update_converter();
11131
11177
  }
11132
11178
  });
11133
11179
 
@@ -11378,7 +11424,9 @@ var init_spawn_log = __esm({
11378
11424
  if (!this.fileHandle) {
11379
11425
  return;
11380
11426
  }
11381
- await this.fileHandle.appendFile(`${JSON.stringify(event)}
11427
+ const meta = event._meta;
11428
+ const toLog = meta?.raw ?? event;
11429
+ await this.fileHandle.appendFile(`${JSON.stringify(toLog)}
11382
11430
  `, "utf8");
11383
11431
  } catch {
11384
11432
  this.isDisabled = true;
@@ -14014,7 +14062,7 @@ function createAbortError4() {
14014
14062
  error2.name = "AbortError";
14015
14063
  return error2;
14016
14064
  }
14017
- var init_utils2 = __esm({
14065
+ var init_utils3 = __esm({
14018
14066
  "packages/pipeline/src/utils.ts"() {
14019
14067
  "use strict";
14020
14068
  }
@@ -14240,7 +14288,7 @@ var init_loader = __esm({
14240
14288
  "packages/pipeline/src/config/loader.ts"() {
14241
14289
  "use strict";
14242
14290
  init_src3();
14243
- init_utils2();
14291
+ init_utils3();
14244
14292
  }
14245
14293
  });
14246
14294
 
@@ -14386,7 +14434,7 @@ function parsePlan(yamlContent, options = {}) {
14386
14434
  var init_parser2 = __esm({
14387
14435
  "packages/pipeline/src/plan/parser.ts"() {
14388
14436
  "use strict";
14389
- init_utils2();
14437
+ init_utils3();
14390
14438
  }
14391
14439
  });
14392
14440
 
@@ -14588,7 +14636,7 @@ var init_discovery = __esm({
14588
14636
  "use strict";
14589
14637
  init_loader();
14590
14638
  init_parser2();
14591
- init_utils2();
14639
+ init_utils3();
14592
14640
  }
14593
14641
  });
14594
14642
 
@@ -15647,7 +15695,7 @@ var init_pipeline = __esm({
15647
15695
  init_parser2();
15648
15696
  init_writer();
15649
15697
  init_runner();
15650
- init_utils2();
15698
+ init_utils3();
15651
15699
  }
15652
15700
  });
15653
15701
 
@@ -17880,6 +17928,7 @@ var init_ralph = __esm({
17880
17928
  this.kind = kind;
17881
17929
  this.name = "RalphWorkflowStopError";
17882
17930
  }
17931
+ kind;
17883
17932
  };
17884
17933
  }
17885
17934
  });
@@ -18073,6 +18122,8 @@ var init_journal = __esm({
18073
18122
  this.journalPath = journalPath;
18074
18123
  this.fs = fs3;
18075
18124
  }
18125
+ journalPath;
18126
+ fs;
18076
18127
  async init() {
18077
18128
  await this.fs.mkdir(dirname2(this.journalPath), { recursive: true });
18078
18129
  try {
@@ -19272,11 +19323,11 @@ function assertValidEnumValues(values) {
19272
19323
  throw new Error("Enum schema values must be unique");
19273
19324
  }
19274
19325
  }
19275
- var S;
19326
+ var S2;
19276
19327
  var init_src17 = __esm({
19277
19328
  "packages/cmdkit-schema/src/index.ts"() {
19278
19329
  "use strict";
19279
- S = {
19330
+ S2 = {
19280
19331
  String(options = {}) {
19281
19332
  return {
19282
19333
  kind: "string",
@@ -20373,7 +20424,7 @@ async function selectAutomationName(message2, automations) {
20373
20424
  message: message2,
20374
20425
  options: automations.map((a) => ({ label: a.label ?? formatLabel(a.name), value: a.name }))
20375
20426
  });
20376
- if (Ct(selected)) {
20427
+ if (q(selected)) {
20377
20428
  cancel("Operation cancelled.");
20378
20429
  throw new UserError("Operation cancelled.");
20379
20430
  }
@@ -20417,12 +20468,12 @@ var init_commands = __esm({
20417
20468
  name: "run",
20418
20469
  description: "Run a GitHub automation.",
20419
20470
  positional: ["name"],
20420
- params: S.Object({
20421
- name: S.Optional(S.String({ description: "Automation name to run" })),
20422
- agent: S.Optional(S.String({ description: "Agent to run the automation with" })),
20423
- model: S.Optional(S.String({ description: "Model override for the agent" })),
20424
- mode: S.Optional(S.Enum(["yolo", "edit", "read"], { description: "Permission mode (yolo | edit | read)" })),
20425
- cwd: S.Optional(S.String({ description: "Working directory for the automation" }))
20471
+ params: S2.Object({
20472
+ name: S2.Optional(S2.String({ description: "Automation name to run" })),
20473
+ agent: S2.Optional(S2.String({ description: "Agent to run the automation with" })),
20474
+ model: S2.Optional(S2.String({ description: "Model override for the agent" })),
20475
+ mode: S2.Optional(S2.Enum(["yolo", "edit", "read"], { description: "Permission mode (yolo | edit | read)" })),
20476
+ cwd: S2.Optional(S2.String({ description: "Working directory for the automation" }))
20426
20477
  }),
20427
20478
  secrets: {
20428
20479
  poeApiKey: { env: "POE_API_KEY" },
@@ -20503,7 +20554,7 @@ var init_commands = __esm({
20503
20554
  listCommand = defineCommand({
20504
20555
  name: "list",
20505
20556
  description: "List available automations.",
20506
- params: S.Object({}),
20557
+ params: S2.Object({}),
20507
20558
  scope: ["cli", "sdk"],
20508
20559
  handler: async () => discoverAutomations(await resolveBuiltInPromptsDir(), ...projectPromptDirs(resolveCwd())),
20509
20560
  render: {
@@ -20531,9 +20582,9 @@ var init_commands = __esm({
20531
20582
  name: "install",
20532
20583
  description: "Install one or all automation workflows into the current repo.",
20533
20584
  positional: ["name"],
20534
- params: S.Object({
20535
- name: S.Optional(
20536
- S.Enum(installableAutomations, {
20585
+ params: S2.Object({
20586
+ name: S2.Optional(
20587
+ S2.Enum(installableAutomations, {
20537
20588
  description: "Pick a GitHub workflow to install",
20538
20589
  loadOptions: async () => {
20539
20590
  const automations = await discoverAutomations(await resolveBuiltInPromptsDir());
@@ -20541,7 +20592,7 @@ var init_commands = __esm({
20541
20592
  }
20542
20593
  })
20543
20594
  ),
20544
- eject: S.Optional(S.Boolean())
20595
+ eject: S2.Optional(S2.Boolean())
20545
20596
  }),
20546
20597
  scope: ["cli"],
20547
20598
  handler: async ({ params }) => {
@@ -20590,8 +20641,8 @@ var init_commands = __esm({
20590
20641
  name: "uninstall",
20591
20642
  description: "Remove an installed automation workflow from the current repo.",
20592
20643
  positional: ["name"],
20593
- params: S.Object({
20594
- name: S.Enum(installableAutomations, {
20644
+ params: S2.Object({
20645
+ name: S2.Enum(installableAutomations, {
20595
20646
  description: "Pick a GitHub workflow to uninstall",
20596
20647
  loadOptions: async () => {
20597
20648
  const automations = await discoverAutomations(await resolveBuiltInPromptsDir());
@@ -20625,8 +20676,8 @@ var init_commands = __esm({
20625
20676
  name: "require-user-allow",
20626
20677
  description: "Fail when COMMENT_AUTHOR_ASSOCIATION is not allowed by the automation frontmatter.",
20627
20678
  positional: ["name"],
20628
- params: S.Object({
20629
- name: S.String()
20679
+ params: S2.Object({
20680
+ name: S2.String()
20630
20681
  }),
20631
20682
  scope: ["cli"],
20632
20683
  handler: async ({ params, env }) => {
@@ -20639,8 +20690,8 @@ var init_commands = __esm({
20639
20690
  name: "require-comment-prefix",
20640
20691
  description: "Fail when COMMENT_BODY does not start with the automation prefix frontmatter.",
20641
20692
  positional: ["name"],
20642
- params: S.Object({
20643
- name: S.String()
20693
+ params: S2.Object({
20694
+ name: S2.String()
20644
20695
  }),
20645
20696
  scope: ["cli"],
20646
20697
  handler: async ({ params, env }) => {
@@ -20653,8 +20704,8 @@ var init_commands = __esm({
20653
20704
  name: "prepare",
20654
20705
  description: "Install and configure the agent required by a workflow automation.",
20655
20706
  positional: ["name"],
20656
- params: S.Object({
20657
- name: S.String()
20707
+ params: S2.Object({
20708
+ name: S2.String()
20658
20709
  }),
20659
20710
  scope: ["cli"],
20660
20711
  handler: async ({ params, env }) => {
@@ -20675,8 +20726,8 @@ var init_commands = __esm({
20675
20726
  name: "prompt-preview",
20676
20727
  description: "Preview the resolved prompt for an automation.",
20677
20728
  positional: ["name"],
20678
- params: S.Object({
20679
- name: S.String()
20729
+ params: S2.Object({
20730
+ name: S2.String()
20680
20731
  }),
20681
20732
  scope: ["cli", "sdk"],
20682
20733
  handler: async ({ params, env }) => {
@@ -20698,7 +20749,7 @@ var init_commands = __esm({
20698
20749
  variablesCommand = defineCommand({
20699
20750
  name: "variables",
20700
20751
  description: "List shared prompt variables and where each value comes from.",
20701
- params: S.Object({}),
20752
+ params: S2.Object({}),
20702
20753
  scope: ["cli", "sdk"],
20703
20754
  handler: async () => {
20704
20755
  const cwd = resolveCwd();
@@ -25057,7 +25108,7 @@ function createEventQueue() {
25057
25108
  }
25058
25109
  };
25059
25110
  }
25060
- function createToolRenderState() {
25111
+ function createToolRenderState2() {
25061
25112
  return {
25062
25113
  startedToolCalls: /* @__PURE__ */ new Set(),
25063
25114
  toolCallKinds: /* @__PURE__ */ new Map(),
@@ -25209,7 +25260,7 @@ function toPromptText2(prompt) {
25209
25260
  }
25210
25261
  return lines.join("\n");
25211
25262
  }
25212
- function toEventsFromSessionUpdate2(notification, state) {
25263
+ function toEventsFromSessionUpdate(notification, state) {
25213
25264
  const update = notification.params.update;
25214
25265
  if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
25215
25266
  return [{ event: "agent_message", text: update.content.text }];
@@ -25407,7 +25458,7 @@ function createInMemoryAcpTransport2(options) {
25407
25458
  }
25408
25459
  async function runPoeAgentAcpLifecycle(options) {
25409
25460
  const sessionUpdates = [];
25410
- const toolState = createToolRenderState();
25461
+ const toolState = createToolRenderState2();
25411
25462
  let sessionId = "";
25412
25463
  let assistantText = "";
25413
25464
  const transport = createInMemoryAcpTransport2({
@@ -25432,7 +25483,7 @@ async function runPoeAgentAcpLifecycle(options) {
25432
25483
  if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
25433
25484
  assistantText += update.content.text;
25434
25485
  }
25435
- for (const event of toEventsFromSessionUpdate2(notification, toolState)) {
25486
+ for (const event of toEventsFromSessionUpdate(notification, toolState)) {
25436
25487
  emitEvent(options.onEvent, event);
25437
25488
  }
25438
25489
  }
@@ -26267,7 +26318,7 @@ async function promptForField(field) {
26267
26318
  options,
26268
26319
  initialValue: field.hasDefault ? field.defaultValue : void 0
26269
26320
  });
26270
- if (Ct(selected)) {
26321
+ if (q(selected)) {
26271
26322
  cancel("Operation cancelled.");
26272
26323
  throw new UserError("Operation cancelled.");
26273
26324
  }
@@ -26278,7 +26329,7 @@ async function promptForField(field) {
26278
26329
  message: field.displayPath,
26279
26330
  initialValue: field.hasDefault ? Boolean(field.defaultValue) : void 0
26280
26331
  });
26281
- if (Ct(selected)) {
26332
+ if (q(selected)) {
26282
26333
  cancel("Operation cancelled.");
26283
26334
  throw new UserError("Operation cancelled.");
26284
26335
  }
@@ -26288,7 +26339,7 @@ async function promptForField(field) {
26288
26339
  message: field.displayPath,
26289
26340
  initialValue: field.hasDefault && field.defaultValue !== void 0 ? formatResolvedValue(field.defaultValue) : void 0
26290
26341
  });
26291
- if (Ct(entered)) {
26342
+ if (q(entered)) {
26292
26343
  cancel("Operation cancelled.");
26293
26344
  throw new UserError("Operation cancelled.");
26294
26345
  }
@@ -26851,7 +26902,7 @@ async function executeCommand(state, services, requirementOptions) {
26851
26902
  message: "Proceed?",
26852
26903
  initialValue: true
26853
26904
  });
26854
- if (Ct(proceed)) {
26905
+ if (q(proceed)) {
26855
26906
  cancel("Operation cancelled.");
26856
26907
  throw new UserError("Operation cancelled.");
26857
26908
  }
@@ -27060,7 +27111,7 @@ function createCliContainer(dependencies) {
27060
27111
  checkAuth: async (apiKey) => await checkAuth({ apiKey }) !== null,
27061
27112
  confirm: async (message2) => {
27062
27113
  const result = await confirm2({ message: message2 });
27063
- if (Ct(result)) {
27114
+ if (q(result)) {
27064
27115
  cancel("Operation cancelled.");
27065
27116
  throw new OperationCancelledError();
27066
27117
  }
@@ -27814,7 +27865,7 @@ async function confirmUnconfiguredService(container, service, label, flags) {
27814
27865
  const shouldProceed = await confirm2({
27815
27866
  message: `${label} is not configured via poe. Do you want to proceed?`
27816
27867
  });
27817
- if (Ct(shouldProceed)) {
27868
+ if (q(shouldProceed)) {
27818
27869
  throw new OperationCancelledError();
27819
27870
  }
27820
27871
  return shouldProceed === true;
@@ -28554,7 +28605,7 @@ function registerUtilsCommand(program, container) {
28554
28605
  const utils = program.command("utils").description("Utility commands for inspecting and managing poe-code.").addHelpCommand(false);
28555
28606
  registerConfigCommand(utils, container);
28556
28607
  }
28557
- var init_utils3 = __esm({
28608
+ var init_utils4 = __esm({
28558
28609
  "src/cli/commands/utils.ts"() {
28559
28610
  "use strict";
28560
28611
  init_config4();
@@ -29082,6 +29133,7 @@ var init_types5 = __esm({
29082
29133
  this.code = code;
29083
29134
  this.name = "ToolError";
29084
29135
  }
29136
+ code;
29085
29137
  };
29086
29138
  }
29087
29139
  });
@@ -29257,6 +29309,8 @@ var init_image = __esm({
29257
29309
  this.base64Data = base64Data;
29258
29310
  this.mimeType = mimeType;
29259
29311
  }
29312
+ base64Data;
29313
+ mimeType;
29260
29314
  static async fromUrl(url) {
29261
29315
  const response = await fetch(url);
29262
29316
  if (!response.ok) {
@@ -29331,6 +29385,8 @@ var init_audio = __esm({
29331
29385
  this.base64Data = base64Data;
29332
29386
  this.mimeType = mimeType;
29333
29387
  }
29388
+ base64Data;
29389
+ mimeType;
29334
29390
  static async fromUrl(url) {
29335
29391
  const response = await fetch(url);
29336
29392
  if (!response.ok) {
@@ -29401,6 +29457,10 @@ var init_file = __esm({
29401
29457
  this.isText = isText;
29402
29458
  this.name = name;
29403
29459
  }
29460
+ data;
29461
+ mimeType;
29462
+ isText;
29463
+ name;
29404
29464
  static async fromUrl(url) {
29405
29465
  const response = await fetch(url);
29406
29466
  if (!response.ok) {
@@ -30678,7 +30738,7 @@ ${formatMcpToolsDocs()}`).action(async (options) => {
30678
30738
  message: "Select agent to configure:",
30679
30739
  options: supportedAgents.map((a) => ({ value: a, label: a }))
30680
30740
  });
30681
- if (Ct(selected)) {
30741
+ if (q(selected)) {
30682
30742
  cancel("Operation cancelled");
30683
30743
  return;
30684
30744
  }
@@ -31032,7 +31092,7 @@ function registerSkillCommand(program, container) {
31032
31092
  message: "Select agent to configure:",
31033
31093
  options: supportedAgents2.map((a) => ({ value: a, label: a }))
31034
31094
  });
31035
- if (Ct(selected)) {
31095
+ if (q(selected)) {
31036
31096
  cancel("Operation cancelled");
31037
31097
  return;
31038
31098
  }
@@ -31065,7 +31125,7 @@ function registerSkillCommand(program, container) {
31065
31125
  { value: "local", label: "Local" }
31066
31126
  ]
31067
31127
  });
31068
- if (Ct(selected)) {
31128
+ if (q(selected)) {
31069
31129
  cancel("Operation cancelled");
31070
31130
  return;
31071
31131
  }
@@ -31111,7 +31171,7 @@ function registerSkillCommand(program, container) {
31111
31171
  message: "Select agent to unconfigure:",
31112
31172
  options: supportedAgents2.map((a) => ({ value: a, label: a }))
31113
31173
  });
31114
- if (Ct(selected)) {
31174
+ if (q(selected)) {
31115
31175
  cancel("Operation cancelled");
31116
31176
  return;
31117
31177
  }
@@ -31141,7 +31201,7 @@ function registerSkillCommand(program, container) {
31141
31201
  { value: "local", label: "Local" }
31142
31202
  ]
31143
31203
  });
31144
- if (Ct(selected)) {
31204
+ if (q(selected)) {
31145
31205
  cancel("Operation cancelled");
31146
31206
  return;
31147
31207
  }
@@ -31504,7 +31564,7 @@ function registerUsageCommand(program, container) {
31504
31564
  startingAfter = result.data[result.data.length - 1].query_id;
31505
31565
  if (maxPages === void 0) {
31506
31566
  const shouldContinue = await confirm2({ message: "Load more?" });
31507
- if (Ct(shouldContinue)) {
31567
+ if (q(shouldContinue)) {
31508
31568
  throw new OperationCancelledError();
31509
31569
  }
31510
31570
  if (!shouldContinue) {
@@ -32028,7 +32088,7 @@ function registerPipelineCommand(program, container) {
32028
32088
  label: value
32029
32089
  }))
32030
32090
  });
32031
- if (Ct(selected)) {
32091
+ if (q(selected)) {
32032
32092
  cancel("Pipeline run cancelled.");
32033
32093
  return;
32034
32094
  }
@@ -32049,7 +32109,7 @@ function registerPipelineCommand(program, container) {
32049
32109
  fs: container.fs,
32050
32110
  selectPlans: async (input) => {
32051
32111
  const selected = await multiselect2(input);
32052
- if (Ct(selected)) {
32112
+ if (q(selected)) {
32053
32113
  cancel("Pipeline run cancelled.");
32054
32114
  return null;
32055
32115
  }
@@ -32057,7 +32117,7 @@ function registerPipelineCommand(program, container) {
32057
32117
  },
32058
32118
  promptForPath: async (input) => {
32059
32119
  const value = await text3(input);
32060
- if (Ct(value)) {
32120
+ if (q(value)) {
32061
32121
  cancel("Pipeline run cancelled.");
32062
32122
  return null;
32063
32123
  }
@@ -32267,7 +32327,7 @@ function registerPipelineCommand(program, container) {
32267
32327
  label: value
32268
32328
  }))
32269
32329
  });
32270
- if (Ct(selected)) {
32330
+ if (q(selected)) {
32271
32331
  cancel("Pipeline install cancelled.");
32272
32332
  return;
32273
32333
  }
@@ -32293,7 +32353,7 @@ function registerPipelineCommand(program, container) {
32293
32353
  { value: "global", label: "Global" }
32294
32354
  ]
32295
32355
  });
32296
- if (Ct(selected)) {
32356
+ if (q(selected)) {
32297
32357
  cancel("Pipeline install cancelled.");
32298
32358
  return;
32299
32359
  }
@@ -32841,7 +32901,7 @@ async function runPlanBrowser(options) {
32841
32901
  value: plan.absolutePath
32842
32902
  }))
32843
32903
  });
32844
- if (Ct(selectedPath)) {
32904
+ if (q(selectedPath)) {
32845
32905
  return;
32846
32906
  }
32847
32907
  const selectedPlan = plans.find((plan) => plan.absolutePath === selectedPath);
@@ -32860,7 +32920,7 @@ async function runPlanBrowser(options) {
32860
32920
  { label: "Delete", value: "delete" }
32861
32921
  ]
32862
32922
  });
32863
- if (Ct(action) || action === "back") {
32923
+ if (q(action) || action === "back") {
32864
32924
  continue;
32865
32925
  }
32866
32926
  if (action === "edit") {
@@ -32997,7 +33057,7 @@ async function resolveSelectedPlan(options) {
32997
33057
  value: plan.absolutePath
32998
33058
  }))
32999
33059
  });
33000
- if (Ct(selected)) {
33060
+ if (q(selected)) {
33001
33061
  throw new ValidationError("Plan selection cancelled.");
33002
33062
  }
33003
33063
  const matched = options.plans.find((plan) => plan.absolutePath === selected);
@@ -33312,7 +33372,7 @@ async function resolveDocPath(options) {
33312
33372
  value: doc.path
33313
33373
  }))
33314
33374
  });
33315
- if (Ct(selected)) {
33375
+ if (q(selected)) {
33316
33376
  cancel("Ralph run cancelled.");
33317
33377
  return null;
33318
33378
  }
@@ -33356,7 +33416,7 @@ async function promptForAgent(program) {
33356
33416
  value: config.agentId
33357
33417
  }))
33358
33418
  });
33359
- if (Ct(selected)) {
33419
+ if (q(selected)) {
33360
33420
  cancel("Ralph run cancelled.");
33361
33421
  return null;
33362
33422
  }
@@ -33393,7 +33453,7 @@ async function resolveRunIterations(options) {
33393
33453
  const entered = await text3({
33394
33454
  message: "How many Ralph iterations should run?"
33395
33455
  });
33396
- if (Ct(entered)) {
33456
+ if (q(entered)) {
33397
33457
  cancel("Ralph run cancelled.");
33398
33458
  return null;
33399
33459
  }
@@ -33423,7 +33483,7 @@ async function resolveInitIterations(options) {
33423
33483
  const entered = await text3({
33424
33484
  message: "How many Ralph iterations should run?"
33425
33485
  });
33426
- if (Ct(entered)) {
33486
+ if (q(entered)) {
33427
33487
  cancel("Ralph init cancelled.");
33428
33488
  return null;
33429
33489
  }
@@ -33773,7 +33833,7 @@ async function resolveDocPath2(options) {
33773
33833
  value: doc.path
33774
33834
  }))
33775
33835
  });
33776
- if (Ct(selected)) {
33836
+ if (q(selected)) {
33777
33837
  cancel(options.cancelMessage);
33778
33838
  return null;
33779
33839
  }
@@ -33803,7 +33863,7 @@ async function promptForAgent2(program) {
33803
33863
  value: config.agentId
33804
33864
  }))
33805
33865
  });
33806
- if (Ct(selected)) {
33866
+ if (q(selected)) {
33807
33867
  cancel("Experiment run cancelled.");
33808
33868
  return null;
33809
33869
  }
@@ -33893,7 +33953,7 @@ function registerExperimentCommand(program, container) {
33893
33953
  resources.logger.info(` Reset to ${targetHash.slice(0, 7)}`);
33894
33954
  },
33895
33955
  onExperimentComplete(index, entry) {
33896
- const scores = entry.scores ? Object.entries(entry.scores).map(([k2, v]) => `${k2}=${v}`).join(", ") : "-";
33956
+ const scores = entry.scores ? Object.entries(entry.scores).map(([k, v]) => `${k}=${v}`).join(", ") : "-";
33897
33957
  resources.logger.info(
33898
33958
  `Experiment ${index} ${entry.status} in ${formatDuration3(entry.durationMs)} \xB7 scores: ${scores}`
33899
33959
  );
@@ -33953,7 +34013,7 @@ function registerExperimentCommand(program, container) {
33953
34013
  const rows = entries.map((entry, index) => ({
33954
34014
  index: String(index + 1),
33955
34015
  status: entry.status,
33956
- scores: entry.scores ? Object.entries(entry.scores).map(([k2, v]) => `${k2}=${v}`).join(", ") : "-",
34016
+ scores: entry.scores ? Object.entries(entry.scores).map(([k, v]) => `${k}=${v}`).join(", ") : "-",
33957
34017
  duration: formatDuration3(entry.durationMs),
33958
34018
  timestamp: entry.timestamp,
33959
34019
  commit: entry.commit,
@@ -34092,7 +34152,7 @@ function registerExperimentCommand(program, container) {
34092
34152
  label: value
34093
34153
  }))
34094
34154
  });
34095
- if (Ct(selected)) {
34155
+ if (q(selected)) {
34096
34156
  cancel("Experiment install cancelled.");
34097
34157
  return;
34098
34158
  }
@@ -34118,7 +34178,7 @@ function registerExperimentCommand(program, container) {
34118
34178
  { value: "global", label: "Global" }
34119
34179
  ]
34120
34180
  });
34121
- if (Ct(selected)) {
34181
+ if (q(selected)) {
34122
34182
  cancel("Experiment install cancelled.");
34123
34183
  return;
34124
34184
  }
@@ -34374,7 +34434,7 @@ async function resolveProcessId(value) {
34374
34434
  const entered = await text3({
34375
34435
  message: "Process ID"
34376
34436
  });
34377
- if (Ct(entered)) {
34437
+ if (q(entered)) {
34378
34438
  cancel("Launch start cancelled.");
34379
34439
  return null;
34380
34440
  }
@@ -34391,7 +34451,7 @@ async function resolveCommandParts(commandArgs) {
34391
34451
  const entered = await text3({
34392
34452
  message: "Command to run"
34393
34453
  });
34394
- if (Ct(entered)) {
34454
+ if (q(entered)) {
34395
34455
  cancel("Launch start cancelled.");
34396
34456
  return null;
34397
34457
  }
@@ -34415,7 +34475,7 @@ async function resolveRuntime(options) {
34415
34475
  { label: "docker", value: "docker" }
34416
34476
  ]
34417
34477
  });
34418
- if (Ct(selected)) {
34478
+ if (q(selected)) {
34419
34479
  cancel("Launch start cancelled.");
34420
34480
  return null;
34421
34481
  }
@@ -34428,7 +34488,7 @@ async function resolveDockerImage(value) {
34428
34488
  const entered = await text3({
34429
34489
  message: "Docker image"
34430
34490
  });
34431
- if (Ct(entered)) {
34491
+ if (q(entered)) {
34432
34492
  cancel("Launch start cancelled.");
34433
34493
  return null;
34434
34494
  }
@@ -34453,7 +34513,7 @@ async function resolveRestart(restart, assumeYes) {
34453
34513
  { label: "always", value: "always" }
34454
34514
  ]
34455
34515
  });
34456
- if (Ct(selected)) {
34516
+ if (q(selected)) {
34457
34517
  cancel("Launch start cancelled.");
34458
34518
  return null;
34459
34519
  }
@@ -34631,7 +34691,7 @@ var init_package = __esm({
34631
34691
  "package.json"() {
34632
34692
  package_default = {
34633
34693
  name: "poe-code",
34634
- version: "3.0.174",
34694
+ version: "3.0.175",
34635
34695
  description: "CLI tool to configure Poe API for developer workflows.",
34636
34696
  type: "module",
34637
34697
  main: "./dist/index.js",
@@ -35125,7 +35185,7 @@ var init_program = __esm({
35125
35185
  init_login();
35126
35186
  init_logout();
35127
35187
  init_auth();
35128
- init_utils3();
35188
+ init_utils4();
35129
35189
  init_install();
35130
35190
  init_unconfigure();
35131
35191
  init_test();
@@ -35200,7 +35260,7 @@ function createPromptRunner(adapter = {
35200
35260
  text: text3,
35201
35261
  password: password2,
35202
35262
  select: select2,
35203
- isCancel: Ct,
35263
+ isCancel: q,
35204
35264
  cancel
35205
35265
  }) {
35206
35266
  const runPrompt = async (descriptor) => {