@buildaharness/aielia 0.3.4 → 0.3.6
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/README.md +156 -35
- package/dist/PlanGraphPane.d.ts +19 -0
- package/dist/_memory-core-generated.d.ts +1764 -0
- package/dist/action-approval-service.d.ts +34 -2
- package/dist/action-record.d.ts +13 -0
- package/dist/activity-log.d.ts +4 -0
- package/dist/agent-loop.d.ts +106 -9
- package/dist/ambiguity-guard-flag.d.ts +12 -0
- package/dist/ambiguity-guard.d.ts +20 -0
- package/dist/answer-claim.d.ts +13 -1
- package/dist/ask-clarification-service.d.ts +12 -1
- package/dist/ask-response-format.d.ts +6 -0
- package/dist/assistant-session.d.ts +32 -2
- package/dist/assistant-source.d.ts +7 -0
- package/dist/assistant-types.d.ts +20 -2
- package/dist/assistant.d.ts +160 -6
- package/dist/benchmark-injected-failure.d.ts +6 -0
- package/dist/bin-BYRl4xXM.js +4985 -0
- package/dist/bin-BYRl4xXM.js.map +1 -0
- package/dist/cli-config.d.ts +3 -0
- package/dist/cli-session.d.ts +19 -5
- package/dist/cli.d.ts +26 -2
- package/dist/cli.js +1 -1
- package/dist/code-plan-templates.d.ts +21 -0
- package/dist/config.d.ts +31 -0
- package/dist/constraint-check.d.ts +35 -0
- package/dist/contradiction-checker.d.ts +7 -0
- package/dist/debug-log.d.ts +10 -1
- package/dist/decomposed-answer.d.ts +13 -0
- package/dist/decomposition-classifier.d.ts +2 -0
- package/dist/doctor-checks.d.ts +3 -0
- package/dist/email.d.ts +5 -3
- package/dist/episodic-digest.d.ts +89 -0
- package/dist/fact-extraction.d.ts +39 -0
- package/dist/file-tools-mcp-server.mjs +288 -37
- package/dist/file-tools.d.ts +6 -0
- package/dist/first-run.d.ts +0 -2
- package/dist/git-exclude.d.ts +9 -0
- package/dist/goal-graph-store.d.ts +18 -18
- package/dist/grounding-check.d.ts +33 -0
- package/dist/harness-bridge.d.ts +75 -2
- package/dist/harness-token-budget.d.ts +9 -0
- package/dist/index.d.ts +21 -2
- package/dist/index.js +166 -94
- package/dist/index.js.map +1 -1
- package/dist/ink-select-prompt.d.ts +2 -0
- package/dist/ink-test-render.d.ts +2 -0
- package/dist/layer-policy-flag.d.ts +13 -0
- package/dist/layer-policy-wiring.d.ts +77 -0
- package/dist/layer-settings.d.ts +49 -0
- package/dist/layer-telemetry.d.ts +2 -0
- package/dist/lexical/lexical-mode.d.ts +29 -0
- package/dist/memory-consolidation.d.ts +80 -0
- package/dist/memory-governance.d.ts +30 -0
- package/dist/memory-reviewer.d.ts +114 -0
- package/dist/memory-service.d.ts +356 -9
- package/dist/model-json.d.ts +17 -0
- package/dist/next-step-context.d.ts +51 -0
- package/dist/next-step-proposer.d.ts +10 -2
- package/dist/plan-drafting-service.d.ts +3 -0
- package/dist/plan-graph-flag.d.ts +20 -0
- package/dist/plan-question.d.ts +60 -0
- package/dist/plan-service.d.ts +6 -2
- package/dist/plan-step-prompt.d.ts +15 -0
- package/dist/plan-store.d.ts +12 -1
- package/dist/plan-viz/normalize.d.ts +14 -0
- package/dist/plan-viz/plan-detail-lines.d.ts +3 -0
- package/dist/plan-viz/plan-layout.d.ts +48 -0
- package/dist/plan-viz/plan-nav.d.ts +29 -0
- package/dist/plan-viz/plan-raster.d.ts +36 -0
- package/dist/plan-viz/plan-routes.d.ts +6 -0
- package/dist/plan-viz/plan-snapshot.d.ts +73 -0
- package/dist/plan-viz/plan-viewport.d.ts +29 -0
- package/dist/plan-viz/plan-width.d.ts +15 -0
- package/dist/plan-viz/testkit/display-width.d.ts +12 -0
- package/dist/plan-viz/testkit/generators.d.ts +61 -0
- package/dist/plan-viz/testkit/grid-oracles.d.ts +38 -0
- package/dist/plan-viz/testkit/nav-oracles.d.ts +79 -0
- package/dist/plan-viz/testkit/types.d.ts +8 -0
- package/dist/plan-viz/types.d.ts +34 -0
- package/dist/{provider-setup-CPbB5y_V.js → provider-setup-CV3S_TAS.js} +10792 -5731
- package/dist/provider-setup-CV3S_TAS.js.map +1 -0
- package/dist/recall-tool.d.ts +43 -0
- package/dist/recovery-note.d.ts +22 -0
- package/dist/reply-audit.d.ts +67 -0
- package/dist/response-service.d.ts +11 -1
- package/dist/review-checker.d.ts +10 -4
- package/dist/reviewer-revision.d.ts +23 -0
- package/dist/risk-classifier.d.ts +7 -0
- package/dist/scripted-llm-client.d.ts +26 -1
- package/dist/semantic-compaction.d.ts +15 -0
- package/dist/semantic-hypotheses.d.ts +40 -0
- package/dist/side-call-policy.d.ts +30 -0
- package/dist/source-reliability.d.ts +71 -0
- package/dist/task-completion-check.d.ts +24 -0
- package/dist/tool-control-plane.d.ts +33 -1
- package/dist/tool-effect-class.d.ts +9 -0
- package/dist/tool-step.d.ts +6 -0
- package/dist/trace-events.d.ts +1 -1
- package/dist/transcript-compaction.d.ts +9 -0
- package/dist/trust-tagging.d.ts +2 -0
- package/dist/{tui-app-DeyZ4Pr9.js → tui-app-CJq6YaiP.js} +436 -21
- package/dist/tui-app-CJq6YaiP.js.map +1 -0
- package/dist/tui-app.d.ts +73 -0
- package/dist/turn-abort.d.ts +18 -0
- package/dist/turn-intent-classifier.d.ts +81 -14
- package/dist/turn-interpreter.d.ts +27 -3
- package/dist/version.d.ts +1 -1
- package/package.json +6 -6
- package/dist/bin-CdVTAe7j.js +0 -2209
- package/dist/bin-CdVTAe7j.js.map +0 -1
- package/dist/provider-setup-CPbB5y_V.js.map +0 -1
- package/dist/tui-app-DeyZ4Pr9.js.map +0 -1
|
@@ -3,11 +3,11 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
5
5
|
import { Readable, Writable } from "node:stream";
|
|
6
|
-
import { useState, useRef, useCallback, useSyncExternalStore
|
|
6
|
+
import { useState, useRef, useEffect, useMemo, useCallback, useSyncExternalStore } from "react";
|
|
7
7
|
import { useWindowSize, usePaste, useInput, Box, Text, render, Static } from "ink";
|
|
8
|
-
import { r as runCli, P as PLAN_LINE_PREFIX, I as ICONS } from "./bin-
|
|
8
|
+
import { s as sanitizeLabel, r as renderPlan, t as toLines, a as runCli, P as PLAN_LINE_PREFIX, I as ICONS } from "./bin-BYRl4xXM.js";
|
|
9
9
|
import { format } from "node:util";
|
|
10
|
-
import {
|
|
10
|
+
import { n as DIFF_INDENT, bL as stripTerminalControls } from "./provider-setup-CV3S_TAS.js";
|
|
11
11
|
function classify(raw, stream) {
|
|
12
12
|
if (raw.startsWith("\r")) {
|
|
13
13
|
return { type: "progress", text: raw.replace(/\r/g, "").trimEnd() };
|
|
@@ -99,6 +99,15 @@ function TuiInput(props) {
|
|
|
99
99
|
const [history, setHistory] = useState([]);
|
|
100
100
|
const [historyIndex, setHistoryIndex] = useState(null);
|
|
101
101
|
const [pendingDraft, setPendingDraft] = useState("");
|
|
102
|
+
const previousPromptLabel = useRef(promptLabel);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (previousPromptLabel.current === promptLabel) return;
|
|
105
|
+
previousPromptLabel.current = promptLabel;
|
|
106
|
+
setValue("");
|
|
107
|
+
setCursor(0);
|
|
108
|
+
setHistoryIndex(null);
|
|
109
|
+
setPendingDraft("");
|
|
110
|
+
}, [promptLabel]);
|
|
102
111
|
const windowSize = useWindowSize();
|
|
103
112
|
const terminalColumns = props.columns ?? windowSize.columns;
|
|
104
113
|
const wrapWidth = Math.max(1, terminalColumns - BOX_CHROME_WIDTH);
|
|
@@ -212,10 +221,20 @@ function TuiInput(props) {
|
|
|
212
221
|
] });
|
|
213
222
|
}
|
|
214
223
|
function SelectPrompt(props) {
|
|
215
|
-
const { question, options, onSubmit, isActive = true } = props;
|
|
224
|
+
const { question, options, onSubmit, isActive = true, armDelayMs = 0 } = props;
|
|
216
225
|
const [highlighted, setHighlighted] = useState(0);
|
|
226
|
+
const armed = useRef(armDelayMs <= 0);
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (armDelayMs <= 0) return;
|
|
229
|
+
armed.current = false;
|
|
230
|
+
const timer = setTimeout(() => {
|
|
231
|
+
armed.current = true;
|
|
232
|
+
}, armDelayMs);
|
|
233
|
+
return () => clearTimeout(timer);
|
|
234
|
+
}, [armDelayMs, question, options]);
|
|
217
235
|
useInput(
|
|
218
236
|
(input, key) => {
|
|
237
|
+
if (!armed.current) return;
|
|
219
238
|
if (key.upArrow) {
|
|
220
239
|
setHighlighted((h) => (h - 1 + options.length) % options.length);
|
|
221
240
|
return;
|
|
@@ -244,6 +263,195 @@ function SelectPrompt(props) {
|
|
|
244
263
|
] }, option.key)) })
|
|
245
264
|
] });
|
|
246
265
|
}
|
|
266
|
+
function navModelFrom(nodes, boxes) {
|
|
267
|
+
const byId = new Map(boxes.map((b) => [b.id, b]));
|
|
268
|
+
const ids = nodes.map((n) => n.id).filter((id) => byId.has(id));
|
|
269
|
+
const dependents = Object.fromEntries(ids.map((id) => [id, []]));
|
|
270
|
+
for (const n of nodes) if (byId.has(n.id)) {
|
|
271
|
+
for (const d of n.deps) if (dependents[d]) dependents[d].push(n.id);
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
ids,
|
|
275
|
+
taskOrder: ids,
|
|
276
|
+
x: Object.fromEntries(ids.map((id) => [id, byId.get(id).x + byId.get(id).w / 2])),
|
|
277
|
+
y: Object.fromEntries(ids.map((id) => [id, byId.get(id).y])),
|
|
278
|
+
deps: Object.fromEntries(nodes.map((n) => [n.id, n.deps.filter((d) => byId.has(d))])),
|
|
279
|
+
dependents
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
283
|
+
const byX = (m, ids) => [...ids].sort((a, b) => m.x[a] - m.x[b] || cmp(a, b));
|
|
284
|
+
const planNavigator = {
|
|
285
|
+
start: (_m, id) => ({ cur: id, k: 0 }),
|
|
286
|
+
press(m, st, key) {
|
|
287
|
+
if (key === "tab" || key === "shiftTab") {
|
|
288
|
+
const n = m.taskOrder.length;
|
|
289
|
+
if (!n) return st;
|
|
290
|
+
const i2 = m.taskOrder.indexOf(st.cur);
|
|
291
|
+
return { cur: m.taskOrder[(i2 + (key === "tab" ? 1 : -1) + n) % n], k: 0 };
|
|
292
|
+
}
|
|
293
|
+
if (key === "up" || key === "down") {
|
|
294
|
+
let origin = st.lastKey === key && st.lastFrom !== void 0 ? st.lastFrom : st.cur;
|
|
295
|
+
let cands = byX(m, (key === "up" ? m.deps[origin] : m.dependents[origin]) ?? []);
|
|
296
|
+
let repeating = st.lastKey === key;
|
|
297
|
+
if (repeating && cands.length < 2) {
|
|
298
|
+
origin = st.cur;
|
|
299
|
+
cands = byX(m, (key === "up" ? m.deps[origin] : m.dependents[origin]) ?? []);
|
|
300
|
+
repeating = false;
|
|
301
|
+
}
|
|
302
|
+
if (!cands.length) return st;
|
|
303
|
+
const nearest = [...cands].sort((a, b) => Math.abs(m.x[a] - m.x[origin]) - Math.abs(m.x[b] - m.x[origin]) || cmp(a, b))[0];
|
|
304
|
+
const k = repeating ? (st.k + 1) % cands.length : 0;
|
|
305
|
+
return { cur: cands[(cands.indexOf(nearest) + k) % cands.length], lastKey: key, lastFrom: origin, k };
|
|
306
|
+
}
|
|
307
|
+
const rank = byX(m, m.ids.filter((id) => m.y[id] === m.y[st.cur]));
|
|
308
|
+
const i = rank.indexOf(st.cur);
|
|
309
|
+
if (i < 0) return st;
|
|
310
|
+
return { cur: rank[(i + (key === "left" ? -1 : 1) + rank.length) % rank.length], lastKey: key, k: 0 };
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
function followSelection(prev, box, grid, term) {
|
|
314
|
+
const width = Math.min(term.cols, grid.width);
|
|
315
|
+
const height = Math.min(term.rows, grid.height);
|
|
316
|
+
const fit = (start, size, bStart, bSize, total) => {
|
|
317
|
+
let s = start;
|
|
318
|
+
if (bStart < s) s = bStart;
|
|
319
|
+
if (bStart + bSize > s + size) s = bStart + bSize - size;
|
|
320
|
+
return Math.max(0, Math.min(s, total - size));
|
|
321
|
+
};
|
|
322
|
+
return { width, height, left: fit(prev.left, width, box.x, box.w, grid.width), top: fit(prev.top, height, box.y, box.h, grid.height) };
|
|
323
|
+
}
|
|
324
|
+
function scrollIndicators(v, grid) {
|
|
325
|
+
return { up: v.top > 0, down: v.top + v.height < grid.height, left: v.left > 0, right: v.left + v.width < grid.width };
|
|
326
|
+
}
|
|
327
|
+
const STATUS_WORD = {
|
|
328
|
+
pending: "pending",
|
|
329
|
+
ready: "ready to run",
|
|
330
|
+
running: "running",
|
|
331
|
+
done: "done",
|
|
332
|
+
failed: "failed",
|
|
333
|
+
awaiting_user: "waiting for you",
|
|
334
|
+
awaiting_input: "blocked, waiting for input",
|
|
335
|
+
cancelled: "cancelled"
|
|
336
|
+
};
|
|
337
|
+
function wrap(text, width) {
|
|
338
|
+
const out = [];
|
|
339
|
+
let line = "";
|
|
340
|
+
for (const word of text.split(/\s+/).filter(Boolean)) {
|
|
341
|
+
let w = word;
|
|
342
|
+
while (w.length > width) {
|
|
343
|
+
if (line) {
|
|
344
|
+
out.push(line);
|
|
345
|
+
line = "";
|
|
346
|
+
}
|
|
347
|
+
out.push(w.slice(0, width));
|
|
348
|
+
w = w.slice(width);
|
|
349
|
+
}
|
|
350
|
+
if (!line) line = w;
|
|
351
|
+
else if (line.length + 1 + w.length <= width) line += ` ${w}`;
|
|
352
|
+
else {
|
|
353
|
+
out.push(line);
|
|
354
|
+
line = w;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (line) out.push(line);
|
|
358
|
+
return out;
|
|
359
|
+
}
|
|
360
|
+
function planDetailLines(nodes, id, width) {
|
|
361
|
+
const node = nodes.find((n) => n.id === id);
|
|
362
|
+
if (!node) return ["No task selected."];
|
|
363
|
+
const w = Math.max(10, width);
|
|
364
|
+
const name = (i) => {
|
|
365
|
+
var _a;
|
|
366
|
+
return sanitizeLabel(((_a = nodes.find((n) => n.id === i)) == null ? void 0 : _a.id) ?? i);
|
|
367
|
+
};
|
|
368
|
+
const dependents = nodes.filter((n) => n.deps.includes(node.id)).map((n) => n.id);
|
|
369
|
+
return [
|
|
370
|
+
...wrap(sanitizeLabel(node.id), w),
|
|
371
|
+
"",
|
|
372
|
+
...wrap(sanitizeLabel(node.label), w),
|
|
373
|
+
"",
|
|
374
|
+
`Status: ${STATUS_WORD[node.status] ?? node.status}`,
|
|
375
|
+
...wrap(`Depends on: ${node.deps.length ? node.deps.map(name).join(", ") : "nothing"}`, w),
|
|
376
|
+
...wrap(`Needed by: ${dependents.length ? dependents.map(sanitizeLabel).join(", ") : "nothing"}`, w)
|
|
377
|
+
];
|
|
378
|
+
}
|
|
379
|
+
const DRAWER_DOCK_COLUMNS = 120;
|
|
380
|
+
const DRAWER_WIDTH = 36;
|
|
381
|
+
function PlanGraphPane({ nodes, columns, rows, active = true, color = true, ascii = false, onClose }) {
|
|
382
|
+
const docked = columns >= DRAWER_DOCK_COLUMNS;
|
|
383
|
+
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
384
|
+
const showDrawer = docked || drawerOpen;
|
|
385
|
+
const graphCols = showDrawer ? Math.max(20, columns - DRAWER_WIDTH - 1) : columns;
|
|
386
|
+
const graphRows = Math.max(3, rows - 2);
|
|
387
|
+
const [nav, setNav] = useState(void 0);
|
|
388
|
+
const lastIndex = useRef(0);
|
|
389
|
+
const viewport = useRef({ left: 0, top: 0, width: 0, height: 0 });
|
|
390
|
+
const base = useMemo(() => renderPlan(nodes, { maxCols: graphCols, ascii, color: false }), [nodes, graphCols, ascii]);
|
|
391
|
+
const model = useMemo(() => base.ok ? navModelFrom(nodes, base.boxes) : void 0, [nodes, base]);
|
|
392
|
+
let selectedId;
|
|
393
|
+
if (model && model.ids.length) {
|
|
394
|
+
if (nav && model.ids.includes(nav.cur)) selectedId = nav.cur;
|
|
395
|
+
else selectedId = model.taskOrder[Math.min(lastIndex.current, model.taskOrder.length - 1)];
|
|
396
|
+
}
|
|
397
|
+
if (model && selectedId) lastIndex.current = model.taskOrder.indexOf(selectedId);
|
|
398
|
+
const detail = useMemo(() => planDetailLines(nodes, selectedId, DRAWER_WIDTH - 2), [nodes, selectedId]);
|
|
399
|
+
const [scroll, setScroll] = useState({ id: void 0, offset: 0 });
|
|
400
|
+
const drawerRows = graphRows;
|
|
401
|
+
const maxScroll = Math.max(0, detail.length - drawerRows);
|
|
402
|
+
const drawerOffset = scroll.id === selectedId ? Math.min(scroll.offset, maxScroll) : 0;
|
|
403
|
+
const scrollDrawer = (delta) => setScroll({ id: selectedId, offset: Math.max(0, Math.min(maxScroll, drawerOffset + delta)) });
|
|
404
|
+
useInput(
|
|
405
|
+
(input, key) => {
|
|
406
|
+
if (key.escape || input === "q") return onClose();
|
|
407
|
+
if (key.return || input === "d") return setDrawerOpen((open) => !open);
|
|
408
|
+
if (showDrawer) {
|
|
409
|
+
if (input === "j") return scrollDrawer(1);
|
|
410
|
+
if (input === "k") return scrollDrawer(-1);
|
|
411
|
+
if (key.pageDown) return scrollDrawer(drawerRows);
|
|
412
|
+
if (key.pageUp) return scrollDrawer(-drawerRows);
|
|
413
|
+
}
|
|
414
|
+
if (!model || !selectedId) return;
|
|
415
|
+
const k = key.upArrow || input === "[" ? "up" : key.downArrow || input === "]" ? "down" : key.leftArrow ? "left" : key.rightArrow ? "right" : key.tab ? key.shift ? "shiftTab" : "tab" : void 0;
|
|
416
|
+
if (!k) return;
|
|
417
|
+
const from = nav && nav.cur === selectedId ? nav : planNavigator.start(model, selectedId);
|
|
418
|
+
setNav(planNavigator.press(model, from, k));
|
|
419
|
+
},
|
|
420
|
+
{ isActive: active }
|
|
421
|
+
);
|
|
422
|
+
if (!base.ok || !model) {
|
|
423
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", height: rows, children: [
|
|
424
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
425
|
+
"Plan graph unavailable: ",
|
|
426
|
+
base.ok ? "nothing to draw" : base.message
|
|
427
|
+
] }),
|
|
428
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "q / Esc closes" })
|
|
429
|
+
] });
|
|
430
|
+
}
|
|
431
|
+
const r = renderPlan(nodes, { maxCols: graphCols, ascii, color, selectedId });
|
|
432
|
+
if (!r.ok) return /* @__PURE__ */ jsxs(Text, { children: [
|
|
433
|
+
"Plan graph unavailable: ",
|
|
434
|
+
r.message
|
|
435
|
+
] });
|
|
436
|
+
const box = r.boxes.find((b) => b.id === selectedId);
|
|
437
|
+
const vp = box ? followSelection(viewport.current, box, r, { cols: graphCols, rows: graphRows }) : { left: 0, top: 0, width: Math.min(graphCols, r.width), height: Math.min(graphRows, r.height) };
|
|
438
|
+
viewport.current = vp;
|
|
439
|
+
const lines = toLines(r.cells, r.styles, [vp.top, vp.top + vp.height], [vp.left, vp.left + vp.width]);
|
|
440
|
+
const more = scrollIndicators(vp, r);
|
|
441
|
+
const arrows = `${more.up ? "↑" : " "}${more.down ? "↓" : " "}${more.left ? "←" : " "}${more.right ? "→" : " "}`;
|
|
442
|
+
const done = nodes.filter((n) => n.status === "done").length;
|
|
443
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", height: rows, children: [
|
|
444
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
445
|
+
`Plan graph — ${done}/${nodes.length} done `,
|
|
446
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: arrows })
|
|
447
|
+
] }),
|
|
448
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexGrow: 1, children: [
|
|
449
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", width: graphCols, children: lines.map((line, i) => /* @__PURE__ */ jsx(Text, { wrap: "truncate", children: line.length ? line : " " }, i)) }),
|
|
450
|
+
showDrawer && /* @__PURE__ */ jsx(Box, { flexDirection: "column", width: DRAWER_WIDTH + 1, paddingLeft: 1, borderStyle: "single", borderTop: false, borderBottom: false, borderRight: false, children: detail.slice(drawerOffset, drawerOffset + drawerRows).map((line, i) => /* @__PURE__ */ jsx(Text, { wrap: "truncate", children: line.length ? line : " " }, i)) })
|
|
451
|
+
] }),
|
|
452
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: docked ? "↑↓←→ move · Tab next · j/k PgUp/PgDn scroll details · q close" : "↑↓←→ move · Tab next · Enter details · q close" })
|
|
453
|
+
] });
|
|
454
|
+
}
|
|
247
455
|
const HEADER_RE = /^(#{1,6})\s+(.*)$/;
|
|
248
456
|
const CHECKBOX_RE = /^(\s*[-*]\s)\[([ xX])\]\s+(.*)$/;
|
|
249
457
|
const DIFF_LINE_RE = /^(\s*\d+) ([+\- ])(.*)$/;
|
|
@@ -323,7 +531,7 @@ const ASSISTANT_INDENT_WIDTH = 2;
|
|
|
323
531
|
function useStore(store) {
|
|
324
532
|
return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
325
533
|
}
|
|
326
|
-
const EMPTY_LOG = { lines: [], progressText: "", transientText: "", waitingForOutput: false };
|
|
534
|
+
const EMPTY_LOG = { lines: [], progressText: "", transientText: "", waitingForOutput: false, turnInFlight: false };
|
|
327
535
|
const TOOL_STEP_PREFIXES = [ICONS.toolStep, ICONS.proposalStep, ICONS.deniedStep];
|
|
328
536
|
const ASSISTANT_REPLY_PREFIX = "Aielia>";
|
|
329
537
|
function classifyLineKind(mergedText, streamedReplyWasOpen, stream) {
|
|
@@ -345,6 +553,8 @@ class EventLogBridge {
|
|
|
345
553
|
__publicField(this, "progressText", "");
|
|
346
554
|
__publicField(this, "transientText", "");
|
|
347
555
|
__publicField(this, "waitingForOutput", false);
|
|
556
|
+
__publicField(this, "turnInFlight", false);
|
|
557
|
+
__publicField(this, "lastActivityAt");
|
|
348
558
|
__publicField(this, "snapshot", EMPTY_LOG);
|
|
349
559
|
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
350
560
|
__publicField(this, "subscribe", (listener) => {
|
|
@@ -356,12 +566,41 @@ class EventLogBridge {
|
|
|
356
566
|
__publicField(this, "getSnapshot", () => this.snapshot);
|
|
357
567
|
}
|
|
358
568
|
commit() {
|
|
359
|
-
this.snapshot = {
|
|
569
|
+
this.snapshot = {
|
|
570
|
+
lines: this.lines,
|
|
571
|
+
progressText: this.progressText,
|
|
572
|
+
transientText: this.transientText,
|
|
573
|
+
waitingForOutput: this.waitingForOutput,
|
|
574
|
+
turnInFlight: this.turnInFlight,
|
|
575
|
+
lastActivityAt: this.lastActivityAt
|
|
576
|
+
};
|
|
360
577
|
for (const listener of this.listeners) listener();
|
|
361
578
|
}
|
|
362
579
|
/** Marks the start of a turn's wait for its first output (see `TuiLogState.waitingForOutput`'s doc comment) — called by `TuiApp` right after a chat line or resolved prompt answer is submitted. */
|
|
363
580
|
beginTurn() {
|
|
364
581
|
this.waitingForOutput = true;
|
|
582
|
+
this.turnInFlight = true;
|
|
583
|
+
this.lastActivityAt = Date.now();
|
|
584
|
+
this.commit();
|
|
585
|
+
}
|
|
586
|
+
/** A resolved approval/clarification answer: output is expected again, but it says nothing about whether a turn is in flight — `TurnActivityTracker` owns that, so a prompt answer can never leave the indicator stuck on. */
|
|
587
|
+
expectOutput() {
|
|
588
|
+
this.waitingForOutput = true;
|
|
589
|
+
this.commit();
|
|
590
|
+
}
|
|
591
|
+
/** Marks a turn in flight (idempotent); the elapsed counter counts from the first call. */
|
|
592
|
+
markBusy() {
|
|
593
|
+
if (this.turnInFlight) return;
|
|
594
|
+
this.turnInFlight = true;
|
|
595
|
+
this.lastActivityAt = Date.now();
|
|
596
|
+
this.commit();
|
|
597
|
+
}
|
|
598
|
+
/** Marks the turn finished (its `dispatchLine()` settled) — the liveness line stops. Safe to call when no turn is in flight. */
|
|
599
|
+
endTurn() {
|
|
600
|
+
if (!this.turnInFlight && !this.waitingForOutput) return;
|
|
601
|
+
this.turnInFlight = false;
|
|
602
|
+
this.waitingForOutput = false;
|
|
603
|
+
this.lastActivityAt = void 0;
|
|
365
604
|
this.commit();
|
|
366
605
|
}
|
|
367
606
|
/**
|
|
@@ -387,18 +626,19 @@ class EventLogBridge {
|
|
|
387
626
|
}
|
|
388
627
|
handleEvent(event) {
|
|
389
628
|
this.waitingForOutput = false;
|
|
629
|
+
if (this.turnInFlight) this.lastActivityAt = Date.now();
|
|
390
630
|
if (event.type === "progress") {
|
|
391
|
-
this.progressText = event.text;
|
|
631
|
+
this.progressText = stripTerminalControls(event.text);
|
|
392
632
|
this.commit();
|
|
393
633
|
return;
|
|
394
634
|
}
|
|
395
635
|
if (event.type === "token") {
|
|
396
|
-
this.transientText += event.text;
|
|
636
|
+
this.transientText += stripTerminalControls(event.text);
|
|
397
637
|
this.commit();
|
|
398
638
|
return;
|
|
399
639
|
}
|
|
400
640
|
const streamedReplyWasOpen = this.transientText.length > 0;
|
|
401
|
-
const merged = this.transientText + event.lines.join("\n");
|
|
641
|
+
const merged = this.transientText + stripTerminalControls(event.lines.join("\n"));
|
|
402
642
|
const kind = classifyLineKind(merged, streamedReplyWasOpen, event.stream);
|
|
403
643
|
const displayText = kind === "assistant" ? stripAssistantLabel(merged) : kind === "plan" ? stripPlanLabel(merged) : merged;
|
|
404
644
|
this.lines = kind === "plan" ? [...this.lines, { text: displayText, kind }] : (
|
|
@@ -413,6 +653,31 @@ class EventLogBridge {
|
|
|
413
653
|
if (kind === "assistant") this.pushTurnMargin();
|
|
414
654
|
}
|
|
415
655
|
}
|
|
656
|
+
class TurnActivityTracker {
|
|
657
|
+
constructor(eventLog) {
|
|
658
|
+
__publicField(this, "dispatches", 0);
|
|
659
|
+
__publicField(this, "cliBusy", false);
|
|
660
|
+
this.eventLog = eventLog;
|
|
661
|
+
}
|
|
662
|
+
/** Wraps one `dispatchLine()` call. Always settles, whether it resolves or throws. */
|
|
663
|
+
async track(run) {
|
|
664
|
+
this.dispatches++;
|
|
665
|
+
try {
|
|
666
|
+
return await run();
|
|
667
|
+
} finally {
|
|
668
|
+
this.dispatches--;
|
|
669
|
+
this.settle();
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
setCliBusy(busy) {
|
|
673
|
+
this.cliBusy = busy;
|
|
674
|
+
if (busy) this.eventLog.markBusy();
|
|
675
|
+
else this.settle();
|
|
676
|
+
}
|
|
677
|
+
settle() {
|
|
678
|
+
if (this.dispatches === 0 && !this.cliBusy) this.eventLog.endTurn();
|
|
679
|
+
}
|
|
680
|
+
}
|
|
416
681
|
class PromptBridge {
|
|
417
682
|
constructor() {
|
|
418
683
|
__publicField(this, "pending");
|
|
@@ -433,7 +698,10 @@ class PromptBridge {
|
|
|
433
698
|
}
|
|
434
699
|
ask(question, options) {
|
|
435
700
|
return new Promise((resolve) => {
|
|
436
|
-
this.pending = {
|
|
701
|
+
this.pending = {
|
|
702
|
+
question: stripTerminalControls(question),
|
|
703
|
+
options: options == null ? void 0 : options.map((o) => ({ ...o, label: stripTerminalControls(o.label) }))
|
|
704
|
+
};
|
|
437
705
|
this.resolve = resolve;
|
|
438
706
|
for (const listener of this.listeners) listener();
|
|
439
707
|
});
|
|
@@ -463,6 +731,108 @@ class StatusBridge {
|
|
|
463
731
|
for (const listener of this.listeners) listener();
|
|
464
732
|
}
|
|
465
733
|
}
|
|
734
|
+
const ALT_SCREEN_ON = "\x1B[?1049h";
|
|
735
|
+
const ALT_SCREEN_OFF = "\x1B[?1049l";
|
|
736
|
+
const ALT_SCREEN_SETTLE_MS = 80;
|
|
737
|
+
const SELECT_ARM_DELAY_MS = 400;
|
|
738
|
+
const PLAN_GRAPH_MIN_RENDER_MS = 100;
|
|
739
|
+
class PlanGraphBridge {
|
|
740
|
+
constructor(writeRaw, settleMs = ALT_SCREEN_SETTLE_MS, minRenderMs = PLAN_GRAPH_MIN_RENDER_MS) {
|
|
741
|
+
__publicField(this, "view", { mode: "chat", nodes: [] });
|
|
742
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
743
|
+
__publicField(this, "timer");
|
|
744
|
+
__publicField(this, "pendingNodes");
|
|
745
|
+
__publicField(this, "transition", Promise.resolve());
|
|
746
|
+
__publicField(this, "subscribe", (listener) => {
|
|
747
|
+
this.listeners.add(listener);
|
|
748
|
+
return () => {
|
|
749
|
+
this.listeners.delete(listener);
|
|
750
|
+
};
|
|
751
|
+
});
|
|
752
|
+
__publicField(this, "getSnapshot", () => this.view);
|
|
753
|
+
this.writeRaw = writeRaw;
|
|
754
|
+
this.settleMs = settleMs;
|
|
755
|
+
this.minRenderMs = minRenderMs;
|
|
756
|
+
}
|
|
757
|
+
isOpen() {
|
|
758
|
+
return this.view.mode !== "chat";
|
|
759
|
+
}
|
|
760
|
+
set(view) {
|
|
761
|
+
this.view = view;
|
|
762
|
+
for (const listener of this.listeners) listener();
|
|
763
|
+
}
|
|
764
|
+
sleep() {
|
|
765
|
+
return new Promise((resolve) => setTimeout(resolve, this.settleMs));
|
|
766
|
+
}
|
|
767
|
+
open(nodes) {
|
|
768
|
+
this.transition = this.transition.then(async () => {
|
|
769
|
+
if (this.view.mode !== "chat") {
|
|
770
|
+
this.update(nodes);
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
this.set({ mode: "blank", nodes });
|
|
774
|
+
await this.sleep();
|
|
775
|
+
this.writeRaw(ALT_SCREEN_ON);
|
|
776
|
+
this.set({ mode: "pane", nodes: this.pendingNodes ?? nodes });
|
|
777
|
+
this.pendingNodes = void 0;
|
|
778
|
+
});
|
|
779
|
+
return this.transition;
|
|
780
|
+
}
|
|
781
|
+
close() {
|
|
782
|
+
this.transition = this.transition.then(async () => {
|
|
783
|
+
if (this.view.mode === "chat") return;
|
|
784
|
+
this.clearTimer();
|
|
785
|
+
this.set({ mode: "blank", nodes: this.view.nodes });
|
|
786
|
+
await this.sleep();
|
|
787
|
+
this.writeRaw(ALT_SCREEN_OFF);
|
|
788
|
+
this.set({ mode: "chat", nodes: [] });
|
|
789
|
+
});
|
|
790
|
+
return this.transition;
|
|
791
|
+
}
|
|
792
|
+
/** Synchronous leave for process exit: restores the main screen without waiting. */
|
|
793
|
+
restore() {
|
|
794
|
+
this.clearTimer();
|
|
795
|
+
if (this.view.mode === "pane") this.writeRaw(ALT_SCREEN_OFF);
|
|
796
|
+
this.view = { mode: "chat", nodes: [] };
|
|
797
|
+
}
|
|
798
|
+
/** Throttled node update: the first goes through at once, later ones coalesce to the newest within `minRenderMs`. Identical content is ignored. */
|
|
799
|
+
update(nodes) {
|
|
800
|
+
if (this.view.mode === "chat") return;
|
|
801
|
+
if (this.view.mode === "blank") {
|
|
802
|
+
this.pendingNodes = nodes;
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
if (this.timer) {
|
|
806
|
+
this.pendingNodes = nodes;
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
this.apply(nodes);
|
|
810
|
+
this.timer = setTimeout(() => this.flush(), this.minRenderMs);
|
|
811
|
+
}
|
|
812
|
+
apply(nodes) {
|
|
813
|
+
if (this.view.mode !== "pane" || JSON.stringify(nodes) === JSON.stringify(this.view.nodes)) return;
|
|
814
|
+
this.set({ mode: "pane", nodes });
|
|
815
|
+
}
|
|
816
|
+
flush() {
|
|
817
|
+
this.timer = void 0;
|
|
818
|
+
const next = this.pendingNodes;
|
|
819
|
+
this.pendingNodes = void 0;
|
|
820
|
+
if (next) {
|
|
821
|
+
this.apply(next);
|
|
822
|
+
this.timer = setTimeout(() => this.flush(), this.minRenderMs);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
clearTimer() {
|
|
826
|
+
if (this.timer) clearTimeout(this.timer);
|
|
827
|
+
this.timer = void 0;
|
|
828
|
+
this.pendingNodes = void 0;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
const NO_PLAN_GRAPH = { subscribe: () => () => {
|
|
832
|
+
}, getSnapshot: /* @__PURE__ */ (() => {
|
|
833
|
+
const v = { mode: "chat", nodes: [] };
|
|
834
|
+
return () => v;
|
|
835
|
+
})() };
|
|
466
836
|
function UserMessageBox({ text, width, borderColor = "gray" }) {
|
|
467
837
|
return /* @__PURE__ */ jsx(Box, { borderStyle: "round", borderColor, flexDirection: "column", paddingX: 1, width, children: text.split("\n").map((line, i) => /* @__PURE__ */ jsx(Text, { children: line.length > 0 ? line : " " }, i)) });
|
|
468
838
|
}
|
|
@@ -491,15 +861,23 @@ function LogLineText({ line, width }) {
|
|
|
491
861
|
}
|
|
492
862
|
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
493
863
|
const SPINNER_INTERVAL_MS = 80;
|
|
494
|
-
|
|
864
|
+
const LIVENESS_COUNTER_AFTER_S = 3;
|
|
865
|
+
function formatLivenessLabel(elapsedMs, hasProgress) {
|
|
866
|
+
const seconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
867
|
+
if (seconds < LIVENESS_COUNTER_AFTER_S) return hasProgress ? "Working…" : "Thinking…";
|
|
868
|
+
return `Working… ${seconds}s`;
|
|
869
|
+
}
|
|
870
|
+
function Spinner({ since, hasProgress, quietOnly = false }) {
|
|
495
871
|
const [frame, setFrame] = useState(0);
|
|
496
872
|
useEffect(() => {
|
|
497
873
|
const id = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), SPINNER_INTERVAL_MS);
|
|
498
874
|
return () => clearInterval(id);
|
|
499
875
|
}, []);
|
|
876
|
+
if (quietOnly && since !== void 0 && Date.now() - since < LIVENESS_COUNTER_AFTER_S * 1e3) return null;
|
|
500
877
|
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
501
878
|
SPINNER_FRAMES[frame],
|
|
502
|
-
"
|
|
879
|
+
" ",
|
|
880
|
+
formatLivenessLabel(since === void 0 ? 0 : Date.now() - since, hasProgress)
|
|
503
881
|
] });
|
|
504
882
|
}
|
|
505
883
|
function StatusLine({ indicators }) {
|
|
@@ -509,12 +887,15 @@ function StatusLine({ indicators }) {
|
|
|
509
887
|
] }, indicator)) });
|
|
510
888
|
}
|
|
511
889
|
function TuiApp(props) {
|
|
512
|
-
const { eventLog, prompt, status, onSubmitChat, onExit, columns } = props;
|
|
890
|
+
const { eventLog, prompt, status, planGraph, onSubmitChat, onExit, columns } = props;
|
|
513
891
|
const log = useStore(eventLog);
|
|
514
892
|
const pending = useStore(prompt);
|
|
515
893
|
const statusIndicators = useStore(status);
|
|
516
894
|
const windowSize = useWindowSize();
|
|
517
895
|
const width = columns ?? windowSize.columns;
|
|
896
|
+
const graphView = useStore(planGraph ?? NO_PLAN_GRAPH);
|
|
897
|
+
const frozenLines = useRef(0);
|
|
898
|
+
if (graphView.mode === "chat") frozenLines.current = log.lines.length;
|
|
518
899
|
useInput((input, key) => {
|
|
519
900
|
if (key.ctrl && input === "c") onExit();
|
|
520
901
|
});
|
|
@@ -533,22 +914,36 @@ function TuiApp(props) {
|
|
|
533
914
|
var _a, _b;
|
|
534
915
|
const displayAnswer = ((_b = (_a = pending == null ? void 0 : pending.options) == null ? void 0 : _a.find((option) => option.key === line)) == null ? void 0 : _b.label) ?? line;
|
|
535
916
|
eventLog.pushEchoLine("> ", (pending == null ? void 0 : pending.question) !== void 0 ? `${pending.question.trimEnd()} → ${displayAnswer}` : line);
|
|
536
|
-
eventLog.
|
|
917
|
+
eventLog.expectOutput();
|
|
537
918
|
prompt.submit(line);
|
|
538
919
|
},
|
|
539
920
|
[eventLog, prompt, pending]
|
|
540
921
|
);
|
|
922
|
+
const closePane = useCallback(() => {
|
|
923
|
+
void (planGraph == null ? void 0 : planGraph.close());
|
|
924
|
+
}, [planGraph]);
|
|
541
925
|
const hasTransient = log.progressText.length > 0 || log.transientText.length > 0;
|
|
542
|
-
const showSpinner = log.waitingForOutput && !
|
|
926
|
+
const showSpinner = (log.turnInFlight || log.waitingForOutput) && !pending;
|
|
927
|
+
const staticItems = graphView.mode === "chat" ? log.lines : log.lines.slice(0, frozenLines.current);
|
|
928
|
+
const paneRows = Math.max(3, (windowSize.rows ?? 24) - 1);
|
|
929
|
+
if (graphView.mode !== "chat") {
|
|
930
|
+
const promptRows = pending ? Math.min(10, Math.floor(paneRows / 2)) : 0;
|
|
931
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
932
|
+
/* @__PURE__ */ jsx(Static, { items: staticItems, children: (line, index) => /* @__PURE__ */ jsx(LogLineText, { line, width }, index) }),
|
|
933
|
+
graphView.mode === "pane" && /* @__PURE__ */ jsx(PlanGraphPane, { nodes: graphView.nodes, columns: width, rows: paneRows - promptRows, active: !pending, color: !process.env.NO_COLOR, onClose: closePane }),
|
|
934
|
+
graphView.mode === "pane" && (pending == null ? void 0 : pending.options) && /* @__PURE__ */ jsx(SelectPrompt, { question: pending.question, options: pending.options, onSubmit: handleSubmitPrompt, armDelayMs: SELECT_ARM_DELAY_MS }),
|
|
935
|
+
graphView.mode === "pane" && pending && !pending.options && /* @__PURE__ */ jsx(TuiInput, { promptLabel: pending.question, onSubmitChat: handleSubmitChat, onSubmitPrompt: handleSubmitPrompt, columns })
|
|
936
|
+
] });
|
|
937
|
+
}
|
|
543
938
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
544
|
-
/* @__PURE__ */ jsx(Static, { items:
|
|
545
|
-
showSpinner && /* @__PURE__ */ jsx(Spinner, {}),
|
|
939
|
+
/* @__PURE__ */ jsx(Static, { items: staticItems, children: (line, index) => /* @__PURE__ */ jsx(LogLineText, { line, width }, index) }),
|
|
546
940
|
hasTransient && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
547
941
|
log.progressText.length > 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: log.progressText }),
|
|
548
942
|
log.transientText.length > 0 && /* @__PURE__ */ jsx(Text, { children: stripAssistantLabel(log.transientText) })
|
|
549
943
|
] }),
|
|
944
|
+
showSpinner && /* @__PURE__ */ jsx(Spinner, { since: log.lastActivityAt, hasProgress: log.progressText.length > 0, quietOnly: log.transientText.length > 0 }),
|
|
550
945
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "─".repeat(Math.max(1, width)) }),
|
|
551
|
-
(pending == null ? void 0 : pending.options) ? /* @__PURE__ */ jsx(SelectPrompt, { question: pending.question, options: pending.options, onSubmit: handleSubmitPrompt }) : /* @__PURE__ */ jsx(
|
|
946
|
+
(pending == null ? void 0 : pending.options) ? /* @__PURE__ */ jsx(SelectPrompt, { question: pending.question, options: pending.options, onSubmit: handleSubmitPrompt, armDelayMs: SELECT_ARM_DELAY_MS }) : /* @__PURE__ */ jsx(
|
|
552
947
|
TuiInput,
|
|
553
948
|
{
|
|
554
949
|
promptLabel: pending == null ? void 0 : pending.question,
|
|
@@ -582,12 +977,20 @@ async function runTuiApp(options = {}) {
|
|
|
582
977
|
const prompt = new PromptBridge();
|
|
583
978
|
const status = new StatusBridge();
|
|
584
979
|
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
980
|
+
const activity = new TurnActivityTracker(eventLog);
|
|
585
981
|
const restoreCapture = startCapture((event) => eventLog.handleEvent(event));
|
|
982
|
+
const planGraph = new PlanGraphBridge((chunk) => void originalWrite(chunk));
|
|
983
|
+
let instanceRef;
|
|
586
984
|
let instance;
|
|
587
985
|
try {
|
|
588
986
|
const inert = createInertStreams();
|
|
589
987
|
instance = await runCli({
|
|
590
988
|
...options,
|
|
989
|
+
onTurnBusyChange: (busy) => activity.setCliBusy(busy),
|
|
990
|
+
openPlanGraph: (nodes) => void planGraph.open(nodes),
|
|
991
|
+
onPlanProgress: (tasks) => {
|
|
992
|
+
if (planGraph.isOpen()) void (instanceRef == null ? void 0 : instanceRef.getPlanGraphNodes(tasks).then((nodes) => nodes && planGraph.update(nodes)));
|
|
993
|
+
},
|
|
591
994
|
input: options.input ?? inert.input,
|
|
592
995
|
output: options.output ?? inert.output,
|
|
593
996
|
askYesNo: prompt.askYesNo,
|
|
@@ -598,23 +1001,32 @@ async function runTuiApp(options = {}) {
|
|
|
598
1001
|
restoreCapture();
|
|
599
1002
|
throw err;
|
|
600
1003
|
}
|
|
1004
|
+
instanceRef = instance;
|
|
601
1005
|
const refreshStatus = async () => {
|
|
602
1006
|
status.set(await instance.getStatusIndicators());
|
|
1007
|
+
if (planGraph.isOpen()) {
|
|
1008
|
+
const nodes = await instance.getPlanGraphNodes();
|
|
1009
|
+
if (nodes) planGraph.update(nodes);
|
|
1010
|
+
}
|
|
603
1011
|
};
|
|
604
1012
|
await refreshStatus();
|
|
605
1013
|
const handleSubmitChat = (line) => {
|
|
606
|
-
void
|
|
1014
|
+
void activity.track(async () => {
|
|
1015
|
+
await instance.dispatchLine(line);
|
|
1016
|
+
await refreshStatus();
|
|
1017
|
+
});
|
|
607
1018
|
};
|
|
608
1019
|
let exiting = false;
|
|
609
1020
|
const exit = () => {
|
|
610
1021
|
if (exiting) return;
|
|
611
1022
|
exiting = true;
|
|
1023
|
+
planGraph.restore();
|
|
612
1024
|
restoreCapture();
|
|
613
1025
|
instance.close();
|
|
614
1026
|
app.unmount();
|
|
615
1027
|
process.exit(0);
|
|
616
1028
|
};
|
|
617
|
-
const app = render(/* @__PURE__ */ jsx(TuiApp, { eventLog, prompt, status, onSubmitChat: handleSubmitChat, onExit: exit }), {
|
|
1029
|
+
const app = render(/* @__PURE__ */ jsx(TuiApp, { eventLog, prompt, status, planGraph, onSubmitChat: handleSubmitChat, onExit: exit }), {
|
|
618
1030
|
// Phase 1's startCapture already routes every console.log/process.stdout.write call into
|
|
619
1031
|
// eventLog — ink's own patchConsole would double-intercept the same calls with a competing
|
|
620
1032
|
// mechanism (writing them above its own Static area independently), not compose with it.
|
|
@@ -629,9 +1041,12 @@ async function runTuiApp(options = {}) {
|
|
|
629
1041
|
}
|
|
630
1042
|
export {
|
|
631
1043
|
EventLogBridge,
|
|
1044
|
+
PlanGraphBridge,
|
|
632
1045
|
PromptBridge,
|
|
633
1046
|
StatusBridge,
|
|
634
1047
|
TuiApp,
|
|
1048
|
+
TurnActivityTracker,
|
|
1049
|
+
formatLivenessLabel,
|
|
635
1050
|
runTuiApp
|
|
636
1051
|
};
|
|
637
|
-
//# sourceMappingURL=tui-app-
|
|
1052
|
+
//# sourceMappingURL=tui-app-CJq6YaiP.js.map
|