reasonix 0.34.1 → 0.36.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/dashboard/app.css +16 -14
- package/dashboard/dist/app.js +77 -18
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{chat-TD6GR3QK.js → chat-RGMYAOY2.js} +18 -17
- package/dist/cli/{chunk-SA4UGZPG.js → chunk-2MCYGFLK.js} +15 -10
- package/dist/cli/chunk-2MCYGFLK.js.map +1 -0
- package/dist/cli/{chunk-SW3CCXEV.js → chunk-4Q3GRJIU.js} +2 -2
- package/dist/cli/{chunk-5JXXEPDM.js → chunk-BHLHOS5Y.js} +8 -2
- package/dist/cli/chunk-BHLHOS5Y.js.map +1 -0
- package/dist/cli/{chunk-F3ILWP2L.js → chunk-BJ376EN3.js} +9 -8
- package/dist/cli/chunk-BJ376EN3.js.map +1 -0
- package/dist/cli/{chunk-2AWTGJ2C.js → chunk-CRPQUBP6.js} +26 -9
- package/dist/cli/{chunk-2AWTGJ2C.js.map → chunk-CRPQUBP6.js.map} +1 -1
- package/dist/cli/{chunk-EINEIIIW.js → chunk-EN4LAZW5.js} +563 -250
- package/dist/cli/chunk-EN4LAZW5.js.map +1 -0
- package/dist/cli/{chunk-OERAGRJX.js → chunk-IPCPEZWQ.js} +2 -2
- package/dist/cli/{chunk-U3V2ZQ5J.js → chunk-KJQIA4US.js} +6 -2
- package/dist/cli/chunk-KJQIA4US.js.map +1 -0
- package/dist/cli/{chunk-Q36KBLSU.js → chunk-MLXUGPJE.js} +292 -35
- package/dist/cli/chunk-MLXUGPJE.js.map +1 -0
- package/dist/cli/{chunk-SX6L4HZZ.js → chunk-QPNZWUZF.js} +53 -6
- package/dist/cli/chunk-QPNZWUZF.js.map +1 -0
- package/dist/cli/{chunk-LNTORE5K.js → chunk-QRUQ2BFT.js} +159 -40
- package/dist/cli/chunk-QRUQ2BFT.js.map +1 -0
- package/dist/cli/{chunk-KZHMKOJH.js → chunk-T52GAWPP.js} +25 -3
- package/dist/cli/chunk-T52GAWPP.js.map +1 -0
- package/dist/cli/{chunk-I6YIAK6C.js → chunk-UNMYFZPZ.js} +2 -2
- package/dist/cli/{update-4TJWRUIN.js → chunk-WJ3YX4PZ.js} +51 -12
- package/dist/cli/chunk-WJ3YX4PZ.js.map +1 -0
- package/dist/cli/{chunk-RXGEGA7K.js → chunk-XQIFIB3U.js} +18 -7
- package/dist/cli/{chunk-RXGEGA7K.js.map → chunk-XQIFIB3U.js.map} +1 -1
- package/dist/cli/{chunk-2EBODRRO.js → chunk-ZJR4QLXB.js} +5 -1
- package/dist/cli/{chunk-2EBODRRO.js.map → chunk-ZJR4QLXB.js.map} +1 -1
- package/dist/cli/{chunk-6TMHAK5D.js → chunk-ZU45XW3P.js} +2 -2
- package/dist/cli/code-KJB3WDU6.js +435 -0
- package/dist/cli/code-KJB3WDU6.js.map +1 -0
- package/dist/cli/{commands-MEZPSEHV.js → commands-FE2UDFBC.js} +3 -3
- package/dist/cli/{commit-CE4EFTUQ.js → commit-3IAGB22T.js} +5 -4
- package/dist/cli/commit-3IAGB22T.js.map +1 -0
- package/dist/cli/{doctor-YASM64X6.js → doctor-DKD34EFD.js} +7 -7
- package/dist/cli/index.js +35 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-LDFK5QJI.js → mcp-2RDEQST6.js} +2 -2
- package/dist/cli/{mcp-browse-FYHEITCM.js → mcp-browse-VM5GLRBQ.js} +2 -2
- package/dist/cli/{mcp-inspect-T2HBR22P.js → mcp-inspect-CWSVCZUQ.js} +3 -3
- package/dist/cli/{prompt-V47QKSAR.js → prompt-YEKXMNNV.js} +3 -3
- package/dist/cli/{replay-JEDLU7F2.js → replay-D7RT2DR7.js} +3 -3
- package/dist/cli/replay-D7RT2DR7.js.map +1 -0
- package/dist/cli/{run-NHD2RSTD.js → run-FK5UBIIM.js} +13 -12
- package/dist/cli/run-FK5UBIIM.js.map +1 -0
- package/dist/cli/{server-MC4A4WAJ.js → server-W4XJK4GX.js} +17 -17
- package/dist/cli/{server-MC4A4WAJ.js.map → server-W4XJK4GX.js.map} +1 -1
- package/dist/cli/{sessions-ZHWJEW4L.js → sessions-YZXWMIWW.js} +10 -10
- package/dist/cli/{setup-DK43MT47.js → setup-IIAJXHP4.js} +196 -130
- package/dist/cli/setup-IIAJXHP4.js.map +1 -0
- package/dist/cli/update-GUCWB4UN.js +13 -0
- package/dist/cli/update-GUCWB4UN.js.map +1 -0
- package/dist/cli/{version-O362UKPM.js → version-DWD6RLIU.js} +12 -12
- package/dist/index.d.ts +19 -2
- package/dist/index.js +543 -78
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-5JXXEPDM.js.map +0 -1
- package/dist/cli/chunk-EINEIIIW.js.map +0 -1
- package/dist/cli/chunk-F3ILWP2L.js.map +0 -1
- package/dist/cli/chunk-KZHMKOJH.js.map +0 -1
- package/dist/cli/chunk-LNTORE5K.js.map +0 -1
- package/dist/cli/chunk-Q36KBLSU.js.map +0 -1
- package/dist/cli/chunk-SA4UGZPG.js.map +0 -1
- package/dist/cli/chunk-SX6L4HZZ.js.map +0 -1
- package/dist/cli/chunk-U3V2ZQ5J.js.map +0 -1
- package/dist/cli/code-TGUOQBRJ.js +0 -153
- package/dist/cli/code-TGUOQBRJ.js.map +0 -1
- package/dist/cli/commit-CE4EFTUQ.js.map +0 -1
- package/dist/cli/replay-JEDLU7F2.js.map +0 -1
- package/dist/cli/run-NHD2RSTD.js.map +0 -1
- package/dist/cli/setup-DK43MT47.js.map +0 -1
- package/dist/cli/update-4TJWRUIN.js.map +0 -1
- /package/dist/cli/{chat-TD6GR3QK.js.map → chat-RGMYAOY2.js.map} +0 -0
- /package/dist/cli/{chunk-SW3CCXEV.js.map → chunk-4Q3GRJIU.js.map} +0 -0
- /package/dist/cli/{chunk-OERAGRJX.js.map → chunk-IPCPEZWQ.js.map} +0 -0
- /package/dist/cli/{chunk-I6YIAK6C.js.map → chunk-UNMYFZPZ.js.map} +0 -0
- /package/dist/cli/{chunk-6TMHAK5D.js.map → chunk-ZU45XW3P.js.map} +0 -0
- /package/dist/cli/{commands-MEZPSEHV.js.map → commands-FE2UDFBC.js.map} +0 -0
- /package/dist/cli/{doctor-YASM64X6.js.map → doctor-DKD34EFD.js.map} +0 -0
- /package/dist/cli/{mcp-LDFK5QJI.js.map → mcp-2RDEQST6.js.map} +0 -0
- /package/dist/cli/{mcp-browse-FYHEITCM.js.map → mcp-browse-VM5GLRBQ.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-T2HBR22P.js.map → mcp-inspect-CWSVCZUQ.js.map} +0 -0
- /package/dist/cli/{prompt-V47QKSAR.js.map → prompt-YEKXMNNV.js.map} +0 -0
- /package/dist/cli/{sessions-ZHWJEW4L.js.map → sessions-YZXWMIWW.js.map} +0 -0
- /package/dist/cli/{version-O362UKPM.js.map → version-DWD6RLIU.js.map} +0 -0
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
toWholeFileEditBlock,
|
|
35
35
|
walkFilesStream,
|
|
36
36
|
webFetch
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-QRUQ2BFT.js";
|
|
38
38
|
import {
|
|
39
39
|
McpClient,
|
|
40
40
|
SseTransport,
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
StreamableHttpTransport,
|
|
43
43
|
inspectMcpServer,
|
|
44
44
|
parseMcpSpec
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-UNMYFZPZ.js";
|
|
46
46
|
import {
|
|
47
47
|
openTranscriptFile,
|
|
48
48
|
recordFromLoopEvent,
|
|
@@ -50,12 +50,12 @@ import {
|
|
|
50
50
|
} from "./chunk-XHQIK7B6.js";
|
|
51
51
|
import {
|
|
52
52
|
MemoryStore
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-ZU45XW3P.js";
|
|
54
54
|
import {
|
|
55
55
|
KeystrokeProvider,
|
|
56
56
|
SingleSelect,
|
|
57
57
|
useKeystroke
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-T52GAWPP.js";
|
|
59
59
|
import {
|
|
60
60
|
COLOR,
|
|
61
61
|
GLYPH,
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
ThemeProvider,
|
|
64
64
|
useColor,
|
|
65
65
|
useThemeTokens
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-ZJR4QLXB.js";
|
|
67
67
|
import {
|
|
68
68
|
PRESETS,
|
|
69
69
|
PRESET_DESCRIPTIONS,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
} from "./chunk-MHDNZXJJ.js";
|
|
72
72
|
import {
|
|
73
73
|
runDoctorChecks
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-BJ376EN3.js";
|
|
75
75
|
import {
|
|
76
76
|
countTokens
|
|
77
77
|
} from "./chunk-DAEAAVDF.js";
|
|
@@ -84,6 +84,10 @@ import {
|
|
|
84
84
|
import {
|
|
85
85
|
renderDashboard
|
|
86
86
|
} from "./chunk-4DCHFFEY.js";
|
|
87
|
+
import {
|
|
88
|
+
MANUAL_UPDATE_COMMANDS,
|
|
89
|
+
planUpdate
|
|
90
|
+
} from "./chunk-WJ3YX4PZ.js";
|
|
87
91
|
import {
|
|
88
92
|
SLASH_COMMANDS,
|
|
89
93
|
archivePlanState,
|
|
@@ -97,29 +101,29 @@ import {
|
|
|
97
101
|
resolveSlashAlias,
|
|
98
102
|
savePlanState,
|
|
99
103
|
suggestSlashCommands
|
|
100
|
-
} from "./chunk-
|
|
101
|
-
import {
|
|
102
|
-
eventLogPath,
|
|
103
|
-
openEventSink
|
|
104
|
-
} from "./chunk-G3XNWSFN.js";
|
|
104
|
+
} from "./chunk-2MCYGFLK.js";
|
|
105
105
|
import {
|
|
106
106
|
fetchSmitheryDetail,
|
|
107
107
|
loadMorePages,
|
|
108
108
|
openRegistry,
|
|
109
109
|
specStringFor
|
|
110
110
|
} from "./chunk-SOZE7V7V.js";
|
|
111
|
+
import {
|
|
112
|
+
eventLogPath,
|
|
113
|
+
openEventSink
|
|
114
|
+
} from "./chunk-G3XNWSFN.js";
|
|
111
115
|
import {
|
|
112
116
|
BUILTIN_ALLOWLIST,
|
|
113
117
|
formatCommandResult,
|
|
114
118
|
pauseGate,
|
|
115
119
|
runCommand
|
|
116
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-QPNZWUZF.js";
|
|
117
121
|
import {
|
|
118
122
|
PROJECT_MEMORY_FILE,
|
|
119
123
|
SkillStore,
|
|
120
124
|
memoryEnabled,
|
|
121
125
|
readProjectMemory
|
|
122
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-KJQIA4US.js";
|
|
123
127
|
import {
|
|
124
128
|
HOOK_EVENTS,
|
|
125
129
|
formatHookOutcomeMessage,
|
|
@@ -127,13 +131,7 @@ import {
|
|
|
127
131
|
loadHooks,
|
|
128
132
|
projectSettingsPath,
|
|
129
133
|
runHooks
|
|
130
|
-
} from "./chunk-
|
|
131
|
-
import {
|
|
132
|
-
VERSION,
|
|
133
|
-
compareVersions,
|
|
134
|
-
getLatestVersion,
|
|
135
|
-
isNpxInstall
|
|
136
|
-
} from "./chunk-2AWTGJ2C.js";
|
|
134
|
+
} from "./chunk-IPCPEZWQ.js";
|
|
137
135
|
import {
|
|
138
136
|
deleteSession,
|
|
139
137
|
detectGitBranch,
|
|
@@ -154,7 +152,7 @@ import {
|
|
|
154
152
|
setLanguage,
|
|
155
153
|
t,
|
|
156
154
|
tObj
|
|
157
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-MLXUGPJE.js";
|
|
158
156
|
import {
|
|
159
157
|
addProjectShellAllowed,
|
|
160
158
|
clearProjectShellAllowed,
|
|
@@ -162,6 +160,7 @@ import {
|
|
|
162
160
|
editModeHintShown,
|
|
163
161
|
isPlausibleKey,
|
|
164
162
|
loadApiKey,
|
|
163
|
+
loadBaseUrl,
|
|
165
164
|
loadEditMode,
|
|
166
165
|
loadProjectShellAllowed,
|
|
167
166
|
loadReasoningEffort,
|
|
@@ -181,7 +180,7 @@ import {
|
|
|
181
180
|
webSearchEndpoint,
|
|
182
181
|
webSearchEngine,
|
|
183
182
|
writeConfig
|
|
184
|
-
} from "./chunk-
|
|
183
|
+
} from "./chunk-BHLHOS5Y.js";
|
|
185
184
|
import {
|
|
186
185
|
CARD,
|
|
187
186
|
FG,
|
|
@@ -205,6 +204,13 @@ import {
|
|
|
205
204
|
DEEPSEEK_PRICING,
|
|
206
205
|
DEFAULT_CONTEXT_TOKENS
|
|
207
206
|
} from "./chunk-ORM6PK57.js";
|
|
207
|
+
import {
|
|
208
|
+
VERSION,
|
|
209
|
+
compareVersions,
|
|
210
|
+
detectInstallSource,
|
|
211
|
+
detectNpmInstallPrefix,
|
|
212
|
+
getLatestVersion
|
|
213
|
+
} from "./chunk-CRPQUBP6.js";
|
|
208
214
|
|
|
209
215
|
// src/cli/commands/chat.tsx
|
|
210
216
|
import { render } from "ink";
|
|
@@ -231,7 +237,7 @@ function buildMcpServerSummary(opts) {
|
|
|
231
237
|
// src/cli/ui/App.tsx
|
|
232
238
|
import { statSync } from "fs";
|
|
233
239
|
import { resolve as resolve2 } from "path";
|
|
234
|
-
import { Box as Box49, Text as Text52, useStdout as
|
|
240
|
+
import { Box as Box49, Text as Text52, useStdout as useStdout15 } from "ink";
|
|
235
241
|
import React60, { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef9, useState as useState20 } from "react";
|
|
236
242
|
|
|
237
243
|
// src/code/checkpoints.ts
|
|
@@ -2376,7 +2382,12 @@ function PlanStepListInner({ steps, statuses, focusStepId }) {
|
|
|
2376
2382
|
const doneCount = statusList.filter((s) => s === "done").length;
|
|
2377
2383
|
const pct = Math.round(doneCount / total * 100);
|
|
2378
2384
|
const showProgress = doneCount > 0;
|
|
2379
|
-
return /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box12, null, /* @__PURE__ */ React15.createElement(Text13, { dimColor: true }, showProgress ?
|
|
2385
|
+
return /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box12, null, /* @__PURE__ */ React15.createElement(Text13, { dimColor: true }, showProgress ? t(
|
|
2386
|
+
total === 1 ? "planFlow.stepList.counterDoneSingular" : "planFlow.stepList.counterDone",
|
|
2387
|
+
{ done: doneCount, total, pct }
|
|
2388
|
+
) : t(total === 1 ? "planFlow.stepList.counterSingular" : "planFlow.stepList.counter", {
|
|
2389
|
+
total
|
|
2390
|
+
}))), /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, steps.map((step, i) => {
|
|
2380
2391
|
const status2 = statusList[i];
|
|
2381
2392
|
const isLast = i === total - 1;
|
|
2382
2393
|
const isCur = focusStepId === step.id;
|
|
@@ -2413,25 +2424,25 @@ function PlanCheckpointConfirmInner({
|
|
|
2413
2424
|
const isLast = total > 0 && completed >= total;
|
|
2414
2425
|
const statuses = buildStatusMap(steps, completedStepIds, stepId, isLast);
|
|
2415
2426
|
const subtitle = counter ? `${counter} \xB7 ${label}` : label;
|
|
2416
|
-
return /* @__PURE__ */ React16.createElement(ApprovalCard, { tone: "ok", glyph: "\u26C1", title: "
|
|
2427
|
+
return /* @__PURE__ */ React16.createElement(ApprovalCard, { tone: "ok", glyph: "\u26C1", title: t("planFlow.checkpoint.title"), metaRight: subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React16.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React16.createElement(
|
|
2417
2428
|
SingleSelect,
|
|
2418
2429
|
{
|
|
2419
2430
|
initialValue: isLast ? "stop" : "continue",
|
|
2420
2431
|
items: [
|
|
2421
2432
|
{
|
|
2422
2433
|
value: "continue",
|
|
2423
|
-
label: "
|
|
2424
|
-
hint: "
|
|
2434
|
+
label: t("planFlow.checkpoint.continue"),
|
|
2435
|
+
hint: t("planFlow.checkpoint.continueHint")
|
|
2425
2436
|
},
|
|
2426
2437
|
{
|
|
2427
2438
|
value: "revise",
|
|
2428
|
-
label: "
|
|
2429
|
-
hint: "
|
|
2439
|
+
label: t("planFlow.checkpoint.revise"),
|
|
2440
|
+
hint: t("planFlow.checkpoint.reviseHint")
|
|
2430
2441
|
},
|
|
2431
2442
|
{
|
|
2432
2443
|
value: "stop",
|
|
2433
|
-
label: "
|
|
2434
|
-
hint: "
|
|
2444
|
+
label: t("planFlow.checkpoint.stop"),
|
|
2445
|
+
hint: t("planFlow.checkpoint.stopHint")
|
|
2435
2446
|
}
|
|
2436
2447
|
],
|
|
2437
2448
|
onSubmit: (v) => onChoose(v),
|
|
@@ -4886,53 +4897,89 @@ function SpanText({
|
|
|
4886
4897
|
);
|
|
4887
4898
|
}
|
|
4888
4899
|
|
|
4900
|
+
// src/cli/ui/plan-open-questions.ts
|
|
4901
|
+
var HEADER_RE = /^(#{1,6})\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear|待确认|开放问题|风险|未知|假设|不确定)(?:[\s::/、,,].*)?$/im;
|
|
4902
|
+
function extractOpenQuestionsSection(plan2) {
|
|
4903
|
+
const lines = plan2.split("\n");
|
|
4904
|
+
let startIdx = -1;
|
|
4905
|
+
let startLevel = 0;
|
|
4906
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4907
|
+
const line = lines[i] ?? "";
|
|
4908
|
+
const m = line.match(HEADER_RE);
|
|
4909
|
+
if (m) {
|
|
4910
|
+
startIdx = i;
|
|
4911
|
+
startLevel = (m[1] ?? "#").length;
|
|
4912
|
+
break;
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
if (startIdx === -1) return null;
|
|
4916
|
+
let endIdx = lines.length;
|
|
4917
|
+
for (let j = startIdx + 1; j < lines.length; j++) {
|
|
4918
|
+
const line = lines[j] ?? "";
|
|
4919
|
+
const lh = line.match(/^(#{1,6})\s+\S/);
|
|
4920
|
+
if (lh && (lh[1] ?? "").length <= startLevel) {
|
|
4921
|
+
endIdx = j;
|
|
4922
|
+
break;
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
const block2 = lines.slice(startIdx, endIdx).join("\n").replace(/\s+$/g, "");
|
|
4926
|
+
return block2.length > 0 ? block2 : null;
|
|
4927
|
+
}
|
|
4928
|
+
|
|
4889
4929
|
// src/cli/ui/PlanConfirm.tsx
|
|
4890
4930
|
var PLAN_BODY_PREVIEW_LINES = 24;
|
|
4891
4931
|
function PlanConfirmInner({ plan: plan2, steps, onChoose }) {
|
|
4892
4932
|
const stepRows = steps?.length ?? 0;
|
|
4893
4933
|
const hasSteps = stepRows > 0;
|
|
4934
|
+
const openQuestions = extractOpenQuestionsSection(plan2);
|
|
4894
4935
|
const planLines = plan2.split("\n");
|
|
4895
4936
|
const truncatedBody = planLines.length > PLAN_BODY_PREVIEW_LINES;
|
|
4896
4937
|
const previewBody = truncatedBody ? planLines.slice(0, PLAN_BODY_PREVIEW_LINES).join("\n") : plan2;
|
|
4897
4938
|
const previewRows = truncatedBody ? PLAN_BODY_PREVIEW_LINES : Math.min(planLines.length, PLAN_BODY_PREVIEW_LINES);
|
|
4898
4939
|
const reservedFor = hasSteps ? stepRows : previewRows;
|
|
4899
|
-
|
|
4900
|
-
|
|
4940
|
+
const oqRows = openQuestions ? openQuestions.split("\n").length : 0;
|
|
4941
|
+
useReserveRows("modal", { min: 10, max: Math.max(16, reservedFor + oqRows + 14) });
|
|
4942
|
+
const refineLabel = t("planFlow.picker.refine");
|
|
4943
|
+
const bannerTemplate = t("planFlow.openQuestionsBanner");
|
|
4944
|
+
const [bannerBefore, bannerAfter] = bannerTemplate.split("{refine}");
|
|
4901
4945
|
return /* @__PURE__ */ React18.createElement(
|
|
4902
4946
|
ApprovalCard,
|
|
4903
4947
|
{
|
|
4904
4948
|
tone: "accent",
|
|
4905
4949
|
glyph: "\u229E",
|
|
4906
|
-
title: "
|
|
4907
|
-
metaRight: "
|
|
4950
|
+
title: t("planFlow.approveCardTitle"),
|
|
4951
|
+
metaRight: t("planFlow.approveCardMetaRight"),
|
|
4908
4952
|
metaRightColor: CARD.plan.color
|
|
4909
4953
|
},
|
|
4910
|
-
|
|
4911
|
-
hasSteps ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(PlanStepList, { steps })) : plan2.trim().length > 0 ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(MarkdownView, { text: previewBody }), truncatedBody ? /* @__PURE__ */ React18.createElement(Text15, { color: FG.faint },
|
|
4954
|
+
openQuestions ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Text15, { color: TONE.warn }, bannerBefore ?? "", /* @__PURE__ */ React18.createElement(Text15, { bold: true }, refineLabel), bannerAfter ?? ""), /* @__PURE__ */ React18.createElement(Box15, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Text15, { color: TONE.warn, bold: true }, t("planFlow.openQuestionsHeader")), /* @__PURE__ */ React18.createElement(MarkdownView, { text: openQuestions }))) : null,
|
|
4955
|
+
hasSteps ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(PlanStepList, { steps })) : plan2.trim().length > 0 ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(MarkdownView, { text: previewBody }), truncatedBody ? /* @__PURE__ */ React18.createElement(Text15, { color: FG.faint }, t(
|
|
4956
|
+
planLines.length - PLAN_BODY_PREVIEW_LINES === 1 ? "planFlow.truncatedBodyMore" : "planFlow.truncatedBodyMorePlural",
|
|
4957
|
+
{ n: planLines.length - PLAN_BODY_PREVIEW_LINES }
|
|
4958
|
+
)) : null) : null,
|
|
4912
4959
|
/* @__PURE__ */ React18.createElement(
|
|
4913
4960
|
SingleSelect,
|
|
4914
4961
|
{
|
|
4915
|
-
initialValue:
|
|
4962
|
+
initialValue: openQuestions ? "refine" : "approve",
|
|
4916
4963
|
items: [
|
|
4917
4964
|
{
|
|
4918
4965
|
value: "approve",
|
|
4919
|
-
label: "accept",
|
|
4920
|
-
hint: "
|
|
4966
|
+
label: t("planFlow.picker.accept"),
|
|
4967
|
+
hint: t("planFlow.picker.acceptHint")
|
|
4921
4968
|
},
|
|
4922
4969
|
{
|
|
4923
4970
|
value: "refine",
|
|
4924
|
-
label:
|
|
4925
|
-
hint: "
|
|
4971
|
+
label: refineLabel,
|
|
4972
|
+
hint: t("planFlow.picker.refineHint")
|
|
4926
4973
|
},
|
|
4927
4974
|
{
|
|
4928
4975
|
value: "revise",
|
|
4929
|
-
label: "revise",
|
|
4930
|
-
hint: "
|
|
4976
|
+
label: t("planFlow.picker.revise"),
|
|
4977
|
+
hint: t("planFlow.picker.reviseHint")
|
|
4931
4978
|
},
|
|
4932
4979
|
{
|
|
4933
4980
|
value: "cancel",
|
|
4934
|
-
label: "reject",
|
|
4935
|
-
hint: "
|
|
4981
|
+
label: t("planFlow.picker.reject"),
|
|
4982
|
+
hint: t("planFlow.picker.rejectHint")
|
|
4936
4983
|
}
|
|
4937
4984
|
],
|
|
4938
4985
|
onSubmit: (v) => onChoose(v),
|
|
@@ -4974,49 +5021,25 @@ function useElapsedSeconds() {
|
|
|
4974
5021
|
}
|
|
4975
5022
|
|
|
4976
5023
|
// src/cli/ui/PlanRefineInput.tsx
|
|
4977
|
-
var
|
|
4978
|
-
approve: {
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
hint: "Answer questions the plan raised, add constraints, or just press Enter to approve as-is.",
|
|
4984
|
-
blankHint: " (Enter with blank = approve without extra instructions.)"
|
|
4985
|
-
},
|
|
4986
|
-
refine: {
|
|
4987
|
-
title: "refining \u2014 what should the model change?",
|
|
4988
|
-
glyph: "\u270E",
|
|
4989
|
-
tone: "warn",
|
|
4990
|
-
cursorColor: CARD.warn.color,
|
|
4991
|
-
hint: "Describe what's wrong or missing, or answer questions the plan raised.",
|
|
4992
|
-
blankHint: " (Enter with blank = ask the model to list concrete questions.)"
|
|
4993
|
-
},
|
|
4994
|
-
reject: {
|
|
4995
|
-
title: "rejecting \u2014 tell the model why (optional)",
|
|
4996
|
-
glyph: "\u2717",
|
|
4997
|
-
tone: "error",
|
|
4998
|
-
cursorColor: CARD.error.color,
|
|
4999
|
-
hint: "Say what the model got wrong about your goal, or what you actually want instead.",
|
|
5000
|
-
blankHint: " (Enter with blank = cancel without explanation; the model will ask what you want.)"
|
|
5001
|
-
},
|
|
5002
|
-
"checkpoint-revise": {
|
|
5003
|
-
title: "revising \u2014 what should change before the next step?",
|
|
5004
|
-
glyph: "\u270E",
|
|
5005
|
-
tone: "warn",
|
|
5006
|
-
cursorColor: CARD.warn.color,
|
|
5007
|
-
hint: "Scope change, skip steps, alternative approach \u2014 the model adjusts the remaining plan.",
|
|
5008
|
-
blankHint: " (Enter with blank = continue with the current plan.)"
|
|
5009
|
-
},
|
|
5010
|
-
"choice-custom": {
|
|
5011
|
-
title: "custom answer \u2014 type whatever fits",
|
|
5012
|
-
glyph: "\u2325",
|
|
5013
|
-
tone: "accent",
|
|
5014
|
-
cursorColor: CARD.plan.color,
|
|
5015
|
-
hint: "Free-form reply. The model reads it verbatim and proceeds \u2014 no need to match the listed options.",
|
|
5016
|
-
blankHint: " (Enter with blank = ask the model what you actually want.)"
|
|
5017
|
-
}
|
|
5024
|
+
var MODE_VISUALS = {
|
|
5025
|
+
approve: { glyph: "\u25C7", tone: "user", cursorColor: CARD.user.color },
|
|
5026
|
+
refine: { glyph: "\u270E", tone: "warn", cursorColor: CARD.warn.color },
|
|
5027
|
+
reject: { glyph: "\u2717", tone: "error", cursorColor: CARD.error.color },
|
|
5028
|
+
"checkpoint-revise": { glyph: "\u270E", tone: "warn", cursorColor: CARD.warn.color },
|
|
5029
|
+
"choice-custom": { glyph: "\u2325", tone: "accent", cursorColor: CARD.plan.color }
|
|
5018
5030
|
};
|
|
5019
|
-
function
|
|
5031
|
+
function modeMeta(mode2) {
|
|
5032
|
+
const v = MODE_VISUALS[mode2];
|
|
5033
|
+
return {
|
|
5034
|
+
title: t(`planFlow.modes.${mode2}.title`),
|
|
5035
|
+
hint: t(`planFlow.modes.${mode2}.hint`),
|
|
5036
|
+
blankHint: t(`planFlow.modes.${mode2}.blankHint`),
|
|
5037
|
+
glyph: v.glyph,
|
|
5038
|
+
tone: v.tone,
|
|
5039
|
+
cursorColor: v.cursorColor
|
|
5040
|
+
};
|
|
5041
|
+
}
|
|
5042
|
+
function PlanRefineInput({ mode: mode2, questions, onSubmit, onCancel }) {
|
|
5020
5043
|
const [value, setValue] = useState9("");
|
|
5021
5044
|
useKeystroke((ev) => {
|
|
5022
5045
|
if (ev.paste) {
|
|
@@ -5041,15 +5064,17 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
|
|
|
5041
5064
|
});
|
|
5042
5065
|
const tick = useTick();
|
|
5043
5066
|
const cursorOn = Math.floor(tick / 4) % 2 === 0;
|
|
5044
|
-
const meta =
|
|
5067
|
+
const meta = modeMeta(mode2);
|
|
5068
|
+
const showQuestions = mode2 === "refine" && !!questions && questions.trim().length > 0;
|
|
5045
5069
|
return /* @__PURE__ */ React20.createElement(
|
|
5046
5070
|
ApprovalCard,
|
|
5047
5071
|
{
|
|
5048
5072
|
tone: meta.tone,
|
|
5049
5073
|
glyph: meta.glyph,
|
|
5050
5074
|
title: meta.title,
|
|
5051
|
-
footerHint: "
|
|
5075
|
+
footerHint: t("planFlow.refineFooter")
|
|
5052
5076
|
},
|
|
5077
|
+
showQuestions ? /* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React20.createElement(Text16, { color: TONE.warn, bold: true }, t("planFlow.refineQuestionsHeading")), /* @__PURE__ */ React20.createElement(MarkdownView, { text: questions })) : null,
|
|
5053
5078
|
/* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, { color: FG.sub }, meta.hint, value === "" ? meta.blankHint : "")),
|
|
5054
5079
|
/* @__PURE__ */ React20.createElement(Box16, null, /* @__PURE__ */ React20.createElement(Text16, { color: meta.cursorColor, bold: true }, "\u203A "), /* @__PURE__ */ React20.createElement(Text16, null, value), /* @__PURE__ */ React20.createElement(Text16, { color: meta.cursorColor, bold: true }, cursorOn ? "\u258D" : " "))
|
|
5055
5080
|
);
|
|
@@ -5303,9 +5328,17 @@ function processMultilineKey(value, cursor, keyIn) {
|
|
|
5303
5328
|
return cursor === value.length ? NOOP : { next: null, cursor: value.length, submit: false };
|
|
5304
5329
|
}
|
|
5305
5330
|
if (key.ctrl && key.input === "p") {
|
|
5331
|
+
if (value.includes("\n")) {
|
|
5332
|
+
const moved = moveCursorUp(value, cursor);
|
|
5333
|
+
if (moved !== cursor) return { next: null, cursor: moved, submit: false };
|
|
5334
|
+
}
|
|
5306
5335
|
return { ...NOOP, historyHandoff: "prev" };
|
|
5307
5336
|
}
|
|
5308
5337
|
if (key.ctrl && key.input === "n") {
|
|
5338
|
+
if (value.includes("\n")) {
|
|
5339
|
+
const moved = moveCursorDown(value, cursor);
|
|
5340
|
+
if (moved !== cursor) return { next: null, cursor: moved, submit: false };
|
|
5341
|
+
}
|
|
5309
5342
|
return { ...NOOP, historyHandoff: "next" };
|
|
5310
5343
|
}
|
|
5311
5344
|
if (key.leftArrow) {
|
|
@@ -5314,15 +5347,8 @@ function processMultilineKey(value, cursor, keyIn) {
|
|
|
5314
5347
|
if (key.rightArrow) {
|
|
5315
5348
|
return { next: null, cursor: Math.min(value.length, cursor + 1), submit: false };
|
|
5316
5349
|
}
|
|
5317
|
-
if (key.upArrow) {
|
|
5318
|
-
|
|
5319
|
-
const moved = moveCursorUp(value, cursor);
|
|
5320
|
-
return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
|
|
5321
|
-
}
|
|
5322
|
-
if (key.downArrow) {
|
|
5323
|
-
if (value.length === 0) return { ...NOOP, historyHandoff: "next" };
|
|
5324
|
-
const moved = moveCursorDown(value, cursor);
|
|
5325
|
-
return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
|
|
5350
|
+
if (key.upArrow || key.downArrow) {
|
|
5351
|
+
return NOOP;
|
|
5326
5352
|
}
|
|
5327
5353
|
if (key.ctrl && key.input === "a" || key.home) {
|
|
5328
5354
|
return { next: null, cursor: startOfLine(value, cursor), submit: false };
|
|
@@ -5888,7 +5914,8 @@ function HintRow() {
|
|
|
5888
5914
|
const items = [
|
|
5889
5915
|
{ key: "\u23CE", sep: "send" },
|
|
5890
5916
|
{ key: "\u21E7\u23CE", sep: "newline" },
|
|
5891
|
-
{ key: "\u2191\u2193", sep: "
|
|
5917
|
+
{ key: "\u2191\u2193", sep: "scroll" },
|
|
5918
|
+
{ key: "^P/^N", sep: "history" },
|
|
5892
5919
|
{ key: "esc", sep: "abort" },
|
|
5893
5920
|
{ key: "^C", sep: "quit" }
|
|
5894
5921
|
];
|
|
@@ -6404,8 +6431,12 @@ function ArgRow({ value, isSelected }) {
|
|
|
6404
6431
|
}
|
|
6405
6432
|
|
|
6406
6433
|
// src/cli/ui/SlashSuggestions.tsx
|
|
6407
|
-
import { Box as Box23, Text as Text23 } from "ink";
|
|
6434
|
+
import { Box as Box23, Text as Text23, useStdout as useStdout8 } from "ink";
|
|
6408
6435
|
import React27 from "react";
|
|
6436
|
+
var GROUP_MODE_MAX_ROWS = 24;
|
|
6437
|
+
var SEARCH_MODE_MAX_ROWS = 8;
|
|
6438
|
+
var COMMAND_NAME_CELLS = 14;
|
|
6439
|
+
var ARGS_CELLS = 14;
|
|
6409
6440
|
var GROUP_LABEL = {
|
|
6410
6441
|
chat: "CHAT",
|
|
6411
6442
|
setup: "SETUP",
|
|
@@ -6423,26 +6454,82 @@ function SlashSuggestions({
|
|
|
6423
6454
|
advancedHidden
|
|
6424
6455
|
}) {
|
|
6425
6456
|
const color = useColor();
|
|
6457
|
+
const { stdout } = useStdout8();
|
|
6458
|
+
const cols = stdout?.columns ?? 80;
|
|
6459
|
+
const [rememberedWindowStart, setRememberedWindowStart] = React27.useState(0);
|
|
6460
|
+
const maxRows = groupMode ? GROUP_MODE_MAX_ROWS : SEARCH_MODE_MAX_ROWS;
|
|
6461
|
+
const safeMatches = matches ?? [];
|
|
6462
|
+
const windowStart = computeWindowStart(
|
|
6463
|
+
safeMatches,
|
|
6464
|
+
maxRows,
|
|
6465
|
+
selectedIndex,
|
|
6466
|
+
rememberedWindowStart,
|
|
6467
|
+
groupMode
|
|
6468
|
+
);
|
|
6469
|
+
React27.useEffect(() => {
|
|
6470
|
+
setRememberedWindowStart(windowStart);
|
|
6471
|
+
}, [windowStart]);
|
|
6426
6472
|
if (matches === null) return null;
|
|
6427
6473
|
if (matches.length === 0) {
|
|
6428
6474
|
return /* @__PURE__ */ React27.createElement(Box23, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ React27.createElement(Text23, null, " "), /* @__PURE__ */ React27.createElement(Text23, { color: color.warn }, "no slash command matches that prefix"), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2014 Backspace to edit, or /help for the full list"));
|
|
6429
6475
|
}
|
|
6430
|
-
const MAX = groupMode ? 24 : 8;
|
|
6431
6476
|
const total = matches.length;
|
|
6432
|
-
const
|
|
6433
|
-
const
|
|
6477
|
+
const items = buildVisibleItems(matches, windowStart, maxRows, groupMode);
|
|
6478
|
+
const shownCommands = items.filter((item) => item.kind === "command");
|
|
6434
6479
|
const hiddenAbove = windowStart;
|
|
6435
|
-
const hiddenBelow = total - windowStart -
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6480
|
+
const hiddenBelow = total - windowStart - shownCommands.length;
|
|
6481
|
+
return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "column", paddingX: 1, marginTop: 1, flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React27.createElement(Box23, null, /* @__PURE__ */ React27.createElement(Text23, { color: color.accent, bold: true }, "/ "), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, `${total} command${total === 1 ? "" : "s"}`), hiddenAbove > 0 ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null), items.map((item) => {
|
|
6482
|
+
if (item.kind === "group") {
|
|
6483
|
+
return /* @__PURE__ */ React27.createElement(GroupHeader, { key: `group:${item.group}:${item.beforeIndex}`, group: item.group });
|
|
6484
|
+
}
|
|
6485
|
+
return /* @__PURE__ */ React27.createElement(
|
|
6486
|
+
SuggestionRow,
|
|
6487
|
+
{
|
|
6488
|
+
key: `cmd:${item.spec.group}:${item.spec.cmd}`,
|
|
6489
|
+
spec: item.spec,
|
|
6490
|
+
isSelected: item.index === selectedIndex,
|
|
6491
|
+
columns: cols
|
|
6492
|
+
}
|
|
6493
|
+
);
|
|
6443
6494
|
}), hiddenBelow > 0 ? /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, groupMode && advancedHidden && advancedHidden > 0 ? /* @__PURE__ */ React27.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, ` + ${advancedHidden} advanced \xB7 type a letter to search`)) : null, /* @__PURE__ */ React27.createElement(Box23, { marginTop: 0 }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true }, " \u2191\u2193 navigate \xB7 Tab / \u23CE pick \xB7 esc cancel")));
|
|
6444
6495
|
}
|
|
6445
|
-
function
|
|
6496
|
+
function computeWindowStart(matches, maxRows, selectedIndex, currentWindowStart, groupMode = false) {
|
|
6497
|
+
if (matches.length <= 0) return 0;
|
|
6498
|
+
const maxWindowStart = Math.max(0, matches.length - 1);
|
|
6499
|
+
let start = Math.max(0, Math.min(currentWindowStart, maxWindowStart));
|
|
6500
|
+
const clampedSelectedIndex = Math.max(0, Math.min(selectedIndex, matches.length - 1));
|
|
6501
|
+
if (clampedSelectedIndex < start) start = clampedSelectedIndex;
|
|
6502
|
+
while (start < clampedSelectedIndex) {
|
|
6503
|
+
const visibleCommandIndexes = buildVisibleItems(matches, start, maxRows, groupMode).filter((item) => item.kind === "command").map((item) => item.index);
|
|
6504
|
+
if (visibleCommandIndexes.includes(clampedSelectedIndex)) break;
|
|
6505
|
+
start += 1;
|
|
6506
|
+
}
|
|
6507
|
+
return Math.min(start, maxWindowStart);
|
|
6508
|
+
}
|
|
6509
|
+
function buildVisibleItems(matches, windowStart, maxRows, groupMode = false) {
|
|
6510
|
+
const out = [];
|
|
6511
|
+
for (let idx = windowStart; idx < matches.length && out.length < maxRows; idx += 1) {
|
|
6512
|
+
const spec = matches[idx];
|
|
6513
|
+
if (groupMode && shouldShowGroupHeader(matches, idx)) {
|
|
6514
|
+
if (out.length >= maxRows) break;
|
|
6515
|
+
out.push({ kind: "group", group: spec.group, beforeIndex: idx });
|
|
6516
|
+
}
|
|
6517
|
+
if (out.length >= maxRows) break;
|
|
6518
|
+
out.push({ kind: "command", spec, index: idx });
|
|
6519
|
+
}
|
|
6520
|
+
return out;
|
|
6521
|
+
}
|
|
6522
|
+
function shouldShowGroupHeader(matches, idx) {
|
|
6523
|
+
return idx === 0 || matches[idx]?.group !== matches[idx - 1]?.group;
|
|
6524
|
+
}
|
|
6525
|
+
function GroupHeader({ group }) {
|
|
6526
|
+
return /* @__PURE__ */ React27.createElement(Box23, { flexShrink: 0, height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React27.createElement(Text23, { dimColor: true, wrap: "truncate" }, ` ${GROUP_LABEL[group]}`));
|
|
6527
|
+
}
|
|
6528
|
+
function SuggestionRow({
|
|
6529
|
+
spec,
|
|
6530
|
+
isSelected,
|
|
6531
|
+
columns
|
|
6532
|
+
}) {
|
|
6446
6533
|
const color = useColor();
|
|
6447
6534
|
const name = `/${spec.cmd}`;
|
|
6448
6535
|
const argsSuffix = spec.argsHint ? spec.argsHint : "";
|
|
@@ -6450,7 +6537,19 @@ function SuggestionRow({ spec, isSelected }) {
|
|
|
6450
6537
|
const translated = t(key);
|
|
6451
6538
|
const summary = translated === key ? spec.summary : translated;
|
|
6452
6539
|
const aliasHint = spec.aliases?.length ? ` \xB7 /${spec.aliases.join(" /")}` : "";
|
|
6453
|
-
|
|
6540
|
+
const reservedCells = 2 + COMMAND_NAME_CELLS + ARGS_CELLS + 2 + 2;
|
|
6541
|
+
const summaryBudget = Math.max(8, columns - reservedCells);
|
|
6542
|
+
const summaryText = truncateCells(`${summary}${aliasHint}`, summaryBudget);
|
|
6543
|
+
return /* @__PURE__ */ React27.createElement(Box23, { flexDirection: "row", flexWrap: "nowrap", flexShrink: 0, height: 1, minHeight: 1 }, /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.primary : color.info, bold: isSelected, wrap: "truncate" }, isSelected ? `${GLYPH.cur} ` : " "), /* @__PURE__ */ React27.createElement(Text23, { color: color.accent, bold: isSelected, wrap: "truncate" }, padOrTrim(name, COMMAND_NAME_CELLS)), /* @__PURE__ */ React27.createElement(Text23, { dimColor: true, wrap: "truncate" }, padOrTrim(argsSuffix, ARGS_CELLS)), /* @__PURE__ */ React27.createElement(Text23, { wrap: "truncate" }, " "), /* @__PURE__ */ React27.createElement(Text23, { color: isSelected ? color.user : color.info, dimColor: !isSelected, wrap: "truncate" }, summaryText));
|
|
6544
|
+
}
|
|
6545
|
+
function padOrTrim(value, cells) {
|
|
6546
|
+
const trimmed = truncateCells(value, cells);
|
|
6547
|
+
return trimmed.padEnd(cells);
|
|
6548
|
+
}
|
|
6549
|
+
function truncateCells(value, maxCells) {
|
|
6550
|
+
if (value.length <= maxCells) return value;
|
|
6551
|
+
if (maxCells <= 1) return value.slice(0, Math.max(0, maxCells));
|
|
6552
|
+
return `${value.slice(0, maxCells - 1)}\u2026`;
|
|
6454
6553
|
}
|
|
6455
6554
|
|
|
6456
6555
|
// src/cli/ui/WelcomeBanner.tsx
|
|
@@ -7819,10 +7918,16 @@ function CtxCard({ card }) {
|
|
|
7819
7918
|
{
|
|
7820
7919
|
glyph: "\u2318",
|
|
7821
7920
|
tone: TONE.brand,
|
|
7822
|
-
title: "context",
|
|
7921
|
+
title: t("cardTitles.context"),
|
|
7823
7922
|
meta: [`${used.toLocaleString()} / ${cap.toLocaleString()} (${usedPct.toFixed(1)}%)`]
|
|
7824
7923
|
}
|
|
7825
|
-
), row("system", card.systemTokens, card.systemTokens / cap, TONE.brand), row("tools", card.toolsTokens, card.toolsTokens / cap, TONE.warn), row("log", card.logTokens, card.logTokens / cap, TONE.ok), row("input", card.inputTokens, card.inputTokens / cap, TONE.accent), card.topTools.length > 0 ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Text26, { color: FG.faint },
|
|
7924
|
+
), row(t("cardLabels.system"), card.systemTokens, card.systemTokens / cap, TONE.brand), row(t("cardLabels.tools"), card.toolsTokens, card.toolsTokens / cap, TONE.warn), row(t("cardLabels.log"), card.logTokens, card.logTokens / cap, TONE.ok), row(t("cardLabels.input"), card.inputTokens, card.inputTokens / cap, TONE.accent), card.topTools.length > 0 ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Text26, { color: FG.faint }, `${t("cardLabels.topTools")} \xB7 ${card.toolsCount} ${t("cardLabels.tools")} \xB7 ${card.logMessages} ${t("cardLabels.logMsgs")}`), card.topTools.slice(0, 5).map((tool) => /* @__PURE__ */ React32.createElement(Box27, { key: `${tool.turn}-${tool.name}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React32.createElement(Text26, { color: FG.sub }, tool.name), /* @__PURE__ */ React32.createElement(
|
|
7925
|
+
Text26,
|
|
7926
|
+
{
|
|
7927
|
+
color: FG.faint
|
|
7928
|
+
},
|
|
7929
|
+
`\xB7 ${t("cardLabels.turn")} ${tool.turn} \xB7 ${tool.tokens.toLocaleString()}`
|
|
7930
|
+
)))) : null);
|
|
7826
7931
|
}
|
|
7827
7932
|
|
|
7828
7933
|
// src/cli/ui/cards/DiffCard.tsx
|
|
@@ -7890,7 +7995,7 @@ import { Box as Box30, Text as Text29 } from "ink";
|
|
|
7890
7995
|
import React35 from "react";
|
|
7891
7996
|
var STACK_TAIL = 5;
|
|
7892
7997
|
function ErrorCard({ card }) {
|
|
7893
|
-
const retryNote = card.retries !== void 0 && card.retries > 0 ? `${card.retries}
|
|
7998
|
+
const retryNote = card.retries !== void 0 && card.retries > 0 ? `${card.retries} ${t("cardLabels.retries")}` : null;
|
|
7894
7999
|
const stackLines = card.stack ? card.stack.split("\n") : [];
|
|
7895
8000
|
const stackTrunc = stackLines.length > STACK_TAIL;
|
|
7896
8001
|
const stackVisible = stackTrunc ? stackLines.slice(-STACK_TAIL) : stackLines;
|
|
@@ -7902,10 +8007,13 @@ function ErrorCard({ card }) {
|
|
|
7902
8007
|
{
|
|
7903
8008
|
glyph: "\u2716",
|
|
7904
8009
|
tone: TONE.err,
|
|
7905
|
-
title: card.title || "error",
|
|
8010
|
+
title: card.title || t("cardTitles.error"),
|
|
7906
8011
|
meta: retryNote ? [retryNote] : void 0
|
|
7907
8012
|
}
|
|
7908
|
-
), messageLines.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.meta }, "
|
|
8013
|
+
), messageLines.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:msg:${i}`, color: TONE.err }, line || " ")), hasStack ? /* @__PURE__ */ React35.createElement(Box30, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: FG.meta }, t("cardLabels.stackTrace")), stackHidden > 0 ? /* @__PURE__ */ React35.createElement(Text29, { color: FG.faint }, t(
|
|
8014
|
+
stackHidden === 1 ? "cardLabels.earlierStackLine" : "cardLabels.earlierStackLines",
|
|
8015
|
+
{ count: stackHidden }
|
|
8016
|
+
)) : null, stackVisible.map((line, i) => /* @__PURE__ */ React35.createElement(Text29, { key: `${card.id}:stk:${stackHidden + i}`, color: FG.meta }, line || " "))) : null);
|
|
7909
8017
|
}
|
|
7910
8018
|
|
|
7911
8019
|
// src/cli/ui/cards/LiveCard.tsx
|
|
@@ -8071,7 +8179,7 @@ function anchorIndex(steps) {
|
|
|
8071
8179
|
}
|
|
8072
8180
|
|
|
8073
8181
|
// src/cli/ui/cards/ReasoningCard.tsx
|
|
8074
|
-
import { Box as Box34, Text as Text35, useStdout as
|
|
8182
|
+
import { Box as Box34, Text as Text35, useStdout as useStdout9 } from "ink";
|
|
8075
8183
|
import React41 from "react";
|
|
8076
8184
|
|
|
8077
8185
|
// src/frame/width.ts
|
|
@@ -8138,7 +8246,7 @@ function ReasoningCard({
|
|
|
8138
8246
|
card,
|
|
8139
8247
|
expanded
|
|
8140
8248
|
}) {
|
|
8141
|
-
const { stdout } =
|
|
8249
|
+
const { stdout } = useStdout9();
|
|
8142
8250
|
const cols = stdout?.columns ?? 80;
|
|
8143
8251
|
const lineCells = Math.max(20, cols - 4);
|
|
8144
8252
|
const allLines = card.text.length > 0 ? card.text.split("\n") : [];
|
|
@@ -8150,7 +8258,7 @@ function ReasoningHeader({ card }) {
|
|
|
8150
8258
|
const streamingActive = card.streaming && !card.aborted;
|
|
8151
8259
|
const headColor = card.aborted ? TONE.err : streamingActive ? TONE_ACTIVE.accent : TONE.accent;
|
|
8152
8260
|
const glyph = streamingActive ? "\u25C7" : "\u25C6";
|
|
8153
|
-
const title = streamingActive ? "
|
|
8261
|
+
const title = streamingActive ? t("cardTitles.reasoningEllipsis") : card.aborted ? t("cardTitles.reasoningAborted") : t("cardTitles.reasoning");
|
|
8154
8262
|
const meta = [];
|
|
8155
8263
|
const m = headerMeta(card);
|
|
8156
8264
|
if (m) meta.push(m);
|
|
@@ -8172,11 +8280,11 @@ function ReasoningHeader({ card }) {
|
|
|
8172
8280
|
}
|
|
8173
8281
|
function headerMeta(card) {
|
|
8174
8282
|
if (card.streaming) {
|
|
8175
|
-
return card.tokens > 0 ? `${card.tokens.toLocaleString()} tok` : "";
|
|
8283
|
+
return card.tokens > 0 ? `${card.tokens.toLocaleString()} ${t("cardLabels.tok")}` : "";
|
|
8176
8284
|
}
|
|
8177
8285
|
const parts = [];
|
|
8178
|
-
if (card.tokens > 0) parts.push(`${card.tokens.toLocaleString()} tok`);
|
|
8179
|
-
if (card.paragraphs > 0) parts.push(`${card.paragraphs}
|
|
8286
|
+
if (card.tokens > 0) parts.push(`${card.tokens.toLocaleString()} ${t("cardLabels.tok")}`);
|
|
8287
|
+
if (card.paragraphs > 0) parts.push(`${card.paragraphs} ${t("cardLabels.pilcrow")}`);
|
|
8180
8288
|
return parts.join(" \xB7 ");
|
|
8181
8289
|
}
|
|
8182
8290
|
function headerDuration(card) {
|
|
@@ -8227,18 +8335,24 @@ import React42 from "react";
|
|
|
8227
8335
|
function SearchCard({ card }) {
|
|
8228
8336
|
const fileCount = new Set(card.hits.map((h) => h.file)).size;
|
|
8229
8337
|
const elapsed = `${(card.elapsedMs / 1e3).toFixed(2)}s`;
|
|
8230
|
-
const stats2 =
|
|
8338
|
+
const stats2 = t(card.hits.length === 1 ? "cardLabels.hitSingular" : "cardLabels.hitsPlural", {
|
|
8339
|
+
count: card.hits.length,
|
|
8340
|
+
files: fileCount
|
|
8341
|
+
});
|
|
8231
8342
|
const grouped = groupByFile(card.hits.slice(0, 10));
|
|
8232
8343
|
return /* @__PURE__ */ React42.createElement(Card, { tone: TONE.info }, /* @__PURE__ */ React42.createElement(
|
|
8233
8344
|
CardHeader,
|
|
8234
8345
|
{
|
|
8235
8346
|
glyph: "\u2299",
|
|
8236
8347
|
tone: TONE.info,
|
|
8237
|
-
title: "search",
|
|
8348
|
+
title: t("cardTitles.search"),
|
|
8238
8349
|
subtitle: `"${card.query}"`,
|
|
8239
8350
|
meta: [stats2, elapsed]
|
|
8240
8351
|
}
|
|
8241
|
-
), grouped.map(([file, hits]) => /* @__PURE__ */ React42.createElement(Box35, { key: file, flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React42.createElement(Box35, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React42.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint },
|
|
8352
|
+
), grouped.map(([file, hits]) => /* @__PURE__ */ React42.createElement(Box35, { key: file, flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: FG.strong }, file), hits.map((h, i) => /* @__PURE__ */ React42.createElement(Box35, { key: `${file}:${h.line}:${i}`, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, `${h.line.toString().padStart(4)} \u2502`), /* @__PURE__ */ React42.createElement(HighlightedLine, { text: h.preview, start: h.matchStart, end: h.matchEnd }))))), card.hits.length > 10 ? /* @__PURE__ */ React42.createElement(Text36, { color: FG.faint }, t(
|
|
8353
|
+
card.hits.length - 10 === 1 ? "cardLabels.moreHitSingular" : "cardLabels.moreHitsPlural",
|
|
8354
|
+
{ count: card.hits.length - 10 }
|
|
8355
|
+
)) : null);
|
|
8242
8356
|
}
|
|
8243
8357
|
function HighlightedLine({
|
|
8244
8358
|
text,
|
|
@@ -8261,7 +8375,7 @@ function groupByFile(hits) {
|
|
|
8261
8375
|
}
|
|
8262
8376
|
|
|
8263
8377
|
// src/cli/ui/cards/StreamingCard.tsx
|
|
8264
|
-
import { Box as Box37, Text as Text38, useStdout as
|
|
8378
|
+
import { Box as Box37, Text as Text38, useStdout as useStdout11 } from "ink";
|
|
8265
8379
|
import React44, { useContext as useContext5 } from "react";
|
|
8266
8380
|
|
|
8267
8381
|
// src/cli/ui/layout/LiveExpandContext.ts
|
|
@@ -8270,7 +8384,7 @@ var LiveExpandContext = createContext3(false);
|
|
|
8270
8384
|
|
|
8271
8385
|
// src/cli/ui/markdown.tsx
|
|
8272
8386
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
8273
|
-
import { Box as Box36, Text as Text37, useStdout as
|
|
8387
|
+
import { Box as Box36, Text as Text37, useStdout as useStdout10 } from "ink";
|
|
8274
8388
|
import React43 from "react";
|
|
8275
8389
|
import stringWidth from "string-width";
|
|
8276
8390
|
var BODY_LEFT_CELLS = 7;
|
|
@@ -8278,7 +8392,7 @@ var MarkdownWidthCtx = React43.createContext(void 0);
|
|
|
8278
8392
|
function useWidth() {
|
|
8279
8393
|
const ctx = React43.useContext(MarkdownWidthCtx);
|
|
8280
8394
|
if (ctx !== void 0) return ctx;
|
|
8281
|
-
return (
|
|
8395
|
+
return (useStdout10()?.stdout?.columns ?? process.stdout.columns ?? 80) - BODY_LEFT_CELLS;
|
|
8282
8396
|
}
|
|
8283
8397
|
marked.setOptions({ gfm: true, breaks: false });
|
|
8284
8398
|
function Markdown({ text, width }) {
|
|
@@ -8599,7 +8713,7 @@ function tokenRate(text, startTs, endTs) {
|
|
|
8599
8713
|
}
|
|
8600
8714
|
var PILL_RATE = { bg: "#11141a", fg: "#8b949e" };
|
|
8601
8715
|
function StreamingCard({ card }) {
|
|
8602
|
-
const { stdout } =
|
|
8716
|
+
const { stdout } = useStdout11();
|
|
8603
8717
|
const cols = stdout?.columns ?? 80;
|
|
8604
8718
|
const expanded = useContext5(LiveExpandContext);
|
|
8605
8719
|
const reserveCap = expanded ? EXPANDED_MAX_LINES + 2 : STREAMING_PREVIEW_LINES2 + 2;
|
|
@@ -8618,7 +8732,7 @@ function StreamingCard({ card }) {
|
|
|
8618
8732
|
{
|
|
8619
8733
|
glyph: "\u2039",
|
|
8620
8734
|
tone: TONE.ok,
|
|
8621
|
-
title: "reply",
|
|
8735
|
+
title: t("cardTitles.reply"),
|
|
8622
8736
|
right: /* @__PURE__ */ React44.createElement(React44.Fragment, null, ratePill, modelPill)
|
|
8623
8737
|
}
|
|
8624
8738
|
), /* @__PURE__ */ React44.createElement(Markdown, { text: card.text }));
|
|
@@ -8632,7 +8746,7 @@ function StreamingCard({ card }) {
|
|
|
8632
8746
|
const aborted = !!card.aborted;
|
|
8633
8747
|
const headColor = aborted ? TONE.err : TONE_ACTIVE.brand;
|
|
8634
8748
|
const glyph = aborted ? "\u2039" : "\u25C8";
|
|
8635
|
-
const headLabel = aborted ? "aborted" : "writing
|
|
8749
|
+
const headLabel = aborted ? t("cardLabels.aborted") : t("cardLabels.writing");
|
|
8636
8750
|
const { tokens: liveTokens, tps: liveTps } = tokenRate(card.text, card.ts, Date.now());
|
|
8637
8751
|
const liveRatePill = !aborted && liveTokens >= MIN_TOKENS_FOR_RATE && liveTps !== null ? /* @__PURE__ */ React44.createElement(Pill, { label: `${liveTps} t/s`, ...PILL_RATE, bold: false }) : null;
|
|
8638
8752
|
const expandPill = !aborted ? /* @__PURE__ */ React44.createElement(Pill, { label: expanded ? "expanded \u2303o" : "preview \u2303o", ...PILL_RATE, bold: false }) : null;
|
|
@@ -8644,13 +8758,9 @@ function StreamingCard({ card }) {
|
|
|
8644
8758
|
title: headLabel,
|
|
8645
8759
|
right: /* @__PURE__ */ React44.createElement(React44.Fragment, null, liveRatePill, expandPill, aborted ? null : /* @__PURE__ */ React44.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand }), modelPill)
|
|
8646
8760
|
}
|
|
8647
|
-
), expanded && droppedAbove > 0 ? /* @__PURE__ */ React44.createElement(
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
color: FG.faint
|
|
8651
|
-
},
|
|
8652
|
-
`\u22EF ${droppedAbove} earlier line${droppedAbove === 1 ? "" : "s"} above`
|
|
8653
|
-
) : null, visible.map((line, i) => /* @__PURE__ */ React44.createElement(Box37, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text38, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, "[truncated by esc]") : null);
|
|
8761
|
+
), expanded && droppedAbove > 0 ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, t(droppedAbove === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
|
|
8762
|
+
count: droppedAbove
|
|
8763
|
+
})) : null, visible.map((line, i) => /* @__PURE__ */ React44.createElement(Box37, { key: `${card.id}:${visualLines.length - visible.length + i}`, flexDirection: "row" }, /* @__PURE__ */ React44.createElement(Text38, { color: aborted ? FG.meta : FG.body }, clipToCells(line, lineCells)))), aborted ? /* @__PURE__ */ React44.createElement(Text38, { color: FG.faint }, t("cardLabels.truncatedByEsc")) : null);
|
|
8654
8764
|
}
|
|
8655
8765
|
|
|
8656
8766
|
// src/cli/ui/cards/SubAgentCard.tsx
|
|
@@ -8664,22 +8774,22 @@ function SubAgentCard({ card }) {
|
|
|
8664
8774
|
failed: tone.err
|
|
8665
8775
|
};
|
|
8666
8776
|
const headColor = statusColor[card.status];
|
|
8667
|
-
const headGlyph = card.status === "failed" ? "\
|
|
8777
|
+
const headGlyph = card.status === "failed" ? "\u2717" : "\u232C";
|
|
8668
8778
|
const runningChildren = card.children.filter((c) => !isChildDone(c)).length;
|
|
8669
8779
|
const isRunning = card.status === "running";
|
|
8670
8780
|
const inLive = useContext6(ActiveCardContext);
|
|
8671
|
-
const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren}
|
|
8781
|
+
const headerMeta2 = isRunning ? runningChildren > 0 ? [`${runningChildren} ${t("cardLabels.runningLabel")}`] : [t("cardLabels.workingLabel")] : [{ text: card.status, color: headColor }];
|
|
8672
8782
|
return /* @__PURE__ */ React45.createElement(Card, { tone: headColor }, /* @__PURE__ */ React45.createElement(
|
|
8673
8783
|
CardHeader,
|
|
8674
8784
|
{
|
|
8675
8785
|
glyph: headGlyph,
|
|
8676
8786
|
tone: headColor,
|
|
8677
|
-
title: "subagent",
|
|
8787
|
+
title: t("cardTitles.subagent"),
|
|
8678
8788
|
titleColor: tone.violet,
|
|
8679
8789
|
subtitle: card.task,
|
|
8680
8790
|
meta: headerMeta2
|
|
8681
8791
|
}
|
|
8682
|
-
), card.name ? /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint },
|
|
8792
|
+
), card.name ? /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `${t("cardLabels.agent")} \xB7 ${card.name}`) : null, card.tools && card.tools.length > 0 && /* @__PURE__ */ React45.createElement(Text39, { color: fg.faint }, `${t("cardLabels.tools")} \xB7 ${card.tools.join(", ")}`), card.children.map((child) => /* @__PURE__ */ React45.createElement(Box38, { key: child.id, flexDirection: "row", gap: 1 }, inLive ? null : /* @__PURE__ */ React45.createElement(Text39, { color: tone.violet }, "\u258E"), /* @__PURE__ */ React45.createElement(ChildRow, { card: child }))));
|
|
8683
8793
|
}
|
|
8684
8794
|
function isChildDone(card) {
|
|
8685
8795
|
switch (card.kind) {
|
|
@@ -8715,7 +8825,7 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
|
|
|
8715
8825
|
statusGlyph: done ? doneGlyph(doneColor) : runningGlyph(CARD.reasoning.color),
|
|
8716
8826
|
kindGlyph: "\u25C6",
|
|
8717
8827
|
kindColor: CARD.reasoning.color,
|
|
8718
|
-
text:
|
|
8828
|
+
text: t("cardLabels.reasoningLabel", { count: card.paragraphs })
|
|
8719
8829
|
};
|
|
8720
8830
|
}
|
|
8721
8831
|
case "tool": {
|
|
@@ -8732,7 +8842,7 @@ function childVisual(card, doneColor, failedColor, fallbackColor) {
|
|
|
8732
8842
|
statusGlyph: card.done ? doneGlyph(doneColor) : runningGlyph(CARD.streaming.color),
|
|
8733
8843
|
kindGlyph: "\u25C8",
|
|
8734
8844
|
kindColor: CARD.streaming.color,
|
|
8735
|
-
text: card.done ? "response" : "writing
|
|
8845
|
+
text: card.done ? t("cardLabels.response") : t("cardLabels.writing")
|
|
8736
8846
|
};
|
|
8737
8847
|
case "diff":
|
|
8738
8848
|
return {
|
|
@@ -8829,7 +8939,7 @@ function TipRowRender({
|
|
|
8829
8939
|
}
|
|
8830
8940
|
|
|
8831
8941
|
// src/cli/ui/cards/ToolCard.tsx
|
|
8832
|
-
import { Text as Text42, useStdout as
|
|
8942
|
+
import { Text as Text42, useStdout as useStdout12 } from "ink";
|
|
8833
8943
|
import React48 from "react";
|
|
8834
8944
|
var READ_TAIL = 2;
|
|
8835
8945
|
var OTHER_TAIL = 5;
|
|
@@ -8838,10 +8948,11 @@ function tailLinesFor(name) {
|
|
|
8838
8948
|
return /(?:^|_)(read|search|list|tree|get|status|diff|fetch|grep)(_|$)/.test(lower) || lower === "job_output" ? READ_TAIL : OTHER_TAIL;
|
|
8839
8949
|
}
|
|
8840
8950
|
function ToolCard({ card }) {
|
|
8841
|
-
const { stdout } =
|
|
8951
|
+
const { stdout } = useStdout12();
|
|
8842
8952
|
const cols = stdout?.columns ?? 80;
|
|
8843
8953
|
const lineCells = Math.max(20, cols - 4);
|
|
8844
8954
|
const argsLabel = formatArgsSummary(card.args);
|
|
8955
|
+
const subagentMarkdown = unwrapSubagentMarkdown(card);
|
|
8845
8956
|
const allLines = card.output.length > 0 ? card.output.split("\n") : [];
|
|
8846
8957
|
const tail = tailLinesFor(card.name);
|
|
8847
8958
|
const truncated = allLines.length > tail;
|
|
@@ -8850,13 +8961,13 @@ function ToolCard({ card }) {
|
|
|
8850
8961
|
const status2 = toolStatus(card);
|
|
8851
8962
|
const headColor = headerColorFor(status2);
|
|
8852
8963
|
const errColor = card.exitCode && card.exitCode !== 0 ? TONE.err : FG.sub;
|
|
8853
|
-
const showBody = !card.rejected && visible.length > 0;
|
|
8964
|
+
const showBody = !card.rejected && (subagentMarkdown !== null || visible.length > 0);
|
|
8854
8965
|
const meta = [];
|
|
8855
8966
|
if (card.retry) {
|
|
8856
8967
|
meta.push({ text: `\u21BB ${card.retry.attempt}/${card.retry.max}`, color: TONE.warn });
|
|
8857
8968
|
}
|
|
8858
8969
|
if (card.rejected) {
|
|
8859
|
-
meta.push({ text: "rejected", color: TONE.err });
|
|
8970
|
+
meta.push({ text: t("cardLabels.rejected"), color: TONE.err });
|
|
8860
8971
|
}
|
|
8861
8972
|
for (const part of metaTrail(card)) meta.push(part);
|
|
8862
8973
|
return /* @__PURE__ */ React48.createElement(Card, { tone: headColor }, /* @__PURE__ */ React48.createElement(
|
|
@@ -8869,7 +8980,9 @@ function ToolCard({ card }) {
|
|
|
8869
8980
|
meta: meta.length > 0 ? meta : void 0,
|
|
8870
8981
|
right: status2 === "running" ? /* @__PURE__ */ React48.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
|
|
8871
8982
|
}
|
|
8872
|
-
), showBody && /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint },
|
|
8983
|
+
), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React48.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, t(hidden === 1 ? "cardLabels.earlierLine" : "cardLabels.earlierLines", {
|
|
8984
|
+
count: hidden
|
|
8985
|
+
})) : null, visible.map((line, i) => /* @__PURE__ */ React48.createElement(
|
|
8873
8986
|
Text42,
|
|
8874
8987
|
{
|
|
8875
8988
|
key: `${card.id}:${hidden + i}`,
|
|
@@ -8877,7 +8990,21 @@ function ToolCard({ card }) {
|
|
|
8877
8990
|
dimColor: !card.exitCode || card.exitCode === 0
|
|
8878
8991
|
},
|
|
8879
8992
|
clipToCells(line, lineCells) || " "
|
|
8880
|
-
))));
|
|
8993
|
+
)))));
|
|
8994
|
+
}
|
|
8995
|
+
function unwrapSubagentMarkdown(card) {
|
|
8996
|
+
if (card.name !== "spawn_subagent") return null;
|
|
8997
|
+
if (card.output.length === 0) return null;
|
|
8998
|
+
try {
|
|
8999
|
+
const parsed = JSON.parse(card.output);
|
|
9000
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
9001
|
+
const obj = parsed;
|
|
9002
|
+
if (obj.success !== true) return null;
|
|
9003
|
+
if (typeof obj.output !== "string") return null;
|
|
9004
|
+
return obj.output;
|
|
9005
|
+
} catch {
|
|
9006
|
+
return null;
|
|
9007
|
+
}
|
|
8881
9008
|
}
|
|
8882
9009
|
function toolStatus(card) {
|
|
8883
9010
|
if (card.rejected) return "rejected";
|
|
@@ -8915,10 +9042,11 @@ function headerColorFor(s) {
|
|
|
8915
9042
|
function metaTrail(card) {
|
|
8916
9043
|
const parts = [];
|
|
8917
9044
|
const inputBytes = largestStringInputBytes(card.args);
|
|
8918
|
-
if (inputBytes !== null) parts.push(
|
|
8919
|
-
if (card.elapsedMs > 0)
|
|
9045
|
+
if (inputBytes !== null) parts.push(t("cardLabels.bytesIn", { bytes: formatBytes(inputBytes) }));
|
|
9046
|
+
if (card.elapsedMs > 0)
|
|
9047
|
+
parts.push(t("cardLabels.elapsedSec", { secs: (card.elapsedMs / 1e3).toFixed(2) }));
|
|
8920
9048
|
if (card.done && !card.rejected && !card.aborted && card.exitCode !== void 0 && card.exitCode !== 0) {
|
|
8921
|
-
parts.push(
|
|
9049
|
+
parts.push(t("cardLabels.exit", { code: card.exitCode }));
|
|
8922
9050
|
}
|
|
8923
9051
|
return parts;
|
|
8924
9052
|
}
|
|
@@ -8975,13 +9103,16 @@ function UsageCard({ card }) {
|
|
|
8975
9103
|
const promptRatio = card.tokens.prompt / cap;
|
|
8976
9104
|
const reasonRatio = card.tokens.reason / cap;
|
|
8977
9105
|
const outputRatio = card.tokens.output / cap;
|
|
8978
|
-
const headerMeta2 = [
|
|
9106
|
+
const headerMeta2 = [
|
|
9107
|
+
`${t("cardLabels.turn")} ${card.turn}`,
|
|
9108
|
+
formatCost(card.cost, card.balanceCurrency)
|
|
9109
|
+
];
|
|
8979
9110
|
if (card.elapsedMs !== void 0) headerMeta2.push(`${(card.elapsedMs / 1e3).toFixed(1)}s`);
|
|
8980
|
-
return /* @__PURE__ */ React49.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React49.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: "usage", meta: headerMeta2 }), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "prompt"), bar(promptRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "reason"), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "output"), bar(outputRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, "cache "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, "session"), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint },
|
|
9111
|
+
return /* @__PURE__ */ React49.createElement(Card, { tone: FG.meta }, /* @__PURE__ */ React49.createElement(CardHeader, { glyph: "\u03A3", tone: FG.meta, title: t("cardTitles.usage"), meta: headerMeta2 }), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.prompt")), bar(promptRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.prompt.toLocaleString()), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `/ 1M \xB7 ${(promptRatio * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.reason")), bar(reasonRatio, TONE.accent), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.reason.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.output")), bar(outputRatio, TONE.brand), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, card.tokens.output.toLocaleString())), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.sub }, t("cardLabels.cache"), " "), bar(card.cacheHit, TONE.ok), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.ok }, `${(card.cacheHit * 100).toFixed(1)}%`)), /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, t("cardLabels.session")), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: FG.body }, `\u26C1 ${formatCost(card.sessionCost, card.balanceCurrency, 3)}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(React49.Fragment, null, /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${t("cardLabels.balance")}`), /* @__PURE__ */ React49.createElement(Text43, { bold: true, color: TONE.brand }, formatBalance(card.balance, card.balanceCurrency))) : null));
|
|
8981
9112
|
}
|
|
8982
9113
|
function CompactUsageRow({ card }) {
|
|
8983
9114
|
const elapsed = card.elapsedMs !== void 0 ? ` \xB7 ${(card.elapsedMs / 1e3).toFixed(1)}s` : "";
|
|
8984
|
-
return /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint },
|
|
9115
|
+
return /* @__PURE__ */ React49.createElement(Box42, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, "\u03A3"), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `${t("cardLabels.turn")} ${card.turn}`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.meta }, `\xB7 ${compactNum(card.tokens.prompt)} ${t("cardLabels.prompt")} \xB7 ${compactNum(card.tokens.output)} ${t("cardLabels.output")}`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${t("cardLabels.cache")}`), /* @__PURE__ */ React49.createElement(Text43, { color: TONE.ok }, `${(card.cacheHit * 100).toFixed(0)}%`), /* @__PURE__ */ React49.createElement(Text43, { color: FG.faint }, `\xB7 ${formatCost(card.cost, card.balanceCurrency)}${elapsed}`), card.balance !== void 0 ? /* @__PURE__ */ React49.createElement(Text43, { color: TONE.brand }, `\xB7 ${formatBalance(card.balance, card.balanceCurrency)}`) : null);
|
|
8985
9116
|
}
|
|
8986
9117
|
|
|
8987
9118
|
// src/cli/ui/cards/UserCard.tsx
|
|
@@ -9304,7 +9435,7 @@ function summarizeToolArgs(name, args) {
|
|
|
9304
9435
|
}
|
|
9305
9436
|
|
|
9306
9437
|
// src/cli/ui/layout/StatusRow.tsx
|
|
9307
|
-
import { Box as Box46, Text as Text49, useStdout as
|
|
9438
|
+
import { Box as Box46, Text as Text49, useStdout as useStdout13 } from "ink";
|
|
9308
9439
|
import React56 from "react";
|
|
9309
9440
|
|
|
9310
9441
|
// src/cli/ui/primitives/Countdown.tsx
|
|
@@ -9320,24 +9451,33 @@ function Countdown({ endsAt, color = TONE.brand }) {
|
|
|
9320
9451
|
var RULE_PAD = 4;
|
|
9321
9452
|
var RULE_MIN = 20;
|
|
9322
9453
|
var WALLET_MIN_COLS = 90;
|
|
9454
|
+
var VERSION_MIN_COLS = 70;
|
|
9455
|
+
var FEEDBACK_HINT_MIN_COLS = 100;
|
|
9323
9456
|
function StatusRow() {
|
|
9324
9457
|
const status2 = useAgentState((s) => s.status);
|
|
9325
9458
|
const session = useAgentState((s) => s.session);
|
|
9326
|
-
const { stdout } =
|
|
9459
|
+
const { stdout } = useStdout13();
|
|
9327
9460
|
const cols = stdout?.columns ?? 80;
|
|
9328
9461
|
const ruleWidth = Math.max(RULE_MIN, cols - RULE_PAD);
|
|
9329
9462
|
const hasTurn = status2.cost > 0;
|
|
9330
9463
|
const hasSession = status2.sessionCost > 0;
|
|
9331
9464
|
const hasBalance = typeof status2.balance === "number";
|
|
9332
9465
|
const showWallet = cols >= WALLET_MIN_COLS && (hasSession || hasBalance);
|
|
9333
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column" }, /* @__PURE__ */ React56.createElement(Box46,
|
|
9466
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Box46, { height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, null, " "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, "\u2500".repeat(ruleWidth))), /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, minHeight: 1, flexWrap: "nowrap", flexShrink: 0 }, /* @__PURE__ */ React56.createElement(Text49, { wrap: "truncate" }, " "), status2.recording ? /* @__PURE__ */ React56.createElement(RecordingPill, { rec: status2.recording }) : status2.countdownSeconds !== void 0 ? /* @__PURE__ */ React56.createElement(CountdownRow, { mode: status2.mode, secondsLeft: status2.countdownSeconds }) : /* @__PURE__ */ React56.createElement(ModePill2, { mode: status2.mode, network: status2.network, detail: status2.networkDetail }), /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, `${session.id} \xB7 ${session.branch}`), hasTurn && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.brand, wrap: "truncate" }, "\u25B8 "), /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: FG.body, wrap: "truncate" }, `${formatCost(status2.cost, status2.balanceCurrency)} turn`)), /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(
|
|
9467
|
+
Text49,
|
|
9468
|
+
{
|
|
9469
|
+
color: TONE.accent,
|
|
9470
|
+
wrap: "truncate"
|
|
9471
|
+
},
|
|
9472
|
+
`cache ${Math.round(status2.cacheHit * 100)}%`
|
|
9473
|
+
), showWallet && /* @__PURE__ */ React56.createElement(
|
|
9334
9474
|
WalletPill,
|
|
9335
9475
|
{
|
|
9336
9476
|
sessionCostUsd: status2.sessionCost,
|
|
9337
9477
|
balance: status2.balance,
|
|
9338
9478
|
currency: status2.balanceCurrency
|
|
9339
9479
|
}
|
|
9340
|
-
)));
|
|
9480
|
+
), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, " \xB7 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, "\u2691 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, "/feedback")))));
|
|
9341
9481
|
}
|
|
9342
9482
|
function WalletPill({
|
|
9343
9483
|
sessionCostUsd,
|
|
@@ -9346,7 +9486,14 @@ function WalletPill({
|
|
|
9346
9486
|
}) {
|
|
9347
9487
|
const showSpent = sessionCostUsd > 0;
|
|
9348
9488
|
const showBalance = typeof balance === "number";
|
|
9349
|
-
return /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta
|
|
9489
|
+
return /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, "\u26C1 "), showSpent && /* @__PURE__ */ React56.createElement(
|
|
9490
|
+
Text49,
|
|
9491
|
+
{
|
|
9492
|
+
color: FG.body,
|
|
9493
|
+
wrap: "truncate"
|
|
9494
|
+
},
|
|
9495
|
+
`${formatCost(sessionCostUsd, currency, 2)} spent`
|
|
9496
|
+
), showSpent && showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, " / "), showBalance && /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: balanceColor(balance, currency), wrap: "truncate" }, formatBalance(balance, currency, { fractionDigits: 2 })), showBalance && /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint, wrap: "truncate" }, " left"));
|
|
9350
9497
|
}
|
|
9351
9498
|
function ModePill2({
|
|
9352
9499
|
mode: mode2,
|
|
@@ -9355,18 +9502,18 @@ function ModePill2({
|
|
|
9355
9502
|
}) {
|
|
9356
9503
|
if (network === "online") {
|
|
9357
9504
|
const pill = modeGlyph(mode2);
|
|
9358
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` ${mode2}`));
|
|
9505
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, ` ${mode2}`));
|
|
9359
9506
|
}
|
|
9360
9507
|
const dot = networkDot(network);
|
|
9361
9508
|
if (network === "slow") {
|
|
9362
9509
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
9363
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, ` ${mode2} \xB7 slow${tail}`));
|
|
9510
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, ` ${mode2} \xB7 slow${tail}`));
|
|
9364
9511
|
}
|
|
9365
9512
|
if (network === "disconnected") {
|
|
9366
9513
|
const tail = detail ? ` \xB7 ${detail}` : "";
|
|
9367
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, ` disconnect${tail}`));
|
|
9514
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, ` disconnect${tail}`));
|
|
9368
9515
|
}
|
|
9369
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color }, " reconnecting\u2026"));
|
|
9516
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, dot.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: dot.color, wrap: "truncate" }, " reconnecting\u2026"));
|
|
9370
9517
|
}
|
|
9371
9518
|
function CountdownRow({
|
|
9372
9519
|
mode: mode2,
|
|
@@ -9374,14 +9521,14 @@ function CountdownRow({
|
|
|
9374
9521
|
}) {
|
|
9375
9522
|
const pill = modeGlyph(mode2);
|
|
9376
9523
|
const endsAt = Date.now() + secondsLeft * 1e3;
|
|
9377
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, ` ${mode2} \xB7 `), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn }, "approving in "), /* @__PURE__ */ React56.createElement(Countdown, { endsAt }), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn }, "s \xB7 esc to interrupt"));
|
|
9524
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { color: pill.color, wrap: "truncate" }, pill.glyph), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub, wrap: "truncate" }, ` ${mode2} \xB7 `), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn, wrap: "truncate" }, "approving in "), /* @__PURE__ */ React56.createElement(Countdown, { endsAt }), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.warn, wrap: "truncate" }, "s \xB7 esc to interrupt"));
|
|
9378
9525
|
}
|
|
9379
9526
|
function RecordingPill({ rec }) {
|
|
9380
9527
|
const sizeMb = (rec.sizeBytes / (1024 * 1024)).toFixed(1);
|
|
9381
|
-
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row" }, /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.err }, "\u25CFREC"), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.err }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
|
|
9528
|
+
return /* @__PURE__ */ React56.createElement(Box46, { flexDirection: "row", height: 1, flexWrap: "nowrap" }, /* @__PURE__ */ React56.createElement(Text49, { bold: true, color: TONE.err, wrap: "truncate" }, "\u25CFREC"), /* @__PURE__ */ React56.createElement(Text49, { color: TONE.err, wrap: "truncate" }, ` ${sizeMb} MB \xB7 ${rec.events} evt`));
|
|
9382
9529
|
}
|
|
9383
9530
|
function Sep() {
|
|
9384
|
-
return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, " \xB7 ");
|
|
9531
|
+
return /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta, wrap: "truncate" }, " \xB7 ");
|
|
9385
9532
|
}
|
|
9386
9533
|
function modeGlyph(mode2) {
|
|
9387
9534
|
switch (mode2) {
|
|
@@ -9409,7 +9556,7 @@ function networkDot(state) {
|
|
|
9409
9556
|
}
|
|
9410
9557
|
|
|
9411
9558
|
// src/cli/ui/layout/ToastRail.tsx
|
|
9412
|
-
import { Box as Box47, Text as Text50, useStdout as
|
|
9559
|
+
import { Box as Box47, Text as Text50, useStdout as useStdout14 } from "ink";
|
|
9413
9560
|
import React57, { useEffect as useEffect8 } from "react";
|
|
9414
9561
|
var TONE_COLOR = {
|
|
9415
9562
|
ok: TONE.ok,
|
|
@@ -9432,7 +9579,7 @@ function ToastRail() {
|
|
|
9432
9579
|
const toasts = useAgentState((s) => s.toasts);
|
|
9433
9580
|
const dispatch = useDispatch();
|
|
9434
9581
|
useSlowTick();
|
|
9435
|
-
const { stdout } =
|
|
9582
|
+
const { stdout } = useStdout14();
|
|
9436
9583
|
const cols = stdout?.columns ?? 80;
|
|
9437
9584
|
const rule = "\u2501".repeat(Math.max(20, cols - 4));
|
|
9438
9585
|
const now = Date.now();
|
|
@@ -9837,24 +9984,28 @@ var update = (_args, _loop, ctx) => {
|
|
|
9837
9984
|
return { info: lines.join("\n") };
|
|
9838
9985
|
}
|
|
9839
9986
|
lines.push(t("handlers.admin.updateLatest", { version: latest }));
|
|
9840
|
-
|
|
9841
|
-
if (diff >= 0) {
|
|
9987
|
+
if (compareVersions(VERSION, latest) >= 0) {
|
|
9842
9988
|
lines.push("", t("handlers.admin.updateUpToDate"));
|
|
9843
9989
|
return { info: lines.join("\n") };
|
|
9844
9990
|
}
|
|
9845
|
-
|
|
9991
|
+
const installSource = detectInstallSource();
|
|
9992
|
+
const npmPrefix = installSource === "npm" ? detectNpmInstallPrefix() : null;
|
|
9993
|
+
const plan2 = planUpdate({ current: VERSION, latest, installSource, npmPrefix });
|
|
9994
|
+
if (plan2.action === "npx-hint") {
|
|
9846
9995
|
lines.push("", t("handlers.admin.updateNpxHint"), t("handlers.admin.updateNpxForce"));
|
|
9996
|
+
return { info: lines.join("\n") };
|
|
9997
|
+
}
|
|
9998
|
+
lines.push("", t("handlers.admin.updateUpgradeHint"), t("handlers.admin.updateUpgradeCmd1"));
|
|
9999
|
+
if (plan2.action === "run-install" && plan2.command) {
|
|
10000
|
+
lines.push(t("handlers.admin.updateUpgradeCmd2", { command: plan2.command.join(" ") }));
|
|
9847
10001
|
} else {
|
|
9848
|
-
lines.push(
|
|
9849
|
-
"",
|
|
9850
|
-
t("handlers.admin.updateUpgradeHint"),
|
|
9851
|
-
t("handlers.admin.updateUpgradeCmd1"),
|
|
9852
|
-
t("handlers.admin.updateUpgradeCmd2"),
|
|
9853
|
-
"",
|
|
9854
|
-
t("handlers.admin.updateInSessionDisabled"),
|
|
9855
|
-
t("handlers.admin.updateInSessionDisabled2")
|
|
9856
|
-
);
|
|
10002
|
+
lines.push(...MANUAL_UPDATE_COMMANDS.map((c) => ` ${c}`));
|
|
9857
10003
|
}
|
|
10004
|
+
lines.push(
|
|
10005
|
+
"",
|
|
10006
|
+
t("handlers.admin.updateInSessionDisabled"),
|
|
10007
|
+
t("handlers.admin.updateInSessionDisabled2")
|
|
10008
|
+
);
|
|
9858
10009
|
return { info: lines.join("\n") };
|
|
9859
10010
|
};
|
|
9860
10011
|
var stats = () => {
|
|
@@ -10931,6 +11082,32 @@ var handlers10 = {
|
|
|
10931
11082
|
budget
|
|
10932
11083
|
};
|
|
10933
11084
|
|
|
11085
|
+
// src/cli/ui/slash/handlers/observability.ts
|
|
11086
|
+
import { release } from "os";
|
|
11087
|
+
|
|
11088
|
+
// src/cli/ui/clipboard.ts
|
|
11089
|
+
import { mkdtempSync, writeFileSync as writeFileSync4 } from "fs";
|
|
11090
|
+
import { tmpdir } from "os";
|
|
11091
|
+
import { join as join6 } from "path";
|
|
11092
|
+
var OSC_52_LIMIT = 75e3;
|
|
11093
|
+
function writeClipboard(text) {
|
|
11094
|
+
const dir = mkdtempSync(join6(tmpdir(), "reasonix-clip-"));
|
|
11095
|
+
const filePath = join6(dir, "clip.txt");
|
|
11096
|
+
let osc52 = false;
|
|
11097
|
+
if (text.length <= OSC_52_LIMIT) {
|
|
11098
|
+
const b64 = Buffer.from(text, "utf8").toString("base64");
|
|
11099
|
+
process.stdout.write(`\x1B]52;c;${b64}\x1B\\`);
|
|
11100
|
+
osc52 = true;
|
|
11101
|
+
}
|
|
11102
|
+
let writtenPath = null;
|
|
11103
|
+
try {
|
|
11104
|
+
writeFileSync4(filePath, text, "utf8");
|
|
11105
|
+
writtenPath = filePath;
|
|
11106
|
+
} catch {
|
|
11107
|
+
}
|
|
11108
|
+
return { osc52, filePath: writtenPath, size: text.length };
|
|
11109
|
+
}
|
|
11110
|
+
|
|
10934
11111
|
// src/cli/ui/ctx-breakdown.tsx
|
|
10935
11112
|
import { Box as Box48, Text as Text51 } from "ink";
|
|
10936
11113
|
import React59 from "react";
|
|
@@ -10975,6 +11152,92 @@ function computeCtxBreakdown(loop2) {
|
|
|
10975
11152
|
};
|
|
10976
11153
|
}
|
|
10977
11154
|
|
|
11155
|
+
// src/cli/ui/feedback.ts
|
|
11156
|
+
var FEEDBACK_ISSUE_BASE = "https://github.com/esengine/DeepSeek-Reasonix/issues/new";
|
|
11157
|
+
var FEEDBACK_BODY_QUERY_LIMIT = 6e3;
|
|
11158
|
+
function buildFeedbackIssueUrl(diagnostic) {
|
|
11159
|
+
const trimmed = diagnostic.length > FEEDBACK_BODY_QUERY_LIMIT ? diagnostic.slice(0, FEEDBACK_BODY_QUERY_LIMIT) : diagnostic;
|
|
11160
|
+
return `${FEEDBACK_ISSUE_BASE}?body=${encodeURIComponent(trimmed)}`;
|
|
11161
|
+
}
|
|
11162
|
+
function buildFeedbackDiagnostic(input) {
|
|
11163
|
+
const lines = [];
|
|
11164
|
+
lines.push(`**Reasonix**: ${formatVersion(input.version, input.latestVersion)}`);
|
|
11165
|
+
lines.push(`**Platform**: ${input.platform} (${input.osRelease})`);
|
|
11166
|
+
lines.push(`**Terminal**: ${formatTerminal(input)}`);
|
|
11167
|
+
if (typeof input.cols === "number" && typeof input.rows === "number") {
|
|
11168
|
+
lines.push(`**Size**: ${input.cols}\xD7${input.rows}`);
|
|
11169
|
+
}
|
|
11170
|
+
lines.push(`**Node**: ${input.nodeVersion}`);
|
|
11171
|
+
lines.push(`**Locale**: ${input.locale}`);
|
|
11172
|
+
if (input.theme) lines.push(`**Theme**: ${input.theme}`);
|
|
11173
|
+
lines.push(`**Model**: ${formatModel(input.model, input.reasoningEffort)}`);
|
|
11174
|
+
const modeLine = formatMode(input.editMode, input.planMode);
|
|
11175
|
+
if (modeLine) lines.push(`**Mode**: ${modeLine}`);
|
|
11176
|
+
if (typeof input.mcpServerCount === "number") {
|
|
11177
|
+
lines.push(`**MCP**: ${input.mcpServerCount} server(s)`);
|
|
11178
|
+
}
|
|
11179
|
+
if (input.sessionId) lines.push(`**Session**: ${input.sessionId}`);
|
|
11180
|
+
lines.push("", "<!-- describe what you were doing when this happened -->", "");
|
|
11181
|
+
return lines.join("\n");
|
|
11182
|
+
}
|
|
11183
|
+
function formatVersion(installed, latest) {
|
|
11184
|
+
if (!latest) return installed;
|
|
11185
|
+
const cmp = compareVersions(installed, latest);
|
|
11186
|
+
if (cmp === 0) return `${installed} (latest)`;
|
|
11187
|
+
if (cmp > 0) return installed;
|
|
11188
|
+
return `${installed} (latest: ${latest})`;
|
|
11189
|
+
}
|
|
11190
|
+
function formatModel(model2, effort) {
|
|
11191
|
+
return effort ? `${model2} \xB7 effort=${effort}` : model2;
|
|
11192
|
+
}
|
|
11193
|
+
function formatMode(editMode, planMode) {
|
|
11194
|
+
const parts = [];
|
|
11195
|
+
if (editMode) parts.push(`edit=${editMode}`);
|
|
11196
|
+
parts.push(`plan=${planMode ? "on" : "off"}`);
|
|
11197
|
+
return parts.join(" \xB7 ");
|
|
11198
|
+
}
|
|
11199
|
+
function formatTerminal(input) {
|
|
11200
|
+
const head = input.termProgram ?? "(unknown)";
|
|
11201
|
+
const env = [];
|
|
11202
|
+
if (input.termProgram) env.push(`TERM_PROGRAM=${input.termProgram}`);
|
|
11203
|
+
if (input.term) env.push(`TERM=${input.term}`);
|
|
11204
|
+
if (input.colorTerm) env.push(`COLORTERM=${input.colorTerm}`);
|
|
11205
|
+
if (input.inWindowsTerminal) env.push("WT_SESSION=set");
|
|
11206
|
+
if (input.inTmux) env.push("TMUX=set");
|
|
11207
|
+
if (input.inSsh) env.push("SSH_TTY=set");
|
|
11208
|
+
if (input.wslDistro) env.push(`WSL=${input.wslDistro}`);
|
|
11209
|
+
if (env.length === 0) return head;
|
|
11210
|
+
return `${head} (${env.join(", ")})`;
|
|
11211
|
+
}
|
|
11212
|
+
|
|
11213
|
+
// src/cli/ui/open-url.ts
|
|
11214
|
+
import { spawn } from "child_process";
|
|
11215
|
+
import { platform } from "os";
|
|
11216
|
+
function openUrl(url) {
|
|
11217
|
+
if (process.env.CI) return { opened: false, reason: "ci" };
|
|
11218
|
+
if (process.env.REASONIX_NO_OPEN) return { opened: false, reason: "disabled" };
|
|
11219
|
+
const os = platform();
|
|
11220
|
+
let cmd;
|
|
11221
|
+
let args;
|
|
11222
|
+
if (os === "win32") {
|
|
11223
|
+
cmd = "cmd";
|
|
11224
|
+
args = ["/c", "start", "", url];
|
|
11225
|
+
} else if (os === "darwin") {
|
|
11226
|
+
cmd = "open";
|
|
11227
|
+
args = [url];
|
|
11228
|
+
} else {
|
|
11229
|
+
cmd = "xdg-open";
|
|
11230
|
+
args = [url];
|
|
11231
|
+
}
|
|
11232
|
+
try {
|
|
11233
|
+
const child = spawn(cmd, args, { detached: true, stdio: "ignore" });
|
|
11234
|
+
child.unref();
|
|
11235
|
+
return { opened: true };
|
|
11236
|
+
} catch {
|
|
11237
|
+
return { opened: false, reason: "spawn-failed" };
|
|
11238
|
+
}
|
|
11239
|
+
}
|
|
11240
|
+
|
|
10978
11241
|
// src/cli/ui/slash/handlers/observability.ts
|
|
10979
11242
|
var context = (_args, loop2) => {
|
|
10980
11243
|
const breakdown = computeCtxBreakdown(loop2);
|
|
@@ -11004,11 +11267,11 @@ var status = (_args, loop2, ctx) => {
|
|
|
11004
11267
|
}) : t("handlers.observability.statusCtxNone");
|
|
11005
11268
|
const cost2 = summary.totalCostUsd;
|
|
11006
11269
|
const cacheLine = summary.turns > 3 ? (() => {
|
|
11007
|
-
const cachePct =
|
|
11270
|
+
const cachePct = summary.cacheHitRatio * 100;
|
|
11008
11271
|
return t("handlers.observability.statusCost", {
|
|
11009
11272
|
cost: cost2.toFixed(4),
|
|
11010
11273
|
bar: renderTinyBar(cachePct, 12),
|
|
11011
|
-
pct: cachePct,
|
|
11274
|
+
pct: cachePct.toFixed(1),
|
|
11012
11275
|
turns: summary.turns
|
|
11013
11276
|
});
|
|
11014
11277
|
})() : t("handlers.observability.statusCostCold", {
|
|
@@ -11147,11 +11410,48 @@ function estimateCost(userText, loop2) {
|
|
|
11147
11410
|
];
|
|
11148
11411
|
return { info: lines.join("\n") };
|
|
11149
11412
|
}
|
|
11413
|
+
var feedback = (_args, loop2, ctx) => {
|
|
11414
|
+
const themeName = resolveThemePreference(loadTheme(), process.env.REASONIX_THEME);
|
|
11415
|
+
const diagnostic = buildFeedbackDiagnostic({
|
|
11416
|
+
version: VERSION,
|
|
11417
|
+
latestVersion: ctx.latestVersion ?? void 0,
|
|
11418
|
+
platform: process.platform,
|
|
11419
|
+
osRelease: release(),
|
|
11420
|
+
termProgram: process.env.TERM_PROGRAM,
|
|
11421
|
+
term: process.env.TERM,
|
|
11422
|
+
colorTerm: process.env.COLORTERM,
|
|
11423
|
+
inWindowsTerminal: !!process.env.WT_SESSION,
|
|
11424
|
+
inTmux: !!process.env.TMUX,
|
|
11425
|
+
inSsh: !!process.env.SSH_TTY,
|
|
11426
|
+
wslDistro: process.env.WSL_DISTRO_NAME,
|
|
11427
|
+
cols: process.stdout.columns,
|
|
11428
|
+
rows: process.stdout.rows,
|
|
11429
|
+
nodeVersion: process.version,
|
|
11430
|
+
locale: getLanguage(),
|
|
11431
|
+
theme: themeName,
|
|
11432
|
+
model: loop2.model,
|
|
11433
|
+
reasoningEffort: loop2.reasoningEffort,
|
|
11434
|
+
editMode: ctx.editMode,
|
|
11435
|
+
planMode: ctx.planMode,
|
|
11436
|
+
mcpServerCount: ctx.mcpServers?.length ?? ctx.mcpSpecs?.length,
|
|
11437
|
+
sessionId: ctx.sessionId
|
|
11438
|
+
});
|
|
11439
|
+
writeClipboard(diagnostic);
|
|
11440
|
+
const url = buildFeedbackIssueUrl(diagnostic);
|
|
11441
|
+
const opened = openUrl(url);
|
|
11442
|
+
const lines = [
|
|
11443
|
+
opened.opened ? "\u25B8 issue page opened with the diagnostic block pre-filled. Just describe what you were doing and submit." : `\u25B8 couldn't open the browser (${opened.reason ?? "unknown"}). Diagnostic info is on your clipboard; open this URL manually: ${url}`,
|
|
11444
|
+
"",
|
|
11445
|
+
diagnostic
|
|
11446
|
+
];
|
|
11447
|
+
return { info: lines.join("\n") };
|
|
11448
|
+
};
|
|
11150
11449
|
var handlers11 = {
|
|
11151
11450
|
context,
|
|
11152
11451
|
status,
|
|
11153
11452
|
compact,
|
|
11154
|
-
cost
|
|
11453
|
+
cost,
|
|
11454
|
+
feedback
|
|
11155
11455
|
};
|
|
11156
11456
|
|
|
11157
11457
|
// src/cli/ui/slash/handlers/permissions.ts
|
|
@@ -11532,6 +11832,31 @@ var handlers17 = {
|
|
|
11532
11832
|
se: (args, loop2, ctx) => handlers17["search-engine"](args, loop2, ctx)
|
|
11533
11833
|
};
|
|
11534
11834
|
|
|
11835
|
+
// src/cli/ui/slash/nearest.ts
|
|
11836
|
+
function nearestCommands(input, all, opts = {}) {
|
|
11837
|
+
if (!input) return [];
|
|
11838
|
+
const max = opts.max ?? 3;
|
|
11839
|
+
const maxDistance = Math.min(opts.maxDistance ?? 3, Math.floor(input.length / 2));
|
|
11840
|
+
if (max <= 0 || maxDistance <= 0) return [];
|
|
11841
|
+
return all.map((name) => ({ name, distance: levenshtein(input, name) })).filter((entry) => entry.distance <= maxDistance).sort((a, b) => a.distance - b.distance || a.name.localeCompare(b.name)).slice(0, max).map((entry) => entry.name);
|
|
11842
|
+
}
|
|
11843
|
+
function levenshtein(a, b) {
|
|
11844
|
+
if (a === b) return 0;
|
|
11845
|
+
if (!a) return b.length;
|
|
11846
|
+
if (!b) return a.length;
|
|
11847
|
+
let prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
11848
|
+
let next = new Array(b.length + 1).fill(0);
|
|
11849
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
11850
|
+
next[0] = i + 1;
|
|
11851
|
+
for (let j = 0; j < b.length; j += 1) {
|
|
11852
|
+
const cost2 = a[i] === b[j] ? 0 : 1;
|
|
11853
|
+
next[j + 1] = Math.min((next[j] ?? 0) + 1, (prev[j + 1] ?? 0) + 1, (prev[j] ?? 0) + cost2);
|
|
11854
|
+
}
|
|
11855
|
+
[prev, next] = [next, prev];
|
|
11856
|
+
}
|
|
11857
|
+
return prev[b.length] ?? 0;
|
|
11858
|
+
}
|
|
11859
|
+
|
|
11535
11860
|
// src/cli/ui/slash/dispatch.ts
|
|
11536
11861
|
var HANDLERS = {
|
|
11537
11862
|
...handlers,
|
|
@@ -11555,6 +11880,11 @@ var HANDLERS = {
|
|
|
11555
11880
|
function handleSlash(cmd, args, loop2, ctx = {}) {
|
|
11556
11881
|
const h = HANDLERS[resolveSlashAlias(cmd)];
|
|
11557
11882
|
if (h) return h(args, loop2, ctx);
|
|
11883
|
+
const suggestions = nearestCommands(cmd, Object.keys(HANDLERS));
|
|
11884
|
+
if (suggestions.length > 0) {
|
|
11885
|
+
const list2 = suggestions.map((name) => `/${name}`).join(", ");
|
|
11886
|
+
return { unknown: true, info: `unknown command: /${cmd} \u2014 did you mean ${list2}?` };
|
|
11887
|
+
}
|
|
11558
11888
|
return { unknown: true, info: `unknown command: /${cmd} (try /help)` };
|
|
11559
11889
|
}
|
|
11560
11890
|
|
|
@@ -12475,9 +12805,9 @@ function useSubagent({
|
|
|
12475
12805
|
// src/cli/ui/App.tsx
|
|
12476
12806
|
var FLUSH_INTERVAL_MS = (() => {
|
|
12477
12807
|
const raw = process.env.REASONIX_FLUSH_MS;
|
|
12478
|
-
if (!raw) return
|
|
12808
|
+
if (!raw) return 16;
|
|
12479
12809
|
const parsed = Number(raw);
|
|
12480
|
-
if (!Number.isFinite(parsed) || parsed < 16 || parsed > 1e3) return
|
|
12810
|
+
if (!Number.isFinite(parsed) || parsed < 16 || parsed > 1e3) return 16;
|
|
12481
12811
|
return Math.round(parsed);
|
|
12482
12812
|
})();
|
|
12483
12813
|
var PLAIN_UI = process.env.REASONIX_UI === "plain";
|
|
@@ -12519,7 +12849,8 @@ function AppInner({
|
|
|
12519
12849
|
progressSink,
|
|
12520
12850
|
codeMode,
|
|
12521
12851
|
noDashboard,
|
|
12522
|
-
onSwitchSession
|
|
12852
|
+
onSwitchSession,
|
|
12853
|
+
mouse = true
|
|
12523
12854
|
}) {
|
|
12524
12855
|
markPhase("app_inner_start");
|
|
12525
12856
|
const log = useScrollback();
|
|
@@ -12551,18 +12882,18 @@ function AppInner({
|
|
|
12551
12882
|
}, [busy]);
|
|
12552
12883
|
const [ongoingTool, setOngoingTool] = useState20(null);
|
|
12553
12884
|
const [toolProgress, setToolProgress] = useState20(null);
|
|
12554
|
-
const { stdout } =
|
|
12885
|
+
const { stdout } = useStdout15();
|
|
12555
12886
|
useEffect12(() => {
|
|
12556
12887
|
if (!stdout || !stdout.isTTY) return;
|
|
12557
12888
|
stdout.write("\x1B[?2004h");
|
|
12558
12889
|
stdout.write("\x1B[>4;2m");
|
|
12559
|
-
stdout.write("\x1B[?
|
|
12890
|
+
if (mouse) stdout.write("\x1B[?1007h");
|
|
12560
12891
|
return () => {
|
|
12561
|
-
stdout.write("\x1B[?
|
|
12892
|
+
if (mouse) stdout.write("\x1B[?1007l");
|
|
12562
12893
|
stdout.write("\x1B[?2004l");
|
|
12563
12894
|
stdout.write("\x1B[>4m");
|
|
12564
12895
|
};
|
|
12565
|
-
}, [stdout]);
|
|
12896
|
+
}, [stdout, mouse]);
|
|
12566
12897
|
const walletCurrencyRef = useRef9(void 0);
|
|
12567
12898
|
const { activities: subagentActivities, sinkRef: subagentSinkRef } = useSubagent({
|
|
12568
12899
|
session,
|
|
@@ -12711,7 +13042,7 @@ function AppInner({
|
|
|
12711
13042
|
const loopRef = useRef9(null);
|
|
12712
13043
|
const loop2 = useMemo9(() => {
|
|
12713
13044
|
if (loopRef.current) return loopRef.current;
|
|
12714
|
-
const client = new DeepSeekClient();
|
|
13045
|
+
const client = new DeepSeekClient({ baseUrl: loadBaseUrl() });
|
|
12715
13046
|
if (tools && !tools.has("run_skill")) {
|
|
12716
13047
|
registerSkillTools(tools, {
|
|
12717
13048
|
projectRoot: codeMode?.rootDir,
|
|
@@ -13031,11 +13362,12 @@ function AppInner({
|
|
|
13031
13362
|
}, [session, loop2, codeMode, syncPendingCount, log]);
|
|
13032
13363
|
const quitProcess = useQuit(transcriptRef);
|
|
13033
13364
|
useKeystroke((ev) => {
|
|
13365
|
+
const pickerOwnsArrows = (atState?.entries.length ?? 0) > 0 || (slashMatches?.length ?? 0) > 0 || (slashArgMatches?.length ?? 0) > 0 || pendingShell != null;
|
|
13034
13366
|
if (ev.pageUp || ev.mouseScrollUp) chatScroll.scrollUp();
|
|
13035
13367
|
else if (ev.pageDown || ev.mouseScrollDown) chatScroll.scrollDown();
|
|
13036
13368
|
else if (ev.end) chatScroll.jumpToBottom();
|
|
13037
|
-
else if (
|
|
13038
|
-
else if (
|
|
13369
|
+
else if (!pickerOwnsArrows && ev.upArrow) chatScroll.scrollUp();
|
|
13370
|
+
else if (!pickerOwnsArrows && ev.downArrow) chatScroll.scrollDown();
|
|
13039
13371
|
}, !modalOpen);
|
|
13040
13372
|
useKeystroke((ev) => {
|
|
13041
13373
|
const chKey = ev.input;
|
|
@@ -13250,7 +13582,7 @@ function AppInner({
|
|
|
13250
13582
|
if (dashboardRef.current) return dashboardRef.current.url;
|
|
13251
13583
|
if (dashboardStartingRef.current) return dashboardStartingRef.current;
|
|
13252
13584
|
const startup = (async () => {
|
|
13253
|
-
const { startDashboardServer } = await import("./server-
|
|
13585
|
+
const { startDashboardServer } = await import("./server-W4XJK4GX.js");
|
|
13254
13586
|
const handle = await startDashboardServer({
|
|
13255
13587
|
mode: "attached",
|
|
13256
13588
|
configPath: defaultConfigPath(),
|
|
@@ -13685,6 +14017,7 @@ function AppInner({
|
|
|
13685
14017
|
startDashboard,
|
|
13686
14018
|
stopDashboard,
|
|
13687
14019
|
getDashboardUrl,
|
|
14020
|
+
sessionId: session,
|
|
13688
14021
|
jobs: codeMode?.jobs,
|
|
13689
14022
|
postInfo: (text2) => log.pushInfo(text2),
|
|
13690
14023
|
postDoctor: (checks) => log.showDoctor(checks),
|
|
@@ -14151,7 +14484,8 @@ function AppInner({
|
|
|
14151
14484
|
}
|
|
14152
14485
|
if (choice === "refine" || choice === "approve") {
|
|
14153
14486
|
if (pendingPlan) {
|
|
14154
|
-
|
|
14487
|
+
const questions = extractOpenQuestionsSection(pendingPlan) ?? void 0;
|
|
14488
|
+
setStagedInput({ plan: pendingPlan, mode: choice, questions });
|
|
14155
14489
|
setPendingPlan(null);
|
|
14156
14490
|
} else if (choice === "approve") {
|
|
14157
14491
|
setStagedInput({ plan: "", mode: "approve" });
|
|
@@ -14166,7 +14500,8 @@ function AppInner({
|
|
|
14166
14500
|
return;
|
|
14167
14501
|
}
|
|
14168
14502
|
if (pendingPlan) {
|
|
14169
|
-
|
|
14503
|
+
const questions = extractOpenQuestionsSection(pendingPlan) ?? void 0;
|
|
14504
|
+
setStagedInput({ plan: pendingPlan, mode: "reject", questions });
|
|
14170
14505
|
setPendingPlan(null);
|
|
14171
14506
|
}
|
|
14172
14507
|
},
|
|
@@ -14181,7 +14516,7 @@ function AppInner({
|
|
|
14181
14516
|
[]
|
|
14182
14517
|
);
|
|
14183
14518
|
const handleStagedInputSubmit = useCallback11(
|
|
14184
|
-
async (
|
|
14519
|
+
async (feedback2, override) => {
|
|
14185
14520
|
const staged = override ?? stagedInput;
|
|
14186
14521
|
if (override) {
|
|
14187
14522
|
setPendingPlan(null);
|
|
@@ -14189,8 +14524,8 @@ function AppInner({
|
|
|
14189
14524
|
setStagedInput(null);
|
|
14190
14525
|
}
|
|
14191
14526
|
if (!staged) return;
|
|
14192
|
-
const trimmed =
|
|
14193
|
-
|
|
14527
|
+
const trimmed = feedback2.trim();
|
|
14528
|
+
const tail = trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed;
|
|
14194
14529
|
let marker;
|
|
14195
14530
|
if (staged.mode === "approve") {
|
|
14196
14531
|
togglePlanMode(false);
|
|
@@ -14208,19 +14543,7 @@ function AppInner({
|
|
|
14208
14543
|
});
|
|
14209
14544
|
persistPlanState();
|
|
14210
14545
|
}
|
|
14211
|
-
|
|
14212
|
-
synthetic = `The plan above has been approved. Implement it now. You are out of plan mode \u2014 use edit_file / write_file / run_command as needed.
|
|
14213
|
-
|
|
14214
|
-
User's additional instructions / answers to your open questions:
|
|
14215
|
-
|
|
14216
|
-
${trimmed}
|
|
14217
|
-
|
|
14218
|
-
Factor these in before the first edit. Stick to the plan unless you discover a concrete reason to deviate; if you do, tell me and wait for a response.`;
|
|
14219
|
-
marker = `\u25B8 plan approved + instructions \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
|
|
14220
|
-
} else {
|
|
14221
|
-
synthetic = "The plan above has been approved. Implement it now. You are out of plan mode \u2014 use edit_file / write_file / run_command as needed. If the plan listed open questions and I didn't answer them, default to the safest interpretation and call them out in your first reply. Don't fabricate preferences \u2014 if a question is truly unanswerable without me, stop and ask.";
|
|
14222
|
-
marker = "\u25B8 plan approved \u2014 implementing";
|
|
14223
|
-
}
|
|
14546
|
+
marker = trimmed ? `\u25B8 plan approved + instructions \u2014 ${tail}` : "\u25B8 plan approved \u2014 implementing";
|
|
14224
14547
|
} else if (staged.mode === "reject") {
|
|
14225
14548
|
planStepsRef.current = null;
|
|
14226
14549
|
completedStepIdsRef.current = /* @__PURE__ */ new Set();
|
|
@@ -14229,38 +14552,20 @@ Factor these in before the first edit. Stick to the plan unless you discover a c
|
|
|
14229
14552
|
persistPlanState();
|
|
14230
14553
|
togglePlanMode(false);
|
|
14231
14554
|
agentStore.dispatch({ type: "plan.drop" });
|
|
14232
|
-
|
|
14233
|
-
synthetic = `The plan was rejected. User's reason / what they actually want:
|
|
14234
|
-
|
|
14235
|
-
${trimmed}
|
|
14236
|
-
|
|
14237
|
-
Drop the proposed plan entirely. Use this guidance to understand what the user is after \u2014 ask follow-up questions if anything is still unclear, otherwise propose a different plan that addresses it.`;
|
|
14238
|
-
marker = `\u25B8 plan rejected \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
|
|
14239
|
-
} else {
|
|
14240
|
-
synthetic = "The plan was cancelled. Drop it entirely. Ask me what I actually want before proposing another plan or making any changes.";
|
|
14241
|
-
marker = "\u25B8 plan cancelled";
|
|
14242
|
-
}
|
|
14555
|
+
marker = trimmed ? `\u25B8 plan rejected \u2014 ${tail}` : "\u25B8 plan cancelled";
|
|
14243
14556
|
} else {
|
|
14244
|
-
|
|
14245
|
-
synthetic = `The plan needs refinement. User feedback / answers:
|
|
14246
|
-
|
|
14247
|
-
${trimmed}
|
|
14248
|
-
|
|
14249
|
-
Stay in plan mode \u2014 address the feedback (explore more if needed), then submit an improved submit_plan call. Don't propose a near-identical plan unless you explain why the feedback doesn't apply.`;
|
|
14250
|
-
marker = `\u25B8 refining \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
|
|
14251
|
-
} else {
|
|
14252
|
-
synthetic = "The plan needs refinement, but the user didn't give specifics. Ask them one or two concrete questions \u2014 scope, approach, file boundaries, or the risks you flagged \u2014 then wait for their answer before submitting an updated plan.";
|
|
14253
|
-
marker = "\u25B8 refining \u2014 asking the model to clarify";
|
|
14254
|
-
}
|
|
14557
|
+
marker = trimmed ? `\u25B8 refining \u2014 ${tail}` : "\u25B8 refining \u2014 using safe defaults";
|
|
14255
14558
|
}
|
|
14559
|
+
log.pushInfo(marker);
|
|
14256
14560
|
const gateId = pendingGateIdRef.current;
|
|
14257
14561
|
if (gateId !== null) {
|
|
14562
|
+
const fb = trimmed || void 0;
|
|
14258
14563
|
if (staged.mode === "approve") {
|
|
14259
|
-
pauseGate.resolve(gateId, { type: "approve" });
|
|
14564
|
+
pauseGate.resolve(gateId, { type: "approve", feedback: fb });
|
|
14260
14565
|
} else if (staged.mode === "reject") {
|
|
14261
|
-
pauseGate.resolve(gateId, { type: "cancel" });
|
|
14566
|
+
pauseGate.resolve(gateId, { type: "cancel", feedback: fb });
|
|
14262
14567
|
} else {
|
|
14263
|
-
pauseGate.resolve(gateId, { type: "refine" });
|
|
14568
|
+
pauseGate.resolve(gateId, { type: "refine", feedback: fb });
|
|
14264
14569
|
}
|
|
14265
14570
|
}
|
|
14266
14571
|
},
|
|
@@ -14453,12 +14758,12 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
14453
14758
|
[]
|
|
14454
14759
|
);
|
|
14455
14760
|
const handleCheckpointReviseSubmit = useCallback11(
|
|
14456
|
-
(
|
|
14761
|
+
(feedback2, snapOverride) => {
|
|
14457
14762
|
const snap = snapOverride;
|
|
14458
14763
|
setStagedCheckpointRevise(null);
|
|
14459
14764
|
if (!snap) return;
|
|
14460
14765
|
const label = snap.title ? `${snap.stepId} \xB7 ${snap.title}` : snap.stepId;
|
|
14461
|
-
const trimmed =
|
|
14766
|
+
const trimmed = feedback2.trim();
|
|
14462
14767
|
const gid = pendingGateIdRef.current;
|
|
14463
14768
|
if (gid !== null) {
|
|
14464
14769
|
pauseGate.resolve(
|
|
@@ -14558,6 +14863,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
14558
14863
|
PlanRefineInput,
|
|
14559
14864
|
{
|
|
14560
14865
|
mode: stagedInput.mode,
|
|
14866
|
+
questions: stagedInput.questions,
|
|
14561
14867
|
onSubmit: handleStagedInputSubmit,
|
|
14562
14868
|
onCancel: handleStagedInputCancel
|
|
14563
14869
|
}
|
|
@@ -14802,7 +15108,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
14802
15108
|
block: pendingEdits.current[0],
|
|
14803
15109
|
onChoose: handleWalkChoice
|
|
14804
15110
|
}
|
|
14805
|
-
) : !chatScroll.pinned ? /* @__PURE__ */ React60.createElement(Text52, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line") : /* @__PURE__ */ React60.createElement(React60.
|
|
15111
|
+
) : !chatScroll.pinned ? /* @__PURE__ */ React60.createElement(Text52, { color: FG.faint }, " \u{1F4D6} reading history \u2014 End / PgDn to return \xB7 \u2193 to advance one line") : /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, codeMode ? /* @__PURE__ */ React60.createElement(
|
|
14806
15112
|
ModeStatusBar,
|
|
14807
15113
|
{
|
|
14808
15114
|
editMode,
|
|
@@ -14822,15 +15128,16 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
|
|
|
14822
15128
|
onHistoryPrev: recallPrev,
|
|
14823
15129
|
onHistoryNext: recallNext
|
|
14824
15130
|
}
|
|
14825
|
-
), slashMatches !== null ? /* @__PURE__ */ React60.createElement(
|
|
15131
|
+
)), /* @__PURE__ */ React60.createElement(Box49, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, slashMatches !== null ? /* @__PURE__ */ React60.createElement(
|
|
14826
15132
|
SlashSuggestions,
|
|
14827
15133
|
{
|
|
15134
|
+
key: `slash-suggestions:${slashGroupMode ? "group" : "search"}`,
|
|
14828
15135
|
matches: slashMatches,
|
|
14829
15136
|
selectedIndex: slashSelected,
|
|
14830
15137
|
groupMode: slashGroupMode,
|
|
14831
15138
|
advancedHidden: slashAdvancedHidden
|
|
14832
15139
|
}
|
|
14833
|
-
) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null, slashArgContext ? /* @__PURE__ */ React60.createElement(
|
|
15140
|
+
) : null, atState !== null ? /* @__PURE__ */ React60.createElement(AtMentionSuggestions, { state: atState, selectedIndex: atSelected }) : null), slashArgContext ? /* @__PURE__ */ React60.createElement(
|
|
14834
15141
|
SlashArgPicker,
|
|
14835
15142
|
{
|
|
14836
15143
|
matches: slashArgMatches,
|
|
@@ -14902,7 +15209,7 @@ function Setup({ onReady }) {
|
|
|
14902
15209
|
return;
|
|
14903
15210
|
}
|
|
14904
15211
|
if (!isPlausibleKey(trimmed)) {
|
|
14905
|
-
setError("
|
|
15212
|
+
setError("Key looks too short \u2014 paste the full token (16+ chars, no spaces).");
|
|
14906
15213
|
setValue("");
|
|
14907
15214
|
return;
|
|
14908
15215
|
}
|
|
@@ -15195,6 +15502,7 @@ function Root({
|
|
|
15195
15502
|
progressSink,
|
|
15196
15503
|
codeMode: appProps.codeMode,
|
|
15197
15504
|
noDashboard: appProps.noDashboard,
|
|
15505
|
+
mouse: appProps.mouse,
|
|
15198
15506
|
onSwitchSession: setActiveSession
|
|
15199
15507
|
}
|
|
15200
15508
|
));
|
|
@@ -15269,7 +15577,12 @@ async function chatCommand(opts) {
|
|
|
15269
15577
|
exitOnCtrlC: true,
|
|
15270
15578
|
// patchConsole:false — winpty/MINTTY redraw-glitch source.
|
|
15271
15579
|
patchConsole: false,
|
|
15272
|
-
incrementalRendering:
|
|
15580
|
+
// incrementalRendering:false — Ink's diff drifts when stringWidth
|
|
15581
|
+
// misjudges CJK / emoji ZWJ width or when async terminal-event
|
|
15582
|
+
// bytes interleave mid-render, leaving residual rows. Full-frame
|
|
15583
|
+
// redraws cost more stdout bytes per flush but eliminate the
|
|
15584
|
+
// ghost class.
|
|
15585
|
+
incrementalRendering: false,
|
|
15273
15586
|
// Default true — alt-screen is the only mode without scrollback-
|
|
15274
15587
|
// reflow ghosting. `--no-alt-screen` opts back into scrollback mode
|
|
15275
15588
|
// for users who need chat output preserved in shell history on exit.
|
|
@@ -15287,4 +15600,4 @@ async function chatCommand(opts) {
|
|
|
15287
15600
|
export {
|
|
15288
15601
|
chatCommand
|
|
15289
15602
|
};
|
|
15290
|
-
//# sourceMappingURL=chunk-
|
|
15603
|
+
//# sourceMappingURL=chunk-EN4LAZW5.js.map
|