mindweave 2.2.0 → 2.3.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/README.md +6 -2
- package/dist/alternator/chassis/lsp.js +47 -2
- package/dist/alternator/chassis/lsp.js.map +1 -1
- package/dist/cli/App.js +104 -39
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/altScreen.js +17 -1
- package/dist/cli/altScreen.js.map +1 -1
- package/dist/cli/blockSpacing.js +29 -0
- package/dist/cli/blockSpacing.js.map +1 -0
- package/dist/cli/commandLabel.js +85 -0
- package/dist/cli/commandLabel.js.map +1 -0
- package/dist/cli/commands.js +40 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/components/PromptInput.js +8 -1
- package/dist/cli/components/PromptInput.js.map +1 -1
- package/dist/cli/components/ToolGroup.js +5 -1
- package/dist/cli/components/ToolGroup.js.map +1 -1
- package/dist/cli/components/ToolLine.js +61 -6
- package/dist/cli/components/ToolLine.js.map +1 -1
- package/dist/cli/framebuffer/parse.js +10 -4
- package/dist/cli/framebuffer/parse.js.map +1 -1
- package/dist/cli/framebuffer/screen.js +26 -0
- package/dist/cli/framebuffer/screen.js.map +1 -1
- package/dist/cli/framebuffer/writer.js +131 -23
- package/dist/cli/framebuffer/writer.js.map +1 -1
- package/dist/cli/restart.js +99 -0
- package/dist/cli/restart.js.map +1 -0
- package/dist/cli/selfUpdate.js +124 -0
- package/dist/cli/selfUpdate.js.map +1 -0
- package/dist/cli/startupArgs.js +29 -2
- package/dist/cli/startupArgs.js.map +1 -1
- package/dist/cli/terminalRestore.js +9 -1
- package/dist/cli/terminalRestore.js.map +1 -1
- package/dist/cli/toolDisplay.js +15 -6
- package/dist/cli/toolDisplay.js.map +1 -1
- package/dist/cli/transcript.js +1 -1
- package/dist/cli/transcript.js.map +1 -1
- package/dist/cli/updateRunner.js +105 -0
- package/dist/cli/updateRunner.js.map +1 -0
- package/dist/drivers/gemini/manifest.js +16 -11
- package/dist/drivers/gemini/manifest.js.map +1 -1
- package/dist/drivers/meta/client.js +15 -4
- package/dist/drivers/meta/client.js.map +1 -1
- package/dist/drivers/meta/manifest.js +40 -13
- package/dist/drivers/meta/manifest.js.map +1 -1
- package/dist/dynamo/engine.js +30 -4
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/dynamo/prompt.js +7 -4
- package/dist/dynamo/prompt.js.map +1 -1
- package/dist/dynamo/verify.js +8 -5
- package/dist/dynamo/verify.js.map +1 -1
- package/dist/index.js +32 -2
- package/dist/index.js.map +1 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/tools/askUser.js +17 -5
- package/dist/tools/askUser.js.map +1 -1
- package/dist/tools/detail.js +69 -11
- package/dist/tools/detail.js.map +1 -1
- package/dist/tools/exitPlan.js +17 -1
- package/dist/tools/exitPlan.js.map +1 -1
- package/dist/tools/outputShape.js +137 -0
- package/dist/tools/outputShape.js.map +1 -0
- package/dist/tools/registry.js +0 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/runCommand.js +31 -7
- package/dist/tools/runCommand.js.map +1 -1
- package/dist/tools/screenshot.js +33 -5
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/testSummary.js +211 -0
- package/dist/tools/testSummary.js.map +1 -0
- package/package.json +2 -2
- package/dist/alternator/chassis/rank.js +0 -72
- package/dist/alternator/chassis/rank.js.map +0 -1
- package/dist/cli/components/MenuFrame.js +0 -24
- package/dist/cli/components/MenuFrame.js.map +0 -1
- package/dist/cli/reveal.js +0 -32
- package/dist/cli/reveal.js.map +0 -1
- package/dist/cli/smoothScroll.js +0 -74
- package/dist/cli/smoothScroll.js.map +0 -1
- package/dist/cli/viewport.js +0 -179
- package/dist/cli/viewport.js.map +0 -1
- package/dist/dynamo/_probe.tmp.js +0 -20
- package/dist/dynamo/_probe.tmp.js.map +0 -1
- package/dist/tools/captureSweep.js +0 -77
- package/dist/tools/captureSweep.js.map +0 -1
- package/dist/tools/diagnostics.js +0 -174
- package/dist/tools/diagnostics.js.map +0 -1
- package/dist/tools/editFile.js +0 -183
- package/dist/tools/editFile.js.map +0 -1
- package/dist/tools/multiEdit.js +0 -168
- package/dist/tools/multiEdit.js.map +0 -1
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
* therefore known to be Ink's renderer output, where a global patch would also catch
|
|
18
18
|
* unrelated writes and have to guess which was which.
|
|
19
19
|
*
|
|
20
|
+
* ## Why it also writes the whole screen from time to time
|
|
21
|
+
*
|
|
22
|
+
* Diffing against a model of the terminal is only correct while the model is right, and
|
|
23
|
+
* a wrong cell is never revisited, because as far as a diff can see nothing about it
|
|
24
|
+
* changed. So the model is thrown away and the screen written in full on a schedule —
|
|
25
|
+
* see `invalidate()`. That is what keeps a single stray row from becoming a session of
|
|
26
|
+
* interleaved text, and it costs one Ink-sized frame every few seconds.
|
|
27
|
+
*
|
|
20
28
|
* ## What is passed through untouched
|
|
21
29
|
*
|
|
22
30
|
* Only frame CONTENT can be diffed. Control sequences that are not a frame — entering
|
|
@@ -38,6 +46,29 @@ import { paint } from "./paint.js";
|
|
|
38
46
|
const ERASE_PREFIX = /^(?:\x1b\[2K(?:\x1b\[1A)?)+\x1b\[G/;
|
|
39
47
|
/** Any escape sequence, for deciding whether a write carries visible content. */
|
|
40
48
|
const ANY_ESCAPE = /\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[[\]()#;?]*[0-9;]*[A-Za-z]|\x1b./g;
|
|
49
|
+
/**
|
|
50
|
+
* How long the model and the real terminal may disagree during continuous work, in
|
|
51
|
+
* milliseconds.
|
|
52
|
+
*
|
|
53
|
+
* Writing every cell costs about what Ink's own renderer cost on EVERY frame, so paying
|
|
54
|
+
* it once every few seconds gives back almost none of the saving and puts a ceiling on
|
|
55
|
+
* how wrong the screen can get. `0` writes in full every frame, which is Ink's original
|
|
56
|
+
* behaviour and the thing to compare against when this is suspected.
|
|
57
|
+
*
|
|
58
|
+
* Read per wrapper rather than once at module load, so it is a property of the stream
|
|
59
|
+
* being wrapped instead of of whichever import happened first.
|
|
60
|
+
*/
|
|
61
|
+
function fullRepaintMs() {
|
|
62
|
+
const raw = Number(process.env["MINDWEAVE_FB_REPAINT_MS"]);
|
|
63
|
+
return Number.isFinite(raw) && raw >= 0 ? raw : 4000;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* How long after the last frame of a burst the screen is written in full.
|
|
67
|
+
*
|
|
68
|
+
* Short enough that a glitch is gone before it can be read, long enough that it never
|
|
69
|
+
* lands mid-burst: every frame cancels and re-arms it.
|
|
70
|
+
*/
|
|
71
|
+
const IDLE_REPAINT_MS = 400;
|
|
41
72
|
/**
|
|
42
73
|
* Wrap `real` so Ink's frames are diffed before they reach it.
|
|
43
74
|
*
|
|
@@ -50,21 +81,22 @@ export function framebufferStdout(real, onFrame) {
|
|
|
50
81
|
// reason the cell data is in typed arrays.
|
|
51
82
|
let onScreen = new Screen(real.columns ?? 80, real.rows ?? 24);
|
|
52
83
|
let pending = new Screen(onScreen.width, onScreen.height);
|
|
84
|
+
const repaintEvery = fullRepaintMs();
|
|
85
|
+
/** When every cell was last written, which is what bounds how long a disagreement
|
|
86
|
+
* with the real terminal can survive. */
|
|
87
|
+
let lastFull = 0;
|
|
88
|
+
/** The pending after-the-burst repaint, cancelled and re-armed by each frame. */
|
|
89
|
+
let idle;
|
|
53
90
|
/**
|
|
54
91
|
* Match the grids to the terminal. Returns true when the size changed, which the
|
|
55
|
-
* caller
|
|
56
|
-
*
|
|
57
|
-
* The erase is the whole point and it used to be missing. Resizing reset `onScreen`
|
|
58
|
-
* to blanks, on the reasoning that a blank model would make every cell differ and
|
|
59
|
-
* force a full repaint. It does the opposite: the new frame's blank regions are also
|
|
60
|
-
* blanks, so the diff finds them identical and writes nothing for them, while the real
|
|
61
|
-
* terminal still holds whatever was in those cells before. That is what fused an old
|
|
62
|
-
* line onto a new one, leaving rows like `Tools(session)s, ask_user, create_skill,`.
|
|
92
|
+
* caller answers with a full write.
|
|
63
93
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
94
|
+
* Resizing used to reset `onScreen` to blanks, on the reasoning that a blank model
|
|
95
|
+
* would make every cell differ and force a full repaint. It does the opposite: the new
|
|
96
|
+
* frame's blank regions are also blanks, so the diff finds them identical and writes
|
|
97
|
+
* nothing for them, while the real terminal still holds whatever was in those cells
|
|
98
|
+
* before. That is what fused an old line onto a new one, leaving rows like
|
|
99
|
+
* `Tools(session)s, ask_user, create_skill,`.
|
|
68
100
|
*/
|
|
69
101
|
function syncSize() {
|
|
70
102
|
const w = real.columns ?? onScreen.width;
|
|
@@ -73,11 +105,63 @@ export function framebufferStdout(real, onFrame) {
|
|
|
73
105
|
return false;
|
|
74
106
|
onScreen.resize(w, h);
|
|
75
107
|
pending.resize(w, h);
|
|
76
|
-
// Now TRUE rather than assumed: the model says blank, and the caller is about to
|
|
77
|
-
// make the terminal blank to match.
|
|
78
|
-
onScreen.clear();
|
|
79
108
|
return true;
|
|
80
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Forget what is on the terminal, so the next paint writes every cell.
|
|
112
|
+
*
|
|
113
|
+
* THIS IS THE RENDERER'S ONLY WAY BACK, and it is the reason the rest of the file is
|
|
114
|
+
* safe. Everything here writes just the cells that changed between two frames, which
|
|
115
|
+
* is correct exactly as long as the model and the terminal agree. When they stop
|
|
116
|
+
* agreeing the error is PERMANENT: a cell the model has right but the terminal has
|
|
117
|
+
* wrong is never rewritten, because as far as the diff can see nothing about it
|
|
118
|
+
* changed. One stray row is enough to end a long session in interleaved text.
|
|
119
|
+
*
|
|
120
|
+
* There are several ways to lose that agreement — a row the terminal wrapped, a scroll
|
|
121
|
+
* it performed, a write from outside this proxy — and no way to detect any of them
|
|
122
|
+
* from in here. So this does not try to detect them. It gives a disagreement a
|
|
123
|
+
* LIFETIME instead: on a resize, once every `FULL_REPAINT_MS` of continuous work, and
|
|
124
|
+
* `IDLE_REPAINT_MS` after the last frame of a burst.
|
|
125
|
+
*
|
|
126
|
+
* Sentinel rather than an erase sequence. Filling the previous grid with a value no
|
|
127
|
+
* real cell can equal makes every cell differ, so the paint that follows covers the
|
|
128
|
+
* screen on its own. Erasing first would reach the same place with a blank flash in
|
|
129
|
+
* between, and would depend on the terminal's erase honouring the current background.
|
|
130
|
+
*/
|
|
131
|
+
function invalidate() {
|
|
132
|
+
onScreen.invalidate();
|
|
133
|
+
lastFull = Date.now();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Re-assert the model onto the terminal outside of any frame.
|
|
137
|
+
*
|
|
138
|
+
* `pending` is scratch between frames — every frame rewrites it from scratch before
|
|
139
|
+
* reading it — so it can hold the picture while `onScreen` becomes the grid that knows
|
|
140
|
+
* nothing, and the two swap back exactly as they do on a normal frame.
|
|
141
|
+
*/
|
|
142
|
+
function repaintNow() {
|
|
143
|
+
if (onScreen.width === 0 || onScreen.height === 0)
|
|
144
|
+
return;
|
|
145
|
+
pending.copyFrom(onScreen);
|
|
146
|
+
invalidate();
|
|
147
|
+
const escape = paint(onScreen, pending, 1);
|
|
148
|
+
const previous = onScreen;
|
|
149
|
+
onScreen = pending;
|
|
150
|
+
pending = previous;
|
|
151
|
+
if (escape !== "")
|
|
152
|
+
real.write(escape);
|
|
153
|
+
}
|
|
154
|
+
/** Arm the after-the-burst repaint. Unref'd: a screen touch-up must never be the
|
|
155
|
+
* reason the process is still alive. */
|
|
156
|
+
function armIdleRepaint() {
|
|
157
|
+
if (idle)
|
|
158
|
+
clearTimeout(idle);
|
|
159
|
+
idle = setTimeout(() => {
|
|
160
|
+
idle = undefined;
|
|
161
|
+
repaintNow();
|
|
162
|
+
}, IDLE_REPAINT_MS);
|
|
163
|
+
idle.unref?.();
|
|
164
|
+
}
|
|
81
165
|
/**
|
|
82
166
|
* Replaces `write` and nothing else.
|
|
83
167
|
*
|
|
@@ -94,21 +178,42 @@ export function framebufferStdout(real, onFrame) {
|
|
|
94
178
|
*/
|
|
95
179
|
const fbWrite = (data, callback) => {
|
|
96
180
|
const body = data.replace(ERASE_PREFIX, "");
|
|
97
|
-
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
|
|
181
|
+
const bare = body.replace(ANY_ESCAPE, "");
|
|
182
|
+
// Nothing at all once the escapes are gone: a pure control sequence, not a frame.
|
|
183
|
+
// Forward verbatim — this is how the alternate screen is entered, the cursor
|
|
184
|
+
// hidden, and frames wrapped in synchronized-update markers, none of which we may
|
|
185
|
+
// swallow.
|
|
186
|
+
if (bare === "")
|
|
101
187
|
return real.write(data, callback);
|
|
188
|
+
// Escapes plus nothing but CONTROL characters — in practice a stray newline.
|
|
189
|
+
//
|
|
190
|
+
// This used to pass through with the case above, because the test trimmed before
|
|
191
|
+
// asking, and a trimmed "\n" is empty. A newline is not inert: written at the
|
|
192
|
+
// bottom row it SCROLLS THE WHOLE SCREEN UP ONE LINE. Every row is then somewhere
|
|
193
|
+
// the model does not think it is, and since the model is the only thing that knows
|
|
194
|
+
// what is on screen, nothing ever corrects it — the banner ends up half under a
|
|
195
|
+
// tool row (`●MWrite(docs.html)`, the `M` being all that survived of "Mindweave").
|
|
196
|
+
//
|
|
197
|
+
// Swallowed rather than forwarded. Vertical position here is decided entirely by
|
|
198
|
+
// the absolute cursor moves `paint` emits, so a newline arriving from outside that
|
|
199
|
+
// can only move the real screen out from under the model. Tested by SPACES, not by
|
|
200
|
+
// whitespace: a frame of nothing but spaces is a real frame that clears the screen,
|
|
201
|
+
// and trimming would have swallowed that too.
|
|
202
|
+
if (bare.replace(/[\r\n\t\v\f\b]/g, "") === "") {
|
|
203
|
+
callback?.(null);
|
|
204
|
+
return true;
|
|
102
205
|
}
|
|
103
|
-
|
|
206
|
+
// A resize invalidates everything, and so does simply having gone a while without
|
|
207
|
+
// writing in full. Both are answered the same way: by knowing nothing about the
|
|
208
|
+
// screen, so that this frame draws all of it.
|
|
209
|
+
if (syncSize() || Date.now() - lastFull >= repaintEvery)
|
|
210
|
+
invalidate();
|
|
104
211
|
// Build the new frame. Cleared first because a frame is a complete statement
|
|
105
212
|
// about the rows it covers: a line that got shorter must leave blanks behind,
|
|
106
213
|
// not the tail of what used to be there.
|
|
107
214
|
pending.clear();
|
|
108
215
|
parseFrame(pending, body);
|
|
109
|
-
|
|
110
|
-
// to bring the real screen into line with the freshly blanked model above.
|
|
111
|
-
const escape = (resized ? "[2J[H" : "") + paint(onScreen, pending, 1);
|
|
216
|
+
const escape = paint(onScreen, pending, 1);
|
|
112
217
|
// Swap rather than copy. Both grids are the same shape and `pending` is fully
|
|
113
218
|
// rewritten at the start of every frame, so the old on-screen grid is free to
|
|
114
219
|
// become the next scratch buffer — no allocation, no memcpy.
|
|
@@ -116,6 +221,9 @@ export function framebufferStdout(real, onFrame) {
|
|
|
116
221
|
onScreen = pending;
|
|
117
222
|
pending = previous;
|
|
118
223
|
onFrame?.({ inBytes: data.length, outBytes: escape.length });
|
|
224
|
+
// Put the screen beyond doubt once this burst of frames stops. During a burst it
|
|
225
|
+
// is only ever cancelled and re-armed, so it costs nothing until things settle.
|
|
226
|
+
armIdleRepaint();
|
|
119
227
|
if (escape === "") {
|
|
120
228
|
// Nothing changed. Writing zero bytes is the correct output, but the caller
|
|
121
229
|
// may be waiting on the callback, so it still has to be settled.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/cli/framebuffer/writer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/cli/framebuffer/writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* restart.ts — handing the terminal to a newer copy of Mindweave without losing the
|
|
3
|
+
* conversation.
|
|
4
|
+
*
|
|
5
|
+
* ## The shape, and why it is this one
|
|
6
|
+
*
|
|
7
|
+
* Node cannot replace its own process image; there is no `exec`. So "restart" always
|
|
8
|
+
* means a second process, and the only real question is who owns the terminal while
|
|
9
|
+
* both exist. The tempting answer — spawn the new one and exit — is the broken one: the
|
|
10
|
+
* shell sees this process end, prints its prompt, and then two things are writing to the
|
|
11
|
+
* same screen.
|
|
12
|
+
*
|
|
13
|
+
* So the old process stays alive as a shell of itself. It tears its own UI down, hands
|
|
14
|
+
* the terminal over in a defined order, spawns the successor with the same stdio, and
|
|
15
|
+
* then does nothing but wait and pass the exit code up. The shell sees one process from
|
|
16
|
+
* start to finish.
|
|
17
|
+
*
|
|
18
|
+
* A supervisor wrapping every launch would be tidier and is what a long-lived design
|
|
19
|
+
* would grow into. It is deliberately not that yet: it would put new code in the path of
|
|
20
|
+
* EVERY launch to serve one that happens rarely, and a fault in it would reach everyone
|
|
21
|
+
* rather than only the person who ran `/update`.
|
|
22
|
+
*
|
|
23
|
+
* ## The handover order is the whole risk
|
|
24
|
+
*
|
|
25
|
+
* Both processes can write to one terminal and both can want raw mode. The old one must
|
|
26
|
+
* be completely out — rendering stopped, alternate screen left, mouse reporting off,
|
|
27
|
+
* cursor and autowrap restored, stdin out of raw mode — BEFORE the new one starts, or
|
|
28
|
+
* the result is two renderers fighting over a screen, which looks exactly like the
|
|
29
|
+
* corruption this whole area has been chasing. That order lives in `relaunch` and
|
|
30
|
+
* nowhere else.
|
|
31
|
+
*
|
|
32
|
+
* The decisions are pure and tested; the one impure function takes its spawn and its
|
|
33
|
+
* teardown as arguments.
|
|
34
|
+
*/
|
|
35
|
+
/** How long a new process gets to prove it can start, in milliseconds. */
|
|
36
|
+
const START_GRACE_MS = 5_000;
|
|
37
|
+
/**
|
|
38
|
+
* Read a child's exit as one of three things (pure).
|
|
39
|
+
*
|
|
40
|
+
* The distinction that matters is between a version that CANNOT START and a session
|
|
41
|
+
* that ended badly much later. Only the first is the update's fault, and only the first
|
|
42
|
+
* should send anyone back to a previous version. Time is the only evidence available:
|
|
43
|
+
* a build that is broken on this machine fails during startup, long before anyone has
|
|
44
|
+
* typed anything.
|
|
45
|
+
*/
|
|
46
|
+
export function classifyExit(code, signal, elapsedMs) {
|
|
47
|
+
// A signal is how a session is ENDED — Ctrl+C, a closed window — not how a bad
|
|
48
|
+
// version behaves, whenever it arrives.
|
|
49
|
+
if (signal !== null)
|
|
50
|
+
return { kind: "ok", code: code ?? 0 };
|
|
51
|
+
const exit = code ?? 0;
|
|
52
|
+
if (exit === 0)
|
|
53
|
+
return { kind: "ok", code: exit };
|
|
54
|
+
return elapsedMs < START_GRACE_MS ? { kind: "failedStart", code: exit } : { kind: "crashed", code: exit };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* How to launch the copy installed at `packageRoot` (pure).
|
|
58
|
+
*
|
|
59
|
+
* The script is run through this process's own Node rather than through the installed
|
|
60
|
+
* launcher. The launcher on Windows is a `.cmd`, and spawning one means going through a
|
|
61
|
+
* shell, which means every path with a space in it becomes a quoting problem. Node is
|
|
62
|
+
* already here, its path is known exactly, and it takes arguments as an array.
|
|
63
|
+
*/
|
|
64
|
+
export function relaunchArgv(execPath, packageRoot, sessionId) {
|
|
65
|
+
const windows = /^[A-Za-z]:/.test(packageRoot) || packageRoot.startsWith("\\\\");
|
|
66
|
+
const sep = windows ? "\\" : "/";
|
|
67
|
+
const entry = `${packageRoot}${sep}dist${sep}index.js`;
|
|
68
|
+
return { command: execPath, args: sessionId ? [entry, "--resume", sessionId] : [entry] };
|
|
69
|
+
}
|
|
70
|
+
/** What to say when the version just installed cannot start. */
|
|
71
|
+
export function failedStartMessage(previousVersion, prefix) {
|
|
72
|
+
return [
|
|
73
|
+
"The updated version did not start.",
|
|
74
|
+
"",
|
|
75
|
+
`Nothing else was changed, and the previous version can be restored with:`,
|
|
76
|
+
` npm install -g --prefix ${prefix} mindweave@${previousVersion}`,
|
|
77
|
+
].join("\n");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Hand the terminal to the copy at `packageRoot` and wait for it.
|
|
81
|
+
*
|
|
82
|
+
* Resolves with the exit code this process should then use, so the shell that started
|
|
83
|
+
* everything sees one process with one result.
|
|
84
|
+
*/
|
|
85
|
+
export async function relaunch(packageRoot, sessionId, previousVersion, prefix, deps) {
|
|
86
|
+
const now = deps.now ?? Date.now;
|
|
87
|
+
// Order matters and this is the line it matters on: the terminal is fully released
|
|
88
|
+
// before anything else is allowed to touch it.
|
|
89
|
+
await deps.teardown();
|
|
90
|
+
const { command, args } = relaunchArgv(process.execPath, packageRoot, sessionId);
|
|
91
|
+
const startedAt = now();
|
|
92
|
+
const ended = await deps.spawn(command, args);
|
|
93
|
+
const outcome = classifyExit(ended.code, ended.signal, now() - startedAt);
|
|
94
|
+
if (outcome.kind === "failedStart") {
|
|
95
|
+
deps.report(failedStartMessage(previousVersion, prefix));
|
|
96
|
+
}
|
|
97
|
+
return outcome.code;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=restart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart.js","sourceRoot":"","sources":["../../src/cli/restart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,0EAA0E;AAC1E,MAAM,cAAc,GAAG,KAAK,CAAC;AAW7B;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAmB,EAAE,MAAqB,EAAE,SAAiB;IACxF,+EAA+E;IAC/E,wCAAwC;IACxC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAClD,OAAO,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC5G,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,WAAmB,EACnB,SAAkB;IAElB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACjF,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IACjC,MAAM,KAAK,GAAG,GAAG,WAAW,GAAG,GAAG,OAAO,GAAG,UAAU,CAAC;IACvD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;AAC3F,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,kBAAkB,CAAC,eAAuB,EAAE,MAAc;IACxE,OAAO;QACL,oCAAoC;QACpC,EAAE;QACF,0EAA0E;QAC1E,6BAA6B,MAAM,cAAc,eAAe,EAAE;KACnE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAmBD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,WAAmB,EACnB,SAA6B,EAC7B,eAAuB,EACvB,MAAc,EACd,IAAkB;IAElB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACjC,mFAAmF;IACnF,+CAA+C;IAC/C,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IAEtB,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IACjF,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IAE1E,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* selfUpdate.ts — deciding whether this copy of Mindweave may update itself, and how.
|
|
3
|
+
*
|
|
4
|
+
* Pure. Nothing here touches the disk, the network or a process; every question about
|
|
5
|
+
* the outside world arrives through `InstallProbe`. That is deliberate, because this is
|
|
6
|
+
* the part of `/update` that can do damage: the command it produces is run with `-g`, and
|
|
7
|
+
* a wrong answer here means npm rewriting something that was never ours to rewrite.
|
|
8
|
+
*
|
|
9
|
+
* ## The mistake this file exists to avoid
|
|
10
|
+
*
|
|
11
|
+
* The obvious implementation asks npm where global packages go (`npm config get prefix`)
|
|
12
|
+
* and installs there. That is wrong, and it is wrong in a way that looks fine on the
|
|
13
|
+
* machine you wrote it on. A package can be installed under one prefix while npm is
|
|
14
|
+
* configured with another — `npm i -g` without an explicit prefix landing in
|
|
15
|
+
* `~/.local` while `npm config get prefix` says `/usr` is a documented, reported case.
|
|
16
|
+
* The updater then either fails on permissions or, worse, SUCCEEDS: it installs a fresh
|
|
17
|
+
* copy somewhere the user's `mindweave` command does not look, reports victory, and
|
|
18
|
+
* leaves them running the old version with no way to tell.
|
|
19
|
+
*
|
|
20
|
+
* So the prefix is never asked for. It is DERIVED from where this code actually is,
|
|
21
|
+
* and the derivation is confirmed by finding our own launcher where a global install
|
|
22
|
+
* would have put it. If that does not check out, this refuses rather than guessing.
|
|
23
|
+
*
|
|
24
|
+
* ## What it refuses, and why each one matters
|
|
25
|
+
*
|
|
26
|
+
* - a working tree (`mwdev` and the like): `npm i -g` would replace a source build with
|
|
27
|
+
* a published one, silently undoing whatever was being worked on
|
|
28
|
+
* - a linked install: the same, one indirection further away
|
|
29
|
+
* - a local dependency: not ours to update, and `-g` would not update it anyway
|
|
30
|
+
* - anything it cannot place: the honest answer, not a guess with a `-g` on the end
|
|
31
|
+
*/
|
|
32
|
+
/** Split a path on either separator, so one implementation reads both shapes. */
|
|
33
|
+
function segments(path) {
|
|
34
|
+
return path.split(/[\\/]+/).filter((s) => s !== "");
|
|
35
|
+
}
|
|
36
|
+
/** Rebuild a path from segments, in the style the input was written in. */
|
|
37
|
+
function join(parts, windows) {
|
|
38
|
+
return windows ? parts.join("\\") : "/" + parts.join("/");
|
|
39
|
+
}
|
|
40
|
+
/** Does this path look like a Windows one — a drive letter or a UNC root? */
|
|
41
|
+
function isWindowsPath(path) {
|
|
42
|
+
return /^[A-Za-z]:/.test(path) || path.startsWith("\\\\");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The launcher a global install writes beside its `node_modules`.
|
|
46
|
+
*
|
|
47
|
+
* Finding it is what turns "these path segments look global" into evidence. A project
|
|
48
|
+
* that happens to depend on Mindweave has the identical `node_modules/mindweave` shape
|
|
49
|
+
* one directory down from its own root; only a global prefix also holds the launcher.
|
|
50
|
+
*/
|
|
51
|
+
function launcherPaths(prefix, windows) {
|
|
52
|
+
return windows
|
|
53
|
+
? [`${prefix}\\mindweave.cmd`, `${prefix}\\mindweave`]
|
|
54
|
+
: [`${prefix}/bin/mindweave`, `${prefix}/mindweave`];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Place this copy of Mindweave from the directory its package sits in.
|
|
58
|
+
*
|
|
59
|
+
* `packageRoot` is the directory holding our `package.json` — the parent of `dist`, not
|
|
60
|
+
* the path of the running file.
|
|
61
|
+
*/
|
|
62
|
+
export function classifyInstall(packageRoot, probe) {
|
|
63
|
+
const windows = isWindowsPath(packageRoot);
|
|
64
|
+
const parts = segments(packageRoot);
|
|
65
|
+
// A link at our own directory is `npm link` or a junction into a checkout. It is
|
|
66
|
+
// checked before anything else: the segments of a linked install look exactly like a
|
|
67
|
+
// real one, and following them would land the update on the target of the link.
|
|
68
|
+
if (probe.isLink(packageRoot))
|
|
69
|
+
return { kind: "source", packageRoot };
|
|
70
|
+
// Running straight out of a checkout — the dev shim's shape. No `node_modules` above
|
|
71
|
+
// us, and a repository beside us.
|
|
72
|
+
const parent = parts[parts.length - 2];
|
|
73
|
+
if (parent !== "node_modules") {
|
|
74
|
+
return probe.exists(`${packageRoot}${windows ? "\\" : "/"}.git`)
|
|
75
|
+
? { kind: "source", packageRoot }
|
|
76
|
+
: { kind: "unknown", packageRoot };
|
|
77
|
+
}
|
|
78
|
+
// `<prefix>/node_modules/mindweave` on Windows, `<prefix>/lib/node_modules/mindweave`
|
|
79
|
+
// elsewhere. Drop our own directory and the `node_modules` above it, then the `lib` if
|
|
80
|
+
// this is the POSIX shape.
|
|
81
|
+
const above = parts.slice(0, -2);
|
|
82
|
+
const base = above[above.length - 1] === "lib" ? above.slice(0, -1) : above;
|
|
83
|
+
if (base.length === 0)
|
|
84
|
+
return { kind: "unknown", packageRoot };
|
|
85
|
+
const prefix = join(base, windows);
|
|
86
|
+
// The launcher is the proof. Without it this is a project's own dependency that
|
|
87
|
+
// happens to have the same shape, and `-g` would install somewhere else entirely
|
|
88
|
+
// while reporting success.
|
|
89
|
+
if (!launcherPaths(prefix, windows).some((p) => probe.exists(p))) {
|
|
90
|
+
return { kind: "local", packageRoot };
|
|
91
|
+
}
|
|
92
|
+
return { kind: "global", packageRoot, prefix };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The exact command that updates a global install.
|
|
96
|
+
*
|
|
97
|
+
* `--prefix` is not optional and not a nicety. Without it npm resolves the target from
|
|
98
|
+
* its own configuration, which is the one thing this module has established it must not
|
|
99
|
+
* trust — see the file header.
|
|
100
|
+
*/
|
|
101
|
+
export function updateCommand(prefix, version = "latest") {
|
|
102
|
+
return { command: "npm", args: ["install", "-g", "--prefix", prefix, `mindweave@${version}`] };
|
|
103
|
+
}
|
|
104
|
+
/** The command to type by hand, for every path where this declines to act. */
|
|
105
|
+
export function manualCommand(install) {
|
|
106
|
+
return install.kind === "global"
|
|
107
|
+
? updateCommand(install.prefix).args.reduce((s, a) => `${s} ${a}`, "npm")
|
|
108
|
+
: "npm install -g mindweave@latest";
|
|
109
|
+
}
|
|
110
|
+
/** Why an update is not being attempted, in the user's terms. */
|
|
111
|
+
export function refusalReason(install) {
|
|
112
|
+
switch (install.kind) {
|
|
113
|
+
case "global":
|
|
114
|
+
return null;
|
|
115
|
+
case "source":
|
|
116
|
+
return ("This is running from a working tree, not an installed copy. Updating would " +
|
|
117
|
+
"replace your build with the published one. Run `npm run build` there instead.");
|
|
118
|
+
case "local":
|
|
119
|
+
return "This copy is a dependency of another project, so it is that project's to update.";
|
|
120
|
+
case "unknown":
|
|
121
|
+
return "This copy is not in a place an update can be placed, so nothing was changed.";
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=selfUpdate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selfUpdate.js","sourceRoot":"","sources":["../../src/cli/selfUpdate.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/startupArgs.js
CHANGED
|
@@ -59,7 +59,9 @@ export function helpText() {
|
|
|
59
59
|
* documented would be a worse failure than ignoring it.
|
|
60
60
|
*/
|
|
61
61
|
export function parseStartupArgs(argv) {
|
|
62
|
-
|
|
62
|
+
let resumeSessionId;
|
|
63
|
+
for (let i = 0; i < argv.length; i++) {
|
|
64
|
+
const arg = argv[i];
|
|
63
65
|
if (arg === "--help" || arg === "-h")
|
|
64
66
|
return { kind: "print", text: helpText() };
|
|
65
67
|
if (arg === "--version" || arg === "-v")
|
|
@@ -68,8 +70,33 @@ export function parseStartupArgs(argv) {
|
|
|
68
70
|
// out of --help, and a one-letter alias for it would be a trap next to -h and -v.
|
|
69
71
|
if (arg === "--reset-terminal")
|
|
70
72
|
return { kind: "reset" };
|
|
73
|
+
if (arg === "--resume") {
|
|
74
|
+
// Undocumented in --help on purpose: nobody types this. It is how a relaunch
|
|
75
|
+
// after `/update` lands back in the conversation it left, and the only thing
|
|
76
|
+
// that writes it is Mindweave itself.
|
|
77
|
+
//
|
|
78
|
+
// A malformed id starts a NORMAL session rather than refusing to launch. This
|
|
79
|
+
// flag's whole job is to make an update invisible, and the one outcome worse
|
|
80
|
+
// than losing the thread is not coming back at all — `/continue` still reaches
|
|
81
|
+
// the session either way.
|
|
82
|
+
resumeSessionId = safeSessionId(argv[i + 1]);
|
|
83
|
+
i++;
|
|
84
|
+
}
|
|
71
85
|
}
|
|
72
|
-
return { kind: "run" };
|
|
86
|
+
return resumeSessionId === undefined ? { kind: "run" } : { kind: "run", resumeSessionId };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A session id, only if it is one (pure).
|
|
90
|
+
*
|
|
91
|
+
* The id is used to build a path under the project's session directory, so it is
|
|
92
|
+
* checked as a filename component rather than trusted as a label: no separators, no
|
|
93
|
+
* dots, nothing that could climb out of the folder it is meant to name. Session ids
|
|
94
|
+
* are UUIDs, so this rejects nothing legitimate.
|
|
95
|
+
*/
|
|
96
|
+
export function safeSessionId(raw) {
|
|
97
|
+
if (raw === undefined)
|
|
98
|
+
return undefined;
|
|
99
|
+
return /^[A-Za-z0-9_-]{1,64}$/.test(raw) ? raw : undefined;
|
|
73
100
|
}
|
|
74
101
|
/**
|
|
75
102
|
* Whether there is a terminal to read keystrokes from.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startupArgs.js","sourceRoot":"","sources":["../../src/cli/startupArgs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAY1C,mFAAmF;AACnF,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC;IACvB,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,6BAA6B,CAAC;AAC9D,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,QAAQ;IACtB,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC;IACvB,OAAO;QACL,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,+DAA+D;QAChG,EAAE;QACF,QAAQ;QACR,0EAA0E;QAC1E,oDAAoD;QACpD,4DAA4D;QAC5D,4EAA4E;QAC5E,EAAE;QACF,+EAA+E;QAC/E,8EAA8E;QAC9E,4CAA4C;QAC5C,EAAE;QACF,QAAQ;QACR,6DAA6D;QAC7D,oCAAoC;QACpC,qCAAqC;QACrC,2DAA2D;QAC3D,EAAE;QACF,mEAAmE;QACnE,4DAA4D;QAC5D,EAAE;QACF,wCAAwC;QACxC,8CAA8C;KAC/C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAuB;IACtD,KAAK,
|
|
1
|
+
{"version":3,"file":"startupArgs.js","sourceRoot":"","sources":["../../src/cli/startupArgs.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,14 @@ export const MOUSE_OFF = "\x1b[?1006l\x1b[?1000l";
|
|
|
20
20
|
export const ALT_SCREEN_OFF = "\x1b[?1049l";
|
|
21
21
|
/** Show the cursor again. */
|
|
22
22
|
export const SHOW_CURSOR = "\x1b[?25h";
|
|
23
|
+
/**
|
|
24
|
+
* Autowrap back on (DECAWM), the default every shell expects.
|
|
25
|
+
*
|
|
26
|
+
* The app turns it OFF while it owns the screen, because it addresses the terminal as a
|
|
27
|
+
* grid of cells and a row that wraps is a row in a place nothing knows about. Leaving it
|
|
28
|
+
* off afterwards would truncate every long line in the shell that follows.
|
|
29
|
+
*/
|
|
30
|
+
export const AUTOWRAP_ON = "\x1b[?7h";
|
|
23
31
|
/**
|
|
24
32
|
* Everything the app switches on, switched back off, in the order a half-dead terminal
|
|
25
33
|
* wants it: stop the reporting that is actively producing garbage, then restore the
|
|
@@ -30,5 +38,5 @@ export const SHOW_CURSOR = "\x1b[?25h";
|
|
|
30
38
|
* without first working out which parts are actually needed — and there is no way to
|
|
31
39
|
* work that out anyway, since the terminal will not tell us what modes it is in.
|
|
32
40
|
*/
|
|
33
|
-
export const TERMINAL_RESTORE = MOUSE_OFF + ALT_SCREEN_OFF + SHOW_CURSOR;
|
|
41
|
+
export const TERMINAL_RESTORE = MOUSE_OFF + ALT_SCREEN_OFF + SHOW_CURSOR + AUTOWRAP_ON;
|
|
34
42
|
//# sourceMappingURL=terminalRestore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminalRestore.js","sourceRoot":"","sources":["../../src/cli/terminalRestore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,wFAAwF;AACxF,MAAM,CAAC,MAAM,SAAS,GAAG,wBAAwB,CAAC;AAElD,oFAAoF;AACpF,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;AAE5C,6BAA6B;AAC7B,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAS,GAAG,cAAc,GAAG,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"terminalRestore.js","sourceRoot":"","sources":["../../src/cli/terminalRestore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,wFAAwF;AACxF,MAAM,CAAC,MAAM,SAAS,GAAG,wBAAwB,CAAC;AAElD,oFAAoF;AACpF,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;AAE5C,6BAA6B;AAC7B,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;AAEtC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAS,GAAG,cAAc,GAAG,WAAW,GAAG,WAAW,CAAC"}
|
package/dist/cli/toolDisplay.js
CHANGED
|
@@ -18,7 +18,6 @@ const DISPLAY_NAME = {
|
|
|
18
18
|
definition: "Map",
|
|
19
19
|
references: "Map",
|
|
20
20
|
relevant: "Map",
|
|
21
|
-
diagnostics: "Check",
|
|
22
21
|
web_fetch: "Fetch",
|
|
23
22
|
web_search: "WebSearch",
|
|
24
23
|
screenshot: "WindowCapture",
|
|
@@ -96,7 +95,6 @@ const TOOL_KIND = {
|
|
|
96
95
|
replace_symbol_body: "edit",
|
|
97
96
|
write_file: "write",
|
|
98
97
|
run_command: "run",
|
|
99
|
-
diagnostics: "check",
|
|
100
98
|
spawn_subagent: "agent",
|
|
101
99
|
shells: "run",
|
|
102
100
|
// web_fetch and web_search are both "reaching out to the web" — same family,
|
|
@@ -193,16 +191,27 @@ export function toolDisplay(name, args) {
|
|
|
193
191
|
if (name === "spawn_subagent")
|
|
194
192
|
return { name: display, arg: clip(str(args.task), 48) || undefined, kind };
|
|
195
193
|
// `paths` is a LIST — read_file takes several files in one call, and the row has to
|
|
196
|
-
// say
|
|
197
|
-
//
|
|
194
|
+
// say WHICH. It used to say "3 files", which repeated the count the header above it
|
|
195
|
+
// already gave and named none of them, so a burst of reads was three rows of arithmetic
|
|
196
|
+
// and no information. The names are what anyone reading it wants, and they are already
|
|
197
|
+
// here in the arguments.
|
|
198
|
+
//
|
|
199
|
+
// A multi-path read has no line range to show — ranges only apply to a single file, and
|
|
200
|
+
// the tool ignores them for a list — so the names are the whole story.
|
|
198
201
|
const many = Array.isArray(args.paths) ? args.paths.filter((v) => typeof v === "string") : [];
|
|
199
202
|
const path = many.length > 0 ? (many.length === 1 ? (many[0] ?? "") : "") : str(args.path);
|
|
200
203
|
const detail = many.length > 1
|
|
201
|
-
?
|
|
204
|
+
? many.map(base).join(", ")
|
|
202
205
|
: path
|
|
203
206
|
? base(path)
|
|
204
207
|
: str(args.symbol) || str(args.name) || str(args.query) || str(args.label);
|
|
205
|
-
return {
|
|
208
|
+
return {
|
|
209
|
+
name: display,
|
|
210
|
+
arg: detail || undefined,
|
|
211
|
+
kind,
|
|
212
|
+
// What the group header counts. One call, three files read.
|
|
213
|
+
...(many.length > 1 ? { covers: many.length } : {}),
|
|
214
|
+
};
|
|
206
215
|
}
|
|
207
216
|
function str(v) {
|
|
208
217
|
return typeof v === "string" ? v : "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolDisplay.js","sourceRoot":"","sources":["../../src/cli/toolDisplay.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,8DAA8D;AAC9D,MAAM,YAAY,GAA2B;IAC3C,SAAS,EAAE,MAAM;IACjB,WAAW,EAAE,MAAM;IACnB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,OAAO;IACnB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,KAAK;IAClB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,KAAK;IACf,
|
|
1
|
+
{"version":3,"file":"toolDisplay.js","sourceRoot":"","sources":["../../src/cli/toolDisplay.ts"],"names":[],"mappings":"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"}
|