@standardagents/code 0.4.0 → 0.5.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/index.js +196 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -572,6 +572,20 @@ function gradAt(t) {
|
|
|
572
572
|
Math.round(a[2] + (b[2] - a[2]) * k)
|
|
573
573
|
];
|
|
574
574
|
}
|
|
575
|
+
function cyclePos(t) {
|
|
576
|
+
const p = t - Math.floor(t);
|
|
577
|
+
return p < 0.5 ? p * 2 : 2 - p * 2;
|
|
578
|
+
}
|
|
579
|
+
function colorAtCycle(tri, tc) {
|
|
580
|
+
if (tc) {
|
|
581
|
+
const [r, g, b] = gradAt(tri);
|
|
582
|
+
return `\x1B[38;2;${r};${g};${b}m`;
|
|
583
|
+
}
|
|
584
|
+
return `\x1B[38;5;${GRAD_256[Math.min(GRAD_256.length - 1, Math.floor(tri * GRAD_256.length))]}m`;
|
|
585
|
+
}
|
|
586
|
+
function brandCycleColor(ms, periodMs = 1200) {
|
|
587
|
+
return colorAtCycle(cyclePos(ms / periodMs), truecolor());
|
|
588
|
+
}
|
|
575
589
|
function gradientText(text, phase = 0) {
|
|
576
590
|
const chars = [...text];
|
|
577
591
|
const visible = chars.filter((ch) => ch.trim().length > 0).length;
|
|
@@ -1832,6 +1846,130 @@ var SystemEvents = class {
|
|
|
1832
1846
|
}
|
|
1833
1847
|
};
|
|
1834
1848
|
|
|
1849
|
+
// src/wordmill.ts
|
|
1850
|
+
var MILL_WORDS = [
|
|
1851
|
+
"Working",
|
|
1852
|
+
"Thinking",
|
|
1853
|
+
"Building",
|
|
1854
|
+
"Brewing",
|
|
1855
|
+
"Crafting",
|
|
1856
|
+
"Scheming",
|
|
1857
|
+
"Tinkering",
|
|
1858
|
+
"Noodling",
|
|
1859
|
+
"Pondering",
|
|
1860
|
+
"Wrangling",
|
|
1861
|
+
"Conjuring",
|
|
1862
|
+
"Percolating",
|
|
1863
|
+
"Assembling",
|
|
1864
|
+
"Cogitating",
|
|
1865
|
+
"Hatching",
|
|
1866
|
+
"Forging",
|
|
1867
|
+
// The silly shelf — irreverent, never profane.
|
|
1868
|
+
"Pickling",
|
|
1869
|
+
"Spooning",
|
|
1870
|
+
"Marinating",
|
|
1871
|
+
"Squishing",
|
|
1872
|
+
"Wiggling",
|
|
1873
|
+
"Frolicking",
|
|
1874
|
+
"Moisturizing",
|
|
1875
|
+
"Bamboozling",
|
|
1876
|
+
"Skedaddling",
|
|
1877
|
+
"Discombobulating",
|
|
1878
|
+
"Waffling",
|
|
1879
|
+
"Yodeling",
|
|
1880
|
+
"Shimmying",
|
|
1881
|
+
"Galumphing",
|
|
1882
|
+
"Snorkeling",
|
|
1883
|
+
"Bedazzling"
|
|
1884
|
+
];
|
|
1885
|
+
var FLIP_POOL = "abcdefghjkmnopqrstuvwxyz#$%&@!*+=.:~";
|
|
1886
|
+
var HOLD_MS = 2600;
|
|
1887
|
+
var LAZY_MS = 320;
|
|
1888
|
+
var LAZY_PERIOD = 200;
|
|
1889
|
+
var FAST_PERIOD = 70;
|
|
1890
|
+
var BOLD = "\x1B[1m";
|
|
1891
|
+
var DIM2 = "\x1B[2m";
|
|
1892
|
+
var OFF = "\x1B[22m";
|
|
1893
|
+
function glyphAt(slot, bucket) {
|
|
1894
|
+
let h = (slot + 1) * 2654435761 ^ (bucket + 1) * 40503;
|
|
1895
|
+
h = Math.imul(h ^ h >>> 13, 1274126177);
|
|
1896
|
+
h ^= h >>> 16;
|
|
1897
|
+
return FLIP_POOL[(h >>> 0) % FLIP_POOL.length];
|
|
1898
|
+
}
|
|
1899
|
+
var WordMill = class {
|
|
1900
|
+
word = MILL_WORDS[0];
|
|
1901
|
+
target = null;
|
|
1902
|
+
// non-null while morphing
|
|
1903
|
+
phaseAt = 0;
|
|
1904
|
+
// clock time the current phase began
|
|
1905
|
+
slots = [];
|
|
1906
|
+
morphLen = 0;
|
|
1907
|
+
rng;
|
|
1908
|
+
constructor(rng = Math.random) {
|
|
1909
|
+
this.rng = rng;
|
|
1910
|
+
}
|
|
1911
|
+
/** Restart at "Working" (called when a turn begins). */
|
|
1912
|
+
reset(now) {
|
|
1913
|
+
this.word = MILL_WORDS[0];
|
|
1914
|
+
this.target = null;
|
|
1915
|
+
this.phaseAt = now;
|
|
1916
|
+
}
|
|
1917
|
+
/** The plain word currently displayed or being formed (for tests). */
|
|
1918
|
+
get current() {
|
|
1919
|
+
return this.target ?? this.word;
|
|
1920
|
+
}
|
|
1921
|
+
/** The styled label for this frame (contains only bold/dim ANSI). */
|
|
1922
|
+
text(now) {
|
|
1923
|
+
if (this.phaseAt === 0) this.phaseAt = now;
|
|
1924
|
+
if (!this.target) {
|
|
1925
|
+
if (now - this.phaseAt >= HOLD_MS) this.beginMorph(now);
|
|
1926
|
+
else return `${BOLD}${this.word}${OFF}`;
|
|
1927
|
+
}
|
|
1928
|
+
return this.morphFrame(now);
|
|
1929
|
+
}
|
|
1930
|
+
beginMorph(now) {
|
|
1931
|
+
const options = MILL_WORDS.filter((w) => w !== this.word);
|
|
1932
|
+
this.target = options[Math.floor(this.rng() * options.length)];
|
|
1933
|
+
this.phaseAt = now;
|
|
1934
|
+
const n = Math.max(this.word.length, this.target.length);
|
|
1935
|
+
this.slots = [];
|
|
1936
|
+
let maxLand = 0;
|
|
1937
|
+
for (let i = 0; i < n; i++) {
|
|
1938
|
+
const start = this.rng() * 500;
|
|
1939
|
+
const land = 750 + i * 90 + this.rng() * 350;
|
|
1940
|
+
this.slots.push({ start, land });
|
|
1941
|
+
if (land > maxLand) maxLand = land;
|
|
1942
|
+
}
|
|
1943
|
+
this.morphLen = maxLand + 60;
|
|
1944
|
+
}
|
|
1945
|
+
morphFrame(now) {
|
|
1946
|
+
const target = this.target;
|
|
1947
|
+
const t = now - this.phaseAt;
|
|
1948
|
+
if (t >= this.morphLen) {
|
|
1949
|
+
this.word = target;
|
|
1950
|
+
this.target = null;
|
|
1951
|
+
this.phaseAt = now;
|
|
1952
|
+
return `${BOLD}${this.word}${OFF}`;
|
|
1953
|
+
}
|
|
1954
|
+
let out = "";
|
|
1955
|
+
for (let i = 0; i < this.slots.length; i++) {
|
|
1956
|
+
const s = this.slots[i];
|
|
1957
|
+
if (t < s.start) {
|
|
1958
|
+
const ch = this.word[i];
|
|
1959
|
+
if (ch) out += `${BOLD}${ch}${OFF}`;
|
|
1960
|
+
} else if (t < s.land) {
|
|
1961
|
+
const age = t - s.start;
|
|
1962
|
+
const period = age < LAZY_MS ? LAZY_PERIOD : FAST_PERIOD;
|
|
1963
|
+
out += `${DIM2}${glyphAt(i, Math.floor(t / period))}${OFF}`;
|
|
1964
|
+
} else {
|
|
1965
|
+
const ch = target[i];
|
|
1966
|
+
if (ch) out += `${BOLD}${ch}${OFF}`;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
return out;
|
|
1970
|
+
}
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1835
1973
|
// src/types.ts
|
|
1836
1974
|
var LEVELS = [1, 2, 3, 4, 5];
|
|
1837
1975
|
var LEVEL_DETAIL = {
|
|
@@ -1950,6 +2088,7 @@ var C = {
|
|
|
1950
2088
|
teal: "\x1B[38;5;37m"
|
|
1951
2089
|
};
|
|
1952
2090
|
var FRAMES = ["\u28F7", "\u28EF", "\u28DF", "\u287F", "\u28BF", "\u28FB", "\u28FD", "\u28FE"];
|
|
2091
|
+
var SPINNER_MS = 70;
|
|
1953
2092
|
var SUBAGENT_COLORS = [
|
|
1954
2093
|
"\x1B[35m",
|
|
1955
2094
|
// magenta
|
|
@@ -1986,6 +2125,8 @@ var Tui = class _Tui {
|
|
|
1986
2125
|
// caret's row offset from the input region top, last render
|
|
1987
2126
|
working = false;
|
|
1988
2127
|
workingStart = 0;
|
|
2128
|
+
// Slot-machine morph for the working label (Working → Brewing → …).
|
|
2129
|
+
wordMill = new WordMill();
|
|
1989
2130
|
spinnerTimer = null;
|
|
1990
2131
|
bgCount = 0;
|
|
1991
2132
|
// The `[⚙ n bg]` prompt badge can be selected with ← from the start of the
|
|
@@ -2495,7 +2636,8 @@ var Tui = class _Tui {
|
|
|
2495
2636
|
return `${(n / 1e6).toFixed(2)}M`;
|
|
2496
2637
|
}
|
|
2497
2638
|
spinnerFrame() {
|
|
2498
|
-
|
|
2639
|
+
const now = Date.now();
|
|
2640
|
+
return `${C.bold}${brandCycleColor(now)}${FRAMES[Math.floor(now / SPINNER_MS) % FRAMES.length]}${C.reset}`;
|
|
2499
2641
|
}
|
|
2500
2642
|
/** "↑X ↓Y" cumulative token totals (greyed — low-priority). */
|
|
2501
2643
|
tokensText() {
|
|
@@ -2568,7 +2710,7 @@ var Tui = class _Tui {
|
|
|
2568
2710
|
if (this.working) {
|
|
2569
2711
|
const el = this.formatElapsed(Date.now() - this.workingStart);
|
|
2570
2712
|
const right = `${C.dim}${el}${C.reset}${tk ? " " + tk : ""}`;
|
|
2571
|
-
const head = `${this.spinnerFrame()} ${
|
|
2713
|
+
const head = `${this.spinnerFrame()} ${this.wordMill.text(Date.now())}`;
|
|
2572
2714
|
const avail = Math.max(
|
|
2573
2715
|
0,
|
|
2574
2716
|
cols2 - this.visibleWidth(head) - this.visibleWidth(right) - 2 - gaugeReserve
|
|
@@ -2697,7 +2839,7 @@ var Tui = class _Tui {
|
|
|
2697
2839
|
const quitLine = this.quitArmed ? `${C.dim}Press Control-C again to exit${C.reset}` : null;
|
|
2698
2840
|
const quitRows = quitLine ? 1 : 0;
|
|
2699
2841
|
if (quitLine) writeHudRow(quitLine);
|
|
2700
|
-
const frame = FRAMES[Math.floor(Date.now() /
|
|
2842
|
+
const frame = FRAMES[Math.floor(Date.now() / SPINNER_MS) % FRAMES.length];
|
|
2701
2843
|
for (const sub of this.subagents) {
|
|
2702
2844
|
const color = sub.agentName === COMPACTION_AGENT ? COMPACTION_COLOR : SUBAGENT_COLORS[this.subagentColorByID.get(sub.id) ?? 0];
|
|
2703
2845
|
const budget = cols2 - 10;
|
|
@@ -2986,6 +3128,7 @@ var Tui = class _Tui {
|
|
|
2986
3128
|
if (on && !this.working) {
|
|
2987
3129
|
this.working = true;
|
|
2988
3130
|
this.workingStart = Date.now();
|
|
3131
|
+
this.wordMill.reset(this.workingStart);
|
|
2989
3132
|
this.goalComplete = false;
|
|
2990
3133
|
} else if (!on) {
|
|
2991
3134
|
this.working = false;
|
|
@@ -3017,7 +3160,7 @@ var Tui = class _Tui {
|
|
|
3017
3160
|
syncSpinner() {
|
|
3018
3161
|
const spinning = this.working || this.subagents.length > 0;
|
|
3019
3162
|
if (spinning && !this.spinnerTimer) {
|
|
3020
|
-
this.spinnerTimer = setInterval(() => this.renderBottom(),
|
|
3163
|
+
this.spinnerTimer = setInterval(() => this.renderBottom(), SPINNER_MS);
|
|
3021
3164
|
} else if (!spinning && this.spinnerTimer) {
|
|
3022
3165
|
clearInterval(this.spinnerTimer);
|
|
3023
3166
|
this.spinnerTimer = null;
|
|
@@ -3296,8 +3439,8 @@ function appendHistory(store, threadId, history, text) {
|
|
|
3296
3439
|
// src/markdown.ts
|
|
3297
3440
|
var ESC = "\x1B[";
|
|
3298
3441
|
var R = ESC + "0m";
|
|
3299
|
-
var
|
|
3300
|
-
var
|
|
3442
|
+
var BOLD2 = ESC + "1m";
|
|
3443
|
+
var DIM3 = ESC + "2m";
|
|
3301
3444
|
var ITAL = ESC + "3m";
|
|
3302
3445
|
var UNDER = ESC + "4m";
|
|
3303
3446
|
var TEAL = ESC + "38;5;37m";
|
|
@@ -3319,11 +3462,11 @@ function inline(s) {
|
|
|
3319
3462
|
});
|
|
3320
3463
|
s = s.replace(
|
|
3321
3464
|
/\[([^\]]+)\]\(([^)\s]+)\)/g,
|
|
3322
|
-
(_, text, url) => `${CYAN}${UNDER}${text}${R} ${
|
|
3465
|
+
(_, text, url) => `${CYAN}${UNDER}${text}${R} ${DIM3}${url}${R}`
|
|
3323
3466
|
);
|
|
3324
|
-
s = s.replace(/\*\*([^*]+)\*\*/g, (_, t) => `${
|
|
3467
|
+
s = s.replace(/\*\*([^*]+)\*\*/g, (_, t) => `${BOLD2}${t}${R}`);
|
|
3325
3468
|
s = s.replace(/\*([^*\n]+)\*/g, (_, t) => `${ITAL}${t}${R}`);
|
|
3326
|
-
s = s.replace(/~~([^~]+)~~/g, (_, t) => `${
|
|
3469
|
+
s = s.replace(/~~([^~]+)~~/g, (_, t) => `${DIM3}${t}${R}`);
|
|
3327
3470
|
s = s.replace(/\x00(\d+)\x00/g, (_, i) => `${TEAL}${codes[+i].replace(/ /g, String.fromCharCode(160))}${R}`);
|
|
3328
3471
|
return s;
|
|
3329
3472
|
}
|
|
@@ -3376,7 +3519,7 @@ function renderTable(rows) {
|
|
|
3376
3519
|
const cells = [];
|
|
3377
3520
|
for (let c2 = 0; c2 < cols2; c2++) {
|
|
3378
3521
|
const raw = r[c2] ?? "";
|
|
3379
|
-
const styled = ri === 0 ? `${
|
|
3522
|
+
const styled = ri === 0 ? `${BOLD2}${inline(raw)}${R}` : inline(raw);
|
|
3380
3523
|
cells.push(padEndVisible(styled, widths[c2]));
|
|
3381
3524
|
}
|
|
3382
3525
|
out.push((" " + cells.join(sep)).replace(/\s+$/, ""));
|
|
@@ -3416,7 +3559,7 @@ function renderMarkdown(src, cols2 = 80) {
|
|
|
3416
3559
|
}
|
|
3417
3560
|
const heading = line.match(/^(#{1,6})\s+(.*)$/);
|
|
3418
3561
|
if (heading) {
|
|
3419
|
-
for (const ln of wrapStyled(heading[2].trim(), cols2)) out.push(`${
|
|
3562
|
+
for (const ln of wrapStyled(heading[2].trim(), cols2)) out.push(`${BOLD2}${TEAL}${ln}${R}`);
|
|
3420
3563
|
i++;
|
|
3421
3564
|
continue;
|
|
3422
3565
|
}
|
|
@@ -3428,7 +3571,7 @@ function renderMarkdown(src, cols2 = 80) {
|
|
|
3428
3571
|
const quote = line.match(/^\s*>\s?(.*)$/);
|
|
3429
3572
|
if (quote) {
|
|
3430
3573
|
for (const ln of wrapStyled(inline(quote[1]), Math.max(8, cols2 - 2))) {
|
|
3431
|
-
out.push(`${GRAY}\u2502${R} ${
|
|
3574
|
+
out.push(`${GRAY}\u2502${R} ${DIM3}${ln}${R}`);
|
|
3432
3575
|
}
|
|
3433
3576
|
i++;
|
|
3434
3577
|
continue;
|
|
@@ -3444,7 +3587,7 @@ function renderMarkdown(src, cols2 = 80) {
|
|
|
3444
3587
|
if (numbered) {
|
|
3445
3588
|
const marker = `${numbered[2]}${numbered[3]}`;
|
|
3446
3589
|
const leadWidth = numbered[1].length + marker.length + 1;
|
|
3447
|
-
wrapBlock(out, cols2, `${numbered[1]}${
|
|
3590
|
+
wrapBlock(out, cols2, `${numbered[1]}${BOLD2}${marker}${R} `, " ".repeat(leadWidth), leadWidth, inline(numbered[4]));
|
|
3448
3591
|
i++;
|
|
3449
3592
|
continue;
|
|
3450
3593
|
}
|
|
@@ -3733,7 +3876,7 @@ var McpManager = class {
|
|
|
3733
3876
|
}));
|
|
3734
3877
|
return {
|
|
3735
3878
|
ok: true,
|
|
3736
|
-
result: servers.length ? JSON.stringify({ servers }, null, 2) :
|
|
3879
|
+
result: servers.length ? JSON.stringify({ servers }, null, 2) : 'No MCP servers are connected. The user can add one with the /mcp command, or you can install one with the mcp tool (action "install").'
|
|
3737
3880
|
};
|
|
3738
3881
|
}
|
|
3739
3882
|
if (action === "list_tools") {
|
|
@@ -3992,7 +4135,25 @@ function printAssistant(tui, text) {
|
|
|
3992
4135
|
}
|
|
3993
4136
|
tui.print("");
|
|
3994
4137
|
}
|
|
4138
|
+
function startLoader(label) {
|
|
4139
|
+
const frames = ["\u28F7", "\u28EF", "\u28DF", "\u287F", "\u28BF", "\u28FB", "\u28FD", "\u28FE"];
|
|
4140
|
+
stdout.write("\x1B[?25l");
|
|
4141
|
+
const draw = () => {
|
|
4142
|
+
const now = Date.now();
|
|
4143
|
+
const f = frames[Math.floor(now / 70) % frames.length];
|
|
4144
|
+
stdout.write(`\r\x1B[K${brandCycleColor(now)}${f}${c.reset} ${c.dim}${label}\u2026${c.reset}`);
|
|
4145
|
+
};
|
|
4146
|
+
draw();
|
|
4147
|
+
const timer = setInterval(draw, 70);
|
|
4148
|
+
return {
|
|
4149
|
+
stop: () => {
|
|
4150
|
+
clearInterval(timer);
|
|
4151
|
+
stdout.write("\r\x1B[K\x1B[?25h");
|
|
4152
|
+
}
|
|
4153
|
+
};
|
|
4154
|
+
}
|
|
3995
4155
|
function farewell(stoppedProcs = 0) {
|
|
4156
|
+
stdout.write("\x1B[?25h");
|
|
3996
4157
|
if (stoppedProcs > 0) {
|
|
3997
4158
|
stdout.write(
|
|
3998
4159
|
`
|
|
@@ -4041,7 +4202,7 @@ function printWelcome(endpoint, projectDir) {
|
|
|
4041
4202
|
const meta = [
|
|
4042
4203
|
`${c.bold}${gradientText("Standard Code")}${c.reset}${version ? ` ${c.dim}v${version}${c.reset}` : ""}`,
|
|
4043
4204
|
`${c.dim}terminal coding agent${c.reset}`,
|
|
4044
|
-
`${c.teal}${host}${c.reset}
|
|
4205
|
+
...endpoint === PRODUCTION_ENDPOINT ? [] : [`${c.teal}${host}${c.reset}`],
|
|
4045
4206
|
`${c.dim}${dir}${c.reset}`
|
|
4046
4207
|
];
|
|
4047
4208
|
const markWidth = Math.max(...LOGO_MARK.map((l) => [...l].length));
|
|
@@ -4157,7 +4318,12 @@ ${c.dim}Press Control-C again to exit${c.reset}
|
|
|
4157
4318
|
}
|
|
4158
4319
|
const stored = getCredential(endpoint);
|
|
4159
4320
|
let api = stored ? new ApiClient(endpoint, stored.access_token) : null;
|
|
4160
|
-
|
|
4321
|
+
let storedCheck = null;
|
|
4322
|
+
if (api) {
|
|
4323
|
+
const connecting = startLoader("Connecting to Standard Agents");
|
|
4324
|
+
storedCheck = await api.verifyDetailed();
|
|
4325
|
+
connecting.stop();
|
|
4326
|
+
}
|
|
4161
4327
|
if (!api || !storedCheck?.ok) {
|
|
4162
4328
|
const host = endpoint.replace(/^https?:\/\//, "").replace(/\/$/, "");
|
|
4163
4329
|
if (storedCheck && !storedCheck.ok) {
|
|
@@ -4199,7 +4365,9 @@ ${c.dim}Press Control-C again to exit${c.reset}
|
|
|
4199
4365
|
});
|
|
4200
4366
|
if (!got) continue;
|
|
4201
4367
|
api = new ApiClient(endpoint, got);
|
|
4368
|
+
const connecting2 = startLoader("Connecting to Standard Agents");
|
|
4202
4369
|
const check2 = await api.verifyDetailed();
|
|
4370
|
+
connecting2.stop();
|
|
4203
4371
|
if (check2.ok) {
|
|
4204
4372
|
saveCredential(
|
|
4205
4373
|
{ endpoint, access_token: got, token_type: "Bearer", saved_at: Date.now() },
|
|
@@ -4213,7 +4381,9 @@ ${c.dim}Press Control-C again to exit${c.reset}
|
|
|
4213
4381
|
continue;
|
|
4214
4382
|
}
|
|
4215
4383
|
api = new ApiClient(endpoint, token);
|
|
4384
|
+
const connecting = startLoader("Connecting to Standard Agents");
|
|
4216
4385
|
const check = await api.verifyDetailed();
|
|
4386
|
+
connecting.stop();
|
|
4217
4387
|
if (check.ok) {
|
|
4218
4388
|
saveCredential(
|
|
4219
4389
|
{ endpoint, access_token: token, token_type: "Bearer", saved_at: Date.now() },
|
|
@@ -4232,18 +4402,20 @@ ${c.dim}Press Control-C again to exit${c.reset}
|
|
|
4232
4402
|
handoffClosing = true;
|
|
4233
4403
|
reader.rl?.close();
|
|
4234
4404
|
const tags = [`path:${projectDir}`, `machine:${machine}`];
|
|
4405
|
+
const loadingSessions = startLoader("Loading sessions");
|
|
4235
4406
|
let existing = [];
|
|
4236
4407
|
try {
|
|
4237
4408
|
existing = await api.listThreads(AGENT_ID_VARIANTS, tags);
|
|
4238
4409
|
} catch {
|
|
4239
4410
|
existing = [];
|
|
4240
4411
|
}
|
|
4412
|
+
const summaries = existing.length > 0 ? await summarizeThreads(api, existing.slice(0, 8)) : [];
|
|
4413
|
+
loadingSessions.stop();
|
|
4241
4414
|
const tui = new Tui(1);
|
|
4242
4415
|
let threadId;
|
|
4243
4416
|
let resumed = false;
|
|
4244
4417
|
let historySeed;
|
|
4245
4418
|
if (existing.length > 0) {
|
|
4246
|
-
const summaries = await summarizeThreads(api, existing.slice(0, 8));
|
|
4247
4419
|
const items = summaries.map((s) => ({
|
|
4248
4420
|
label: s.label,
|
|
4249
4421
|
hint: s.hint,
|
|
@@ -4409,6 +4581,7 @@ async function runInteractive(tui, api, threadId, projectDir, machine, resumed,
|
|
|
4409
4581
|
saveApprovals(api, threadId, perm);
|
|
4410
4582
|
void api.kvSet(threadId, "session_info", { cwd: projectDir, machine }).catch(() => {
|
|
4411
4583
|
});
|
|
4584
|
+
const attaching = startLoader("Attaching to thread");
|
|
4412
4585
|
let busy = false;
|
|
4413
4586
|
let interrupting = false;
|
|
4414
4587
|
const queued = [];
|
|
@@ -4599,7 +4772,8 @@ ${c.bold}why: ${req.requestPermission}${c.reset}` : ""}`,
|
|
|
4599
4772
|
return mcpCtl.connect(cfg);
|
|
4600
4773
|
},
|
|
4601
4774
|
// Seed the request into the main chat — the agent researches + installs it
|
|
4602
|
-
// there (using research_agent +
|
|
4775
|
+
// there (using research_agent + the mcp tool's install action), visible in
|
|
4776
|
+
// the transcript.
|
|
4603
4777
|
requestInstall: (query) => {
|
|
4604
4778
|
void sendNow(
|
|
4605
4779
|
`Install an MCP server for me: ${query}. Research the best one and its exact launch command, then install it.`
|
|
@@ -4649,10 +4823,11 @@ ${c.bold}why: ${req.requestPermission}${c.reset}` : ""}`,
|
|
|
4649
4823
|
setEnabled: (name, enabled) => api.setSkillEnabled(name, enabled),
|
|
4650
4824
|
remove: (name) => api.removeSkill(name),
|
|
4651
4825
|
// Seed the request into the main chat — the agent researches or authors
|
|
4652
|
-
// the skill there (research_agent +
|
|
4826
|
+
// the skill there (research_agent + the skill tool's install action),
|
|
4827
|
+
// visible in the transcript.
|
|
4653
4828
|
requestInstall: (query) => {
|
|
4654
4829
|
void sendNow(
|
|
4655
|
-
`Install a skill for me: ${query}. Find the skill's published files (or author a proper SKILL.md from your research), install it
|
|
4830
|
+
`Install a skill for me: ${query}. Find the skill's published files (or author a proper SKILL.md from your research), install it, then tell me what it can do.`
|
|
4656
4831
|
);
|
|
4657
4832
|
}
|
|
4658
4833
|
};
|
|
@@ -4751,6 +4926,7 @@ ${c.bold}why: ${req.requestPermission}${c.reset}` : ""}`,
|
|
|
4751
4926
|
await Promise.all([bridge.connect(), stream.connect()]);
|
|
4752
4927
|
void api.getGoal(threadId).then((g) => tui.setGoal(g)).catch(() => {
|
|
4753
4928
|
});
|
|
4929
|
+
attaching.stop();
|
|
4754
4930
|
tui.banner([
|
|
4755
4931
|
`${c.bold}${c.magenta}Standard Code${c.reset} ${c.dim}\u2014 coding agent${c.reset}`,
|
|
4756
4932
|
`${c.gray}project:${c.reset} ${projectDir}`,
|