@standardagents/code 0.5.0 → 0.5.1
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 +225 -17
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import os6 from 'os';
|
|
2
|
+
import os6, { homedir } from 'os';
|
|
3
3
|
import fs4 from 'fs';
|
|
4
4
|
import path3 from 'path';
|
|
5
5
|
import readline2 from 'readline/promises';
|
|
@@ -2105,6 +2105,19 @@ var SUBAGENT_COLORS = [
|
|
|
2105
2105
|
];
|
|
2106
2106
|
var COMPACTION_COLOR = "\x1B[38;5;208m";
|
|
2107
2107
|
var COMPACTION_AGENT = "compaction_agent";
|
|
2108
|
+
function isWideCodePoint(cp) {
|
|
2109
|
+
return cp >= 4352 && cp <= 4447 || // Hangul Jamo
|
|
2110
|
+
cp >= 11904 && cp <= 42191 || // CJK radicals … Yi
|
|
2111
|
+
cp >= 44032 && cp <= 55203 || // Hangul syllables
|
|
2112
|
+
cp >= 63744 && cp <= 64255 || // CJK compatibility ideographs
|
|
2113
|
+
cp >= 65072 && cp <= 65103 || // CJK compatibility forms
|
|
2114
|
+
cp >= 65280 && cp <= 65376 || // fullwidth forms
|
|
2115
|
+
cp >= 65504 && cp <= 65510 || cp >= 127744 && cp <= 129791 || // emoji
|
|
2116
|
+
cp >= 131072;
|
|
2117
|
+
}
|
|
2118
|
+
function sanitizeHudRow(s) {
|
|
2119
|
+
return s.replace(/\x1b(?!\[)/g, "").replace(/[\x00-\x1a\x1c-\x1f\x7f]/g, " ");
|
|
2120
|
+
}
|
|
2108
2121
|
var Tui = class _Tui {
|
|
2109
2122
|
constructor(level = 1) {
|
|
2110
2123
|
this.level = level;
|
|
@@ -2741,7 +2754,50 @@ var Tui = class _Tui {
|
|
|
2741
2754
|
return `${q}${bg}${this.levelColor()}\u276F${C.reset} `;
|
|
2742
2755
|
}
|
|
2743
2756
|
visibleWidth(s) {
|
|
2744
|
-
|
|
2757
|
+
let w = 0;
|
|
2758
|
+
for (const ch of s.replace(/\x1b\[[0-9;]*m/g, "")) {
|
|
2759
|
+
w += isWideCodePoint(ch.codePointAt(0)) ? 2 : 1;
|
|
2760
|
+
}
|
|
2761
|
+
return w;
|
|
2762
|
+
}
|
|
2763
|
+
/**
|
|
2764
|
+
* Truncate a styled string to at most `max` VISIBLE columns, copying ANSI
|
|
2765
|
+
* escape sequences through without counting them and appending a reset if it
|
|
2766
|
+
* cut mid-style. The redraw's whole height math assumes every HUD row is
|
|
2767
|
+
* exactly ONE physical terminal row — true only while each row's visible
|
|
2768
|
+
* width is strictly less than `cols`. A row of width == cols hits the
|
|
2769
|
+
* terminal's auto-wrap boundary: many terminals push the cursor to the next
|
|
2770
|
+
* line, so the following CR/LF yields an EXTRA physical row we didn't count,
|
|
2771
|
+
* and the region marches down the screen leaving a trail on every tick. Every
|
|
2772
|
+
* HUD row is clamped through here to keep that invariant no matter what any
|
|
2773
|
+
* individual line builder produces.
|
|
2774
|
+
*/
|
|
2775
|
+
clampVisible(s, max) {
|
|
2776
|
+
let out = "";
|
|
2777
|
+
let width = 0;
|
|
2778
|
+
let i = 0;
|
|
2779
|
+
let truncated = false;
|
|
2780
|
+
while (i < s.length) {
|
|
2781
|
+
if (s[i] === "\x1B" && s[i + 1] === "[") {
|
|
2782
|
+
let j = i + 2;
|
|
2783
|
+
while (j < s.length && !/[a-zA-Z]/.test(s[j])) j++;
|
|
2784
|
+
out += s.slice(i, j + 1);
|
|
2785
|
+
i = j + 1;
|
|
2786
|
+
continue;
|
|
2787
|
+
}
|
|
2788
|
+
const cp = s.codePointAt(i);
|
|
2789
|
+
const chLen = cp > 65535 ? 2 : 1;
|
|
2790
|
+
const chWidth = isWideCodePoint(cp) ? 2 : 1;
|
|
2791
|
+
if (width + chWidth > max) {
|
|
2792
|
+
truncated = true;
|
|
2793
|
+
break;
|
|
2794
|
+
}
|
|
2795
|
+
out += s.slice(i, i + chLen);
|
|
2796
|
+
width += chWidth;
|
|
2797
|
+
i += chLen;
|
|
2798
|
+
}
|
|
2799
|
+
if (truncated) out += C.reset;
|
|
2800
|
+
return out;
|
|
2745
2801
|
}
|
|
2746
2802
|
/**
|
|
2747
2803
|
* The slash-palette block rendered BELOW the input. While the palette is open
|
|
@@ -2754,7 +2810,7 @@ var Tui = class _Tui {
|
|
|
2754
2810
|
*/
|
|
2755
2811
|
paletteBlockLines(cols2) {
|
|
2756
2812
|
if (!this.paletteOpen()) return [];
|
|
2757
|
-
const rows = this.paletteLines(cols2);
|
|
2813
|
+
const rows = this.paletteLines(cols2).map((r) => this.clampVisible(r, Math.max(1, cols2 - 1)));
|
|
2758
2814
|
const reserved = Math.max(this.commands.length, rows.length);
|
|
2759
2815
|
while (rows.length < reserved) rows.push("");
|
|
2760
2816
|
return rows;
|
|
@@ -2823,11 +2879,13 @@ var Tui = class _Tui {
|
|
|
2823
2879
|
if (!this.started || this.takeoverHandler) return;
|
|
2824
2880
|
const cols2 = process.stdout.columns || 80;
|
|
2825
2881
|
this.moveToRegionTop();
|
|
2826
|
-
process.stdout.write("\x1B[J");
|
|
2827
2882
|
const hudWidths = [];
|
|
2883
|
+
const hudRows = [];
|
|
2884
|
+
const rowCap = Math.max(1, cols2 - 1);
|
|
2828
2885
|
const writeHudRow = (line) => {
|
|
2829
|
-
|
|
2830
|
-
|
|
2886
|
+
const row = this.clampVisible(sanitizeHudRow(line), rowCap);
|
|
2887
|
+
hudWidths.push(this.visibleWidth(row));
|
|
2888
|
+
hudRows.push(row);
|
|
2831
2889
|
};
|
|
2832
2890
|
const previewLines = this.streamPreviewLines(cols2);
|
|
2833
2891
|
for (const line of previewLines) writeHudRow(line);
|
|
@@ -2858,8 +2916,8 @@ var Tui = class _Tui {
|
|
|
2858
2916
|
const prefix = this.promptPrefix();
|
|
2859
2917
|
const pw = this.visibleWidth(prefix);
|
|
2860
2918
|
const lines = this.inputBuffer.split("\n");
|
|
2861
|
-
|
|
2862
|
-
for (let i = 1; i < lines.length; i++)
|
|
2919
|
+
const tail = [prefix + lines[0]];
|
|
2920
|
+
for (let i = 1; i < lines.length; i++) tail.push("\r\n" + lines[i]);
|
|
2863
2921
|
const rowsOf = (len, lead) => Math.max(1, Math.ceil((lead + len) / cols2));
|
|
2864
2922
|
const lineRows = lines.map((l, i) => rowsOf(l.length, i === 0 ? pw : 0));
|
|
2865
2923
|
const inputRows = lineRows.reduce((a, b) => a + b, 0);
|
|
@@ -2874,18 +2932,18 @@ var Tui = class _Tui {
|
|
|
2874
2932
|
for (let i = 0; i < caretLine; i++) caretRow += lineRows[i];
|
|
2875
2933
|
const caretCol = caretCell % cols2;
|
|
2876
2934
|
const paletteBlock = this.paletteBlockLines(cols2);
|
|
2877
|
-
for (const line of paletteBlock)
|
|
2935
|
+
for (const line of paletteBlock) tail.push("\r\n" + line);
|
|
2878
2936
|
if (paletteBlock.length > 0) {
|
|
2879
|
-
|
|
2937
|
+
tail.push("\r");
|
|
2880
2938
|
const up = inputRows - 1 + paletteBlock.length - caretRow;
|
|
2881
|
-
if (up > 0)
|
|
2882
|
-
if (caretCol > 0)
|
|
2939
|
+
if (up > 0) tail.push(`\x1B[${up}A`);
|
|
2940
|
+
if (caretCol > 0) tail.push(`\x1B[${caretCol}C`);
|
|
2883
2941
|
this.lastCursorRow = aboveRows + caretRow;
|
|
2884
2942
|
} else if (this.cursorPos < this.inputBuffer.length) {
|
|
2885
|
-
|
|
2943
|
+
tail.push("\r");
|
|
2886
2944
|
const up = inputRows - 1 - caretRow;
|
|
2887
|
-
if (up > 0)
|
|
2888
|
-
if (caretCol > 0)
|
|
2945
|
+
if (up > 0) tail.push(`\x1B[${up}A`);
|
|
2946
|
+
if (caretCol > 0) tail.push(`\x1B[${caretCol}C`);
|
|
2889
2947
|
this.lastCursorRow = aboveRows + caretRow;
|
|
2890
2948
|
} else {
|
|
2891
2949
|
this.lastCursorRow = aboveRows + (inputRows - 1);
|
|
@@ -2893,6 +2951,8 @@ var Tui = class _Tui {
|
|
|
2893
2951
|
this.drawnHudWidths = hudWidths;
|
|
2894
2952
|
this.lastDrawnCols = cols2;
|
|
2895
2953
|
this.bottomDrawn = true;
|
|
2954
|
+
const out = "\x1B[J" + hudRows.join("\r\n") + "\r\n" + tail.join("");
|
|
2955
|
+
process.stdout.write(out);
|
|
2896
2956
|
}
|
|
2897
2957
|
clearBottom() {
|
|
2898
2958
|
if (!this.bottomDrawn) return;
|
|
@@ -3206,7 +3266,7 @@ var Tui = class _Tui {
|
|
|
3206
3266
|
* resets whenever the label changes.
|
|
3207
3267
|
*/
|
|
3208
3268
|
setStep(label, outTokens) {
|
|
3209
|
-
const next = label && label.trim() ? label.trim() : null;
|
|
3269
|
+
const next = label && label.trim() ? label.replace(/\s+/g, " ").trim() : null;
|
|
3210
3270
|
if (next !== this.step) {
|
|
3211
3271
|
this.step = next;
|
|
3212
3272
|
this.stepStart = Date.now();
|
|
@@ -4032,6 +4092,107 @@ function saveDefaultEndpoint(endpoint) {
|
|
|
4032
4092
|
} catch {
|
|
4033
4093
|
}
|
|
4034
4094
|
}
|
|
4095
|
+
var PKG_NAME = "@standardagents/code";
|
|
4096
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PKG_NAME)}`;
|
|
4097
|
+
var CACHE_REL_DIR = ".config/standardagents-cli";
|
|
4098
|
+
var CACHE_FILE = "update-check.json";
|
|
4099
|
+
var CACHE_TTL_MS = 1e3 * 60 * 60 * 24;
|
|
4100
|
+
var CHECK_TIMEOUT_MS = 4e3;
|
|
4101
|
+
function cacheDir() {
|
|
4102
|
+
return path3.join(homedir(), CACHE_REL_DIR);
|
|
4103
|
+
}
|
|
4104
|
+
function cachePath() {
|
|
4105
|
+
return path3.join(cacheDir(), CACHE_FILE);
|
|
4106
|
+
}
|
|
4107
|
+
function readCache() {
|
|
4108
|
+
try {
|
|
4109
|
+
const raw = fs4.readFileSync(cachePath(), "utf-8");
|
|
4110
|
+
return JSON.parse(raw);
|
|
4111
|
+
} catch {
|
|
4112
|
+
return null;
|
|
4113
|
+
}
|
|
4114
|
+
}
|
|
4115
|
+
function writeCache(latest) {
|
|
4116
|
+
try {
|
|
4117
|
+
const dir = cacheDir();
|
|
4118
|
+
if (!fs4.existsSync(dir)) fs4.mkdirSync(dir, { recursive: true });
|
|
4119
|
+
fs4.writeFileSync(cachePath(), JSON.stringify({ latest, timestamp: Date.now() }));
|
|
4120
|
+
} catch {
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
async function checkForUpdate(currentVersion) {
|
|
4124
|
+
if (!currentVersion) return null;
|
|
4125
|
+
if (process.env.NO_UPDATE_NOTIFIER || process.env.CI) return null;
|
|
4126
|
+
const cached = readCache();
|
|
4127
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
4128
|
+
if (cached.latest !== currentVersion) {
|
|
4129
|
+
return { current: currentVersion, latest: cached.latest };
|
|
4130
|
+
}
|
|
4131
|
+
return null;
|
|
4132
|
+
}
|
|
4133
|
+
const controller = new AbortController();
|
|
4134
|
+
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS);
|
|
4135
|
+
try {
|
|
4136
|
+
const res = await fetch(REGISTRY_URL, {
|
|
4137
|
+
signal: controller.signal,
|
|
4138
|
+
headers: {
|
|
4139
|
+
Accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
|
|
4140
|
+
"User-Agent": `${PKG_NAME}/${currentVersion}`
|
|
4141
|
+
}
|
|
4142
|
+
});
|
|
4143
|
+
if (!res.ok) return null;
|
|
4144
|
+
const data = await res.json();
|
|
4145
|
+
const latest = data["dist-tags"]?.latest;
|
|
4146
|
+
if (!latest) return null;
|
|
4147
|
+
writeCache(latest);
|
|
4148
|
+
if (latest !== currentVersion) {
|
|
4149
|
+
return { current: currentVersion, latest };
|
|
4150
|
+
}
|
|
4151
|
+
return null;
|
|
4152
|
+
} catch {
|
|
4153
|
+
return null;
|
|
4154
|
+
} finally {
|
|
4155
|
+
clearTimeout(timeout);
|
|
4156
|
+
}
|
|
4157
|
+
}
|
|
4158
|
+
async function forceCheckForUpdate(currentVersion) {
|
|
4159
|
+
if (!currentVersion) return null;
|
|
4160
|
+
if (process.env.NO_UPDATE_NOTIFIER || process.env.CI) return null;
|
|
4161
|
+
const controller = new AbortController();
|
|
4162
|
+
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS);
|
|
4163
|
+
try {
|
|
4164
|
+
const res = await fetch(REGISTRY_URL, {
|
|
4165
|
+
signal: controller.signal,
|
|
4166
|
+
headers: {
|
|
4167
|
+
Accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
|
|
4168
|
+
"User-Agent": `${PKG_NAME}/${currentVersion}`
|
|
4169
|
+
}
|
|
4170
|
+
});
|
|
4171
|
+
if (!res.ok) return null;
|
|
4172
|
+
const data = await res.json();
|
|
4173
|
+
const latest = data["dist-tags"]?.latest;
|
|
4174
|
+
if (!latest) return null;
|
|
4175
|
+
writeCache(latest);
|
|
4176
|
+
if (latest !== currentVersion) {
|
|
4177
|
+
return { current: currentVersion, latest };
|
|
4178
|
+
}
|
|
4179
|
+
return null;
|
|
4180
|
+
} catch {
|
|
4181
|
+
return null;
|
|
4182
|
+
} finally {
|
|
4183
|
+
clearTimeout(timeout);
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
function runNpmUpdate() {
|
|
4187
|
+
return new Promise((resolve) => {
|
|
4188
|
+
const child = spawn("npm", ["i", "-g", `${PKG_NAME}@latest`], {
|
|
4189
|
+
stdio: "inherit",
|
|
4190
|
+
shell: true
|
|
4191
|
+
});
|
|
4192
|
+
child.on("close", (code) => resolve(code === 0));
|
|
4193
|
+
child.on("error", () => resolve(false));
|
|
4194
|
+
});
|
|
4195
|
+
}
|
|
4035
4196
|
|
|
4036
4197
|
// src/index.ts
|
|
4037
4198
|
var AGENT_ID = "standard_code_agent";
|
|
@@ -4316,6 +4477,21 @@ ${c.dim}Press Control-C again to exit${c.reset}
|
|
|
4316
4477
|
|
|
4317
4478
|
`);
|
|
4318
4479
|
}
|
|
4480
|
+
const version = readVersion();
|
|
4481
|
+
let updateAvailable = null;
|
|
4482
|
+
{
|
|
4483
|
+
const loading = startLoader("Checking for updates");
|
|
4484
|
+
updateAvailable = await checkForUpdate(version);
|
|
4485
|
+
loading.stop();
|
|
4486
|
+
if (updateAvailable) {
|
|
4487
|
+
stdout.write(
|
|
4488
|
+
` ${c.teal}\u25C7${c.reset} ${c.dim}Update available:${c.reset} ${c.dim}v${updateAvailable.current}${c.reset} \u2192 ${c.bold}v${updateAvailable.latest}${c.reset}
|
|
4489
|
+
${c.dim}Run ${c.reset}${c.bold}npm i -g @standardagents/code@latest${c.reset}${c.dim} to update${c.reset}
|
|
4490
|
+
|
|
4491
|
+
`
|
|
4492
|
+
);
|
|
4493
|
+
}
|
|
4494
|
+
}
|
|
4319
4495
|
const stored = getCredential(endpoint);
|
|
4320
4496
|
let api = stored ? new ApiClient(endpoint, stored.access_token) : null;
|
|
4321
4497
|
let storedCheck = null;
|
|
@@ -4675,7 +4851,8 @@ ${c.bold}why: ${req.requestPermission}${c.reset}` : ""}`,
|
|
|
4675
4851
|
for (const s of subs) {
|
|
4676
4852
|
const status = (s.status || "").trim();
|
|
4677
4853
|
if (status === "idle" || status === "terminated") continue;
|
|
4678
|
-
const
|
|
4854
|
+
const oneLineStatus = status.replace(/\s+/g, " ");
|
|
4855
|
+
const detail = oneLineStatus && oneLineStatus !== "running" ? ` \u2014 ${oneLineStatus.slice(0, 80)}` : "";
|
|
4679
4856
|
activeSubagents.set(s.id, {
|
|
4680
4857
|
label: `${subagentLabel(s, agentTitles)}${detail}`,
|
|
4681
4858
|
agentName: s.agent_name ?? void 0
|
|
@@ -4871,6 +5048,7 @@ ${c.bold}why: ${req.requestPermission}${c.reset}` : ""}`,
|
|
|
4871
5048
|
},
|
|
4872
5049
|
{ name: "background", label: "Background processes", hint: "list / stop", run: () => runProcessMenu(tui, bgMgr) },
|
|
4873
5050
|
{ name: "keybindings", label: "Keyboard shortcuts", run: () => showKeybindings(tui) },
|
|
5051
|
+
{ name: "update", label: "Check for updates", hint: "check npm for a newer version", run: () => runUpdateCommand(tui) },
|
|
4874
5052
|
{ name: "logout", label: "Sign out", hint: "delete the saved token & quit", run: () => logout() },
|
|
4875
5053
|
{ name: "quit", label: "Quit", run: () => quit() }
|
|
4876
5054
|
]);
|
|
@@ -5127,6 +5305,36 @@ function showKeybindings(tui) {
|
|
|
5127
5305
|
tui.print(`${c.gray} \u2190${c.reset} from the start of the input: select the [\u2699 n bg] badge (enter opens it)`);
|
|
5128
5306
|
tui.print(`${c.gray} ctrl-c${c.reset} quit`);
|
|
5129
5307
|
}
|
|
5308
|
+
async function runUpdateCommand(tui) {
|
|
5309
|
+
const version = readVersion();
|
|
5310
|
+
const result = await forceCheckForUpdate(version);
|
|
5311
|
+
if (!result) {
|
|
5312
|
+
tui.print(`${c.green}\u2713${c.reset} ${c.gray}@standardagents/code${c.reset} is up to date (v${version})`);
|
|
5313
|
+
return;
|
|
5314
|
+
}
|
|
5315
|
+
const { latest } = result;
|
|
5316
|
+
tui.print(`
|
|
5317
|
+
${c.yellow}\u27F3${c.reset} Update available: ${c.gray}v${version}${c.reset} \u2192 ${c.green}v${latest}${c.reset}`);
|
|
5318
|
+
const choice = await tui.select(`Update now with \`npm i -g @standardagents/code@latest\`?`, [
|
|
5319
|
+
{ label: "Yes, update now", value: "yes" },
|
|
5320
|
+
{ label: "No, skip", value: "no" }
|
|
5321
|
+
]);
|
|
5322
|
+
if (choice === "yes") {
|
|
5323
|
+
tui.print(` ${c.gray}Running npm i -g @standardagents/code@latest\u2026${c.reset}`);
|
|
5324
|
+
try {
|
|
5325
|
+
const ok = await runNpmUpdate();
|
|
5326
|
+
if (ok) {
|
|
5327
|
+
tui.print(` ${c.green}\u2713${c.reset} Updated to v${latest}. Restart to use the new version.`);
|
|
5328
|
+
} else {
|
|
5329
|
+
tui.print(` ${c.red}\u2717${c.reset} Update failed.`);
|
|
5330
|
+
}
|
|
5331
|
+
} catch (e) {
|
|
5332
|
+
tui.print(` ${c.red}\u2717${c.reset} Update failed: ${e}`);
|
|
5333
|
+
}
|
|
5334
|
+
} else {
|
|
5335
|
+
tui.print(` ${c.gray}Skipped. Run /update later.${c.reset}`);
|
|
5336
|
+
}
|
|
5337
|
+
}
|
|
5130
5338
|
async function runProcessMenu(tui, bg) {
|
|
5131
5339
|
const procs = await bg.list();
|
|
5132
5340
|
if (!procs.length) {
|