@cydm/pie 1.0.19 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
3
3
  import {
4
+ VERSION,
4
5
  createCliHostCapabilities,
5
6
  createCliWebResearchHealthStore,
6
7
  getAgentDir,
@@ -14,11 +15,12 @@ import {
14
15
  getSettingsPath,
15
16
  getThemesDir,
16
17
  migrateConfigFromAgentDir
17
- } from "./chunks/chunk-KZ54RSWP.js";
18
+ } from "./chunks/chunk-ZYOTRKU7.js";
18
19
  import {
19
20
  AGENTS_CONTEXT_FILE_NAME,
20
21
  AgentSessionController,
21
22
  BUILTIN_TOOL_CAPABILITY_METADATA,
23
+ FileSessionStore,
22
24
  SessionTraceSnapshotWriter,
23
25
  abortExecutionState,
24
26
  attachAgentEventsToSessionTrace,
@@ -45,6 +47,7 @@ import {
45
47
  evaluateTodoClosureAfterFailedTurn,
46
48
  findFirstKeptEntryId,
47
49
  formatSkillSummariesForPrompt,
50
+ generateEntryId,
48
51
  getAutoCompactTokenLimit,
49
52
  hasInteractionHandler,
50
53
  maybeAdvanceTodoExecutionState,
@@ -56,8 +59,8 @@ import {
56
59
  selectToolsForRuntimePolicy,
57
60
  shouldPreserveExecutionStateForUserText,
58
61
  supersedeExecutionState
59
- } from "./chunks/chunk-GZVSE44O.js";
60
- import "./chunks/chunk-2R3XTLE2.js";
62
+ } from "./chunks/chunk-NHR6EBM2.js";
63
+ import "./chunks/chunk-L5BJNCNG.js";
61
64
  import {
62
65
  Deref,
63
66
  Errors,
@@ -91,7 +94,7 @@ import {
91
94
  setLogger,
92
95
  sortToolModelCandidatesByCapability,
93
96
  type_exports
94
- } from "./chunks/chunk-Q2N6B5JN.js";
97
+ } from "./chunks/chunk-VESPMEDG.js";
95
98
  import {
96
99
  resolveCliProjectRoot
97
100
  } from "./chunks/chunk-NTYHFBUA.js";
@@ -1221,12 +1224,12 @@ var require_supports_color = __commonJS({
1221
1224
  "use strict";
1222
1225
  var os6 = __require("os");
1223
1226
  var tty = __require("tty");
1224
- var hasFlag = require_has_flag();
1227
+ var hasFlag2 = require_has_flag();
1225
1228
  var { env } = process;
1226
1229
  var forceColor;
1227
- if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
1230
+ if (hasFlag2("no-color") || hasFlag2("no-colors") || hasFlag2("color=false") || hasFlag2("color=never")) {
1228
1231
  forceColor = 0;
1229
- } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
1232
+ } else if (hasFlag2("color") || hasFlag2("colors") || hasFlag2("color=true") || hasFlag2("color=always")) {
1230
1233
  forceColor = 1;
1231
1234
  }
1232
1235
  if ("FORCE_COLOR" in env) {
@@ -1253,10 +1256,10 @@ var require_supports_color = __commonJS({
1253
1256
  if (forceColor === 0) {
1254
1257
  return 0;
1255
1258
  }
1256
- if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
1259
+ if (hasFlag2("color=16m") || hasFlag2("color=full") || hasFlag2("color=truecolor")) {
1257
1260
  return 3;
1258
1261
  }
1259
- if (hasFlag("color=256")) {
1262
+ if (hasFlag2("color=256")) {
1260
1263
  return 2;
1261
1264
  }
1262
1265
  if (haveStream && !streamIsTTY && forceColor === void 0) {
@@ -14068,7 +14071,7 @@ var require_http = __commonJS({
14068
14071
  return joined;
14069
14072
  }
14070
14073
  function http(hljs) {
14071
- const VERSION = "HTTP/(2|1\\.[01])";
14074
+ const VERSION2 = "HTTP/(2|1\\.[01])";
14072
14075
  const HEADER_NAME = /[A-Za-z][A-Za-z0-9-]*/;
14073
14076
  const HEADER = {
14074
14077
  className: "attribute",
@@ -14101,12 +14104,12 @@ var require_http = __commonJS({
14101
14104
  contains: [
14102
14105
  // response
14103
14106
  {
14104
- begin: "^(?=" + VERSION + " \\d{3})",
14107
+ begin: "^(?=" + VERSION2 + " \\d{3})",
14105
14108
  end: /$/,
14106
14109
  contains: [
14107
14110
  {
14108
14111
  className: "meta",
14109
- begin: VERSION
14112
+ begin: VERSION2
14110
14113
  },
14111
14114
  {
14112
14115
  className: "number",
@@ -14121,7 +14124,7 @@ var require_http = __commonJS({
14121
14124
  },
14122
14125
  // request
14123
14126
  {
14124
- begin: "(?=^[A-Z]+ (.*?) " + VERSION + "$)",
14127
+ begin: "(?=^[A-Z]+ (.*?) " + VERSION2 + "$)",
14125
14128
  end: /$/,
14126
14129
  contains: [
14127
14130
  {
@@ -14133,7 +14136,7 @@ var require_http = __commonJS({
14133
14136
  },
14134
14137
  {
14135
14138
  className: "meta",
14136
- begin: VERSION
14139
+ begin: VERSION2
14137
14140
  },
14138
14141
  {
14139
14142
  className: "keyword",
@@ -43943,7 +43946,7 @@ var require_dist = __commonJS({
43943
43946
  });
43944
43947
 
43945
43948
  // src/cli.ts
43946
- import * as fs25 from "fs";
43949
+ import * as fs26 from "fs";
43947
43950
  import * as path26 from "path";
43948
43951
 
43949
43952
  // src/cli-args.ts
@@ -45481,6 +45484,356 @@ function parseModelsCommandArgs(args) {
45481
45484
  return parsed;
45482
45485
  }
45483
45486
 
45487
+ // src/commands/sessions.ts
45488
+ import fs6 from "node:fs";
45489
+ async function runSessionsCommand(args) {
45490
+ const command = args[0] || "help";
45491
+ const rest = args.slice(1);
45492
+ try {
45493
+ if (command === "list") {
45494
+ await listSessions(rest);
45495
+ return;
45496
+ }
45497
+ if (command === "read") {
45498
+ await readSession(rest);
45499
+ return;
45500
+ }
45501
+ if (command === "rename") {
45502
+ await renameSession(rest);
45503
+ return;
45504
+ }
45505
+ if (command === "rewind") {
45506
+ await rewindSession(rest);
45507
+ return;
45508
+ }
45509
+ if (command === "fork") {
45510
+ await forkSession(rest);
45511
+ return;
45512
+ }
45513
+ if (command === "help" || command === "--help" || command === "-h") {
45514
+ printSessionsUsage();
45515
+ return;
45516
+ }
45517
+ throw new Error(`Unknown sessions command: ${command}`);
45518
+ } catch (error) {
45519
+ if (hasFlag(args, "--json")) {
45520
+ console.log(JSON.stringify({ ok: false, error: error instanceof Error ? error.message : String(error) }));
45521
+ } else {
45522
+ console.error(error instanceof Error ? error.message : String(error));
45523
+ }
45524
+ process.exitCode = 1;
45525
+ }
45526
+ }
45527
+ async function listSessions(args) {
45528
+ const json = hasFlag(args, "--json");
45529
+ const limit = numericFlag(args, "--limit", 50);
45530
+ const cwd = stringFlag(args, "--cwd");
45531
+ const cursor = stringFlag(args, "--cursor");
45532
+ const store = new FileSessionStore(getSessionsDir());
45533
+ const cursorState = decodeListCursor(cursor);
45534
+ const queryKey = listCursorQueryKey({ cwd });
45535
+ const after = cursorState.q === queryKey ? cursorState.after : void 0;
45536
+ const page = await store.listMetadataPage({
45537
+ limit,
45538
+ after,
45539
+ filter: (metadata) => !cwd || cwdMatches(typeof metadata.cwd === "string" ? metadata.cwd : void 0, cwd)
45540
+ });
45541
+ const sessions = page.metadata.map(sessionSummary);
45542
+ const hasMore = page.hasMore;
45543
+ const lastSession = sessions.at(-1);
45544
+ const nextCursor = hasMore && lastSession ? encodeListCursor({ v: 2, q: queryKey, after: { updatedAt: lastSession.updatedAt, id: lastSession.id } }) : void 0;
45545
+ if (json) {
45546
+ console.log(JSON.stringify({ ok: true, sessions, hasMore, nextCursor }, null, 2));
45547
+ return;
45548
+ }
45549
+ if (sessions.length === 0) {
45550
+ console.log("No sessions.");
45551
+ return;
45552
+ }
45553
+ for (const session of sessions) {
45554
+ console.log(`${session.id} ${session.name} ${new Date(session.updatedAt).toISOString()}${session.cwd ? ` ${session.cwd}` : ""}`);
45555
+ }
45556
+ }
45557
+ async function readSession(args) {
45558
+ const json = hasFlag(args, "--json");
45559
+ const sessionId = positionalArgs(args, /* @__PURE__ */ new Set(["--limit", "--before"]))[0];
45560
+ if (!sessionId) throw new Error("Usage: pie sessions read <sessionId> [--json] [--limit <n>] [--before <cursor>]");
45561
+ const limit = numericFlag(args, "--limit", 200);
45562
+ const before = stringFlag(args, "--before");
45563
+ const store = new FileSessionStore(getSessionsDir());
45564
+ const data = await store.load(sessionId);
45565
+ if (!data) throw new Error(`Session not found: ${sessionId}`);
45566
+ const events = activeTranscriptEvents(activePathEntries(data));
45567
+ const end = resolveBeforeCursor(events, before);
45568
+ const start = Math.max(0, end - limit);
45569
+ const page = events.slice(start, end);
45570
+ const response = {
45571
+ ok: true,
45572
+ session: sessionSummary(data.metadata),
45573
+ currentHead: data.metadata.activeEntryId,
45574
+ activeEntryId: data.metadata.activeEntryId,
45575
+ events: page,
45576
+ hasMoreBefore: start > 0,
45577
+ nextBefore: start > 0 ? String(start) : void 0
45578
+ };
45579
+ if (json) {
45580
+ console.log(JSON.stringify(response, null, 2));
45581
+ return;
45582
+ }
45583
+ console.log(`${response.session.id}: ${response.session.name}`);
45584
+ for (const entry of page) {
45585
+ console.log(`${entry.logicalSeq} ${entry.type}${entry.role ? `:${entry.role}` : ""} ${entry.content ?? ""}`);
45586
+ }
45587
+ }
45588
+ async function renameSession(args) {
45589
+ const json = hasFlag(args, "--json");
45590
+ const cwd = stringFlag(args, "--cwd");
45591
+ const positionals = positionalArgs(args, /* @__PURE__ */ new Set(["--cwd"]));
45592
+ const sessionId = positionals[0];
45593
+ const name = positionals.slice(1).join(" ").trim();
45594
+ if (!sessionId || !name) throw new Error("Usage: pie sessions rename <sessionId> <name> [--json] [--cwd <path>]");
45595
+ const store = new FileSessionStore(getSessionsDir());
45596
+ const data = await store.load(sessionId);
45597
+ if (!data) throw new Error(`Session not found: ${sessionId}`);
45598
+ await store.save(sessionId, data.entries, { ...data.metadata, name, ...cwd ? { cwd } : {}, updatedAt: Date.now() });
45599
+ const updated = await store.getMetadata(sessionId);
45600
+ if (!updated) throw new Error(`Session not found after rename: ${sessionId}`);
45601
+ const response = { ok: true, session: sessionSummary(updated) };
45602
+ if (json) {
45603
+ console.log(JSON.stringify(response, null, 2));
45604
+ return;
45605
+ }
45606
+ console.log(`Renamed ${sessionId} to "${name}".`);
45607
+ }
45608
+ async function rewindSession(args) {
45609
+ const json = hasFlag(args, "--json");
45610
+ const sessionId = positionalArgs(args, /* @__PURE__ */ new Set(["--to"]))[0];
45611
+ const entryId = stringFlag(args, "--to");
45612
+ if (!sessionId || !entryId) throw new Error("Usage: pie sessions rewind <sessionId> --to <entryId> [--json]");
45613
+ const store = new FileSessionStore(getSessionsDir());
45614
+ const data = await store.load(sessionId);
45615
+ if (!data) throw new Error(`Session not found: ${sessionId}`);
45616
+ if (!data.entries.some((entry) => entry.id === entryId)) throw new Error(`Entry not found: ${entryId}`);
45617
+ await store.save(sessionId, data.entries, { ...data.metadata, activeEntryId: entryId, updatedAt: Date.now() });
45618
+ const updated = await store.getMetadata(sessionId);
45619
+ if (!updated) throw new Error(`Session not found after rewind: ${sessionId}`);
45620
+ const response = {
45621
+ ok: true,
45622
+ session: sessionSummary(updated),
45623
+ activeEntryId: entryId,
45624
+ currentHead: entryId
45625
+ };
45626
+ if (json) {
45627
+ console.log(JSON.stringify(response, null, 2));
45628
+ return;
45629
+ }
45630
+ console.log(`Rewound ${sessionId} to ${entryId}.`);
45631
+ }
45632
+ async function forkSession(args) {
45633
+ const json = hasFlag(args, "--json");
45634
+ const sourceSessionId = positionalArgs(args, /* @__PURE__ */ new Set(["--from", "--target", "--name", "--cwd"]))[0];
45635
+ const sourceEntryId = stringFlag(args, "--from");
45636
+ const targetSessionId = stringFlag(args, "--target");
45637
+ const name = stringFlag(args, "--name");
45638
+ const cwd = stringFlag(args, "--cwd");
45639
+ if (!sourceSessionId || !sourceEntryId || !targetSessionId || !name) {
45640
+ throw new Error("Usage: pie sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--json]");
45641
+ }
45642
+ const store = new FileSessionStore(getSessionsDir());
45643
+ const source = await store.load(sourceSessionId);
45644
+ if (!source) throw new Error(`Session not found: ${sourceSessionId}`);
45645
+ if (await store.exists(targetSessionId)) throw new Error(`Target session already exists: ${targetSessionId}`);
45646
+ const pathEntries = pathToEntry(source, sourceEntryId);
45647
+ if (pathEntries.length === 0 || pathEntries[pathEntries.length - 1]?.id !== sourceEntryId) {
45648
+ throw new Error(`Entry not found: ${sourceEntryId}`);
45649
+ }
45650
+ const now = Date.now();
45651
+ const idMap = /* @__PURE__ */ new Map();
45652
+ for (const entry of pathEntries) idMap.set(entry.id, generateEntryId());
45653
+ const forkedEntries = pathEntries.map((entry) => {
45654
+ const nextId = idMap.get(entry.id);
45655
+ if (!nextId) throw new Error(`Failed to map entry: ${entry.id}`);
45656
+ const parentId = entry.parentId ? idMap.get(entry.parentId) ?? null : null;
45657
+ return {
45658
+ ...cloneJson(entry),
45659
+ id: nextId,
45660
+ parentId,
45661
+ timestamp: entry.timestamp
45662
+ };
45663
+ });
45664
+ const activeEntryId = idMap.get(sourceEntryId) ?? null;
45665
+ await store.save(targetSessionId, forkedEntries, {
45666
+ name,
45667
+ createdAt: now,
45668
+ updatedAt: now,
45669
+ activeEntryId,
45670
+ cwd: cwd ?? source.metadata.cwd,
45671
+ sourceSessionId,
45672
+ sourceEntryId,
45673
+ sourceActiveEntryId: source.metadata.activeEntryId ?? void 0,
45674
+ forkBaseEntryId: activeEntryId ?? void 0
45675
+ });
45676
+ const updated = await store.getMetadata(targetSessionId);
45677
+ if (!updated) throw new Error(`Session not found after fork: ${targetSessionId}`);
45678
+ const response = {
45679
+ ok: true,
45680
+ session: sessionSummary(updated),
45681
+ sourceSessionId,
45682
+ sourceEntryId,
45683
+ sourceActiveEntryId: source.metadata.activeEntryId,
45684
+ forkBaseEntryId: activeEntryId,
45685
+ activeEntryId,
45686
+ currentHead: activeEntryId
45687
+ };
45688
+ if (json) {
45689
+ console.log(JSON.stringify(response, null, 2));
45690
+ return;
45691
+ }
45692
+ console.log(`Forked ${sourceSessionId} at ${sourceEntryId} into ${targetSessionId}.`);
45693
+ }
45694
+ function printSessionsUsage() {
45695
+ console.log(`Usage:
45696
+ pie sessions list [--json] [--limit <n>] [--cursor <cursor>] [--cwd <path>]
45697
+ pie sessions read <sessionId> [--json] [--limit <n>] [--before <cursor>]
45698
+ pie sessions rename <sessionId> <name> [--json] [--cwd <path>]
45699
+ pie sessions rewind <sessionId> --to <entryId> [--json]
45700
+ pie sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--json]`);
45701
+ }
45702
+ function hasFlag(args, flag) {
45703
+ return args.includes(flag);
45704
+ }
45705
+ function stringFlag(args, flag) {
45706
+ const index = args.indexOf(flag);
45707
+ if (index < 0) return void 0;
45708
+ const value = args[index + 1];
45709
+ return value && !value.startsWith("-") ? value : void 0;
45710
+ }
45711
+ function numericFlag(args, flag, fallback) {
45712
+ const value = stringFlag(args, flag);
45713
+ if (!value) return fallback;
45714
+ const parsed = Number(value);
45715
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
45716
+ }
45717
+ function positionalArgs(args, valueFlags) {
45718
+ const result = [];
45719
+ for (let index = 0; index < args.length; index += 1) {
45720
+ const arg = args[index];
45721
+ if (arg.startsWith("--")) {
45722
+ if (valueFlags.has(arg)) index += 1;
45723
+ continue;
45724
+ }
45725
+ result.push(arg);
45726
+ }
45727
+ return result;
45728
+ }
45729
+ function sessionSummary(metadata) {
45730
+ return {
45731
+ id: metadata.id,
45732
+ name: metadata.name,
45733
+ createdAt: metadata.createdAt,
45734
+ updatedAt: metadata.updatedAt,
45735
+ cwd: typeof metadata.cwd === "string" ? metadata.cwd : void 0,
45736
+ entryCount: metadata.entryCount,
45737
+ messageCount: metadata.messageCount,
45738
+ activeEntryId: metadata.activeEntryId,
45739
+ rootEntryId: metadata.rootEntryId,
45740
+ sourceSessionId: typeof metadata.sourceSessionId === "string" ? metadata.sourceSessionId : void 0,
45741
+ sourceEntryId: typeof metadata.sourceEntryId === "string" ? metadata.sourceEntryId : void 0,
45742
+ sourceActiveEntryId: typeof metadata.sourceActiveEntryId === "string" ? metadata.sourceActiveEntryId : void 0,
45743
+ forkBaseEntryId: typeof metadata.forkBaseEntryId === "string" ? metadata.forkBaseEntryId : void 0
45744
+ };
45745
+ }
45746
+ function cwdMatches(sessionCwd, requestedCwd) {
45747
+ if (!sessionCwd) return false;
45748
+ if (sessionCwd === requestedCwd) return true;
45749
+ return realpathOrInput(sessionCwd) === realpathOrInput(requestedCwd);
45750
+ }
45751
+ function realpathOrInput(value) {
45752
+ try {
45753
+ return fs6.realpathSync.native(value);
45754
+ } catch {
45755
+ return value;
45756
+ }
45757
+ }
45758
+ function activeTranscriptEvents(entries) {
45759
+ return entries.map((entry, index) => {
45760
+ const role = isRecord2(entry.message) && typeof entry.message.role === "string" ? entry.message.role : void 0;
45761
+ return {
45762
+ logicalSeq: index + 1,
45763
+ checkpointId: entry.id,
45764
+ entryId: entry.id,
45765
+ id: entry.id,
45766
+ type: entry.type,
45767
+ timestamp: entry.timestamp,
45768
+ occurredAt: entry.timestamp,
45769
+ role,
45770
+ content: textFromMessage(entry.message),
45771
+ message: entry.message ? cloneJson(entry.message) : void 0
45772
+ };
45773
+ });
45774
+ }
45775
+ function activePathEntries(data) {
45776
+ const activeEntryId = data.metadata.activeEntryId;
45777
+ if (!activeEntryId) return [];
45778
+ return pathToEntry(data, activeEntryId);
45779
+ }
45780
+ function pathToEntry(data, entryId) {
45781
+ const byId = new Map(data.entries.map((entry) => [entry.id, entry]));
45782
+ const path27 = [];
45783
+ let current = entryId;
45784
+ while (current) {
45785
+ const entry = byId.get(current);
45786
+ if (!entry) return [];
45787
+ path27.unshift(entry);
45788
+ current = entry.parentId;
45789
+ }
45790
+ return path27;
45791
+ }
45792
+ function resolveBeforeCursor(events, cursor) {
45793
+ if (!cursor) return events.length;
45794
+ const numeric = Number(cursor);
45795
+ if (Number.isInteger(numeric) && numeric >= 0) {
45796
+ return Math.max(0, Math.min(events.length, numeric));
45797
+ }
45798
+ const index = events.findIndex((event) => event.entryId === cursor || event.checkpointId === cursor);
45799
+ return index >= 0 ? index : events.length;
45800
+ }
45801
+ function cloneJson(value) {
45802
+ return JSON.parse(JSON.stringify(value));
45803
+ }
45804
+ function listCursorQueryKey(input) {
45805
+ return JSON.stringify({ cwd: input.cwd ? realpathOrInput(input.cwd) : "" });
45806
+ }
45807
+ function encodeListCursor(state) {
45808
+ return `list:${Buffer.from(JSON.stringify(state), "utf8").toString("base64url")}`;
45809
+ }
45810
+ function decodeListCursor(cursor) {
45811
+ if (!cursor?.startsWith("list:")) return { v: 2 };
45812
+ try {
45813
+ const parsed = JSON.parse(Buffer.from(cursor.slice("list:".length), "base64url").toString("utf8"));
45814
+ if (!isRecord2(parsed) || parsed.v !== 2) return { v: 2 };
45815
+ const after = isRecord2(parsed.after) && typeof parsed.after.id === "string" && typeof parsed.after.updatedAt === "number" && Number.isFinite(parsed.after.updatedAt) ? { id: parsed.after.id, updatedAt: parsed.after.updatedAt } : void 0;
45816
+ return {
45817
+ v: 2,
45818
+ q: typeof parsed.q === "string" ? parsed.q : void 0,
45819
+ ...after ? { after } : {}
45820
+ };
45821
+ } catch {
45822
+ return { v: 2 };
45823
+ }
45824
+ }
45825
+ function textFromMessage(message) {
45826
+ if (!isRecord2(message)) return void 0;
45827
+ const content = message.content;
45828
+ if (typeof content === "string") return content;
45829
+ if (!Array.isArray(content)) return void 0;
45830
+ const text = content.map((block) => isRecord2(block) && block.type === "text" && typeof block.text === "string" ? block.text : "").filter(Boolean).join("\n").trim();
45831
+ return text || void 0;
45832
+ }
45833
+ function isRecord2(value) {
45834
+ return !!value && typeof value === "object" && !Array.isArray(value);
45835
+ }
45836
+
45484
45837
  // ../../packages/tui/src/fuzzy.ts
45485
45838
  function fuzzyMatch(query, text) {
45486
45839
  const queryLower = query.toLowerCase();
@@ -47031,7 +47384,7 @@ var KillRing = class {
47031
47384
  };
47032
47385
 
47033
47386
  // ../../packages/tui/src/tui.ts
47034
- import * as fs6 from "node:fs";
47387
+ import * as fs7 from "node:fs";
47035
47388
  import * as os2 from "node:os";
47036
47389
  import * as path5 from "node:path";
47037
47390
 
@@ -47710,10 +48063,10 @@ var TUI = class extends Container {
47710
48063
  const logRedraw = (reason) => {
47711
48064
  if (!debugRedraw) return;
47712
48065
  const logPath = path5.join(os2.homedir(), ".pie", "logs", "pie-cli.log");
47713
- fs6.mkdirSync(path5.dirname(logPath), { recursive: true });
48066
+ fs7.mkdirSync(path5.dirname(logPath), { recursive: true });
47714
48067
  const msg = `[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] [ui] fullRender: ${reason} (prev=${this.previousLines.length}, new=${newLines.length}, height=${height})
47715
48068
  `;
47716
- fs6.appendFileSync(logPath, msg);
48069
+ fs7.appendFileSync(logPath, msg);
47717
48070
  };
47718
48071
  if (this.previousLines.length === 0 && !widthChanged) {
47719
48072
  logRedraw("first render");
@@ -47816,8 +48169,8 @@ var TUI = class extends Container {
47816
48169
  ...newLines.map((l, idx) => `[${idx}] (w=${visibleWidth(l)}) ${l}`),
47817
48170
  ""
47818
48171
  ].join("\n");
47819
- fs6.mkdirSync(path5.dirname(crashLogPath), { recursive: true });
47820
- fs6.writeFileSync(crashLogPath, crashData);
48172
+ fs7.mkdirSync(path5.dirname(crashLogPath), { recursive: true });
48173
+ fs7.writeFileSync(crashLogPath, crashData);
47821
48174
  this.stop();
47822
48175
  const errorMsg = [
47823
48176
  `Rendered line ${i} exceeds terminal width (${visibleWidth(line)} > ${width}).`,
@@ -47847,7 +48200,7 @@ var TUI = class extends Container {
47847
48200
  buffer += "\x1B[?2026l";
47848
48201
  if (process.env.PIE_TUI_DEBUG === "1") {
47849
48202
  const debugDir = "/tmp/tui";
47850
- fs6.mkdirSync(debugDir, { recursive: true });
48203
+ fs7.mkdirSync(debugDir, { recursive: true });
47851
48204
  const debugPath = path5.join(debugDir, `render-${Date.now()}-${Math.random().toString(36).slice(2)}.log`);
47852
48205
  const debugData = [
47853
48206
  `firstChanged: ${firstChanged}`,
@@ -47871,7 +48224,7 @@ var TUI = class extends Container {
47871
48224
  "=== buffer ===",
47872
48225
  JSON.stringify(buffer)
47873
48226
  ].join("\n");
47874
- fs6.writeFileSync(debugPath, debugData);
48227
+ fs7.writeFileSync(debugPath, debugData);
47875
48228
  }
47876
48229
  this.terminal.write(buffer);
47877
48230
  this.cursorRow = Math.max(0, newLines.length - 1);
@@ -52046,7 +52399,7 @@ var StdinBuffer = class extends EventEmitter {
52046
52399
  };
52047
52400
 
52048
52401
  // ../../packages/tui/src/terminal.ts
52049
- import * as fs7 from "node:fs";
52402
+ import * as fs8 from "node:fs";
52050
52403
  import koffi from "koffi";
52051
52404
  var ProcessTerminal = class {
52052
52405
  wasRaw = false;
@@ -52207,7 +52560,7 @@ var ProcessTerminal = class {
52207
52560
  process.stdout.write(data);
52208
52561
  if (this.writeLogPath) {
52209
52562
  try {
52210
- fs7.appendFileSync(this.writeLogPath, data, { encoding: "utf8" });
52563
+ fs8.appendFileSync(this.writeLogPath, data, { encoding: "utf8" });
52211
52564
  } catch {
52212
52565
  }
52213
52566
  }
@@ -52379,7 +52732,7 @@ var KeybindingsManager = class _KeybindingsManager {
52379
52732
  };
52380
52733
 
52381
52734
  // src/project-knowledge.ts
52382
- import fs8 from "node:fs";
52735
+ import fs9 from "node:fs";
52383
52736
  import path6 from "node:path";
52384
52737
  function collectAncestorAgentsFiles(cwd) {
52385
52738
  const resolvedCwd = path6.resolve(cwd || process.cwd());
@@ -52399,13 +52752,13 @@ function collectAncestorAgentsFiles(cwd) {
52399
52752
  }
52400
52753
  const files = [];
52401
52754
  for (const candidate of candidates) {
52402
- if (!fs8.existsSync(candidate)) {
52755
+ if (!fs9.existsSync(candidate)) {
52403
52756
  continue;
52404
52757
  }
52405
52758
  try {
52406
52759
  files.push({
52407
52760
  path: path6.relative(resolvedCwd, candidate) || AGENTS_CONTEXT_FILE_NAME,
52408
- content: fs8.readFileSync(candidate, "utf-8")
52761
+ content: fs9.readFileSync(candidate, "utf-8")
52409
52762
  });
52410
52763
  } catch {
52411
52764
  }
@@ -52443,7 +52796,7 @@ function buildCliFileAccessOptions(params) {
52443
52796
  }
52444
52797
 
52445
52798
  // src/theme/theme.ts
52446
- import * as fs9 from "node:fs";
52799
+ import * as fs10 from "node:fs";
52447
52800
  import * as path8 from "node:path";
52448
52801
 
52449
52802
  // ../../node_modules/@sinclair/typebox/build/esm/compiler/compiler.mjs
@@ -53334,8 +53687,8 @@ function getBuiltinThemes() {
53334
53687
  const darkPath = path8.join(themesDir, "dark.json");
53335
53688
  const lightPath = path8.join(themesDir, "light.json");
53336
53689
  BUILTIN_THEMES = {
53337
- dark: JSON.parse(fs9.readFileSync(darkPath, "utf-8")),
53338
- light: JSON.parse(fs9.readFileSync(lightPath, "utf-8"))
53690
+ dark: JSON.parse(fs10.readFileSync(darkPath, "utf-8")),
53691
+ light: JSON.parse(fs10.readFileSync(lightPath, "utf-8"))
53339
53692
  };
53340
53693
  }
53341
53694
  return BUILTIN_THEMES;
@@ -53343,8 +53696,8 @@ function getBuiltinThemes() {
53343
53696
  function getAvailableThemes() {
53344
53697
  const themes = new Set(Object.keys(getBuiltinThemes()));
53345
53698
  const customThemesDir = getCustomThemesDir();
53346
- if (fs9.existsSync(customThemesDir)) {
53347
- const files = fs9.readdirSync(customThemesDir);
53699
+ if (fs10.existsSync(customThemesDir)) {
53700
+ const files = fs10.readdirSync(customThemesDir);
53348
53701
  for (const file of files) {
53349
53702
  if (file.endsWith(".json")) {
53350
53703
  themes.add(file.slice(0, -5));
@@ -53405,7 +53758,7 @@ function loadThemeJson(name) {
53405
53758
  }
53406
53759
  const registeredTheme = registeredThemes.get(name);
53407
53760
  if (registeredTheme?.sourcePath) {
53408
- const content2 = fs9.readFileSync(registeredTheme.sourcePath, "utf-8");
53761
+ const content2 = fs10.readFileSync(registeredTheme.sourcePath, "utf-8");
53409
53762
  return parseThemeJsonContent(registeredTheme.sourcePath, content2);
53410
53763
  }
53411
53764
  if (registeredTheme) {
@@ -53413,10 +53766,10 @@ function loadThemeJson(name) {
53413
53766
  }
53414
53767
  const customThemesDir = getCustomThemesDir();
53415
53768
  const themePath = path8.join(customThemesDir, `${name}.json`);
53416
- if (!fs9.existsSync(themePath)) {
53769
+ if (!fs10.existsSync(themePath)) {
53417
53770
  throw new Error(`Theme not found: ${name}`);
53418
53771
  }
53419
- const content = fs9.readFileSync(themePath, "utf-8");
53772
+ const content = fs10.readFileSync(themePath, "utf-8");
53420
53773
  return parseThemeJsonContent(name, content);
53421
53774
  }
53422
53775
  function createTheme(themeJson, mode, sourcePath) {
@@ -53530,11 +53883,11 @@ function startThemeWatcher() {
53530
53883
  }
53531
53884
  const customThemesDir = getCustomThemesDir();
53532
53885
  const themeFile = path8.join(customThemesDir, `${currentThemeName}.json`);
53533
- if (!fs9.existsSync(themeFile)) {
53886
+ if (!fs10.existsSync(themeFile)) {
53534
53887
  return;
53535
53888
  }
53536
53889
  try {
53537
- themeWatcher = fs9.watch(themeFile, (eventType) => {
53890
+ themeWatcher = fs10.watch(themeFile, (eventType) => {
53538
53891
  if (eventType === "change") {
53539
53892
  setTimeout(() => {
53540
53893
  try {
@@ -53547,7 +53900,7 @@ function startThemeWatcher() {
53547
53900
  }, 100);
53548
53901
  } else if (eventType === "rename") {
53549
53902
  setTimeout(() => {
53550
- if (!fs9.existsSync(themeFile)) {
53903
+ if (!fs10.existsSync(themeFile)) {
53551
53904
  currentThemeName = "dark";
53552
53905
  setGlobalTheme(loadTheme("dark"));
53553
53906
  if (themeWatcher) {
@@ -53718,7 +54071,7 @@ function getEditorTheme() {
53718
54071
  }
53719
54072
 
53720
54073
  // src/skills/loader.ts
53721
- import * as fs10 from "fs";
54074
+ import * as fs11 from "fs";
53722
54075
  import * as path9 from "path";
53723
54076
  function parseSkillDescription(content) {
53724
54077
  const frontmatterMatch = content.match(/^---\n[\s\S]*?description:\s*["']?(.+?)["']?(?:\n|$)/m);
@@ -53737,18 +54090,18 @@ function parseSkillDescription(content) {
53737
54090
  function loadSkillsFromDir(dir, source) {
53738
54091
  const skills = [];
53739
54092
  const diagnostics = [];
53740
- if (!fs10.existsSync(dir)) {
54093
+ if (!fs11.existsSync(dir)) {
53741
54094
  return { skills, diagnostics };
53742
54095
  }
53743
- const entries = fs10.readdirSync(dir, { withFileTypes: true });
54096
+ const entries = fs11.readdirSync(dir, { withFileTypes: true });
53744
54097
  for (const entry of entries) {
53745
54098
  if (entry.name.startsWith(".")) continue;
53746
54099
  const fullPath = path9.join(dir, entry.name);
53747
54100
  if (entry.isDirectory()) {
53748
54101
  const skillMdPath = path9.join(fullPath, "SKILL.md");
53749
- if (fs10.existsSync(skillMdPath)) {
54102
+ if (fs11.existsSync(skillMdPath)) {
53750
54103
  try {
53751
- const content = fs10.readFileSync(skillMdPath, "utf-8");
54104
+ const content = fs11.readFileSync(skillMdPath, "utf-8");
53752
54105
  const description = parseSkillDescription(content);
53753
54106
  skills.push({
53754
54107
  name: entry.name,
@@ -53769,7 +54122,7 @@ function loadSkillsFromDir(dir, source) {
53769
54122
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
53770
54123
  const name = entry.name.slice(0, -3);
53771
54124
  try {
53772
- const content = fs10.readFileSync(fullPath, "utf-8");
54125
+ const content = fs11.readFileSync(fullPath, "utf-8");
53773
54126
  const description = parseSkillDescription(content);
53774
54127
  skills.push({
53775
54128
  name,
@@ -53966,7 +54319,7 @@ function validateSkillName(name) {
53966
54319
 
53967
54320
  // src/capabilities/read-file-understanding.ts
53968
54321
  import * as path18 from "node:path";
53969
- import * as fs18 from "node:fs/promises";
54322
+ import * as fs19 from "node:fs/promises";
53970
54323
 
53971
54324
  // src/core/provider-capabilities.ts
53972
54325
  var PLATFORM_DISPLAY_NAMES = {
@@ -53992,7 +54345,7 @@ function getProviderDisplayName(platform2) {
53992
54345
  }
53993
54346
 
53994
54347
  // src/files/adapters/kimi-adapter.ts
53995
- import * as fs11 from "node:fs";
54348
+ import * as fs12 from "node:fs";
53996
54349
  import * as path10 from "node:path";
53997
54350
 
53998
54351
  // src/files/errors.ts
@@ -54133,14 +54486,14 @@ var KimiFileAdapter = class {
54133
54486
  const fileName = options.sourceName || path10.basename(filePath);
54134
54487
  const mimeType = options.mimeType || this.guessMimeType(fileName);
54135
54488
  const purpose = this.detectPurpose(filePath, options.purpose, mimeType);
54136
- const stats = fs11.statSync(filePath);
54489
+ const stats = fs12.statSync(filePath);
54137
54490
  if (stats.size > this.capabilities.maxFileSize) {
54138
54491
  throw new FileManagerError(
54139
54492
  "FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
54140
54493
  `File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds Kimi limit of 100MB`
54141
54494
  );
54142
54495
  }
54143
- const fileBuffer = fs11.readFileSync(filePath);
54496
+ const fileBuffer = fs12.readFileSync(filePath);
54144
54497
  const file = new File([fileBuffer], fileName, { type: mimeType });
54145
54498
  const formData = new FormData();
54146
54499
  formData.append("file", file);
@@ -54354,7 +54707,7 @@ var KimiFileAdapter = class {
54354
54707
  };
54355
54708
 
54356
54709
  // src/files/adapters/gemini-adapter.ts
54357
- import * as fs12 from "node:fs";
54710
+ import * as fs13 from "node:fs";
54358
54711
  import * as path11 from "node:path";
54359
54712
  import { Readable } from "node:stream";
54360
54713
  var GeminiFileAdapter = class {
@@ -54412,7 +54765,7 @@ var GeminiFileAdapter = class {
54412
54765
  // Upload
54413
54766
  // ============================================================================
54414
54767
  async upload(filePath, options = {}) {
54415
- const stats = fs12.statSync(filePath);
54768
+ const stats = fs13.statSync(filePath);
54416
54769
  if (stats.size > this.capabilities.maxFileSize) {
54417
54770
  throw new FileManagerError(
54418
54771
  "FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
@@ -54451,7 +54804,7 @@ var GeminiFileAdapter = class {
54451
54804
  "No upload URL received"
54452
54805
  );
54453
54806
  }
54454
- const fileStream = Readable.toWeb(fs12.createReadStream(filePath));
54807
+ const fileStream = Readable.toWeb(fs13.createReadStream(filePath));
54455
54808
  const uploadResponse = await fetch(uploadUrl, {
54456
54809
  method: "POST",
54457
54810
  headers: {
@@ -54655,7 +55008,7 @@ var GeminiFileAdapter = class {
54655
55008
  };
54656
55009
 
54657
55010
  // src/files/adapters/openai-compatible-files-adapter.ts
54658
- import * as fs13 from "node:fs";
55011
+ import * as fs14 from "node:fs";
54659
55012
  import * as path12 from "node:path";
54660
55013
  var OpenAICompatibleFilesAdapter = class {
54661
55014
  constructor(apiKey, baseUrl, extraHeaders = {}) {
@@ -54684,14 +55037,14 @@ var OpenAICompatibleFilesAdapter = class {
54684
55037
  async upload(filePath, options = {}) {
54685
55038
  const fileName = options.sourceName || path12.basename(filePath);
54686
55039
  const mimeType = options.mimeType || guessMimeType(fileName);
54687
- const stats = fs13.statSync(filePath);
55040
+ const stats = fs14.statSync(filePath);
54688
55041
  if (stats.size > this.capabilities.maxFileSize) {
54689
55042
  throw new FileManagerError(
54690
55043
  "FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
54691
55044
  `File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds OpenAI-compatible Files limit of ${this.capabilities.maxFileSize / 1024 / 1024}MB`
54692
55045
  );
54693
55046
  }
54694
- const file = new File([fs13.readFileSync(filePath)], fileName, { type: mimeType });
55047
+ const file = new File([fs14.readFileSync(filePath)], fileName, { type: mimeType });
54695
55048
  const formData = new FormData();
54696
55049
  formData.append("file", file);
54697
55050
  formData.append("purpose", options.purpose && options.purpose !== "auto" ? options.purpose : "file-extract");
@@ -54824,12 +55177,12 @@ function guessMimeType(filename) {
54824
55177
  }
54825
55178
 
54826
55179
  // src/files/file-manager.ts
54827
- import * as fs17 from "node:fs";
55180
+ import * as fs18 from "node:fs";
54828
55181
  import * as path17 from "node:path";
54829
55182
  import * as crypto2 from "node:crypto";
54830
55183
 
54831
55184
  // src/files/file-cache.ts
54832
- import * as fs14 from "node:fs";
55185
+ import * as fs15 from "node:fs";
54833
55186
  import * as path14 from "node:path";
54834
55187
  import * as crypto from "node:crypto";
54835
55188
 
@@ -54990,22 +55343,22 @@ var FileCache = class _FileCache {
54990
55343
  // Directory Management
54991
55344
  // ============================================================================
54992
55345
  ensureDirectories() {
54993
- if (!fs14.existsSync(this.baseDir)) {
54994
- fs14.mkdirSync(this.baseDir, { recursive: true });
55346
+ if (!fs15.existsSync(this.baseDir)) {
55347
+ fs15.mkdirSync(this.baseDir, { recursive: true });
54995
55348
  }
54996
- if (!fs14.existsSync(this.dataDir)) {
54997
- fs14.mkdirSync(this.dataDir, { recursive: true });
55349
+ if (!fs15.existsSync(this.dataDir)) {
55350
+ fs15.mkdirSync(this.dataDir, { recursive: true });
54998
55351
  }
54999
55352
  }
55000
55353
  // ============================================================================
55001
55354
  // Index Management
55002
55355
  // ============================================================================
55003
55356
  loadIndex() {
55004
- if (!fs14.existsSync(this.indexPath)) {
55357
+ if (!fs15.existsSync(this.indexPath)) {
55005
55358
  return { version: CACHE_VERSION, files: {}, pathHints: {} };
55006
55359
  }
55007
55360
  try {
55008
- const data = JSON.parse(fs14.readFileSync(this.indexPath, "utf-8"));
55361
+ const data = JSON.parse(fs15.readFileSync(this.indexPath, "utf-8"));
55009
55362
  if (data.version !== CACHE_VERSION) {
55010
55363
  cacheLogger.warn(`Index version mismatch: ${data.version} vs ${CACHE_VERSION}`);
55011
55364
  }
@@ -55021,7 +55374,7 @@ var FileCache = class _FileCache {
55021
55374
  }
55022
55375
  saveIndex() {
55023
55376
  try {
55024
- fs14.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
55377
+ fs15.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
55025
55378
  } catch (err) {
55026
55379
  cacheLogger.error(" Failed to save index:", err);
55027
55380
  throw err;
@@ -55033,7 +55386,7 @@ var FileCache = class _FileCache {
55033
55386
  async computeHash(filePath) {
55034
55387
  return new Promise((resolve4, reject) => {
55035
55388
  const hash = crypto.createHash("sha256");
55036
- const stream = fs14.createReadStream(filePath);
55389
+ const stream = fs15.createReadStream(filePath);
55037
55390
  stream.on("data", (chunk) => hash.update(chunk));
55038
55391
  stream.on("end", () => resolve4(hash.digest("hex")));
55039
55392
  stream.on("error", reject);
@@ -55048,8 +55401,8 @@ var FileCache = class _FileCache {
55048
55401
  getStoragePath(hash) {
55049
55402
  const subdir = hash.slice(0, 2);
55050
55403
  const fullDir = path14.join(this.dataDir, subdir);
55051
- if (!fs14.existsSync(fullDir)) {
55052
- fs14.mkdirSync(fullDir, { recursive: true });
55404
+ if (!fs15.existsSync(fullDir)) {
55405
+ fs15.mkdirSync(fullDir, { recursive: true });
55053
55406
  }
55054
55407
  return path14.join(fullDir, hash);
55055
55408
  }
@@ -55061,11 +55414,11 @@ var FileCache = class _FileCache {
55061
55414
  const hash = await this.computeHash(sourcePath);
55062
55415
  const storagePath = this.getStoragePath(hash);
55063
55416
  this.rememberPathHint(sourcePath, hash, name);
55064
- if (fs14.existsSync(storagePath)) {
55417
+ if (fs15.existsSync(storagePath)) {
55065
55418
  return { hash, localPath: storagePath };
55066
55419
  }
55067
- fs14.copyFileSync(sourcePath, storagePath);
55068
- const stat2 = fs14.statSync(storagePath);
55420
+ fs15.copyFileSync(sourcePath, storagePath);
55421
+ const stat2 = fs15.statSync(storagePath);
55069
55422
  this.index.files[hash] = {
55070
55423
  hash,
55071
55424
  name,
@@ -55082,10 +55435,10 @@ var FileCache = class _FileCache {
55082
55435
  async storeBuffer(data, name, mimeType) {
55083
55436
  const hash = this.computeHashSync(data);
55084
55437
  const storagePath = this.getStoragePath(hash);
55085
- if (fs14.existsSync(storagePath)) {
55438
+ if (fs15.existsSync(storagePath)) {
55086
55439
  return { hash, localPath: storagePath };
55087
55440
  }
55088
- fs14.writeFileSync(storagePath, data);
55441
+ fs15.writeFileSync(storagePath, data);
55089
55442
  this.index.files[hash] = {
55090
55443
  hash,
55091
55444
  name,
@@ -55157,7 +55510,7 @@ var FileCache = class _FileCache {
55157
55510
  getPathHint(filePath) {
55158
55511
  try {
55159
55512
  const resolvedPath = this.getResolvedHintPath(filePath);
55160
- const stat2 = fs14.statSync(resolvedPath);
55513
+ const stat2 = fs15.statSync(resolvedPath);
55161
55514
  if (!stat2.isFile()) return void 0;
55162
55515
  const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
55163
55516
  const key = this.getPathHintKey(resolvedPath);
@@ -55187,7 +55540,7 @@ var FileCache = class _FileCache {
55187
55540
  rememberPathHint(filePath, hash, name) {
55188
55541
  try {
55189
55542
  const resolvedPath = this.getResolvedHintPath(filePath);
55190
- const stat2 = fs14.statSync(resolvedPath);
55543
+ const stat2 = fs15.statSync(resolvedPath);
55191
55544
  if (!stat2.isFile()) return;
55192
55545
  const entry = this.index.files[hash];
55193
55546
  const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
@@ -55246,8 +55599,8 @@ var FileCache = class _FileCache {
55246
55599
  entry = entry || this.index.files[hash];
55247
55600
  if (!entry) return;
55248
55601
  const localPath = path14.join(this.dataDir, entry.localPath);
55249
- if (fs14.existsSync(localPath)) {
55250
- fs14.unlinkSync(localPath);
55602
+ if (fs15.existsSync(localPath)) {
55603
+ fs15.unlinkSync(localPath);
55251
55604
  }
55252
55605
  delete this.index.files[hash];
55253
55606
  if (this.index.pathHints) {
@@ -55262,8 +55615,8 @@ var FileCache = class _FileCache {
55262
55615
  clear() {
55263
55616
  for (const entry of Object.values(this.index.files)) {
55264
55617
  const localPath = path14.join(this.dataDir, entry.localPath);
55265
- if (fs14.existsSync(localPath)) {
55266
- fs14.unlinkSync(localPath);
55618
+ if (fs15.existsSync(localPath)) {
55619
+ fs15.unlinkSync(localPath);
55267
55620
  }
55268
55621
  }
55269
55622
  this.index = { version: CACHE_VERSION, files: {}, pathHints: {} };
@@ -55351,7 +55704,7 @@ var FileCache = class _FileCache {
55351
55704
  getResolvedHintPath(filePath) {
55352
55705
  const resolvedPath = resolvePath(filePath);
55353
55706
  try {
55354
- return fs14.realpathSync.native ? fs14.realpathSync.native(resolvedPath) : fs14.realpathSync(resolvedPath);
55707
+ return fs15.realpathSync.native ? fs15.realpathSync.native(resolvedPath) : fs15.realpathSync(resolvedPath);
55355
55708
  } catch {
55356
55709
  return resolvedPath;
55357
55710
  }
@@ -55359,7 +55712,7 @@ var FileCache = class _FileCache {
55359
55712
  };
55360
55713
 
55361
55714
  // src/files/session-file-manager.ts
55362
- import * as fs15 from "node:fs";
55715
+ import * as fs16 from "node:fs";
55363
55716
  import * as path15 from "node:path";
55364
55717
  var INITIAL_REFRESH_BACKOFF_MS = 6e4;
55365
55718
  var MAX_REFRESH_BACKOFF_MS = 60 * 60 * 1e3;
@@ -55384,15 +55737,15 @@ var SessionFileManager = class {
55384
55737
  // Directory Management
55385
55738
  // ============================================================================
55386
55739
  ensureDirectories() {
55387
- if (!fs15.existsSync(this.sessionsDir)) {
55388
- fs15.mkdirSync(this.sessionsDir, { recursive: true });
55740
+ if (!fs16.existsSync(this.sessionsDir)) {
55741
+ fs16.mkdirSync(this.sessionsDir, { recursive: true });
55389
55742
  }
55390
55743
  }
55391
55744
  // ============================================================================
55392
55745
  // State Management
55393
55746
  // ============================================================================
55394
55747
  loadState() {
55395
- if (!fs15.existsSync(this.statePath)) {
55748
+ if (!fs16.existsSync(this.statePath)) {
55396
55749
  return {
55397
55750
  sessionId: this.sessionId,
55398
55751
  lastSyncedAt: 0,
@@ -55400,7 +55753,7 @@ var SessionFileManager = class {
55400
55753
  };
55401
55754
  }
55402
55755
  try {
55403
- return JSON.parse(fs15.readFileSync(this.statePath, "utf-8"));
55756
+ return JSON.parse(fs16.readFileSync(this.statePath, "utf-8"));
55404
55757
  } catch (err) {
55405
55758
  sessionLogger.error(" Failed to load state:", err);
55406
55759
  return {
@@ -55413,12 +55766,12 @@ var SessionFileManager = class {
55413
55766
  saveState() {
55414
55767
  try {
55415
55768
  if (Object.keys(this.state.files).length === 0) {
55416
- if (fs15.existsSync(this.statePath)) {
55417
- fs15.unlinkSync(this.statePath);
55769
+ if (fs16.existsSync(this.statePath)) {
55770
+ fs16.unlinkSync(this.statePath);
55418
55771
  }
55419
55772
  return;
55420
55773
  }
55421
- fs15.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
55774
+ fs16.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
55422
55775
  } catch (err) {
55423
55776
  sessionLogger.error(" Failed to save state:", err);
55424
55777
  }
@@ -55564,7 +55917,7 @@ var SessionFileManager = class {
55564
55917
  return { success: false, coolingDown: true };
55565
55918
  }
55566
55919
  const localPath = this.fileCache.getLocalPath(entry.hash);
55567
- if (!localPath || !fs15.existsSync(localPath)) {
55920
+ if (!localPath || !fs16.existsSync(localPath)) {
55568
55921
  sessionLogger.warn(`Local file not found for ${fileId}`);
55569
55922
  entry.status = "expired";
55570
55923
  entry.error = "Local file missing";
@@ -55715,15 +56068,15 @@ var SessionFileManager = class {
55715
56068
  // Static Utilities
55716
56069
  // ============================================================================
55717
56070
  static cleanupOldSessions(sessionsDir, maxAge = 30 * 24 * 60 * 60 * 1e3) {
55718
- if (!fs15.existsSync(sessionsDir)) return;
56071
+ if (!fs16.existsSync(sessionsDir)) return;
55719
56072
  const now = Date.now();
55720
- const files = fs15.readdirSync(sessionsDir);
56073
+ const files = fs16.readdirSync(sessionsDir);
55721
56074
  for (const file of files) {
55722
56075
  if (!file.endsWith(".json")) continue;
55723
56076
  const filePath = path15.join(sessionsDir, file);
55724
- const stat2 = fs15.statSync(filePath);
56077
+ const stat2 = fs16.statSync(filePath);
55725
56078
  if (now - stat2.mtime.getTime() > maxAge) {
55726
- fs15.unlinkSync(filePath);
56079
+ fs16.unlinkSync(filePath);
55727
56080
  sessionLogger.debug(`Cleaned up old session: ${file}`);
55728
56081
  }
55729
56082
  }
@@ -55731,7 +56084,7 @@ var SessionFileManager = class {
55731
56084
  };
55732
56085
 
55733
56086
  // src/files/ffmpeg-processor.ts
55734
- import * as fs16 from "node:fs";
56087
+ import * as fs17 from "node:fs";
55735
56088
  import * as path16 from "node:path";
55736
56089
  import { spawn } from "node:child_process";
55737
56090
  var FFmpegProcessor = class {
@@ -55867,7 +56220,7 @@ var FFmpegProcessor = class {
55867
56220
  onProgress?.(percent);
55868
56221
  }
55869
56222
  });
55870
- const outputStat = fs16.statSync(outputPath);
56223
+ const outputStat = fs17.statSync(outputPath);
55871
56224
  return {
55872
56225
  type: "video",
55873
56226
  output: outputPath,
@@ -55899,7 +56252,7 @@ var FFmpegProcessor = class {
55899
56252
  async extractKeyframes(inputPath, outputDir, info, opts, onProgress) {
55900
56253
  const interval = Math.floor(info.duration / opts.keyframeCount);
55901
56254
  const framesDir = path16.join(outputDir, `keyframes_${Date.now()}`);
55902
- fs16.mkdirSync(framesDir, { recursive: true });
56255
+ fs17.mkdirSync(framesDir, { recursive: true });
55903
56256
  const outputPattern = path16.join(framesDir, "frame_%03d.jpg");
55904
56257
  const args = [
55905
56258
  "-i",
@@ -55918,10 +56271,10 @@ var FFmpegProcessor = class {
55918
56271
  onProgress?.(percent);
55919
56272
  }
55920
56273
  });
55921
- let frames = fs16.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
56274
+ let frames = fs17.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
55922
56275
  if (frames.length < opts.keyframeCount / 2) {
55923
- fs16.rmSync(framesDir, { recursive: true, force: true });
55924
- fs16.mkdirSync(framesDir, { recursive: true });
56276
+ fs17.rmSync(framesDir, { recursive: true, force: true });
56277
+ fs17.mkdirSync(framesDir, { recursive: true });
55925
56278
  const uniformArgs = [
55926
56279
  "-i",
55927
56280
  inputPath,
@@ -55937,10 +56290,10 @@ var FFmpegProcessor = class {
55937
56290
  onProgress?.(percent);
55938
56291
  }
55939
56292
  });
55940
- frames = fs16.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
56293
+ frames = fs17.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
55941
56294
  }
55942
56295
  const totalOutputSize = frames.reduce(
55943
- (sum, f) => sum + fs16.statSync(f).size,
56296
+ (sum, f) => sum + fs17.statSync(f).size,
55944
56297
  0
55945
56298
  );
55946
56299
  return {
@@ -56160,8 +56513,8 @@ var FileManager = class {
56160
56513
  directoryListingCache = /* @__PURE__ */ new Map();
56161
56514
  authFingerprint;
56162
56515
  ensureDirectories() {
56163
- if (!fs17.existsSync(this.tempDir)) {
56164
- fs17.mkdirSync(this.tempDir, { recursive: true });
56516
+ if (!fs18.existsSync(this.tempDir)) {
56517
+ fs18.mkdirSync(this.tempDir, { recursive: true });
56165
56518
  }
56166
56519
  }
56167
56520
  // ============================================================================
@@ -56192,7 +56545,7 @@ var FileManager = class {
56192
56545
  async stageLocal(filePath, options = {}) {
56193
56546
  const resolvedPath = resolvePath(filePath);
56194
56547
  const sourceName = options.sourceName || path17.basename(resolvedPath);
56195
- if (!fs17.existsSync(resolvedPath)) {
56548
+ if (!fs18.existsSync(resolvedPath)) {
56196
56549
  throw new FileManagerError(
56197
56550
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56198
56551
  `File not found: ${filePath}`
@@ -56207,7 +56560,7 @@ var FileManager = class {
56207
56560
  this.fileCache.rememberPathHint(resolvedPath, hash, sourceName);
56208
56561
  this.invalidateDirectoryListingCacheForPath(resolvedPath);
56209
56562
  const entry = this.fileCache.getByHash(hash);
56210
- const size = entry?.size ?? fs17.statSync(resolvedPath).size;
56563
+ const size = entry?.size ?? fs18.statSync(resolvedPath).size;
56211
56564
  return {
56212
56565
  success: true,
56213
56566
  hash,
@@ -56222,7 +56575,7 @@ var FileManager = class {
56222
56575
  async upload(filePath, options = {}) {
56223
56576
  const resolvedPath = resolvePath(filePath);
56224
56577
  const sourceName = options.sourceName || path17.basename(resolvedPath);
56225
- if (!fs17.existsSync(resolvedPath)) {
56578
+ if (!fs18.existsSync(resolvedPath)) {
56226
56579
  throw new FileManagerError(
56227
56580
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56228
56581
  `File not found: ${filePath}`
@@ -56303,7 +56656,7 @@ var FileManager = class {
56303
56656
  // ============================================================================
56304
56657
  async uploadPic(filePath, options = {}) {
56305
56658
  const resolvedPath = resolvePath(filePath);
56306
- if (!fs17.existsSync(resolvedPath)) {
56659
+ if (!fs18.existsSync(resolvedPath)) {
56307
56660
  throw new FileManagerError(
56308
56661
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56309
56662
  `File not found: ${filePath}`
@@ -56333,7 +56686,7 @@ var FileManager = class {
56333
56686
  this.fileCache.rememberPathHint(resolvedPath, result.hash, path17.basename(resolvedPath));
56334
56687
  this.invalidateDirectoryListingCacheForPath(resolvedPath);
56335
56688
  try {
56336
- fs17.unlinkSync(optimizedPath);
56689
+ fs18.unlinkSync(optimizedPath);
56337
56690
  } catch {
56338
56691
  }
56339
56692
  return result;
@@ -56343,7 +56696,7 @@ var FileManager = class {
56343
56696
  // ============================================================================
56344
56697
  async uploadVideo(filePath, options = {}) {
56345
56698
  const resolvedPath = resolvePath(filePath);
56346
- if (!fs17.existsSync(resolvedPath)) {
56699
+ if (!fs18.existsSync(resolvedPath)) {
56347
56700
  throw new FileManagerError(
56348
56701
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56349
56702
  `File not found: ${filePath}`
@@ -56737,13 +57090,13 @@ var FileManager = class {
56737
57090
  cleanupTempFiles(output) {
56738
57091
  try {
56739
57092
  if (typeof output === "string") {
56740
- if (fs17.existsSync(output)) {
56741
- fs17.unlinkSync(output);
57093
+ if (fs18.existsSync(output)) {
57094
+ fs18.unlinkSync(output);
56742
57095
  }
56743
57096
  } else {
56744
57097
  for (const file of output) {
56745
- if (fs17.existsSync(file)) {
56746
- fs17.unlinkSync(file);
57098
+ if (fs18.existsSync(file)) {
57099
+ fs18.unlinkSync(file);
56747
57100
  }
56748
57101
  }
56749
57102
  }
@@ -56775,7 +57128,7 @@ var FileManager = class {
56775
57128
  }];
56776
57129
  }
56777
57130
  const localPath = this.fileCache.getLocalPath(entry.hash);
56778
- if (localPath && fs17.existsSync(localPath)) {
57131
+ if (localPath && fs18.existsSync(localPath)) {
56779
57132
  return [{
56780
57133
  fileId,
56781
57134
  name: cacheEntry.name,
@@ -56872,7 +57225,7 @@ var FileManager = class {
56872
57225
  directories: []
56873
57226
  };
56874
57227
  try {
56875
- const entries = fs17.readdirSync(resolvedDir, { withFileTypes: true });
57228
+ const entries = fs18.readdirSync(resolvedDir, { withFileTypes: true });
56876
57229
  for (const entry of entries) {
56877
57230
  if (!entry.name || entry.name.startsWith(".")) {
56878
57231
  continue;
@@ -56886,7 +57239,7 @@ var FileManager = class {
56886
57239
  let isFile = entry.isFile();
56887
57240
  if (entry.isSymbolicLink()) {
56888
57241
  try {
56889
- const targetStat = fs17.statSync(fullPath);
57242
+ const targetStat = fs18.statSync(fullPath);
56890
57243
  isDirectory = targetStat.isDirectory();
56891
57244
  isFile = targetStat.isFile();
56892
57245
  } catch {
@@ -56904,7 +57257,7 @@ var FileManager = class {
56904
57257
  if (!type) {
56905
57258
  continue;
56906
57259
  }
56907
- const stat2 = fs17.statSync(fullPath);
57260
+ const stat2 = fs18.statSync(fullPath);
56908
57261
  listing.files.push({
56909
57262
  name: entry.name,
56910
57263
  path: fullPath,
@@ -57003,7 +57356,7 @@ function isInlineMediaRequest(request) {
57003
57356
  return request.kind === "image" || request.kind === "video";
57004
57357
  }
57005
57358
  async function prepareInlineMediaContent(params) {
57006
- const stat2 = await fs18.stat(params.request.absolutePath);
57359
+ const stat2 = await fs19.stat(params.request.absolutePath);
57007
57360
  const limitMb = getCapabilityLimitMb(params.model, params.request.kind);
57008
57361
  const limitBytes = limitMb * 1024 * 1024;
57009
57362
  if (stat2.size > limitBytes) {
@@ -57011,7 +57364,7 @@ async function prepareInlineMediaContent(params) {
57011
57364
  `${params.request.kind} understanding for ${params.model.provider}/${params.model.id} supports inline files up to ${limitMb}MB; ${path18.basename(params.request.displayPath)} is ${(stat2.size / 1024 / 1024).toFixed(1)}MB. Configure a model with a file upload adapter, or compress/trim the file before reading it.`
57012
57365
  );
57013
57366
  }
57014
- const data = await fs18.readFile(params.request.absolutePath, "base64");
57367
+ const data = await fs19.readFile(params.request.absolutePath, "base64");
57015
57368
  const content = params.request.kind === "video" ? [{ type: "video", data, mimeType: params.request.mimeType }] : [{ type: "image", data, mimeType: params.request.mimeType }];
57016
57369
  return {
57017
57370
  content,
@@ -57381,22 +57734,22 @@ var ExecutionStateManager = class {
57381
57734
  };
57382
57735
 
57383
57736
  // src/session-trace.ts
57384
- import * as fs19 from "node:fs";
57737
+ import * as fs20 from "node:fs";
57385
57738
  import * as path19 from "node:path";
57386
57739
  function saveTraceFileBestEffort(tracePath, content) {
57387
57740
  const tempPath = `${tracePath}.${process.pid}.${Date.now()}.tmp`;
57388
57741
  try {
57389
- fs19.writeFileSync(tempPath, content, "utf8");
57742
+ fs20.writeFileSync(tempPath, content, "utf8");
57390
57743
  try {
57391
- fs19.renameSync(tempPath, tracePath);
57744
+ fs20.renameSync(tempPath, tracePath);
57392
57745
  return;
57393
57746
  } catch {
57394
57747
  try {
57395
- fs19.copyFileSync(tempPath, tracePath);
57748
+ fs20.copyFileSync(tempPath, tracePath);
57396
57749
  } catch {
57397
57750
  } finally {
57398
57751
  try {
57399
- fs19.unlinkSync(tempPath);
57752
+ fs20.unlinkSync(tempPath);
57400
57753
  } catch {
57401
57754
  }
57402
57755
  }
@@ -57410,9 +57763,9 @@ var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
57410
57763
  getSessionId: () => sessionManager.getActiveSessionId(),
57411
57764
  loadTrace: (sessionId) => {
57412
57765
  const tracePath = path19.join(sessionsDir, `${sessionId}.trace.json`);
57413
- if (!fs19.existsSync(tracePath)) return null;
57766
+ if (!fs20.existsSync(tracePath)) return null;
57414
57767
  try {
57415
- return JSON.parse(fs19.readFileSync(tracePath, "utf8"));
57768
+ return JSON.parse(fs20.readFileSync(tracePath, "utf8"));
57416
57769
  } catch {
57417
57770
  return null;
57418
57771
  }
@@ -60129,7 +60482,7 @@ async function handleForkCommand(host) {
60129
60482
  }
60130
60483
 
60131
60484
  // src/commands/interactive-skill-commands.ts
60132
- import * as fs20 from "fs";
60485
+ import * as fs21 from "fs";
60133
60486
  import * as os4 from "os";
60134
60487
  import * as path20 from "path";
60135
60488
 
@@ -60473,7 +60826,7 @@ function expandSkillCommand(host, text) {
60473
60826
  const skill = host.skills.find((s) => s.name === skillName);
60474
60827
  if (!skill) return text;
60475
60828
  try {
60476
- const content = fs20.readFileSync(skill.filePath, "utf-8");
60829
+ const content = fs21.readFileSync(skill.filePath, "utf-8");
60477
60830
  const body = host.stripFrontmatter(content).trim();
60478
60831
  const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
60479
60832
  References are relative to ${skill.baseDir}.
@@ -60543,13 +60896,13 @@ async function handleSkillsCreate(host, args) {
60543
60896
  const skillDir = path20.join(skillsDir, name);
60544
60897
  const skillFile = path20.join(skillDir, "SKILL.md");
60545
60898
  console.error(`[SkillsCreate] Creating at: ${skillFile}`);
60546
- if (fs20.existsSync(skillDir)) {
60899
+ if (fs21.existsSync(skillDir)) {
60547
60900
  host.showError(`Skill "${name}" already exists at ${skillDir}`);
60548
60901
  return;
60549
60902
  }
60550
- fs20.mkdirSync(skillDir, { recursive: true });
60903
+ fs21.mkdirSync(skillDir, { recursive: true });
60551
60904
  const template = createSkillTemplate(name, description);
60552
- fs20.writeFileSync(skillFile, template, "utf-8");
60905
+ fs21.writeFileSync(skillFile, template, "utf-8");
60553
60906
  console.error(`[SkillsCreate] Successfully created skill`);
60554
60907
  host.chatContainer.addChild(new Spacer(1));
60555
60908
  host.chatContainer.addChild(new Text(theme.fg("accent", `\u2713 Created skill: ${name}`), 1, 0));
@@ -62020,7 +62373,7 @@ function setupInteractiveEditorSubmitHandler(host) {
62020
62373
  }
62021
62374
 
62022
62375
  // src/input/interactive-file-pipeline.ts
62023
- import * as fs23 from "fs";
62376
+ import * as fs24 from "fs";
62024
62377
  import * as path23 from "path";
62025
62378
 
62026
62379
  // src/components/file-picker.ts
@@ -62242,7 +62595,7 @@ var FilePickerComponent = class extends Container {
62242
62595
  };
62243
62596
 
62244
62597
  // src/files/commands/file-commands.ts
62245
- import * as fs21 from "node:fs";
62598
+ import * as fs22 from "node:fs";
62246
62599
  import * as path21 from "node:path";
62247
62600
  var FileCommands = class {
62248
62601
  context;
@@ -62259,7 +62612,7 @@ var FileCommands = class {
62259
62612
  return;
62260
62613
  }
62261
62614
  const filePath = resolvePath(parsed.path);
62262
- if (!fs21.existsSync(filePath)) {
62615
+ if (!fs22.existsSync(filePath)) {
62263
62616
  this.context.showError(`File not found: ${parsed.path}`);
62264
62617
  return;
62265
62618
  }
@@ -62298,7 +62651,7 @@ var FileCommands = class {
62298
62651
  return;
62299
62652
  }
62300
62653
  const resolvedPath = resolvePath(filePath);
62301
- if (!fs21.existsSync(resolvedPath)) {
62654
+ if (!fs22.existsSync(resolvedPath)) {
62302
62655
  this.context.showError(`File not found: ${filePath}`);
62303
62656
  return;
62304
62657
  }
@@ -62329,7 +62682,7 @@ var FileCommands = class {
62329
62682
  return;
62330
62683
  }
62331
62684
  const resolvedPath = resolvePath(parsed.path);
62332
- if (!fs21.existsSync(resolvedPath)) {
62685
+ if (!fs22.existsSync(resolvedPath)) {
62333
62686
  this.context.showError(`File not found: ${parsed.path}`);
62334
62687
  return;
62335
62688
  }
@@ -62807,7 +63160,7 @@ var FileStatusMonitor = class {
62807
63160
  };
62808
63161
 
62809
63162
  // src/files/mention/mention-handler.ts
62810
- import * as fs22 from "node:fs";
63163
+ import * as fs23 from "node:fs";
62811
63164
  import * as path22 from "node:path";
62812
63165
  var MentionHandler = class {
62813
63166
  fileManager;
@@ -63177,8 +63530,8 @@ var MentionHandler = class {
63177
63530
  }
63178
63531
  if (this.isPath(query)) {
63179
63532
  const resolvedPath = resolvePath(query);
63180
- if (fs22.existsSync(resolvedPath)) {
63181
- const stats = fs22.statSync(resolvedPath);
63533
+ if (fs23.existsSync(resolvedPath)) {
63534
+ const stats = fs23.statSync(resolvedPath);
63182
63535
  if (stats.isFile()) {
63183
63536
  const type = FileCache.getFileTypeFromName(resolvedPath);
63184
63537
  const name = path22.basename(resolvedPath);
@@ -63202,7 +63555,7 @@ var MentionHandler = class {
63202
63555
  return void 0;
63203
63556
  }
63204
63557
  const queryPath = this.isPath(query) ? resolvePath(query) : void 0;
63205
- const filter = queryPath ? fs22.existsSync(queryPath) && fs22.statSync(queryPath).isDirectory() ? "" : path22.basename(queryPath) : query;
63558
+ const filter = queryPath ? fs23.existsSync(queryPath) && fs23.statSync(queryPath).isDirectory() ? "" : path22.basename(queryPath) : query;
63206
63559
  const entries = this.fileManager.listPathEntries(currentDir, filter);
63207
63560
  const options = [];
63208
63561
  const homeDir = process.env.HOME || "";
@@ -63243,7 +63596,7 @@ var MentionHandler = class {
63243
63596
  getBrowserDirectory(query = this.currentQuery) {
63244
63597
  if (this.isPath(query)) {
63245
63598
  const resolvedPath = resolvePath(query);
63246
- if (fs22.existsSync(resolvedPath) && fs22.statSync(resolvedPath).isDirectory()) {
63599
+ if (fs23.existsSync(resolvedPath) && fs23.statSync(resolvedPath).isDirectory()) {
63247
63600
  return resolvedPath;
63248
63601
  }
63249
63602
  return path22.dirname(resolvedPath);
@@ -63607,13 +63960,13 @@ function convertPreparedAttachmentItems(items) {
63607
63960
  break;
63608
63961
  case "image": {
63609
63962
  if (!item.data && !item.path) return void 0;
63610
- const data = item.data ?? fs23.readFileSync(item.path, "base64");
63963
+ const data = item.data ?? fs24.readFileSync(item.path, "base64");
63611
63964
  converted.push({ type: "image", data, mimeType: item.mimeType });
63612
63965
  break;
63613
63966
  }
63614
63967
  case "video": {
63615
63968
  if (!item.data && !item.path) return void 0;
63616
- const data = item.data ?? fs23.readFileSync(item.path, "base64");
63969
+ const data = item.data ?? fs24.readFileSync(item.path, "base64");
63617
63970
  converted.push({ type: "video", data, mimeType: item.mimeType });
63618
63971
  break;
63619
63972
  }
@@ -65099,7 +65452,7 @@ var RUNTIME_MODE_CONTEXT_MARKER = "<runtime-mode-context>";
65099
65452
  var RUNTIME_MODE_CONTEXT_END_MARKER = "</runtime-mode-context>";
65100
65453
  var STALE_SYSTEM_REMINDER_RE = /<system-reminder>\s*# Plan Mode[\s\S]*?<\/system-reminder>\s*/gi;
65101
65454
  var STALE_RUNTIME_CONTEXT_RE = /<runtime-mode-context>[\s\S]*?<\/runtime-mode-context>\s*/gi;
65102
- function isRecord2(value) {
65455
+ function isRecord3(value) {
65103
65456
  return !!value && typeof value === "object" && !Array.isArray(value);
65104
65457
  }
65105
65458
  function cleanText(text) {
@@ -65115,7 +65468,7 @@ function cleanText(text) {
65115
65468
  return { text: withoutPlanReminder, stripped };
65116
65469
  }
65117
65470
  function stripUserMessage(message) {
65118
- if (!isRecord2(message) || message.role !== "user") {
65471
+ if (!isRecord3(message) || message.role !== "user") {
65119
65472
  return { message, stripped: 0 };
65120
65473
  }
65121
65474
  const content = message.content;
@@ -65135,13 +65488,13 @@ function stripUserMessage(message) {
65135
65488
  }
65136
65489
  let stripped = 0;
65137
65490
  const nextContent = content.map((block) => {
65138
- if (!isRecord2(block) || block.type !== "text" || typeof block.text !== "string") {
65491
+ if (!isRecord3(block) || block.type !== "text" || typeof block.text !== "string") {
65139
65492
  return block;
65140
65493
  }
65141
65494
  const cleaned = cleanText(block.text);
65142
65495
  stripped += cleaned.stripped;
65143
65496
  return { ...block, text: cleaned.text };
65144
- }).filter((block) => !(isRecord2(block) && block.type === "text" && String(block.text ?? "").length === 0));
65497
+ }).filter((block) => !(isRecord3(block) && block.type === "text" && String(block.text ?? "").length === 0));
65145
65498
  if (stripped === 0) return { message, stripped: 0 };
65146
65499
  return {
65147
65500
  message: {
@@ -65157,7 +65510,7 @@ function stripRuntimeModeContext(messages) {
65157
65510
  for (const message of messages) {
65158
65511
  const result = stripUserMessage(message);
65159
65512
  stripped += result.stripped;
65160
- if (isRecord2(result.message) && result.message.role === "user") {
65513
+ if (isRecord3(result.message) && result.message.role === "user") {
65161
65514
  const content = result.message.content;
65162
65515
  if (typeof content === "string" && content.trim().length === 0) {
65163
65516
  continue;
@@ -65199,7 +65552,7 @@ function buildRuntimeModeContext(state) {
65199
65552
  function findLatestUserIndex(messages) {
65200
65553
  for (let index = messages.length - 1; index >= 0; index--) {
65201
65554
  const message = messages[index];
65202
- if (isRecord2(message) && message.role === "user") {
65555
+ if (isRecord3(message) && message.role === "user") {
65203
65556
  return index;
65204
65557
  }
65205
65558
  }
@@ -65678,7 +66031,7 @@ var AttachmentResolver = class {
65678
66031
  };
65679
66032
 
65680
66033
  // src/extensions/loader.ts
65681
- import * as fs24 from "node:fs";
66034
+ import * as fs25 from "node:fs";
65682
66035
  import * as os5 from "os";
65683
66036
  import * as path24 from "path";
65684
66037
  import { pathToFileURL } from "node:url";
@@ -65862,7 +66215,7 @@ function normalizeExtensionImportPath(extensionPath) {
65862
66215
  }
65863
66216
  async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, hasUI, actions) {
65864
66217
  const resolvedPath = resolvePath2(extensionPath, cwd);
65865
- if (!fs24.existsSync(resolvedPath)) {
66218
+ if (!fs25.existsSync(resolvedPath)) {
65866
66219
  return { extension: null, error: `Extension not found: ${extensionPath}` };
65867
66220
  }
65868
66221
  try {
@@ -65883,12 +66236,12 @@ async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, h
65883
66236
  }
65884
66237
  }
65885
66238
  function discoverExtensionsInDir(dir) {
65886
- if (!fs24.existsSync(dir)) {
66239
+ if (!fs25.existsSync(dir)) {
65887
66240
  return [];
65888
66241
  }
65889
66242
  const discovered = [];
65890
66243
  try {
65891
- const entries = fs24.readdirSync(dir, { withFileTypes: true });
66244
+ const entries = fs25.readdirSync(dir, { withFileTypes: true });
65892
66245
  for (const entry of entries) {
65893
66246
  const entryPath = path24.join(dir, entry.name);
65894
66247
  if (entry.isFile() && (entry.name.endsWith(".cjs") || entry.name.endsWith(".js") || entry.name.endsWith(".ts"))) {
@@ -65897,13 +66250,13 @@ function discoverExtensionsInDir(dir) {
65897
66250
  }
65898
66251
  if (entry.isDirectory()) {
65899
66252
  const packageJsonPath = path24.join(entryPath, "package.json");
65900
- if (fs24.existsSync(packageJsonPath)) {
66253
+ if (fs25.existsSync(packageJsonPath)) {
65901
66254
  try {
65902
- const pkg = JSON.parse(fs24.readFileSync(packageJsonPath, "utf-8"));
66255
+ const pkg = JSON.parse(fs25.readFileSync(packageJsonPath, "utf-8"));
65903
66256
  const manifest = pkg.pie;
65904
66257
  if (manifest?.main) {
65905
66258
  const mainPath = path24.resolve(entryPath, manifest.main);
65906
- if (fs24.existsSync(mainPath)) {
66259
+ if (fs25.existsSync(mainPath)) {
65907
66260
  discovered.push({
65908
66261
  entryPath: mainPath,
65909
66262
  manifestName: manifest.name || pkg.name
@@ -65915,17 +66268,17 @@ function discoverExtensionsInDir(dir) {
65915
66268
  }
65916
66269
  }
65917
66270
  const indexCjs = path24.join(entryPath, "index.cjs");
65918
- if (fs24.existsSync(indexCjs)) {
66271
+ if (fs25.existsSync(indexCjs)) {
65919
66272
  discovered.push({ entryPath: indexCjs });
65920
66273
  continue;
65921
66274
  }
65922
66275
  const indexJs = path24.join(entryPath, "index.js");
65923
- if (fs24.existsSync(indexJs)) {
66276
+ if (fs25.existsSync(indexJs)) {
65924
66277
  discovered.push({ entryPath: indexJs });
65925
66278
  continue;
65926
66279
  }
65927
66280
  const indexTs = path24.join(entryPath, "index.ts");
65928
- if (fs24.existsSync(indexTs)) {
66281
+ if (fs25.existsSync(indexTs)) {
65929
66282
  discovered.push({ entryPath: indexTs });
65930
66283
  continue;
65931
66284
  }
@@ -65974,11 +66327,11 @@ async function loadExtensions(configuredPaths, cwd, uiContext, abortFn, isIdleFn
65974
66327
  }
65975
66328
  for (const p of configuredPaths) {
65976
66329
  const resolved = resolvePath2(p, cwd);
65977
- if (!fs24.existsSync(resolved)) {
66330
+ if (!fs25.existsSync(resolved)) {
65978
66331
  errors.push({ path: p, error: `Extension path not found: ${p}` });
65979
66332
  continue;
65980
66333
  }
65981
- if (!fs24.statSync(resolved).isDirectory()) {
66334
+ if (!fs25.statSync(resolved).isDirectory()) {
65982
66335
  errors.push({ path: p, error: `Extension path must be a directory: ${p}` });
65983
66336
  continue;
65984
66337
  }
@@ -66962,7 +67315,7 @@ var InteractiveMode = class {
66962
67315
  if (savedLevel) {
66963
67316
  this.thinkingLevel = savedLevel;
66964
67317
  }
66965
- const { Agent } = await import("./chunks/src-7UV3KKGU.js");
67318
+ const { Agent } = await import("./chunks/src-2FHZO63Y.js");
66966
67319
  const activeSession = this.sessionManager.getActiveSession();
66967
67320
  this.agent = new Agent({
66968
67321
  initialState: {
@@ -67364,10 +67717,12 @@ async function composeCliRuntime(params) {
67364
67717
  inputSummary: `provider=${settingsManager.getDefaultProvider() || "unset"} model=${settingsManager.getDefaultModel() || "unset"}`,
67365
67718
  outputSummary: `provider=${provider} model=${modelId} configured=${!initialModel.unconfigured}`
67366
67719
  });
67367
- const cwd = process.cwd();
67720
+ const cwd = params.cwd ?? process.cwd();
67368
67721
  const sessionManager = createSessionManager({ sessionsDir: paths.sessionsDir });
67369
67722
  if (params.explicitSessionId) {
67370
- const loaded = await sessionManager.loadSession(params.explicitSessionId);
67723
+ const loaded = await sessionManager.loadSession(params.explicitSessionId, {
67724
+ warnIfMissing: params.warnIfExplicitSessionMissing
67725
+ });
67371
67726
  if (!loaded) {
67372
67727
  await sessionManager.createSession(void 0, void 0, params.explicitSessionId);
67373
67728
  } else {
@@ -67391,6 +67746,11 @@ async function composeCliRuntime(params) {
67391
67746
  await sessionManager.createSession();
67392
67747
  }
67393
67748
  syncSessionModelMetadata(sessionManager, model, settingsManager.getDefaultThinkingLevel() || "off");
67749
+ const activeSession = sessionManager.getActiveSession();
67750
+ if (activeSession && activeSession.metadata.cwd !== cwd) {
67751
+ activeSession.metadata.cwd = cwd;
67752
+ await sessionManager.save();
67753
+ }
67394
67754
  const sessionId = sessionManager.getActiveSession()?.id;
67395
67755
  const fileObservationState = createFileObservationState();
67396
67756
  if (sessionId) {
@@ -67633,7 +67993,7 @@ async function runPrintMode(params) {
67633
67993
  `);
67634
67994
  console.log("Assistant: ");
67635
67995
  }
67636
- const { Agent: AgentClass } = await import("./chunks/src-7UV3KKGU.js");
67996
+ const { Agent: AgentClass } = await import("./chunks/src-2FHZO63Y.js");
67637
67997
  let agent;
67638
67998
  const printModeExtensions = await loadPrintModeExtensions({
67639
67999
  cwd: runtime.cwd,
@@ -67853,7 +68213,7 @@ function toJsonValue(value, depth = 0) {
67853
68213
  }
67854
68214
  return result;
67855
68215
  }
67856
- function isRecord3(value) {
68216
+ function isRecord4(value) {
67857
68217
  return !!value && typeof value === "object" && !Array.isArray(value);
67858
68218
  }
67859
68219
  function parseInput(line) {
@@ -67863,7 +68223,7 @@ function parseInput(line) {
67863
68223
  } catch {
67864
68224
  return null;
67865
68225
  }
67866
- if (!isRecord3(parsed) || typeof parsed.type !== "string") return null;
68226
+ if (!isRecord4(parsed) || typeof parsed.type !== "string") return null;
67867
68227
  if (parsed.type === "shutdown") {
67868
68228
  return { type: "shutdown", reason: typeof parsed.reason === "string" ? parsed.reason : void 0 };
67869
68229
  }
@@ -67882,7 +68242,7 @@ function parseInput(line) {
67882
68242
  turnId: parsed.turnId,
67883
68243
  prompt: parsed.prompt,
67884
68244
  cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0,
67885
- metadata: isRecord3(parsed.metadata) ? parsed.metadata : void 0
68245
+ metadata: isRecord4(parsed.metadata) ? parsed.metadata : void 0
67886
68246
  };
67887
68247
  }
67888
68248
  return null;
@@ -67916,15 +68276,15 @@ function readProgressText(value) {
67916
68276
  function extractJsonEventsToolProgressText(partialResult) {
67917
68277
  const plainText = readProgressText(partialResult).trim();
67918
68278
  if (plainText) return plainText;
67919
- if (!isRecord3(partialResult)) return "";
68279
+ if (!isRecord4(partialResult)) return "";
67920
68280
  const content = partialResult.content;
67921
68281
  if (Array.isArray(content)) {
67922
- return content.map((block) => isRecord3(block) && block.type === "text" ? readProgressText(block.text) : "").filter(Boolean).join("\n").trim();
68282
+ return content.map((block) => isRecord4(block) && block.type === "text" ? readProgressText(block.text) : "").filter(Boolean).join("\n").trim();
67923
68283
  }
67924
68284
  const directText = readProgressText(partialResult.text) || readProgressText(partialResult.message);
67925
68285
  if (directText) return directText.trim();
67926
68286
  const details = partialResult.details;
67927
- if (isRecord3(details)) {
68287
+ if (isRecord4(details)) {
67928
68288
  return (readProgressText(details.text) || readProgressText(details.message)).trim();
67929
68289
  }
67930
68290
  return "";
@@ -68011,12 +68371,14 @@ async function loadJsonModeExtensions(params) {
68011
68371
  async function runJsonEventsMode(params) {
68012
68372
  const sessionId = params.explicitSessionId || params.runtime?.sessionManager.getActiveSession()?.id || `pie-json-${Date.now()}`;
68013
68373
  let activeTurn = null;
68374
+ let runtime = params.runtime;
68014
68375
  let agent;
68015
68376
  let controller;
68016
68377
  let disposeAgentSubscription;
68017
68378
  let disposeSemanticSubscription;
68018
68379
  let trace;
68019
68380
  let lastRetryEvent;
68381
+ let mockActiveEntryId;
68020
68382
  const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
68021
68383
  const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
68022
68384
  writeEvent({ type: "agent.ready", sessionId });
@@ -68036,6 +68398,7 @@ async function runJsonEventsMode(params) {
68036
68398
  }
68037
68399
  function display(chunk, options) {
68038
68400
  if (!activeTurn || !chunk) return;
68401
+ activeTurn.outputStarted = true;
68039
68402
  if (options?.appendToSummary !== false) {
68040
68403
  activeTurn.summary += chunk;
68041
68404
  }
@@ -68058,6 +68421,78 @@ async function runJsonEventsMode(params) {
68058
68421
  activeTurn.pendingAssistantOutput = "";
68059
68422
  }
68060
68423
  }
68424
+ function activeHeadEntryId() {
68425
+ return mockActiveEntryId ?? runtime?.sessionManager.getActiveEntryId() ?? void 0;
68426
+ }
68427
+ function persistedMockMetadata(existing, activeEntryId, rootEntryId, cwd) {
68428
+ const metadata = {};
68429
+ if (existing) {
68430
+ for (const [key, value] of Object.entries(existing)) {
68431
+ if (["id", "createdAt", "updatedAt", "entryCount", "messageCount", "activeEntryId", "rootEntryId"].includes(key)) {
68432
+ continue;
68433
+ }
68434
+ metadata[key] = value;
68435
+ }
68436
+ }
68437
+ metadata.name = typeof existing?.name === "string" ? existing.name : `Session ${sessionId.slice(0, 8)}`;
68438
+ if (cwd || existing?.cwd || runtime?.cwd) {
68439
+ metadata.cwd = cwd ?? existing?.cwd ?? runtime?.cwd;
68440
+ }
68441
+ metadata.activeEntryId = activeEntryId;
68442
+ metadata.rootEntryId = existing?.rootEntryId ?? rootEntryId;
68443
+ return metadata;
68444
+ }
68445
+ async function persistMockTurn(message, assistantText) {
68446
+ const store = new FileSessionStore(getSessionsDir());
68447
+ const existing = await store.load(message.sessionId ?? sessionId);
68448
+ const startedAt = activeTurn?.startedAt ?? Date.now();
68449
+ const userEntryId = generateEntryId();
68450
+ const assistantEntryId = generateEntryId();
68451
+ const parentId = existing?.metadata.activeEntryId ?? null;
68452
+ const userEntry = {
68453
+ id: userEntryId,
68454
+ parentId,
68455
+ type: "message",
68456
+ timestamp: startedAt,
68457
+ message: {
68458
+ role: "user",
68459
+ content: message.prompt,
68460
+ timestamp: startedAt
68461
+ }
68462
+ };
68463
+ const assistantTimestamp = Date.now();
68464
+ const assistantMessage = {
68465
+ role: "assistant",
68466
+ content: [{ type: "text", text: assistantText }],
68467
+ api: "mock",
68468
+ provider: "mock",
68469
+ model: "mock",
68470
+ usage: {
68471
+ input: 0,
68472
+ output: 0,
68473
+ cacheRead: 0,
68474
+ cacheWrite: 0,
68475
+ totalTokens: 0,
68476
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
68477
+ },
68478
+ stopReason: "stop",
68479
+ timestamp: assistantTimestamp
68480
+ };
68481
+ const assistantEntry = {
68482
+ id: assistantEntryId,
68483
+ parentId: userEntryId,
68484
+ type: "message",
68485
+ timestamp: assistantTimestamp,
68486
+ message: assistantMessage
68487
+ };
68488
+ const entries = [...existing?.entries ?? [], userEntry, assistantEntry];
68489
+ await store.save(
68490
+ message.sessionId ?? sessionId,
68491
+ entries,
68492
+ persistedMockMetadata(existing?.metadata, assistantEntryId, existing?.metadata.rootEntryId ?? userEntryId, message.cwd)
68493
+ );
68494
+ return assistantEntryId;
68495
+ }
68061
68496
  function flushAssistantOutput(fallbackText = "") {
68062
68497
  if (!activeTurn) return;
68063
68498
  const chunk = activeTurn.pendingAssistantOutput || fallbackText;
@@ -68070,21 +68505,38 @@ async function runJsonEventsMode(params) {
68070
68505
  const turn = activeTurn;
68071
68506
  if (!turn || turn.finalized) return;
68072
68507
  turn.finalized = true;
68508
+ const headEntryId = activeHeadEntryId();
68509
+ const base = {
68510
+ sessionId: turn.sessionId,
68511
+ turnId: turn.turnId,
68512
+ headEntryId,
68513
+ activeEntryId: headEntryId
68514
+ };
68073
68515
  switch (kind) {
68074
68516
  case "completed":
68075
- writeEvent({ type: "turn.completed", sessionId: turn.sessionId, turnId: turn.turnId, summary: (detail ?? turn.summary).trim() });
68517
+ writeEvent({ type: "turn.completed", ...base, summary: (detail ?? turn.summary).trim() });
68076
68518
  break;
68077
68519
  case "failed":
68078
- writeEvent({ type: "turn.failed", sessionId: turn.sessionId, turnId: turn.turnId, error: detail || "turn failed" });
68520
+ writeEvent({ type: "turn.failed", ...base, error: detail || "turn failed" });
68079
68521
  break;
68080
68522
  case "cancelled":
68081
- writeEvent({ type: "turn.cancelled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "interrupted" });
68523
+ writeEvent({ type: "turn.cancelled", ...base, reason: detail || "interrupted" });
68082
68524
  break;
68083
68525
  case "stalled":
68084
- writeEvent({ type: "turn.stalled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "no_progress_timeout" });
68526
+ writeEvent({ type: "turn.stalled", ...base, reason: detail || "no_progress_timeout" });
68085
68527
  break;
68086
68528
  }
68087
68529
  }
68530
+ function emitSettled(turn) {
68531
+ const headEntryId = activeHeadEntryId();
68532
+ writeEvent({
68533
+ type: "turn.settled",
68534
+ sessionId: turn.sessionId,
68535
+ turnId: turn.turnId,
68536
+ headEntryId,
68537
+ activeEntryId: headEntryId
68538
+ });
68539
+ }
68088
68540
  function rememberTerminal(kind, detail, options) {
68089
68541
  if (!activeTurn || activeTurn.finalized) return;
68090
68542
  if (activeTurn.pendingTerminal && options?.overwrite === false) return;
@@ -68144,15 +68596,10 @@ async function runJsonEventsMode(params) {
68144
68596
  function handleControllerEvent(event) {
68145
68597
  trace?.noteRuntimeEvent(event.type, event);
68146
68598
  if (event.type === "auto_compaction_end" && !event.errorMessage) {
68147
- params.runtime?.fileObservationState.clear();
68599
+ runtime?.fileObservationState.clear();
68148
68600
  }
68149
68601
  if (event.type === "turn_settled" && activeTurn) {
68150
- finalizePendingTerminal();
68151
- writeEvent({
68152
- type: "turn.settled",
68153
- sessionId: activeTurn.sessionId,
68154
- turnId: activeTurn.turnId
68155
- });
68602
+ touch();
68156
68603
  return;
68157
68604
  }
68158
68605
  if (!activeTurn || activeTurn.finalized) return;
@@ -68252,16 +68699,35 @@ async function runJsonEventsMode(params) {
68252
68699
  rememberTerminal("cancelled", event.reason, { overwrite: false });
68253
68700
  }
68254
68701
  }
68255
- async function ensureRuntime() {
68256
- if (params.mockResponse !== void 0 || controller) return;
68257
- const runtime = params.runtime;
68702
+ async function disposeRuntime() {
68703
+ disposeAgentSubscription?.();
68704
+ disposeAgentSubscription = void 0;
68705
+ disposeSemanticSubscription?.();
68706
+ disposeSemanticSubscription = void 0;
68707
+ controller?.dispose();
68708
+ controller = void 0;
68709
+ agent = void 0;
68710
+ try {
68711
+ await runtime?.sessionManager.save();
68712
+ } catch {
68713
+ }
68714
+ trace?.flush();
68715
+ trace = void 0;
68716
+ }
68717
+ async function ensureRuntime(requestedCwd) {
68718
+ if (params.mockResponse !== void 0) return;
68719
+ const effectiveCwd = requestedCwd ?? process.cwd();
68720
+ if (params.createRuntime && (!runtime || runtime.cwd !== effectiveCwd)) {
68721
+ await disposeRuntime();
68722
+ runtime = await params.createRuntime({ cwd: effectiveCwd, sessionId });
68723
+ }
68258
68724
  if (!runtime) {
68259
68725
  throw new Error("JSON events mode requires a CLI runtime");
68260
68726
  }
68261
- if (runtime.initialModel.unconfigured) {
68727
+ if (runtime.initialModel.unconfigured || controller) {
68262
68728
  return;
68263
68729
  }
68264
- const { Agent: AgentClass } = await import("./chunks/src-7UV3KKGU.js");
68730
+ const { Agent: AgentClass } = await import("./chunks/src-2FHZO63Y.js");
68265
68731
  const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
68266
68732
  const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
68267
68733
  recordCliCompositionStep(runtime.compositionTrace, {
@@ -68367,6 +68833,7 @@ async function runJsonEventsMode(params) {
68367
68833
  interrupted: false,
68368
68834
  stalled: false,
68369
68835
  finalized: false,
68836
+ outputStarted: false,
68370
68837
  summary: "",
68371
68838
  pendingAssistantOutput: ""
68372
68839
  };
@@ -68380,30 +68847,43 @@ async function runJsonEventsMode(params) {
68380
68847
  return;
68381
68848
  }
68382
68849
  display(params.mockResponse);
68850
+ try {
68851
+ mockActiveEntryId = await persistMockTurn(message, params.mockResponse);
68852
+ } catch (error) {
68853
+ finalize("failed", error instanceof Error ? error.message : String(error));
68854
+ if (activeTurn === turn) emitSettled(turn);
68855
+ if (activeTurn === turn) activeTurn = null;
68856
+ return;
68857
+ }
68383
68858
  finalize("completed");
68859
+ if (activeTurn === turn) emitSettled(turn);
68384
68860
  if (activeTurn === turn) activeTurn = null;
68385
68861
  return;
68386
68862
  }
68387
68863
  if (params.startupError) {
68388
68864
  finalize("failed", params.startupError);
68865
+ if (activeTurn === turn) emitSettled(turn);
68389
68866
  if (activeTurn === turn) activeTurn = null;
68390
68867
  return;
68391
68868
  }
68392
68869
  try {
68393
- await ensureRuntime();
68870
+ await ensureRuntime(message.cwd);
68394
68871
  } catch (error) {
68395
68872
  finalize("failed", error instanceof Error ? error.message : String(error));
68873
+ if (activeTurn === turn) emitSettled(turn);
68396
68874
  if (activeTurn === turn) activeTurn = null;
68397
68875
  return;
68398
68876
  }
68399
- const runtime = params.runtime;
68400
- if (runtime?.initialModel.unconfigured) {
68401
- finalize("failed", runtime.initialModel.warning || "No models are configured.");
68877
+ const activeRuntime = runtime;
68878
+ if (activeRuntime?.initialModel.unconfigured) {
68879
+ finalize("failed", activeRuntime.initialModel.warning || "No models are configured.");
68880
+ if (activeTurn === turn) emitSettled(turn);
68402
68881
  if (activeTurn === turn) activeTurn = null;
68403
68882
  return;
68404
68883
  }
68405
68884
  if (!controller || !agent) {
68406
68885
  finalize("failed", "JSON events runtime was not initialized");
68886
+ if (activeTurn === turn) emitSettled(turn);
68407
68887
  if (activeTurn === turn) activeTurn = null;
68408
68888
  return;
68409
68889
  }
@@ -68425,31 +68905,36 @@ async function runJsonEventsMode(params) {
68425
68905
  trace?.noteWaitForIdleStart({ mode: "json-events" });
68426
68906
  await controller.waitForSettled();
68427
68907
  trace?.noteWaitForIdleSettled({ mode: "json-events" });
68908
+ await activeRuntime?.sessionManager.save();
68428
68909
  finalizePendingTerminal();
68429
68910
  if (!activeTurn?.finalized) {
68430
68911
  const finalError = assistantErrorFromAgent(agent);
68431
68912
  if (activeTurn?.interrupted) {
68432
68913
  finalize("cancelled", "user_interrupt");
68433
- return;
68434
- }
68435
- if (finalError) {
68914
+ } else if (finalError) {
68436
68915
  finalize("failed", finalError);
68437
- return;
68916
+ } else {
68917
+ const text = assistantTextFromAgent(agent);
68918
+ flushAssistantOutput(text);
68919
+ finalize("completed", text || activeTurn?.summary.trim());
68438
68920
  }
68439
- const text = assistantTextFromAgent(agent);
68440
- flushAssistantOutput(text);
68441
- finalize("completed", text || activeTurn?.summary.trim());
68442
68921
  }
68922
+ if (activeTurn === turn) emitSettled(turn);
68443
68923
  } catch (error) {
68444
68924
  const messageText = error instanceof Error ? error.message : String(error);
68445
68925
  trace?.noteStalled(messageText, { mode: "json-events" });
68926
+ try {
68927
+ await activeRuntime?.sessionManager.save();
68928
+ } catch {
68929
+ }
68446
68930
  if (!activeTurn?.finalized) {
68447
68931
  finalize(activeTurn?.interrupted ? "cancelled" : "failed", activeTurn?.interrupted ? "user_interrupt" : messageText);
68448
68932
  }
68933
+ if (activeTurn === turn) emitSettled(turn);
68449
68934
  } finally {
68450
68935
  clearInterval(progressTimer);
68451
68936
  trace?.flush();
68452
- await runtime?.sessionManager.save();
68937
+ await activeRuntime?.sessionManager.save();
68453
68938
  if (activeTurn === turn) activeTurn = null;
68454
68939
  }
68455
68940
  }
@@ -68481,12 +68966,29 @@ async function runJsonEventsMode(params) {
68481
68966
  });
68482
68967
  return;
68483
68968
  }
68969
+ if (params.mockResponse !== void 0) {
68970
+ if (activeTurn.outputStarted) return;
68971
+ activeTurn.interrupted = true;
68972
+ finalize("cancelled", message.reason || "user_interrupt");
68973
+ emitSettled(activeTurn);
68974
+ activeTurn = null;
68975
+ return;
68976
+ }
68484
68977
  activeTurn.interrupted = true;
68485
68978
  controller?.abort();
68979
+ }
68980
+ function shutdownActiveTurn(reason) {
68981
+ if (!activeTurn || activeTurn.finalized) return;
68486
68982
  if (params.mockResponse !== void 0) {
68487
- finalize("cancelled", message.reason || "user_interrupt");
68983
+ if (activeTurn.outputStarted) return;
68984
+ activeTurn.interrupted = true;
68985
+ finalize("cancelled", reason || "shutdown");
68986
+ emitSettled(activeTurn);
68488
68987
  activeTurn = null;
68988
+ return;
68489
68989
  }
68990
+ activeTurn.interrupted = true;
68991
+ controller?.abort();
68490
68992
  }
68491
68993
  const input = readline.createInterface({ input: process.stdin });
68492
68994
  let activeTurnPromise = null;
@@ -68498,15 +69000,7 @@ async function runJsonEventsMode(params) {
68498
69000
  continue;
68499
69001
  }
68500
69002
  if (message.type === "shutdown") {
68501
- if (activeTurn && !activeTurn.finalized) {
68502
- activeTurn.interrupted = true;
68503
- controller?.abort();
68504
- if (!controller) {
68505
- finalize("cancelled", message.reason || "shutdown");
68506
- } else {
68507
- rememberTerminal("cancelled", message.reason || "shutdown");
68508
- }
68509
- }
69003
+ shutdownActiveTurn(message.reason);
68510
69004
  break;
68511
69005
  }
68512
69006
  if (message.type === "turn.interrupt") {
@@ -68531,11 +69025,7 @@ async function runJsonEventsMode(params) {
68531
69025
  }
68532
69026
  }
68533
69027
  await activeTurnPromise;
68534
- disposeAgentSubscription?.();
68535
- disposeSemanticSubscription?.();
68536
- controller?.dispose();
68537
- await params.runtime?.sessionManager.save();
68538
- trace?.flush();
69028
+ await disposeRuntime();
68539
69029
  }
68540
69030
 
68541
69031
  // src/cli.ts
@@ -68544,8 +69034,8 @@ var logError = (msg, err) => {
68544
69034
  const logPath = getRuntimeLogPath();
68545
69035
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
68546
69036
  const stack = err instanceof Error ? err.stack || "" : "";
68547
- fs25.mkdirSync(path26.dirname(logPath), { recursive: true });
68548
- fs25.appendFileSync(logPath, `[${timestamp}] ${msg}
69037
+ fs26.mkdirSync(path26.dirname(logPath), { recursive: true });
69038
+ fs26.appendFileSync(logPath, `[${timestamp}] ${msg}
68549
69039
  ${stack}
68550
69040
 
68551
69041
  `);
@@ -68564,6 +69054,7 @@ Commands:
68564
69054
  doctor Diagnose local Pie configuration and runtime dependencies
68565
69055
  models init Create a starter ~/.pie/models.json
68566
69056
  models validate Validate ~/.pie/models.json
69057
+ sessions List, read, rename, rewind, and fork Pie sessions
68567
69058
  permissions Explain Pie tool and shell safety defaults
68568
69059
  help Show this help message
68569
69060
 
@@ -68688,7 +69179,7 @@ async function createCliTestStreamFnFromEnv() {
68688
69179
  if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) {
68689
69180
  return void 0;
68690
69181
  }
68691
- const { createTestStreamFnFromSequenceEnv } = await import("./chunks/test-stream-PP63L7MK.js");
69182
+ const { createTestStreamFnFromSequenceEnv } = await import("./chunks/test-stream-UW74PA6T.js");
68692
69183
  return createTestStreamFnFromSequenceEnv();
68693
69184
  }
68694
69185
  async function startChat(initialPrompt, testCommand) {
@@ -68707,23 +69198,15 @@ async function startChat(initialPrompt, testCommand) {
68707
69198
  });
68708
69199
  return;
68709
69200
  }
68710
- let runtime2;
68711
- try {
68712
- runtime2 = await composeCliRuntime({ explicitSessionId, extensionPaths });
68713
- } catch (error) {
68714
- if (error instanceof CliMissingApiKeyError) {
68715
- await runJsonEventsMode({
68716
- explicitSessionId,
68717
- startupError: error.message
68718
- });
68719
- return;
68720
- }
68721
- throw error;
68722
- }
68723
69201
  await runJsonEventsMode({
68724
- runtime: runtime2,
68725
69202
  explicitSessionId,
68726
- streamFn: await createCliTestStreamFnFromEnv()
69203
+ streamFn: await createCliTestStreamFnFromEnv(),
69204
+ createRuntime: async ({ cwd, sessionId }) => composeCliRuntime({
69205
+ explicitSessionId: explicitSessionId ?? sessionId,
69206
+ extensionPaths,
69207
+ cwd,
69208
+ warnIfExplicitSessionMissing: false
69209
+ })
68727
69210
  });
68728
69211
  });
68729
69212
  return;
@@ -68794,6 +69277,10 @@ async function startChat(initialPrompt, testCommand) {
68794
69277
  }
68795
69278
  async function main() {
68796
69279
  const args = process.argv.slice(2);
69280
+ if (args[0] === "--version" || args[0] === "-v") {
69281
+ console.log(VERSION);
69282
+ return;
69283
+ }
68797
69284
  if (args[0] === "doctor") {
68798
69285
  await runDoctorCommand(args.slice(1));
68799
69286
  return;
@@ -68807,6 +69294,10 @@ async function main() {
68807
69294
  }
68808
69295
  return;
68809
69296
  }
69297
+ if (args[0] === "sessions") {
69298
+ await runSessionsCommand(args.slice(1));
69299
+ return;
69300
+ }
68810
69301
  if (args[0] === "permissions") {
68811
69302
  console.log(formatPermissionsHelp());
68812
69303
  return;