@cydm/pie 1.0.35 → 1.0.37

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.
@@ -5,6 +5,28 @@ import {
5
5
  import "./chunk-TG2EQLX2.js";
6
6
 
7
7
  // src/app/test-stream.ts
8
+ function parseSystemPromptExpectations(value) {
9
+ if (!value) return [];
10
+ const parsed = JSON.parse(value);
11
+ const normalize = (item) => {
12
+ if (typeof item === "string") return [item];
13
+ if (Array.isArray(item) && item.every((entry) => typeof entry === "string")) return item;
14
+ throw new Error("PIE_TEST_EXPECT_SYSTEM_PROMPT_INCLUDES entries must be strings");
15
+ };
16
+ if (typeof parsed === "string" || Array.isArray(parsed) && parsed.every((entry) => typeof entry === "string")) {
17
+ return [normalize(parsed)];
18
+ }
19
+ if (!Array.isArray(parsed)) throw new Error("PIE_TEST_EXPECT_SYSTEM_PROMPT_INCLUDES must be JSON");
20
+ return parsed.map(normalize);
21
+ }
22
+ function assertSystemPromptIncludes(systemPrompt, callIndex) {
23
+ const expectations = parseSystemPromptExpectations(process.env.PIE_TEST_EXPECT_SYSTEM_PROMPT_INCLUDES);
24
+ for (const expected of expectations[Math.min(callIndex, Math.max(0, expectations.length - 1))] ?? []) {
25
+ if (!systemPrompt.includes(expected)) {
26
+ throw new Error(`Expected system prompt to include ${JSON.stringify(expected)}`);
27
+ }
28
+ }
29
+ }
8
30
  function createAssistantMessage(model, text, stopReason = "stop", errorMessage) {
9
31
  return {
10
32
  role: "assistant",
@@ -68,8 +90,9 @@ function createTestStreamFnFromSequenceEnv(value = process.env.PIE_TEST_MOCK_STR
68
90
  }
69
91
  const steps = parseMockStreamSequence(value);
70
92
  let callIndex = 0;
71
- return async (model) => {
93
+ return async (model, context) => {
72
94
  const step = steps[Math.min(callIndex, steps.length - 1)];
95
+ assertSystemPromptIncludes(context.systemPrompt, callIndex);
73
96
  callIndex += 1;
74
97
  const stream = new EventStream(
75
98
  (event) => event.type === "done" || event.type === "error",
package/dist/cli.js CHANGED
@@ -985,15 +985,15 @@ var require_route = __commonJS({
985
985
  };
986
986
  }
987
987
  function wrapConversion(toModel, graph) {
988
- const path30 = [graph[toModel].parent, toModel];
988
+ const path31 = [graph[toModel].parent, toModel];
989
989
  let fn = conversions[graph[toModel].parent][toModel];
990
990
  let cur = graph[toModel].parent;
991
991
  while (graph[cur].parent) {
992
- path30.unshift(graph[cur].parent);
992
+ path31.unshift(graph[cur].parent);
993
993
  fn = link(conversions[graph[cur].parent][cur], fn);
994
994
  cur = graph[cur].parent;
995
995
  }
996
- fn.conversion = path30;
996
+ fn.conversion = path31;
997
997
  return fn;
998
998
  }
999
999
  module.exports = function(fromModel) {
@@ -43957,11 +43957,11 @@ var require_dist = __commonJS({
43957
43957
  });
43958
43958
 
43959
43959
  // src/cli.ts
43960
- import * as fs26 from "fs";
43961
- import * as path29 from "path";
43960
+ import * as fs27 from "fs";
43961
+ import * as path30 from "path";
43962
43962
 
43963
43963
  // src/cli-args.ts
43964
- var FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--session-id", "--extension-path"]);
43964
+ var FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--session-id", "--extension-path", "--developer-instructions", "--developer-instructions-file"]);
43965
43965
  var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--raw-output", "--json-output", "--json-events", "--resume-required"]);
43966
43966
  var HELP_FLAGS = /* @__PURE__ */ new Set(["help", "--help", "-h"]);
43967
43967
  var COMMANDS = /* @__PURE__ */ new Set(["chat", "help"]);
@@ -44561,7 +44561,7 @@ async function acquireRemoteRefreshLock(modelsPath) {
44561
44561
  throw lockError;
44562
44562
  }
44563
44563
  if (Date.now() >= deadline) throw new Error(`timed out waiting for remote catalog refresh lock: ${lockPath}`);
44564
- await new Promise((resolve5) => setTimeout(resolve5, 25));
44564
+ await new Promise((resolve6) => setTimeout(resolve6, 25));
44565
44565
  }
44566
44566
  }
44567
44567
  }
@@ -46565,6 +46565,165 @@ function parseModelsCommandArgs(args) {
46565
46565
 
46566
46566
  // src/commands/sessions.ts
46567
46567
  import fs6 from "node:fs";
46568
+
46569
+ // src/session-control.ts
46570
+ var SessionControlError = class extends Error {
46571
+ constructor(code, message, recoverable = sessionControlErrorRecoverable(code)) {
46572
+ super(message);
46573
+ this.code = code;
46574
+ this.recoverable = recoverable;
46575
+ this.name = "SessionControlError";
46576
+ }
46577
+ code;
46578
+ recoverable;
46579
+ };
46580
+ function sessionControlErrorRecoverable(code) {
46581
+ return code !== "session_unrecoverable" && code !== "session_mismatch";
46582
+ }
46583
+ async function loadRequiredSession(store, sessionId) {
46584
+ const exists = await store.exists(sessionId);
46585
+ const data = await store.load(sessionId);
46586
+ if (data) return data;
46587
+ throw new SessionControlError(
46588
+ exists ? "session_unrecoverable" : "session_not_found",
46589
+ exists ? `Session could not be recovered: ${sessionId}` : `Session not found: ${sessionId}`
46590
+ );
46591
+ }
46592
+ async function rewindStoredSession(params) {
46593
+ const data = await loadRequiredSession(params.store, params.sessionId);
46594
+ if (!data.entries.some((entry) => entry.id === params.entryId)) {
46595
+ throw new SessionControlError("checkpoint_not_found", `Entry not found: ${params.entryId}`);
46596
+ }
46597
+ try {
46598
+ await params.store.save(params.sessionId, data.entries, {
46599
+ ...data.metadata,
46600
+ activeEntryId: params.entryId,
46601
+ updatedAt: params.now ?? Date.now()
46602
+ });
46603
+ const metadata = await params.store.getMetadata(params.sessionId);
46604
+ if (!metadata) {
46605
+ throw new SessionControlError("session_unrecoverable", `Session could not be recovered after rewind: ${params.sessionId}`, false);
46606
+ }
46607
+ return {
46608
+ sessionId: params.sessionId,
46609
+ entryId: params.entryId,
46610
+ checkpointId: params.entryId,
46611
+ activeEntryId: params.entryId,
46612
+ headEntryId: params.entryId,
46613
+ metadata
46614
+ };
46615
+ } catch (error) {
46616
+ if (error instanceof SessionControlError) throw error;
46617
+ throw new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
46618
+ }
46619
+ }
46620
+ async function forkStoredSession(params) {
46621
+ try {
46622
+ const existingTarget = await maybeLoadExistingForkTarget(params);
46623
+ if (existingTarget) return existingTarget;
46624
+ const source = await loadRequiredSession(params.store, params.sourceSessionId);
46625
+ const pathEntries = pathToEntry(source, params.sourceEntryId);
46626
+ if (pathEntries.length === 0 || pathEntries[pathEntries.length - 1]?.id !== params.sourceEntryId) {
46627
+ throw new SessionControlError("checkpoint_not_found", `Entry not found: ${params.sourceEntryId}`);
46628
+ }
46629
+ const now = params.now ?? Date.now();
46630
+ const idMap = /* @__PURE__ */ new Map();
46631
+ for (const entry of pathEntries) idMap.set(entry.id, generateEntryId());
46632
+ const forkedEntries = pathEntries.map((entry) => {
46633
+ const nextId = idMap.get(entry.id);
46634
+ if (!nextId) throw new SessionControlError("session_io_error", `Failed to map entry: ${entry.id}`);
46635
+ const parentId = entry.parentId ? idMap.get(entry.parentId) ?? null : null;
46636
+ return {
46637
+ ...cloneJson(entry),
46638
+ id: nextId,
46639
+ parentId,
46640
+ timestamp: entry.timestamp
46641
+ };
46642
+ });
46643
+ const activeEntryId = idMap.get(params.sourceEntryId);
46644
+ if (!activeEntryId) {
46645
+ throw new SessionControlError("session_io_error", `Failed to map active entry: ${params.sourceEntryId}`);
46646
+ }
46647
+ await params.store.save(params.targetSessionId, forkedEntries, {
46648
+ name: params.name,
46649
+ createdAt: now,
46650
+ updatedAt: now,
46651
+ activeEntryId,
46652
+ cwd: params.cwd ?? source.metadata.cwd,
46653
+ sourceSessionId: params.sourceSessionId,
46654
+ sourceEntryId: params.sourceEntryId,
46655
+ sourceActiveEntryId: source.metadata.activeEntryId ?? void 0,
46656
+ forkBaseEntryId: activeEntryId,
46657
+ ...params.requestId ? { sessionControlRequestId: params.requestId } : {}
46658
+ });
46659
+ const metadata = await params.store.getMetadata(params.targetSessionId);
46660
+ if (!metadata) {
46661
+ throw new SessionControlError("session_unrecoverable", `Session could not be recovered after fork: ${params.targetSessionId}`, false);
46662
+ }
46663
+ return buildForkResult({
46664
+ metadata,
46665
+ sourceSessionId: params.sourceSessionId,
46666
+ sourceEntryId: params.sourceEntryId,
46667
+ sourceActiveEntryId: source.metadata.activeEntryId ?? null
46668
+ });
46669
+ } catch (error) {
46670
+ if (error instanceof SessionControlError) throw error;
46671
+ throw new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
46672
+ }
46673
+ }
46674
+ async function maybeLoadExistingForkTarget(params) {
46675
+ if (!await params.store.exists(params.targetSessionId)) return null;
46676
+ const target = await params.store.load(params.targetSessionId);
46677
+ if (!target) {
46678
+ throw new SessionControlError("session_unrecoverable", `Session could not be recovered: ${params.targetSessionId}`, false);
46679
+ }
46680
+ const metadata = target.metadata;
46681
+ if (params.requestId && metadata.sessionControlRequestId === params.requestId && metadata.sourceSessionId === params.sourceSessionId && metadata.sourceEntryId === params.sourceEntryId && typeof metadata.forkBaseEntryId === "string" && metadata.activeEntryId === metadata.forkBaseEntryId) {
46682
+ return buildForkResult({
46683
+ metadata,
46684
+ sourceSessionId: params.sourceSessionId,
46685
+ sourceEntryId: params.sourceEntryId,
46686
+ sourceActiveEntryId: typeof metadata.sourceActiveEntryId === "string" ? metadata.sourceActiveEntryId : null
46687
+ });
46688
+ }
46689
+ throw new SessionControlError("target_exists", `Target session already exists: ${params.targetSessionId}`);
46690
+ }
46691
+ function buildForkResult(params) {
46692
+ const targetActiveEntryId = params.metadata.activeEntryId;
46693
+ if (!targetActiveEntryId) {
46694
+ throw new SessionControlError("session_unrecoverable", `Fork target has no active entry: ${params.metadata.id}`, false);
46695
+ }
46696
+ const forkBaseEntryId = typeof params.metadata.forkBaseEntryId === "string" ? params.metadata.forkBaseEntryId : targetActiveEntryId;
46697
+ return {
46698
+ sourceSessionId: params.sourceSessionId,
46699
+ sourceEntryId: params.sourceEntryId,
46700
+ sourceCheckpointId: params.sourceEntryId,
46701
+ targetSessionId: params.metadata.id,
46702
+ targetActiveEntryId,
46703
+ targetHeadEntryId: targetActiveEntryId,
46704
+ headEntryId: targetActiveEntryId,
46705
+ sourceActiveEntryId: params.sourceActiveEntryId,
46706
+ forkBaseEntryId,
46707
+ metadata: params.metadata
46708
+ };
46709
+ }
46710
+ function pathToEntry(data, entryId) {
46711
+ const byId = new Map(data.entries.map((entry) => [entry.id, entry]));
46712
+ const path31 = [];
46713
+ let current = entryId;
46714
+ while (current) {
46715
+ const entry = byId.get(current);
46716
+ if (!entry) return [];
46717
+ path31.unshift(entry);
46718
+ current = entry.parentId;
46719
+ }
46720
+ return path31;
46721
+ }
46722
+ function cloneJson(value) {
46723
+ return JSON.parse(JSON.stringify(value));
46724
+ }
46725
+
46726
+ // src/commands/sessions.ts
46568
46727
  async function runSessionsCommand(args) {
46569
46728
  const command = args[0] || "help";
46570
46729
  const rest = args.slice(1);
@@ -46691,17 +46850,12 @@ async function rewindSession(args) {
46691
46850
  const entryId = stringFlag(args, "--to");
46692
46851
  if (!sessionId || !entryId) throw new Error("Usage: pie sessions rewind <sessionId> --to <entryId> [--json]");
46693
46852
  const store = new FileSessionStore(getSessionsDir());
46694
- const data = await store.load(sessionId);
46695
- if (!data) throw new Error(`Session not found: ${sessionId}`);
46696
- if (!data.entries.some((entry) => entry.id === entryId)) throw new Error(`Entry not found: ${entryId}`);
46697
- await store.save(sessionId, data.entries, { ...data.metadata, activeEntryId: entryId, updatedAt: Date.now() });
46698
- const updated = await store.getMetadata(sessionId);
46699
- if (!updated) throw new Error(`Session not found after rewind: ${sessionId}`);
46853
+ const result = await rewindStoredSession({ store, sessionId, entryId });
46700
46854
  const response = {
46701
46855
  ok: true,
46702
- session: sessionSummary(updated),
46703
- activeEntryId: entryId,
46704
- currentHead: entryId
46856
+ session: sessionSummary(result.metadata),
46857
+ activeEntryId: result.activeEntryId,
46858
+ currentHead: result.headEntryId
46705
46859
  };
46706
46860
  if (json) {
46707
46861
  console.log(JSON.stringify(response, null, 2));
@@ -46720,50 +46874,23 @@ async function forkSession(args) {
46720
46874
  throw new Error("Usage: pie sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--json]");
46721
46875
  }
46722
46876
  const store = new FileSessionStore(getSessionsDir());
46723
- const source = await store.load(sourceSessionId);
46724
- if (!source) throw new Error(`Session not found: ${sourceSessionId}`);
46725
- if (await store.exists(targetSessionId)) throw new Error(`Target session already exists: ${targetSessionId}`);
46726
- const pathEntries = pathToEntry(source, sourceEntryId);
46727
- if (pathEntries.length === 0 || pathEntries[pathEntries.length - 1]?.id !== sourceEntryId) {
46728
- throw new Error(`Entry not found: ${sourceEntryId}`);
46729
- }
46730
- const now = Date.now();
46731
- const idMap = /* @__PURE__ */ new Map();
46732
- for (const entry of pathEntries) idMap.set(entry.id, generateEntryId());
46733
- const forkedEntries = pathEntries.map((entry) => {
46734
- const nextId = idMap.get(entry.id);
46735
- if (!nextId) throw new Error(`Failed to map entry: ${entry.id}`);
46736
- const parentId = entry.parentId ? idMap.get(entry.parentId) ?? null : null;
46737
- return {
46738
- ...cloneJson(entry),
46739
- id: nextId,
46740
- parentId,
46741
- timestamp: entry.timestamp
46742
- };
46743
- });
46744
- const activeEntryId = idMap.get(sourceEntryId) ?? null;
46745
- await store.save(targetSessionId, forkedEntries, {
46746
- name,
46747
- createdAt: now,
46748
- updatedAt: now,
46749
- activeEntryId,
46750
- cwd: cwd ?? source.metadata.cwd,
46877
+ const result = await forkStoredSession({
46878
+ store,
46751
46879
  sourceSessionId,
46752
46880
  sourceEntryId,
46753
- sourceActiveEntryId: source.metadata.activeEntryId ?? void 0,
46754
- forkBaseEntryId: activeEntryId ?? void 0
46881
+ targetSessionId,
46882
+ name,
46883
+ cwd
46755
46884
  });
46756
- const updated = await store.getMetadata(targetSessionId);
46757
- if (!updated) throw new Error(`Session not found after fork: ${targetSessionId}`);
46758
46885
  const response = {
46759
46886
  ok: true,
46760
- session: sessionSummary(updated),
46887
+ session: sessionSummary(result.metadata),
46761
46888
  sourceSessionId,
46762
46889
  sourceEntryId,
46763
- sourceActiveEntryId: source.metadata.activeEntryId,
46764
- forkBaseEntryId: activeEntryId,
46765
- activeEntryId,
46766
- currentHead: activeEntryId
46890
+ sourceActiveEntryId: result.sourceActiveEntryId,
46891
+ forkBaseEntryId: result.forkBaseEntryId,
46892
+ activeEntryId: result.targetActiveEntryId,
46893
+ currentHead: result.targetHeadEntryId
46767
46894
  };
46768
46895
  if (json) {
46769
46896
  console.log(JSON.stringify(response, null, 2));
@@ -46856,7 +46983,7 @@ function activeTranscriptEvents(entries) {
46856
46983
  role,
46857
46984
  turnId,
46858
46985
  content: textFromMessage(entry.message),
46859
- message: entry.message ? cloneJson(entry.message) : void 0
46986
+ message: entry.message ? cloneJson2(entry.message) : void 0
46860
46987
  };
46861
46988
  });
46862
46989
  }
@@ -46879,18 +47006,6 @@ function activePathEntries(data) {
46879
47006
  if (!activeEntryId) return [];
46880
47007
  return pathToEntry(data, activeEntryId);
46881
47008
  }
46882
- function pathToEntry(data, entryId) {
46883
- const byId = new Map(data.entries.map((entry) => [entry.id, entry]));
46884
- const path30 = [];
46885
- let current = entryId;
46886
- while (current) {
46887
- const entry = byId.get(current);
46888
- if (!entry) return [];
46889
- path30.unshift(entry);
46890
- current = entry.parentId;
46891
- }
46892
- return path30;
46893
- }
46894
47009
  function resolveBeforeCursor(events, cursor) {
46895
47010
  if (!cursor) return events.length;
46896
47011
  const numeric = Number(cursor);
@@ -46900,7 +47015,7 @@ function resolveBeforeCursor(events, cursor) {
46900
47015
  const index = events.findIndex((event) => event.entryId === cursor || event.checkpointId === cursor);
46901
47016
  return index >= 0 ? index : events.length;
46902
47017
  }
46903
- function cloneJson(value) {
47018
+ function cloneJson2(value) {
46904
47019
  return JSON.parse(JSON.stringify(value));
46905
47020
  }
46906
47021
  function listCursorQueryKey(input) {
@@ -46952,19 +47067,19 @@ var CommandTree = class {
46952
47067
  * register(["session", "new"], { description, handler })
46953
47068
  * register(["tools", "subagent", "spawn", "local"], { description, handler })
46954
47069
  */
46955
- register(path30, info) {
46956
- if (path30.length === 0) {
47070
+ register(path31, info) {
47071
+ if (path31.length === 0) {
46957
47072
  throw new Error("Command path cannot be empty");
46958
47073
  }
46959
47074
  let current = this.root;
46960
47075
  const fullPath = [];
46961
- for (let i = 0; i < path30.length; i++) {
46962
- const segment = path30[i];
47076
+ for (let i = 0; i < path31.length; i++) {
47077
+ const segment = path31[i];
46963
47078
  fullPath.push(segment);
46964
47079
  if (!current.children) {
46965
47080
  current.children = [];
46966
47081
  }
46967
- const isLast = i === path30.length - 1;
47082
+ const isLast = i === path31.length - 1;
46968
47083
  let node = current.children.find((n) => n.name === segment);
46969
47084
  if (!node) {
46970
47085
  node = {
@@ -46994,31 +47109,31 @@ var CommandTree = class {
46994
47109
  /**
46995
47110
  * Find a node by path
46996
47111
  */
46997
- find(path30) {
46998
- if (path30.length === 0) {
47112
+ find(path31) {
47113
+ if (path31.length === 0) {
46999
47114
  return this.root;
47000
47115
  }
47001
- const key = path30.join("/");
47116
+ const key = path31.join("/");
47002
47117
  return this.pathCache.get(key) || null;
47003
47118
  }
47004
47119
  /**
47005
47120
  * Get children of a path
47006
47121
  */
47007
- getChildren(path30) {
47008
- const node = this.find(path30);
47122
+ getChildren(path31) {
47123
+ const node = this.find(path31);
47009
47124
  return (node?.children || []).filter((child) => !child.hidden);
47010
47125
  }
47011
47126
  /**
47012
47127
  * Check if a path exists (as category or command)
47013
47128
  */
47014
- exists(path30) {
47015
- return this.find(path30) !== null;
47129
+ exists(path31) {
47130
+ return this.find(path31) !== null;
47016
47131
  }
47017
47132
  /**
47018
47133
  * Check if path is a category (has children)
47019
47134
  */
47020
- isCategory(path30) {
47021
- const node = this.find(path30);
47135
+ isCategory(path31) {
47136
+ const node = this.find(path31);
47022
47137
  return node?.isCategory || false;
47023
47138
  }
47024
47139
  /**
@@ -47097,8 +47212,8 @@ var CommandTree = class {
47097
47212
  * Supports dot notation: "tools.subagent.spawn.local"
47098
47213
  */
47099
47214
  registerFromPath(pathStr, info) {
47100
- const path30 = pathStr.split(/[./]/).filter(Boolean);
47101
- this.register(path30, info);
47215
+ const path31 = pathStr.split(/[./]/).filter(Boolean);
47216
+ this.register(path31, info);
47102
47217
  }
47103
47218
  };
47104
47219
  var commandTree = new CommandTree();
@@ -54388,7 +54503,7 @@ var ProcessTerminal = class {
54388
54503
  const timeLeft = endTime - now;
54389
54504
  if (timeLeft <= 0) break;
54390
54505
  if (now - lastDataTime >= idleMs) break;
54391
- await new Promise((resolve5) => setTimeout(resolve5, Math.min(idleMs, timeLeft)));
54506
+ await new Promise((resolve6) => setTimeout(resolve6, Math.min(idleMs, timeLeft)));
54392
54507
  }
54393
54508
  } finally {
54394
54509
  process.stdin.removeListener("data", onData);
@@ -54922,10 +55037,10 @@ var KeybindingsManager = class _KeybindingsManager {
54922
55037
  static inMemory(config = {}) {
54923
55038
  return new _KeybindingsManager(config);
54924
55039
  }
54925
- static loadFromFile(path30) {
54926
- if (!existsSync7(path30)) return {};
55040
+ static loadFromFile(path31) {
55041
+ if (!existsSync7(path31)) return {};
54927
55042
  try {
54928
- return JSON.parse(readFileSync6(path30, "utf-8"));
55043
+ return JSON.parse(readFileSync6(path31, "utf-8"));
54929
55044
  } catch {
54930
55045
  return {};
54931
55046
  }
@@ -57635,11 +57750,11 @@ var FileCache = class _FileCache {
57635
57750
  // Hash Computation
57636
57751
  // ============================================================================
57637
57752
  async computeHash(filePath) {
57638
- return new Promise((resolve5, reject) => {
57753
+ return new Promise((resolve6, reject) => {
57639
57754
  const hash = crypto.createHash("sha256");
57640
57755
  const stream = fs16.createReadStream(filePath);
57641
57756
  stream.on("data", (chunk) => hash.update(chunk));
57642
- stream.on("end", () => resolve5(hash.digest("hex")));
57757
+ stream.on("end", () => resolve6(hash.digest("hex")));
57643
57758
  stream.on("error", reject);
57644
57759
  });
57645
57760
  }
@@ -58349,17 +58464,17 @@ var FFmpegProcessor = class {
58349
58464
  // Detection
58350
58465
  // ============================================================================
58351
58466
  async checkAvailability() {
58352
- return new Promise((resolve5) => {
58467
+ return new Promise((resolve6) => {
58353
58468
  const proc = spawn(this.ffmpegPath, ["-version"]);
58354
- proc.on("error", () => resolve5(false));
58355
- proc.on("exit", (code) => resolve5(code === 0));
58469
+ proc.on("error", () => resolve6(false));
58470
+ proc.on("exit", (code) => resolve6(code === 0));
58356
58471
  });
58357
58472
  }
58358
58473
  // ============================================================================
58359
58474
  // Video Analysis
58360
58475
  // ============================================================================
58361
58476
  async analyzeVideo(videoPath) {
58362
- return new Promise((resolve5, reject) => {
58477
+ return new Promise((resolve6, reject) => {
58363
58478
  const args = [
58364
58479
  "-v",
58365
58480
  "error",
@@ -58388,7 +58503,7 @@ var FFmpegProcessor = class {
58388
58503
  }
58389
58504
  try {
58390
58505
  const info = this.parseProbeOutput(stdout, videoPath);
58391
- resolve5(info);
58506
+ resolve6(info);
58392
58507
  } catch (err) {
58393
58508
  reject(err);
58394
58509
  }
@@ -58583,7 +58698,7 @@ var FFmpegProcessor = class {
58583
58698
  // FFmpeg Execution
58584
58699
  // ============================================================================
58585
58700
  runFFmpeg(args) {
58586
- return new Promise((resolve5, reject) => {
58701
+ return new Promise((resolve6, reject) => {
58587
58702
  const proc = spawn(this.ffmpegPath, args);
58588
58703
  let stderr = "";
58589
58704
  proc.stderr.on("data", (data) => {
@@ -58598,7 +58713,7 @@ var FFmpegProcessor = class {
58598
58713
  )
58599
58714
  );
58600
58715
  } else {
58601
- resolve5();
58716
+ resolve6();
58602
58717
  }
58603
58718
  });
58604
58719
  proc.on("error", (err) => {
@@ -58615,7 +58730,7 @@ var FFmpegProcessor = class {
58615
58730
  // Progress Monitoring (for future use)
58616
58731
  // ============================================================================
58617
58732
  async runWithProgress(args, onProgress) {
58618
- return new Promise((resolve5, reject) => {
58733
+ return new Promise((resolve6, reject) => {
58619
58734
  const progressArgs = [
58620
58735
  ...args,
58621
58736
  "-progress",
@@ -58645,7 +58760,7 @@ var FFmpegProcessor = class {
58645
58760
  )
58646
58761
  );
58647
58762
  } else {
58648
- resolve5();
58763
+ resolve6();
58649
58764
  }
58650
58765
  });
58651
58766
  });
@@ -59635,7 +59750,7 @@ async function waitForReady(params) {
59635
59750
  if (status.status === "error" || status.status === "expired") {
59636
59751
  throw new Error(`Uploaded file is not ready: ${status.status}${status.error ? ` (${status.error})` : ""}`);
59637
59752
  }
59638
- await new Promise((resolve5) => setTimeout(resolve5, 1500));
59753
+ await new Promise((resolve6) => setTimeout(resolve6, 1500));
59639
59754
  }
59640
59755
  throw new Error("Timed out waiting for uploaded file to become ready");
59641
59756
  }
@@ -59731,8 +59846,8 @@ function createIsolatedRegexSession(pattern, ignoreCase) {
59731
59846
  let initError;
59732
59847
  let readyResolve;
59733
59848
  let readyReject;
59734
- const ready = new Promise((resolve5, reject) => {
59735
- readyResolve = resolve5;
59849
+ const ready = new Promise((resolve6, reject) => {
59850
+ readyResolve = resolve6;
59736
59851
  readyReject = reject;
59737
59852
  });
59738
59853
  void ready.catch(() => void 0);
@@ -59754,7 +59869,7 @@ function createIsolatedRegexSession(pattern, ignoreCase) {
59754
59869
  if (initError) throw initError;
59755
59870
  if (signal?.aborted) throw new Error("Operation aborted");
59756
59871
  const id = nextId++;
59757
- return new Promise((resolve5, reject) => {
59872
+ return new Promise((resolve6, reject) => {
59758
59873
  let settled = false;
59759
59874
  const finish = (error, matches) => {
59760
59875
  if (settled) return;
@@ -59764,7 +59879,7 @@ function createIsolatedRegexSession(pattern, ignoreCase) {
59764
59879
  worker.off("message", onMessage);
59765
59880
  worker.off("error", onWorkerError);
59766
59881
  if (error) reject(error);
59767
- else resolve5(matches ?? []);
59882
+ else resolve6(matches ?? []);
59768
59883
  };
59769
59884
  const terminate = (error) => {
59770
59885
  disposed = true;
@@ -60992,7 +61107,7 @@ async function handleCacheTest(host) {
60992
61107
  host.chatContainer.addChild(new Text(theme.fg("dim", ` ${summarizeUsage(result1.usage)}`), 1, 0));
60993
61108
  host.chatContainer.addChild(new Text(theme.fg("dim", " Waiting 2s before replaying identical request..."), 1, 0));
60994
61109
  host.ui.requestRender();
60995
- await new Promise((resolve5) => setTimeout(resolve5, 2e3));
61110
+ await new Promise((resolve6) => setTimeout(resolve6, 2e3));
60996
61111
  host.chatContainer.addChild(new Text(theme.fg("accent", "Request 2/2: replaying identical request..."), 1, 0));
60997
61112
  host.ui.requestRender();
60998
61113
  result2 = await completeSimple(model, context, options);
@@ -61982,16 +62097,16 @@ var Diff = class {
61982
62097
  }
61983
62098
  }
61984
62099
  }
61985
- addToPath(path30, added, removed, oldPosInc, options) {
61986
- const last = path30.lastComponent;
62100
+ addToPath(path31, added, removed, oldPosInc, options) {
62101
+ const last = path31.lastComponent;
61987
62102
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
61988
62103
  return {
61989
- oldPos: path30.oldPos + oldPosInc,
62104
+ oldPos: path31.oldPos + oldPosInc,
61990
62105
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
61991
62106
  };
61992
62107
  } else {
61993
62108
  return {
61994
- oldPos: path30.oldPos + oldPosInc,
62109
+ oldPos: path31.oldPos + oldPosInc,
61995
62110
  lastComponent: { count: 1, added, removed, previousComponent: last }
61996
62111
  };
61997
62112
  }
@@ -62439,13 +62554,13 @@ function formatSize2(bytes) {
62439
62554
  }
62440
62555
  var DEFAULT_MAX_BYTES = 102400;
62441
62556
  var DEFAULT_MAX_LINES = 100;
62442
- function shortenPath(path30) {
62443
- if (typeof path30 !== "string") return "";
62557
+ function shortenPath(path31) {
62558
+ if (typeof path31 !== "string") return "";
62444
62559
  const home = os4.homedir();
62445
- if (path30.startsWith(home)) {
62446
- return `~${path30.slice(home.length)}`;
62560
+ if (path31.startsWith(home)) {
62561
+ return `~${path31.slice(home.length)}`;
62447
62562
  }
62448
- return path30;
62563
+ return path31;
62449
62564
  }
62450
62565
  function replaceTabs(text) {
62451
62566
  return text.replace(/\t/g, " ");
@@ -62526,14 +62641,14 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
62526
62641
  }
62527
62642
  } else if (this.toolName === "read_file") {
62528
62643
  const rawPath = str(this.args?.file_path ?? this.args?.path);
62529
- const path30 = rawPath !== null ? shortenPath(rawPath) : null;
62644
+ const path31 = rawPath !== null ? shortenPath(rawPath) : null;
62530
62645
  const offset = typeof this.args?.offset === "number" ? this.args.offset : void 0;
62531
62646
  const limit = typeof this.args?.limit === "number" ? this.args.limit : void 0;
62532
62647
  let pathDisplay;
62533
- if (path30 === null) {
62648
+ if (path31 === null) {
62534
62649
  pathDisplay = invalidArg;
62535
- } else if (path30) {
62536
- pathDisplay = theme.fg("accent", path30);
62650
+ } else if (path31) {
62651
+ pathDisplay = theme.fg("accent", path31);
62537
62652
  } else {
62538
62653
  const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
62539
62654
  pathDisplay = theme.fg("toolOutput", partialPath);
@@ -62580,12 +62695,12 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
62580
62695
  } else if (this.toolName === "write_file") {
62581
62696
  const rawPath = str(this.args?.file_path ?? this.args?.path);
62582
62697
  const fileContent = str(this.args?.content);
62583
- const path30 = rawPath !== null ? shortenPath(rawPath) : null;
62698
+ const path31 = rawPath !== null ? shortenPath(rawPath) : null;
62584
62699
  let pathDisplay;
62585
- if (path30 === null) {
62700
+ if (path31 === null) {
62586
62701
  pathDisplay = invalidArg;
62587
- } else if (path30) {
62588
- pathDisplay = theme.fg("accent", path30);
62702
+ } else if (path31) {
62703
+ pathDisplay = theme.fg("accent", path31);
62589
62704
  } else {
62590
62705
  const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
62591
62706
  pathDisplay = theme.fg("toolOutput", partialPath);
@@ -62622,12 +62737,12 @@ ${theme.fg("error", errorText)}`;
62622
62737
  }
62623
62738
  } else if (this.toolName === "edit_file") {
62624
62739
  const rawPath = str(this.args?.file_path ?? this.args?.path);
62625
- const path30 = rawPath !== null ? shortenPath(rawPath) : null;
62740
+ const path31 = rawPath !== null ? shortenPath(rawPath) : null;
62626
62741
  let pathDisplay;
62627
- if (path30 === null) {
62742
+ if (path31 === null) {
62628
62743
  pathDisplay = invalidArg;
62629
- } else if (path30) {
62630
- pathDisplay = theme.fg("accent", path30);
62744
+ } else if (path31) {
62745
+ pathDisplay = theme.fg("accent", path31);
62631
62746
  } else {
62632
62747
  const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
62633
62748
  pathDisplay = theme.fg("toolOutput", partialPath);
@@ -62652,7 +62767,7 @@ ${theme.fg("error", errorText)}`;
62652
62767
  const diff = this.result.details.diff;
62653
62768
  const firstChangedLine = this.result.details.firstChangedLine;
62654
62769
  if (firstChangedLine) {
62655
- text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path30 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
62770
+ text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path31 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
62656
62771
  }
62657
62772
  const lines = diff.split("\n");
62658
62773
  const maxLines = this.expanded ? lines.length : 15;
@@ -62672,7 +62787,7 @@ ${theme.fg("error", errorText)}`;
62672
62787
  const diff = generateEditDiff(oldText, newText, rawPath);
62673
62788
  const firstChangedLine = findFirstChangedLine(oldText, newText);
62674
62789
  if (firstChangedLine) {
62675
- text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path30 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
62790
+ text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path31 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
62676
62791
  }
62677
62792
  const lines = diff.split("\n");
62678
62793
  const maxLines = this.expanded ? lines.length : 15;
@@ -62691,9 +62806,9 @@ ${theme.fg("error", errorText)}`;
62691
62806
  }
62692
62807
  } else if (this.toolName === "list_dir") {
62693
62808
  const rawPath = str(this.args?.path);
62694
- const path30 = rawPath !== null ? shortenPath(rawPath || ".") : null;
62809
+ const path31 = rawPath !== null ? shortenPath(rawPath || ".") : null;
62695
62810
  const limit = this.args?.limit;
62696
- text = `${theme.fg("toolTitle", theme.bold("list_dir"))} ${path30 === null ? invalidArg : theme.fg("accent", path30)}`;
62811
+ text = `${theme.fg("toolTitle", theme.bold("list_dir"))} ${path31 === null ? invalidArg : theme.fg("accent", path31)}`;
62697
62812
  if (limit !== void 0) {
62698
62813
  text += theme.fg("toolOutput", ` (limit ${limit})`);
62699
62814
  }
@@ -62729,9 +62844,9 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
62729
62844
  } else if (this.toolName === "find_files") {
62730
62845
  const pattern = str(this.args?.pattern);
62731
62846
  const rawPath = str(this.args?.path);
62732
- const path30 = rawPath !== null ? shortenPath(rawPath || ".") : null;
62847
+ const path31 = rawPath !== null ? shortenPath(rawPath || ".") : null;
62733
62848
  const limit = this.args?.limit;
62734
- text = theme.fg("toolTitle", theme.bold("find_files")) + " " + (pattern === null ? invalidArg : theme.fg("accent", pattern || "")) + theme.fg("toolOutput", ` in ${path30 === null ? invalidArg : path30}`);
62849
+ text = theme.fg("toolTitle", theme.bold("find_files")) + " " + (pattern === null ? invalidArg : theme.fg("accent", pattern || "")) + theme.fg("toolOutput", ` in ${path31 === null ? invalidArg : path31}`);
62735
62850
  if (limit !== void 0) {
62736
62851
  text += theme.fg("toolOutput", ` (limit ${limit})`);
62737
62852
  }
@@ -62767,10 +62882,10 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
62767
62882
  } else if (this.toolName === "grep_text") {
62768
62883
  const pattern = str(this.args?.pattern);
62769
62884
  const rawPath = str(this.args?.path);
62770
- const path30 = rawPath !== null ? shortenPath(rawPath || ".") : null;
62885
+ const path31 = rawPath !== null ? shortenPath(rawPath || ".") : null;
62771
62886
  const glob = str(this.args?.glob);
62772
62887
  const limit = this.args?.limit;
62773
- text = theme.fg("toolTitle", theme.bold("grep_text")) + " " + (pattern === null ? invalidArg : theme.fg("accent", `/${pattern || ""}/`)) + theme.fg("toolOutput", ` in ${path30 === null ? invalidArg : path30}`);
62888
+ text = theme.fg("toolTitle", theme.bold("grep_text")) + " " + (pattern === null ? invalidArg : theme.fg("accent", `/${pattern || ""}/`)) + theme.fg("toolOutput", ` in ${path31 === null ? invalidArg : path31}`);
62774
62889
  if (glob) {
62775
62890
  text += theme.fg("toolOutput", ` (${glob})`);
62776
62891
  }
@@ -63224,8 +63339,8 @@ async function forkAtEntry(host, entryId) {
63224
63339
  host.showError("Failed to branch at entry");
63225
63340
  return;
63226
63341
  }
63227
- const path30 = host.sessionManager.getPathToEntry(entryId);
63228
- const pathNames = path30.map((e) => e.message?.role || "entry").join(" \u2192 ");
63342
+ const path31 = host.sessionManager.getPathToEntry(entryId);
63343
+ const pathNames = path31.map((e) => e.message?.role || "entry").join(" \u2192 ");
63229
63344
  const messages = host.sessionManager.getMessages();
63230
63345
  host.syncAgentFromActiveSession(messages);
63231
63346
  await host.syncSessionScopedState(messages);
@@ -63238,7 +63353,7 @@ async function forkAtEntry(host, entryId) {
63238
63353
  host.updatePendingMessagesDisplay();
63239
63354
  host.renderMessageHistory(messages);
63240
63355
  await host.sessionManager.save();
63241
- host.showStatus(`Branched at: ${pathNames} (${path30.length} messages). Continue to add to this branch.`);
63356
+ host.showStatus(`Branched at: ${pathNames} (${path31.length} messages). Continue to add to this branch.`);
63242
63357
  } catch (error) {
63243
63358
  host.showError(
63244
63359
  `Failed to branch: ${error instanceof Error ? error.message : String(error)}`
@@ -63266,10 +63381,10 @@ async function navigateToEntry(host, entryId) {
63266
63381
  host.sessionManager.save().catch((err) => {
63267
63382
  console.error("[Session] Save after navigation failed:", err);
63268
63383
  });
63269
- const path30 = host.sessionManager.getPathToEntry(entryId);
63384
+ const path31 = host.sessionManager.getPathToEntry(entryId);
63270
63385
  const entry = host.sessionManager.getEntry(entryId);
63271
63386
  const role = entry?.message?.role || "entry";
63272
- host.showStatus(`Switched to branch: ${role} (${path30.length} messages in path)`);
63387
+ host.showStatus(`Switched to branch: ${role} (${path31.length} messages in path)`);
63273
63388
  } catch (error) {
63274
63389
  host.showError(
63275
63390
  `Failed to navigate: ${error instanceof Error ? error.message : String(error)}`
@@ -65059,7 +65174,7 @@ function setupInteractiveEditorSubmitHandler(host) {
65059
65174
  host.chatContainer.addChild(userMsg);
65060
65175
  host.editor.setText("");
65061
65176
  host.ui.requestRender();
65062
- await new Promise((resolve5) => setImmediate(resolve5));
65177
+ await new Promise((resolve6) => setImmediate(resolve6));
65063
65178
  let finalContent = messageContent;
65064
65179
  const reminderPrefix = host.executionReminder;
65065
65180
  const combinedPrefix = [reminderPrefix].filter((value) => Boolean(value)).join("");
@@ -67713,11 +67828,11 @@ var HierarchicalSelectorComponent = class extends Container {
67713
67828
  // src/runtime/interactive-ui-helpers.ts
67714
67829
  function showHierarchicalMenu(host, initialPath = []) {
67715
67830
  const basePath = [...initialPath];
67716
- const showAtPath = (path30) => {
67831
+ const showAtPath = (path31) => {
67717
67832
  host.showSelector((done) => {
67718
67833
  const selector = new HierarchicalSelectorComponent({
67719
67834
  tree: commandTree,
67720
- path: path30,
67835
+ path: path31,
67721
67836
  basePath,
67722
67837
  onNavigate: (newPath) => {
67723
67838
  done();
@@ -67725,7 +67840,7 @@ function showHierarchicalMenu(host, initialPath = []) {
67725
67840
  },
67726
67841
  onSelect: async (selectedPath, node, searchArgs) => {
67727
67842
  if (node.handler) {
67728
- const args = searchArgs || (selectedPath.length > path30.length ? selectedPath.slice(path30.length).join(" ") : void 0);
67843
+ const args = searchArgs || (selectedPath.length > path31.length ? selectedPath.slice(path31.length).join(" ") : void 0);
67729
67844
  const commandPath = "/" + selectedPath.join("/");
67730
67845
  if (!args && host.isInteractiveCommand(commandPath)) {
67731
67846
  done();
@@ -68404,7 +68519,7 @@ async function handleDirectBash(host, command) {
68404
68519
  child.stderr.on("data", (data) => {
68405
68520
  output.append(data.toString());
68406
68521
  });
68407
- return new Promise((resolve5) => {
68522
+ return new Promise((resolve6) => {
68408
68523
  let settled = false;
68409
68524
  const finish = (code) => {
68410
68525
  if (settled) return;
@@ -68417,7 +68532,7 @@ async function handleDirectBash(host, command) {
68417
68532
  }
68418
68533
  host.chatContainer.addChild(new Spacer(1));
68419
68534
  host.ui.requestRender();
68420
- resolve5();
68535
+ resolve6();
68421
68536
  };
68422
68537
  child.on("error", (error) => {
68423
68538
  output.append(error.message);
@@ -68460,11 +68575,11 @@ function installInteractiveInteractionHandler(host) {
68460
68575
  if (!("timeoutMs" in request) || !request.timeoutMs || request.timeoutMs <= 0) {
68461
68576
  return { value: await promise, timedOut: false };
68462
68577
  }
68463
- return await new Promise((resolve5, reject) => {
68464
- const timer = setTimeout(() => resolve5({ timedOut: true }), request.timeoutMs);
68578
+ return await new Promise((resolve6, reject) => {
68579
+ const timer = setTimeout(() => resolve6({ timedOut: true }), request.timeoutMs);
68465
68580
  promise.then((value) => {
68466
68581
  clearTimeout(timer);
68467
- resolve5({ value, timedOut: false });
68582
+ resolve6({ value, timedOut: false });
68468
68583
  }).catch((error) => {
68469
68584
  clearTimeout(timer);
68470
68585
  reject(error);
@@ -68564,15 +68679,15 @@ function showExtensionNotification(host, message, type = "info") {
68564
68679
  host.ui.requestRender();
68565
68680
  }
68566
68681
  function showExtensionSelector2(host, title, options, opts) {
68567
- return new Promise((resolve5) => {
68682
+ return new Promise((resolve6) => {
68568
68683
  host.showStatus(`Waiting for selection: ${title}`);
68569
68684
  if (opts?.signal?.aborted) {
68570
- resolve5(void 0);
68685
+ resolve6(void 0);
68571
68686
  return;
68572
68687
  }
68573
68688
  const onAbort = () => {
68574
68689
  host.restoreEditor();
68575
- resolve5(void 0);
68690
+ resolve6(void 0);
68576
68691
  };
68577
68692
  opts?.signal?.addEventListener("abort", onAbort, { once: true });
68578
68693
  const selector = new ExtensionSelectorComponent(
@@ -68581,12 +68696,12 @@ function showExtensionSelector2(host, title, options, opts) {
68581
68696
  (option) => {
68582
68697
  opts?.signal?.removeEventListener("abort", onAbort);
68583
68698
  host.restoreEditor();
68584
- resolve5(option);
68699
+ resolve6(option);
68585
68700
  },
68586
68701
  () => {
68587
68702
  opts?.signal?.removeEventListener("abort", onAbort);
68588
68703
  host.restoreEditor();
68589
- resolve5(void 0);
68704
+ resolve6(void 0);
68590
68705
  }
68591
68706
  );
68592
68707
  host.editorContainer.clear();
@@ -68602,15 +68717,15 @@ ${message}`, ["Yes", "No"], opts);
68602
68717
  return result === "Yes";
68603
68718
  }
68604
68719
  function showExtensionInput(host, title, placeholder, opts) {
68605
- return new Promise((resolve5) => {
68720
+ return new Promise((resolve6) => {
68606
68721
  host.showStatus(`Waiting for input: ${title}`);
68607
68722
  if (opts?.signal?.aborted) {
68608
- resolve5(void 0);
68723
+ resolve6(void 0);
68609
68724
  return;
68610
68725
  }
68611
68726
  const onAbort = () => {
68612
68727
  host.restoreEditor();
68613
- resolve5(void 0);
68728
+ resolve6(void 0);
68614
68729
  };
68615
68730
  opts?.signal?.addEventListener("abort", onAbort, { once: true });
68616
68731
  const input = new ExtensionInputComponent(
@@ -68619,12 +68734,12 @@ function showExtensionInput(host, title, placeholder, opts) {
68619
68734
  (value) => {
68620
68735
  opts?.signal?.removeEventListener("abort", onAbort);
68621
68736
  host.restoreEditor();
68622
- resolve5(value);
68737
+ resolve6(value);
68623
68738
  },
68624
68739
  () => {
68625
68740
  opts?.signal?.removeEventListener("abort", onAbort);
68626
68741
  host.restoreEditor();
68627
- resolve5(void 0);
68742
+ resolve6(void 0);
68628
68743
  }
68629
68744
  );
68630
68745
  host.editorContainer.clear();
@@ -68635,7 +68750,7 @@ function showExtensionInput(host, title, placeholder, opts) {
68635
68750
  });
68636
68751
  }
68637
68752
  function showExtensionEditor(host, title, prefill) {
68638
- return new Promise((resolve5) => {
68753
+ return new Promise((resolve6) => {
68639
68754
  host.showStatus(`Waiting for input: ${title}`);
68640
68755
  const container = new Container();
68641
68756
  container.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
@@ -68657,12 +68772,12 @@ function showExtensionEditor(host, title, prefill) {
68657
68772
  preview: value.slice(0, 120)
68658
68773
  });
68659
68774
  host.restoreEditor();
68660
- resolve5(value);
68775
+ resolve6(value);
68661
68776
  };
68662
68777
  editor.onEscape = () => {
68663
68778
  host.logDebug("extension:editor:cancel", { title });
68664
68779
  host.restoreEditor();
68665
- resolve5(void 0);
68780
+ resolve6(void 0);
68666
68781
  };
68667
68782
  container.addChild(editor);
68668
68783
  container.addChild(new Spacer(1));
@@ -68676,14 +68791,14 @@ function showExtensionEditor(host, title, prefill) {
68676
68791
  }
68677
68792
  function showExtensionCustom(host, factory, options) {
68678
68793
  const savedText = host.editor.getText();
68679
- return new Promise((resolve5, reject) => {
68794
+ return new Promise((resolve6, reject) => {
68680
68795
  let closed = false;
68681
68796
  const close = (result) => {
68682
68797
  if (closed) return;
68683
68798
  closed = true;
68684
68799
  host.restoreEditor();
68685
68800
  host.editor.setText(savedText);
68686
- resolve5(result);
68801
+ resolve6(result);
68687
68802
  };
68688
68803
  Promise.resolve(factory(host.ui, theme, close)).then((component) => {
68689
68804
  if (closed) return;
@@ -68895,8 +69010,8 @@ async function loadInteractiveExtensions(host) {
68895
69010
  );
68896
69011
  host.extensionRunner.setUIContext(host.extensionUIContext);
68897
69012
  if (process.env.PIE_VERBOSE) {
68898
- for (const { path: path30, error } of errors) {
68899
- console.error(`[Extension] Failed to load ${path30}: ${error}`);
69013
+ for (const { path: path31, error } of errors) {
69014
+ console.error(`[Extension] Failed to load ${path31}: ${error}`);
68900
69015
  }
68901
69016
  }
68902
69017
  const extensionTools = convertExtensionTools(extensions);
@@ -70224,6 +70339,26 @@ function parseInput(line) {
70224
70339
  reason: typeof parsed.reason === "string" ? parsed.reason : void 0
70225
70340
  };
70226
70341
  }
70342
+ if (parsed.type === "session.rewind") {
70343
+ return {
70344
+ type: "session.rewind",
70345
+ sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
70346
+ requestId: typeof parsed.requestId === "string" ? parsed.requestId : void 0,
70347
+ entryId: typeof parsed.entryId === "string" ? parsed.entryId : void 0,
70348
+ checkpointId: typeof parsed.checkpointId === "string" ? parsed.checkpointId : void 0
70349
+ };
70350
+ }
70351
+ if (parsed.type === "session.fork") {
70352
+ return {
70353
+ type: "session.fork",
70354
+ sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
70355
+ requestId: typeof parsed.requestId === "string" ? parsed.requestId : void 0,
70356
+ fromEntryId: typeof parsed.fromEntryId === "string" ? parsed.fromEntryId : void 0,
70357
+ targetSessionId: typeof parsed.targetSessionId === "string" ? parsed.targetSessionId : void 0,
70358
+ name: typeof parsed.name === "string" ? parsed.name : void 0,
70359
+ cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0
70360
+ };
70361
+ }
70227
70362
  if ((parsed.type === "turn.request" || parsed.type === "turn.input") && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
70228
70363
  const streamingBehavior = parsed.streamingBehavior;
70229
70364
  if (streamingBehavior !== void 0 && streamingBehavior !== "steer" && streamingBehavior !== "followUp") {
@@ -70386,6 +70521,7 @@ async function runJsonEventsMode(params) {
70386
70521
  let thinkingLevel = "off";
70387
70522
  let defaultRuntime;
70388
70523
  let defaultModelState;
70524
+ const completedSessionControlRequests = /* @__PURE__ */ new Map();
70389
70525
  const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
70390
70526
  const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
70391
70527
  writeEvent({ type: "agent.ready", sessionId });
@@ -70396,7 +70532,7 @@ async function runJsonEventsMode(params) {
70396
70532
  return typeof message.sessionId === "string" && message.sessionId !== sessionId;
70397
70533
  }
70398
70534
  function delay(ms) {
70399
- return new Promise((resolve5) => setTimeout(resolve5, Math.max(0, ms)));
70535
+ return new Promise((resolve6) => setTimeout(resolve6, Math.max(0, ms)));
70400
70536
  }
70401
70537
  async function waitForActiveController(timeoutMs = 1e3) {
70402
70538
  const deadline = Date.now() + timeoutMs;
@@ -70534,6 +70670,148 @@ async function runJsonEventsMode(params) {
70534
70670
  }
70535
70671
  return error instanceof Error ? error.message : String(error);
70536
70672
  }
70673
+ function sessionControlStore() {
70674
+ return new FileSessionStore(runtime?.paths.sessionsDir ?? getSessionsDir());
70675
+ }
70676
+ function invalidSessionControl(message) {
70677
+ return new SessionControlError("invalid_request", message);
70678
+ }
70679
+ function requireSessionControlString(value, field) {
70680
+ const normalized = value?.trim();
70681
+ if (!normalized) {
70682
+ throw invalidSessionControl(`${field} is required`);
70683
+ }
70684
+ return normalized;
70685
+ }
70686
+ function requireSessionControlBase(message) {
70687
+ const requestedSessionId = requireSessionControlString(message.sessionId, "sessionId");
70688
+ const requestId = requireSessionControlString(message.requestId, "requestId");
70689
+ if (requestedSessionId !== sessionId) {
70690
+ throw new SessionControlError("session_mismatch", sessionMismatchError(requestedSessionId), false);
70691
+ }
70692
+ if (activeTurn && !activeTurn.finalized) {
70693
+ throw new SessionControlError("session_busy", `Cannot ${message.type.slice("session.".length)} session while a turn is active`);
70694
+ }
70695
+ return { sessionId: requestedSessionId, requestId };
70696
+ }
70697
+ function resolveRewindEntryId(message) {
70698
+ const entryId = message.entryId?.trim();
70699
+ const checkpointId = message.checkpointId?.trim();
70700
+ if (entryId && checkpointId && entryId !== checkpointId) {
70701
+ throw invalidSessionControl("entryId and checkpointId must match when both are provided");
70702
+ }
70703
+ const resolved = entryId || checkpointId;
70704
+ if (!resolved) {
70705
+ throw invalidSessionControl("entryId or checkpointId is required");
70706
+ }
70707
+ return resolved;
70708
+ }
70709
+ function writeSessionControlFailure(message, operation, error) {
70710
+ const detail = error instanceof SessionControlError ? error : new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
70711
+ writeEvent({
70712
+ type: "session.failed",
70713
+ sessionId: message.sessionId || sessionId,
70714
+ requestId: message.requestId,
70715
+ operation,
70716
+ error: detail.message,
70717
+ code: detail.code,
70718
+ recoverable: detail.recoverable
70719
+ });
70720
+ }
70721
+ async function saveRuntimeSessionForControl() {
70722
+ if (!runtime?.sessionManager.getActiveSession()) return;
70723
+ try {
70724
+ await runtime.sessionManager.save();
70725
+ } catch (error) {
70726
+ throw new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
70727
+ }
70728
+ }
70729
+ async function syncRuntimeAfterRewind(controlSessionId) {
70730
+ if (params.mockResponse !== void 0) return;
70731
+ if (runtime?.sessionManager.getActiveSessionId() !== controlSessionId) return;
70732
+ const loaded = await runtime.sessionManager.loadSession(controlSessionId, { warnIfMissing: false });
70733
+ if (!loaded) {
70734
+ const exists = await runtime.sessionManager.hasSession(controlSessionId);
70735
+ throw new SessionControlError(
70736
+ exists ? "session_unrecoverable" : "session_not_found",
70737
+ exists ? `Session could not be recovered: ${controlSessionId}` : `Session not found: ${controlSessionId}`,
70738
+ !exists
70739
+ );
70740
+ }
70741
+ controller?.syncFromActiveSession();
70742
+ }
70743
+ async function handleSessionRewind(message) {
70744
+ try {
70745
+ const { sessionId: controlSessionId, requestId } = requireSessionControlBase(message);
70746
+ const cached = completedSessionControlRequests.get(requestId);
70747
+ if (cached) {
70748
+ writeEvent(cached);
70749
+ return;
70750
+ }
70751
+ const entryId = resolveRewindEntryId(message);
70752
+ await saveRuntimeSessionForControl();
70753
+ const result = await rewindStoredSession({
70754
+ store: sessionControlStore(),
70755
+ sessionId: controlSessionId,
70756
+ entryId
70757
+ });
70758
+ await syncRuntimeAfterRewind(controlSessionId);
70759
+ mockActiveEntryId = result.headEntryId;
70760
+ const event = {
70761
+ type: "session.rewound",
70762
+ sessionId: controlSessionId,
70763
+ requestId,
70764
+ entryId: result.entryId,
70765
+ checkpointId: result.checkpointId,
70766
+ headEntryId: result.headEntryId,
70767
+ activeEntryId: result.activeEntryId
70768
+ };
70769
+ completedSessionControlRequests.set(requestId, event);
70770
+ writeEvent(event);
70771
+ } catch (error) {
70772
+ writeSessionControlFailure(message, "rewind", error);
70773
+ }
70774
+ }
70775
+ async function handleSessionFork(message) {
70776
+ try {
70777
+ const { sessionId: controlSessionId, requestId } = requireSessionControlBase(message);
70778
+ const sourceEntryId = requireSessionControlString(message.fromEntryId, "fromEntryId");
70779
+ const targetSessionId = requireSessionControlString(message.targetSessionId, "targetSessionId");
70780
+ const name = requireSessionControlString(message.name, "name");
70781
+ const forkCwd = message.cwd?.trim() || void 0;
70782
+ const cached = completedSessionControlRequests.get(requestId);
70783
+ if (cached) {
70784
+ writeEvent(cached);
70785
+ return;
70786
+ }
70787
+ await saveRuntimeSessionForControl();
70788
+ const result = await forkStoredSession({
70789
+ store: sessionControlStore(),
70790
+ sourceSessionId: controlSessionId,
70791
+ sourceEntryId,
70792
+ targetSessionId,
70793
+ name,
70794
+ cwd: forkCwd,
70795
+ requestId
70796
+ });
70797
+ const event = {
70798
+ type: "session.forked",
70799
+ sessionId: controlSessionId,
70800
+ requestId,
70801
+ sourceSessionId: result.sourceSessionId,
70802
+ sourceEntryId: result.sourceEntryId,
70803
+ sourceCheckpointId: result.sourceCheckpointId,
70804
+ targetSessionId: result.targetSessionId,
70805
+ targetHeadEntryId: result.targetHeadEntryId,
70806
+ targetActiveEntryId: result.targetActiveEntryId,
70807
+ headEntryId: result.headEntryId
70808
+ };
70809
+ completedSessionControlRequests.set(requestId, event);
70810
+ writeEvent(event);
70811
+ } catch (error) {
70812
+ writeSessionControlFailure(message, "fork", error);
70813
+ }
70814
+ }
70537
70815
  function finalize(kind, detail) {
70538
70816
  const turn = activeTurn;
70539
70817
  if (!turn || turn.finalized) return;
@@ -70783,6 +71061,7 @@ async function runJsonEventsMode(params) {
70783
71061
  cwd: runtime.cwd,
70784
71062
  skillsSection: runtime.skillsSection,
70785
71063
  knowledgeSection: runtime.knowledgeSection,
71064
+ appendSystemPrompt: params.developerInstructions,
70786
71065
  tools: tools.map((tool) => ({ name: tool.name, description: tool.description }))
70787
71066
  });
70788
71067
  agent = new AgentClass({
@@ -71168,6 +71447,14 @@ async function runJsonEventsMode(params) {
71168
71447
  await interrupt(message);
71169
71448
  continue;
71170
71449
  }
71450
+ if (message.type === "session.rewind") {
71451
+ await handleSessionRewind(message);
71452
+ continue;
71453
+ }
71454
+ if (message.type === "session.fork") {
71455
+ await handleSessionFork(message);
71456
+ continue;
71457
+ }
71171
71458
  const shouldTrackTurn = !activeTurn || activeTurn.finalized;
71172
71459
  const turnPromise = runTurn(message).catch((error) => {
71173
71460
  writeEvent({
@@ -71189,20 +71476,44 @@ async function runJsonEventsMode(params) {
71189
71476
  await disposeRuntime();
71190
71477
  }
71191
71478
 
71192
- // src/cli.ts
71193
- enableEarlyLogBuffer();
71194
- var logError = (msg, err) => {
71195
- const logPath = getRuntimeLogPath();
71196
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
71197
- const stack = err instanceof Error ? err.stack || "" : "";
71198
- fs26.mkdirSync(path29.dirname(logPath), { recursive: true });
71199
- fs26.appendFileSync(logPath, `[${timestamp}] ${msg}
71200
- ${stack}
71479
+ // src/developer-instructions.ts
71480
+ import * as fs26 from "fs";
71481
+ import * as path29 from "path";
71482
+ var MAX_DEVELOPER_INSTRUCTIONS_CHARS = 64e3;
71483
+ function readTextFileBounded(filePath) {
71484
+ const resolved = path29.resolve(filePath);
71485
+ const stat2 = fs26.statSync(resolved);
71486
+ if (!stat2.isFile()) {
71487
+ throw new Error(`Developer instructions file is not a regular file: ${filePath}`);
71488
+ }
71489
+ if (stat2.size > MAX_DEVELOPER_INSTRUCTIONS_CHARS * 4) {
71490
+ throw new Error(`Developer instructions file is too large: ${filePath}`);
71491
+ }
71492
+ return fs26.readFileSync(resolved, "utf8");
71493
+ }
71494
+ function collectFlagValues(args, flag) {
71495
+ const values = [];
71496
+ for (let i = 0; i < args.length; i += 1) {
71497
+ if (args[i] === flag && args[i + 1]) {
71498
+ values.push(args[i + 1]);
71499
+ i += 1;
71500
+ }
71501
+ }
71502
+ return values;
71503
+ }
71504
+ function resolveDeveloperInstructionsFromArgs(args) {
71505
+ const direct = collectFlagValues(args, "--developer-instructions");
71506
+ const files = collectFlagValues(args, "--developer-instructions-file").map(readTextFileBounded);
71507
+ const parts = [...direct, ...files].map((part) => part.trim()).filter(Boolean);
71508
+ if (parts.length === 0) return void 0;
71509
+ const combined = parts.join("\n\n");
71510
+ if (combined.length > MAX_DEVELOPER_INSTRUCTIONS_CHARS) {
71511
+ throw new Error(`Developer instructions exceed ${MAX_DEVELOPER_INSTRUCTIONS_CHARS} characters`);
71512
+ }
71513
+ return combined;
71514
+ }
71201
71515
 
71202
- `);
71203
- };
71204
- setupGlobalErrorHandlers(logError);
71205
- migrateConfigFromAgentDir();
71516
+ // src/cli-help.ts
71206
71517
  function showHelp() {
71207
71518
  console.log(`
71208
71519
  Pie AI Agent CLI
@@ -71242,11 +71553,36 @@ Print Mode Options:
71242
71553
  --json-events Run JSONL protocol mode over stdin/stdout
71243
71554
  --session-id Reuse or create a specific session in non-interactive mode
71244
71555
  --resume-required In JSON-events mode, fail if --session-id cannot be resumed
71556
+ --developer-instructions <text> Append stable host/developer instructions in JSON-events mode
71557
+ --developer-instructions-file <path> Read stable host/developer instructions from a file
71245
71558
  --extension-path Add an extra extension search directory (repeatable)
71246
71559
  --no-builtin-extensions Skip built-in extensions (keep user/project ones)
71247
71560
  --no-extensions Skip all discovered extensions (keeps --extension-path)
71248
71561
  `);
71249
71562
  }
71563
+
71564
+ // src/cli.ts
71565
+ enableEarlyLogBuffer();
71566
+ var logError = (msg, err) => {
71567
+ const logPath = getRuntimeLogPath();
71568
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
71569
+ const stack = err instanceof Error ? err.stack || "" : "";
71570
+ fs27.mkdirSync(path30.dirname(logPath), { recursive: true });
71571
+ fs27.appendFileSync(logPath, `[${timestamp}] ${msg}
71572
+ ${stack}
71573
+
71574
+ `);
71575
+ };
71576
+ setupGlobalErrorHandlers(logError);
71577
+ migrateConfigFromAgentDir();
71578
+ var STABLE_CLI_COMMANDS = {
71579
+ chat: "chat",
71580
+ doctor: "doctor",
71581
+ models: "models",
71582
+ sessions: "sessions",
71583
+ extensions: "extensions",
71584
+ permissions: "permissions"
71585
+ };
71250
71586
  async function runDoctorCommand(args) {
71251
71587
  const json = args.includes("--json");
71252
71588
  const report = await runDoctor();
@@ -71339,7 +71675,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
71339
71675
  }
71340
71676
  async function createCliTestStreamFnFromEnv() {
71341
71677
  if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
71342
- return (await import("./chunks/test-stream-A7JSM2UM.js")).createTestStreamFnFromSequenceEnv();
71678
+ return (await import("./chunks/test-stream-L4PUYWQQ.js")).createTestStreamFnFromSequenceEnv();
71343
71679
  }
71344
71680
  async function startChat(initialPrompt, testCommand) {
71345
71681
  const rawOutput = process.argv.includes("--raw-output");
@@ -71351,11 +71687,19 @@ async function startChat(initialPrompt, testCommand) {
71351
71687
  const extensionPaths = parseRepeatedFlag(process.argv, "--extension-path");
71352
71688
  const extensionFlags = parseExtensionFlags(process.argv);
71353
71689
  if (jsonEvents) {
71690
+ let developerInstructions;
71691
+ try {
71692
+ developerInstructions = resolveDeveloperInstructionsFromArgs(process.argv);
71693
+ } catch (error) {
71694
+ console.error(error instanceof Error ? `Error: ${error.message}` : String(error));
71695
+ process.exit(1);
71696
+ }
71354
71697
  await runWithJsonEventsConsoleIsolation(async () => {
71355
71698
  if (process.env.PIE_TEST_MOCK_RESPONSE !== void 0) {
71356
71699
  await runJsonEventsMode({
71357
71700
  explicitSessionId,
71358
71701
  resumeRequired,
71702
+ developerInstructions,
71359
71703
  mockResponse: process.env.PIE_TEST_MOCK_RESPONSE
71360
71704
  });
71361
71705
  return;
@@ -71363,6 +71707,7 @@ async function startChat(initialPrompt, testCommand) {
71363
71707
  await runJsonEventsMode({
71364
71708
  explicitSessionId,
71365
71709
  resumeRequired,
71710
+ developerInstructions,
71366
71711
  streamFn: await createCliTestStreamFnFromEnv(),
71367
71712
  createRuntime: async ({ cwd, sessionId }) => composeCliRuntime({
71368
71713
  explicitSessionId: explicitSessionId ?? sessionId,
@@ -71425,9 +71770,9 @@ async function startChat(initialPrompt, testCommand) {
71425
71770
  flushEarlyLogs();
71426
71771
  if (testCommand) {
71427
71772
  console.log(`[TEST] Auto-executing command: ${testCommand}`);
71428
- await new Promise((resolve5) => setTimeout(resolve5, 500));
71773
+ await new Promise((resolve6) => setTimeout(resolve6, 500));
71429
71774
  await interactive.executeCommand(testCommand);
71430
- await new Promise((resolve5) => setTimeout(resolve5, 2e3));
71775
+ await new Promise((resolve6) => setTimeout(resolve6, 2e3));
71431
71776
  console.log("[TEST] Command executed, exiting...");
71432
71777
  process.exit(0);
71433
71778
  return;
@@ -71448,11 +71793,11 @@ async function main() {
71448
71793
  console.log(VERSION);
71449
71794
  return;
71450
71795
  }
71451
- if (args[0] === "doctor") {
71796
+ if (args[0] === STABLE_CLI_COMMANDS.doctor) {
71452
71797
  await runDoctorCommand(args.slice(1));
71453
71798
  return;
71454
71799
  }
71455
- if (args[0] === "models") {
71800
+ if (args[0] === STABLE_CLI_COMMANDS.models) {
71456
71801
  try {
71457
71802
  await runModelsCommand(args.slice(1));
71458
71803
  } catch (error) {
@@ -71461,15 +71806,15 @@ async function main() {
71461
71806
  }
71462
71807
  return;
71463
71808
  }
71464
- if (args[0] === "sessions") {
71809
+ if (args[0] === STABLE_CLI_COMMANDS.sessions) {
71465
71810
  await runSessionsCommand(args.slice(1));
71466
71811
  return;
71467
71812
  }
71468
- if (args[0] === "extensions") {
71813
+ if (args[0] === STABLE_CLI_COMMANDS.extensions) {
71469
71814
  await runExtensionsCommand(args.slice(1));
71470
71815
  return;
71471
71816
  }
71472
- if (args[0] === "permissions") {
71817
+ if (args[0] === STABLE_CLI_COMMANDS.permissions) {
71473
71818
  console.log(formatPermissionsHelp());
71474
71819
  return;
71475
71820
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/pie",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "Pie AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {