@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/engine.js CHANGED
@@ -21441,7 +21441,9 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
21441
21441
  // unrecognized delivery from a newer peer reads as absent instead of failing the snapshot.
21442
21442
  command: commandDeliverySchema.optional().catch(void 0),
21443
21443
  // Absent from older Runtimes and while the last started command is still running.
21444
- lastTurn: lastTurnOutcomeSchema.optional().catch(void 0)
21444
+ lastTurn: lastTurnOutcomeSchema.optional().catch(void 0),
21445
+ // Runtime-owned support; older Relays strip this field before exposing the snapshot.
21446
+ queuedCancellation: external_exports.literal("before-start").optional().catch(void 0)
21445
21447
  }).readonly(),
21446
21448
  external_exports.object({
21447
21449
  ...resultEnvelope,
@@ -71070,9 +71072,9 @@ import {
71070
71072
  // src/engine/acp/harness/pi/upstream/dist/acp/agent.js
71071
71073
  import { spawnSync } from "node:child_process";
71072
71074
  import { randomUUID as randomUUID11 } from "node:crypto";
71073
- import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync8, realpathSync as realpathSync3, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
71075
+ import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync9, realpathSync as realpathSync3, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
71074
71076
  import { basename as basename5, dirname as dirname8, isAbsolute as isAbsolute12, join as join20 } from "node:path";
71075
- import { RequestError as RequestError10 } from "@agentclientprotocol/sdk";
71077
+ import { RequestError as RequestError11 } from "@agentclientprotocol/sdk";
71076
71078
 
71077
71079
  // src/engine/acp/harness/pi/upstream/dist/pi-rpc/process.js
71078
71080
  import { spawn as spawn5 } from "node:child_process";
@@ -71585,8 +71587,62 @@ function toAvailableCommandsFromPiGetCommands(data, opts) {
71585
71587
  return { commands: out2, raw: commandsRaw };
71586
71588
  }
71587
71589
 
71590
+ // src/engine/acp/harness/pi/upstream/dist/acp/pi-history.js
71591
+ import { readFileSync as readFileSync3 } from "node:fs";
71592
+ import { RequestError as RequestError8 } from "@agentclientprotocol/sdk";
71593
+ var entrySchema = external_exports.object({
71594
+ type: external_exports.string(),
71595
+ id: external_exports.string(),
71596
+ parentId: external_exports.string().nullable()
71597
+ }).passthrough();
71598
+ var messageSchema = external_exports.object({
71599
+ role: external_exports.enum(["user", "assistant", "toolResult"]),
71600
+ content: external_exports.unknown()
71601
+ }).passthrough();
71602
+ function readPiHistory(sessionFile) {
71603
+ try {
71604
+ const entries = /* @__PURE__ */ new Map();
71605
+ let leaf = null;
71606
+ for (const line of readFileSync3(sessionFile, "utf8").split(/\r?\n/u)) {
71607
+ if (!line.trim()) {
71608
+ continue;
71609
+ }
71610
+ const value = JSON.parse(line);
71611
+ if (external_exports.object({ type: external_exports.literal("session") }).safeParse(value).success) {
71612
+ continue;
71613
+ }
71614
+ const entry = entrySchema.parse(value);
71615
+ entries.set(entry.id, entry);
71616
+ leaf = entry.id;
71617
+ }
71618
+ const history = [];
71619
+ const visited = /* @__PURE__ */ new Set();
71620
+ while (leaf !== null) {
71621
+ const entry = entries.get(leaf);
71622
+ if (entry === void 0 || visited.has(leaf)) {
71623
+ throw new Error("Invalid Pi history branch");
71624
+ }
71625
+ visited.add(leaf);
71626
+ if (entry.type === "message") {
71627
+ const { role } = external_exports.object({ role: external_exports.string() }).parse(entry.message);
71628
+ if (role === "user" || role === "assistant" || role === "toolResult") {
71629
+ history.push({ type: "message", message: messageSchema.parse(entry.message) });
71630
+ }
71631
+ } else if (entry.type === "compaction") {
71632
+ history.push({ type: "compaction", id: entry.id, summary: external_exports.string().parse(entry.summary) });
71633
+ }
71634
+ leaf = entry.parentId;
71635
+ }
71636
+ return history.reverse();
71637
+ } catch (cause) {
71638
+ const error62 = RequestError8.internalError({ code: "PI_HISTORY_READ_FAILED" }, "Unable to read Pi history");
71639
+ error62.cause = cause;
71640
+ throw error62;
71641
+ }
71642
+ }
71643
+
71588
71644
  // src/engine/acp/harness/pi/upstream/dist/acp/pi-sessions.js
71589
- 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";
71645
+ 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";
71590
71646
  import { isAbsolute as isAbsolute10, join as join17, resolve as resolve10 } from "node:path";
71591
71647
  var DEFAULT_TAIL_BYTES = 256 * 1024;
71592
71648
  var DEFAULT_HEAD_BYTES = 64 * 1024;
@@ -71600,7 +71656,7 @@ function readSessionDirFromSettings(agentDir) {
71600
71656
  if (!existsSync4(settingsPath)) {
71601
71657
  return null;
71602
71658
  }
71603
- const raw = readFileSync3(settingsPath, "utf8");
71659
+ const raw = readFileSync4(settingsPath, "utf8");
71604
71660
  const data = JSON.parse(raw);
71605
71661
  if (!data || typeof data !== "object" || Array.isArray(data)) {
71606
71662
  return null;
@@ -71816,7 +71872,7 @@ function pickUpdatedAtFromTail(tail) {
71816
71872
  }
71817
71873
  function pickFallbackTitleFromHead(path7) {
71818
71874
  try {
71819
- const raw = readFileSync3(path7, { encoding: "utf8" });
71875
+ const raw = readFileSync4(path7, { encoding: "utf8" });
71820
71876
  const lines = raw.split(/\r?\n/);
71821
71877
  for (const line0 of lines) {
71822
71878
  const line = line0.trim();
@@ -71912,7 +71968,7 @@ function findPiSession(sessionId, environment = process.env) {
71912
71968
  }
71913
71969
 
71914
71970
  // src/engine/acp/harness/pi/upstream/dist/acp/pi-settings.js
71915
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
71971
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
71916
71972
  import { join as join18, resolve as resolve11 } from "node:path";
71917
71973
  function isObject2(x) {
71918
71974
  return Boolean(x) && typeof x === "object" && !Array.isArray(x);
@@ -71934,7 +71990,7 @@ function readJsonFile2(path7) {
71934
71990
  if (!existsSync5(path7)) {
71935
71991
  return {};
71936
71992
  }
71937
- const raw = readFileSync4(path7, "utf-8");
71993
+ const raw = readFileSync5(path7, "utf-8");
71938
71994
  const data = JSON.parse(raw);
71939
71995
  return isObject2(data) ? data : {};
71940
71996
  } catch {
@@ -71979,12 +72035,12 @@ function getQuietStartup(cwd, environment = process.env) {
71979
72035
 
71980
72036
  // src/engine/acp/harness/pi/upstream/dist/acp/session.js
71981
72037
  import { randomUUID as randomUUID10 } from "node:crypto";
71982
- import { readFileSync as readFileSync7 } from "node:fs";
72038
+ import { readFileSync as readFileSync8 } from "node:fs";
71983
72039
  import { isAbsolute as isAbsolute11, resolve as resolvePath } from "node:path";
71984
- import { RequestError as RequestError9 } from "@agentclientprotocol/sdk";
72040
+ import { RequestError as RequestError10 } from "@agentclientprotocol/sdk";
71985
72041
 
71986
72042
  // src/engine/acp/harness/pi/upstream/dist/acp/extension-questions.js
71987
- import { RequestError as RequestError8 } from "@agentclientprotocol/sdk";
72043
+ import { RequestError as RequestError9 } from "@agentclientprotocol/sdk";
71988
72044
  var questionBase = {
71989
72045
  id: external_exports.string().min(1).max(255),
71990
72046
  title: external_exports.string().max(255),
@@ -72001,7 +72057,7 @@ var questionSchema = external_exports.discriminatedUnion("method", [
72001
72057
  external_exports.object({ ...questionBase, method: external_exports.literal("editor"), prefill: external_exports.string().max(1e4).optional() })
72002
72058
  ]).readonly();
72003
72059
  var QUESTION_TIMEOUT_MS = 36e5;
72004
- var PiQuestionError = class extends RequestError8 {
72060
+ var PiQuestionError = class extends RequestError9 {
72005
72061
  constructor(kind, cause) {
72006
72062
  const messages = {
72007
72063
  request_failed: "Pi could not request an answer.",
@@ -72139,7 +72195,7 @@ var PiExtensionQuestions = class {
72139
72195
  throw new PiQuestionError("invalid_response");
72140
72196
  }
72141
72197
  } catch (cause) {
72142
- if (!signal.aborted && !(cause instanceof RequestError8 && cause.code === -32800)) {
72198
+ if (!signal.aborted && !(cause instanceof RequestError9 && cause.code === -32800)) {
72143
72199
  turn.controller.abort(cause instanceof PiQuestionError ? cause : new PiQuestionError("request_failed", cause));
72144
72200
  }
72145
72201
  } finally {
@@ -72153,14 +72209,14 @@ var PiExtensionQuestions = class {
72153
72209
  };
72154
72210
 
72155
72211
  // src/engine/acp/harness/pi/upstream/dist/acp/session-store.js
72156
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync } from "node:fs";
72212
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync } from "node:fs";
72157
72213
  import { dirname as dirname7 } from "node:path";
72158
72214
  function ensureParentDir(path7) {
72159
72215
  mkdirSync2(dirname7(path7), { recursive: true });
72160
72216
  }
72161
72217
  function loadFile(path7) {
72162
72218
  try {
72163
- const raw = readFileSync5(path7, "utf-8");
72219
+ const raw = readFileSync6(path7, "utf-8");
72164
72220
  const parsed = JSON.parse(raw);
72165
72221
  if (parsed?.version !== 1 || typeof parsed.sessions !== "object" || !parsed.sessions) {
72166
72222
  return { version: 1, sessions: {} };
@@ -72205,7 +72261,7 @@ var SessionStore = class {
72205
72261
  };
72206
72262
 
72207
72263
  // src/engine/acp/harness/pi/upstream/dist/acp/slash-commands.js
72208
- import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync6 } from "node:fs";
72264
+ import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync7 } from "node:fs";
72209
72265
  import { join as join19, resolve as resolve12 } from "node:path";
72210
72266
  function parseFrontmatter(content) {
72211
72267
  const frontmatter = {};
@@ -72244,7 +72300,7 @@ function loadCommandsFromDir(dir, source, subdir = "") {
72244
72300
  continue;
72245
72301
  }
72246
72302
  try {
72247
- const rawContent = readFileSync6(fullPath, "utf-8");
72303
+ const rawContent = readFileSync7(fullPath, "utf-8");
72248
72304
  const { frontmatter, content } = parseFrontmatter(rawContent);
72249
72305
  const name2 = entry.name.slice(0, -3);
72250
72306
  const sourceStr = source === "user" ? subdir ? `(user:${subdir})` : "(user)" : subdir ? `(project:${subdir})` : "(project)";
@@ -72419,6 +72475,16 @@ ${stderr}`);
72419
72475
  }
72420
72476
 
72421
72477
  // src/engine/acp/harness/pi/upstream/dist/acp/session.js
72478
+ var nativeUserMessageSchema = external_exports.object({
72479
+ role: external_exports.literal("user"),
72480
+ content: external_exports.union([
72481
+ external_exports.string().transform((text2) => [{ type: "text", text: text2 }]),
72482
+ external_exports.array(external_exports.discriminatedUnion("type", [
72483
+ external_exports.object({ type: external_exports.literal("text"), text: external_exports.string() }),
72484
+ external_exports.object({ type: external_exports.literal("image"), data: external_exports.string(), mimeType: external_exports.string() })
72485
+ ]))
72486
+ ])
72487
+ });
72422
72488
  function toUsageUpdate(stats) {
72423
72489
  const used = stats?.contextUsage?.tokens;
72424
72490
  const size = stats?.contextUsage?.contextWindow;
@@ -72564,7 +72630,7 @@ var SessionManager = class {
72564
72630
  });
72565
72631
  } catch (e) {
72566
72632
  if (e instanceof PiRpcSpawnError) {
72567
- throw RequestError9.internalError({ code: e.code }, e.message);
72633
+ throw RequestError10.internalError({ code: e.code }, e.message);
72568
72634
  }
72569
72635
  throw e;
72570
72636
  }
@@ -72593,7 +72659,7 @@ var SessionManager = class {
72593
72659
  get(sessionId) {
72594
72660
  const s = this.sessions.get(sessionId);
72595
72661
  if (!s) {
72596
- throw RequestError9.invalidParams(`Unknown sessionId: ${sessionId}`);
72662
+ throw RequestError10.invalidParams(`Unknown sessionId: ${sessionId}`);
72597
72663
  }
72598
72664
  return s;
72599
72665
  }
@@ -72693,8 +72759,8 @@ var PiAcpSession = class {
72693
72759
  if (cause instanceof PiRpcProcessError) {
72694
72760
  const pending = this.pendingTurn;
72695
72761
  const reason = pending?.questionSignal.reason;
72696
- const error62 = reason instanceof RequestError9 ? reason : RequestError9.internalError({ code: cause.code, details: cause.message });
72697
- if (!(reason instanceof RequestError9)) {
72762
+ const error62 = reason instanceof RequestError10 ? reason : RequestError10.internalError({ code: cause.code, details: cause.message });
72763
+ if (!(reason instanceof RequestError10)) {
72698
72764
  error62.cause = cause;
72699
72765
  }
72700
72766
  this.extensionQuestions.endTurn(error62);
@@ -72762,12 +72828,12 @@ var PiAcpSession = class {
72762
72828
  const signal = this.extensionQuestions.startTurn();
72763
72829
  try {
72764
72830
  const result = await this.proc.compact(customInstructions, { signal, timeoutMs });
72765
- if (signal.aborted && signal.reason instanceof RequestError9) {
72831
+ if (signal.aborted && signal.reason instanceof RequestError10) {
72766
72832
  throw signal.reason;
72767
72833
  }
72768
72834
  return result;
72769
72835
  } catch (cause) {
72770
- if (signal.aborted && signal.reason instanceof RequestError9) {
72836
+ if (signal.aborted && signal.reason instanceof RequestError10) {
72771
72837
  try {
72772
72838
  await this.proc.abort({ signal: this.proc.signal, timeoutMs });
72773
72839
  } catch (abortCause) {
@@ -72860,14 +72926,14 @@ var PiAcpSession = class {
72860
72926
  await this.publishContextUsage();
72861
72927
  const retryFailure = this.turnRetryFailure;
72862
72928
  this.turnRetryFailure = null;
72863
- if (questionSignal?.aborted && questionSignal.reason instanceof RequestError9 && !this.cancelRequested) {
72929
+ if (questionSignal?.aborted && questionSignal.reason instanceof RequestError10 && !this.cancelRequested) {
72864
72930
  this.pendingTurn?.reject(questionSignal.reason);
72865
72931
  } else if (retryFailure !== null && !this.cancelRequested) {
72866
72932
  this.pendingTurn?.reject(
72867
72933
  // The message rides in `data.details` so clients that unwrap the
72868
72934
  // JSON-RPC internal-error envelope (like Mobius) surface the real
72869
72935
  // model error; `code` keeps the failure machine-readable.
72870
- RequestError9.internalError({
72936
+ RequestError10.internalError({
72871
72937
  code: "pi_retries_exhausted",
72872
72938
  details: `Pi retries exhausted: ${retryFailure}`
72873
72939
  })
@@ -72951,6 +73017,17 @@ var PiAcpSession = class {
72951
73017
  handlePiEvent(ev2) {
72952
73018
  const type = String(ev2.type ?? "");
72953
73019
  switch (type) {
73020
+ case "message_start": {
73021
+ const message = nativeUserMessageSchema.safeParse(ev2.message);
73022
+ if (!message.success) {
73023
+ break;
73024
+ }
73025
+ this.lastEmit = this.lastEmit.then(() => this.conn.startUserMessage());
73026
+ for (const content of message.data.content) {
73027
+ this.emit({ sessionUpdate: "user_message_chunk", content });
73028
+ }
73029
+ break;
73030
+ }
72954
73031
  case "message_update": {
72955
73032
  const ame2 = ev2.assistantMessageEvent;
72956
73033
  if (this.turnRetryFailure !== null && (ame2?.type === "text_delta" || ame2?.type === "thinking_delta" || ame2?.type === "toolcall_start")) {
@@ -73057,7 +73134,7 @@ var PiAcpSession = class {
73057
73134
  if (p) {
73058
73135
  try {
73059
73136
  const abs = isAbsolute11(p) ? p : resolvePath(this.cwd, p);
73060
- snapshotOldText = readFileSync7(abs, "utf8");
73137
+ snapshotOldText = readFileSync8(abs, "utf8");
73061
73138
  this.fileSnapshots.set(toolCallId, { path: p, oldText: snapshotOldText });
73062
73139
  if (toolName === "edit") {
73063
73140
  for (const needle of getEditOldTexts(args)) {
@@ -73140,7 +73217,7 @@ var PiAcpSession = class {
73140
73217
  if (!isError && snapshot) {
73141
73218
  try {
73142
73219
  const abs = isAbsolute11(snapshot.path) ? snapshot.path : resolvePath(this.cwd, snapshot.path);
73143
- const newText = readFileSync7(abs, "utf8");
73220
+ const newText = readFileSync8(abs, "utf8");
73144
73221
  if (snapshot.oldText === null || newText !== snapshot.oldText) {
73145
73222
  hasStructuredDiff = true;
73146
73223
  content = [
@@ -73462,7 +73539,7 @@ var PiAcpAgent = class {
73462
73539
  const restorePromise = (async () => {
73463
73540
  const stored = this.findStoredSession(sessionId);
73464
73541
  if (!stored) {
73465
- throw RequestError10.invalidParams(`Unknown sessionId: ${sessionId}`);
73542
+ throw RequestError11.invalidParams(`Unknown sessionId: ${sessionId}`);
73466
73543
  }
73467
73544
  const cwd = opts?.cwd ?? stored.cwd;
73468
73545
  let proc;
@@ -73475,7 +73552,7 @@ var PiAcpAgent = class {
73475
73552
  });
73476
73553
  } catch (e) {
73477
73554
  if (e?.name === "PiRpcSpawnError") {
73478
- throw RequestError10.internalError({ code: e?.code }, String(e?.message ?? e));
73555
+ throw RequestError11.internalError({ code: e?.code }, String(e?.message ?? e));
73479
73556
  }
73480
73557
  throw e;
73481
73558
  }
@@ -73535,7 +73612,7 @@ var PiAcpAgent = class {
73535
73612
  }
73536
73613
  async newSession(params) {
73537
73614
  if (!isAbsolute12(params.cwd)) {
73538
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
73615
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
73539
73616
  }
73540
73617
  this.lastSessionCwd = params.cwd;
73541
73618
  const fileCommands = loadSlashCommands(params.cwd, this.environment);
@@ -73574,16 +73651,16 @@ var PiAcpAgent = class {
73574
73651
  }
73575
73652
  if (availableModelsErr) {
73576
73653
  this.cleanupFailedNewSession(session.sessionId, state);
73577
- throw RequestError10.internalError({}, String(availableModelsErr?.message ?? availableModelsErr));
73654
+ throw RequestError11.internalError({}, String(availableModelsErr?.message ?? availableModelsErr));
73578
73655
  }
73579
73656
  const rawModelsCount = Array.isArray(availableModels?.models) ? availableModels.models.length : 0;
73580
73657
  if (rawModelsCount === 0) {
73581
73658
  this.cleanupFailedNewSession(session.sessionId, state);
73582
- throw RequestError10.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
73659
+ throw RequestError11.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
73583
73660
  }
73584
73661
  if (stateErr && maybeAuthRequiredError(stateErr)) {
73585
73662
  this.cleanupFailedNewSession(session.sessionId, state);
73586
- throw RequestError10.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
73663
+ throw RequestError11.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
73587
73664
  }
73588
73665
  let configuration;
73589
73666
  try {
@@ -73593,7 +73670,7 @@ var PiAcpAgent = class {
73593
73670
  configuration = await getSessionConfiguration(session.proc, { state, availableModels });
73594
73671
  } catch (err) {
73595
73672
  this.cleanupFailedNewSession(session.sessionId, state);
73596
- throw maybeAuthRequiredError(err) ?? RequestError10.internalError({}, String(err?.message ?? err));
73673
+ throw maybeAuthRequiredError(err) ?? RequestError11.internalError({}, String(err?.message ?? err));
73597
73674
  }
73598
73675
  const { configOptions, models, modes } = configuration;
73599
73676
  const quietStartup = getQuietStartup(params.cwd, this.environment);
@@ -73673,16 +73750,6 @@ var PiAcpAgent = class {
73673
73750
  }
73674
73751
  async promptSubmission(params, submission) {
73675
73752
  const session = await this.restoreSession(params.sessionId);
73676
- this.conn.startUserMessage();
73677
- for (const content of params.prompt) {
73678
- if (submission.aborted) {
73679
- return { stopReason: "cancelled" };
73680
- }
73681
- await this.conn.sessionUpdate({
73682
- sessionId: params.sessionId,
73683
- update: { sessionUpdate: "user_message_chunk", content }
73684
- });
73685
- }
73686
73753
  if (submission.aborted) {
73687
73754
  return { stopReason: "cancelled" };
73688
73755
  }
@@ -73693,6 +73760,9 @@ var PiAcpAgent = class {
73693
73760
  const cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space);
73694
73761
  const argsString = space === -1 ? "" : trimmed.slice(space + 1);
73695
73762
  const args = parseCommandArgs(argsString);
73763
+ if (builtinAvailableCommands().some((command) => command.name === cmd)) {
73764
+ this.conn.startUserMessage();
73765
+ }
73696
73766
  if (cmd === "compact") {
73697
73767
  const customInstructions = args.join(" ").trim() || void 0;
73698
73768
  const compactionId = randomUUID11();
@@ -73954,7 +74024,7 @@ ${JSON.stringify(stats, null, 2)}`;
73954
74024
  }
73955
74025
  let text2 = "";
73956
74026
  try {
73957
- text2 = readFileSync8(changelogPath, "utf-8");
74027
+ text2 = readFileSync9(changelogPath, "utf-8");
73958
74028
  } catch (e) {
73959
74029
  await this.conn.sessionUpdate({
73960
74030
  sessionId: session.sessionId,
@@ -73998,7 +74068,7 @@ ${JSON.stringify(stats, null, 2)}`;
73998
74068
  return { stopReason: "end_turn" };
73999
74069
  }
74000
74070
  try {
74001
- const raw = readFileSync8(sessionFile, "utf-8");
74071
+ const raw = readFileSync9(sessionFile, "utf-8");
74002
74072
  if (raw.trim().length === 0) {
74003
74073
  await this.conn.sessionUpdate({
74004
74074
  sessionId: session.sessionId,
@@ -74121,7 +74191,7 @@ ${JSON.stringify(stats, null, 2)}`;
74121
74191
  signal.throwIfAborted();
74122
74192
  const parsed = steerRequestSchema.safeParse(params);
74123
74193
  if (!parsed.success) {
74124
- throw RequestError10.invalidParams("Invalid steering request");
74194
+ throw RequestError11.invalidParams("Invalid steering request");
74125
74195
  }
74126
74196
  const session = this.sessions.maybeGet(parsed.data.sessionId);
74127
74197
  if (session === void 0) {
@@ -74133,14 +74203,6 @@ ${JSON.stringify(stats, null, 2)}`;
74133
74203
  case "idle":
74134
74204
  return { outcome: "promptRequired", reason: "noRunningTurn" };
74135
74205
  case "injected": {
74136
- this.conn.startUserMessage();
74137
- for (const content of parsed.data.prompt) {
74138
- signal.throwIfAborted();
74139
- await this.conn.sessionUpdate({
74140
- sessionId: parsed.data.sessionId,
74141
- update: { sessionUpdate: "user_message_chunk", content }
74142
- });
74143
- }
74144
74206
  return { outcome: "injected" };
74145
74207
  }
74146
74208
  }
@@ -74174,11 +74236,11 @@ ${JSON.stringify(stats, null, 2)}`;
74174
74236
  }
74175
74237
  async forkSession(params) {
74176
74238
  if (!isAbsolute12(params.cwd)) {
74177
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
74239
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
74178
74240
  }
74179
74241
  const source = this.findStoredSession(params.sessionId);
74180
74242
  if (!source) {
74181
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
74243
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
74182
74244
  }
74183
74245
  this.lastSessionCwd = params.cwd;
74184
74246
  const fileCommands = loadSlashCommands(params.cwd, this.environment);
@@ -74240,13 +74302,13 @@ ${JSON.stringify(stats, null, 2)}`;
74240
74302
  }
74241
74303
  async resumeSession(params) {
74242
74304
  if (!isAbsolute12(params.cwd)) {
74243
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
74305
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
74244
74306
  }
74245
74307
  this.sessions.close(params.sessionId);
74246
74308
  this.lastSessionCwd = params.cwd;
74247
74309
  const stored = this.findStoredSession(params.sessionId);
74248
74310
  if (!stored) {
74249
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
74311
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
74250
74312
  }
74251
74313
  const session = await this.restoreSession(params.sessionId, {
74252
74314
  cwd: params.cwd,
@@ -74311,13 +74373,13 @@ ${JSON.stringify(stats, null, 2)}`;
74311
74373
  }
74312
74374
  async loadSession(params) {
74313
74375
  if (!isAbsolute12(params.cwd)) {
74314
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
74376
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
74315
74377
  }
74316
74378
  this.sessions.close(params.sessionId);
74317
74379
  this.lastSessionCwd = params.cwd;
74318
74380
  const stored = this.findStoredSession(params.sessionId);
74319
74381
  if (!stored) {
74320
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
74382
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
74321
74383
  }
74322
74384
  const enableSkillCommands = getEnableSkillCommands(params.cwd, this.environment);
74323
74385
  const session = await this.restoreSession(params.sessionId, {
@@ -74340,9 +74402,29 @@ ${JSON.stringify(stats, null, 2)}`;
74340
74402
  cwd: params.cwd,
74341
74403
  sessionFile: stored.sessionFile
74342
74404
  });
74343
- const data = await proc.getMessages();
74344
- const messages = Array.isArray(data?.messages) ? data.messages : [];
74345
- for (const m of messages) {
74405
+ for (const entry of readPiHistory(stored.sessionFile)) {
74406
+ if (entry.type === "compaction") {
74407
+ await this.conn.sessionUpdate({
74408
+ sessionId: session.sessionId,
74409
+ update: {
74410
+ sessionUpdate: "compaction_update",
74411
+ compactionId: entry.id,
74412
+ status: "completed"
74413
+ }
74414
+ });
74415
+ if (entry.summary) {
74416
+ await this.conn.sessionUpdate({
74417
+ sessionId: session.sessionId,
74418
+ update: {
74419
+ sessionUpdate: "compaction_summary_chunk",
74420
+ compactionId: entry.id,
74421
+ content: { type: "text", text: entry.summary }
74422
+ }
74423
+ });
74424
+ }
74425
+ continue;
74426
+ }
74427
+ const m = entry.message;
74346
74428
  const role = String(m?.role ?? "");
74347
74429
  if (role === "user") {
74348
74430
  const text2 = normalizePiMessageText(m?.content);
@@ -74492,7 +74574,7 @@ ${JSON.stringify(stats, null, 2)}`;
74492
74574
  const session = await this.restoreSession(params.sessionId);
74493
74575
  const mode = params.modeId;
74494
74576
  if (typeof mode !== "string" || mode.length === 0) {
74495
- throw RequestError10.invalidParams("Expected nonempty string modeId");
74577
+ throw RequestError11.invalidParams("Expected nonempty string modeId");
74496
74578
  }
74497
74579
  await session.proc.setThinkingLevel(mode);
74498
74580
  await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
@@ -74503,18 +74585,18 @@ ${JSON.stringify(stats, null, 2)}`;
74503
74585
  const configId = String(params.configId);
74504
74586
  let modelChanged = false;
74505
74587
  if (typeof params.value !== "string") {
74506
- throw RequestError10.invalidParams(`Expected string value for config option: ${configId}`);
74588
+ throw RequestError11.invalidParams(`Expected string value for config option: ${configId}`);
74507
74589
  }
74508
74590
  if (configId === MODEL_CONFIG_ID2) {
74509
74591
  await setSessionModel(session.proc, params.value);
74510
74592
  modelChanged = true;
74511
74593
  } else if (configId === THOUGHT_LEVEL_CONFIG_ID) {
74512
74594
  if (params.value.length === 0) {
74513
- throw RequestError10.invalidParams("Expected nonempty thinking level");
74595
+ throw RequestError11.invalidParams("Expected nonempty thinking level");
74514
74596
  }
74515
74597
  await session.proc.setThinkingLevel(params.value);
74516
74598
  } else {
74517
- throw RequestError10.invalidParams(`Unknown config option: ${configId}`);
74599
+ throw RequestError11.invalidParams(`Unknown config option: ${configId}`);
74518
74600
  }
74519
74601
  const configOptions = await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
74520
74602
  if (modelChanged) {
@@ -74670,7 +74752,7 @@ async function setSessionModel(proc, requestedModelId) {
74670
74752
  }
74671
74753
  }
74672
74754
  if (!provider || !modelId) {
74673
- throw RequestError10.invalidParams(`Unknown modelId: ${requestedModelId}`);
74755
+ throw RequestError11.invalidParams(`Unknown modelId: ${requestedModelId}`);
74674
74756
  }
74675
74757
  await proc.setModel(provider, modelId);
74676
74758
  }
@@ -74824,7 +74906,7 @@ function buildStartupInfo(opts) {
74824
74906
  ];
74825
74907
  for (const settingsPath of settingsPaths) {
74826
74908
  try {
74827
- const settings = JSON.parse(readFileSync8(settingsPath, "utf-8"));
74909
+ const settings = JSON.parse(readFileSync9(settingsPath, "utf-8"));
74828
74910
  const pkgs = Array.isArray(settings?.packages) ? settings.packages : [];
74829
74911
  for (const pkg of pkgs) {
74830
74912
  const s = String(pkg);
@@ -83392,7 +83474,7 @@ function describeEnvironmentProxyRoute(target) {
83392
83474
  import { join as join26 } from "node:path";
83393
83475
 
83394
83476
  // src/engine/storage/logs/bounded-log.ts
83395
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
83477
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
83396
83478
  import { join as join24 } from "node:path";
83397
83479
  var BoundedLineLog = class {
83398
83480
  #path;
@@ -83433,7 +83515,7 @@ var BoundedLineLog = class {
83433
83515
  appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
83434
83516
  return;
83435
83517
  }
83436
- const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
83518
+ const lines = `${existingBytes === 0 ? "" : readFileSync10(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
83437
83519
  let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
83438
83520
  while (totalBytes > this.#maximumBytes && lines.length > 0) {
83439
83521
  const oldest = lines.shift();
@@ -83452,7 +83534,7 @@ var BoundedLineLog = class {
83452
83534
  };
83453
83535
 
83454
83536
  // src/engine/storage/logs/log-files.ts
83455
- import { readFileSync as readFileSync10 } from "node:fs";
83537
+ import { readFileSync as readFileSync11 } from "node:fs";
83456
83538
  import { join as join25 } from "node:path";
83457
83539
  var DAEMON_LOG_FILENAME = "daemon.log";
83458
83540
  var WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
@@ -83471,7 +83553,7 @@ function processLogPaths(dataDirectory) {
83471
83553
  }
83472
83554
  function readLogText(path7) {
83473
83555
  try {
83474
- return readFileSync10(path7, "utf8");
83556
+ return readFileSync11(path7, "utf8");
83475
83557
  } catch {
83476
83558
  return null;
83477
83559
  }
@@ -85112,7 +85194,7 @@ var SessionConfigurations = class {
85112
85194
  restore = async (stored, options, apply, signal) => {
85113
85195
  this.#selected = stored;
85114
85196
  for (const selection of this.#selected) {
85115
- const current = options.find(
85197
+ const current = options().find(
85116
85198
  (option) => option.id === selection.configId && option.type === selection.type
85117
85199
  );
85118
85200
  if (current === void 0) {
@@ -85304,6 +85386,7 @@ async function restoreSession(session, signal, recovery, origin) {
85304
85386
  session.store.remove(session.sessionId);
85305
85387
  stored = session.metrics.measureSync("session-state-read", () => session.store.read(session.sessionId));
85306
85388
  }
85389
+ const forkSource = origin?.kind === "fork" ? session.store.findNative(session.agentId, origin.nativeSessionId)[0] : void 0;
85307
85390
  let lifecycleResponse;
85308
85391
  if (origin?.kind === "fork") {
85309
85392
  if (!session.capabilities.unstableForkSession) {
@@ -85465,7 +85548,9 @@ async function restoreSession(session, signal, recovery, origin) {
85465
85548
  }
85466
85549
  session.restrictSessionCapabilities(lifecycleResponse);
85467
85550
  session.setConfigOptions(session.sessionConfigProtocol.normalizeLifecycle(lifecycleResponse));
85468
- if (stored instanceof FoundStoredSession && session.restored) {
85551
+ if (forkSource !== void 0) {
85552
+ await session.restoreStoredConfigurations(forkSource, signal, "fork");
85553
+ } else if (stored instanceof FoundStoredSession && session.restored) {
85469
85554
  await session.restoreStoredConfigurations(stored.session, signal);
85470
85555
  }
85471
85556
  await session.drained();
@@ -85677,13 +85762,31 @@ var AgentSession = class _AgentSession {
85677
85762
  this.writeStoredSession((/* @__PURE__ */ new Date()).toISOString());
85678
85763
  }
85679
85764
  };
85680
- restoreStoredConfigurations = async (session, signal) => {
85765
+ restoreStoredConfigurations = async (session, signal, intent = "restore") => {
85766
+ const configurations = intent === "fork" ? session.configurations.toSorted(
85767
+ (left, right) => Number(right.configId === "model") - Number(left.configId === "model")
85768
+ ) : session.configurations;
85681
85769
  await this.#sessionConfigurations.restore(
85682
- session.configurations,
85683
- this.#configOptions,
85770
+ configurations,
85771
+ () => this.#configOptions,
85684
85772
  this.#applyConfiguration,
85685
85773
  signal
85686
85774
  );
85775
+ if (intent === "fork") {
85776
+ for (const selection of session.configurations) {
85777
+ if (selection.configId !== "mode") {
85778
+ continue;
85779
+ }
85780
+ const current = this.#configOptions.find((option) => option.id === selection.configId);
85781
+ if (current?.type !== selection.type || (selection.type === "select" ? current.currentValue !== selection.value : current.booleanValue !== selection.booleanValue)) {
85782
+ throw new AcpExecutionError(
85783
+ "The Agent could not preserve the source Session mode for this Fork",
85784
+ {},
85785
+ "invalid_session_configuration"
85786
+ );
85787
+ }
85788
+ }
85789
+ }
85687
85790
  };
85688
85791
  restrictSessionCapabilities = (response) => {
85689
85792
  this.#capabilities = restrictAcpSessionCapabilities(this.#capabilities, response);
@@ -87124,7 +87227,8 @@ var NativeSessionService = class {
87124
87227
  requestId: command.requestId,
87125
87228
  sessionId: command.sessionId,
87126
87229
  targetSessionId: command.targetSessionId,
87127
- ...await this.#activeTurn(command, options)
87230
+ ...await this.#activeTurn(command, options),
87231
+ queuedCancellation: "before-start"
87128
87232
  };
87129
87233
  }
87130
87234
  const capabilities = await options.adapter.getCapabilities(options);
@@ -87734,6 +87838,11 @@ var ExecutionReceipts = class {
87734
87838
  return void 0;
87735
87839
  }
87736
87840
  };
87841
+ /** Started identities remain authoritative after their detailed receipt is evicted. */
87842
+ hasStarted = (commandId, sessionId) => {
87843
+ const receipt = this.#executions.get(commandId);
87844
+ return receipt === void 0 ? this.#table.identity(commandId)?.sessionId === sessionId : receipt.sessionId === sessionId && receipt.started;
87845
+ };
87737
87846
  /** Reserves an unseen command for cancellation before a delayed prompt can claim its identity. */
87738
87847
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
87739
87848
  const existing = this.#executions.get(commandId);
@@ -90292,10 +90401,19 @@ var sessionCancelBeforeStartCommand = {
90292
90401
  if (message.kind !== SESSION_CANCEL_BEFORE_START_KIND) {
90293
90402
  throw new Error("Command kind mismatch");
90294
90403
  }
90404
+ if (operations.hasStarted(message.commandId, message.sessionId)) {
90405
+ reportOperationFailure(
90406
+ socket,
90407
+ message.commandId,
90408
+ message.sessionId,
90409
+ new SessionError("turn_already_started", "The message already started and could not be withdrawn")
90410
+ );
90411
+ return;
90412
+ }
90295
90413
  const turn = sessionTurns.get(message.commandId, message.sessionId);
90296
90414
  if (turn === void 0) {
90297
90415
  const outcome = operations.recordCancellationBeforeAdmission(message.commandId, message.sessionId);
90298
- if (outcome !== void 0) {
90416
+ if (outcome?.type === "lifecycle-metadata" && outcome.payload.kind === "prompt.completed" && outcome.payload.stopReason === "cancelled") {
90299
90417
  void eventProjection.replayOutcome(message.sessionId, outcome).catch((error62) => {
90300
90418
  reportOperationFailure(socket, message.commandId, message.sessionId, error62);
90301
90419
  });
@@ -90767,6 +90885,7 @@ async function executePrompt({
90767
90885
  );
90768
90886
  prepared = await sessions.prepareExecutionSession(preparation);
90769
90887
  }
90888
+ signal.throwIfAborted();
90770
90889
  operations.markExecutionStarted(command.commandId);
90771
90890
  if (availability.disposition === SessionPromptDisposition.Steer) {
90772
90891
  if (!recordSteeringPrompt()) {
@@ -90949,7 +91068,7 @@ var sessionPromptCommand = {
90949
91068
  // package.json
90950
91069
  var package_default = {
90951
91070
  name: "@moxt-ai/mobius",
90952
- version: "0.0.355",
91071
+ version: "0.0.356",
90953
91072
  description: "Mobius CLI for pairing and running local AI agent services.",
90954
91073
  type: "module",
90955
91074
  bin: {