reasonix 0.24.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +8664 -6343
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{prompt-VZQ2CPID.js → prompt-YUL7CYKY.js} +1 -2
- package/dist/index.d.ts +1 -16
- package/dist/index.js +2 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/banner-demo-C3FJP4R6.js +0 -77
- package/dist/cli/banner-demo-C3FJP4R6.js.map +0 -1
- package/dist/cli/card-demo-OEFBRAJP.js +0 -944
- package/dist/cli/card-demo-OEFBRAJP.js.map +0 -1
- package/dist/cli/chunk-2H7UOFLK.js +0 -11
- package/dist/cli/chunk-2K5D5J3I.js +0 -197
- package/dist/cli/chunk-2K5D5J3I.js.map +0 -1
- package/dist/cli/chunk-V3DLUJY6.js +0 -2066
- package/dist/cli/chunk-V3DLUJY6.js.map +0 -1
- package/dist/cli/flicker-demo-YCYC5AR7.js +0 -165
- package/dist/cli/flicker-demo-YCYC5AR7.js.map +0 -1
- package/dist/cli/preview-7BGTDC65.js +0 -224
- package/dist/cli/preview-7BGTDC65.js.map +0 -1
- package/dist/cli/prompt-VZQ2CPID.js.map +0 -1
- package/dist/cli/renderer-demo-262TD7PU.js +0 -95
- package/dist/cli/renderer-demo-262TD7PU.js.map +0 -1
- package/dist/cli/select-demo-3QMFXV5D.js +0 -107
- package/dist/cli/select-demo-3QMFXV5D.js.map +0 -1
- package/dist/cli/stress-demo-W3AU6PUZ.js +0 -211
- package/dist/cli/stress-demo-W3AU6PUZ.js.map +0 -1
- /package/dist/cli/{chunk-2H7UOFLK.js.map → prompt-YUL7CYKY.js.map} +0 -0
|
@@ -1,944 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
CharPool,
|
|
4
|
-
HyperlinkPool,
|
|
5
|
-
StylePool,
|
|
6
|
-
ink_compat_exports,
|
|
7
|
-
mount,
|
|
8
|
-
useKeystroke
|
|
9
|
-
} from "./chunk-V3DLUJY6.js";
|
|
10
|
-
import "./chunk-2H7UOFLK.js";
|
|
11
|
-
|
|
12
|
-
// src/cli/commands/card-demo.tsx
|
|
13
|
-
import React, { useEffect, useRef, useState } from "react";
|
|
14
|
-
var BRAND = "#79c0ff";
|
|
15
|
-
var FAINT = "#6e7681";
|
|
16
|
-
var META = "#8b949e";
|
|
17
|
-
var ACCENT = "#d2a8ff";
|
|
18
|
-
var VIOLET = "#b395f5";
|
|
19
|
-
var OK = "#7ee787";
|
|
20
|
-
var WARN = "#f0b07d";
|
|
21
|
-
var ERR = "#ff8b81";
|
|
22
|
-
var PEND = "#484f58";
|
|
23
|
-
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
24
|
-
var TOOL_GLYPH = {
|
|
25
|
-
read: "\u25A4",
|
|
26
|
-
write: "\u25A5",
|
|
27
|
-
bash: "\u25B6",
|
|
28
|
-
search: "\u2299",
|
|
29
|
-
fetch: "\u232C",
|
|
30
|
-
mcp: "\u2295",
|
|
31
|
-
patch: "\u270E"
|
|
32
|
-
};
|
|
33
|
-
var TOOL_COLOR = {
|
|
34
|
-
read: BRAND,
|
|
35
|
-
write: WARN,
|
|
36
|
-
bash: ACCENT,
|
|
37
|
-
search: BRAND,
|
|
38
|
-
fetch: VIOLET,
|
|
39
|
-
mcp: VIOLET,
|
|
40
|
-
patch: WARN
|
|
41
|
-
};
|
|
42
|
-
var TOOL_TAIL_LEN = {
|
|
43
|
-
read: 2,
|
|
44
|
-
write: 2,
|
|
45
|
-
bash: 5,
|
|
46
|
-
search: 2,
|
|
47
|
-
fetch: 2,
|
|
48
|
-
mcp: 5,
|
|
49
|
-
patch: 2
|
|
50
|
-
};
|
|
51
|
-
function StaticRow({ item }) {
|
|
52
|
-
switch (item.kind) {
|
|
53
|
-
case "user":
|
|
54
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT }, "\u203A"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, null, item.text)));
|
|
55
|
-
case "reasoning":
|
|
56
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: item.aborted ? ERR : ACCENT }, "\u25C6"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: item.aborted ? ERR : ACCENT, bold: true }, item.aborted ? "reasoning (aborted)" : "reasoning"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `${item.paragraphs}\xB6 \xB7 ${item.tokens} tok \xB7 ${item.seconds.toFixed(1)}s`)), item.tail.map((line, i) => (
|
|
57
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: tail preview, positional
|
|
58
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: `r-${i}`, paddingLeft: 2 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: true }, line))
|
|
59
|
-
)));
|
|
60
|
-
case "tool":
|
|
61
|
-
return /* @__PURE__ */ React.createElement(ToolStaticRow, { item });
|
|
62
|
-
case "plan":
|
|
63
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT }, "\u229E"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT, bold: true }, "plan"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `${item.steps.length} steps \xB7 ${item.seconds.toFixed(1)}s`)), item.steps.map((step) => /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: step.label, paddingLeft: 2, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: planColor(step.status) }, planGlyph(step.status)), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: step.status === "skipped" }, step.label), step.note ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `\xB7 ${step.note}`) : null)));
|
|
64
|
-
case "response":
|
|
65
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: item.aborted ? ERR : OK }, "\u2039"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: item.aborted ? ERR : OK, bold: true }, item.aborted ? "response (truncated by esc)" : "response")), item.lines.map((line, i) => (
|
|
66
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: response body lines positional
|
|
67
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: `resp-${i}`, paddingLeft: 2 }, line.kind === "code" ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: BRAND }, line.text || " ") : line.kind === "header" ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { bold: true }, line.text || " ") : line.kind === "list" ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, null, ` \u2022 ${line.text}`) : /* @__PURE__ */ React.createElement(ink_compat_exports.Text, null, line.text || " "))
|
|
68
|
-
)));
|
|
69
|
-
case "diff":
|
|
70
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: WARN }, "\xB1"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { bold: true }, item.file), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: OK }, `+${item.added}`), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ERR }, `-${item.removed}`)), item.preview.map((row, i) => (
|
|
71
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: diff preview lines positional
|
|
72
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: `d-${i}`, paddingLeft: 2, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: row.kind === "+" ? OK : row.kind === "-" ? ERR : FAINT }, row.kind), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: row.kind === " " }, row.text))
|
|
73
|
-
)));
|
|
74
|
-
case "subagent":
|
|
75
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: item.ok ? VIOLET : ERR }, item.ok ? "\u232C" : "\u2716"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: VIOLET, bold: true }, "subagent"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, null, item.task), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `\xB7 ${item.seconds.toFixed(1)}s`)), item.children.map((c, i) => (
|
|
76
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: subagent children positional
|
|
77
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: `sub-${i}`, paddingLeft: 2, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: VIOLET }, "\u258E"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: subChildColor(c.kind) }, subChildGlyph(c.kind)), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: true }, c.summary))
|
|
78
|
-
)));
|
|
79
|
-
case "usage":
|
|
80
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 2, marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: BRAND }, "\u03A3"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: META }, `in ${item.inputTokens} \xB7 out ${item.outputTokens} \xB7 $${item.totalCost.toFixed(4)}`));
|
|
81
|
-
case "error":
|
|
82
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ERR }, "\u2716"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ERR }, item.message));
|
|
83
|
-
case "warn":
|
|
84
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: WARN }, "\u26A0"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: WARN }, item.message));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
function ToolStaticRow({ item }) {
|
|
88
|
-
const glyph = item.status === "ok" ? "\u2713" : item.status === "rejected" ? "\u2717" : "\u2716";
|
|
89
|
-
const headerColor = item.status === "ok" ? TOOL_COLOR[item.tone] : item.status === "rejected" ? FAINT : ERR;
|
|
90
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: headerColor }, glyph), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: headerColor }, TOOL_GLYPH[item.tone]), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: headerColor, bold: true }, item.name), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, item.args), item.status === "rejected" ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ERR, bold: true }, "rejected") : null, item.status === "retry" && item.retryInfo ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: WARN }, `R ${item.retryInfo}`) : null, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `${item.seconds.toFixed(1)}s`)), item.status === "rejected" ? null : /* @__PURE__ */ React.createElement(React.Fragment, null, item.hidden > 0 ? /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { paddingLeft: 2 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `: ${item.hidden} earlier lines`)) : null, item.output.map((line, i) => (
|
|
91
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: tool tail output lines positional
|
|
92
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: `tool-${i}`, paddingLeft: 2 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: true, color: item.status === "error" ? ERR : void 0 }, line || " "))
|
|
93
|
-
))));
|
|
94
|
-
}
|
|
95
|
-
function planGlyph(status) {
|
|
96
|
-
switch (status) {
|
|
97
|
-
case "todo":
|
|
98
|
-
return "\u25CB";
|
|
99
|
-
case "running":
|
|
100
|
-
return "\u25B6";
|
|
101
|
-
case "done":
|
|
102
|
-
return "\u2713";
|
|
103
|
-
case "skipped":
|
|
104
|
-
return "s";
|
|
105
|
-
case "failed":
|
|
106
|
-
return "\u2717";
|
|
107
|
-
case "blocked":
|
|
108
|
-
return "!";
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function planColor(status) {
|
|
112
|
-
switch (status) {
|
|
113
|
-
case "todo":
|
|
114
|
-
return PEND;
|
|
115
|
-
case "running":
|
|
116
|
-
return BRAND;
|
|
117
|
-
case "done":
|
|
118
|
-
return OK;
|
|
119
|
-
case "skipped":
|
|
120
|
-
return FAINT;
|
|
121
|
-
case "failed":
|
|
122
|
-
return ERR;
|
|
123
|
-
case "blocked":
|
|
124
|
-
return WARN;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
function subChildGlyph(kind) {
|
|
128
|
-
switch (kind) {
|
|
129
|
-
case "reasoning":
|
|
130
|
-
return "\u25C6";
|
|
131
|
-
case "tool":
|
|
132
|
-
return "\u25B6";
|
|
133
|
-
case "diff":
|
|
134
|
-
return "\xB1";
|
|
135
|
-
case "error":
|
|
136
|
-
return "\u2716";
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
function subChildColor(kind) {
|
|
140
|
-
switch (kind) {
|
|
141
|
-
case "reasoning":
|
|
142
|
-
return ACCENT;
|
|
143
|
-
case "tool":
|
|
144
|
-
return BRAND;
|
|
145
|
-
case "diff":
|
|
146
|
-
return WARN;
|
|
147
|
-
case "error":
|
|
148
|
-
return ERR;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
function ReasoningCard({ card }) {
|
|
152
|
-
const spin = SPINNER[card.frame % SPINNER.length] ?? "\xB7";
|
|
153
|
-
return /* @__PURE__ */ React.createElement(
|
|
154
|
-
ink_compat_exports.Box,
|
|
155
|
-
{
|
|
156
|
-
flexDirection: "column",
|
|
157
|
-
borderStyle: "round",
|
|
158
|
-
borderColor: ACCENT,
|
|
159
|
-
paddingX: 1,
|
|
160
|
-
marginTop: 1
|
|
161
|
-
},
|
|
162
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT }, spin), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT, bold: true }, "reasoning"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `\xB7 ${card.tokens} tok`)),
|
|
163
|
-
card.tail.map((line, i) => (
|
|
164
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: tail preview rotates by content, positional
|
|
165
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Text, { key: `rl-${i}`, dimColor: true }, line)
|
|
166
|
-
))
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
function ToolActiveCard({ card }) {
|
|
170
|
-
const spin = SPINNER[card.frame % SPINNER.length] ?? "\xB7";
|
|
171
|
-
const tailLen = TOOL_TAIL_LEN[card.tone];
|
|
172
|
-
const tail = card.outputLines.slice(-tailLen);
|
|
173
|
-
const hidden = Math.max(0, card.outputLines.length - tail.length);
|
|
174
|
-
const seconds = (card.elapsedMs / 1e3).toFixed(1);
|
|
175
|
-
const c = TOOL_COLOR[card.tone];
|
|
176
|
-
return /* @__PURE__ */ React.createElement(
|
|
177
|
-
ink_compat_exports.Box,
|
|
178
|
-
{
|
|
179
|
-
flexDirection: "column",
|
|
180
|
-
borderStyle: "round",
|
|
181
|
-
borderColor: c,
|
|
182
|
-
paddingX: 1,
|
|
183
|
-
marginTop: 1
|
|
184
|
-
},
|
|
185
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: c }, spin), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: c }, TOOL_GLYPH[card.tone]), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: c, bold: true }, card.name), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, card.args), card.retry ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: WARN }, `R ${card.retry.attempt}/${card.retry.max}`) : null, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `\xB7 ${seconds}s`)),
|
|
186
|
-
hidden > 0 ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `: ${hidden} earlier lines`) : null,
|
|
187
|
-
tail.map((line, i) => (
|
|
188
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: tool active tail positional
|
|
189
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Text, { key: `ta-${i}`, dimColor: true }, line || " ")
|
|
190
|
-
))
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
function PlanActiveCard({ card }) {
|
|
194
|
-
const spin = SPINNER[card.frame % SPINNER.length] ?? "\xB7";
|
|
195
|
-
const done = card.steps.filter((s) => s.status === "done" || s.status === "skipped").length;
|
|
196
|
-
return /* @__PURE__ */ React.createElement(
|
|
197
|
-
ink_compat_exports.Box,
|
|
198
|
-
{
|
|
199
|
-
flexDirection: "column",
|
|
200
|
-
borderStyle: "round",
|
|
201
|
-
borderColor: ACCENT,
|
|
202
|
-
paddingX: 1,
|
|
203
|
-
marginTop: 1
|
|
204
|
-
},
|
|
205
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT }, "\u229E"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT, bold: true }, card.title), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `${done} of ${card.steps.length} done`)),
|
|
206
|
-
card.steps.map((step, i) => {
|
|
207
|
-
const running = i === card.inProgressIdx;
|
|
208
|
-
const glyph = running ? spin : planGlyph(step.status);
|
|
209
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: step.label, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: planColor(step.status) }, glyph), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { bold: running, dimColor: step.status === "todo" && !running }, step.label), step.note ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `\xB7 ${step.note}`) : null, running ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, "\u2190 in progress") : null);
|
|
210
|
-
})
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
function SubAgentActiveCard({ card }) {
|
|
214
|
-
const spin = SPINNER[card.frame % SPINNER.length] ?? "\xB7";
|
|
215
|
-
const runningCount = card.children.filter((c) => c.status === "running").length;
|
|
216
|
-
return /* @__PURE__ */ React.createElement(
|
|
217
|
-
ink_compat_exports.Box,
|
|
218
|
-
{
|
|
219
|
-
flexDirection: "column",
|
|
220
|
-
borderStyle: "round",
|
|
221
|
-
borderColor: VIOLET,
|
|
222
|
-
paddingX: 1,
|
|
223
|
-
marginTop: 1
|
|
224
|
-
},
|
|
225
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: VIOLET }, spin), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: VIOLET, bold: true }, "subagent"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, null, card.task), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `${runningCount} running`)),
|
|
226
|
-
card.children.map((c, i) => {
|
|
227
|
-
const cglyph = c.status === "running" ? spin : "\u2713";
|
|
228
|
-
const ccolor = c.status === "running" ? BRAND : OK;
|
|
229
|
-
return /* @__PURE__ */ React.createElement(
|
|
230
|
-
ink_compat_exports.Box,
|
|
231
|
-
{
|
|
232
|
-
key: `sc-${i}`,
|
|
233
|
-
flexDirection: "row",
|
|
234
|
-
gap: 1
|
|
235
|
-
},
|
|
236
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: VIOLET }, "\u258E"),
|
|
237
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ccolor }, cglyph),
|
|
238
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: subChildColor(c.kind) }, subChildGlyph(c.kind)),
|
|
239
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: c.status === "done" }, c.summary)
|
|
240
|
-
);
|
|
241
|
-
})
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
function ResponseActiveCard({ card }) {
|
|
245
|
-
const spin = SPINNER[card.frame % SPINNER.length] ?? "\xB7";
|
|
246
|
-
return /* @__PURE__ */ React.createElement(
|
|
247
|
-
ink_compat_exports.Box,
|
|
248
|
-
{
|
|
249
|
-
flexDirection: "column",
|
|
250
|
-
borderStyle: "round",
|
|
251
|
-
borderColor: OK,
|
|
252
|
-
paddingX: 1,
|
|
253
|
-
marginTop: 1
|
|
254
|
-
},
|
|
255
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: OK }, spin), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: OK, bold: true }, "writing\u2026")),
|
|
256
|
-
card.tail.map((line, i) => (
|
|
257
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: response tail positional
|
|
258
|
-
/* @__PURE__ */ React.createElement(ink_compat_exports.Text, { key: `rsp-${i}` }, line || " ")
|
|
259
|
-
))
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
function ActiveCardView({ card }) {
|
|
263
|
-
switch (card.kind) {
|
|
264
|
-
case "reasoning":
|
|
265
|
-
return /* @__PURE__ */ React.createElement(ReasoningCard, { card });
|
|
266
|
-
case "tool":
|
|
267
|
-
return /* @__PURE__ */ React.createElement(ToolActiveCard, { card });
|
|
268
|
-
case "plan":
|
|
269
|
-
return /* @__PURE__ */ React.createElement(PlanActiveCard, { card });
|
|
270
|
-
case "subagent":
|
|
271
|
-
return /* @__PURE__ */ React.createElement(SubAgentActiveCard, { card });
|
|
272
|
-
case "response":
|
|
273
|
-
return /* @__PURE__ */ React.createElement(ResponseActiveCard, { card });
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
function StatusRow({ elapsedMs, cost }) {
|
|
277
|
-
const seconds = (elapsedMs / 1e3).toFixed(1);
|
|
278
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 2 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: BRAND, bold: true }, "\u25C8 Reasonix"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: META }, "deepseek-r1"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `${seconds}s`), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `$${cost.toFixed(4)}`));
|
|
279
|
-
}
|
|
280
|
-
function PromptInput() {
|
|
281
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1, marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: BRAND, bold: true }, "\u203A"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: true }, "type your question\u2026"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, "\u258F"));
|
|
282
|
-
}
|
|
283
|
-
function HintBar() {
|
|
284
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: true }, "card lifecycle reference \xB7 auto-replays \xB7 Esc exit"));
|
|
285
|
-
}
|
|
286
|
-
function CardDemoShell({ onExit }) {
|
|
287
|
-
const [history, setHistory] = useState([]);
|
|
288
|
-
const [active, setActive] = useState([]);
|
|
289
|
-
const [elapsed, setElapsed] = useState(0);
|
|
290
|
-
const [cost, setCost] = useState(0);
|
|
291
|
-
const startedRef = useRef(Date.now());
|
|
292
|
-
useKeystroke((k) => {
|
|
293
|
-
if (k.escape) onExit();
|
|
294
|
-
});
|
|
295
|
-
useEffect(() => {
|
|
296
|
-
const id = setInterval(() => {
|
|
297
|
-
const now = Date.now() - startedRef.current;
|
|
298
|
-
setElapsed(now);
|
|
299
|
-
setCost(now / 1e3 * 8e-4);
|
|
300
|
-
}, 100);
|
|
301
|
-
return () => clearInterval(id);
|
|
302
|
-
}, []);
|
|
303
|
-
useEffect(() => {
|
|
304
|
-
let cancelled = false;
|
|
305
|
-
const api = {
|
|
306
|
-
setActive: (updater) => {
|
|
307
|
-
if (cancelled) return;
|
|
308
|
-
setActive((prev) => updater(prev));
|
|
309
|
-
},
|
|
310
|
-
push: (item) => {
|
|
311
|
-
if (cancelled) return;
|
|
312
|
-
setHistory((prev) => [...prev, item]);
|
|
313
|
-
},
|
|
314
|
-
reset: () => {
|
|
315
|
-
if (cancelled) return;
|
|
316
|
-
setActive([]);
|
|
317
|
-
setHistory([]);
|
|
318
|
-
startedRef.current = Date.now();
|
|
319
|
-
},
|
|
320
|
-
cancelled: () => cancelled,
|
|
321
|
-
sleep: (ms) => new Promise((r) => setTimeout(r, ms))
|
|
322
|
-
};
|
|
323
|
-
void runScript(api);
|
|
324
|
-
return () => {
|
|
325
|
-
cancelled = true;
|
|
326
|
-
};
|
|
327
|
-
}, []);
|
|
328
|
-
return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(StatusRow, { elapsedMs: elapsed, cost }), /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column" }, history.map((item, i) => (
|
|
329
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: append-only history
|
|
330
|
-
/* @__PURE__ */ React.createElement(StaticRow, { key: `h-${i}`, item })
|
|
331
|
-
))), active.map((card, i) => (
|
|
332
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: live region cards positional
|
|
333
|
-
/* @__PURE__ */ React.createElement(ActiveCardView, { key: `a-${i}-${card.id}`, card })
|
|
334
|
-
)), active.length === 0 ? /* @__PURE__ */ React.createElement(PromptInput, null) : null, /* @__PURE__ */ React.createElement(HintBar, null));
|
|
335
|
-
}
|
|
336
|
-
function replaceById(cards, id, next) {
|
|
337
|
-
if (next === null) return cards.filter((c) => c.id !== id);
|
|
338
|
-
return cards.map((c) => c.id === id ? next : c);
|
|
339
|
-
}
|
|
340
|
-
function appendCard(cards, card) {
|
|
341
|
-
return [...cards, card];
|
|
342
|
-
}
|
|
343
|
-
async function runScript(api) {
|
|
344
|
-
while (!api.cancelled()) {
|
|
345
|
-
await sceneFixFailingTest(api);
|
|
346
|
-
if (api.cancelled()) return;
|
|
347
|
-
await api.sleep(1e3);
|
|
348
|
-
if (api.cancelled()) return;
|
|
349
|
-
await sceneSubagent(api);
|
|
350
|
-
if (api.cancelled()) return;
|
|
351
|
-
await api.sleep(800);
|
|
352
|
-
if (api.cancelled()) return;
|
|
353
|
-
await sceneEdgeCases(api);
|
|
354
|
-
if (api.cancelled()) return;
|
|
355
|
-
await api.sleep(1500);
|
|
356
|
-
api.reset();
|
|
357
|
-
await api.sleep(500);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
async function streamReasoning(api, fullText, durationMs, abortAtMs) {
|
|
361
|
-
const id = "reason";
|
|
362
|
-
const start = Date.now();
|
|
363
|
-
let frame = 0;
|
|
364
|
-
let revealed = "";
|
|
365
|
-
let aborted = false;
|
|
366
|
-
api.setActive((prev) => appendCard(prev, { id, kind: "reasoning", tail: [], tokens: 0, frame }));
|
|
367
|
-
while (Date.now() - start < durationMs && !api.cancelled()) {
|
|
368
|
-
if (abortAtMs !== void 0 && Date.now() - start >= abortAtMs) {
|
|
369
|
-
aborted = true;
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
await api.sleep(60);
|
|
373
|
-
frame++;
|
|
374
|
-
revealed = fullText.slice(0, Math.min(fullText.length, revealed.length + 6));
|
|
375
|
-
const lines2 = wrapText(revealed, 70);
|
|
376
|
-
const tail = lines2.slice(-4);
|
|
377
|
-
const tokens = Math.floor(revealed.length / 3);
|
|
378
|
-
const aborting = abortAtMs !== void 0 && Date.now() - start >= abortAtMs - 100;
|
|
379
|
-
api.setActive(
|
|
380
|
-
(prev) => replaceById(prev, id, {
|
|
381
|
-
id,
|
|
382
|
-
kind: "reasoning",
|
|
383
|
-
tail,
|
|
384
|
-
tokens,
|
|
385
|
-
frame,
|
|
386
|
-
aborted: aborting
|
|
387
|
-
})
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
api.setActive((prev) => replaceById(prev, id, null));
|
|
391
|
-
const lines = wrapText(revealed, 70);
|
|
392
|
-
return { tokens: Math.floor(revealed.length / 3), lines, aborted };
|
|
393
|
-
}
|
|
394
|
-
async function streamTool(api, config) {
|
|
395
|
-
const id = `tool-${Math.random().toString(36).slice(2)}`;
|
|
396
|
-
const start = Date.now();
|
|
397
|
-
let frame = 0;
|
|
398
|
-
const out = [];
|
|
399
|
-
api.setActive(
|
|
400
|
-
(prev) => appendCard(prev, {
|
|
401
|
-
id,
|
|
402
|
-
kind: "tool",
|
|
403
|
-
tone: config.tone,
|
|
404
|
-
name: config.name,
|
|
405
|
-
args: config.args,
|
|
406
|
-
outputLines: out,
|
|
407
|
-
elapsedMs: 0,
|
|
408
|
-
frame,
|
|
409
|
-
retry: config.retry
|
|
410
|
-
})
|
|
411
|
-
);
|
|
412
|
-
const lineRate = config.durationMs / Math.max(1, config.output.length);
|
|
413
|
-
let lineIdx = 0;
|
|
414
|
-
while (Date.now() - start < config.durationMs && !api.cancelled()) {
|
|
415
|
-
await api.sleep(80);
|
|
416
|
-
frame++;
|
|
417
|
-
const elapsed = Date.now() - start;
|
|
418
|
-
while (lineIdx < config.output.length && elapsed > lineIdx * lineRate) {
|
|
419
|
-
out.push(config.output[lineIdx] ?? "");
|
|
420
|
-
lineIdx++;
|
|
421
|
-
}
|
|
422
|
-
api.setActive(
|
|
423
|
-
(prev) => replaceById(prev, id, {
|
|
424
|
-
id,
|
|
425
|
-
kind: "tool",
|
|
426
|
-
tone: config.tone,
|
|
427
|
-
name: config.name,
|
|
428
|
-
args: config.args,
|
|
429
|
-
outputLines: out.slice(),
|
|
430
|
-
elapsedMs: elapsed,
|
|
431
|
-
frame,
|
|
432
|
-
retry: config.retry
|
|
433
|
-
})
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
api.setActive((prev) => replaceById(prev, id, null));
|
|
437
|
-
}
|
|
438
|
-
async function sceneFixFailingTest(api) {
|
|
439
|
-
api.push({ kind: "user", text: "fix the failing test in src/loop.test.ts" });
|
|
440
|
-
await api.sleep(400);
|
|
441
|
-
if (api.cancelled()) return;
|
|
442
|
-
const reasoningText = "Looking at recent test failures in src/loop.test.ts. The assertion shape changed -- expects a stripped trailing marker. The new tokenizer in src/parser.ts keeps it. Two paths: patch tokenizer's strip step, or update the test expectation.";
|
|
443
|
-
const reasonStart = Date.now();
|
|
444
|
-
const r = await streamReasoning(api, reasoningText, 2200);
|
|
445
|
-
if (api.cancelled()) return;
|
|
446
|
-
api.push({
|
|
447
|
-
kind: "reasoning",
|
|
448
|
-
tail: r.lines.slice(-2),
|
|
449
|
-
paragraphs: 3,
|
|
450
|
-
tokens: r.tokens,
|
|
451
|
-
seconds: (Date.now() - reasonStart) / 1e3
|
|
452
|
-
});
|
|
453
|
-
await api.sleep(200);
|
|
454
|
-
const planId = "plan-main";
|
|
455
|
-
const planStart = Date.now();
|
|
456
|
-
let frame = 0;
|
|
457
|
-
const steps = [
|
|
458
|
-
{ status: "todo", label: "locate failing assertion" },
|
|
459
|
-
{ status: "todo", label: "patch tokenizer.strip()" },
|
|
460
|
-
{ status: "todo", label: "verify with npm test" },
|
|
461
|
-
{ status: "todo", label: "publish patch" }
|
|
462
|
-
];
|
|
463
|
-
const renderPlan = (inProgressIdx) => {
|
|
464
|
-
api.setActive(
|
|
465
|
-
(prev) => replaceById(
|
|
466
|
-
prev.find((c) => c.id === planId) ? prev : appendCard(prev, makePlan()),
|
|
467
|
-
planId,
|
|
468
|
-
makePlan()
|
|
469
|
-
)
|
|
470
|
-
);
|
|
471
|
-
function makePlan() {
|
|
472
|
-
return {
|
|
473
|
-
id: planId,
|
|
474
|
-
kind: "plan",
|
|
475
|
-
title: "fix loop test",
|
|
476
|
-
steps: steps.slice(),
|
|
477
|
-
inProgressIdx,
|
|
478
|
-
frame
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
};
|
|
482
|
-
api.setActive(
|
|
483
|
-
(prev) => appendCard(prev, {
|
|
484
|
-
id: planId,
|
|
485
|
-
kind: "plan",
|
|
486
|
-
title: "fix loop test",
|
|
487
|
-
steps: steps.slice(),
|
|
488
|
-
inProgressIdx: 0,
|
|
489
|
-
frame
|
|
490
|
-
})
|
|
491
|
-
);
|
|
492
|
-
const planTick = setInterval(() => {
|
|
493
|
-
frame++;
|
|
494
|
-
api.setActive((prev) => {
|
|
495
|
-
const cur = prev.find((c) => c.id === planId);
|
|
496
|
-
if (!cur || cur.kind !== "plan") return prev;
|
|
497
|
-
return replaceById(prev, planId, { ...cur, frame });
|
|
498
|
-
});
|
|
499
|
-
}, 80);
|
|
500
|
-
try {
|
|
501
|
-
steps[0] = { ...steps[0], status: "running" };
|
|
502
|
-
renderPlan(0);
|
|
503
|
-
await streamTool(api, {
|
|
504
|
-
tone: "search",
|
|
505
|
-
name: "grep",
|
|
506
|
-
args: "TRAILER src/parser.ts",
|
|
507
|
-
output: [
|
|
508
|
-
"src/parser.ts:42:const TRAILER = '<|/tool|>';",
|
|
509
|
-
"src/parser.ts:67: if (s.endsWith(TRAILER))"
|
|
510
|
-
],
|
|
511
|
-
durationMs: 800
|
|
512
|
-
});
|
|
513
|
-
if (api.cancelled()) return;
|
|
514
|
-
api.push({
|
|
515
|
-
kind: "tool",
|
|
516
|
-
tone: "search",
|
|
517
|
-
name: "grep",
|
|
518
|
-
args: "TRAILER src/parser.ts",
|
|
519
|
-
output: ["src/parser.ts:67: if (s.endsWith(TRAILER))"],
|
|
520
|
-
hidden: 1,
|
|
521
|
-
seconds: 0.8,
|
|
522
|
-
status: "ok"
|
|
523
|
-
});
|
|
524
|
-
steps[0] = { ...steps[0], status: "done" };
|
|
525
|
-
renderPlan(1);
|
|
526
|
-
await api.sleep(300);
|
|
527
|
-
if (api.cancelled()) return;
|
|
528
|
-
steps[1] = { ...steps[1], status: "running" };
|
|
529
|
-
renderPlan(1);
|
|
530
|
-
await streamTool(api, {
|
|
531
|
-
tone: "write",
|
|
532
|
-
name: "write_file",
|
|
533
|
-
args: "src/parser.ts (full rewrite)",
|
|
534
|
-
output: [],
|
|
535
|
-
durationMs: 600
|
|
536
|
-
});
|
|
537
|
-
if (api.cancelled()) return;
|
|
538
|
-
api.push({
|
|
539
|
-
kind: "tool",
|
|
540
|
-
tone: "write",
|
|
541
|
-
name: "write_file",
|
|
542
|
-
args: "src/parser.ts (full rewrite)",
|
|
543
|
-
output: [],
|
|
544
|
-
hidden: 0,
|
|
545
|
-
seconds: 0.6,
|
|
546
|
-
status: "rejected"
|
|
547
|
-
});
|
|
548
|
-
steps[1] = { ...steps[1], status: "blocked", note: "rejected; trying patch instead" };
|
|
549
|
-
renderPlan(null);
|
|
550
|
-
await api.sleep(800);
|
|
551
|
-
if (api.cancelled()) return;
|
|
552
|
-
steps[1] = { ...steps[1], status: "running", note: void 0 };
|
|
553
|
-
renderPlan(1);
|
|
554
|
-
await streamTool(api, {
|
|
555
|
-
tone: "patch",
|
|
556
|
-
name: "edit_file",
|
|
557
|
-
args: "src/parser.ts -3+12",
|
|
558
|
-
output: [
|
|
559
|
-
"applying hunk 1/1",
|
|
560
|
-
"--- src/parser.ts",
|
|
561
|
-
"+++ src/parser.ts",
|
|
562
|
-
"@@ -42,3 +42,12 @@",
|
|
563
|
-
"+function strip(token: string) {...}"
|
|
564
|
-
],
|
|
565
|
-
durationMs: 1100
|
|
566
|
-
});
|
|
567
|
-
if (api.cancelled()) return;
|
|
568
|
-
api.push({
|
|
569
|
-
kind: "tool",
|
|
570
|
-
tone: "patch",
|
|
571
|
-
name: "edit_file",
|
|
572
|
-
args: "src/parser.ts -3+12",
|
|
573
|
-
output: ["+function strip(token: string) {...}"],
|
|
574
|
-
hidden: 4,
|
|
575
|
-
seconds: 1.1,
|
|
576
|
-
status: "ok"
|
|
577
|
-
});
|
|
578
|
-
steps[1] = { ...steps[1], status: "done" };
|
|
579
|
-
renderPlan(2);
|
|
580
|
-
await api.sleep(300);
|
|
581
|
-
if (api.cancelled()) return;
|
|
582
|
-
steps[2] = { ...steps[2], status: "running" };
|
|
583
|
-
renderPlan(2);
|
|
584
|
-
const bashOutput = [
|
|
585
|
-
" RUNS src/loop.test.ts",
|
|
586
|
-
" FAIL src/loop.test.ts",
|
|
587
|
-
" expect(received).toBe(expected)",
|
|
588
|
-
" - expected: '<final>'",
|
|
589
|
-
" + received: '<final><|/tool|>'"
|
|
590
|
-
];
|
|
591
|
-
await streamTool(api, {
|
|
592
|
-
tone: "bash",
|
|
593
|
-
name: "bash",
|
|
594
|
-
args: "npm test",
|
|
595
|
-
output: bashOutput,
|
|
596
|
-
durationMs: 900,
|
|
597
|
-
retry: { attempt: 1, max: 3 }
|
|
598
|
-
});
|
|
599
|
-
if (api.cancelled()) return;
|
|
600
|
-
api.push({
|
|
601
|
-
kind: "tool",
|
|
602
|
-
tone: "bash",
|
|
603
|
-
name: "bash",
|
|
604
|
-
args: "npm test",
|
|
605
|
-
output: bashOutput.slice(-5),
|
|
606
|
-
hidden: 0,
|
|
607
|
-
seconds: 0.9,
|
|
608
|
-
status: "retry",
|
|
609
|
-
retryInfo: "1/3"
|
|
610
|
-
});
|
|
611
|
-
await api.sleep(200);
|
|
612
|
-
const bashOk = [
|
|
613
|
-
" PASS src/loop.test.ts",
|
|
614
|
-
" PASS src/parser.test.ts",
|
|
615
|
-
" PASS src/diff/cell.test.ts",
|
|
616
|
-
" PASS src/diff/screen.test.ts",
|
|
617
|
-
" PASS src/renderer/layout.test.ts",
|
|
618
|
-
"Tests: 142 passed"
|
|
619
|
-
];
|
|
620
|
-
await streamTool(api, {
|
|
621
|
-
tone: "bash",
|
|
622
|
-
name: "bash",
|
|
623
|
-
args: "npm test",
|
|
624
|
-
output: bashOk,
|
|
625
|
-
durationMs: 1300,
|
|
626
|
-
retry: { attempt: 2, max: 3 }
|
|
627
|
-
});
|
|
628
|
-
if (api.cancelled()) return;
|
|
629
|
-
api.push({
|
|
630
|
-
kind: "tool",
|
|
631
|
-
tone: "bash",
|
|
632
|
-
name: "bash",
|
|
633
|
-
args: "npm test",
|
|
634
|
-
output: bashOk.slice(-5),
|
|
635
|
-
hidden: 1,
|
|
636
|
-
seconds: 1.3,
|
|
637
|
-
status: "ok"
|
|
638
|
-
});
|
|
639
|
-
steps[2] = { ...steps[2], status: "done" };
|
|
640
|
-
renderPlan(3);
|
|
641
|
-
await api.sleep(300);
|
|
642
|
-
if (api.cancelled()) return;
|
|
643
|
-
steps[3] = { ...steps[3], status: "running" };
|
|
644
|
-
renderPlan(3);
|
|
645
|
-
await streamTool(api, {
|
|
646
|
-
tone: "bash",
|
|
647
|
-
name: "bash",
|
|
648
|
-
args: "npm run build && npm publish",
|
|
649
|
-
output: [
|
|
650
|
-
" > tsup",
|
|
651
|
-
" ESM Build start",
|
|
652
|
-
" CJS Build start",
|
|
653
|
-
" DTS Build start",
|
|
654
|
-
" ESM done",
|
|
655
|
-
" + reasonix@0.24.0"
|
|
656
|
-
],
|
|
657
|
-
durationMs: 1500
|
|
658
|
-
});
|
|
659
|
-
if (api.cancelled()) return;
|
|
660
|
-
api.push({
|
|
661
|
-
kind: "tool",
|
|
662
|
-
tone: "bash",
|
|
663
|
-
name: "bash",
|
|
664
|
-
args: "npm run build && npm publish",
|
|
665
|
-
output: [" + reasonix@0.24.0"],
|
|
666
|
-
hidden: 5,
|
|
667
|
-
seconds: 1.5,
|
|
668
|
-
status: "ok"
|
|
669
|
-
});
|
|
670
|
-
steps[3] = { ...steps[3], status: "done" };
|
|
671
|
-
renderPlan(null);
|
|
672
|
-
} finally {
|
|
673
|
-
clearInterval(planTick);
|
|
674
|
-
}
|
|
675
|
-
await api.sleep(400);
|
|
676
|
-
api.setActive((prev) => replaceById(prev, planId, null));
|
|
677
|
-
api.push({ kind: "plan", steps: steps.slice(), seconds: (Date.now() - planStart) / 1e3 });
|
|
678
|
-
await api.sleep(300);
|
|
679
|
-
if (api.cancelled()) return;
|
|
680
|
-
api.push({
|
|
681
|
-
kind: "diff",
|
|
682
|
-
file: "src/parser.ts",
|
|
683
|
-
added: 12,
|
|
684
|
-
removed: 3,
|
|
685
|
-
preview: [
|
|
686
|
-
{ kind: " ", text: "function strip(token: string) {" },
|
|
687
|
-
{ kind: "-", text: " return token.trimEnd();" },
|
|
688
|
-
{ kind: "+", text: " if (token.endsWith(TRAILER)) {" },
|
|
689
|
-
{ kind: "+", text: " return token.slice(0, -TRAILER.length);" },
|
|
690
|
-
{ kind: "+", text: " }" },
|
|
691
|
-
{ kind: "+", text: " return token;" },
|
|
692
|
-
{ kind: " ", text: "}" }
|
|
693
|
-
]
|
|
694
|
-
});
|
|
695
|
-
await api.sleep(400);
|
|
696
|
-
if (api.cancelled()) return;
|
|
697
|
-
await streamMarkdownResponse(api);
|
|
698
|
-
}
|
|
699
|
-
async function streamMarkdownResponse(api) {
|
|
700
|
-
const lines = [
|
|
701
|
-
{ kind: "header", text: "## Patch landed" },
|
|
702
|
-
{ kind: "text", text: "Tests pass on second retry. The patch:" },
|
|
703
|
-
{ kind: "text", text: "" },
|
|
704
|
-
{ kind: "code", text: "function strip(token: string) {" },
|
|
705
|
-
{ kind: "code", text: " if (token.endsWith(TRAILER))" },
|
|
706
|
-
{ kind: "code", text: " return token.slice(0, -TRAILER.length);" },
|
|
707
|
-
{ kind: "code", text: " return token;" },
|
|
708
|
-
{ kind: "code", text: "}" },
|
|
709
|
-
{ kind: "text", text: "" },
|
|
710
|
-
{ kind: "list", text: "checks the suffix before slicing \u2014 no spurious slices on plain tokens" },
|
|
711
|
-
{ kind: "list", text: "released as 0.24.0 to npm" }
|
|
712
|
-
];
|
|
713
|
-
const id = "resp";
|
|
714
|
-
let frame = 0;
|
|
715
|
-
let revealed = 0;
|
|
716
|
-
api.setActive((prev) => appendCard(prev, { id, kind: "response", tail: [], frame }));
|
|
717
|
-
while (revealed < lines.length && !api.cancelled()) {
|
|
718
|
-
await api.sleep(160);
|
|
719
|
-
frame++;
|
|
720
|
-
revealed = Math.min(lines.length, revealed + 1);
|
|
721
|
-
const tail = lines.slice(0, revealed).slice(-4).map(
|
|
722
|
-
(l) => l.kind === "code" ? ` ${l.text}` : l.kind === "list" ? ` - ${l.text}` : l.text
|
|
723
|
-
);
|
|
724
|
-
api.setActive((prev) => replaceById(prev, id, { id, kind: "response", tail, frame }));
|
|
725
|
-
}
|
|
726
|
-
api.setActive((prev) => replaceById(prev, id, null));
|
|
727
|
-
api.push({ kind: "response", lines });
|
|
728
|
-
await api.sleep(200);
|
|
729
|
-
if (api.cancelled()) return;
|
|
730
|
-
api.push({ kind: "usage", inputTokens: 1842, outputTokens: 421, totalCost: 94e-4 });
|
|
731
|
-
}
|
|
732
|
-
async function sceneSubagent(api) {
|
|
733
|
-
api.push({ kind: "user", text: "investigate the auth flow regressions in 0.24" });
|
|
734
|
-
await api.sleep(400);
|
|
735
|
-
if (api.cancelled()) return;
|
|
736
|
-
const id = "sub";
|
|
737
|
-
let frame = 0;
|
|
738
|
-
const start = Date.now();
|
|
739
|
-
const children = [
|
|
740
|
-
{ status: "running", kind: "reasoning", summary: "scanning auth fixtures" },
|
|
741
|
-
{ status: "running", kind: "tool", summary: "grep 'authToken' src/", tone: "search" },
|
|
742
|
-
{ status: "running", kind: "tool", summary: "read src/auth/session.ts", tone: "read" }
|
|
743
|
-
];
|
|
744
|
-
api.setActive(
|
|
745
|
-
(prev) => appendCard(prev, {
|
|
746
|
-
id,
|
|
747
|
-
kind: "subagent",
|
|
748
|
-
task: "auth regressions",
|
|
749
|
-
children: children.slice(),
|
|
750
|
-
frame
|
|
751
|
-
})
|
|
752
|
-
);
|
|
753
|
-
const tick = setInterval(() => {
|
|
754
|
-
frame++;
|
|
755
|
-
api.setActive((prev) => {
|
|
756
|
-
const cur = prev.find((c) => c.id === id);
|
|
757
|
-
if (!cur || cur.kind !== "subagent") return prev;
|
|
758
|
-
return replaceById(prev, id, { ...cur, frame, children: children.slice() });
|
|
759
|
-
});
|
|
760
|
-
}, 80);
|
|
761
|
-
try {
|
|
762
|
-
await api.sleep(1200);
|
|
763
|
-
if (api.cancelled()) return;
|
|
764
|
-
children[0] = { ...children[0], status: "done" };
|
|
765
|
-
await api.sleep(900);
|
|
766
|
-
if (api.cancelled()) return;
|
|
767
|
-
children[1] = { ...children[1], status: "done" };
|
|
768
|
-
await api.sleep(1100);
|
|
769
|
-
if (api.cancelled()) return;
|
|
770
|
-
children[2] = { ...children[2], status: "done" };
|
|
771
|
-
children.push({ status: "running", kind: "diff", summary: "patching session.ts" });
|
|
772
|
-
await api.sleep(1e3);
|
|
773
|
-
if (api.cancelled()) return;
|
|
774
|
-
children[3] = { ...children[3], status: "done" };
|
|
775
|
-
await api.sleep(400);
|
|
776
|
-
} finally {
|
|
777
|
-
clearInterval(tick);
|
|
778
|
-
}
|
|
779
|
-
api.setActive((prev) => replaceById(prev, id, null));
|
|
780
|
-
api.push({
|
|
781
|
-
kind: "subagent",
|
|
782
|
-
task: "auth regressions",
|
|
783
|
-
children: [
|
|
784
|
-
{ kind: "reasoning", summary: "scanned 14 fixtures, found 2 stale" },
|
|
785
|
-
{ kind: "tool", summary: "grep 'authToken' src/" },
|
|
786
|
-
{ kind: "tool", summary: "read src/auth/session.ts" },
|
|
787
|
-
{ kind: "diff", summary: "src/auth/session.ts +5 -2" }
|
|
788
|
-
],
|
|
789
|
-
seconds: (Date.now() - start) / 1e3,
|
|
790
|
-
ok: true
|
|
791
|
-
});
|
|
792
|
-
await api.sleep(400);
|
|
793
|
-
if (api.cancelled()) return;
|
|
794
|
-
const id2 = "resp-cjk";
|
|
795
|
-
const text = "\u6211\u5DF2\u7ECF\u5B9A\u4F4D\u5230\u95EE\u9898\uFF1Asession.ts \u7684 token \u7EED\u671F\u903B\u8F91\u5728 0.24 \u6539\u4E86\u987A\u5E8F\uFF0C\u5BFC\u81F4\u65E7 token \u5728 refresh \u4E4B\u524D\u5C31\u88AB\u6E05\u6389\u3002\u4FEE\u4E86\uFF0C\u518D\u8DD1\u6D4B\u8BD5\u90FD\u8FC7\u4E86\u3002";
|
|
796
|
-
const lines = [
|
|
797
|
-
{ kind: "header", text: "\u7ED3\u8BBA" },
|
|
798
|
-
{ kind: "text", text },
|
|
799
|
-
{ kind: "list", text: "\u5DF2\u4FEE\u590D\uFF0C\u63D0\u4EA4\u5728 src/auth/session.ts" }
|
|
800
|
-
];
|
|
801
|
-
let frame2 = 0;
|
|
802
|
-
let revealed2 = 0;
|
|
803
|
-
api.setActive((prev) => appendCard(prev, { id: id2, kind: "response", tail: [], frame: frame2 }));
|
|
804
|
-
while (revealed2 < lines.length && !api.cancelled()) {
|
|
805
|
-
await api.sleep(180);
|
|
806
|
-
frame2++;
|
|
807
|
-
revealed2++;
|
|
808
|
-
const tail = lines.slice(0, revealed2).slice(-4).map((l) => l.kind === "list" ? ` - ${l.text}` : l.text);
|
|
809
|
-
api.setActive(
|
|
810
|
-
(prev) => replaceById(prev, id2, { id: id2, kind: "response", tail, frame: frame2 })
|
|
811
|
-
);
|
|
812
|
-
}
|
|
813
|
-
api.setActive((prev) => replaceById(prev, id2, null));
|
|
814
|
-
api.push({ kind: "response", lines });
|
|
815
|
-
}
|
|
816
|
-
async function sceneEdgeCases(api) {
|
|
817
|
-
api.push({ kind: "user", text: "summarize the deploy log" });
|
|
818
|
-
await api.sleep(400);
|
|
819
|
-
if (api.cancelled()) return;
|
|
820
|
-
const reasoningText = "Pulling deploy logs from the last hour. Looking for warnings and errors. The database connection retried 3 times before stabilizing...";
|
|
821
|
-
const reasonStart = Date.now();
|
|
822
|
-
const r = await streamReasoning(api, reasoningText, 1200, 800);
|
|
823
|
-
if (api.cancelled()) return;
|
|
824
|
-
api.push({
|
|
825
|
-
kind: "reasoning",
|
|
826
|
-
tail: r.lines.slice(-2),
|
|
827
|
-
paragraphs: 1,
|
|
828
|
-
tokens: r.tokens,
|
|
829
|
-
seconds: (Date.now() - reasonStart) / 1e3,
|
|
830
|
-
aborted: true
|
|
831
|
-
});
|
|
832
|
-
await api.sleep(300);
|
|
833
|
-
if (api.cancelled()) return;
|
|
834
|
-
await streamTool(api, {
|
|
835
|
-
tone: "mcp",
|
|
836
|
-
name: "mcp.linear.search_issues",
|
|
837
|
-
args: '{"query":"deploy error","limit":5}',
|
|
838
|
-
output: [
|
|
839
|
-
"INC-2871 \u2014 db pool exhausted on retry",
|
|
840
|
-
"INC-2872 \u2014 auth refresh race",
|
|
841
|
-
"INC-2873 \u2014 log shipper timeout"
|
|
842
|
-
],
|
|
843
|
-
durationMs: 1100
|
|
844
|
-
});
|
|
845
|
-
if (api.cancelled()) return;
|
|
846
|
-
api.push({
|
|
847
|
-
kind: "tool",
|
|
848
|
-
tone: "mcp",
|
|
849
|
-
name: "mcp.linear.search_issues",
|
|
850
|
-
args: '{"query":"deploy error","limit":5}',
|
|
851
|
-
output: ["INC-2873 \u2014 log shipper timeout"],
|
|
852
|
-
hidden: 2,
|
|
853
|
-
seconds: 1.1,
|
|
854
|
-
status: "ok"
|
|
855
|
-
});
|
|
856
|
-
await api.sleep(300);
|
|
857
|
-
if (api.cancelled()) return;
|
|
858
|
-
await streamTool(api, {
|
|
859
|
-
tone: "fetch",
|
|
860
|
-
name: "web_fetch",
|
|
861
|
-
args: "https://status.deepseek.com/api/incidents",
|
|
862
|
-
output: ["status: 200", '{"incidents":[]}'],
|
|
863
|
-
durationMs: 700
|
|
864
|
-
});
|
|
865
|
-
if (api.cancelled()) return;
|
|
866
|
-
api.push({
|
|
867
|
-
kind: "tool",
|
|
868
|
-
tone: "fetch",
|
|
869
|
-
name: "web_fetch",
|
|
870
|
-
args: "https://status.deepseek.com/api/incidents",
|
|
871
|
-
output: ["status: 200", '{"incidents":[]}'],
|
|
872
|
-
hidden: 0,
|
|
873
|
-
seconds: 0.7,
|
|
874
|
-
status: "ok"
|
|
875
|
-
});
|
|
876
|
-
await api.sleep(300);
|
|
877
|
-
if (api.cancelled()) return;
|
|
878
|
-
api.push({ kind: "warn", message: "context budget at 73% \xB7 /compact suggested" });
|
|
879
|
-
await api.sleep(400);
|
|
880
|
-
api.push({ kind: "error", message: "rate-limit hit \xB7 backing off 8s" });
|
|
881
|
-
await api.sleep(500);
|
|
882
|
-
api.push({ kind: "usage", inputTokens: 487, outputTokens: 96, totalCost: 21e-4 });
|
|
883
|
-
}
|
|
884
|
-
function wrapText(text, width) {
|
|
885
|
-
const lines = [];
|
|
886
|
-
for (const para of text.split("\n")) {
|
|
887
|
-
if (para.length <= width) {
|
|
888
|
-
lines.push(para);
|
|
889
|
-
continue;
|
|
890
|
-
}
|
|
891
|
-
const words = para.split(" ");
|
|
892
|
-
let cur = "";
|
|
893
|
-
for (const w of words) {
|
|
894
|
-
if (cur.length + w.length + 1 > width) {
|
|
895
|
-
if (cur) lines.push(cur);
|
|
896
|
-
cur = w;
|
|
897
|
-
} else {
|
|
898
|
-
cur = cur ? `${cur} ${w}` : w;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
if (cur) lines.push(cur);
|
|
902
|
-
}
|
|
903
|
-
return lines;
|
|
904
|
-
}
|
|
905
|
-
async function runCardDemo(opts = {}) {
|
|
906
|
-
const stdout = opts.stdout ?? process.stdout;
|
|
907
|
-
const stdin = opts.stdin ?? process.stdin;
|
|
908
|
-
if (!stdin.isTTY || !stdout.isTTY) {
|
|
909
|
-
console.error("card-demo requires an interactive TTY.");
|
|
910
|
-
process.exit(1);
|
|
911
|
-
}
|
|
912
|
-
const pools = {
|
|
913
|
-
char: new CharPool(),
|
|
914
|
-
style: new StylePool(),
|
|
915
|
-
hyperlink: new HyperlinkPool()
|
|
916
|
-
};
|
|
917
|
-
let resolveExit = () => {
|
|
918
|
-
};
|
|
919
|
-
const exited = new Promise((resolve) => {
|
|
920
|
-
resolveExit = resolve;
|
|
921
|
-
});
|
|
922
|
-
const handle = mount(/* @__PURE__ */ React.createElement(CardDemoShell, { onExit: () => resolveExit() }), {
|
|
923
|
-
viewportWidth: stdout.columns ?? 80,
|
|
924
|
-
viewportHeight: stdout.rows ?? 30,
|
|
925
|
-
pools,
|
|
926
|
-
write: (bytes) => stdout.write(bytes),
|
|
927
|
-
stdin,
|
|
928
|
-
onExit: () => resolveExit()
|
|
929
|
-
});
|
|
930
|
-
const onResize = () => handle.resize(stdout.columns ?? 80, stdout.rows ?? 30);
|
|
931
|
-
stdout.on("resize", onResize);
|
|
932
|
-
try {
|
|
933
|
-
await exited;
|
|
934
|
-
} finally {
|
|
935
|
-
stdout.off("resize", onResize);
|
|
936
|
-
handle.destroy();
|
|
937
|
-
stdin.pause();
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
export {
|
|
941
|
-
CardDemoShell,
|
|
942
|
-
runCardDemo
|
|
943
|
-
};
|
|
944
|
-
//# sourceMappingURL=card-demo-OEFBRAJP.js.map
|