spacecode 2.1.1 → 2.2.0

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/repl.mjs CHANGED
@@ -1404,7 +1404,7 @@ var require_react_development = __commonJS({
1404
1404
  var dispatcher = resolveDispatcher();
1405
1405
  return dispatcher.useReducer(reducer, initialArg, init);
1406
1406
  }
1407
- function useRef4(initialValue) {
1407
+ function useRef5(initialValue) {
1408
1408
  var dispatcher = resolveDispatcher();
1409
1409
  return dispatcher.useRef(initialValue);
1410
1410
  }
@@ -1416,7 +1416,7 @@ var require_react_development = __commonJS({
1416
1416
  var dispatcher = resolveDispatcher();
1417
1417
  return dispatcher.useInsertionEffect(create2, deps);
1418
1418
  }
1419
- function useLayoutEffect2(create2, deps) {
1419
+ function useLayoutEffect3(create2, deps) {
1420
1420
  var dispatcher = resolveDispatcher();
1421
1421
  return dispatcher.useLayoutEffect(create2, deps);
1422
1422
  }
@@ -2195,10 +2195,10 @@ var require_react_development = __commonJS({
2195
2195
  exports.useId = useId;
2196
2196
  exports.useImperativeHandle = useImperativeHandle;
2197
2197
  exports.useInsertionEffect = useInsertionEffect;
2198
- exports.useLayoutEffect = useLayoutEffect2;
2198
+ exports.useLayoutEffect = useLayoutEffect3;
2199
2199
  exports.useMemo = useMemo8;
2200
2200
  exports.useReducer = useReducer;
2201
- exports.useRef = useRef4;
2201
+ exports.useRef = useRef5;
2202
2202
  exports.useState = useState10;
2203
2203
  exports.useSyncExternalStore = useSyncExternalStore;
2204
2204
  exports.useTransition = useTransition;
@@ -2255,7 +2255,7 @@ var require_react_jsx_runtime_development = __commonJS({
2255
2255
  if (process.env.NODE_ENV !== "production") {
2256
2256
  (function() {
2257
2257
  "use strict";
2258
- var React19 = require_react();
2258
+ var React20 = require_react();
2259
2259
  var REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.element");
2260
2260
  var REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal");
2261
2261
  var REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment");
@@ -2281,7 +2281,7 @@ var require_react_jsx_runtime_development = __commonJS({
2281
2281
  }
2282
2282
  return null;
2283
2283
  }
2284
- var ReactSharedInternals = React19.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
2284
+ var ReactSharedInternals = React20.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
2285
2285
  function error(format) {
2286
2286
  {
2287
2287
  {
@@ -3131,10 +3131,10 @@ var require_react_jsx_runtime_development = __commonJS({
3131
3131
  return jsxWithValidation(type, props, key, false);
3132
3132
  }
3133
3133
  }
3134
- var jsx12 = jsxWithValidationDynamic;
3134
+ var jsx13 = jsxWithValidationDynamic;
3135
3135
  var jsxs12 = jsxWithValidationStatic;
3136
3136
  exports.Fragment = REACT_FRAGMENT_TYPE;
3137
- exports.jsx = jsx12;
3137
+ exports.jsx = jsx13;
3138
3138
  exports.jsxs = jsxs12;
3139
3139
  })();
3140
3140
  }
@@ -10823,9 +10823,9 @@ var require_react_reconciler_development = __commonJS({
10823
10823
  module.exports = function $$$reconciler($$$hostConfig) {
10824
10824
  var exports2 = {};
10825
10825
  "use strict";
10826
- var React19 = require_react();
10826
+ var React20 = require_react();
10827
10827
  var Scheduler = require_scheduler();
10828
- var ReactSharedInternals = React19.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
10828
+ var ReactSharedInternals = React20.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
10829
10829
  var suppressWarning = false;
10830
10830
  function setSuppressWarning(newSuppressWarning) {
10831
10831
  {
@@ -25702,10 +25702,10 @@ var require_react_reconciler_development = __commonJS({
25702
25702
  var setErrorHandler = null;
25703
25703
  var setSuspenseHandler = null;
25704
25704
  {
25705
- var copyWithDeleteImpl = function(obj, path11, index2) {
25706
- var key = path11[index2];
25705
+ var copyWithDeleteImpl = function(obj, path12, index2) {
25706
+ var key = path12[index2];
25707
25707
  var updated = isArray(obj) ? obj.slice() : assign({}, obj);
25708
- if (index2 + 1 === path11.length) {
25708
+ if (index2 + 1 === path12.length) {
25709
25709
  if (isArray(updated)) {
25710
25710
  updated.splice(key, 1);
25711
25711
  } else {
@@ -25713,11 +25713,11 @@ var require_react_reconciler_development = __commonJS({
25713
25713
  }
25714
25714
  return updated;
25715
25715
  }
25716
- updated[key] = copyWithDeleteImpl(obj[key], path11, index2 + 1);
25716
+ updated[key] = copyWithDeleteImpl(obj[key], path12, index2 + 1);
25717
25717
  return updated;
25718
25718
  };
25719
- var copyWithDelete = function(obj, path11) {
25720
- return copyWithDeleteImpl(obj, path11, 0);
25719
+ var copyWithDelete = function(obj, path12) {
25720
+ return copyWithDeleteImpl(obj, path12, 0);
25721
25721
  };
25722
25722
  var copyWithRenameImpl = function(obj, oldPath, newPath, index2) {
25723
25723
  var oldKey = oldPath[index2];
@@ -25755,17 +25755,17 @@ var require_react_reconciler_development = __commonJS({
25755
25755
  }
25756
25756
  return copyWithRenameImpl(obj, oldPath, newPath, 0);
25757
25757
  };
25758
- var copyWithSetImpl = function(obj, path11, index2, value) {
25759
- if (index2 >= path11.length) {
25758
+ var copyWithSetImpl = function(obj, path12, index2, value) {
25759
+ if (index2 >= path12.length) {
25760
25760
  return value;
25761
25761
  }
25762
- var key = path11[index2];
25762
+ var key = path12[index2];
25763
25763
  var updated = isArray(obj) ? obj.slice() : assign({}, obj);
25764
- updated[key] = copyWithSetImpl(obj[key], path11, index2 + 1, value);
25764
+ updated[key] = copyWithSetImpl(obj[key], path12, index2 + 1, value);
25765
25765
  return updated;
25766
25766
  };
25767
- var copyWithSet = function(obj, path11, value) {
25768
- return copyWithSetImpl(obj, path11, 0, value);
25767
+ var copyWithSet = function(obj, path12, value) {
25768
+ return copyWithSetImpl(obj, path12, 0, value);
25769
25769
  };
25770
25770
  var findHook = function(fiber, id) {
25771
25771
  var currentHook2 = fiber.memoizedState;
@@ -25775,10 +25775,10 @@ var require_react_reconciler_development = __commonJS({
25775
25775
  }
25776
25776
  return currentHook2;
25777
25777
  };
25778
- overrideHookState = function(fiber, id, path11, value) {
25778
+ overrideHookState = function(fiber, id, path12, value) {
25779
25779
  var hook = findHook(fiber, id);
25780
25780
  if (hook !== null) {
25781
- var newState = copyWithSet(hook.memoizedState, path11, value);
25781
+ var newState = copyWithSet(hook.memoizedState, path12, value);
25782
25782
  hook.memoizedState = newState;
25783
25783
  hook.baseState = newState;
25784
25784
  fiber.memoizedProps = assign({}, fiber.memoizedProps);
@@ -25788,10 +25788,10 @@ var require_react_reconciler_development = __commonJS({
25788
25788
  }
25789
25789
  }
25790
25790
  };
25791
- overrideHookStateDeletePath = function(fiber, id, path11) {
25791
+ overrideHookStateDeletePath = function(fiber, id, path12) {
25792
25792
  var hook = findHook(fiber, id);
25793
25793
  if (hook !== null) {
25794
- var newState = copyWithDelete(hook.memoizedState, path11);
25794
+ var newState = copyWithDelete(hook.memoizedState, path12);
25795
25795
  hook.memoizedState = newState;
25796
25796
  hook.baseState = newState;
25797
25797
  fiber.memoizedProps = assign({}, fiber.memoizedProps);
@@ -25814,8 +25814,8 @@ var require_react_reconciler_development = __commonJS({
25814
25814
  }
25815
25815
  }
25816
25816
  };
25817
- overrideProps = function(fiber, path11, value) {
25818
- fiber.pendingProps = copyWithSet(fiber.memoizedProps, path11, value);
25817
+ overrideProps = function(fiber, path12, value) {
25818
+ fiber.pendingProps = copyWithSet(fiber.memoizedProps, path12, value);
25819
25819
  if (fiber.alternate) {
25820
25820
  fiber.alternate.pendingProps = fiber.pendingProps;
25821
25821
  }
@@ -25824,8 +25824,8 @@ var require_react_reconciler_development = __commonJS({
25824
25824
  scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
25825
25825
  }
25826
25826
  };
25827
- overridePropsDeletePath = function(fiber, path11) {
25828
- fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path11);
25827
+ overridePropsDeletePath = function(fiber, path12) {
25828
+ fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path12);
25829
25829
  if (fiber.alternate) {
25830
25830
  fiber.alternate.pendingProps = fiber.pendingProps;
25831
25831
  }
@@ -33426,7 +33426,7 @@ var init_Text = __esm({
33426
33426
  });
33427
33427
 
33428
33428
  // ../../node_modules/ink/build/components/ErrorOverview.js
33429
- import * as fs from "node:fs";
33429
+ import * as fs2 from "node:fs";
33430
33430
  import { cwd } from "node:process";
33431
33431
  function ErrorOverview({ error }) {
33432
33432
  const stack = error.stack ? error.stack.split("\n").slice(1) : void 0;
@@ -33434,8 +33434,8 @@ function ErrorOverview({ error }) {
33434
33434
  const filePath = cleanupPath(origin?.file);
33435
33435
  let excerpt;
33436
33436
  let lineWidth = 0;
33437
- if (filePath && origin?.line && fs.existsSync(filePath)) {
33438
- const sourceCode = fs.readFileSync(filePath, "utf8");
33437
+ if (filePath && origin?.line && fs2.existsSync(filePath)) {
33438
+ const sourceCode = fs2.readFileSync(filePath, "utf8");
33439
33439
  excerpt = dist_default3(sourceCode, origin.line);
33440
33440
  if (excerpt) {
33441
33441
  for (const { line } of excerpt) {
@@ -33530,8 +33530,8 @@ var init_ErrorOverview = __esm({
33530
33530
  init_dist3();
33531
33531
  init_Box();
33532
33532
  init_Text();
33533
- cleanupPath = (path11) => {
33534
- return path11?.replace(`file://${cwd()}/`, "");
33533
+ cleanupPath = (path12) => {
33534
+ return path12?.replace(`file://${cwd()}/`, "");
33535
33535
  };
33536
33536
  stackUtils = new import_stack_utils.default({
33537
33537
  cwd: cwd(),
@@ -36759,7 +36759,7 @@ var require_has_flag = __commonJS({
36759
36759
  var require_supports_colors = __commonJS({
36760
36760
  "../../node_modules/@colors/colors/lib/system/supports-colors.js"(exports, module) {
36761
36761
  "use strict";
36762
- var os5 = __require("os");
36762
+ var os6 = __require("os");
36763
36763
  var hasFlag2 = require_has_flag();
36764
36764
  var env3 = process.env;
36765
36765
  var forceColor = void 0;
@@ -36797,7 +36797,7 @@ var require_supports_colors = __commonJS({
36797
36797
  }
36798
36798
  var min = forceColor ? 1 : 0;
36799
36799
  if (process.platform === "win32") {
36800
- var osRelease = os5.release().split(".");
36800
+ var osRelease = os6.release().split(".");
36801
36801
  if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
36802
36802
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
36803
36803
  }
@@ -37189,7 +37189,7 @@ var require_colors = __commonJS({
37189
37189
  var colors = {};
37190
37190
  module["exports"] = colors;
37191
37191
  colors.themes = {};
37192
- var util = __require("util");
37192
+ var util3 = __require("util");
37193
37193
  var ansiStyles3 = colors.styles = require_styles();
37194
37194
  var defineProps = Object.defineProperties;
37195
37195
  var newLineRegex = new RegExp(/[\r\n]+/g);
@@ -37252,7 +37252,7 @@ var require_colors = __commonJS({
37252
37252
  if (arg != null && arg.constructor === String) {
37253
37253
  return arg;
37254
37254
  } else {
37255
- return util.inspect(arg);
37255
+ return util3.inspect(arg);
37256
37256
  }
37257
37257
  }).join(" ");
37258
37258
  if (!colors.enabled || !str) {
@@ -80882,15 +80882,15 @@ var require_route = __commonJS({
80882
80882
  };
80883
80883
  }
80884
80884
  function wrapConversion(toModel, graph) {
80885
- const path11 = [graph[toModel].parent, toModel];
80885
+ const path12 = [graph[toModel].parent, toModel];
80886
80886
  let fn = conversions[graph[toModel].parent][toModel];
80887
80887
  let cur = graph[toModel].parent;
80888
80888
  while (graph[cur].parent) {
80889
- path11.unshift(graph[cur].parent);
80889
+ path12.unshift(graph[cur].parent);
80890
80890
  fn = link2(conversions[graph[cur].parent][cur], fn);
80891
80891
  cur = graph[cur].parent;
80892
80892
  }
80893
- fn.conversion = path11;
80893
+ fn.conversion = path12;
80894
80894
  return fn;
80895
80895
  }
80896
80896
  module.exports = function(fromModel) {
@@ -81130,7 +81130,7 @@ var require_has_flag2 = __commonJS({
81130
81130
  var require_supports_color = __commonJS({
81131
81131
  "../../node_modules/supports-color/index.js"(exports, module) {
81132
81132
  "use strict";
81133
- var os5 = __require("os");
81133
+ var os6 = __require("os");
81134
81134
  var tty2 = __require("tty");
81135
81135
  var hasFlag2 = require_has_flag2();
81136
81136
  var { env: env3 } = process;
@@ -81178,7 +81178,7 @@ var require_supports_color = __commonJS({
81178
81178
  return min;
81179
81179
  }
81180
81180
  if (process.platform === "win32") {
81181
- const osRelease = os5.release().split(".");
81181
+ const osRelease = os6.release().split(".");
81182
81182
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
81183
81183
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
81184
81184
  }
@@ -96159,10 +96159,10 @@ var init_session_store = __esm({
96159
96159
  if (!ID.test(id)) throw new SessionError(this.dir, `Invalid session id ${JSON.stringify(id)}`);
96160
96160
  return path.join(this.dir, `${id}.jsonl`);
96161
96161
  }
96162
- async save(session) {
96163
- const file = this.fileFor(session.meta.id);
96164
- const meta = { ...session.meta, updatedAt: this.now().toISOString() };
96165
- const body = [meta, ...session.messages].map((entry) => JSON.stringify(redactCredentials(entry))).join("\n") + "\n";
96162
+ async save(session2) {
96163
+ const file = this.fileFor(session2.meta.id);
96164
+ const meta = { ...session2.meta, updatedAt: this.now().toISOString() };
96165
+ const body = [meta, ...session2.messages].map((entry) => JSON.stringify(redactCredentials(entry))).join("\n") + "\n";
96166
96166
  const bytes = Buffer.byteLength(body);
96167
96167
  if (bytes > MAX_SESSION_BYTES) {
96168
96168
  throw new SessionError(file, `Session is ${bytes} bytes, over the ${MAX_SESSION_BYTES}-byte cap; use /compact or /clear`);
@@ -96191,9 +96191,9 @@ var init_session_store = __esm({
96191
96191
  if (err instanceof SessionError) throw err;
96192
96192
  throw new SessionError(file, `Could not read session: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
96193
96193
  }
96194
- const session = parseSession(file, text);
96195
- if (session.meta.id !== id) throw new SessionError(file, `Session header id "${session.meta.id}" does not match the file name`);
96196
- return session;
96194
+ const session2 = parseSession(file, text);
96195
+ if (session2.meta.id !== id) throw new SessionError(file, `Session header id "${session2.meta.id}" does not match the file name`);
96196
+ return session2;
96197
96197
  }
96198
96198
  /** Newest first. Unreadable files are reported, not skipped silently. */
96199
96199
  async list() {
@@ -97276,17 +97276,17 @@ function isSubsequence(needle, hay) {
97276
97276
  for (let j2 = 0; j2 < hay.length && i < needle.length; j2++) if (hay[j2] === needle[i]) i++;
97277
97277
  return i === needle.length;
97278
97278
  }
97279
- function tier(path11, q2) {
97280
- const base = path11.slice(path11.lastIndexOf("/") + 1);
97279
+ function tier(path12, q2) {
97280
+ const base = path12.slice(path12.lastIndexOf("/") + 1);
97281
97281
  if (base.startsWith(q2)) return 0;
97282
97282
  if (base.includes(q2)) return 1;
97283
- if (path11.includes(q2)) return 2;
97283
+ if (path12.includes(q2)) return 2;
97284
97284
  return 3;
97285
97285
  }
97286
97286
  function rankPaths(paths, query, limit = 8) {
97287
97287
  if (query === "") return paths.slice(0, limit);
97288
97288
  const q2 = query.toLowerCase();
97289
- return paths.map((path11) => ({ path: path11, lower: path11.toLowerCase() })).filter(({ lower }) => isSubsequence(q2, lower)).map(({ path: path11, lower }) => ({ path: path11, rank: tier(lower, q2) })).sort((a, b2) => a.rank - b2.rank || a.path.length - b2.path.length || (a.path < b2.path ? -1 : a.path > b2.path ? 1 : 0)).slice(0, limit).map((m2) => m2.path);
97289
+ return paths.map((path12) => ({ path: path12, lower: path12.toLowerCase() })).filter(({ lower }) => isSubsequence(q2, lower)).map(({ path: path12, lower }) => ({ path: path12, rank: tier(lower, q2) })).sort((a, b2) => a.rank - b2.rank || a.path.length - b2.path.length || (a.path < b2.path ? -1 : a.path > b2.path ? 1 : 0)).slice(0, limit).map((m2) => m2.path);
97290
97290
  }
97291
97291
  var init_mention_rank = __esm({
97292
97292
  "src/editor/mention-rank.ts"() {
@@ -97303,9 +97303,9 @@ function activeMention(text, cursor) {
97303
97303
  const explicit = token[1] === "!";
97304
97304
  return { start, query: token.slice(explicit ? 2 : 1), explicit };
97305
97305
  }
97306
- function insertMention(text, cursor, mention, path11) {
97307
- if (/\s/.test(path11)) return { text, cursor };
97308
- const inserted = `@${mention.explicit ? "!" : ""}${path11}`;
97306
+ function insertMention(text, cursor, mention, path12) {
97307
+ if (/\s/.test(path12)) return { text, cursor };
97308
+ const inserted = `@${mention.explicit ? "!" : ""}${path12}`;
97309
97309
  const head = text.slice(0, mention.start) + inserted;
97310
97310
  const next = text[cursor];
97311
97311
  if (next !== void 0 && /\s/.test(next)) return { text: head + text.slice(cursor), cursor: head.length + 1 };
@@ -97392,7 +97392,7 @@ function validateSubmission(text) {
97392
97392
  function withCursor(row, col) {
97393
97393
  return `${row.slice(0, col)}\x1B[7m${row[col] ?? " "}\x1B[27m${row.slice(col + 1)}`;
97394
97394
  }
97395
- function PromptEditor({ onSubmit, disabled, history, listFiles: listFiles2, onTab, locked = false, promptGlyph: promptGlyph2 = ">", onEmptyEnter, unicode = true }) {
97395
+ function PromptEditor({ onSubmit, disabled, history, listFiles: listFiles2, onTab, locked = false, promptGlyph: promptGlyph2 = ">", onEmptyEnter, unicode = true, fullWidth = false }) {
97396
97396
  const { exit } = use_app_default();
97397
97397
  const { columns } = useTerminalSize();
97398
97398
  const { isRawModeSupported } = use_stdin_default();
@@ -97552,7 +97552,7 @@ function PromptEditor({ onSubmit, disabled, history, listFiles: listFiles2, onTa
97552
97552
  const picks = mention && files ? rankPaths(files, mention.query, PICKER_ROWS) : [];
97553
97553
  const pickAt = Math.min(sel, Math.max(picks.length - 1, 0));
97554
97554
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", children: [
97555
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box_default, { flexDirection: "column", borderStyle: unicode ? "round" : "classic", borderColor: paint("secondary").color, borderDimColor: disabled, paddingX: 1, width: Math.min(columns, MAX_STATIC_LINE), children: rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { children: [
97555
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box_default, { flexDirection: "column", borderStyle: unicode ? "round" : "classic", borderColor: paint("secondary").color, borderDimColor: disabled, paddingX: 1, width: fullWidth ? columns : Math.min(columns, MAX_STATIC_LINE), children: rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { children: [
97556
97556
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { ...paint(shell ? "action" : "agent"), bold: true, dimColor: disabled, children: i === 0 ? shell ? "! " : `${promptGlyph2} ` : " " }),
97557
97557
  disabled && !locked && buf.text === "" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { ...paint("secondary"), children: "turn running - type to queue your next prompt" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { dimColor: disabled, children: i === line && !disabled ? withCursor(row, col) : row })
97558
97558
  ] }, i)) }),
@@ -98364,9 +98364,9 @@ function createFileTools(store) {
98364
98364
  readCache.clear();
98365
98365
  listCache.clear();
98366
98366
  }
98367
- function invalidatePath(path11) {
98368
- readCache.delete(path11);
98369
- const parent = path11.includes("/") ? path11.slice(0, path11.lastIndexOf("/") + 1) : "";
98367
+ function invalidatePath(path12) {
98368
+ readCache.delete(path12);
98369
+ const parent = path12.includes("/") ? path12.slice(0, path12.lastIndexOf("/") + 1) : "";
98370
98370
  listCache.delete(parent);
98371
98371
  listCache.delete("");
98372
98372
  listCache.delete(".");
@@ -98374,36 +98374,36 @@ function createFileTools(store) {
98374
98374
  }
98375
98375
  const handlers = {
98376
98376
  read_file: async (input) => {
98377
- const path11 = input.path;
98378
- const cached = readCache.get(path11);
98377
+ const path12 = input.path;
98378
+ const cached = readCache.get(path12);
98379
98379
  if (cached !== void 0) {
98380
98380
  return { output: cached };
98381
98381
  }
98382
- const content = await store.readFile(path11);
98382
+ const content = await store.readFile(path12);
98383
98383
  if (content === null) {
98384
- return { output: `File not found: ${path11}`, is_error: true };
98384
+ return { output: `File not found: ${path12}`, is_error: true };
98385
98385
  }
98386
- readCache.set(path11, content);
98386
+ readCache.set(path12, content);
98387
98387
  return { output: content };
98388
98388
  },
98389
98389
  write_file: async (input) => {
98390
- const path11 = input.path;
98390
+ const path12 = input.path;
98391
98391
  const content = input.content;
98392
- await store.writeFile(path11, content);
98393
- invalidatePath(path11);
98394
- readCache.set(path11, content);
98395
- return { output: `Written: ${path11}` };
98392
+ await store.writeFile(path12, content);
98393
+ invalidatePath(path12);
98394
+ readCache.set(path12, content);
98395
+ return { output: `Written: ${path12}` };
98396
98396
  },
98397
98397
  edit_file: async (input) => {
98398
- const path11 = input.path;
98398
+ const path12 = input.path;
98399
98399
  const oldStr = input.old_string;
98400
98400
  const newStr = input.new_string;
98401
- let content = readCache.get(path11);
98401
+ let content = readCache.get(path12);
98402
98402
  if (content === void 0) {
98403
- const stored = await store.readFile(path11);
98403
+ const stored = await store.readFile(path12);
98404
98404
  if (stored === null) {
98405
98405
  return {
98406
- output: `File not found: ${path11}. Did you read the file first?`,
98406
+ output: `File not found: ${path12}. Did you read the file first?`,
98407
98407
  is_error: true
98408
98408
  };
98409
98409
  }
@@ -98413,41 +98413,41 @@ function createFileTools(store) {
98413
98413
  if (lineNumbers.length === 0) {
98414
98414
  const lineCount = content.split("\n").length;
98415
98415
  return {
98416
- output: `old_string not found in ${path11}. The file has ${lineCount} lines. Did you read the file first?`,
98416
+ output: `old_string not found in ${path12}. The file has ${lineCount} lines. Did you read the file first?`,
98417
98417
  is_error: true
98418
98418
  };
98419
98419
  }
98420
98420
  if (lineNumbers.length > 1) {
98421
98421
  const locations = lineNumbers.map((ln) => ` - line ${ln}`).join("\n");
98422
98422
  return {
98423
- output: `old_string matches ${lineNumbers.length} locations in ${path11}:
98423
+ output: `old_string matches ${lineNumbers.length} locations in ${path12}:
98424
98424
  ${locations}
98425
98425
  Include more surrounding context to make old_string unique.`,
98426
98426
  is_error: true
98427
98427
  };
98428
98428
  }
98429
- const result = await store.editFile(path11, oldStr, newStr);
98429
+ const result = await store.editFile(path12, oldStr, newStr);
98430
98430
  if (!result.success) {
98431
98431
  return { output: result.error, is_error: true };
98432
98432
  }
98433
- invalidatePath(path11);
98434
- const updated = await store.readFile(path11);
98435
- if (updated !== null) readCache.set(path11, updated);
98436
- return { output: `Edited: ${path11}` };
98433
+ invalidatePath(path12);
98434
+ const updated = await store.readFile(path12);
98435
+ if (updated !== null) readCache.set(path12, updated);
98436
+ return { output: `Edited: ${path12}` };
98437
98437
  },
98438
98438
  list_directory: async (input) => {
98439
- const path11 = input.path;
98440
- const cached = listCache.get(path11);
98439
+ const path12 = input.path;
98440
+ const cached = listCache.get(path12);
98441
98441
  if (cached !== void 0) {
98442
98442
  if (cached.length === 0) {
98443
- return { output: `Empty or not found: ${path11}` };
98443
+ return { output: `Empty or not found: ${path12}` };
98444
98444
  }
98445
98445
  return { output: cached.join("\n") };
98446
98446
  }
98447
- const entries = await store.listDirectory(path11);
98448
- listCache.set(path11, entries);
98447
+ const entries = await store.listDirectory(path12);
98448
+ listCache.set(path12, entries);
98449
98449
  if (entries.length === 0) {
98450
- return { output: `Empty or not found: ${path11}` };
98450
+ return { output: `Empty or not found: ${path12}` };
98451
98451
  }
98452
98452
  return { output: entries.join("\n") };
98453
98453
  }
@@ -98784,7 +98784,7 @@ var init_host = __esm({
98784
98784
 
98785
98785
  // ../agent/src/host/local-host.ts
98786
98786
  import { execFile as execFile2 } from "node:child_process";
98787
- import { promises as fs2 } from "node:fs";
98787
+ import { promises as fs3 } from "node:fs";
98788
98788
  import * as path3 from "node:path";
98789
98789
  var LocalHost;
98790
98790
  var init_local_host = __esm({
@@ -98811,18 +98811,18 @@ var init_local_host = __esm({
98811
98811
  async resolve(p) {
98812
98812
  const abs = path3.resolve(this.root, p);
98813
98813
  if (!_LocalHost.inside(this.root, abs)) throw new Error(`Path escapes workspace root: ${p}`);
98814
- const realRoot = await fs2.realpath(this.root);
98814
+ const realRoot = await fs3.realpath(this.root);
98815
98815
  let probe = abs;
98816
98816
  for (; ; ) {
98817
98817
  try {
98818
- const real = await fs2.realpath(probe);
98818
+ const real = await fs3.realpath(probe);
98819
98819
  if (!_LocalHost.inside(realRoot, real)) {
98820
98820
  throw new Error(`Path escapes workspace root via symlink: ${p}`);
98821
98821
  }
98822
98822
  break;
98823
98823
  } catch (err) {
98824
98824
  if (err.code !== "ENOENT") throw err;
98825
- const st = await fs2.lstat(probe).catch((e) => {
98825
+ const st = await fs3.lstat(probe).catch((e) => {
98826
98826
  if (e.code === "ENOENT") return null;
98827
98827
  throw e;
98828
98828
  });
@@ -98836,7 +98836,7 @@ var init_local_host = __esm({
98836
98836
  }
98837
98837
  async readFile(p) {
98838
98838
  try {
98839
- return await fs2.readFile(await this.resolve(p), "utf8");
98839
+ return await fs3.readFile(await this.resolve(p), "utf8");
98840
98840
  } catch (err) {
98841
98841
  if (err.code === "ENOENT") return null;
98842
98842
  throw err;
@@ -98844,8 +98844,8 @@ var init_local_host = __esm({
98844
98844
  }
98845
98845
  async writeFile(p, content) {
98846
98846
  const abs = await this.resolve(p);
98847
- await fs2.mkdir(path3.dirname(abs), { recursive: true });
98848
- await fs2.writeFile(abs, content, "utf8");
98847
+ await fs3.mkdir(path3.dirname(abs), { recursive: true });
98848
+ await fs3.writeFile(abs, content, "utf8");
98849
98849
  }
98850
98850
  async editFile(p, oldStr, newStr) {
98851
98851
  const content = await this.readFile(p);
@@ -98860,7 +98860,7 @@ var init_local_host = __esm({
98860
98860
  }
98861
98861
  async listDirectory(p) {
98862
98862
  try {
98863
- const entries = await fs2.readdir(await this.resolve(p), { withFileTypes: true });
98863
+ const entries = await fs3.readdir(await this.resolve(p), { withFileTypes: true });
98864
98864
  return entries.map((e) => e.isDirectory() ? `${e.name}/` : e.name);
98865
98865
  } catch (err) {
98866
98866
  if (err.code === "ENOENT") return [];
@@ -99135,7 +99135,7 @@ var init_policy = __esm({
99135
99135
  });
99136
99136
 
99137
99137
  // ../agent/src/host/audit-log.ts
99138
- import { promises as fs3 } from "node:fs";
99138
+ import { promises as fs4 } from "node:fs";
99139
99139
  import * as path4 from "node:path";
99140
99140
  function truncate(e) {
99141
99141
  return e.subject.length > MAX_SUBJECT ? { ...e, subject: e.subject.slice(0, MAX_SUBJECT) + "...[truncated]" } : e;
@@ -99150,8 +99150,8 @@ var init_audit_log = __esm({
99150
99150
  this.file = file;
99151
99151
  }
99152
99152
  async record(entry) {
99153
- await fs3.mkdir(path4.dirname(this.file), { recursive: true });
99154
- await fs3.appendFile(this.file, JSON.stringify(truncate(entry)) + "\n", { mode: 384 });
99153
+ await fs4.mkdir(path4.dirname(this.file), { recursive: true });
99154
+ await fs4.appendFile(this.file, JSON.stringify(truncate(entry)) + "\n", { mode: 384 });
99155
99155
  }
99156
99156
  };
99157
99157
  }
@@ -99891,10 +99891,10 @@ async function readGitignore(cwd2) {
99891
99891
  }
99892
99892
  }
99893
99893
  function createNodeMentions(cwd2) {
99894
- const fs4 = createNodeMentionFS(cwd2);
99894
+ const fs6 = createNodeMentionFS(cwd2);
99895
99895
  return {
99896
99896
  async attach(text) {
99897
- const result = await resolveMentions(text, { cwd: cwd2, fs: fs4, ignored: await readGitignore(cwd2) });
99897
+ const result = await resolveMentions(text, { cwd: cwd2, fs: fs6, ignored: await readGitignore(cwd2) });
99898
99898
  return formatMentionPrompt(text, result);
99899
99899
  },
99900
99900
  async list() {
@@ -100701,6 +100701,31 @@ var init_ResumePicker = __esm({
100701
100701
  }
100702
100702
  });
100703
100703
 
100704
+ // src/components/Transcript.tsx
100705
+ function Transcript({ scroll, onMeasure, children }) {
100706
+ const viewportRef = (0, import_react33.useRef)(null);
100707
+ const contentRef = (0, import_react33.useRef)(null);
100708
+ const last = (0, import_react33.useRef)({ viewport: -1, content: -1 });
100709
+ (0, import_react33.useLayoutEffect)(() => {
100710
+ if (!viewportRef.current || !contentRef.current) return;
100711
+ const viewport = measure_element_default(viewportRef.current).height;
100712
+ const content = measure_element_default(contentRef.current).height;
100713
+ if (viewport === last.current.viewport && content === last.current.content) return;
100714
+ last.current = { viewport, content };
100715
+ onMeasure(viewport, content);
100716
+ });
100717
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Box_default, { ref: viewportRef, flexDirection: "column", flexGrow: 1, flexShrink: 1, flexBasis: 0, overflow: "hidden", justifyContent: "flex-end", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Box_default, { ref: contentRef, flexDirection: "column", flexShrink: 0, marginBottom: -scroll, children }) });
100718
+ }
100719
+ var import_react33, import_jsx_runtime12;
100720
+ var init_Transcript = __esm({
100721
+ async "src/components/Transcript.tsx"() {
100722
+ "use strict";
100723
+ import_react33 = __toESM(require_react(), 1);
100724
+ await init_build2();
100725
+ import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
100726
+ }
100727
+ });
100728
+
100704
100729
  // src/App.tsx
100705
100730
  var App_exports = {};
100706
100731
  __export(App_exports, {
@@ -100708,39 +100733,58 @@ __export(App_exports, {
100708
100733
  });
100709
100734
  import os4 from "node:os";
100710
100735
  import path10 from "node:path";
100711
- function App2({ repoName: repoName2, onboardingMode: onboardingMode2, launchCount: launchCount2, yolo: yolo2, history, sessions, resumeLatest: resumeLatest2, git: gitRunner, interactivePicker = true }) {
100712
- const promptHistory = (0, import_react33.useMemo)(
100736
+ function App2({ repoName: repoName2, onboardingMode: onboardingMode2, launchCount: launchCount2, yolo: yolo2, history, sessions, resumeLatest: resumeLatest2, git: gitRunner, interactivePicker = true, fullscreen: fullscreen2 = false }) {
100737
+ const promptHistory = (0, import_react34.useMemo)(
100713
100738
  () => history ?? new PromptHistory(createFileHistoryIO(path10.join(os4.homedir(), ".spacecode", "history"))),
100714
100739
  [history]
100715
100740
  );
100716
- const sessionStore = (0, import_react33.useMemo)(() => sessions ?? new SessionStore(path10.join(os4.homedir(), ".spacecode", "sessions")), [sessions]);
100717
- const runGit = (0, import_react33.useMemo)(() => gitRunner ?? createNodeGitRunner(process.cwd()), [gitRunner]);
100718
- const startedAtRef = (0, import_react33.useRef)(Date.now());
100719
- const [viewingRaw, setViewing] = (0, import_react33.useState)(false);
100720
- const escViewRef = (0, import_react33.useRef)(false);
100721
- const escSwallowRef = (0, import_react33.useRef)(false);
100722
- const swallowEsc = (0, import_react33.useCallback)(() => {
100741
+ const sessionStore = (0, import_react34.useMemo)(() => sessions ?? new SessionStore(path10.join(os4.homedir(), ".spacecode", "sessions")), [sessions]);
100742
+ const runGit = (0, import_react34.useMemo)(() => gitRunner ?? createNodeGitRunner(process.cwd()), [gitRunner]);
100743
+ const startedAtRef = (0, import_react34.useRef)(Date.now());
100744
+ const [viewingRaw, setViewing] = (0, import_react34.useState)(false);
100745
+ const escViewRef = (0, import_react34.useRef)(false);
100746
+ const escSwallowRef = (0, import_react34.useRef)(false);
100747
+ const swallowEsc = (0, import_react34.useCallback)(() => {
100723
100748
  escSwallowRef.current = true;
100724
100749
  setTimeout(() => {
100725
100750
  escSwallowRef.current = false;
100726
100751
  }, 0);
100727
100752
  }, []);
100728
- const isEscOwned = (0, import_react33.useCallback)(() => escViewRef.current || escSwallowRef.current, []);
100729
- const openViewer = (0, import_react33.useCallback)(() => setViewing(true), []);
100753
+ const isEscOwned = (0, import_react34.useCallback)(() => escViewRef.current || escSwallowRef.current, []);
100754
+ const openViewer = (0, import_react34.useCallback)(() => setViewing(true), []);
100730
100755
  const { isRawModeSupported } = use_stdin_default();
100731
- const [resumeFound, setResumeFound] = (0, import_react33.useState)(null);
100732
- const openResume = (0, import_react33.useCallback)((found) => setResumeFound(found), []);
100756
+ const [resumeFound, setResumeFound] = (0, import_react34.useState)(null);
100757
+ const openResume = (0, import_react34.useCallback)((found) => setResumeFound(found), []);
100733
100758
  const { turns, events, isRunning, livePrompt, notices, pending, mode, todos, stats, submit, retry, mentions, replayed, resume } = useReplController({ repoName: repoName2, yolo: yolo2, sessions: sessionStore, resumeLatest: resumeLatest2, onViewTurns: openViewer, onViewResume: isRawModeSupported && interactivePicker ? openResume : void 0, isEscOwned });
100734
100759
  const { columns, rows } = useTerminalSize();
100735
100760
  const viewing = viewingRaw && !pending;
100736
100761
  const picking = resumeFound !== null && !pending;
100737
- const liveSteps = (0, import_react33.useMemo)(() => stepsOfEvents(events), [events]);
100738
- const [focusId, setFocusId] = (0, import_react33.useState)(null);
100739
- const [openId, setOpenId] = (0, import_react33.useState)(null);
100762
+ const [scroll, setScroll] = (0, import_react34.useState)(0);
100763
+ const measured = (0, import_react34.useRef)({ viewport: 0, content: 0 });
100764
+ const onMeasure = (0, import_react34.useCallback)((viewport, content) => {
100765
+ if (viewport <= 0) return;
100766
+ const prev = measured.current;
100767
+ measured.current = { viewport, content };
100768
+ setScroll((s) => s === 0 ? 0 : Math.min(Math.max(0, content - viewport), s + Math.max(0, content - prev.content)));
100769
+ }, []);
100770
+ const pageBy = (0, import_react34.useCallback)((dir) => {
100771
+ const { viewport, content } = measured.current;
100772
+ setScroll((s) => Math.min(Math.max(0, content - viewport), Math.max(0, s + dir * Math.max(1, viewport - 2))));
100773
+ }, []);
100774
+ use_input_default((_input, key) => {
100775
+ if (key.pageUp) pageBy(1);
100776
+ else if (key.pageDown) pageBy(-1);
100777
+ }, { isActive: fullscreen2 && Boolean(isRawModeSupported) && !viewing && !picking });
100778
+ (0, import_react34.useEffect)(() => {
100779
+ if (pending || isRunning) setScroll(0);
100780
+ }, [pending, isRunning]);
100781
+ const liveSteps = (0, import_react34.useMemo)(() => stepsOfEvents(events), [events]);
100782
+ const [focusId, setFocusId] = (0, import_react34.useState)(null);
100783
+ const [openId, setOpenId] = (0, import_react34.useState)(null);
100740
100784
  const focusIdx = focusId === null ? -1 : liveSteps.findIndex((r) => r.id === focusId);
100741
100785
  const focusing = focusIdx >= 0 && !viewing && !picking && !pending;
100742
100786
  escViewRef.current = focusing || viewing || picking;
100743
- const enterFocus = (0, import_react33.useCallback)(() => {
100787
+ const enterFocus = (0, import_react34.useCallback)(() => {
100744
100788
  if (liveSteps.length > 0) setFocusId(liveSteps[liveSteps.length - 1].id);
100745
100789
  }, [liveSteps]);
100746
100790
  use_input_default((input, key) => {
@@ -100762,11 +100806,11 @@ function App2({ repoName: repoName2, onboardingMode: onboardingMode2, launchCoun
100762
100806
  if (key.ctrl && input === "o") setViewing(true);
100763
100807
  }, { isActive: Boolean(isRawModeSupported) && !viewing && !picking && !pending });
100764
100808
  const waitingStep = pending ? findBlockedStep(liveSteps, pending.req) : void 0;
100765
- const promptNode = pending ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PermissionPrompt, { req: pending.req, onDecide: pending.resolve }, pending.id) : null;
100766
- const viewerTurns = (0, import_react33.useMemo)(() => [...replayed, ...turns], [replayed, turns]);
100767
- const turnSteps = (0, import_react33.useMemo)(() => viewing ? stepsOfTurns(viewerTurns) : /* @__PURE__ */ new Map(), [viewing, viewerTurns]);
100768
- const [gitState, setGitState] = (0, import_react33.useState)(null);
100769
- (0, import_react33.useEffect)(() => {
100809
+ const promptNode = pending ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PermissionPrompt, { req: pending.req, onDecide: pending.resolve }, pending.id) : null;
100810
+ const viewerTurns = (0, import_react34.useMemo)(() => [...replayed, ...turns], [replayed, turns]);
100811
+ const turnSteps = (0, import_react34.useMemo)(() => viewing ? stepsOfTurns(viewerTurns) : /* @__PURE__ */ new Map(), [viewing, viewerTurns]);
100812
+ const [gitState, setGitState] = (0, import_react34.useState)(null);
100813
+ (0, import_react34.useEffect)(() => {
100770
100814
  let live = true;
100771
100815
  void readGitState(runGit).then((g2) => {
100772
100816
  if (live) setGitState(g2);
@@ -100776,20 +100820,57 @@ function App2({ repoName: repoName2, onboardingMode: onboardingMode2, launchCoun
100776
100820
  };
100777
100821
  }, [runGit, turns.length]);
100778
100822
  const footer = formatFooter({ mode, contextPct: stats.contextPct, costUsd: stats.costUsd, model: stats.model, columns });
100779
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", children: [
100780
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Header, { project: repoName2 ?? path10.basename(process.cwd()), git: gitState, turns: turns.length, elapsedMs: Date.now() - startedAtRef.current, columns }),
100781
- notices.map((n, i) => typeof n === "string" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { ...paint("action"), children: n }, i) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ErrorBlock, { view: n.error }, i)),
100782
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Static, { items: [BANNER, ...turns], children: (turn) => typeof turn === "symbol" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(WelcomeBanner, { repoName: repoName2, onboardingMode: onboardingMode2, launchCount: launchCount2 }, "banner") : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", children: [
100783
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { ...paint("secondary"), children: [
100823
+ const turnNode = (turn) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TurnBlock, { turn }, turn.id);
100824
+ if (fullscreen2) {
100825
+ const hidden = viewing || picking;
100826
+ const unicode = activeGlyphs().rail === "\u2502";
100827
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", height: Math.max(rows - 1, 5), children: [
100828
+ viewing && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TurnViewer, { turns: viewerTurns, steps: turnSteps, rows: rows - 2, columns, onClose: () => setViewing(false), onEscape: swallowEsc }),
100829
+ picking && resumeFound && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ResumePicker, { sessions: resumeFound.sessions, errors: resumeFound.errors, projectRoot: process.cwd(), now: /* @__PURE__ */ new Date(), rows: rows - 2, columns, preview: resume.preview, onResume: resume.load, onDelete: resume.remove, onClose: () => setResumeFound(null), onEscape: swallowEsc }),
100830
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, display: hidden ? "none" : "flex", children: [
100831
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Header, { project: repoName2 ?? path10.basename(process.cwd()), git: gitState, turns: turns.length, elapsedMs: Date.now() - startedAtRef.current, columns }) }),
100832
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Transcript, { scroll, onMeasure, children: [
100833
+ notices.map((n, i) => typeof n === "string" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("action"), children: n }, i) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ErrorBlock, { view: n.error }, i)),
100834
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(WelcomeBanner, { repoName: repoName2, onboardingMode: onboardingMode2, launchCount: launchCount2 }),
100835
+ turns.map(turnNode),
100836
+ livePrompt !== null && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { ...paint("secondary"), children: [
100837
+ "> ",
100838
+ livePrompt
100839
+ ] }),
100840
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EventRenderer, { deferErrors: true, events, liveMaxLines: Math.max(6, rows - 12), focusId: focusing ? focusId : null, openId: focusing ? openId : null, detailRows: Math.max(4, rows - 14), waitingId: waitingStep?.id ?? null, prompt: promptNode }),
100841
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TodoChecklist, { todos }),
100842
+ pending && !waitingStep && promptNode
100843
+ ] }),
100844
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", flexShrink: 0, children: [
100845
+ scroll > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { ...paint("needsYou"), children: [
100846
+ unicode ? "\u2193" : "v",
100847
+ " scrolled up ",
100848
+ scroll,
100849
+ " lines - PgDn for newer output"
100850
+ ] }),
100851
+ isRunning && !pending && stats.elapsedMs !== null && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: formatThinking(stats.elapsedMs, stats.approxTokens, unicode) }),
100852
+ focusing && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: unicode ? "step focus: \u2191\u2193 or tab move \xB7 enter open/close \xB7 esc back to the prompt" : "step focus: up/down or tab move - enter open/close - esc back to the prompt" }),
100853
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PromptEditor, { onEmptyEnter: isRunning ? void 0 : retry, promptGlyph: promptGlyph(mode, unicode), unicode, fullWidth: true, onSubmit: submit, disabled: isRunning, history: promptHistory, listFiles: mentions.list, onTab: enterFocus, locked: focusing || viewing || picking || Boolean(pending) }),
100854
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...footer.level === "critical" ? paint("delete") : footer.level === "warn" ? paint("needsYou") : paint("secondary"), children: footer.text }),
100855
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: formatHints({ running: isRunning, asking: Boolean(pending), columns }, activeGlyphs().sep) })
100856
+ ] })
100857
+ ] })
100858
+ ] });
100859
+ }
100860
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", children: [
100861
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Header, { project: repoName2 ?? path10.basename(process.cwd()), git: gitState, turns: turns.length, elapsedMs: Date.now() - startedAtRef.current, columns }),
100862
+ notices.map((n, i) => typeof n === "string" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("action"), children: n }, i) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ErrorBlock, { view: n.error }, i)),
100863
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Static, { items: [BANNER, ...turns], children: (turn) => typeof turn === "symbol" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(WelcomeBanner, { repoName: repoName2, onboardingMode: onboardingMode2, launchCount: launchCount2 }, "banner") : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", children: [
100864
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { ...paint("secondary"), children: [
100784
100865
  "> ",
100785
100866
  turn.prompt
100786
100867
  ] }),
100787
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EventRenderer, { events: turn.events, promptSaved: turn.retained }),
100788
- turn.interrupted && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { ...paint("needsYou"), children: "Interrupted" }),
100789
- turn.summary && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { ...paint("secondary"), children: turn.summary })
100868
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EventRenderer, { events: turn.events, promptSaved: turn.retained }),
100869
+ turn.interrupted && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("needsYou"), children: "Interrupted" }),
100870
+ turn.summary && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: turn.summary })
100790
100871
  ] }, turn.id) }),
100791
- viewing && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TurnViewer, { turns: viewerTurns, steps: turnSteps, rows, columns, onClose: () => setViewing(false), onEscape: swallowEsc }),
100792
- picking && resumeFound && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
100872
+ viewing && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TurnViewer, { turns: viewerTurns, steps: turnSteps, rows, columns, onClose: () => setViewing(false), onEscape: swallowEsc }),
100873
+ picking && resumeFound && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
100793
100874
  ResumePicker,
100794
100875
  {
100795
100876
  sessions: resumeFound.sessions,
@@ -100805,27 +100886,27 @@ function App2({ repoName: repoName2, onboardingMode: onboardingMode2, launchCoun
100805
100886
  onEscape: swallowEsc
100806
100887
  }
100807
100888
  ),
100808
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", display: viewing || picking ? "none" : "flex", children: [
100809
- livePrompt !== null && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { ...paint("secondary"), children: [
100889
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", display: viewing || picking ? "none" : "flex", children: [
100890
+ livePrompt !== null && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { ...paint("secondary"), children: [
100810
100891
  "> ",
100811
100892
  livePrompt
100812
100893
  ] }),
100813
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EventRenderer, { deferErrors: true, events, liveMaxLines: Math.max(6, rows - 15), focusId: focusing ? focusId : null, openId: focusing ? openId : null, detailRows: Math.max(4, rows - 14), waitingId: waitingStep?.id ?? null, prompt: promptNode }),
100814
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TodoChecklist, { todos }),
100894
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EventRenderer, { deferErrors: true, events, liveMaxLines: Math.max(6, rows - 15), focusId: focusing ? focusId : null, openId: focusing ? openId : null, detailRows: Math.max(4, rows - 14), waitingId: waitingStep?.id ?? null, prompt: promptNode }),
100895
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TodoChecklist, { todos }),
100815
100896
  pending && !waitingStep && promptNode,
100816
- isRunning && !pending && stats.elapsedMs !== null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { ...paint("secondary"), children: formatThinking(stats.elapsedMs, stats.approxTokens, activeGlyphs().rail === "\u2502") }),
100817
- focusing && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { ...paint("secondary"), children: activeGlyphs().rail === "\u2502" ? "step focus: \u2191\u2193 or tab move \xB7 enter open/close \xB7 esc back to the prompt" : "step focus: up/down or tab move - enter open/close - esc back to the prompt" }),
100818
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PromptEditor, { onEmptyEnter: isRunning ? void 0 : retry, promptGlyph: promptGlyph(mode, activeGlyphs().rail === "\u2502"), unicode: activeGlyphs().rail === "\u2502", onSubmit: submit, disabled: isRunning, history: promptHistory, listFiles: mentions.list, onTab: enterFocus, locked: focusing || viewing || picking || Boolean(pending) }),
100819
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { ...footer.level === "critical" ? paint("delete") : footer.level === "warn" ? paint("needsYou") : paint("secondary"), children: footer.text }),
100820
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { ...paint("secondary"), children: formatHints({ running: isRunning, asking: Boolean(pending), columns }, activeGlyphs().sep) })
100897
+ isRunning && !pending && stats.elapsedMs !== null && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: formatThinking(stats.elapsedMs, stats.approxTokens, activeGlyphs().rail === "\u2502") }),
100898
+ focusing && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: activeGlyphs().rail === "\u2502" ? "step focus: \u2191\u2193 or tab move \xB7 enter open/close \xB7 esc back to the prompt" : "step focus: up/down or tab move - enter open/close - esc back to the prompt" }),
100899
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PromptEditor, { onEmptyEnter: isRunning ? void 0 : retry, promptGlyph: promptGlyph(mode, activeGlyphs().rail === "\u2502"), unicode: activeGlyphs().rail === "\u2502", onSubmit: submit, disabled: isRunning, history: promptHistory, listFiles: mentions.list, onTab: enterFocus, locked: focusing || viewing || picking || Boolean(pending) }),
100900
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...footer.level === "critical" ? paint("delete") : footer.level === "warn" ? paint("needsYou") : paint("secondary"), children: footer.text }),
100901
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: formatHints({ running: isRunning, asking: Boolean(pending), columns }, activeGlyphs().sep) })
100821
100902
  ] })
100822
100903
  ] });
100823
100904
  }
100824
- var import_react33, import_jsx_runtime12, BANNER;
100905
+ var import_react34, import_jsx_runtime13, BANNER, TurnBlock;
100825
100906
  var init_App2 = __esm({
100826
100907
  async "src/App.tsx"() {
100827
100908
  "use strict";
100828
- import_react33 = __toESM(require_react(), 1);
100909
+ import_react34 = __toESM(require_react(), 1);
100829
100910
  await init_build2();
100830
100911
  await init_WelcomeBanner();
100831
100912
  await init_Header();
@@ -100848,9 +100929,21 @@ var init_App2 = __esm({
100848
100929
  init_theme();
100849
100930
  await init_TurnViewer();
100850
100931
  await init_ResumePicker();
100932
+ await init_Transcript();
100851
100933
  init_step_view();
100852
- import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
100934
+ import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
100853
100935
  BANNER = /* @__PURE__ */ Symbol("welcome-banner");
100936
+ TurnBlock = import_react34.default.memo(function TurnBlock2({ turn }) {
100937
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", children: [
100938
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { ...paint("secondary"), children: [
100939
+ "> ",
100940
+ turn.prompt
100941
+ ] }),
100942
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EventRenderer, { events: turn.events, promptSaved: turn.retained }),
100943
+ turn.interrupted && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("needsYou"), children: "Interrupted" }),
100944
+ turn.summary && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { ...paint("secondary"), children: turn.summary })
100945
+ ] });
100946
+ });
100854
100947
  }
100855
100948
  });
100856
100949
 
@@ -100858,6 +100951,12 @@ var init_App2 = __esm({
100858
100951
  init_color_policy();
100859
100952
  applyColorPolicy(process.env, Boolean(process.stdout.isTTY));
100860
100953
 
100954
+ // src/index.tsx
100955
+ import os5 from "node:os";
100956
+ import path11 from "node:path";
100957
+ import fs5 from "node:fs";
100958
+ import util2 from "node:util";
100959
+
100861
100960
  // src/render/terminal-env.ts
100862
100961
  function hideCiVariables(env3, stdoutIsTTY) {
100863
100962
  if (!stdoutIsTTY || env3.CI !== void 0) return () => {
@@ -100869,8 +100968,75 @@ function hideCiVariables(env3, stdoutIsTTY) {
100869
100968
  };
100870
100969
  }
100871
100970
 
100971
+ // src/fullscreen.ts
100972
+ import fs from "node:fs";
100973
+ import util from "node:util";
100974
+ var ENTER = "\x1B[?1049h\x1B[2J\x1B[H\x1B[?25l";
100975
+ var LEAVE = "\x1B[?25h\x1B[?1049l";
100976
+ function shouldUseFullscreen(env3, stdout, stdinIsTTY) {
100977
+ if (!stdout.isTTY || !stdinIsTTY) return false;
100978
+ if (env3.SPACECODE_INLINE && env3.SPACECODE_INLINE !== "0") return false;
100979
+ return env3.TERM !== "dumb";
100980
+ }
100981
+ function enterFullscreen(out, proc, stderr = process.stderr) {
100982
+ let active2 = true;
100983
+ const cleanups = [];
100984
+ const leave = () => {
100985
+ if (!active2) return;
100986
+ active2 = false;
100987
+ for (const fn of cleanups) fn();
100988
+ out.write(LEAVE);
100989
+ };
100990
+ const fatal = (err) => {
100991
+ leave();
100992
+ stderr.write(`${util.inspect(err)}
100993
+ `);
100994
+ proc.exit(1);
100995
+ };
100996
+ out.write(ENTER);
100997
+ proc.on("exit", leave);
100998
+ for (const [sig, code] of [["SIGINT", 130], ["SIGTERM", 143], ["SIGHUP", 129]]) {
100999
+ proc.on(sig, () => {
101000
+ leave();
101001
+ proc.exit(code);
101002
+ });
101003
+ }
101004
+ proc.on("uncaughtException", fatal);
101005
+ proc.on("unhandledRejection", fatal);
101006
+ return { leave, onLeave: (fn) => {
101007
+ cleanups.push(fn);
101008
+ } };
101009
+ }
101010
+ function redirectConsole(file) {
101011
+ const original = { log: console.log, info: console.info, warn: console.warn, error: console.error, debug: console.debug };
101012
+ const write = (level) => (...args) => {
101013
+ try {
101014
+ fs.appendFileSync(file, `${(/* @__PURE__ */ new Date()).toISOString()} ${level} ${util.format(...args)}
101015
+ `, { mode: 384 });
101016
+ } catch (err) {
101017
+ process.stderr.write(`[spacecode] could not write ${file}: ${String(err)}
101018
+ `);
101019
+ }
101020
+ };
101021
+ console.log = write("log");
101022
+ console.info = write("info");
101023
+ console.warn = write("warn");
101024
+ console.error = write("error");
101025
+ console.debug = write("debug");
101026
+ return () => Object.assign(console, original);
101027
+ }
101028
+ function clearOnResize(stdout) {
101029
+ const clear = () => {
101030
+ stdout.write("\x1B[2J\x1B[H");
101031
+ };
101032
+ stdout.prependListener("resize", clear);
101033
+ return () => {
101034
+ stdout.off("resize", clear);
101035
+ };
101036
+ }
101037
+
100872
101038
  // src/index.tsx
100873
- var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
101039
+ var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
100874
101040
  var repoName = process.env.REPO_NAME || process.cwd().split("/").pop() || void 0;
100875
101041
  var validModes = ["guest", "new_project", "existing_repo"];
100876
101042
  var rawMode = process.env.ONBOARDING_MODE;
@@ -100887,7 +101053,34 @@ try {
100887
101053
  } finally {
100888
101054
  restoreCiVariables();
100889
101055
  }
100890
- render2(/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(App3, { repoName, onboardingMode, launchCount, yolo, resumeLatest, interactivePicker: Boolean(process.stdout.isTTY) }));
101056
+ var fullscreen = shouldUseFullscreen(process.env, process.stdout, Boolean(process.stdin.isTTY));
101057
+ var session;
101058
+ if (fullscreen) {
101059
+ const dir = path11.join(os5.homedir(), ".spacecode");
101060
+ fs5.mkdirSync(dir, { recursive: true });
101061
+ const restoreConsole = redirectConsole(path11.join(dir, "repl.log"));
101062
+ session = enterFullscreen(process.stdout, process);
101063
+ session.onLeave(restoreConsole);
101064
+ session.onLeave(clearOnResize(process.stdout));
101065
+ }
101066
+ var app = render2(
101067
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(App3, { repoName, onboardingMode, launchCount, yolo, resumeLatest, interactivePicker: Boolean(process.stdout.isTTY), fullscreen }),
101068
+ { patchConsole: !fullscreen }
101069
+ );
101070
+ if (session) {
101071
+ try {
101072
+ await app.waitUntilExit();
101073
+ session.leave();
101074
+ process.stdout.write("Session saved. Resume it with `spacecode --continue` or `/resume`.\n");
101075
+ } catch (err) {
101076
+ session.leave();
101077
+ process.stderr.write(`${util2.inspect(err)}
101078
+ `);
101079
+ process.exitCode = 1;
101080
+ } finally {
101081
+ session.leave();
101082
+ }
101083
+ }
100891
101084
  /*! Bundled license information:
100892
101085
 
100893
101086
  react/cjs/react.production.min.js: