@cydm/pie 1.0.19 → 1.0.21

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,379 @@ 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 includeMessage = hasFlag(args, "--raw") || hasFlag(args, "--include-message");
45560
+ const sessionId = positionalArgs(args, /* @__PURE__ */ new Set(["--limit", "--before"]))[0];
45561
+ if (!sessionId) throw new Error("Usage: pie sessions read <sessionId> [--json] [--raw|--include-message] [--limit <n>] [--before <cursor>]");
45562
+ const limit = numericFlag(args, "--limit", 200);
45563
+ const before = stringFlag(args, "--before");
45564
+ const store = new FileSessionStore(getSessionsDir());
45565
+ const data = await store.load(sessionId);
45566
+ if (!data) throw new Error(`Session not found: ${sessionId}`);
45567
+ const events = activeTranscriptEvents(activePathEntries(data));
45568
+ const end = resolveBeforeCursor(events, before);
45569
+ const start = Math.max(0, end - limit);
45570
+ const page = events.slice(start, end);
45571
+ const response = {
45572
+ ok: true,
45573
+ session: sessionSummary(data.metadata),
45574
+ currentHead: data.metadata.activeEntryId,
45575
+ activeEntryId: data.metadata.activeEntryId,
45576
+ events: json && !includeMessage ? page.map(stableTranscriptEvent) : page,
45577
+ hasMoreBefore: start > 0,
45578
+ nextBefore: start > 0 ? String(start) : void 0
45579
+ };
45580
+ if (json) {
45581
+ console.log(JSON.stringify(response, null, 2));
45582
+ return;
45583
+ }
45584
+ console.log(`${response.session.id}: ${response.session.name}`);
45585
+ for (const entry of page) {
45586
+ console.log(`${entry.logicalSeq} ${entry.type}${entry.role ? `:${entry.role}` : ""} ${entry.content ?? ""}`);
45587
+ }
45588
+ }
45589
+ async function renameSession(args) {
45590
+ const json = hasFlag(args, "--json");
45591
+ const cwd = stringFlag(args, "--cwd");
45592
+ const positionals = positionalArgs(args, /* @__PURE__ */ new Set(["--cwd"]));
45593
+ const sessionId = positionals[0];
45594
+ const name = positionals.slice(1).join(" ").trim();
45595
+ if (!sessionId || !name) throw new Error("Usage: pie sessions rename <sessionId> <name> [--json] [--cwd <path>]");
45596
+ const store = new FileSessionStore(getSessionsDir());
45597
+ const data = await store.load(sessionId);
45598
+ if (!data) throw new Error(`Session not found: ${sessionId}`);
45599
+ await store.save(sessionId, data.entries, { ...data.metadata, name, ...cwd ? { cwd } : {}, updatedAt: Date.now() });
45600
+ const updated = await store.getMetadata(sessionId);
45601
+ if (!updated) throw new Error(`Session not found after rename: ${sessionId}`);
45602
+ const response = { ok: true, session: sessionSummary(updated) };
45603
+ if (json) {
45604
+ console.log(JSON.stringify(response, null, 2));
45605
+ return;
45606
+ }
45607
+ console.log(`Renamed ${sessionId} to "${name}".`);
45608
+ }
45609
+ async function rewindSession(args) {
45610
+ const json = hasFlag(args, "--json");
45611
+ const sessionId = positionalArgs(args, /* @__PURE__ */ new Set(["--to"]))[0];
45612
+ const entryId = stringFlag(args, "--to");
45613
+ if (!sessionId || !entryId) throw new Error("Usage: pie sessions rewind <sessionId> --to <entryId> [--json]");
45614
+ const store = new FileSessionStore(getSessionsDir());
45615
+ const data = await store.load(sessionId);
45616
+ if (!data) throw new Error(`Session not found: ${sessionId}`);
45617
+ if (!data.entries.some((entry) => entry.id === entryId)) throw new Error(`Entry not found: ${entryId}`);
45618
+ await store.save(sessionId, data.entries, { ...data.metadata, activeEntryId: entryId, updatedAt: Date.now() });
45619
+ const updated = await store.getMetadata(sessionId);
45620
+ if (!updated) throw new Error(`Session not found after rewind: ${sessionId}`);
45621
+ const response = {
45622
+ ok: true,
45623
+ session: sessionSummary(updated),
45624
+ activeEntryId: entryId,
45625
+ currentHead: entryId
45626
+ };
45627
+ if (json) {
45628
+ console.log(JSON.stringify(response, null, 2));
45629
+ return;
45630
+ }
45631
+ console.log(`Rewound ${sessionId} to ${entryId}.`);
45632
+ }
45633
+ async function forkSession(args) {
45634
+ const json = hasFlag(args, "--json");
45635
+ const sourceSessionId = positionalArgs(args, /* @__PURE__ */ new Set(["--from", "--target", "--name", "--cwd"]))[0];
45636
+ const sourceEntryId = stringFlag(args, "--from");
45637
+ const targetSessionId = stringFlag(args, "--target");
45638
+ const name = stringFlag(args, "--name");
45639
+ const cwd = stringFlag(args, "--cwd");
45640
+ if (!sourceSessionId || !sourceEntryId || !targetSessionId || !name) {
45641
+ throw new Error("Usage: pie sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--json]");
45642
+ }
45643
+ const store = new FileSessionStore(getSessionsDir());
45644
+ const source = await store.load(sourceSessionId);
45645
+ if (!source) throw new Error(`Session not found: ${sourceSessionId}`);
45646
+ if (await store.exists(targetSessionId)) throw new Error(`Target session already exists: ${targetSessionId}`);
45647
+ const pathEntries = pathToEntry(source, sourceEntryId);
45648
+ if (pathEntries.length === 0 || pathEntries[pathEntries.length - 1]?.id !== sourceEntryId) {
45649
+ throw new Error(`Entry not found: ${sourceEntryId}`);
45650
+ }
45651
+ const now = Date.now();
45652
+ const idMap = /* @__PURE__ */ new Map();
45653
+ for (const entry of pathEntries) idMap.set(entry.id, generateEntryId());
45654
+ const forkedEntries = pathEntries.map((entry) => {
45655
+ const nextId = idMap.get(entry.id);
45656
+ if (!nextId) throw new Error(`Failed to map entry: ${entry.id}`);
45657
+ const parentId = entry.parentId ? idMap.get(entry.parentId) ?? null : null;
45658
+ return {
45659
+ ...cloneJson(entry),
45660
+ id: nextId,
45661
+ parentId,
45662
+ timestamp: entry.timestamp
45663
+ };
45664
+ });
45665
+ const activeEntryId = idMap.get(sourceEntryId) ?? null;
45666
+ await store.save(targetSessionId, forkedEntries, {
45667
+ name,
45668
+ createdAt: now,
45669
+ updatedAt: now,
45670
+ activeEntryId,
45671
+ cwd: cwd ?? source.metadata.cwd,
45672
+ sourceSessionId,
45673
+ sourceEntryId,
45674
+ sourceActiveEntryId: source.metadata.activeEntryId ?? void 0,
45675
+ forkBaseEntryId: activeEntryId ?? void 0
45676
+ });
45677
+ const updated = await store.getMetadata(targetSessionId);
45678
+ if (!updated) throw new Error(`Session not found after fork: ${targetSessionId}`);
45679
+ const response = {
45680
+ ok: true,
45681
+ session: sessionSummary(updated),
45682
+ sourceSessionId,
45683
+ sourceEntryId,
45684
+ sourceActiveEntryId: source.metadata.activeEntryId,
45685
+ forkBaseEntryId: activeEntryId,
45686
+ activeEntryId,
45687
+ currentHead: activeEntryId
45688
+ };
45689
+ if (json) {
45690
+ console.log(JSON.stringify(response, null, 2));
45691
+ return;
45692
+ }
45693
+ console.log(`Forked ${sourceSessionId} at ${sourceEntryId} into ${targetSessionId}.`);
45694
+ }
45695
+ function printSessionsUsage() {
45696
+ console.log(`Usage:
45697
+ pie sessions list [--json] [--limit <n>] [--cursor <cursor>] [--cwd <path>]
45698
+ pie sessions read <sessionId> [--json] [--raw|--include-message] [--limit <n>] [--before <cursor>]
45699
+ pie sessions rename <sessionId> <name> [--json] [--cwd <path>]
45700
+ pie sessions rewind <sessionId> --to <entryId> [--json]
45701
+ pie sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--json]`);
45702
+ }
45703
+ function hasFlag(args, flag) {
45704
+ return args.includes(flag);
45705
+ }
45706
+ function stringFlag(args, flag) {
45707
+ const index = args.indexOf(flag);
45708
+ if (index < 0) return void 0;
45709
+ const value = args[index + 1];
45710
+ return value && !value.startsWith("-") ? value : void 0;
45711
+ }
45712
+ function numericFlag(args, flag, fallback) {
45713
+ const index = args.indexOf(flag);
45714
+ if (index < 0) return fallback;
45715
+ const value = args[index + 1];
45716
+ if (!value) throw new Error(`${flag} requires a value.`);
45717
+ const parsed = Number(value);
45718
+ const max = 1e3;
45719
+ if (!Number.isInteger(parsed) || parsed <= 0 || parsed > max) {
45720
+ throw new Error(`${flag} must be a positive integer no greater than ${max}.`);
45721
+ }
45722
+ return parsed;
45723
+ }
45724
+ function positionalArgs(args, valueFlags) {
45725
+ const result = [];
45726
+ for (let index = 0; index < args.length; index += 1) {
45727
+ const arg = args[index];
45728
+ if (arg.startsWith("--")) {
45729
+ if (valueFlags.has(arg)) index += 1;
45730
+ continue;
45731
+ }
45732
+ result.push(arg);
45733
+ }
45734
+ return result;
45735
+ }
45736
+ function sessionSummary(metadata) {
45737
+ return {
45738
+ id: metadata.id,
45739
+ name: metadata.name,
45740
+ createdAt: metadata.createdAt,
45741
+ updatedAt: metadata.updatedAt,
45742
+ cwd: typeof metadata.cwd === "string" ? metadata.cwd : void 0,
45743
+ entryCount: metadata.entryCount,
45744
+ messageCount: metadata.messageCount,
45745
+ activeEntryId: metadata.activeEntryId,
45746
+ rootEntryId: metadata.rootEntryId,
45747
+ sourceSessionId: typeof metadata.sourceSessionId === "string" ? metadata.sourceSessionId : void 0,
45748
+ sourceEntryId: typeof metadata.sourceEntryId === "string" ? metadata.sourceEntryId : void 0,
45749
+ sourceActiveEntryId: typeof metadata.sourceActiveEntryId === "string" ? metadata.sourceActiveEntryId : void 0,
45750
+ forkBaseEntryId: typeof metadata.forkBaseEntryId === "string" ? metadata.forkBaseEntryId : void 0
45751
+ };
45752
+ }
45753
+ function cwdMatches(sessionCwd, requestedCwd) {
45754
+ if (!sessionCwd) return false;
45755
+ if (sessionCwd === requestedCwd) return true;
45756
+ return realpathOrInput(sessionCwd) === realpathOrInput(requestedCwd);
45757
+ }
45758
+ function realpathOrInput(value) {
45759
+ try {
45760
+ return fs6.realpathSync.native(value);
45761
+ } catch {
45762
+ return value;
45763
+ }
45764
+ }
45765
+ function activeTranscriptEvents(entries) {
45766
+ return entries.map((entry, index) => {
45767
+ const role = isRecord2(entry.message) && typeof entry.message.role === "string" ? entry.message.role : void 0;
45768
+ const turnId = isRecord2(entry.message) && typeof entry.message.turnId === "string" ? entry.message.turnId : void 0;
45769
+ return {
45770
+ logicalSeq: index + 1,
45771
+ checkpointId: entry.id,
45772
+ entryId: entry.id,
45773
+ id: entry.id,
45774
+ type: entry.type,
45775
+ timestamp: entry.timestamp,
45776
+ occurredAt: entry.timestamp,
45777
+ role,
45778
+ turnId,
45779
+ content: textFromMessage(entry.message),
45780
+ message: entry.message ? cloneJson(entry.message) : void 0
45781
+ };
45782
+ });
45783
+ }
45784
+ function stableTranscriptEvent(event) {
45785
+ return {
45786
+ logicalSeq: event.logicalSeq,
45787
+ checkpointId: event.checkpointId,
45788
+ entryId: event.entryId,
45789
+ id: event.id,
45790
+ type: event.type,
45791
+ timestamp: event.timestamp,
45792
+ occurredAt: event.occurredAt,
45793
+ ...event.role ? { role: event.role } : {},
45794
+ ...event.turnId ? { turnId: event.turnId } : {},
45795
+ ...event.content ? { content: event.content } : {}
45796
+ };
45797
+ }
45798
+ function activePathEntries(data) {
45799
+ const activeEntryId = data.metadata.activeEntryId;
45800
+ if (!activeEntryId) return [];
45801
+ return pathToEntry(data, activeEntryId);
45802
+ }
45803
+ function pathToEntry(data, entryId) {
45804
+ const byId = new Map(data.entries.map((entry) => [entry.id, entry]));
45805
+ const path27 = [];
45806
+ let current = entryId;
45807
+ while (current) {
45808
+ const entry = byId.get(current);
45809
+ if (!entry) return [];
45810
+ path27.unshift(entry);
45811
+ current = entry.parentId;
45812
+ }
45813
+ return path27;
45814
+ }
45815
+ function resolveBeforeCursor(events, cursor) {
45816
+ if (!cursor) return events.length;
45817
+ const numeric = Number(cursor);
45818
+ if (Number.isInteger(numeric) && numeric >= 0) {
45819
+ return Math.max(0, Math.min(events.length, numeric));
45820
+ }
45821
+ const index = events.findIndex((event) => event.entryId === cursor || event.checkpointId === cursor);
45822
+ return index >= 0 ? index : events.length;
45823
+ }
45824
+ function cloneJson(value) {
45825
+ return JSON.parse(JSON.stringify(value));
45826
+ }
45827
+ function listCursorQueryKey(input) {
45828
+ return JSON.stringify({ cwd: input.cwd ? realpathOrInput(input.cwd) : "" });
45829
+ }
45830
+ function encodeListCursor(state) {
45831
+ return `list:${Buffer.from(JSON.stringify(state), "utf8").toString("base64url")}`;
45832
+ }
45833
+ function decodeListCursor(cursor) {
45834
+ if (!cursor?.startsWith("list:")) return { v: 2 };
45835
+ try {
45836
+ const parsed = JSON.parse(Buffer.from(cursor.slice("list:".length), "base64url").toString("utf8"));
45837
+ if (!isRecord2(parsed) || parsed.v !== 2) return { v: 2 };
45838
+ 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;
45839
+ return {
45840
+ v: 2,
45841
+ q: typeof parsed.q === "string" ? parsed.q : void 0,
45842
+ ...after ? { after } : {}
45843
+ };
45844
+ } catch {
45845
+ return { v: 2 };
45846
+ }
45847
+ }
45848
+ function textFromMessage(message) {
45849
+ if (!isRecord2(message)) return void 0;
45850
+ const content = message.content;
45851
+ if (typeof content === "string") return content;
45852
+ if (!Array.isArray(content)) return void 0;
45853
+ const text = content.map((block) => isRecord2(block) && block.type === "text" && typeof block.text === "string" ? block.text : "").filter(Boolean).join("\n").trim();
45854
+ return text || void 0;
45855
+ }
45856
+ function isRecord2(value) {
45857
+ return !!value && typeof value === "object" && !Array.isArray(value);
45858
+ }
45859
+
45484
45860
  // ../../packages/tui/src/fuzzy.ts
45485
45861
  function fuzzyMatch(query, text) {
45486
45862
  const queryLower = query.toLowerCase();
@@ -47031,7 +47407,7 @@ var KillRing = class {
47031
47407
  };
47032
47408
 
47033
47409
  // ../../packages/tui/src/tui.ts
47034
- import * as fs6 from "node:fs";
47410
+ import * as fs7 from "node:fs";
47035
47411
  import * as os2 from "node:os";
47036
47412
  import * as path5 from "node:path";
47037
47413
 
@@ -47710,10 +48086,10 @@ var TUI = class extends Container {
47710
48086
  const logRedraw = (reason) => {
47711
48087
  if (!debugRedraw) return;
47712
48088
  const logPath = path5.join(os2.homedir(), ".pie", "logs", "pie-cli.log");
47713
- fs6.mkdirSync(path5.dirname(logPath), { recursive: true });
48089
+ fs7.mkdirSync(path5.dirname(logPath), { recursive: true });
47714
48090
  const msg = `[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] [ui] fullRender: ${reason} (prev=${this.previousLines.length}, new=${newLines.length}, height=${height})
47715
48091
  `;
47716
- fs6.appendFileSync(logPath, msg);
48092
+ fs7.appendFileSync(logPath, msg);
47717
48093
  };
47718
48094
  if (this.previousLines.length === 0 && !widthChanged) {
47719
48095
  logRedraw("first render");
@@ -47816,8 +48192,8 @@ var TUI = class extends Container {
47816
48192
  ...newLines.map((l, idx) => `[${idx}] (w=${visibleWidth(l)}) ${l}`),
47817
48193
  ""
47818
48194
  ].join("\n");
47819
- fs6.mkdirSync(path5.dirname(crashLogPath), { recursive: true });
47820
- fs6.writeFileSync(crashLogPath, crashData);
48195
+ fs7.mkdirSync(path5.dirname(crashLogPath), { recursive: true });
48196
+ fs7.writeFileSync(crashLogPath, crashData);
47821
48197
  this.stop();
47822
48198
  const errorMsg = [
47823
48199
  `Rendered line ${i} exceeds terminal width (${visibleWidth(line)} > ${width}).`,
@@ -47847,7 +48223,7 @@ var TUI = class extends Container {
47847
48223
  buffer += "\x1B[?2026l";
47848
48224
  if (process.env.PIE_TUI_DEBUG === "1") {
47849
48225
  const debugDir = "/tmp/tui";
47850
- fs6.mkdirSync(debugDir, { recursive: true });
48226
+ fs7.mkdirSync(debugDir, { recursive: true });
47851
48227
  const debugPath = path5.join(debugDir, `render-${Date.now()}-${Math.random().toString(36).slice(2)}.log`);
47852
48228
  const debugData = [
47853
48229
  `firstChanged: ${firstChanged}`,
@@ -47871,7 +48247,7 @@ var TUI = class extends Container {
47871
48247
  "=== buffer ===",
47872
48248
  JSON.stringify(buffer)
47873
48249
  ].join("\n");
47874
- fs6.writeFileSync(debugPath, debugData);
48250
+ fs7.writeFileSync(debugPath, debugData);
47875
48251
  }
47876
48252
  this.terminal.write(buffer);
47877
48253
  this.cursorRow = Math.max(0, newLines.length - 1);
@@ -52046,7 +52422,7 @@ var StdinBuffer = class extends EventEmitter {
52046
52422
  };
52047
52423
 
52048
52424
  // ../../packages/tui/src/terminal.ts
52049
- import * as fs7 from "node:fs";
52425
+ import * as fs8 from "node:fs";
52050
52426
  import koffi from "koffi";
52051
52427
  var ProcessTerminal = class {
52052
52428
  wasRaw = false;
@@ -52207,7 +52583,7 @@ var ProcessTerminal = class {
52207
52583
  process.stdout.write(data);
52208
52584
  if (this.writeLogPath) {
52209
52585
  try {
52210
- fs7.appendFileSync(this.writeLogPath, data, { encoding: "utf8" });
52586
+ fs8.appendFileSync(this.writeLogPath, data, { encoding: "utf8" });
52211
52587
  } catch {
52212
52588
  }
52213
52589
  }
@@ -52379,7 +52755,7 @@ var KeybindingsManager = class _KeybindingsManager {
52379
52755
  };
52380
52756
 
52381
52757
  // src/project-knowledge.ts
52382
- import fs8 from "node:fs";
52758
+ import fs9 from "node:fs";
52383
52759
  import path6 from "node:path";
52384
52760
  function collectAncestorAgentsFiles(cwd) {
52385
52761
  const resolvedCwd = path6.resolve(cwd || process.cwd());
@@ -52399,13 +52775,13 @@ function collectAncestorAgentsFiles(cwd) {
52399
52775
  }
52400
52776
  const files = [];
52401
52777
  for (const candidate of candidates) {
52402
- if (!fs8.existsSync(candidate)) {
52778
+ if (!fs9.existsSync(candidate)) {
52403
52779
  continue;
52404
52780
  }
52405
52781
  try {
52406
52782
  files.push({
52407
52783
  path: path6.relative(resolvedCwd, candidate) || AGENTS_CONTEXT_FILE_NAME,
52408
- content: fs8.readFileSync(candidate, "utf-8")
52784
+ content: fs9.readFileSync(candidate, "utf-8")
52409
52785
  });
52410
52786
  } catch {
52411
52787
  }
@@ -52443,7 +52819,7 @@ function buildCliFileAccessOptions(params) {
52443
52819
  }
52444
52820
 
52445
52821
  // src/theme/theme.ts
52446
- import * as fs9 from "node:fs";
52822
+ import * as fs10 from "node:fs";
52447
52823
  import * as path8 from "node:path";
52448
52824
 
52449
52825
  // ../../node_modules/@sinclair/typebox/build/esm/compiler/compiler.mjs
@@ -53334,8 +53710,8 @@ function getBuiltinThemes() {
53334
53710
  const darkPath = path8.join(themesDir, "dark.json");
53335
53711
  const lightPath = path8.join(themesDir, "light.json");
53336
53712
  BUILTIN_THEMES = {
53337
- dark: JSON.parse(fs9.readFileSync(darkPath, "utf-8")),
53338
- light: JSON.parse(fs9.readFileSync(lightPath, "utf-8"))
53713
+ dark: JSON.parse(fs10.readFileSync(darkPath, "utf-8")),
53714
+ light: JSON.parse(fs10.readFileSync(lightPath, "utf-8"))
53339
53715
  };
53340
53716
  }
53341
53717
  return BUILTIN_THEMES;
@@ -53343,8 +53719,8 @@ function getBuiltinThemes() {
53343
53719
  function getAvailableThemes() {
53344
53720
  const themes = new Set(Object.keys(getBuiltinThemes()));
53345
53721
  const customThemesDir = getCustomThemesDir();
53346
- if (fs9.existsSync(customThemesDir)) {
53347
- const files = fs9.readdirSync(customThemesDir);
53722
+ if (fs10.existsSync(customThemesDir)) {
53723
+ const files = fs10.readdirSync(customThemesDir);
53348
53724
  for (const file of files) {
53349
53725
  if (file.endsWith(".json")) {
53350
53726
  themes.add(file.slice(0, -5));
@@ -53405,7 +53781,7 @@ function loadThemeJson(name) {
53405
53781
  }
53406
53782
  const registeredTheme = registeredThemes.get(name);
53407
53783
  if (registeredTheme?.sourcePath) {
53408
- const content2 = fs9.readFileSync(registeredTheme.sourcePath, "utf-8");
53784
+ const content2 = fs10.readFileSync(registeredTheme.sourcePath, "utf-8");
53409
53785
  return parseThemeJsonContent(registeredTheme.sourcePath, content2);
53410
53786
  }
53411
53787
  if (registeredTheme) {
@@ -53413,10 +53789,10 @@ function loadThemeJson(name) {
53413
53789
  }
53414
53790
  const customThemesDir = getCustomThemesDir();
53415
53791
  const themePath = path8.join(customThemesDir, `${name}.json`);
53416
- if (!fs9.existsSync(themePath)) {
53792
+ if (!fs10.existsSync(themePath)) {
53417
53793
  throw new Error(`Theme not found: ${name}`);
53418
53794
  }
53419
- const content = fs9.readFileSync(themePath, "utf-8");
53795
+ const content = fs10.readFileSync(themePath, "utf-8");
53420
53796
  return parseThemeJsonContent(name, content);
53421
53797
  }
53422
53798
  function createTheme(themeJson, mode, sourcePath) {
@@ -53530,11 +53906,11 @@ function startThemeWatcher() {
53530
53906
  }
53531
53907
  const customThemesDir = getCustomThemesDir();
53532
53908
  const themeFile = path8.join(customThemesDir, `${currentThemeName}.json`);
53533
- if (!fs9.existsSync(themeFile)) {
53909
+ if (!fs10.existsSync(themeFile)) {
53534
53910
  return;
53535
53911
  }
53536
53912
  try {
53537
- themeWatcher = fs9.watch(themeFile, (eventType) => {
53913
+ themeWatcher = fs10.watch(themeFile, (eventType) => {
53538
53914
  if (eventType === "change") {
53539
53915
  setTimeout(() => {
53540
53916
  try {
@@ -53547,7 +53923,7 @@ function startThemeWatcher() {
53547
53923
  }, 100);
53548
53924
  } else if (eventType === "rename") {
53549
53925
  setTimeout(() => {
53550
- if (!fs9.existsSync(themeFile)) {
53926
+ if (!fs10.existsSync(themeFile)) {
53551
53927
  currentThemeName = "dark";
53552
53928
  setGlobalTheme(loadTheme("dark"));
53553
53929
  if (themeWatcher) {
@@ -53718,7 +54094,7 @@ function getEditorTheme() {
53718
54094
  }
53719
54095
 
53720
54096
  // src/skills/loader.ts
53721
- import * as fs10 from "fs";
54097
+ import * as fs11 from "fs";
53722
54098
  import * as path9 from "path";
53723
54099
  function parseSkillDescription(content) {
53724
54100
  const frontmatterMatch = content.match(/^---\n[\s\S]*?description:\s*["']?(.+?)["']?(?:\n|$)/m);
@@ -53737,18 +54113,18 @@ function parseSkillDescription(content) {
53737
54113
  function loadSkillsFromDir(dir, source) {
53738
54114
  const skills = [];
53739
54115
  const diagnostics = [];
53740
- if (!fs10.existsSync(dir)) {
54116
+ if (!fs11.existsSync(dir)) {
53741
54117
  return { skills, diagnostics };
53742
54118
  }
53743
- const entries = fs10.readdirSync(dir, { withFileTypes: true });
54119
+ const entries = fs11.readdirSync(dir, { withFileTypes: true });
53744
54120
  for (const entry of entries) {
53745
54121
  if (entry.name.startsWith(".")) continue;
53746
54122
  const fullPath = path9.join(dir, entry.name);
53747
54123
  if (entry.isDirectory()) {
53748
54124
  const skillMdPath = path9.join(fullPath, "SKILL.md");
53749
- if (fs10.existsSync(skillMdPath)) {
54125
+ if (fs11.existsSync(skillMdPath)) {
53750
54126
  try {
53751
- const content = fs10.readFileSync(skillMdPath, "utf-8");
54127
+ const content = fs11.readFileSync(skillMdPath, "utf-8");
53752
54128
  const description = parseSkillDescription(content);
53753
54129
  skills.push({
53754
54130
  name: entry.name,
@@ -53769,7 +54145,7 @@ function loadSkillsFromDir(dir, source) {
53769
54145
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
53770
54146
  const name = entry.name.slice(0, -3);
53771
54147
  try {
53772
- const content = fs10.readFileSync(fullPath, "utf-8");
54148
+ const content = fs11.readFileSync(fullPath, "utf-8");
53773
54149
  const description = parseSkillDescription(content);
53774
54150
  skills.push({
53775
54151
  name,
@@ -53966,7 +54342,7 @@ function validateSkillName(name) {
53966
54342
 
53967
54343
  // src/capabilities/read-file-understanding.ts
53968
54344
  import * as path18 from "node:path";
53969
- import * as fs18 from "node:fs/promises";
54345
+ import * as fs19 from "node:fs/promises";
53970
54346
 
53971
54347
  // src/core/provider-capabilities.ts
53972
54348
  var PLATFORM_DISPLAY_NAMES = {
@@ -53992,7 +54368,7 @@ function getProviderDisplayName(platform2) {
53992
54368
  }
53993
54369
 
53994
54370
  // src/files/adapters/kimi-adapter.ts
53995
- import * as fs11 from "node:fs";
54371
+ import * as fs12 from "node:fs";
53996
54372
  import * as path10 from "node:path";
53997
54373
 
53998
54374
  // src/files/errors.ts
@@ -54133,14 +54509,14 @@ var KimiFileAdapter = class {
54133
54509
  const fileName = options.sourceName || path10.basename(filePath);
54134
54510
  const mimeType = options.mimeType || this.guessMimeType(fileName);
54135
54511
  const purpose = this.detectPurpose(filePath, options.purpose, mimeType);
54136
- const stats = fs11.statSync(filePath);
54512
+ const stats = fs12.statSync(filePath);
54137
54513
  if (stats.size > this.capabilities.maxFileSize) {
54138
54514
  throw new FileManagerError(
54139
54515
  "FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
54140
54516
  `File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds Kimi limit of 100MB`
54141
54517
  );
54142
54518
  }
54143
- const fileBuffer = fs11.readFileSync(filePath);
54519
+ const fileBuffer = fs12.readFileSync(filePath);
54144
54520
  const file = new File([fileBuffer], fileName, { type: mimeType });
54145
54521
  const formData = new FormData();
54146
54522
  formData.append("file", file);
@@ -54354,7 +54730,7 @@ var KimiFileAdapter = class {
54354
54730
  };
54355
54731
 
54356
54732
  // src/files/adapters/gemini-adapter.ts
54357
- import * as fs12 from "node:fs";
54733
+ import * as fs13 from "node:fs";
54358
54734
  import * as path11 from "node:path";
54359
54735
  import { Readable } from "node:stream";
54360
54736
  var GeminiFileAdapter = class {
@@ -54412,7 +54788,7 @@ var GeminiFileAdapter = class {
54412
54788
  // Upload
54413
54789
  // ============================================================================
54414
54790
  async upload(filePath, options = {}) {
54415
- const stats = fs12.statSync(filePath);
54791
+ const stats = fs13.statSync(filePath);
54416
54792
  if (stats.size > this.capabilities.maxFileSize) {
54417
54793
  throw new FileManagerError(
54418
54794
  "FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
@@ -54451,7 +54827,7 @@ var GeminiFileAdapter = class {
54451
54827
  "No upload URL received"
54452
54828
  );
54453
54829
  }
54454
- const fileStream = Readable.toWeb(fs12.createReadStream(filePath));
54830
+ const fileStream = Readable.toWeb(fs13.createReadStream(filePath));
54455
54831
  const uploadResponse = await fetch(uploadUrl, {
54456
54832
  method: "POST",
54457
54833
  headers: {
@@ -54655,7 +55031,7 @@ var GeminiFileAdapter = class {
54655
55031
  };
54656
55032
 
54657
55033
  // src/files/adapters/openai-compatible-files-adapter.ts
54658
- import * as fs13 from "node:fs";
55034
+ import * as fs14 from "node:fs";
54659
55035
  import * as path12 from "node:path";
54660
55036
  var OpenAICompatibleFilesAdapter = class {
54661
55037
  constructor(apiKey, baseUrl, extraHeaders = {}) {
@@ -54684,14 +55060,14 @@ var OpenAICompatibleFilesAdapter = class {
54684
55060
  async upload(filePath, options = {}) {
54685
55061
  const fileName = options.sourceName || path12.basename(filePath);
54686
55062
  const mimeType = options.mimeType || guessMimeType(fileName);
54687
- const stats = fs13.statSync(filePath);
55063
+ const stats = fs14.statSync(filePath);
54688
55064
  if (stats.size > this.capabilities.maxFileSize) {
54689
55065
  throw new FileManagerError(
54690
55066
  "FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
54691
55067
  `File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds OpenAI-compatible Files limit of ${this.capabilities.maxFileSize / 1024 / 1024}MB`
54692
55068
  );
54693
55069
  }
54694
- const file = new File([fs13.readFileSync(filePath)], fileName, { type: mimeType });
55070
+ const file = new File([fs14.readFileSync(filePath)], fileName, { type: mimeType });
54695
55071
  const formData = new FormData();
54696
55072
  formData.append("file", file);
54697
55073
  formData.append("purpose", options.purpose && options.purpose !== "auto" ? options.purpose : "file-extract");
@@ -54824,12 +55200,12 @@ function guessMimeType(filename) {
54824
55200
  }
54825
55201
 
54826
55202
  // src/files/file-manager.ts
54827
- import * as fs17 from "node:fs";
55203
+ import * as fs18 from "node:fs";
54828
55204
  import * as path17 from "node:path";
54829
55205
  import * as crypto2 from "node:crypto";
54830
55206
 
54831
55207
  // src/files/file-cache.ts
54832
- import * as fs14 from "node:fs";
55208
+ import * as fs15 from "node:fs";
54833
55209
  import * as path14 from "node:path";
54834
55210
  import * as crypto from "node:crypto";
54835
55211
 
@@ -54990,22 +55366,22 @@ var FileCache = class _FileCache {
54990
55366
  // Directory Management
54991
55367
  // ============================================================================
54992
55368
  ensureDirectories() {
54993
- if (!fs14.existsSync(this.baseDir)) {
54994
- fs14.mkdirSync(this.baseDir, { recursive: true });
55369
+ if (!fs15.existsSync(this.baseDir)) {
55370
+ fs15.mkdirSync(this.baseDir, { recursive: true });
54995
55371
  }
54996
- if (!fs14.existsSync(this.dataDir)) {
54997
- fs14.mkdirSync(this.dataDir, { recursive: true });
55372
+ if (!fs15.existsSync(this.dataDir)) {
55373
+ fs15.mkdirSync(this.dataDir, { recursive: true });
54998
55374
  }
54999
55375
  }
55000
55376
  // ============================================================================
55001
55377
  // Index Management
55002
55378
  // ============================================================================
55003
55379
  loadIndex() {
55004
- if (!fs14.existsSync(this.indexPath)) {
55380
+ if (!fs15.existsSync(this.indexPath)) {
55005
55381
  return { version: CACHE_VERSION, files: {}, pathHints: {} };
55006
55382
  }
55007
55383
  try {
55008
- const data = JSON.parse(fs14.readFileSync(this.indexPath, "utf-8"));
55384
+ const data = JSON.parse(fs15.readFileSync(this.indexPath, "utf-8"));
55009
55385
  if (data.version !== CACHE_VERSION) {
55010
55386
  cacheLogger.warn(`Index version mismatch: ${data.version} vs ${CACHE_VERSION}`);
55011
55387
  }
@@ -55021,7 +55397,7 @@ var FileCache = class _FileCache {
55021
55397
  }
55022
55398
  saveIndex() {
55023
55399
  try {
55024
- fs14.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
55400
+ fs15.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
55025
55401
  } catch (err) {
55026
55402
  cacheLogger.error(" Failed to save index:", err);
55027
55403
  throw err;
@@ -55033,7 +55409,7 @@ var FileCache = class _FileCache {
55033
55409
  async computeHash(filePath) {
55034
55410
  return new Promise((resolve4, reject) => {
55035
55411
  const hash = crypto.createHash("sha256");
55036
- const stream = fs14.createReadStream(filePath);
55412
+ const stream = fs15.createReadStream(filePath);
55037
55413
  stream.on("data", (chunk) => hash.update(chunk));
55038
55414
  stream.on("end", () => resolve4(hash.digest("hex")));
55039
55415
  stream.on("error", reject);
@@ -55048,8 +55424,8 @@ var FileCache = class _FileCache {
55048
55424
  getStoragePath(hash) {
55049
55425
  const subdir = hash.slice(0, 2);
55050
55426
  const fullDir = path14.join(this.dataDir, subdir);
55051
- if (!fs14.existsSync(fullDir)) {
55052
- fs14.mkdirSync(fullDir, { recursive: true });
55427
+ if (!fs15.existsSync(fullDir)) {
55428
+ fs15.mkdirSync(fullDir, { recursive: true });
55053
55429
  }
55054
55430
  return path14.join(fullDir, hash);
55055
55431
  }
@@ -55061,11 +55437,11 @@ var FileCache = class _FileCache {
55061
55437
  const hash = await this.computeHash(sourcePath);
55062
55438
  const storagePath = this.getStoragePath(hash);
55063
55439
  this.rememberPathHint(sourcePath, hash, name);
55064
- if (fs14.existsSync(storagePath)) {
55440
+ if (fs15.existsSync(storagePath)) {
55065
55441
  return { hash, localPath: storagePath };
55066
55442
  }
55067
- fs14.copyFileSync(sourcePath, storagePath);
55068
- const stat2 = fs14.statSync(storagePath);
55443
+ fs15.copyFileSync(sourcePath, storagePath);
55444
+ const stat2 = fs15.statSync(storagePath);
55069
55445
  this.index.files[hash] = {
55070
55446
  hash,
55071
55447
  name,
@@ -55082,10 +55458,10 @@ var FileCache = class _FileCache {
55082
55458
  async storeBuffer(data, name, mimeType) {
55083
55459
  const hash = this.computeHashSync(data);
55084
55460
  const storagePath = this.getStoragePath(hash);
55085
- if (fs14.existsSync(storagePath)) {
55461
+ if (fs15.existsSync(storagePath)) {
55086
55462
  return { hash, localPath: storagePath };
55087
55463
  }
55088
- fs14.writeFileSync(storagePath, data);
55464
+ fs15.writeFileSync(storagePath, data);
55089
55465
  this.index.files[hash] = {
55090
55466
  hash,
55091
55467
  name,
@@ -55157,7 +55533,7 @@ var FileCache = class _FileCache {
55157
55533
  getPathHint(filePath) {
55158
55534
  try {
55159
55535
  const resolvedPath = this.getResolvedHintPath(filePath);
55160
- const stat2 = fs14.statSync(resolvedPath);
55536
+ const stat2 = fs15.statSync(resolvedPath);
55161
55537
  if (!stat2.isFile()) return void 0;
55162
55538
  const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
55163
55539
  const key = this.getPathHintKey(resolvedPath);
@@ -55187,7 +55563,7 @@ var FileCache = class _FileCache {
55187
55563
  rememberPathHint(filePath, hash, name) {
55188
55564
  try {
55189
55565
  const resolvedPath = this.getResolvedHintPath(filePath);
55190
- const stat2 = fs14.statSync(resolvedPath);
55566
+ const stat2 = fs15.statSync(resolvedPath);
55191
55567
  if (!stat2.isFile()) return;
55192
55568
  const entry = this.index.files[hash];
55193
55569
  const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
@@ -55246,8 +55622,8 @@ var FileCache = class _FileCache {
55246
55622
  entry = entry || this.index.files[hash];
55247
55623
  if (!entry) return;
55248
55624
  const localPath = path14.join(this.dataDir, entry.localPath);
55249
- if (fs14.existsSync(localPath)) {
55250
- fs14.unlinkSync(localPath);
55625
+ if (fs15.existsSync(localPath)) {
55626
+ fs15.unlinkSync(localPath);
55251
55627
  }
55252
55628
  delete this.index.files[hash];
55253
55629
  if (this.index.pathHints) {
@@ -55262,8 +55638,8 @@ var FileCache = class _FileCache {
55262
55638
  clear() {
55263
55639
  for (const entry of Object.values(this.index.files)) {
55264
55640
  const localPath = path14.join(this.dataDir, entry.localPath);
55265
- if (fs14.existsSync(localPath)) {
55266
- fs14.unlinkSync(localPath);
55641
+ if (fs15.existsSync(localPath)) {
55642
+ fs15.unlinkSync(localPath);
55267
55643
  }
55268
55644
  }
55269
55645
  this.index = { version: CACHE_VERSION, files: {}, pathHints: {} };
@@ -55351,7 +55727,7 @@ var FileCache = class _FileCache {
55351
55727
  getResolvedHintPath(filePath) {
55352
55728
  const resolvedPath = resolvePath(filePath);
55353
55729
  try {
55354
- return fs14.realpathSync.native ? fs14.realpathSync.native(resolvedPath) : fs14.realpathSync(resolvedPath);
55730
+ return fs15.realpathSync.native ? fs15.realpathSync.native(resolvedPath) : fs15.realpathSync(resolvedPath);
55355
55731
  } catch {
55356
55732
  return resolvedPath;
55357
55733
  }
@@ -55359,7 +55735,7 @@ var FileCache = class _FileCache {
55359
55735
  };
55360
55736
 
55361
55737
  // src/files/session-file-manager.ts
55362
- import * as fs15 from "node:fs";
55738
+ import * as fs16 from "node:fs";
55363
55739
  import * as path15 from "node:path";
55364
55740
  var INITIAL_REFRESH_BACKOFF_MS = 6e4;
55365
55741
  var MAX_REFRESH_BACKOFF_MS = 60 * 60 * 1e3;
@@ -55384,15 +55760,15 @@ var SessionFileManager = class {
55384
55760
  // Directory Management
55385
55761
  // ============================================================================
55386
55762
  ensureDirectories() {
55387
- if (!fs15.existsSync(this.sessionsDir)) {
55388
- fs15.mkdirSync(this.sessionsDir, { recursive: true });
55763
+ if (!fs16.existsSync(this.sessionsDir)) {
55764
+ fs16.mkdirSync(this.sessionsDir, { recursive: true });
55389
55765
  }
55390
55766
  }
55391
55767
  // ============================================================================
55392
55768
  // State Management
55393
55769
  // ============================================================================
55394
55770
  loadState() {
55395
- if (!fs15.existsSync(this.statePath)) {
55771
+ if (!fs16.existsSync(this.statePath)) {
55396
55772
  return {
55397
55773
  sessionId: this.sessionId,
55398
55774
  lastSyncedAt: 0,
@@ -55400,7 +55776,7 @@ var SessionFileManager = class {
55400
55776
  };
55401
55777
  }
55402
55778
  try {
55403
- return JSON.parse(fs15.readFileSync(this.statePath, "utf-8"));
55779
+ return JSON.parse(fs16.readFileSync(this.statePath, "utf-8"));
55404
55780
  } catch (err) {
55405
55781
  sessionLogger.error(" Failed to load state:", err);
55406
55782
  return {
@@ -55413,12 +55789,12 @@ var SessionFileManager = class {
55413
55789
  saveState() {
55414
55790
  try {
55415
55791
  if (Object.keys(this.state.files).length === 0) {
55416
- if (fs15.existsSync(this.statePath)) {
55417
- fs15.unlinkSync(this.statePath);
55792
+ if (fs16.existsSync(this.statePath)) {
55793
+ fs16.unlinkSync(this.statePath);
55418
55794
  }
55419
55795
  return;
55420
55796
  }
55421
- fs15.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
55797
+ fs16.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
55422
55798
  } catch (err) {
55423
55799
  sessionLogger.error(" Failed to save state:", err);
55424
55800
  }
@@ -55564,7 +55940,7 @@ var SessionFileManager = class {
55564
55940
  return { success: false, coolingDown: true };
55565
55941
  }
55566
55942
  const localPath = this.fileCache.getLocalPath(entry.hash);
55567
- if (!localPath || !fs15.existsSync(localPath)) {
55943
+ if (!localPath || !fs16.existsSync(localPath)) {
55568
55944
  sessionLogger.warn(`Local file not found for ${fileId}`);
55569
55945
  entry.status = "expired";
55570
55946
  entry.error = "Local file missing";
@@ -55715,15 +56091,15 @@ var SessionFileManager = class {
55715
56091
  // Static Utilities
55716
56092
  // ============================================================================
55717
56093
  static cleanupOldSessions(sessionsDir, maxAge = 30 * 24 * 60 * 60 * 1e3) {
55718
- if (!fs15.existsSync(sessionsDir)) return;
56094
+ if (!fs16.existsSync(sessionsDir)) return;
55719
56095
  const now = Date.now();
55720
- const files = fs15.readdirSync(sessionsDir);
56096
+ const files = fs16.readdirSync(sessionsDir);
55721
56097
  for (const file of files) {
55722
56098
  if (!file.endsWith(".json")) continue;
55723
56099
  const filePath = path15.join(sessionsDir, file);
55724
- const stat2 = fs15.statSync(filePath);
56100
+ const stat2 = fs16.statSync(filePath);
55725
56101
  if (now - stat2.mtime.getTime() > maxAge) {
55726
- fs15.unlinkSync(filePath);
56102
+ fs16.unlinkSync(filePath);
55727
56103
  sessionLogger.debug(`Cleaned up old session: ${file}`);
55728
56104
  }
55729
56105
  }
@@ -55731,7 +56107,7 @@ var SessionFileManager = class {
55731
56107
  };
55732
56108
 
55733
56109
  // src/files/ffmpeg-processor.ts
55734
- import * as fs16 from "node:fs";
56110
+ import * as fs17 from "node:fs";
55735
56111
  import * as path16 from "node:path";
55736
56112
  import { spawn } from "node:child_process";
55737
56113
  var FFmpegProcessor = class {
@@ -55867,7 +56243,7 @@ var FFmpegProcessor = class {
55867
56243
  onProgress?.(percent);
55868
56244
  }
55869
56245
  });
55870
- const outputStat = fs16.statSync(outputPath);
56246
+ const outputStat = fs17.statSync(outputPath);
55871
56247
  return {
55872
56248
  type: "video",
55873
56249
  output: outputPath,
@@ -55899,7 +56275,7 @@ var FFmpegProcessor = class {
55899
56275
  async extractKeyframes(inputPath, outputDir, info, opts, onProgress) {
55900
56276
  const interval = Math.floor(info.duration / opts.keyframeCount);
55901
56277
  const framesDir = path16.join(outputDir, `keyframes_${Date.now()}`);
55902
- fs16.mkdirSync(framesDir, { recursive: true });
56278
+ fs17.mkdirSync(framesDir, { recursive: true });
55903
56279
  const outputPattern = path16.join(framesDir, "frame_%03d.jpg");
55904
56280
  const args = [
55905
56281
  "-i",
@@ -55918,10 +56294,10 @@ var FFmpegProcessor = class {
55918
56294
  onProgress?.(percent);
55919
56295
  }
55920
56296
  });
55921
- let frames = fs16.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
56297
+ let frames = fs17.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
55922
56298
  if (frames.length < opts.keyframeCount / 2) {
55923
- fs16.rmSync(framesDir, { recursive: true, force: true });
55924
- fs16.mkdirSync(framesDir, { recursive: true });
56299
+ fs17.rmSync(framesDir, { recursive: true, force: true });
56300
+ fs17.mkdirSync(framesDir, { recursive: true });
55925
56301
  const uniformArgs = [
55926
56302
  "-i",
55927
56303
  inputPath,
@@ -55937,10 +56313,10 @@ var FFmpegProcessor = class {
55937
56313
  onProgress?.(percent);
55938
56314
  }
55939
56315
  });
55940
- frames = fs16.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
56316
+ frames = fs17.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path16.join(framesDir, f));
55941
56317
  }
55942
56318
  const totalOutputSize = frames.reduce(
55943
- (sum, f) => sum + fs16.statSync(f).size,
56319
+ (sum, f) => sum + fs17.statSync(f).size,
55944
56320
  0
55945
56321
  );
55946
56322
  return {
@@ -56160,8 +56536,8 @@ var FileManager = class {
56160
56536
  directoryListingCache = /* @__PURE__ */ new Map();
56161
56537
  authFingerprint;
56162
56538
  ensureDirectories() {
56163
- if (!fs17.existsSync(this.tempDir)) {
56164
- fs17.mkdirSync(this.tempDir, { recursive: true });
56539
+ if (!fs18.existsSync(this.tempDir)) {
56540
+ fs18.mkdirSync(this.tempDir, { recursive: true });
56165
56541
  }
56166
56542
  }
56167
56543
  // ============================================================================
@@ -56192,7 +56568,7 @@ var FileManager = class {
56192
56568
  async stageLocal(filePath, options = {}) {
56193
56569
  const resolvedPath = resolvePath(filePath);
56194
56570
  const sourceName = options.sourceName || path17.basename(resolvedPath);
56195
- if (!fs17.existsSync(resolvedPath)) {
56571
+ if (!fs18.existsSync(resolvedPath)) {
56196
56572
  throw new FileManagerError(
56197
56573
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56198
56574
  `File not found: ${filePath}`
@@ -56207,7 +56583,7 @@ var FileManager = class {
56207
56583
  this.fileCache.rememberPathHint(resolvedPath, hash, sourceName);
56208
56584
  this.invalidateDirectoryListingCacheForPath(resolvedPath);
56209
56585
  const entry = this.fileCache.getByHash(hash);
56210
- const size = entry?.size ?? fs17.statSync(resolvedPath).size;
56586
+ const size = entry?.size ?? fs18.statSync(resolvedPath).size;
56211
56587
  return {
56212
56588
  success: true,
56213
56589
  hash,
@@ -56222,7 +56598,7 @@ var FileManager = class {
56222
56598
  async upload(filePath, options = {}) {
56223
56599
  const resolvedPath = resolvePath(filePath);
56224
56600
  const sourceName = options.sourceName || path17.basename(resolvedPath);
56225
- if (!fs17.existsSync(resolvedPath)) {
56601
+ if (!fs18.existsSync(resolvedPath)) {
56226
56602
  throw new FileManagerError(
56227
56603
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56228
56604
  `File not found: ${filePath}`
@@ -56303,7 +56679,7 @@ var FileManager = class {
56303
56679
  // ============================================================================
56304
56680
  async uploadPic(filePath, options = {}) {
56305
56681
  const resolvedPath = resolvePath(filePath);
56306
- if (!fs17.existsSync(resolvedPath)) {
56682
+ if (!fs18.existsSync(resolvedPath)) {
56307
56683
  throw new FileManagerError(
56308
56684
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56309
56685
  `File not found: ${filePath}`
@@ -56333,7 +56709,7 @@ var FileManager = class {
56333
56709
  this.fileCache.rememberPathHint(resolvedPath, result.hash, path17.basename(resolvedPath));
56334
56710
  this.invalidateDirectoryListingCacheForPath(resolvedPath);
56335
56711
  try {
56336
- fs17.unlinkSync(optimizedPath);
56712
+ fs18.unlinkSync(optimizedPath);
56337
56713
  } catch {
56338
56714
  }
56339
56715
  return result;
@@ -56343,7 +56719,7 @@ var FileManager = class {
56343
56719
  // ============================================================================
56344
56720
  async uploadVideo(filePath, options = {}) {
56345
56721
  const resolvedPath = resolvePath(filePath);
56346
- if (!fs17.existsSync(resolvedPath)) {
56722
+ if (!fs18.existsSync(resolvedPath)) {
56347
56723
  throw new FileManagerError(
56348
56724
  "LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
56349
56725
  `File not found: ${filePath}`
@@ -56737,13 +57113,13 @@ var FileManager = class {
56737
57113
  cleanupTempFiles(output) {
56738
57114
  try {
56739
57115
  if (typeof output === "string") {
56740
- if (fs17.existsSync(output)) {
56741
- fs17.unlinkSync(output);
57116
+ if (fs18.existsSync(output)) {
57117
+ fs18.unlinkSync(output);
56742
57118
  }
56743
57119
  } else {
56744
57120
  for (const file of output) {
56745
- if (fs17.existsSync(file)) {
56746
- fs17.unlinkSync(file);
57121
+ if (fs18.existsSync(file)) {
57122
+ fs18.unlinkSync(file);
56747
57123
  }
56748
57124
  }
56749
57125
  }
@@ -56775,7 +57151,7 @@ var FileManager = class {
56775
57151
  }];
56776
57152
  }
56777
57153
  const localPath = this.fileCache.getLocalPath(entry.hash);
56778
- if (localPath && fs17.existsSync(localPath)) {
57154
+ if (localPath && fs18.existsSync(localPath)) {
56779
57155
  return [{
56780
57156
  fileId,
56781
57157
  name: cacheEntry.name,
@@ -56872,7 +57248,7 @@ var FileManager = class {
56872
57248
  directories: []
56873
57249
  };
56874
57250
  try {
56875
- const entries = fs17.readdirSync(resolvedDir, { withFileTypes: true });
57251
+ const entries = fs18.readdirSync(resolvedDir, { withFileTypes: true });
56876
57252
  for (const entry of entries) {
56877
57253
  if (!entry.name || entry.name.startsWith(".")) {
56878
57254
  continue;
@@ -56886,7 +57262,7 @@ var FileManager = class {
56886
57262
  let isFile = entry.isFile();
56887
57263
  if (entry.isSymbolicLink()) {
56888
57264
  try {
56889
- const targetStat = fs17.statSync(fullPath);
57265
+ const targetStat = fs18.statSync(fullPath);
56890
57266
  isDirectory = targetStat.isDirectory();
56891
57267
  isFile = targetStat.isFile();
56892
57268
  } catch {
@@ -56904,7 +57280,7 @@ var FileManager = class {
56904
57280
  if (!type) {
56905
57281
  continue;
56906
57282
  }
56907
- const stat2 = fs17.statSync(fullPath);
57283
+ const stat2 = fs18.statSync(fullPath);
56908
57284
  listing.files.push({
56909
57285
  name: entry.name,
56910
57286
  path: fullPath,
@@ -57003,7 +57379,7 @@ function isInlineMediaRequest(request) {
57003
57379
  return request.kind === "image" || request.kind === "video";
57004
57380
  }
57005
57381
  async function prepareInlineMediaContent(params) {
57006
- const stat2 = await fs18.stat(params.request.absolutePath);
57382
+ const stat2 = await fs19.stat(params.request.absolutePath);
57007
57383
  const limitMb = getCapabilityLimitMb(params.model, params.request.kind);
57008
57384
  const limitBytes = limitMb * 1024 * 1024;
57009
57385
  if (stat2.size > limitBytes) {
@@ -57011,7 +57387,7 @@ async function prepareInlineMediaContent(params) {
57011
57387
  `${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
57388
  );
57013
57389
  }
57014
- const data = await fs18.readFile(params.request.absolutePath, "base64");
57390
+ const data = await fs19.readFile(params.request.absolutePath, "base64");
57015
57391
  const content = params.request.kind === "video" ? [{ type: "video", data, mimeType: params.request.mimeType }] : [{ type: "image", data, mimeType: params.request.mimeType }];
57016
57392
  return {
57017
57393
  content,
@@ -57381,22 +57757,22 @@ var ExecutionStateManager = class {
57381
57757
  };
57382
57758
 
57383
57759
  // src/session-trace.ts
57384
- import * as fs19 from "node:fs";
57760
+ import * as fs20 from "node:fs";
57385
57761
  import * as path19 from "node:path";
57386
57762
  function saveTraceFileBestEffort(tracePath, content) {
57387
57763
  const tempPath = `${tracePath}.${process.pid}.${Date.now()}.tmp`;
57388
57764
  try {
57389
- fs19.writeFileSync(tempPath, content, "utf8");
57765
+ fs20.writeFileSync(tempPath, content, "utf8");
57390
57766
  try {
57391
- fs19.renameSync(tempPath, tracePath);
57767
+ fs20.renameSync(tempPath, tracePath);
57392
57768
  return;
57393
57769
  } catch {
57394
57770
  try {
57395
- fs19.copyFileSync(tempPath, tracePath);
57771
+ fs20.copyFileSync(tempPath, tracePath);
57396
57772
  } catch {
57397
57773
  } finally {
57398
57774
  try {
57399
- fs19.unlinkSync(tempPath);
57775
+ fs20.unlinkSync(tempPath);
57400
57776
  } catch {
57401
57777
  }
57402
57778
  }
@@ -57410,9 +57786,9 @@ var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
57410
57786
  getSessionId: () => sessionManager.getActiveSessionId(),
57411
57787
  loadTrace: (sessionId) => {
57412
57788
  const tracePath = path19.join(sessionsDir, `${sessionId}.trace.json`);
57413
- if (!fs19.existsSync(tracePath)) return null;
57789
+ if (!fs20.existsSync(tracePath)) return null;
57414
57790
  try {
57415
- return JSON.parse(fs19.readFileSync(tracePath, "utf8"));
57791
+ return JSON.parse(fs20.readFileSync(tracePath, "utf8"));
57416
57792
  } catch {
57417
57793
  return null;
57418
57794
  }
@@ -59418,6 +59794,11 @@ var ToolExecutionComponent = class extends Container {
59418
59794
  const textBlocks = this.result.content?.filter((content) => content.type === "text") || [];
59419
59795
  return textBlocks.map((content) => (content.text || "").replace(/\r/g, "")).join("\n");
59420
59796
  }
59797
+ getExpandedOutputLineLimit(collapsedMaxLines) {
59798
+ if (!this.expanded) return collapsedMaxLines;
59799
+ const visibleOutputRows = Math.max(collapsedMaxLines, this.ui.terminal.rows - 15);
59800
+ return visibleOutputRows;
59801
+ }
59421
59802
  formatToolExecution() {
59422
59803
  let text = "";
59423
59804
  const invalidArg = theme.fg("error", "[invalid arg]");
@@ -59723,7 +60104,7 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
59723
60104
  const output = this.getTextOutput().trim();
59724
60105
  if (output) {
59725
60106
  const lines = output.split("\n");
59726
- const maxLines = this.expanded ? lines.length : 5;
60107
+ const maxLines = this.getExpandedOutputLineLimit(5);
59727
60108
  const displayLines = lines.slice(0, maxLines);
59728
60109
  const remaining = lines.length - maxLines;
59729
60110
  text += "\n\n" + displayLines.map((line) => theme.fg("toolOutput", line)).join("\n");
@@ -60129,7 +60510,7 @@ async function handleForkCommand(host) {
60129
60510
  }
60130
60511
 
60131
60512
  // src/commands/interactive-skill-commands.ts
60132
- import * as fs20 from "fs";
60513
+ import * as fs21 from "fs";
60133
60514
  import * as os4 from "os";
60134
60515
  import * as path20 from "path";
60135
60516
 
@@ -60473,7 +60854,7 @@ function expandSkillCommand(host, text) {
60473
60854
  const skill = host.skills.find((s) => s.name === skillName);
60474
60855
  if (!skill) return text;
60475
60856
  try {
60476
- const content = fs20.readFileSync(skill.filePath, "utf-8");
60857
+ const content = fs21.readFileSync(skill.filePath, "utf-8");
60477
60858
  const body = host.stripFrontmatter(content).trim();
60478
60859
  const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
60479
60860
  References are relative to ${skill.baseDir}.
@@ -60543,13 +60924,13 @@ async function handleSkillsCreate(host, args) {
60543
60924
  const skillDir = path20.join(skillsDir, name);
60544
60925
  const skillFile = path20.join(skillDir, "SKILL.md");
60545
60926
  console.error(`[SkillsCreate] Creating at: ${skillFile}`);
60546
- if (fs20.existsSync(skillDir)) {
60927
+ if (fs21.existsSync(skillDir)) {
60547
60928
  host.showError(`Skill "${name}" already exists at ${skillDir}`);
60548
60929
  return;
60549
60930
  }
60550
- fs20.mkdirSync(skillDir, { recursive: true });
60931
+ fs21.mkdirSync(skillDir, { recursive: true });
60551
60932
  const template = createSkillTemplate(name, description);
60552
- fs20.writeFileSync(skillFile, template, "utf-8");
60933
+ fs21.writeFileSync(skillFile, template, "utf-8");
60553
60934
  console.error(`[SkillsCreate] Successfully created skill`);
60554
60935
  host.chatContainer.addChild(new Spacer(1));
60555
60936
  host.chatContainer.addChild(new Text(theme.fg("accent", `\u2713 Created skill: ${name}`), 1, 0));
@@ -62020,7 +62401,7 @@ function setupInteractiveEditorSubmitHandler(host) {
62020
62401
  }
62021
62402
 
62022
62403
  // src/input/interactive-file-pipeline.ts
62023
- import * as fs23 from "fs";
62404
+ import * as fs24 from "fs";
62024
62405
  import * as path23 from "path";
62025
62406
 
62026
62407
  // src/components/file-picker.ts
@@ -62242,7 +62623,7 @@ var FilePickerComponent = class extends Container {
62242
62623
  };
62243
62624
 
62244
62625
  // src/files/commands/file-commands.ts
62245
- import * as fs21 from "node:fs";
62626
+ import * as fs22 from "node:fs";
62246
62627
  import * as path21 from "node:path";
62247
62628
  var FileCommands = class {
62248
62629
  context;
@@ -62259,7 +62640,7 @@ var FileCommands = class {
62259
62640
  return;
62260
62641
  }
62261
62642
  const filePath = resolvePath(parsed.path);
62262
- if (!fs21.existsSync(filePath)) {
62643
+ if (!fs22.existsSync(filePath)) {
62263
62644
  this.context.showError(`File not found: ${parsed.path}`);
62264
62645
  return;
62265
62646
  }
@@ -62298,7 +62679,7 @@ var FileCommands = class {
62298
62679
  return;
62299
62680
  }
62300
62681
  const resolvedPath = resolvePath(filePath);
62301
- if (!fs21.existsSync(resolvedPath)) {
62682
+ if (!fs22.existsSync(resolvedPath)) {
62302
62683
  this.context.showError(`File not found: ${filePath}`);
62303
62684
  return;
62304
62685
  }
@@ -62329,7 +62710,7 @@ var FileCommands = class {
62329
62710
  return;
62330
62711
  }
62331
62712
  const resolvedPath = resolvePath(parsed.path);
62332
- if (!fs21.existsSync(resolvedPath)) {
62713
+ if (!fs22.existsSync(resolvedPath)) {
62333
62714
  this.context.showError(`File not found: ${parsed.path}`);
62334
62715
  return;
62335
62716
  }
@@ -62807,7 +63188,7 @@ var FileStatusMonitor = class {
62807
63188
  };
62808
63189
 
62809
63190
  // src/files/mention/mention-handler.ts
62810
- import * as fs22 from "node:fs";
63191
+ import * as fs23 from "node:fs";
62811
63192
  import * as path22 from "node:path";
62812
63193
  var MentionHandler = class {
62813
63194
  fileManager;
@@ -63177,8 +63558,8 @@ var MentionHandler = class {
63177
63558
  }
63178
63559
  if (this.isPath(query)) {
63179
63560
  const resolvedPath = resolvePath(query);
63180
- if (fs22.existsSync(resolvedPath)) {
63181
- const stats = fs22.statSync(resolvedPath);
63561
+ if (fs23.existsSync(resolvedPath)) {
63562
+ const stats = fs23.statSync(resolvedPath);
63182
63563
  if (stats.isFile()) {
63183
63564
  const type = FileCache.getFileTypeFromName(resolvedPath);
63184
63565
  const name = path22.basename(resolvedPath);
@@ -63202,7 +63583,7 @@ var MentionHandler = class {
63202
63583
  return void 0;
63203
63584
  }
63204
63585
  const queryPath = this.isPath(query) ? resolvePath(query) : void 0;
63205
- const filter = queryPath ? fs22.existsSync(queryPath) && fs22.statSync(queryPath).isDirectory() ? "" : path22.basename(queryPath) : query;
63586
+ const filter = queryPath ? fs23.existsSync(queryPath) && fs23.statSync(queryPath).isDirectory() ? "" : path22.basename(queryPath) : query;
63206
63587
  const entries = this.fileManager.listPathEntries(currentDir, filter);
63207
63588
  const options = [];
63208
63589
  const homeDir = process.env.HOME || "";
@@ -63243,7 +63624,7 @@ var MentionHandler = class {
63243
63624
  getBrowserDirectory(query = this.currentQuery) {
63244
63625
  if (this.isPath(query)) {
63245
63626
  const resolvedPath = resolvePath(query);
63246
- if (fs22.existsSync(resolvedPath) && fs22.statSync(resolvedPath).isDirectory()) {
63627
+ if (fs23.existsSync(resolvedPath) && fs23.statSync(resolvedPath).isDirectory()) {
63247
63628
  return resolvedPath;
63248
63629
  }
63249
63630
  return path22.dirname(resolvedPath);
@@ -63607,13 +63988,13 @@ function convertPreparedAttachmentItems(items) {
63607
63988
  break;
63608
63989
  case "image": {
63609
63990
  if (!item.data && !item.path) return void 0;
63610
- const data = item.data ?? fs23.readFileSync(item.path, "base64");
63991
+ const data = item.data ?? fs24.readFileSync(item.path, "base64");
63611
63992
  converted.push({ type: "image", data, mimeType: item.mimeType });
63612
63993
  break;
63613
63994
  }
63614
63995
  case "video": {
63615
63996
  if (!item.data && !item.path) return void 0;
63616
- const data = item.data ?? fs23.readFileSync(item.path, "base64");
63997
+ const data = item.data ?? fs24.readFileSync(item.path, "base64");
63617
63998
  converted.push({ type: "video", data, mimeType: item.mimeType });
63618
63999
  break;
63619
64000
  }
@@ -65099,7 +65480,7 @@ var RUNTIME_MODE_CONTEXT_MARKER = "<runtime-mode-context>";
65099
65480
  var RUNTIME_MODE_CONTEXT_END_MARKER = "</runtime-mode-context>";
65100
65481
  var STALE_SYSTEM_REMINDER_RE = /<system-reminder>\s*# Plan Mode[\s\S]*?<\/system-reminder>\s*/gi;
65101
65482
  var STALE_RUNTIME_CONTEXT_RE = /<runtime-mode-context>[\s\S]*?<\/runtime-mode-context>\s*/gi;
65102
- function isRecord2(value) {
65483
+ function isRecord3(value) {
65103
65484
  return !!value && typeof value === "object" && !Array.isArray(value);
65104
65485
  }
65105
65486
  function cleanText(text) {
@@ -65115,7 +65496,7 @@ function cleanText(text) {
65115
65496
  return { text: withoutPlanReminder, stripped };
65116
65497
  }
65117
65498
  function stripUserMessage(message) {
65118
- if (!isRecord2(message) || message.role !== "user") {
65499
+ if (!isRecord3(message) || message.role !== "user") {
65119
65500
  return { message, stripped: 0 };
65120
65501
  }
65121
65502
  const content = message.content;
@@ -65135,13 +65516,13 @@ function stripUserMessage(message) {
65135
65516
  }
65136
65517
  let stripped = 0;
65137
65518
  const nextContent = content.map((block) => {
65138
- if (!isRecord2(block) || block.type !== "text" || typeof block.text !== "string") {
65519
+ if (!isRecord3(block) || block.type !== "text" || typeof block.text !== "string") {
65139
65520
  return block;
65140
65521
  }
65141
65522
  const cleaned = cleanText(block.text);
65142
65523
  stripped += cleaned.stripped;
65143
65524
  return { ...block, text: cleaned.text };
65144
- }).filter((block) => !(isRecord2(block) && block.type === "text" && String(block.text ?? "").length === 0));
65525
+ }).filter((block) => !(isRecord3(block) && block.type === "text" && String(block.text ?? "").length === 0));
65145
65526
  if (stripped === 0) return { message, stripped: 0 };
65146
65527
  return {
65147
65528
  message: {
@@ -65157,7 +65538,7 @@ function stripRuntimeModeContext(messages) {
65157
65538
  for (const message of messages) {
65158
65539
  const result = stripUserMessage(message);
65159
65540
  stripped += result.stripped;
65160
- if (isRecord2(result.message) && result.message.role === "user") {
65541
+ if (isRecord3(result.message) && result.message.role === "user") {
65161
65542
  const content = result.message.content;
65162
65543
  if (typeof content === "string" && content.trim().length === 0) {
65163
65544
  continue;
@@ -65199,7 +65580,7 @@ function buildRuntimeModeContext(state) {
65199
65580
  function findLatestUserIndex(messages) {
65200
65581
  for (let index = messages.length - 1; index >= 0; index--) {
65201
65582
  const message = messages[index];
65202
- if (isRecord2(message) && message.role === "user") {
65583
+ if (isRecord3(message) && message.role === "user") {
65203
65584
  return index;
65204
65585
  }
65205
65586
  }
@@ -65678,7 +66059,7 @@ var AttachmentResolver = class {
65678
66059
  };
65679
66060
 
65680
66061
  // src/extensions/loader.ts
65681
- import * as fs24 from "node:fs";
66062
+ import * as fs25 from "node:fs";
65682
66063
  import * as os5 from "os";
65683
66064
  import * as path24 from "path";
65684
66065
  import { pathToFileURL } from "node:url";
@@ -65862,7 +66243,7 @@ function normalizeExtensionImportPath(extensionPath) {
65862
66243
  }
65863
66244
  async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, hasUI, actions) {
65864
66245
  const resolvedPath = resolvePath2(extensionPath, cwd);
65865
- if (!fs24.existsSync(resolvedPath)) {
66246
+ if (!fs25.existsSync(resolvedPath)) {
65866
66247
  return { extension: null, error: `Extension not found: ${extensionPath}` };
65867
66248
  }
65868
66249
  try {
@@ -65883,12 +66264,12 @@ async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, h
65883
66264
  }
65884
66265
  }
65885
66266
  function discoverExtensionsInDir(dir) {
65886
- if (!fs24.existsSync(dir)) {
66267
+ if (!fs25.existsSync(dir)) {
65887
66268
  return [];
65888
66269
  }
65889
66270
  const discovered = [];
65890
66271
  try {
65891
- const entries = fs24.readdirSync(dir, { withFileTypes: true });
66272
+ const entries = fs25.readdirSync(dir, { withFileTypes: true });
65892
66273
  for (const entry of entries) {
65893
66274
  const entryPath = path24.join(dir, entry.name);
65894
66275
  if (entry.isFile() && (entry.name.endsWith(".cjs") || entry.name.endsWith(".js") || entry.name.endsWith(".ts"))) {
@@ -65897,13 +66278,13 @@ function discoverExtensionsInDir(dir) {
65897
66278
  }
65898
66279
  if (entry.isDirectory()) {
65899
66280
  const packageJsonPath = path24.join(entryPath, "package.json");
65900
- if (fs24.existsSync(packageJsonPath)) {
66281
+ if (fs25.existsSync(packageJsonPath)) {
65901
66282
  try {
65902
- const pkg = JSON.parse(fs24.readFileSync(packageJsonPath, "utf-8"));
66283
+ const pkg = JSON.parse(fs25.readFileSync(packageJsonPath, "utf-8"));
65903
66284
  const manifest = pkg.pie;
65904
66285
  if (manifest?.main) {
65905
66286
  const mainPath = path24.resolve(entryPath, manifest.main);
65906
- if (fs24.existsSync(mainPath)) {
66287
+ if (fs25.existsSync(mainPath)) {
65907
66288
  discovered.push({
65908
66289
  entryPath: mainPath,
65909
66290
  manifestName: manifest.name || pkg.name
@@ -65915,17 +66296,17 @@ function discoverExtensionsInDir(dir) {
65915
66296
  }
65916
66297
  }
65917
66298
  const indexCjs = path24.join(entryPath, "index.cjs");
65918
- if (fs24.existsSync(indexCjs)) {
66299
+ if (fs25.existsSync(indexCjs)) {
65919
66300
  discovered.push({ entryPath: indexCjs });
65920
66301
  continue;
65921
66302
  }
65922
66303
  const indexJs = path24.join(entryPath, "index.js");
65923
- if (fs24.existsSync(indexJs)) {
66304
+ if (fs25.existsSync(indexJs)) {
65924
66305
  discovered.push({ entryPath: indexJs });
65925
66306
  continue;
65926
66307
  }
65927
66308
  const indexTs = path24.join(entryPath, "index.ts");
65928
- if (fs24.existsSync(indexTs)) {
66309
+ if (fs25.existsSync(indexTs)) {
65929
66310
  discovered.push({ entryPath: indexTs });
65930
66311
  continue;
65931
66312
  }
@@ -65974,11 +66355,11 @@ async function loadExtensions(configuredPaths, cwd, uiContext, abortFn, isIdleFn
65974
66355
  }
65975
66356
  for (const p of configuredPaths) {
65976
66357
  const resolved = resolvePath2(p, cwd);
65977
- if (!fs24.existsSync(resolved)) {
66358
+ if (!fs25.existsSync(resolved)) {
65978
66359
  errors.push({ path: p, error: `Extension path not found: ${p}` });
65979
66360
  continue;
65980
66361
  }
65981
- if (!fs24.statSync(resolved).isDirectory()) {
66362
+ if (!fs25.statSync(resolved).isDirectory()) {
65982
66363
  errors.push({ path: p, error: `Extension path must be a directory: ${p}` });
65983
66364
  continue;
65984
66365
  }
@@ -66962,7 +67343,7 @@ var InteractiveMode = class {
66962
67343
  if (savedLevel) {
66963
67344
  this.thinkingLevel = savedLevel;
66964
67345
  }
66965
- const { Agent } = await import("./chunks/src-7UV3KKGU.js");
67346
+ const { Agent } = await import("./chunks/src-2FHZO63Y.js");
66966
67347
  const activeSession = this.sessionManager.getActiveSession();
66967
67348
  this.agent = new Agent({
66968
67349
  initialState: {
@@ -67364,10 +67745,12 @@ async function composeCliRuntime(params) {
67364
67745
  inputSummary: `provider=${settingsManager.getDefaultProvider() || "unset"} model=${settingsManager.getDefaultModel() || "unset"}`,
67365
67746
  outputSummary: `provider=${provider} model=${modelId} configured=${!initialModel.unconfigured}`
67366
67747
  });
67367
- const cwd = process.cwd();
67748
+ const cwd = params.cwd ?? process.cwd();
67368
67749
  const sessionManager = createSessionManager({ sessionsDir: paths.sessionsDir });
67369
67750
  if (params.explicitSessionId) {
67370
- const loaded = await sessionManager.loadSession(params.explicitSessionId);
67751
+ const loaded = await sessionManager.loadSession(params.explicitSessionId, {
67752
+ warnIfMissing: params.warnIfExplicitSessionMissing
67753
+ });
67371
67754
  if (!loaded) {
67372
67755
  await sessionManager.createSession(void 0, void 0, params.explicitSessionId);
67373
67756
  } else {
@@ -67391,6 +67774,11 @@ async function composeCliRuntime(params) {
67391
67774
  await sessionManager.createSession();
67392
67775
  }
67393
67776
  syncSessionModelMetadata(sessionManager, model, settingsManager.getDefaultThinkingLevel() || "off");
67777
+ const activeSession = sessionManager.getActiveSession();
67778
+ if (activeSession && activeSession.metadata.cwd !== cwd) {
67779
+ activeSession.metadata.cwd = cwd;
67780
+ await sessionManager.save();
67781
+ }
67394
67782
  const sessionId = sessionManager.getActiveSession()?.id;
67395
67783
  const fileObservationState = createFileObservationState();
67396
67784
  if (sessionId) {
@@ -67633,7 +68021,7 @@ async function runPrintMode(params) {
67633
68021
  `);
67634
68022
  console.log("Assistant: ");
67635
68023
  }
67636
- const { Agent: AgentClass } = await import("./chunks/src-7UV3KKGU.js");
68024
+ const { Agent: AgentClass } = await import("./chunks/src-2FHZO63Y.js");
67637
68025
  let agent;
67638
68026
  const printModeExtensions = await loadPrintModeExtensions({
67639
68027
  cwd: runtime.cwd,
@@ -67853,7 +68241,7 @@ function toJsonValue(value, depth = 0) {
67853
68241
  }
67854
68242
  return result;
67855
68243
  }
67856
- function isRecord3(value) {
68244
+ function isRecord4(value) {
67857
68245
  return !!value && typeof value === "object" && !Array.isArray(value);
67858
68246
  }
67859
68247
  function parseInput(line) {
@@ -67863,7 +68251,7 @@ function parseInput(line) {
67863
68251
  } catch {
67864
68252
  return null;
67865
68253
  }
67866
- if (!isRecord3(parsed) || typeof parsed.type !== "string") return null;
68254
+ if (!isRecord4(parsed) || typeof parsed.type !== "string") return null;
67867
68255
  if (parsed.type === "shutdown") {
67868
68256
  return { type: "shutdown", reason: typeof parsed.reason === "string" ? parsed.reason : void 0 };
67869
68257
  }
@@ -67882,7 +68270,7 @@ function parseInput(line) {
67882
68270
  turnId: parsed.turnId,
67883
68271
  prompt: parsed.prompt,
67884
68272
  cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0,
67885
- metadata: isRecord3(parsed.metadata) ? parsed.metadata : void 0
68273
+ metadata: isRecord4(parsed.metadata) ? parsed.metadata : void 0
67886
68274
  };
67887
68275
  }
67888
68276
  return null;
@@ -67916,15 +68304,15 @@ function readProgressText(value) {
67916
68304
  function extractJsonEventsToolProgressText(partialResult) {
67917
68305
  const plainText = readProgressText(partialResult).trim();
67918
68306
  if (plainText) return plainText;
67919
- if (!isRecord3(partialResult)) return "";
68307
+ if (!isRecord4(partialResult)) return "";
67920
68308
  const content = partialResult.content;
67921
68309
  if (Array.isArray(content)) {
67922
- return content.map((block) => isRecord3(block) && block.type === "text" ? readProgressText(block.text) : "").filter(Boolean).join("\n").trim();
68310
+ return content.map((block) => isRecord4(block) && block.type === "text" ? readProgressText(block.text) : "").filter(Boolean).join("\n").trim();
67923
68311
  }
67924
68312
  const directText = readProgressText(partialResult.text) || readProgressText(partialResult.message);
67925
68313
  if (directText) return directText.trim();
67926
68314
  const details = partialResult.details;
67927
- if (isRecord3(details)) {
68315
+ if (isRecord4(details)) {
67928
68316
  return (readProgressText(details.text) || readProgressText(details.message)).trim();
67929
68317
  }
67930
68318
  return "";
@@ -68011,12 +68399,14 @@ async function loadJsonModeExtensions(params) {
68011
68399
  async function runJsonEventsMode(params) {
68012
68400
  const sessionId = params.explicitSessionId || params.runtime?.sessionManager.getActiveSession()?.id || `pie-json-${Date.now()}`;
68013
68401
  let activeTurn = null;
68402
+ let runtime = params.runtime;
68014
68403
  let agent;
68015
68404
  let controller;
68016
68405
  let disposeAgentSubscription;
68017
68406
  let disposeSemanticSubscription;
68018
68407
  let trace;
68019
68408
  let lastRetryEvent;
68409
+ let mockActiveEntryId;
68020
68410
  const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
68021
68411
  const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
68022
68412
  writeEvent({ type: "agent.ready", sessionId });
@@ -68036,6 +68426,7 @@ async function runJsonEventsMode(params) {
68036
68426
  }
68037
68427
  function display(chunk, options) {
68038
68428
  if (!activeTurn || !chunk) return;
68429
+ activeTurn.outputStarted = true;
68039
68430
  if (options?.appendToSummary !== false) {
68040
68431
  activeTurn.summary += chunk;
68041
68432
  }
@@ -68058,6 +68449,78 @@ async function runJsonEventsMode(params) {
68058
68449
  activeTurn.pendingAssistantOutput = "";
68059
68450
  }
68060
68451
  }
68452
+ function activeHeadEntryId() {
68453
+ return mockActiveEntryId ?? runtime?.sessionManager.getActiveEntryId() ?? void 0;
68454
+ }
68455
+ function persistedMockMetadata(existing, activeEntryId, rootEntryId, cwd) {
68456
+ const metadata = {};
68457
+ if (existing) {
68458
+ for (const [key, value] of Object.entries(existing)) {
68459
+ if (["id", "createdAt", "updatedAt", "entryCount", "messageCount", "activeEntryId", "rootEntryId"].includes(key)) {
68460
+ continue;
68461
+ }
68462
+ metadata[key] = value;
68463
+ }
68464
+ }
68465
+ metadata.name = typeof existing?.name === "string" ? existing.name : `Session ${sessionId.slice(0, 8)}`;
68466
+ if (cwd || existing?.cwd || runtime?.cwd) {
68467
+ metadata.cwd = cwd ?? existing?.cwd ?? runtime?.cwd;
68468
+ }
68469
+ metadata.activeEntryId = activeEntryId;
68470
+ metadata.rootEntryId = existing?.rootEntryId ?? rootEntryId;
68471
+ return metadata;
68472
+ }
68473
+ async function persistMockTurn(message, assistantText) {
68474
+ const store = new FileSessionStore(getSessionsDir());
68475
+ const existing = await store.load(message.sessionId ?? sessionId);
68476
+ const startedAt = activeTurn?.startedAt ?? Date.now();
68477
+ const userEntryId = generateEntryId();
68478
+ const assistantEntryId = generateEntryId();
68479
+ const parentId = existing?.metadata.activeEntryId ?? null;
68480
+ const userEntry = {
68481
+ id: userEntryId,
68482
+ parentId,
68483
+ type: "message",
68484
+ timestamp: startedAt,
68485
+ message: {
68486
+ role: "user",
68487
+ content: message.prompt,
68488
+ timestamp: startedAt
68489
+ }
68490
+ };
68491
+ const assistantTimestamp = Date.now();
68492
+ const assistantMessage = {
68493
+ role: "assistant",
68494
+ content: [{ type: "text", text: assistantText }],
68495
+ api: "mock",
68496
+ provider: "mock",
68497
+ model: "mock",
68498
+ usage: {
68499
+ input: 0,
68500
+ output: 0,
68501
+ cacheRead: 0,
68502
+ cacheWrite: 0,
68503
+ totalTokens: 0,
68504
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
68505
+ },
68506
+ stopReason: "stop",
68507
+ timestamp: assistantTimestamp
68508
+ };
68509
+ const assistantEntry = {
68510
+ id: assistantEntryId,
68511
+ parentId: userEntryId,
68512
+ type: "message",
68513
+ timestamp: assistantTimestamp,
68514
+ message: assistantMessage
68515
+ };
68516
+ const entries = [...existing?.entries ?? [], userEntry, assistantEntry];
68517
+ await store.save(
68518
+ message.sessionId ?? sessionId,
68519
+ entries,
68520
+ persistedMockMetadata(existing?.metadata, assistantEntryId, existing?.metadata.rootEntryId ?? userEntryId, message.cwd)
68521
+ );
68522
+ return assistantEntryId;
68523
+ }
68061
68524
  function flushAssistantOutput(fallbackText = "") {
68062
68525
  if (!activeTurn) return;
68063
68526
  const chunk = activeTurn.pendingAssistantOutput || fallbackText;
@@ -68070,21 +68533,38 @@ async function runJsonEventsMode(params) {
68070
68533
  const turn = activeTurn;
68071
68534
  if (!turn || turn.finalized) return;
68072
68535
  turn.finalized = true;
68536
+ const headEntryId = activeHeadEntryId();
68537
+ const base = {
68538
+ sessionId: turn.sessionId,
68539
+ turnId: turn.turnId,
68540
+ headEntryId,
68541
+ activeEntryId: headEntryId
68542
+ };
68073
68543
  switch (kind) {
68074
68544
  case "completed":
68075
- writeEvent({ type: "turn.completed", sessionId: turn.sessionId, turnId: turn.turnId, summary: (detail ?? turn.summary).trim() });
68545
+ writeEvent({ type: "turn.completed", ...base, summary: (detail ?? turn.summary).trim() });
68076
68546
  break;
68077
68547
  case "failed":
68078
- writeEvent({ type: "turn.failed", sessionId: turn.sessionId, turnId: turn.turnId, error: detail || "turn failed" });
68548
+ writeEvent({ type: "turn.failed", ...base, error: detail || "turn failed" });
68079
68549
  break;
68080
68550
  case "cancelled":
68081
- writeEvent({ type: "turn.cancelled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "interrupted" });
68551
+ writeEvent({ type: "turn.cancelled", ...base, reason: detail || "interrupted" });
68082
68552
  break;
68083
68553
  case "stalled":
68084
- writeEvent({ type: "turn.stalled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "no_progress_timeout" });
68554
+ writeEvent({ type: "turn.stalled", ...base, reason: detail || "no_progress_timeout" });
68085
68555
  break;
68086
68556
  }
68087
68557
  }
68558
+ function emitSettled(turn) {
68559
+ const headEntryId = activeHeadEntryId();
68560
+ writeEvent({
68561
+ type: "turn.settled",
68562
+ sessionId: turn.sessionId,
68563
+ turnId: turn.turnId,
68564
+ headEntryId,
68565
+ activeEntryId: headEntryId
68566
+ });
68567
+ }
68088
68568
  function rememberTerminal(kind, detail, options) {
68089
68569
  if (!activeTurn || activeTurn.finalized) return;
68090
68570
  if (activeTurn.pendingTerminal && options?.overwrite === false) return;
@@ -68144,15 +68624,10 @@ async function runJsonEventsMode(params) {
68144
68624
  function handleControllerEvent(event) {
68145
68625
  trace?.noteRuntimeEvent(event.type, event);
68146
68626
  if (event.type === "auto_compaction_end" && !event.errorMessage) {
68147
- params.runtime?.fileObservationState.clear();
68627
+ runtime?.fileObservationState.clear();
68148
68628
  }
68149
68629
  if (event.type === "turn_settled" && activeTurn) {
68150
- finalizePendingTerminal();
68151
- writeEvent({
68152
- type: "turn.settled",
68153
- sessionId: activeTurn.sessionId,
68154
- turnId: activeTurn.turnId
68155
- });
68630
+ touch();
68156
68631
  return;
68157
68632
  }
68158
68633
  if (!activeTurn || activeTurn.finalized) return;
@@ -68252,16 +68727,35 @@ async function runJsonEventsMode(params) {
68252
68727
  rememberTerminal("cancelled", event.reason, { overwrite: false });
68253
68728
  }
68254
68729
  }
68255
- async function ensureRuntime() {
68256
- if (params.mockResponse !== void 0 || controller) return;
68257
- const runtime = params.runtime;
68730
+ async function disposeRuntime() {
68731
+ disposeAgentSubscription?.();
68732
+ disposeAgentSubscription = void 0;
68733
+ disposeSemanticSubscription?.();
68734
+ disposeSemanticSubscription = void 0;
68735
+ controller?.dispose();
68736
+ controller = void 0;
68737
+ agent = void 0;
68738
+ try {
68739
+ await runtime?.sessionManager.save();
68740
+ } catch {
68741
+ }
68742
+ trace?.flush();
68743
+ trace = void 0;
68744
+ }
68745
+ async function ensureRuntime(requestedCwd) {
68746
+ if (params.mockResponse !== void 0) return;
68747
+ const effectiveCwd = requestedCwd ?? process.cwd();
68748
+ if (params.createRuntime && (!runtime || runtime.cwd !== effectiveCwd)) {
68749
+ await disposeRuntime();
68750
+ runtime = await params.createRuntime({ cwd: effectiveCwd, sessionId });
68751
+ }
68258
68752
  if (!runtime) {
68259
68753
  throw new Error("JSON events mode requires a CLI runtime");
68260
68754
  }
68261
- if (runtime.initialModel.unconfigured) {
68755
+ if (runtime.initialModel.unconfigured || controller) {
68262
68756
  return;
68263
68757
  }
68264
- const { Agent: AgentClass } = await import("./chunks/src-7UV3KKGU.js");
68758
+ const { Agent: AgentClass } = await import("./chunks/src-2FHZO63Y.js");
68265
68759
  const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
68266
68760
  const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
68267
68761
  recordCliCompositionStep(runtime.compositionTrace, {
@@ -68367,6 +68861,7 @@ async function runJsonEventsMode(params) {
68367
68861
  interrupted: false,
68368
68862
  stalled: false,
68369
68863
  finalized: false,
68864
+ outputStarted: false,
68370
68865
  summary: "",
68371
68866
  pendingAssistantOutput: ""
68372
68867
  };
@@ -68380,30 +68875,43 @@ async function runJsonEventsMode(params) {
68380
68875
  return;
68381
68876
  }
68382
68877
  display(params.mockResponse);
68878
+ try {
68879
+ mockActiveEntryId = await persistMockTurn(message, params.mockResponse);
68880
+ } catch (error) {
68881
+ finalize("failed", error instanceof Error ? error.message : String(error));
68882
+ if (activeTurn === turn) emitSettled(turn);
68883
+ if (activeTurn === turn) activeTurn = null;
68884
+ return;
68885
+ }
68383
68886
  finalize("completed");
68887
+ if (activeTurn === turn) emitSettled(turn);
68384
68888
  if (activeTurn === turn) activeTurn = null;
68385
68889
  return;
68386
68890
  }
68387
68891
  if (params.startupError) {
68388
68892
  finalize("failed", params.startupError);
68893
+ if (activeTurn === turn) emitSettled(turn);
68389
68894
  if (activeTurn === turn) activeTurn = null;
68390
68895
  return;
68391
68896
  }
68392
68897
  try {
68393
- await ensureRuntime();
68898
+ await ensureRuntime(message.cwd);
68394
68899
  } catch (error) {
68395
68900
  finalize("failed", error instanceof Error ? error.message : String(error));
68901
+ if (activeTurn === turn) emitSettled(turn);
68396
68902
  if (activeTurn === turn) activeTurn = null;
68397
68903
  return;
68398
68904
  }
68399
- const runtime = params.runtime;
68400
- if (runtime?.initialModel.unconfigured) {
68401
- finalize("failed", runtime.initialModel.warning || "No models are configured.");
68905
+ const activeRuntime = runtime;
68906
+ if (activeRuntime?.initialModel.unconfigured) {
68907
+ finalize("failed", activeRuntime.initialModel.warning || "No models are configured.");
68908
+ if (activeTurn === turn) emitSettled(turn);
68402
68909
  if (activeTurn === turn) activeTurn = null;
68403
68910
  return;
68404
68911
  }
68405
68912
  if (!controller || !agent) {
68406
68913
  finalize("failed", "JSON events runtime was not initialized");
68914
+ if (activeTurn === turn) emitSettled(turn);
68407
68915
  if (activeTurn === turn) activeTurn = null;
68408
68916
  return;
68409
68917
  }
@@ -68425,31 +68933,36 @@ async function runJsonEventsMode(params) {
68425
68933
  trace?.noteWaitForIdleStart({ mode: "json-events" });
68426
68934
  await controller.waitForSettled();
68427
68935
  trace?.noteWaitForIdleSettled({ mode: "json-events" });
68936
+ await activeRuntime?.sessionManager.save();
68428
68937
  finalizePendingTerminal();
68429
68938
  if (!activeTurn?.finalized) {
68430
68939
  const finalError = assistantErrorFromAgent(agent);
68431
68940
  if (activeTurn?.interrupted) {
68432
68941
  finalize("cancelled", "user_interrupt");
68433
- return;
68434
- }
68435
- if (finalError) {
68942
+ } else if (finalError) {
68436
68943
  finalize("failed", finalError);
68437
- return;
68944
+ } else {
68945
+ const text = assistantTextFromAgent(agent);
68946
+ flushAssistantOutput(text);
68947
+ finalize("completed", text || activeTurn?.summary.trim());
68438
68948
  }
68439
- const text = assistantTextFromAgent(agent);
68440
- flushAssistantOutput(text);
68441
- finalize("completed", text || activeTurn?.summary.trim());
68442
68949
  }
68950
+ if (activeTurn === turn) emitSettled(turn);
68443
68951
  } catch (error) {
68444
68952
  const messageText = error instanceof Error ? error.message : String(error);
68445
68953
  trace?.noteStalled(messageText, { mode: "json-events" });
68954
+ try {
68955
+ await activeRuntime?.sessionManager.save();
68956
+ } catch {
68957
+ }
68446
68958
  if (!activeTurn?.finalized) {
68447
68959
  finalize(activeTurn?.interrupted ? "cancelled" : "failed", activeTurn?.interrupted ? "user_interrupt" : messageText);
68448
68960
  }
68961
+ if (activeTurn === turn) emitSettled(turn);
68449
68962
  } finally {
68450
68963
  clearInterval(progressTimer);
68451
68964
  trace?.flush();
68452
- await runtime?.sessionManager.save();
68965
+ await activeRuntime?.sessionManager.save();
68453
68966
  if (activeTurn === turn) activeTurn = null;
68454
68967
  }
68455
68968
  }
@@ -68481,12 +68994,29 @@ async function runJsonEventsMode(params) {
68481
68994
  });
68482
68995
  return;
68483
68996
  }
68997
+ if (params.mockResponse !== void 0) {
68998
+ if (activeTurn.outputStarted) return;
68999
+ activeTurn.interrupted = true;
69000
+ finalize("cancelled", message.reason || "user_interrupt");
69001
+ emitSettled(activeTurn);
69002
+ activeTurn = null;
69003
+ return;
69004
+ }
68484
69005
  activeTurn.interrupted = true;
68485
69006
  controller?.abort();
69007
+ }
69008
+ function shutdownActiveTurn(reason) {
69009
+ if (!activeTurn || activeTurn.finalized) return;
68486
69010
  if (params.mockResponse !== void 0) {
68487
- finalize("cancelled", message.reason || "user_interrupt");
69011
+ if (activeTurn.outputStarted) return;
69012
+ activeTurn.interrupted = true;
69013
+ finalize("cancelled", reason || "shutdown");
69014
+ emitSettled(activeTurn);
68488
69015
  activeTurn = null;
69016
+ return;
68489
69017
  }
69018
+ activeTurn.interrupted = true;
69019
+ controller?.abort();
68490
69020
  }
68491
69021
  const input = readline.createInterface({ input: process.stdin });
68492
69022
  let activeTurnPromise = null;
@@ -68498,15 +69028,7 @@ async function runJsonEventsMode(params) {
68498
69028
  continue;
68499
69029
  }
68500
69030
  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
- }
69031
+ shutdownActiveTurn(message.reason);
68510
69032
  break;
68511
69033
  }
68512
69034
  if (message.type === "turn.interrupt") {
@@ -68531,11 +69053,7 @@ async function runJsonEventsMode(params) {
68531
69053
  }
68532
69054
  }
68533
69055
  await activeTurnPromise;
68534
- disposeAgentSubscription?.();
68535
- disposeSemanticSubscription?.();
68536
- controller?.dispose();
68537
- await params.runtime?.sessionManager.save();
68538
- trace?.flush();
69056
+ await disposeRuntime();
68539
69057
  }
68540
69058
 
68541
69059
  // src/cli.ts
@@ -68544,8 +69062,8 @@ var logError = (msg, err) => {
68544
69062
  const logPath = getRuntimeLogPath();
68545
69063
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
68546
69064
  const stack = err instanceof Error ? err.stack || "" : "";
68547
- fs25.mkdirSync(path26.dirname(logPath), { recursive: true });
68548
- fs25.appendFileSync(logPath, `[${timestamp}] ${msg}
69065
+ fs26.mkdirSync(path26.dirname(logPath), { recursive: true });
69066
+ fs26.appendFileSync(logPath, `[${timestamp}] ${msg}
68549
69067
  ${stack}
68550
69068
 
68551
69069
  `);
@@ -68564,6 +69082,7 @@ Commands:
68564
69082
  doctor Diagnose local Pie configuration and runtime dependencies
68565
69083
  models init Create a starter ~/.pie/models.json
68566
69084
  models validate Validate ~/.pie/models.json
69085
+ sessions List, read, rename, rewind, and fork Pie sessions
68567
69086
  permissions Explain Pie tool and shell safety defaults
68568
69087
  help Show this help message
68569
69088
 
@@ -68688,7 +69207,7 @@ async function createCliTestStreamFnFromEnv() {
68688
69207
  if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) {
68689
69208
  return void 0;
68690
69209
  }
68691
- const { createTestStreamFnFromSequenceEnv } = await import("./chunks/test-stream-PP63L7MK.js");
69210
+ const { createTestStreamFnFromSequenceEnv } = await import("./chunks/test-stream-UW74PA6T.js");
68692
69211
  return createTestStreamFnFromSequenceEnv();
68693
69212
  }
68694
69213
  async function startChat(initialPrompt, testCommand) {
@@ -68707,23 +69226,15 @@ async function startChat(initialPrompt, testCommand) {
68707
69226
  });
68708
69227
  return;
68709
69228
  }
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
69229
  await runJsonEventsMode({
68724
- runtime: runtime2,
68725
69230
  explicitSessionId,
68726
- streamFn: await createCliTestStreamFnFromEnv()
69231
+ streamFn: await createCliTestStreamFnFromEnv(),
69232
+ createRuntime: async ({ cwd, sessionId }) => composeCliRuntime({
69233
+ explicitSessionId: explicitSessionId ?? sessionId,
69234
+ extensionPaths,
69235
+ cwd,
69236
+ warnIfExplicitSessionMissing: false
69237
+ })
68727
69238
  });
68728
69239
  });
68729
69240
  return;
@@ -68794,6 +69305,10 @@ async function startChat(initialPrompt, testCommand) {
68794
69305
  }
68795
69306
  async function main() {
68796
69307
  const args = process.argv.slice(2);
69308
+ if (args[0] === "--version" || args[0] === "-v") {
69309
+ console.log(VERSION);
69310
+ return;
69311
+ }
68797
69312
  if (args[0] === "doctor") {
68798
69313
  await runDoctorCommand(args.slice(1));
68799
69314
  return;
@@ -68807,6 +69322,10 @@ async function main() {
68807
69322
  }
68808
69323
  return;
68809
69324
  }
69325
+ if (args[0] === "sessions") {
69326
+ await runSessionsCommand(args.slice(1));
69327
+ return;
69328
+ }
68810
69329
  if (args[0] === "permissions") {
68811
69330
  console.log(formatPermissionsHelp());
68812
69331
  return;