reasonix 0.30.1 → 0.30.2
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/dashboard/dist/app.js +18 -6
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/index.js +126 -29
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -20890,7 +20890,8 @@ var PAGE_MARGIN = 6;
|
|
|
20890
20890
|
function SessionPicker({
|
|
20891
20891
|
sessions: sessions2,
|
|
20892
20892
|
workspace: workspace2,
|
|
20893
|
-
onChoose
|
|
20893
|
+
onChoose,
|
|
20894
|
+
walletCurrency
|
|
20894
20895
|
}) {
|
|
20895
20896
|
const [focus, setFocus] = useState11(0);
|
|
20896
20897
|
const [renaming, setRenaming] = useState11(null);
|
|
@@ -20947,18 +20948,28 @@ function SessionPicker({
|
|
|
20947
20948
|
const end = Math.min(sessions2.length, start + visibleCount);
|
|
20948
20949
|
const shown = sessions2.slice(start, end);
|
|
20949
20950
|
const hiddenBelow = sessions2.length - end;
|
|
20950
|
-
return /* @__PURE__ */ React28.createElement(Box21, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React28.createElement(Box21, null, /* @__PURE__ */ React28.createElement(Text20, { bold: true, color: TONE.brand }, " \u25C8 REASONIX \xB7 pick a session "), /* @__PURE__ */ React28.createElement(Text20, { color: FG.meta }, ` \xB7 ${workspace2}`)), /* @__PURE__ */ React28.createElement(Box21, { height: 1 }), sessions2.length === 0 ? /* @__PURE__ */ React28.createElement(Box21, null, /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, " no saved sessions in this workspace yet \u2014 press "), /* @__PURE__ */ React28.createElement(Text20, { bold: true, color: TONE.brand }, "\u23CE"), /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, " to start a new one")) : shown.map((s, i) => /* @__PURE__ */ React28.createElement(
|
|
20951
|
+
return /* @__PURE__ */ React28.createElement(Box21, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React28.createElement(Box21, null, /* @__PURE__ */ React28.createElement(Text20, { bold: true, color: TONE.brand }, " \u25C8 REASONIX \xB7 pick a session "), /* @__PURE__ */ React28.createElement(Text20, { color: FG.meta }, ` \xB7 ${workspace2}`)), /* @__PURE__ */ React28.createElement(Box21, { height: 1 }), sessions2.length === 0 ? /* @__PURE__ */ React28.createElement(Box21, null, /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, " no saved sessions in this workspace yet \u2014 press "), /* @__PURE__ */ React28.createElement(Text20, { bold: true, color: TONE.brand }, "\u23CE"), /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, " to start a new one")) : shown.map((s, i) => /* @__PURE__ */ React28.createElement(
|
|
20952
|
+
SessionRow,
|
|
20953
|
+
{
|
|
20954
|
+
key: s.name,
|
|
20955
|
+
info: s,
|
|
20956
|
+
focused: start + i === focus,
|
|
20957
|
+
walletCurrency
|
|
20958
|
+
}
|
|
20959
|
+
)), hiddenBelow > 0 ? /* @__PURE__ */ React28.createElement(Box21, null, /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, ` \u2026 ${hiddenBelow} more`)) : null, renaming ? /* @__PURE__ */ React28.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, ` rename "${renaming.from}" \u2192 `), /* @__PURE__ */ React28.createElement(Text20, { bold: true, color: TONE.brand }, renaming.buf), /* @__PURE__ */ React28.createElement(Text20, { backgroundColor: TONE.brand, color: "black" }, " ")) : null, /* @__PURE__ */ React28.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, renaming ? " \u23CE confirm rename \xB7 esc cancel" : sessions2.length === 0 ? " \u23CE new session \xB7 esc quit" : " \u2191\u2193 pick \xB7 \u23CE open \xB7 [n] new \xB7 [d] delete \xB7 [r] rename \xB7 esc quit")));
|
|
20951
20960
|
}
|
|
20952
20961
|
function SessionRow({
|
|
20953
20962
|
info,
|
|
20954
|
-
focused
|
|
20963
|
+
focused,
|
|
20964
|
+
walletCurrency
|
|
20955
20965
|
}) {
|
|
20956
20966
|
const branch2 = info.meta.branch ?? "main";
|
|
20957
20967
|
const summary = info.meta.summary ?? `${info.messageCount} message${info.messageCount === 1 ? "" : "s"}`;
|
|
20958
20968
|
const turns = info.meta.turnCount ?? Math.ceil(info.messageCount / 2);
|
|
20959
|
-
const
|
|
20969
|
+
const currency = walletCurrency ?? info.meta.balanceCurrency;
|
|
20970
|
+
const costLabel = info.meta.totalCostUsd !== void 0 ? formatCost(info.meta.totalCostUsd, currency, 2) : "";
|
|
20960
20971
|
const time = relativeTime2(info.mtime);
|
|
20961
|
-
return /* @__PURE__ */ React28.createElement(Box21, null, /* @__PURE__ */ React28.createElement(Text20, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React28.createElement(Text20, { bold: focused, color: focused ? FG.strong : FG.sub }, info.name.padEnd(12)), /* @__PURE__ */ React28.createElement(Text20, { color: FG.meta }, ` \xB7 ${branch2.padEnd(8)} \xB7 `), /* @__PURE__ */ React28.createElement(Text20, { color: focused ? FG.body : FG.sub }, truncate2(summary, 40)), /* @__PURE__ */ React28.createElement(Box21, { flexGrow: 1 }), /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, `${time.padStart(11)} `), /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, `${turns} turns`),
|
|
20972
|
+
return /* @__PURE__ */ React28.createElement(Box21, null, /* @__PURE__ */ React28.createElement(Text20, { color: focused ? TONE.brand : FG.faint }, focused ? " \u25B8 " : " "), /* @__PURE__ */ React28.createElement(Text20, { bold: focused, color: focused ? FG.strong : FG.sub }, info.name.padEnd(12)), /* @__PURE__ */ React28.createElement(Text20, { color: FG.meta }, ` \xB7 ${branch2.padEnd(8)} \xB7 `), /* @__PURE__ */ React28.createElement(Text20, { color: focused ? FG.body : FG.sub }, truncate2(summary, 40)), /* @__PURE__ */ React28.createElement(Box21, { flexGrow: 1 }), /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, `${time.padStart(11)} `), /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, `${turns} turns`), costLabel ? /* @__PURE__ */ React28.createElement(Text20, { color: FG.faint }, ` \xB7 ${costLabel}`) : null);
|
|
20962
20973
|
}
|
|
20963
20974
|
function truncate2(s, max) {
|
|
20964
20975
|
if (s.length <= max) return s;
|
|
@@ -22953,7 +22964,11 @@ function groupByFile(hits) {
|
|
|
22953
22964
|
|
|
22954
22965
|
// src/cli/ui/cards/StreamingCard.tsx
|
|
22955
22966
|
import { Box as Box39, Text as Text40, useStdout as useStdout9 } from "ink";
|
|
22956
|
-
import React50 from "react";
|
|
22967
|
+
import React50, { useContext as useContext10 } from "react";
|
|
22968
|
+
|
|
22969
|
+
// src/cli/ui/layout/LiveExpandContext.ts
|
|
22970
|
+
import { createContext as createContext9 } from "react";
|
|
22971
|
+
var LiveExpandContext = createContext9(false);
|
|
22957
22972
|
|
|
22958
22973
|
// src/cli/ui/markdown.tsx
|
|
22959
22974
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
@@ -23268,40 +23283,81 @@ function plainText(tokens) {
|
|
|
23268
23283
|
|
|
23269
23284
|
// src/cli/ui/cards/StreamingCard.tsx
|
|
23270
23285
|
var STREAMING_PREVIEW_LINES2 = 4;
|
|
23286
|
+
var EXPANDED_MAX_LINES = 60;
|
|
23287
|
+
var MIN_ELAPSED_MS_FOR_RATE = 500;
|
|
23288
|
+
var MIN_TOKENS_FOR_RATE = 4;
|
|
23289
|
+
function formatTokenCount(n) {
|
|
23290
|
+
if (n >= 1e4) return `${(n / 1e3).toFixed(1)}k`;
|
|
23291
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(2)}k`;
|
|
23292
|
+
return String(n);
|
|
23293
|
+
}
|
|
23294
|
+
function tokenRate(text, startTs, endTs) {
|
|
23295
|
+
const tokens = countTokens(text);
|
|
23296
|
+
const elapsedMs = endTs - startTs;
|
|
23297
|
+
if (elapsedMs < MIN_ELAPSED_MS_FOR_RATE || tokens < MIN_TOKENS_FOR_RATE) {
|
|
23298
|
+
return { tokens, tps: null };
|
|
23299
|
+
}
|
|
23300
|
+
return { tokens, tps: Math.round(tokens * 1e3 / elapsedMs) };
|
|
23301
|
+
}
|
|
23302
|
+
var PILL_RATE = { bg: "#11141a", fg: "#8b949e" };
|
|
23271
23303
|
function StreamingCard({ card }) {
|
|
23272
23304
|
const { stdout: stdout4 } = useStdout9();
|
|
23273
23305
|
const cols = stdout4?.columns ?? 80;
|
|
23306
|
+
const expanded = useContext10(LiveExpandContext);
|
|
23307
|
+
const reserveCap = expanded ? EXPANDED_MAX_LINES + 2 : STREAMING_PREVIEW_LINES2 + 2;
|
|
23274
23308
|
useReserveRows("stream", {
|
|
23275
23309
|
min: STREAMING_PREVIEW_LINES2 + 1,
|
|
23276
|
-
max:
|
|
23310
|
+
max: reserveCap
|
|
23277
23311
|
});
|
|
23312
|
+
useSlowTick();
|
|
23278
23313
|
const modelBadge = card.model ? modelBadgeFor(card.model) : null;
|
|
23279
23314
|
const modelPill = modelBadge ? /* @__PURE__ */ React50.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null;
|
|
23280
23315
|
if (card.done && !card.aborted) {
|
|
23281
|
-
|
|
23316
|
+
const { tokens, tps } = tokenRate(card.text, card.ts, card.endedAt ?? Date.now());
|
|
23317
|
+
const ratePill = tokens >= MIN_TOKENS_FOR_RATE && tps !== null ? /* @__PURE__ */ React50.createElement(Pill, { label: `${formatTokenCount(tokens)} tok \xB7 ${tps} t/s`, ...PILL_RATE, bold: false }) : null;
|
|
23318
|
+
return /* @__PURE__ */ React50.createElement(Card, { tone: TONE.ok }, /* @__PURE__ */ React50.createElement(
|
|
23319
|
+
CardHeader,
|
|
23320
|
+
{
|
|
23321
|
+
glyph: "\u2039",
|
|
23322
|
+
tone: TONE.ok,
|
|
23323
|
+
title: "reply",
|
|
23324
|
+
right: /* @__PURE__ */ React50.createElement(React50.Fragment, null, ratePill, modelPill)
|
|
23325
|
+
}
|
|
23326
|
+
), /* @__PURE__ */ React50.createElement(Markdown, { text: card.text }));
|
|
23282
23327
|
}
|
|
23283
23328
|
const lineCells = Math.max(20, cols - 4);
|
|
23284
23329
|
const allLines = card.text.length > 0 ? card.text.split("\n") : [""];
|
|
23285
23330
|
const visualLines = allLines.flatMap((l) => wrapToCells(l, lineCells));
|
|
23286
|
-
const
|
|
23331
|
+
const cap = expanded ? EXPANDED_MAX_LINES : STREAMING_PREVIEW_LINES2;
|
|
23332
|
+
const visible = visualLines.slice(-cap);
|
|
23333
|
+
const droppedAbove = Math.max(0, visualLines.length - visible.length);
|
|
23287
23334
|
const aborted = !!card.aborted;
|
|
23288
23335
|
const headColor = aborted ? TONE.err : TONE_ACTIVE.brand;
|
|
23289
23336
|
const glyph = aborted ? "\u2039" : "\u25C8";
|
|
23290
23337
|
const headLabel = aborted ? "aborted" : "writing\u2026";
|
|
23338
|
+
const { tokens: liveTokens, tps: liveTps } = tokenRate(card.text, card.ts, Date.now());
|
|
23339
|
+
const liveRatePill = !aborted && liveTokens >= MIN_TOKENS_FOR_RATE && liveTps !== null ? /* @__PURE__ */ React50.createElement(Pill, { label: `${liveTps} t/s`, ...PILL_RATE, bold: false }) : null;
|
|
23340
|
+
const expandPill = !aborted ? /* @__PURE__ */ React50.createElement(Pill, { label: expanded ? "expanded \u2303o" : "preview \u2303o", ...PILL_RATE, bold: false }) : null;
|
|
23291
23341
|
return /* @__PURE__ */ React50.createElement(Card, { tone: headColor }, /* @__PURE__ */ React50.createElement(
|
|
23292
23342
|
CardHeader,
|
|
23293
23343
|
{
|
|
23294
23344
|
glyph,
|
|
23295
23345
|
tone: headColor,
|
|
23296
23346
|
title: headLabel,
|
|
23297
|
-
right: /* @__PURE__ */ React50.createElement(React50.Fragment, null, aborted ? null : /* @__PURE__ */ React50.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand }), modelPill)
|
|
23347
|
+
right: /* @__PURE__ */ React50.createElement(React50.Fragment, null, liveRatePill, expandPill, aborted ? null : /* @__PURE__ */ React50.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand }), modelPill)
|
|
23298
23348
|
}
|
|
23299
|
-
),
|
|
23349
|
+
), expanded && droppedAbove > 0 ? /* @__PURE__ */ React50.createElement(
|
|
23350
|
+
Text40,
|
|
23351
|
+
{
|
|
23352
|
+
color: FG.faint
|
|
23353
|
+
},
|
|
23354
|
+
`\u22EF ${droppedAbove} earlier line${droppedAbove === 1 ? "" : "s"} above`
|
|
23355
|
+
) : null, visible.map((line, i) => /* @__PURE__ */ React50.createElement(Box39, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React50.createElement(Text40, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React50.createElement(Text40, { color: FG.faint }, "[truncated by esc]") : null);
|
|
23300
23356
|
}
|
|
23301
23357
|
|
|
23302
23358
|
// src/cli/ui/cards/SubAgentCard.tsx
|
|
23303
23359
|
import { Box as Box40, Text as Text41 } from "ink";
|
|
23304
|
-
import React51, { useContext as
|
|
23360
|
+
import React51, { useContext as useContext11 } from "react";
|
|
23305
23361
|
var STATUS_COLOR2 = {
|
|
23306
23362
|
running: TONE_ACTIVE.violet,
|
|
23307
23363
|
done: TONE.ok,
|
|
@@ -23312,7 +23368,7 @@ function SubAgentCard({ card }) {
|
|
|
23312
23368
|
const headGlyph = card.status === "failed" ? "\u2716" : "\u232C";
|
|
23313
23369
|
const runningChildren = card.children.filter((c) => !isChildDone(c)).length;
|
|
23314
23370
|
const isRunning = card.status === "running";
|
|
23315
|
-
const inLive =
|
|
23371
|
+
const inLive = useContext11(ActiveCardContext);
|
|
23316
23372
|
const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren} running`] : ["working"] : [{ text: card.status, color: headColor }];
|
|
23317
23373
|
return /* @__PURE__ */ React51.createElement(Card, { tone: headColor }, /* @__PURE__ */ React51.createElement(
|
|
23318
23374
|
CardHeader,
|
|
@@ -23705,14 +23761,15 @@ function isSettled(card) {
|
|
|
23705
23761
|
}
|
|
23706
23762
|
}
|
|
23707
23763
|
function splitCardStream(cards, suppressLive = false) {
|
|
23708
|
-
const
|
|
23709
|
-
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
|
|
23714
|
-
|
|
23715
|
-
|
|
23764
|
+
const firstUnsettledIdx = cards.findIndex((c) => !isSettled(c));
|
|
23765
|
+
if (firstUnsettledIdx === -1) {
|
|
23766
|
+
return { committed: cards.slice(), live: [] };
|
|
23767
|
+
}
|
|
23768
|
+
const committed = cards.slice(0, firstUnsettledIdx);
|
|
23769
|
+
const live = cards.slice(firstUnsettledIdx);
|
|
23770
|
+
if (suppressLive && live.length > 0 && !isSettled(live[live.length - 1])) {
|
|
23771
|
+
return { committed, live: live.slice(0, -1) };
|
|
23772
|
+
}
|
|
23716
23773
|
return { committed, live };
|
|
23717
23774
|
}
|
|
23718
23775
|
function CardStream({
|
|
@@ -23768,14 +23825,15 @@ function UndoBanner({
|
|
|
23768
23825
|
}) {
|
|
23769
23826
|
useTick();
|
|
23770
23827
|
const totalMs = 5e3;
|
|
23771
|
-
const
|
|
23828
|
+
const paused = banner.pausedRemainingMs !== null;
|
|
23829
|
+
const remainingMs = paused ? banner.pausedRemainingMs ?? 0 : Math.max(0, banner.expiresAt - Date.now());
|
|
23772
23830
|
const remainingSec = Math.ceil(remainingMs / 1e3);
|
|
23773
23831
|
const ok = banner.results.filter((r) => r.status === "applied" || r.status === "created").length;
|
|
23774
23832
|
const total = banner.results.length;
|
|
23775
|
-
const urgent = remainingSec <= 1;
|
|
23833
|
+
const urgent = !paused && remainingSec <= 1;
|
|
23776
23834
|
const pct2 = remainingMs / totalMs * 100;
|
|
23777
|
-
const tone = urgent ? TONE.err : TONE.accent;
|
|
23778
|
-
return /* @__PURE__ */ React59.createElement(Box45, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React59.createElement(Text47, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React59.createElement(Text47, { color: FG.faint }, " press "), /* @__PURE__ */ React59.createElement(Text47, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React59.createElement(Text47, { color: FG.faint }, " to undo "), /* @__PURE__ */ React59.createElement(CharBar, { pct: pct2, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React59.createElement(Text47, { color: FG.faint }, " "), /* @__PURE__ */ React59.createElement(Text47, { color: tone, bold: urgent }, `${remainingSec}s`));
|
|
23835
|
+
const tone = paused ? TONE.warn : urgent ? TONE.err : TONE.accent;
|
|
23836
|
+
return /* @__PURE__ */ React59.createElement(Box45, { marginY: 1, paddingX: 1 }, /* @__PURE__ */ React59.createElement(Text47, { backgroundColor: TONE.accent, color: "black", bold: true }, ` \u2713 AUTO-APPLIED ${ok}/${total} `), /* @__PURE__ */ React59.createElement(Text47, { color: FG.faint }, " press "), /* @__PURE__ */ React59.createElement(Text47, { backgroundColor: TONE.brand, color: "black", bold: true }, " u "), /* @__PURE__ */ React59.createElement(Text47, { color: FG.faint }, paused ? " to undo \xB7 " : " to undo \xB7 "), /* @__PURE__ */ React59.createElement(Text47, { backgroundColor: paused ? TONE.warn : FG.faint, color: "black", bold: true }, " space "), /* @__PURE__ */ React59.createElement(Text47, { color: FG.faint }, paused ? " to resume " : " to pause "), /* @__PURE__ */ React59.createElement(CharBar, { pct: pct2, width: 20, color: tone, showLabel: false }), /* @__PURE__ */ React59.createElement(Text47, { color: FG.faint }, " "), /* @__PURE__ */ React59.createElement(Text47, { color: tone, bold: urgent || paused }, paused ? `${remainingSec}s \xB7 paused` : `${remainingSec}s`));
|
|
23779
23837
|
}
|
|
23780
23838
|
function subagentPhaseLabel(phase, iter, elapsedMs) {
|
|
23781
23839
|
if (phase === "summarising") return "summarising findings\u2026";
|
|
@@ -27417,13 +27475,32 @@ function useEditHistory(codeMode) {
|
|
|
27417
27475
|
[]
|
|
27418
27476
|
);
|
|
27419
27477
|
const armUndoBanner = useCallback8((results) => {
|
|
27420
|
-
setUndoBanner({ results, expiresAt: Date.now() + 5e3 });
|
|
27478
|
+
setUndoBanner({ results, expiresAt: Date.now() + 5e3, pausedRemainingMs: null });
|
|
27421
27479
|
if (undoTimeoutRef.current) clearTimeout(undoTimeoutRef.current);
|
|
27422
27480
|
undoTimeoutRef.current = setTimeout(() => {
|
|
27423
27481
|
setUndoBanner(null);
|
|
27424
27482
|
undoTimeoutRef.current = null;
|
|
27425
27483
|
}, 5e3);
|
|
27426
27484
|
}, []);
|
|
27485
|
+
const toggleUndoPause = useCallback8(() => {
|
|
27486
|
+
setUndoBanner((prev) => {
|
|
27487
|
+
if (!prev) return prev;
|
|
27488
|
+
if (prev.pausedRemainingMs === null) {
|
|
27489
|
+
const remaining2 = Math.max(0, prev.expiresAt - Date.now());
|
|
27490
|
+
if (undoTimeoutRef.current) {
|
|
27491
|
+
clearTimeout(undoTimeoutRef.current);
|
|
27492
|
+
undoTimeoutRef.current = null;
|
|
27493
|
+
}
|
|
27494
|
+
return { ...prev, pausedRemainingMs: remaining2 };
|
|
27495
|
+
}
|
|
27496
|
+
const remaining = prev.pausedRemainingMs;
|
|
27497
|
+
undoTimeoutRef.current = setTimeout(() => {
|
|
27498
|
+
setUndoBanner(null);
|
|
27499
|
+
undoTimeoutRef.current = null;
|
|
27500
|
+
}, remaining);
|
|
27501
|
+
return { ...prev, expiresAt: Date.now() + remaining, pausedRemainingMs: null };
|
|
27502
|
+
});
|
|
27503
|
+
}, []);
|
|
27427
27504
|
const codeUndo = useCallback8(
|
|
27428
27505
|
(args = []) => {
|
|
27429
27506
|
if (!codeMode) return "not in code mode";
|
|
@@ -27583,6 +27660,7 @@ function useEditHistory(codeMode) {
|
|
|
27583
27660
|
undoBanner,
|
|
27584
27661
|
recordEdit,
|
|
27585
27662
|
armUndoBanner,
|
|
27663
|
+
toggleUndoPause,
|
|
27586
27664
|
codeUndo,
|
|
27587
27665
|
codeHistory,
|
|
27588
27666
|
codeShowEdit,
|
|
@@ -27830,6 +27908,10 @@ function AppInner({
|
|
|
27830
27908
|
const isStreaming = useAgentState((s) => s.cards.some((c) => c.kind === "streaming" && !c.done));
|
|
27831
27909
|
const [input, setInput] = useState18("");
|
|
27832
27910
|
const [busy, setBusy] = useState18(false);
|
|
27911
|
+
const [liveExpand, setLiveExpand] = useState18(false);
|
|
27912
|
+
useEffect14(() => {
|
|
27913
|
+
if (!isStreaming && liveExpand) setLiveExpand(false);
|
|
27914
|
+
}, [isStreaming, liveExpand]);
|
|
27833
27915
|
const [languageVersion, setLanguageVersion] = useState18(0);
|
|
27834
27916
|
useEffect14(() => onLanguageChange(() => setLanguageVersion((v) => v + 1)), []);
|
|
27835
27917
|
const [liveMcpServers, setLiveMcpServers] = useState18(() => mcpServers ?? []);
|
|
@@ -27882,6 +27964,7 @@ function AppInner({
|
|
|
27882
27964
|
undoBanner,
|
|
27883
27965
|
recordEdit,
|
|
27884
27966
|
armUndoBanner,
|
|
27967
|
+
toggleUndoPause,
|
|
27885
27968
|
codeUndo,
|
|
27886
27969
|
codeHistory,
|
|
27887
27970
|
codeShowEdit,
|
|
@@ -28342,7 +28425,7 @@ function AppInner({
|
|
|
28342
28425
|
const cur = editModeRef.current;
|
|
28343
28426
|
const next = cur === "review" ? "auto" : cur === "auto" ? "yolo" : "review";
|
|
28344
28427
|
setEditMode(next);
|
|
28345
|
-
const message = next === "yolo" ? "\u25B8 edit mode: YOLO \u2014 edits AND shell commands auto-run. /undo still rolls back edits. Use carefully." : next === "auto" ? "\u25B8 edit mode: AUTO \u2014 edits apply immediately; press u within 5s to undo. Shell commands still ask." : "\u25B8 edit mode: review \u2014 edits queue for /apply (or y) / /discard (or n)";
|
|
28428
|
+
const message = next === "yolo" ? "\u25B8 edit mode: YOLO \u2014 edits AND shell commands auto-run. /undo still rolls back edits. Use carefully." : next === "auto" ? "\u25B8 edit mode: AUTO \u2014 edits apply immediately; press u within 5s to undo (space pauses the timer). Shell commands still ask." : "\u25B8 edit mode: review \u2014 edits queue for /apply (or y) / /discard (or n)";
|
|
28346
28429
|
log.pushInfo(message);
|
|
28347
28430
|
return;
|
|
28348
28431
|
}
|
|
@@ -28354,6 +28437,14 @@ function AppInner({
|
|
|
28354
28437
|
log.pushInfo(out);
|
|
28355
28438
|
return;
|
|
28356
28439
|
}
|
|
28440
|
+
if (codeMode && input.length === 0 && chKey === " " && undoBanner && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
28441
|
+
toggleUndoPause();
|
|
28442
|
+
return;
|
|
28443
|
+
}
|
|
28444
|
+
if (key.ctrl && key.input === "o" && isStreaming && !pendingShell && !pendingPlan && !pendingReviseEditor && !pendingSessionsPicker && !pendingMcpHub && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
28445
|
+
setLiveExpand((v) => !v);
|
|
28446
|
+
return;
|
|
28447
|
+
}
|
|
28357
28448
|
if (busy) return;
|
|
28358
28449
|
if (pendingShell) return;
|
|
28359
28450
|
if (atMatches && atMatches.length > 0) {
|
|
@@ -29124,7 +29215,12 @@ function AppInner({
|
|
|
29124
29215
|
const m = loadSessionMeta(session);
|
|
29125
29216
|
const cost2 = (m.totalCostUsd ?? 0) + (ev.stats?.cost ?? 0);
|
|
29126
29217
|
const turn = (m.turnCount ?? 0) + 1;
|
|
29127
|
-
|
|
29218
|
+
const currency = walletCurrencyRef.current;
|
|
29219
|
+
patchSessionMeta(session, {
|
|
29220
|
+
totalCostUsd: cost2,
|
|
29221
|
+
turnCount: turn,
|
|
29222
|
+
...currency ? { balanceCurrency: currency } : {}
|
|
29223
|
+
});
|
|
29128
29224
|
}
|
|
29129
29225
|
} else if (ev.role === "tool_start") {
|
|
29130
29226
|
handleToolStart(ev, {
|
|
@@ -29632,7 +29728,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
29632
29728
|
// changes (incoming stream, key press, modal popup).
|
|
29633
29729
|
!busy && !isStreaming
|
|
29634
29730
|
},
|
|
29635
|
-
/* @__PURE__ */ React66.createElement(ViewportBudgetProvider, null, /* @__PURE__ */ React66.createElement(Box49, { flexDirection: "row" }, /* @__PURE__ */ React66.createElement(Box49, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React66.createElement(Box49, { flexDirection: "column" }, /* @__PURE__ */ React66.createElement(CardStream, { suppressLive: modalOpen }), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React66.createElement(
|
|
29731
|
+
/* @__PURE__ */ React66.createElement(ViewportBudgetProvider, null, /* @__PURE__ */ React66.createElement(Box49, { flexDirection: "row" }, /* @__PURE__ */ React66.createElement(Box49, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React66.createElement(Box49, { flexDirection: "column" }, /* @__PURE__ */ React66.createElement(LiveExpandContext.Provider, { value: liveExpand }, /* @__PURE__ */ React66.createElement(CardStream, { suppressLive: modalOpen })), !hasConversation && !busy && !isStreaming ? /* @__PURE__ */ React66.createElement(
|
|
29636
29732
|
WelcomeBanner,
|
|
29637
29733
|
{
|
|
29638
29734
|
inCodeMode: !!codeMode,
|
|
@@ -29695,6 +29791,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
29695
29791
|
{
|
|
29696
29792
|
sessions: sessionsPickerList,
|
|
29697
29793
|
workspace: currentRootDir,
|
|
29794
|
+
walletCurrency: walletCurrencyRef.current,
|
|
29698
29795
|
onChoose: (outcome) => {
|
|
29699
29796
|
if (outcome.kind === "open") {
|
|
29700
29797
|
setPendingSessionsPicker(false);
|