@standardagents/code 0.5.1 → 0.6.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 +198 -73
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { stdout, stdin } from 'process';
|
|
|
8
8
|
import fsp from 'fs/promises';
|
|
9
9
|
import crypto from 'crypto';
|
|
10
10
|
import readline from 'readline';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
11
12
|
|
|
12
13
|
// src/api.ts
|
|
13
14
|
function classifyConnectError(err, endpoint) {
|
|
@@ -795,13 +796,7 @@ var Bridge = class {
|
|
|
795
796
|
this.hooks.onStatus?.(callKey, null);
|
|
796
797
|
}
|
|
797
798
|
if (result.ok) {
|
|
798
|
-
const display
|
|
799
|
-
let detail;
|
|
800
|
-
if (req.tool === "edit_file") {
|
|
801
|
-
detail = diffLines(String(req.args.old_string ?? ""), String(req.args.new_string ?? ""));
|
|
802
|
-
} else if (req.tool === "write_file") {
|
|
803
|
-
detail = newFileLines(String(req.args.content ?? ""));
|
|
804
|
-
}
|
|
799
|
+
const { display, detail } = activityPresentation(req, summary);
|
|
805
800
|
this.hooks.onActivity(`\u2713 ${display}${detailSuffix(req.tool, result.result)}`, detail);
|
|
806
801
|
this.respond(req, true, result.result ?? "");
|
|
807
802
|
} else {
|
|
@@ -819,6 +814,35 @@ function permissionKey(req) {
|
|
|
819
814
|
if (action === "list_tools") return `mcp:${server}/list`;
|
|
820
815
|
return `mcp:${server}/${String(a.tool || "?")}`;
|
|
821
816
|
}
|
|
817
|
+
var DIM2 = "\x1B[2m";
|
|
818
|
+
var RESET2 = "\x1B[0m";
|
|
819
|
+
function activityPresentation(req, summary) {
|
|
820
|
+
const a = req.args;
|
|
821
|
+
const cols2 = Math.max(40, process.stdout.columns || 80);
|
|
822
|
+
if (req.tool === "bash") {
|
|
823
|
+
return { display: `bash: ${highlightBash(oneLineCommand(String(a.command ?? ""), cols2 - 20))}` };
|
|
824
|
+
}
|
|
825
|
+
if (req.tool === "edit_file") {
|
|
826
|
+
return { display: summary, detail: diffLines(String(a.old_string ?? ""), String(a.new_string ?? "")) };
|
|
827
|
+
}
|
|
828
|
+
if (req.tool === "write_file") {
|
|
829
|
+
return { display: summary, detail: newFileLines(String(a.content ?? "")) };
|
|
830
|
+
}
|
|
831
|
+
if (req.tool === "background_process") {
|
|
832
|
+
const action = String(a.action || "list");
|
|
833
|
+
const id = a.id ? ` ${String(a.id)}` : "";
|
|
834
|
+
const display = action === "start" ? "bg start" : `bg ${action}${id}`;
|
|
835
|
+
const detail = [];
|
|
836
|
+
if (action === "start" && a.command) {
|
|
837
|
+
detail.push(` ${DIM2}${oneLineCommand(String(a.command), cols2 - 8)}${RESET2}`);
|
|
838
|
+
}
|
|
839
|
+
if (typeof a.description === "string" && a.description.trim()) {
|
|
840
|
+
detail.push(` ${DIM2}${oneLineCommand(a.description, cols2 - 8)}${RESET2}`);
|
|
841
|
+
}
|
|
842
|
+
return { display, detail: detail.length ? detail : void 0 };
|
|
843
|
+
}
|
|
844
|
+
return { display: summary };
|
|
845
|
+
}
|
|
822
846
|
function describe(req) {
|
|
823
847
|
const a = req.args;
|
|
824
848
|
switch (req.tool) {
|
|
@@ -845,6 +869,12 @@ function describe(req) {
|
|
|
845
869
|
return `skill ${a.skill}: run ${a.entry}`;
|
|
846
870
|
case "bash":
|
|
847
871
|
return `bash: ${oneLineCommand(String(a.command ?? ""), 80)}`;
|
|
872
|
+
case "background_process": {
|
|
873
|
+
const action = String(a.action || "list");
|
|
874
|
+
if (action === "start") return `bg start: ${oneLineCommand(String(a.command ?? ""), 80)}`;
|
|
875
|
+
if (action === "list") return "bg list";
|
|
876
|
+
return `bg ${action}${a.id ? ` ${String(a.id)}` : ""}`;
|
|
877
|
+
}
|
|
848
878
|
default:
|
|
849
879
|
return `${req.tool} ${JSON.stringify(a).slice(0, 80)}`;
|
|
850
880
|
}
|
|
@@ -1888,7 +1918,7 @@ var LAZY_MS = 320;
|
|
|
1888
1918
|
var LAZY_PERIOD = 200;
|
|
1889
1919
|
var FAST_PERIOD = 70;
|
|
1890
1920
|
var BOLD = "\x1B[1m";
|
|
1891
|
-
var
|
|
1921
|
+
var DIM3 = "\x1B[2m";
|
|
1892
1922
|
var OFF = "\x1B[22m";
|
|
1893
1923
|
function glyphAt(slot, bucket) {
|
|
1894
1924
|
let h = (slot + 1) * 2654435761 ^ (bucket + 1) * 40503;
|
|
@@ -1960,7 +1990,7 @@ var WordMill = class {
|
|
|
1960
1990
|
} else if (t < s.land) {
|
|
1961
1991
|
const age = t - s.start;
|
|
1962
1992
|
const period = age < LAZY_MS ? LAZY_PERIOD : FAST_PERIOD;
|
|
1963
|
-
out += `${
|
|
1993
|
+
out += `${DIM3}${glyphAt(i, Math.floor(t / period))}${OFF}`;
|
|
1964
1994
|
} else {
|
|
1965
1995
|
const ch = target[i];
|
|
1966
1996
|
if (ch) out += `${BOLD}${ch}${OFF}`;
|
|
@@ -3052,7 +3082,8 @@ var Tui = class _Tui {
|
|
|
3052
3082
|
const t = s.length > max ? s.slice(0, Math.max(0, max - 1)) + "\u2026" : s;
|
|
3053
3083
|
return wrap ? `${lead}${wrap}${t}${C.reset}` : `${lead}${t}`;
|
|
3054
3084
|
};
|
|
3055
|
-
const
|
|
3085
|
+
const leakedMarkup = /<\/?[||]DSML[||]|^\s*\[\/?SESSION\]\s*<?\s*$/;
|
|
3086
|
+
const realLines = (text) => text.replace(/\r/g, "").split("\n").filter((l) => l.trim() !== "" && !leakedMarkup.test(l));
|
|
3056
3087
|
if (this.streamResponse) {
|
|
3057
3088
|
const all = realLines(this.streamResponse);
|
|
3058
3089
|
const shown = all.slice(-20);
|
|
@@ -3500,7 +3531,7 @@ function appendHistory(store, threadId, history, text) {
|
|
|
3500
3531
|
var ESC = "\x1B[";
|
|
3501
3532
|
var R = ESC + "0m";
|
|
3502
3533
|
var BOLD2 = ESC + "1m";
|
|
3503
|
-
var
|
|
3534
|
+
var DIM4 = ESC + "2m";
|
|
3504
3535
|
var ITAL = ESC + "3m";
|
|
3505
3536
|
var UNDER = ESC + "4m";
|
|
3506
3537
|
var TEAL = ESC + "38;5;37m";
|
|
@@ -3522,11 +3553,11 @@ function inline(s) {
|
|
|
3522
3553
|
});
|
|
3523
3554
|
s = s.replace(
|
|
3524
3555
|
/\[([^\]]+)\]\(([^)\s]+)\)/g,
|
|
3525
|
-
(_, text, url) => `${CYAN}${UNDER}${text}${R} ${
|
|
3556
|
+
(_, text, url) => `${CYAN}${UNDER}${text}${R} ${DIM4}${url}${R}`
|
|
3526
3557
|
);
|
|
3527
3558
|
s = s.replace(/\*\*([^*]+)\*\*/g, (_, t) => `${BOLD2}${t}${R}`);
|
|
3528
3559
|
s = s.replace(/\*([^*\n]+)\*/g, (_, t) => `${ITAL}${t}${R}`);
|
|
3529
|
-
s = s.replace(/~~([^~]+)~~/g, (_, t) => `${
|
|
3560
|
+
s = s.replace(/~~([^~]+)~~/g, (_, t) => `${DIM4}${t}${R}`);
|
|
3530
3561
|
s = s.replace(/\x00(\d+)\x00/g, (_, i) => `${TEAL}${codes[+i].replace(/ /g, String.fromCharCode(160))}${R}`);
|
|
3531
3562
|
return s;
|
|
3532
3563
|
}
|
|
@@ -3631,7 +3662,7 @@ function renderMarkdown(src, cols2 = 80) {
|
|
|
3631
3662
|
const quote = line.match(/^\s*>\s?(.*)$/);
|
|
3632
3663
|
if (quote) {
|
|
3633
3664
|
for (const ln of wrapStyled(inline(quote[1]), Math.max(8, cols2 - 2))) {
|
|
3634
|
-
out.push(`${GRAY}\u2502${R} ${
|
|
3665
|
+
out.push(`${GRAY}\u2502${R} ${DIM4}${ln}${R}`);
|
|
3635
3666
|
}
|
|
3636
3667
|
i++;
|
|
3637
3668
|
continue;
|
|
@@ -4096,8 +4127,10 @@ var PKG_NAME = "@standardagents/code";
|
|
|
4096
4127
|
var REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PKG_NAME)}`;
|
|
4097
4128
|
var CACHE_REL_DIR = ".config/standardagents-cli";
|
|
4098
4129
|
var CACHE_FILE = "update-check.json";
|
|
4099
|
-
var
|
|
4130
|
+
var STATE_FILE = "auto-update.json";
|
|
4131
|
+
var CACHE_TTL_MS = 1e3 * 60 * 60 * 6;
|
|
4100
4132
|
var CHECK_TIMEOUT_MS = 4e3;
|
|
4133
|
+
var IN_FLIGHT_TTL_MS = 15 * 60 * 1e3;
|
|
4101
4134
|
function cacheDir() {
|
|
4102
4135
|
return path3.join(homedir(), CACHE_REL_DIR);
|
|
4103
4136
|
}
|
|
@@ -4120,16 +4153,86 @@ function writeCache(latest) {
|
|
|
4120
4153
|
} catch {
|
|
4121
4154
|
}
|
|
4122
4155
|
}
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
return { current: currentVersion, latest: cached.latest };
|
|
4130
|
-
}
|
|
4156
|
+
function readAutoUpdateState(dir = cacheDir()) {
|
|
4157
|
+
try {
|
|
4158
|
+
const raw = fs4.readFileSync(path3.join(dir, STATE_FILE), "utf-8");
|
|
4159
|
+
const state = JSON.parse(raw);
|
|
4160
|
+
return typeof state?.version === "string" ? state : null;
|
|
4161
|
+
} catch {
|
|
4131
4162
|
return null;
|
|
4132
4163
|
}
|
|
4164
|
+
}
|
|
4165
|
+
function writeAutoUpdateState(state, dir = cacheDir()) {
|
|
4166
|
+
try {
|
|
4167
|
+
if (!fs4.existsSync(dir)) fs4.mkdirSync(dir, { recursive: true });
|
|
4168
|
+
fs4.writeFileSync(path3.join(dir, STATE_FILE), JSON.stringify(state));
|
|
4169
|
+
} catch {
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
function clearAutoUpdateState(dir = cacheDir()) {
|
|
4173
|
+
try {
|
|
4174
|
+
fs4.unlinkSync(path3.join(dir, STATE_FILE));
|
|
4175
|
+
} catch {
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
function detectPackageManager(selfPath = fileURLToPath(import.meta.url), env = process.env) {
|
|
4179
|
+
const norm = selfPath.split(/[\\/]/).join("/");
|
|
4180
|
+
if (!norm.includes("node_modules/@standardagents/code")) return null;
|
|
4181
|
+
const pnpmHome = (env.PNPM_HOME || "").split(/[\\/]/).join("/");
|
|
4182
|
+
if (pnpmHome && norm.startsWith(pnpmHome)) return "pnpm";
|
|
4183
|
+
if (norm.includes("/.pnpm/") || /\/pnpm\/global\//.test(norm)) return "pnpm";
|
|
4184
|
+
if (norm.includes("/.bun/")) return "bun";
|
|
4185
|
+
if (norm.includes("/.config/yarn/") || norm.includes("/.yarn/")) return "yarn";
|
|
4186
|
+
return "npm";
|
|
4187
|
+
}
|
|
4188
|
+
function updateCommand(pm) {
|
|
4189
|
+
switch (pm) {
|
|
4190
|
+
case "pnpm":
|
|
4191
|
+
return { cmd: "pnpm", args: ["add", "-g", `${PKG_NAME}@latest`], display: `pnpm add -g ${PKG_NAME}@latest` };
|
|
4192
|
+
case "yarn":
|
|
4193
|
+
return { cmd: "yarn", args: ["global", "add", `${PKG_NAME}@latest`], display: `yarn global add ${PKG_NAME}@latest` };
|
|
4194
|
+
case "bun":
|
|
4195
|
+
return { cmd: "bun", args: ["add", "-g", `${PKG_NAME}@latest`], display: `bun add -g ${PKG_NAME}@latest` };
|
|
4196
|
+
default:
|
|
4197
|
+
return { cmd: "npm", args: ["i", "-g", `${PKG_NAME}@latest`], display: `npm i -g ${PKG_NAME}@latest` };
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4200
|
+
function decideAutoUpdate(info, opts) {
|
|
4201
|
+
const env = opts.env ?? process.env;
|
|
4202
|
+
if (env.STANDARD_CODE_NO_AUTO_UPDATE) return "disabled";
|
|
4203
|
+
if (!opts.pm) return "dev_checkout";
|
|
4204
|
+
const state = opts.state;
|
|
4205
|
+
if (state && state.version === info.latest) {
|
|
4206
|
+
if (state.exitCode === null) {
|
|
4207
|
+
const now = opts.now ?? Date.now();
|
|
4208
|
+
return now - state.startedAt < IN_FLIGHT_TTL_MS ? "in_flight" : "start";
|
|
4209
|
+
}
|
|
4210
|
+
return state.exitCode === 0 ? "path_shadowed" : "already_failed";
|
|
4211
|
+
}
|
|
4212
|
+
return "start";
|
|
4213
|
+
}
|
|
4214
|
+
function startBackgroundUpdate(latest, pm, dir = cacheDir()) {
|
|
4215
|
+
const startedAt = Date.now();
|
|
4216
|
+
writeAutoUpdateState({ version: latest, startedAt, exitCode: null }, dir);
|
|
4217
|
+
const stateFile = path3.join(dir, STATE_FILE);
|
|
4218
|
+
const { cmd, args } = updateCommand(pm);
|
|
4219
|
+
const script = `const cp=require('child_process');const fs=require('fs');const r=cp.spawnSync(${JSON.stringify(cmd)},${JSON.stringify(args)},{shell:process.platform==='win32',encoding:'utf8'});const out=((r.stdout||'')+(r.stderr||'')).slice(-2000);fs.writeFileSync(${JSON.stringify(stateFile)},JSON.stringify({version:${JSON.stringify(latest)},startedAt:${startedAt},exitCode:r.status==null?-1:r.status,finishedAt:Date.now(),output:out}));`;
|
|
4220
|
+
try {
|
|
4221
|
+
const child = spawn(process.execPath, ["-e", script], { detached: true, stdio: "ignore" });
|
|
4222
|
+
child.unref();
|
|
4223
|
+
return true;
|
|
4224
|
+
} catch {
|
|
4225
|
+
writeAutoUpdateState({ version: latest, startedAt, exitCode: -1, finishedAt: Date.now() }, dir);
|
|
4226
|
+
return false;
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
function consumeAppliedUpdate(currentVersion, dir = cacheDir()) {
|
|
4230
|
+
const state = readAutoUpdateState(dir);
|
|
4231
|
+
if (!state || state.version !== currentVersion) return null;
|
|
4232
|
+
clearAutoUpdateState(dir);
|
|
4233
|
+
return state.exitCode === 0 ? state : null;
|
|
4234
|
+
}
|
|
4235
|
+
async function fetchLatest(currentVersion) {
|
|
4133
4236
|
const controller = new AbortController();
|
|
4134
4237
|
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS);
|
|
4135
4238
|
try {
|
|
@@ -4142,55 +4245,48 @@ async function checkForUpdate(currentVersion) {
|
|
|
4142
4245
|
});
|
|
4143
4246
|
if (!res.ok) return null;
|
|
4144
4247
|
const data = await res.json();
|
|
4145
|
-
|
|
4146
|
-
if (!latest) return null;
|
|
4147
|
-
writeCache(latest);
|
|
4148
|
-
if (latest !== currentVersion) {
|
|
4149
|
-
return { current: currentVersion, latest };
|
|
4150
|
-
}
|
|
4151
|
-
return null;
|
|
4248
|
+
return data["dist-tags"]?.latest ?? null;
|
|
4152
4249
|
} catch {
|
|
4153
4250
|
return null;
|
|
4154
4251
|
} finally {
|
|
4155
4252
|
clearTimeout(timeout);
|
|
4156
4253
|
}
|
|
4157
4254
|
}
|
|
4158
|
-
async function
|
|
4255
|
+
async function checkForUpdate(currentVersion) {
|
|
4159
4256
|
if (!currentVersion) return null;
|
|
4160
4257
|
if (process.env.NO_UPDATE_NOTIFIER || process.env.CI) return null;
|
|
4161
|
-
const
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
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 };
|
|
4258
|
+
const cached = readCache();
|
|
4259
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
4260
|
+
if (cached.latest !== currentVersion) {
|
|
4261
|
+
return { current: currentVersion, latest: cached.latest };
|
|
4178
4262
|
}
|
|
4179
4263
|
return null;
|
|
4180
|
-
} catch {
|
|
4181
|
-
return null;
|
|
4182
|
-
} finally {
|
|
4183
|
-
clearTimeout(timeout);
|
|
4184
4264
|
}
|
|
4265
|
+
const latest = await fetchLatest(currentVersion);
|
|
4266
|
+
if (!latest) return null;
|
|
4267
|
+
writeCache(latest);
|
|
4268
|
+
return latest !== currentVersion ? { current: currentVersion, latest } : null;
|
|
4269
|
+
}
|
|
4270
|
+
async function forceCheckForUpdate(currentVersion) {
|
|
4271
|
+
if (!currentVersion) return null;
|
|
4272
|
+
if (process.env.NO_UPDATE_NOTIFIER || process.env.CI) return null;
|
|
4273
|
+
const latest = await fetchLatest(currentVersion);
|
|
4274
|
+
if (!latest) return null;
|
|
4275
|
+
writeCache(latest);
|
|
4276
|
+
return latest !== currentVersion ? { current: currentVersion, latest } : null;
|
|
4185
4277
|
}
|
|
4186
|
-
function
|
|
4278
|
+
function runUpdate(pm) {
|
|
4187
4279
|
return new Promise((resolve) => {
|
|
4188
|
-
const
|
|
4189
|
-
|
|
4190
|
-
shell:
|
|
4280
|
+
const { cmd, args } = updateCommand(pm);
|
|
4281
|
+
const child = spawn(cmd, args, {
|
|
4282
|
+
shell: process.platform === "win32",
|
|
4283
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
4191
4284
|
});
|
|
4192
|
-
|
|
4193
|
-
child.on("
|
|
4285
|
+
let out = "";
|
|
4286
|
+
child.stdout?.on("data", (d) => out += d);
|
|
4287
|
+
child.stderr?.on("data", (d) => out += d);
|
|
4288
|
+
child.on("close", (code) => resolve({ ok: code === 0, output: out }));
|
|
4289
|
+
child.on("error", (err) => resolve({ ok: false, output: String(err) }));
|
|
4194
4290
|
});
|
|
4195
4291
|
}
|
|
4196
4292
|
|
|
@@ -4483,13 +4579,36 @@ ${c.dim}Press Control-C again to exit${c.reset}
|
|
|
4483
4579
|
const loading = startLoader("Checking for updates");
|
|
4484
4580
|
updateAvailable = await checkForUpdate(version);
|
|
4485
4581
|
loading.stop();
|
|
4582
|
+
const applied = consumeAppliedUpdate(version);
|
|
4583
|
+
if (applied) {
|
|
4584
|
+
stdout.write(` ${c.green}\u2713${c.reset} ${c.dim}Standard Code updated to v${version}.${c.reset}
|
|
4585
|
+
|
|
4586
|
+
`);
|
|
4587
|
+
}
|
|
4486
4588
|
if (updateAvailable) {
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4589
|
+
const pm = detectPackageManager();
|
|
4590
|
+
const decision = decideAutoUpdate(updateAvailable, { state: readAutoUpdateState(), pm });
|
|
4591
|
+
if (decision === "start" && pm && startBackgroundUpdate(updateAvailable.latest, pm)) {
|
|
4592
|
+
stdout.write(
|
|
4593
|
+
` ${c.teal}\u27F3${c.reset} ${c.dim}Standard Code ${c.reset}${c.bold}v${updateAvailable.latest}${c.reset}${c.dim} is installing in the background \u2014 it applies on your next launch.${c.reset}
|
|
4490
4594
|
|
|
4491
4595
|
`
|
|
4492
|
-
|
|
4596
|
+
);
|
|
4597
|
+
} else if (decision === "in_flight") {
|
|
4598
|
+
stdout.write(
|
|
4599
|
+
` ${c.teal}\u27F3${c.reset} ${c.dim}Standard Code v${updateAvailable.latest} is still installing in the background.${c.reset}
|
|
4600
|
+
|
|
4601
|
+
`
|
|
4602
|
+
);
|
|
4603
|
+
} else {
|
|
4604
|
+
const display = updateCommand(pm ?? "npm").display;
|
|
4605
|
+
stdout.write(
|
|
4606
|
+
` ${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}
|
|
4607
|
+
${c.dim}Run ${c.reset}${c.bold}${display}${c.reset}${c.dim} to update${c.reset}
|
|
4608
|
+
|
|
4609
|
+
`
|
|
4610
|
+
);
|
|
4611
|
+
}
|
|
4493
4612
|
}
|
|
4494
4613
|
}
|
|
4495
4614
|
const stored = getCredential(endpoint);
|
|
@@ -4619,6 +4738,7 @@ ${c.dim}Press Control-C again to exit${c.reset}
|
|
|
4619
4738
|
await runInteractive(tui, api, threadId, projectDir, machine, resumed, historySeed);
|
|
4620
4739
|
historySeed = threadId;
|
|
4621
4740
|
threadId = await api.createThread(AGENT_ID, tags);
|
|
4741
|
+
await api.kvSet(threadId, "lease_supersedes", historySeed);
|
|
4622
4742
|
resumed = false;
|
|
4623
4743
|
}
|
|
4624
4744
|
}
|
|
@@ -5048,7 +5168,7 @@ ${c.bold}why: ${req.requestPermission}${c.reset}` : ""}`,
|
|
|
5048
5168
|
},
|
|
5049
5169
|
{ name: "background", label: "Background processes", hint: "list / stop", run: () => runProcessMenu(tui, bgMgr) },
|
|
5050
5170
|
{ name: "keybindings", label: "Keyboard shortcuts", run: () => showKeybindings(tui) },
|
|
5051
|
-
{ name: "update", label: "Check for updates", hint: "check
|
|
5171
|
+
{ name: "update", label: "Check for updates", hint: "check for a newer version", run: () => runUpdateCommand(tui) },
|
|
5052
5172
|
{ name: "logout", label: "Sign out", hint: "delete the saved token & quit", run: () => logout() },
|
|
5053
5173
|
{ name: "quit", label: "Quit", run: () => quit() }
|
|
5054
5174
|
]);
|
|
@@ -5315,21 +5435,26 @@ async function runUpdateCommand(tui) {
|
|
|
5315
5435
|
const { latest } = result;
|
|
5316
5436
|
tui.print(`
|
|
5317
5437
|
${c.yellow}\u27F3${c.reset} Update available: ${c.gray}v${version}${c.reset} \u2192 ${c.green}v${latest}${c.reset}`);
|
|
5318
|
-
const
|
|
5438
|
+
const pm = detectPackageManager();
|
|
5439
|
+
if (!pm) {
|
|
5440
|
+
tui.print(` ${c.gray}This is a source checkout \u2014 pull the repo to update.${c.reset}`);
|
|
5441
|
+
return;
|
|
5442
|
+
}
|
|
5443
|
+
const { display } = updateCommand(pm);
|
|
5444
|
+
const choice = await tui.select(`Update now with \`${display}\`?`, [
|
|
5319
5445
|
{ label: "Yes, update now", value: "yes" },
|
|
5320
5446
|
{ label: "No, skip", value: "no" }
|
|
5321
5447
|
]);
|
|
5322
5448
|
if (choice === "yes") {
|
|
5323
|
-
tui.print(` ${c.gray}Running
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
}
|
|
5329
|
-
|
|
5449
|
+
tui.print(` ${c.gray}Running ${display}\u2026${c.reset}`);
|
|
5450
|
+
const { ok, output: pmOutput } = await runUpdate(pm);
|
|
5451
|
+
if (ok) {
|
|
5452
|
+
tui.print(` ${c.green}\u2713${c.reset} Updated to v${latest}. Restart to use the new version.`);
|
|
5453
|
+
} else {
|
|
5454
|
+
tui.print(` ${c.red}\u2717${c.reset} Update failed:`);
|
|
5455
|
+
for (const line of pmOutput.trim().split("\n").slice(-6)) {
|
|
5456
|
+
tui.print(` ${c.dim}${line}${c.reset}`);
|
|
5330
5457
|
}
|
|
5331
|
-
} catch (e) {
|
|
5332
|
-
tui.print(` ${c.red}\u2717${c.reset} Update failed: ${e}`);
|
|
5333
5458
|
}
|
|
5334
5459
|
} else {
|
|
5335
5460
|
tui.print(` ${c.gray}Skipped. Run /update later.${c.reset}`);
|