@moxt-ai/mobius 0.0.355 → 0.0.356

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/cli.js +211 -83
  2. package/dist/cli.js.map +4 -4
  3. package/dist/engine/runtime/command/registry/interactions.d.ts.map +1 -1
  4. package/dist/engine/runtime/command/registry/interactions.js +7 -1
  5. package/dist/engine/runtime/command/registry/interactions.js.map +1 -1
  6. package/dist/engine/session/live/agent-session-restore.d.ts +1 -1
  7. package/dist/engine/session/live/agent-session-restore.d.ts.map +1 -1
  8. package/dist/engine/session/live/agent-session.d.ts +1 -1
  9. package/dist/engine/session/live/agent-session.d.ts.map +1 -1
  10. package/dist/engine/session/live/agent-session.js +23 -2
  11. package/dist/engine/session/live/agent-session.js.map +1 -1
  12. package/dist/engine/session/live/session-configurations.d.ts +1 -1
  13. package/dist/engine/session/live/session-configurations.d.ts.map +1 -1
  14. package/dist/engine/session/live/session-configurations.js +1 -1
  15. package/dist/engine/session/live/session-configurations.js.map +1 -1
  16. package/dist/engine/session/live/session-restore.d.ts.map +1 -1
  17. package/dist/engine/session/live/session-restore.js +7 -1
  18. package/dist/engine/session/live/session-restore.js.map +1 -1
  19. package/dist/engine/session/native/native-session-browser.d.ts.map +1 -1
  20. package/dist/engine/session/native/native-session-browser.js +1 -0
  21. package/dist/engine/session/native/native-session-browser.js.map +1 -1
  22. package/dist/engine/session/prompt/execute-prompt.d.ts.map +1 -1
  23. package/dist/engine/session/prompt/execute-prompt.js +1 -0
  24. package/dist/engine/session/prompt/execute-prompt.js.map +1 -1
  25. package/dist/engine/session/turn/execution-receipts.d.ts +2 -0
  26. package/dist/engine/session/turn/execution-receipts.d.ts.map +1 -1
  27. package/dist/engine/session/turn/execution-receipts.js +7 -0
  28. package/dist/engine/session/turn/execution-receipts.js.map +1 -1
  29. package/dist/engine.js +201 -82
  30. package/dist/engine.js.map +4 -4
  31. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -2086,7 +2086,7 @@ var init_package = __esm({
2086
2086
  "package.json"() {
2087
2087
  package_default = {
2088
2088
  name: "@moxt-ai/mobius",
2089
- version: "0.0.355",
2089
+ version: "0.0.356",
2090
2090
  description: "Mobius CLI for pairing and running local AI agent services.",
2091
2091
  type: "module",
2092
2092
  bin: {
@@ -27963,7 +27963,9 @@ var init_native = __esm({
27963
27963
  // unrecognized delivery from a newer peer reads as absent instead of failing the snapshot.
27964
27964
  command: commandDeliverySchema.optional().catch(void 0),
27965
27965
  // Absent from older Runtimes and while the last started command is still running.
27966
- lastTurn: lastTurnOutcomeSchema.optional().catch(void 0)
27966
+ lastTurn: lastTurnOutcomeSchema.optional().catch(void 0),
27967
+ // Runtime-owned support; older Relays strip this field before exposing the snapshot.
27968
+ queuedCancellation: external_exports.literal("before-start").optional().catch(void 0)
27967
27969
  }).readonly(),
27968
27970
  external_exports.object({
27969
27971
  ...resultEnvelope,
@@ -78349,8 +78351,69 @@ var init_pi_commands = __esm({
78349
78351
  }
78350
78352
  });
78351
78353
 
78354
+ // src/engine/acp/harness/pi/upstream/dist/acp/pi-history.js
78355
+ import { readFileSync as readFileSync3 } from "node:fs";
78356
+ import { RequestError as RequestError8 } from "@agentclientprotocol/sdk";
78357
+ function readPiHistory(sessionFile) {
78358
+ try {
78359
+ const entries = /* @__PURE__ */ new Map();
78360
+ let leaf = null;
78361
+ for (const line of readFileSync3(sessionFile, "utf8").split(/\r?\n/u)) {
78362
+ if (!line.trim()) {
78363
+ continue;
78364
+ }
78365
+ const value = JSON.parse(line);
78366
+ if (external_exports.object({ type: external_exports.literal("session") }).safeParse(value).success) {
78367
+ continue;
78368
+ }
78369
+ const entry = entrySchema.parse(value);
78370
+ entries.set(entry.id, entry);
78371
+ leaf = entry.id;
78372
+ }
78373
+ const history = [];
78374
+ const visited = /* @__PURE__ */ new Set();
78375
+ while (leaf !== null) {
78376
+ const entry = entries.get(leaf);
78377
+ if (entry === void 0 || visited.has(leaf)) {
78378
+ throw new Error("Invalid Pi history branch");
78379
+ }
78380
+ visited.add(leaf);
78381
+ if (entry.type === "message") {
78382
+ const { role } = external_exports.object({ role: external_exports.string() }).parse(entry.message);
78383
+ if (role === "user" || role === "assistant" || role === "toolResult") {
78384
+ history.push({ type: "message", message: messageSchema.parse(entry.message) });
78385
+ }
78386
+ } else if (entry.type === "compaction") {
78387
+ history.push({ type: "compaction", id: entry.id, summary: external_exports.string().parse(entry.summary) });
78388
+ }
78389
+ leaf = entry.parentId;
78390
+ }
78391
+ return history.reverse();
78392
+ } catch (cause) {
78393
+ const error62 = RequestError8.internalError({ code: "PI_HISTORY_READ_FAILED" }, "Unable to read Pi history");
78394
+ error62.cause = cause;
78395
+ throw error62;
78396
+ }
78397
+ }
78398
+ var entrySchema, messageSchema;
78399
+ var init_pi_history = __esm({
78400
+ "src/engine/acp/harness/pi/upstream/dist/acp/pi-history.js"() {
78401
+ "use strict";
78402
+ init_zod();
78403
+ entrySchema = external_exports.object({
78404
+ type: external_exports.string(),
78405
+ id: external_exports.string(),
78406
+ parentId: external_exports.string().nullable()
78407
+ }).passthrough();
78408
+ messageSchema = external_exports.object({
78409
+ role: external_exports.enum(["user", "assistant", "toolResult"]),
78410
+ content: external_exports.unknown()
78411
+ }).passthrough();
78412
+ }
78413
+ });
78414
+
78352
78415
  // src/engine/acp/harness/pi/upstream/dist/acp/pi-sessions.js
78353
- import { closeSync as closeSync2, existsSync as existsSync4, openSync as openSync2, readdirSync as readdirSync4, readFileSync as readFileSync3, readSync as readSync2, statSync as statSync2 } from "node:fs";
78416
+ import { closeSync as closeSync2, existsSync as existsSync4, openSync as openSync2, readdirSync as readdirSync4, readFileSync as readFileSync4, readSync as readSync2, statSync as statSync2 } from "node:fs";
78354
78417
  import { isAbsolute as isAbsolute10, join as join19, resolve as resolve11 } from "node:path";
78355
78418
  function getPiAgentDir(environment) {
78356
78419
  const configured = environment["PI_CODING_AGENT_DIR"];
@@ -78362,7 +78425,7 @@ function readSessionDirFromSettings(agentDir) {
78362
78425
  if (!existsSync4(settingsPath)) {
78363
78426
  return null;
78364
78427
  }
78365
- const raw = readFileSync3(settingsPath, "utf8");
78428
+ const raw = readFileSync4(settingsPath, "utf8");
78366
78429
  const data = JSON.parse(raw);
78367
78430
  if (!data || typeof data !== "object" || Array.isArray(data)) {
78368
78431
  return null;
@@ -78578,7 +78641,7 @@ function pickUpdatedAtFromTail(tail) {
78578
78641
  }
78579
78642
  function pickFallbackTitleFromHead(path8) {
78580
78643
  try {
78581
- const raw = readFileSync3(path8, { encoding: "utf8" });
78644
+ const raw = readFileSync4(path8, { encoding: "utf8" });
78582
78645
  const lines = raw.split(/\r?\n/);
78583
78646
  for (const line0 of lines) {
78584
78647
  const line = line0.trim();
@@ -78683,7 +78746,7 @@ var init_pi_sessions = __esm({
78683
78746
  });
78684
78747
 
78685
78748
  // src/engine/acp/harness/pi/upstream/dist/acp/pi-settings.js
78686
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
78749
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
78687
78750
  import { join as join20, resolve as resolve12 } from "node:path";
78688
78751
  function isObject2(x) {
78689
78752
  return Boolean(x) && typeof x === "object" && !Array.isArray(x);
@@ -78705,7 +78768,7 @@ function readJsonFile2(path8) {
78705
78768
  if (!existsSync5(path8)) {
78706
78769
  return {};
78707
78770
  }
78708
- const raw = readFileSync4(path8, "utf-8");
78771
+ const raw = readFileSync5(path8, "utf-8");
78709
78772
  const data = JSON.parse(raw);
78710
78773
  return isObject2(data) ? data : {};
78711
78774
  } catch {
@@ -78755,7 +78818,7 @@ var init_pi_settings = __esm({
78755
78818
  });
78756
78819
 
78757
78820
  // src/engine/acp/harness/pi/upstream/dist/acp/extension-questions.js
78758
- import { RequestError as RequestError8 } from "@agentclientprotocol/sdk";
78821
+ import { RequestError as RequestError9 } from "@agentclientprotocol/sdk";
78759
78822
  function questionField(question) {
78760
78823
  const title2 = question.title || "Answer";
78761
78824
  switch (question.method) {
@@ -78803,7 +78866,7 @@ var init_extension_questions = __esm({
78803
78866
  external_exports.object({ ...questionBase, method: external_exports.literal("editor"), prefill: external_exports.string().max(1e4).optional() })
78804
78867
  ]).readonly();
78805
78868
  QUESTION_TIMEOUT_MS = 36e5;
78806
- PiQuestionError = class extends RequestError8 {
78869
+ PiQuestionError = class extends RequestError9 {
78807
78870
  constructor(kind, cause) {
78808
78871
  const messages = {
78809
78872
  request_failed: "Pi could not request an answer.",
@@ -78915,7 +78978,7 @@ var init_extension_questions = __esm({
78915
78978
  throw new PiQuestionError("invalid_response");
78916
78979
  }
78917
78980
  } catch (cause) {
78918
- if (!signal.aborted && !(cause instanceof RequestError8 && cause.code === -32800)) {
78981
+ if (!signal.aborted && !(cause instanceof RequestError9 && cause.code === -32800)) {
78919
78982
  turn.controller.abort(cause instanceof PiQuestionError ? cause : new PiQuestionError("request_failed", cause));
78920
78983
  }
78921
78984
  } finally {
@@ -78931,14 +78994,14 @@ var init_extension_questions = __esm({
78931
78994
  });
78932
78995
 
78933
78996
  // src/engine/acp/harness/pi/upstream/dist/acp/session-store.js
78934
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync } from "node:fs";
78997
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync } from "node:fs";
78935
78998
  import { dirname as dirname8 } from "node:path";
78936
78999
  function ensureParentDir(path8) {
78937
79000
  mkdirSync2(dirname8(path8), { recursive: true });
78938
79001
  }
78939
79002
  function loadFile(path8) {
78940
79003
  try {
78941
- const raw = readFileSync5(path8, "utf-8");
79004
+ const raw = readFileSync6(path8, "utf-8");
78942
79005
  const parsed = JSON.parse(raw);
78943
79006
  if (parsed?.version !== 1 || typeof parsed.sessions !== "object" || !parsed.sessions) {
78944
79007
  return { version: 1, sessions: {} };
@@ -78990,7 +79053,7 @@ var init_session_store = __esm({
78990
79053
  });
78991
79054
 
78992
79055
  // src/engine/acp/harness/pi/upstream/dist/acp/slash-commands.js
78993
- import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync6 } from "node:fs";
79056
+ import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync7 } from "node:fs";
78994
79057
  import { join as join21, resolve as resolve13 } from "node:path";
78995
79058
  function parseFrontmatter(content) {
78996
79059
  const frontmatter = {};
@@ -79029,7 +79092,7 @@ function loadCommandsFromDir(dir, source, subdir = "") {
79029
79092
  continue;
79030
79093
  }
79031
79094
  try {
79032
- const rawContent = readFileSync6(fullPath, "utf-8");
79095
+ const rawContent = readFileSync7(fullPath, "utf-8");
79033
79096
  const { frontmatter, content } = parseFrontmatter(rawContent);
79034
79097
  const name2 = entry.name.slice(0, -3);
79035
79098
  const sourceStr = source === "user" ? subdir ? `(user:${subdir})` : "(user)" : subdir ? `(project:${subdir})` : "(project)";
@@ -79221,9 +79284,9 @@ var init_pi_tools = __esm({
79221
79284
 
79222
79285
  // src/engine/acp/harness/pi/upstream/dist/acp/session.js
79223
79286
  import { randomUUID as randomUUID10 } from "node:crypto";
79224
- import { readFileSync as readFileSync7 } from "node:fs";
79287
+ import { readFileSync as readFileSync8 } from "node:fs";
79225
79288
  import { isAbsolute as isAbsolute11, resolve as resolvePath } from "node:path";
79226
- import { RequestError as RequestError9 } from "@agentclientprotocol/sdk";
79289
+ import { RequestError as RequestError10 } from "@agentclientprotocol/sdk";
79227
79290
  function toUsageUpdate(stats) {
79228
79291
  const used = stats?.contextUsage?.tokens;
79229
79292
  const size = stats?.contextUsage?.contextWindow;
@@ -79338,10 +79401,11 @@ function toToolKind(toolName) {
79338
79401
  return "other";
79339
79402
  }
79340
79403
  }
79341
- var SessionManager, PiAcpSession;
79404
+ var nativeUserMessageSchema, SessionManager, PiAcpSession;
79342
79405
  var init_session = __esm({
79343
79406
  "src/engine/acp/harness/pi/upstream/dist/acp/session.js"() {
79344
79407
  "use strict";
79408
+ init_zod();
79345
79409
  init_process();
79346
79410
  init_auth_required();
79347
79411
  init_extension_questions();
@@ -79349,6 +79413,16 @@ var init_session = __esm({
79349
79413
  init_slash_commands();
79350
79414
  init_bash();
79351
79415
  init_pi_tools();
79416
+ nativeUserMessageSchema = external_exports.object({
79417
+ role: external_exports.literal("user"),
79418
+ content: external_exports.union([
79419
+ external_exports.string().transform((text2) => [{ type: "text", text: text2 }]),
79420
+ external_exports.array(external_exports.discriminatedUnion("type", [
79421
+ external_exports.object({ type: external_exports.literal("text"), text: external_exports.string() }),
79422
+ external_exports.object({ type: external_exports.literal("image"), data: external_exports.string(), mimeType: external_exports.string() })
79423
+ ]))
79424
+ ])
79425
+ });
79352
79426
  SessionManager = class {
79353
79427
  sessions = /* @__PURE__ */ new Map();
79354
79428
  store = new SessionStore();
@@ -79397,7 +79471,7 @@ var init_session = __esm({
79397
79471
  });
79398
79472
  } catch (e) {
79399
79473
  if (e instanceof PiRpcSpawnError) {
79400
- throw RequestError9.internalError({ code: e.code }, e.message);
79474
+ throw RequestError10.internalError({ code: e.code }, e.message);
79401
79475
  }
79402
79476
  throw e;
79403
79477
  }
@@ -79426,7 +79500,7 @@ var init_session = __esm({
79426
79500
  get(sessionId) {
79427
79501
  const s = this.sessions.get(sessionId);
79428
79502
  if (!s) {
79429
- throw RequestError9.invalidParams(`Unknown sessionId: ${sessionId}`);
79503
+ throw RequestError10.invalidParams(`Unknown sessionId: ${sessionId}`);
79430
79504
  }
79431
79505
  return s;
79432
79506
  }
@@ -79526,8 +79600,8 @@ var init_session = __esm({
79526
79600
  if (cause instanceof PiRpcProcessError) {
79527
79601
  const pending = this.pendingTurn;
79528
79602
  const reason = pending?.questionSignal.reason;
79529
- const error62 = reason instanceof RequestError9 ? reason : RequestError9.internalError({ code: cause.code, details: cause.message });
79530
- if (!(reason instanceof RequestError9)) {
79603
+ const error62 = reason instanceof RequestError10 ? reason : RequestError10.internalError({ code: cause.code, details: cause.message });
79604
+ if (!(reason instanceof RequestError10)) {
79531
79605
  error62.cause = cause;
79532
79606
  }
79533
79607
  this.extensionQuestions.endTurn(error62);
@@ -79595,12 +79669,12 @@ var init_session = __esm({
79595
79669
  const signal = this.extensionQuestions.startTurn();
79596
79670
  try {
79597
79671
  const result = await this.proc.compact(customInstructions, { signal, timeoutMs });
79598
- if (signal.aborted && signal.reason instanceof RequestError9) {
79672
+ if (signal.aborted && signal.reason instanceof RequestError10) {
79599
79673
  throw signal.reason;
79600
79674
  }
79601
79675
  return result;
79602
79676
  } catch (cause) {
79603
- if (signal.aborted && signal.reason instanceof RequestError9) {
79677
+ if (signal.aborted && signal.reason instanceof RequestError10) {
79604
79678
  try {
79605
79679
  await this.proc.abort({ signal: this.proc.signal, timeoutMs });
79606
79680
  } catch (abortCause) {
@@ -79693,14 +79767,14 @@ var init_session = __esm({
79693
79767
  await this.publishContextUsage();
79694
79768
  const retryFailure = this.turnRetryFailure;
79695
79769
  this.turnRetryFailure = null;
79696
- if (questionSignal?.aborted && questionSignal.reason instanceof RequestError9 && !this.cancelRequested) {
79770
+ if (questionSignal?.aborted && questionSignal.reason instanceof RequestError10 && !this.cancelRequested) {
79697
79771
  this.pendingTurn?.reject(questionSignal.reason);
79698
79772
  } else if (retryFailure !== null && !this.cancelRequested) {
79699
79773
  this.pendingTurn?.reject(
79700
79774
  // The message rides in `data.details` so clients that unwrap the
79701
79775
  // JSON-RPC internal-error envelope (like Mobius) surface the real
79702
79776
  // model error; `code` keeps the failure machine-readable.
79703
- RequestError9.internalError({
79777
+ RequestError10.internalError({
79704
79778
  code: "pi_retries_exhausted",
79705
79779
  details: `Pi retries exhausted: ${retryFailure}`
79706
79780
  })
@@ -79784,6 +79858,17 @@ var init_session = __esm({
79784
79858
  handlePiEvent(ev2) {
79785
79859
  const type = String(ev2.type ?? "");
79786
79860
  switch (type) {
79861
+ case "message_start": {
79862
+ const message = nativeUserMessageSchema.safeParse(ev2.message);
79863
+ if (!message.success) {
79864
+ break;
79865
+ }
79866
+ this.lastEmit = this.lastEmit.then(() => this.conn.startUserMessage());
79867
+ for (const content of message.data.content) {
79868
+ this.emit({ sessionUpdate: "user_message_chunk", content });
79869
+ }
79870
+ break;
79871
+ }
79787
79872
  case "message_update": {
79788
79873
  const ame2 = ev2.assistantMessageEvent;
79789
79874
  if (this.turnRetryFailure !== null && (ame2?.type === "text_delta" || ame2?.type === "thinking_delta" || ame2?.type === "toolcall_start")) {
@@ -79890,7 +79975,7 @@ var init_session = __esm({
79890
79975
  if (p) {
79891
79976
  try {
79892
79977
  const abs = isAbsolute11(p) ? p : resolvePath(this.cwd, p);
79893
- snapshotOldText = readFileSync7(abs, "utf8");
79978
+ snapshotOldText = readFileSync8(abs, "utf8");
79894
79979
  this.fileSnapshots.set(toolCallId, { path: p, oldText: snapshotOldText });
79895
79980
  if (toolName === "edit") {
79896
79981
  for (const needle of getEditOldTexts(args)) {
@@ -79973,7 +80058,7 @@ var init_session = __esm({
79973
80058
  if (!isError && snapshot) {
79974
80059
  try {
79975
80060
  const abs = isAbsolute11(snapshot.path) ? snapshot.path : resolvePath(this.cwd, snapshot.path);
79976
- const newText = readFileSync7(abs, "utf8");
80061
+ const newText = readFileSync8(abs, "utf8");
79977
80062
  if (snapshot.oldText === null || newText !== snapshot.oldText) {
79978
80063
  hasStructuredDiff = true;
79979
80064
  content = [
@@ -80150,9 +80235,9 @@ var init_prompt = __esm({
80150
80235
  // src/engine/acp/harness/pi/upstream/dist/acp/agent.js
80151
80236
  import { spawnSync } from "node:child_process";
80152
80237
  import { randomUUID as randomUUID11 } from "node:crypto";
80153
- import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync8, realpathSync as realpathSync3, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
80238
+ import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync9, realpathSync as realpathSync3, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
80154
80239
  import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute12, join as join22 } from "node:path";
80155
- import { RequestError as RequestError10 } from "@agentclientprotocol/sdk";
80240
+ import { RequestError as RequestError11 } from "@agentclientprotocol/sdk";
80156
80241
  function thinkingLevelName(id) {
80157
80242
  return id.split(/[_-]/u).map((part) => part.length === 0 ? part : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
80158
80243
  }
@@ -80356,7 +80441,7 @@ async function setSessionModel(proc, requestedModelId) {
80356
80441
  }
80357
80442
  }
80358
80443
  if (!provider || !modelId) {
80359
- throw RequestError10.invalidParams(`Unknown modelId: ${requestedModelId}`);
80444
+ throw RequestError11.invalidParams(`Unknown modelId: ${requestedModelId}`);
80360
80445
  }
80361
80446
  await proc.setModel(provider, modelId);
80362
80447
  }
@@ -80510,7 +80595,7 @@ function buildStartupInfo(opts) {
80510
80595
  ];
80511
80596
  for (const settingsPath of settingsPaths) {
80512
80597
  try {
80513
- const settings = JSON.parse(readFileSync8(settingsPath, "utf-8"));
80598
+ const settings = JSON.parse(readFileSync9(settingsPath, "utf-8"));
80514
80599
  const pkgs = Array.isArray(settings?.packages) ? settings.packages : [];
80515
80600
  for (const pkg of pkgs) {
80516
80601
  const s = String(pkg);
@@ -80543,6 +80628,7 @@ var init_agent2 = __esm({
80543
80628
  init_auth_required();
80544
80629
  init_paths();
80545
80630
  init_pi_commands();
80631
+ init_pi_history();
80546
80632
  init_pi_sessions();
80547
80633
  init_pi_settings();
80548
80634
  init_session();
@@ -80638,7 +80724,7 @@ var init_agent2 = __esm({
80638
80724
  const restorePromise = (async () => {
80639
80725
  const stored = this.findStoredSession(sessionId);
80640
80726
  if (!stored) {
80641
- throw RequestError10.invalidParams(`Unknown sessionId: ${sessionId}`);
80727
+ throw RequestError11.invalidParams(`Unknown sessionId: ${sessionId}`);
80642
80728
  }
80643
80729
  const cwd = opts?.cwd ?? stored.cwd;
80644
80730
  let proc;
@@ -80651,7 +80737,7 @@ var init_agent2 = __esm({
80651
80737
  });
80652
80738
  } catch (e) {
80653
80739
  if (e?.name === "PiRpcSpawnError") {
80654
- throw RequestError10.internalError({ code: e?.code }, String(e?.message ?? e));
80740
+ throw RequestError11.internalError({ code: e?.code }, String(e?.message ?? e));
80655
80741
  }
80656
80742
  throw e;
80657
80743
  }
@@ -80711,7 +80797,7 @@ var init_agent2 = __esm({
80711
80797
  }
80712
80798
  async newSession(params) {
80713
80799
  if (!isAbsolute12(params.cwd)) {
80714
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
80800
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
80715
80801
  }
80716
80802
  this.lastSessionCwd = params.cwd;
80717
80803
  const fileCommands = loadSlashCommands(params.cwd, this.environment);
@@ -80750,16 +80836,16 @@ var init_agent2 = __esm({
80750
80836
  }
80751
80837
  if (availableModelsErr) {
80752
80838
  this.cleanupFailedNewSession(session.sessionId, state);
80753
- throw RequestError10.internalError({}, String(availableModelsErr?.message ?? availableModelsErr));
80839
+ throw RequestError11.internalError({}, String(availableModelsErr?.message ?? availableModelsErr));
80754
80840
  }
80755
80841
  const rawModelsCount = Array.isArray(availableModels?.models) ? availableModels.models.length : 0;
80756
80842
  if (rawModelsCount === 0) {
80757
80843
  this.cleanupFailedNewSession(session.sessionId, state);
80758
- throw RequestError10.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80844
+ throw RequestError11.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80759
80845
  }
80760
80846
  if (stateErr && maybeAuthRequiredError(stateErr)) {
80761
80847
  this.cleanupFailedNewSession(session.sessionId, state);
80762
- throw RequestError10.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80848
+ throw RequestError11.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80763
80849
  }
80764
80850
  let configuration;
80765
80851
  try {
@@ -80769,7 +80855,7 @@ var init_agent2 = __esm({
80769
80855
  configuration = await getSessionConfiguration(session.proc, { state, availableModels });
80770
80856
  } catch (err) {
80771
80857
  this.cleanupFailedNewSession(session.sessionId, state);
80772
- throw maybeAuthRequiredError(err) ?? RequestError10.internalError({}, String(err?.message ?? err));
80858
+ throw maybeAuthRequiredError(err) ?? RequestError11.internalError({}, String(err?.message ?? err));
80773
80859
  }
80774
80860
  const { configOptions, models, modes } = configuration;
80775
80861
  const quietStartup = getQuietStartup(params.cwd, this.environment);
@@ -80849,16 +80935,6 @@ var init_agent2 = __esm({
80849
80935
  }
80850
80936
  async promptSubmission(params, submission) {
80851
80937
  const session = await this.restoreSession(params.sessionId);
80852
- this.conn.startUserMessage();
80853
- for (const content of params.prompt) {
80854
- if (submission.aborted) {
80855
- return { stopReason: "cancelled" };
80856
- }
80857
- await this.conn.sessionUpdate({
80858
- sessionId: params.sessionId,
80859
- update: { sessionUpdate: "user_message_chunk", content }
80860
- });
80861
- }
80862
80938
  if (submission.aborted) {
80863
80939
  return { stopReason: "cancelled" };
80864
80940
  }
@@ -80869,6 +80945,9 @@ var init_agent2 = __esm({
80869
80945
  const cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space);
80870
80946
  const argsString = space === -1 ? "" : trimmed.slice(space + 1);
80871
80947
  const args = parseCommandArgs(argsString);
80948
+ if (builtinAvailableCommands().some((command) => command.name === cmd)) {
80949
+ this.conn.startUserMessage();
80950
+ }
80872
80951
  if (cmd === "compact") {
80873
80952
  const customInstructions = args.join(" ").trim() || void 0;
80874
80953
  const compactionId = randomUUID11();
@@ -81130,7 +81209,7 @@ ${JSON.stringify(stats, null, 2)}`;
81130
81209
  }
81131
81210
  let text2 = "";
81132
81211
  try {
81133
- text2 = readFileSync8(changelogPath, "utf-8");
81212
+ text2 = readFileSync9(changelogPath, "utf-8");
81134
81213
  } catch (e) {
81135
81214
  await this.conn.sessionUpdate({
81136
81215
  sessionId: session.sessionId,
@@ -81174,7 +81253,7 @@ ${JSON.stringify(stats, null, 2)}`;
81174
81253
  return { stopReason: "end_turn" };
81175
81254
  }
81176
81255
  try {
81177
- const raw = readFileSync8(sessionFile, "utf-8");
81256
+ const raw = readFileSync9(sessionFile, "utf-8");
81178
81257
  if (raw.trim().length === 0) {
81179
81258
  await this.conn.sessionUpdate({
81180
81259
  sessionId: session.sessionId,
@@ -81297,7 +81376,7 @@ ${JSON.stringify(stats, null, 2)}`;
81297
81376
  signal.throwIfAborted();
81298
81377
  const parsed = steerRequestSchema.safeParse(params);
81299
81378
  if (!parsed.success) {
81300
- throw RequestError10.invalidParams("Invalid steering request");
81379
+ throw RequestError11.invalidParams("Invalid steering request");
81301
81380
  }
81302
81381
  const session = this.sessions.maybeGet(parsed.data.sessionId);
81303
81382
  if (session === void 0) {
@@ -81309,14 +81388,6 @@ ${JSON.stringify(stats, null, 2)}`;
81309
81388
  case "idle":
81310
81389
  return { outcome: "promptRequired", reason: "noRunningTurn" };
81311
81390
  case "injected": {
81312
- this.conn.startUserMessage();
81313
- for (const content of parsed.data.prompt) {
81314
- signal.throwIfAborted();
81315
- await this.conn.sessionUpdate({
81316
- sessionId: parsed.data.sessionId,
81317
- update: { sessionUpdate: "user_message_chunk", content }
81318
- });
81319
- }
81320
81391
  return { outcome: "injected" };
81321
81392
  }
81322
81393
  }
@@ -81350,11 +81421,11 @@ ${JSON.stringify(stats, null, 2)}`;
81350
81421
  }
81351
81422
  async forkSession(params) {
81352
81423
  if (!isAbsolute12(params.cwd)) {
81353
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81424
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81354
81425
  }
81355
81426
  const source = this.findStoredSession(params.sessionId);
81356
81427
  if (!source) {
81357
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81428
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81358
81429
  }
81359
81430
  this.lastSessionCwd = params.cwd;
81360
81431
  const fileCommands = loadSlashCommands(params.cwd, this.environment);
@@ -81416,13 +81487,13 @@ ${JSON.stringify(stats, null, 2)}`;
81416
81487
  }
81417
81488
  async resumeSession(params) {
81418
81489
  if (!isAbsolute12(params.cwd)) {
81419
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81490
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81420
81491
  }
81421
81492
  this.sessions.close(params.sessionId);
81422
81493
  this.lastSessionCwd = params.cwd;
81423
81494
  const stored = this.findStoredSession(params.sessionId);
81424
81495
  if (!stored) {
81425
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81496
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81426
81497
  }
81427
81498
  const session = await this.restoreSession(params.sessionId, {
81428
81499
  cwd: params.cwd,
@@ -81487,13 +81558,13 @@ ${JSON.stringify(stats, null, 2)}`;
81487
81558
  }
81488
81559
  async loadSession(params) {
81489
81560
  if (!isAbsolute12(params.cwd)) {
81490
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81561
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81491
81562
  }
81492
81563
  this.sessions.close(params.sessionId);
81493
81564
  this.lastSessionCwd = params.cwd;
81494
81565
  const stored = this.findStoredSession(params.sessionId);
81495
81566
  if (!stored) {
81496
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81567
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81497
81568
  }
81498
81569
  const enableSkillCommands = getEnableSkillCommands(params.cwd, this.environment);
81499
81570
  const session = await this.restoreSession(params.sessionId, {
@@ -81516,9 +81587,29 @@ ${JSON.stringify(stats, null, 2)}`;
81516
81587
  cwd: params.cwd,
81517
81588
  sessionFile: stored.sessionFile
81518
81589
  });
81519
- const data = await proc.getMessages();
81520
- const messages = Array.isArray(data?.messages) ? data.messages : [];
81521
- for (const m of messages) {
81590
+ for (const entry of readPiHistory(stored.sessionFile)) {
81591
+ if (entry.type === "compaction") {
81592
+ await this.conn.sessionUpdate({
81593
+ sessionId: session.sessionId,
81594
+ update: {
81595
+ sessionUpdate: "compaction_update",
81596
+ compactionId: entry.id,
81597
+ status: "completed"
81598
+ }
81599
+ });
81600
+ if (entry.summary) {
81601
+ await this.conn.sessionUpdate({
81602
+ sessionId: session.sessionId,
81603
+ update: {
81604
+ sessionUpdate: "compaction_summary_chunk",
81605
+ compactionId: entry.id,
81606
+ content: { type: "text", text: entry.summary }
81607
+ }
81608
+ });
81609
+ }
81610
+ continue;
81611
+ }
81612
+ const m = entry.message;
81522
81613
  const role = String(m?.role ?? "");
81523
81614
  if (role === "user") {
81524
81615
  const text2 = normalizePiMessageText(m?.content);
@@ -81668,7 +81759,7 @@ ${JSON.stringify(stats, null, 2)}`;
81668
81759
  const session = await this.restoreSession(params.sessionId);
81669
81760
  const mode = params.modeId;
81670
81761
  if (typeof mode !== "string" || mode.length === 0) {
81671
- throw RequestError10.invalidParams("Expected nonempty string modeId");
81762
+ throw RequestError11.invalidParams("Expected nonempty string modeId");
81672
81763
  }
81673
81764
  await session.proc.setThinkingLevel(mode);
81674
81765
  await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
@@ -81679,18 +81770,18 @@ ${JSON.stringify(stats, null, 2)}`;
81679
81770
  const configId = String(params.configId);
81680
81771
  let modelChanged = false;
81681
81772
  if (typeof params.value !== "string") {
81682
- throw RequestError10.invalidParams(`Expected string value for config option: ${configId}`);
81773
+ throw RequestError11.invalidParams(`Expected string value for config option: ${configId}`);
81683
81774
  }
81684
81775
  if (configId === MODEL_CONFIG_ID2) {
81685
81776
  await setSessionModel(session.proc, params.value);
81686
81777
  modelChanged = true;
81687
81778
  } else if (configId === THOUGHT_LEVEL_CONFIG_ID) {
81688
81779
  if (params.value.length === 0) {
81689
- throw RequestError10.invalidParams("Expected nonempty thinking level");
81780
+ throw RequestError11.invalidParams("Expected nonempty thinking level");
81690
81781
  }
81691
81782
  await session.proc.setThinkingLevel(params.value);
81692
81783
  } else {
81693
- throw RequestError10.invalidParams(`Unknown config option: ${configId}`);
81784
+ throw RequestError11.invalidParams(`Unknown config option: ${configId}`);
81694
81785
  }
81695
81786
  const configOptions = await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
81696
81787
  if (modelChanged) {
@@ -91190,7 +91281,7 @@ var init_environment_proxy = __esm({
91190
91281
  });
91191
91282
 
91192
91283
  // src/engine/storage/logs/bounded-log.ts
91193
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
91284
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
91194
91285
  import { join as join26 } from "node:path";
91195
91286
  var BoundedLineLog;
91196
91287
  var init_bounded_log = __esm({
@@ -91235,7 +91326,7 @@ var init_bounded_log = __esm({
91235
91326
  appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
91236
91327
  return;
91237
91328
  }
91238
- const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
91329
+ const lines = `${existingBytes === 0 ? "" : readFileSync10(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
91239
91330
  let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
91240
91331
  while (totalBytes > this.#maximumBytes && lines.length > 0) {
91241
91332
  const oldest = lines.shift();
@@ -91256,7 +91347,7 @@ var init_bounded_log = __esm({
91256
91347
  });
91257
91348
 
91258
91349
  // src/engine/storage/logs/log-files.ts
91259
- import { readFileSync as readFileSync10 } from "node:fs";
91350
+ import { readFileSync as readFileSync11 } from "node:fs";
91260
91351
  import { join as join27 } from "node:path";
91261
91352
  function unhandledRejectionLogFilename(role) {
91262
91353
  return `unhandled-rejections-${role}.log`;
@@ -91273,7 +91364,7 @@ function processLogPaths(dataDirectory) {
91273
91364
  }
91274
91365
  function readLogText(path8) {
91275
91366
  try {
91276
- return readFileSync10(path8, "utf8");
91367
+ return readFileSync11(path8, "utf8");
91277
91368
  } catch {
91278
91369
  return null;
91279
91370
  }
@@ -93205,7 +93296,7 @@ var init_session_configurations = __esm({
93205
93296
  restore = async (stored, options, apply, signal) => {
93206
93297
  this.#selected = stored;
93207
93298
  for (const selection of this.#selected) {
93208
- const current = options.find(
93299
+ const current = options().find(
93209
93300
  (option) => option.id === selection.configId && option.type === selection.type
93210
93301
  );
93211
93302
  if (current === void 0) {
@@ -93414,6 +93505,7 @@ async function restoreSession(session, signal, recovery, origin) {
93414
93505
  session.store.remove(session.sessionId);
93415
93506
  stored = session.metrics.measureSync("session-state-read", () => session.store.read(session.sessionId));
93416
93507
  }
93508
+ const forkSource = origin?.kind === "fork" ? session.store.findNative(session.agentId, origin.nativeSessionId)[0] : void 0;
93417
93509
  let lifecycleResponse2;
93418
93510
  if (origin?.kind === "fork") {
93419
93511
  if (!session.capabilities.unstableForkSession) {
@@ -93575,7 +93667,9 @@ async function restoreSession(session, signal, recovery, origin) {
93575
93667
  }
93576
93668
  session.restrictSessionCapabilities(lifecycleResponse2);
93577
93669
  session.setConfigOptions(session.sessionConfigProtocol.normalizeLifecycle(lifecycleResponse2));
93578
- if (stored instanceof FoundStoredSession && session.restored) {
93670
+ if (forkSource !== void 0) {
93671
+ await session.restoreStoredConfigurations(forkSource, signal, "fork");
93672
+ } else if (stored instanceof FoundStoredSession && session.restored) {
93579
93673
  await session.restoreStoredConfigurations(stored.session, signal);
93580
93674
  }
93581
93675
  await session.drained();
@@ -93819,13 +93913,31 @@ var init_agent_session = __esm({
93819
93913
  this.writeStoredSession((/* @__PURE__ */ new Date()).toISOString());
93820
93914
  }
93821
93915
  };
93822
- restoreStoredConfigurations = async (session, signal) => {
93916
+ restoreStoredConfigurations = async (session, signal, intent = "restore") => {
93917
+ const configurations = intent === "fork" ? session.configurations.toSorted(
93918
+ (left, right) => Number(right.configId === "model") - Number(left.configId === "model")
93919
+ ) : session.configurations;
93823
93920
  await this.#sessionConfigurations.restore(
93824
- session.configurations,
93825
- this.#configOptions,
93921
+ configurations,
93922
+ () => this.#configOptions,
93826
93923
  this.#applyConfiguration,
93827
93924
  signal
93828
93925
  );
93926
+ if (intent === "fork") {
93927
+ for (const selection of session.configurations) {
93928
+ if (selection.configId !== "mode") {
93929
+ continue;
93930
+ }
93931
+ const current = this.#configOptions.find((option) => option.id === selection.configId);
93932
+ if (current?.type !== selection.type || (selection.type === "select" ? current.currentValue !== selection.value : current.booleanValue !== selection.booleanValue)) {
93933
+ throw new AcpExecutionError(
93934
+ "The Agent could not preserve the source Session mode for this Fork",
93935
+ {},
93936
+ "invalid_session_configuration"
93937
+ );
93938
+ }
93939
+ }
93940
+ }
93829
93941
  };
93830
93942
  restrictSessionCapabilities = (response) => {
93831
93943
  this.#capabilities = restrictAcpSessionCapabilities(this.#capabilities, response);
@@ -95311,7 +95423,8 @@ var init_native_session_browser = __esm({
95311
95423
  requestId: command.requestId,
95312
95424
  sessionId: command.sessionId,
95313
95425
  targetSessionId: command.targetSessionId,
95314
- ...await this.#activeTurn(command, options)
95426
+ ...await this.#activeTurn(command, options),
95427
+ queuedCancellation: "before-start"
95315
95428
  };
95316
95429
  }
95317
95430
  const capabilities = await options.adapter.getCapabilities(options);
@@ -95945,6 +96058,11 @@ var init_execution_receipts = __esm({
95945
96058
  return void 0;
95946
96059
  }
95947
96060
  };
96061
+ /** Started identities remain authoritative after their detailed receipt is evicted. */
96062
+ hasStarted = (commandId, sessionId) => {
96063
+ const receipt = this.#executions.get(commandId);
96064
+ return receipt === void 0 ? this.#table.identity(commandId)?.sessionId === sessionId : receipt.sessionId === sessionId && receipt.started;
96065
+ };
95948
96066
  /** Reserves an unseen command for cancellation before a delayed prompt can claim its identity. */
95949
96067
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
95950
96068
  const existing = this.#executions.get(commandId);
@@ -98730,10 +98848,19 @@ var init_interactions2 = __esm({
98730
98848
  if (message.kind !== SESSION_CANCEL_BEFORE_START_KIND) {
98731
98849
  throw new Error("Command kind mismatch");
98732
98850
  }
98851
+ if (operations.hasStarted(message.commandId, message.sessionId)) {
98852
+ reportOperationFailure(
98853
+ socket,
98854
+ message.commandId,
98855
+ message.sessionId,
98856
+ new SessionError("turn_already_started", "The message already started and could not be withdrawn")
98857
+ );
98858
+ return;
98859
+ }
98733
98860
  const turn = sessionTurns.get(message.commandId, message.sessionId);
98734
98861
  if (turn === void 0) {
98735
98862
  const outcome = operations.recordCancellationBeforeAdmission(message.commandId, message.sessionId);
98736
- if (outcome !== void 0) {
98863
+ if (outcome?.type === "lifecycle-metadata" && outcome.payload.kind === "prompt.completed" && outcome.payload.stopReason === "cancelled") {
98737
98864
  void eventProjection.replayOutcome(message.sessionId, outcome).catch((error62) => {
98738
98865
  reportOperationFailure(socket, message.commandId, message.sessionId, error62);
98739
98866
  });
@@ -99230,6 +99357,7 @@ async function executePrompt({
99230
99357
  );
99231
99358
  prepared = await sessions.prepareExecutionSession(preparation);
99232
99359
  }
99360
+ signal.throwIfAborted();
99233
99361
  operations.markExecutionStarted(command.commandId);
99234
99362
  if (availability.disposition === SessionPromptDisposition.Steer) {
99235
99363
  if (!recordSteeringPrompt()) {