@standardagents/code 0.11.2 → 0.11.4
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 +31 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -579,14 +579,24 @@ var ApiClient = class {
|
|
|
579
579
|
// Backed by the instance's /api/users/me/kv store. This is where the machine
|
|
580
580
|
// registry lives: which machines (laptops / VPS daemons) belong to this
|
|
581
581
|
// account, and which projects each machine has.
|
|
582
|
-
/**
|
|
583
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Read one value from the signed-in user's account-wide KV (null if absent).
|
|
584
|
+
* A missing key is a 200 `{value: null}` from the instance, so any THROWN
|
|
585
|
+
* error is a transport/server failure, never "not found". `strict` rethrows
|
|
586
|
+
* those failures — required by read-modify-write callers (the machine
|
|
587
|
+
* registry), where treating a failed read as "no record yet" would overwrite
|
|
588
|
+
* the real record with a fresh empty one (this wiped a machine's whole
|
|
589
|
+
* project list during a deploy window). Non-strict callers (pollers,
|
|
590
|
+
* display overlays) keep the lenient null.
|
|
591
|
+
*/
|
|
592
|
+
async userKvGet(key, opts) {
|
|
584
593
|
try {
|
|
585
594
|
const res = await this.json(
|
|
586
595
|
`/api/users/me/kv?key=${encodeURIComponent(key)}`
|
|
587
596
|
);
|
|
588
597
|
return res?.value ?? null;
|
|
589
|
-
} catch {
|
|
598
|
+
} catch (error) {
|
|
599
|
+
if (opts?.strict) throw error;
|
|
590
600
|
return null;
|
|
591
601
|
}
|
|
592
602
|
}
|
|
@@ -6587,8 +6597,8 @@ function parseMachineRecord(value) {
|
|
|
6587
6597
|
updated_at: typeof r.updated_at === "number" ? r.updated_at : 0
|
|
6588
6598
|
};
|
|
6589
6599
|
}
|
|
6590
|
-
async function loadRawMachine(api, machineId) {
|
|
6591
|
-
return parseMachineRecord(await api.userKvGet(machineKey(machineId)));
|
|
6600
|
+
async function loadRawMachine(api, machineId, opts) {
|
|
6601
|
+
return parseMachineRecord(await api.userKvGet(machineKey(machineId), opts));
|
|
6592
6602
|
}
|
|
6593
6603
|
async function loadMachines(api) {
|
|
6594
6604
|
const entries = await api.userKvList(KEY_PREFIX);
|
|
@@ -6715,7 +6725,7 @@ function newRecord(identity) {
|
|
|
6715
6725
|
};
|
|
6716
6726
|
}
|
|
6717
6727
|
async function updateOwnMachineRecord(api, identity, mutate) {
|
|
6718
|
-
const existing = await loadRawMachine(api, identity.machine_id);
|
|
6728
|
+
const existing = await loadRawMachine(api, identity.machine_id, { strict: true });
|
|
6719
6729
|
const record2 = existing ?? newRecord(identity);
|
|
6720
6730
|
record2.hostname = os8.hostname();
|
|
6721
6731
|
record2.platform = process.platform;
|
|
@@ -7023,7 +7033,7 @@ async function pickDirectory(tui, backend, opts = {}) {
|
|
|
7023
7033
|
return null;
|
|
7024
7034
|
}
|
|
7025
7035
|
spin?.stop();
|
|
7026
|
-
const title = () => `${c2.bold}
|
|
7036
|
+
const title = () => `${c2.bold}Browse ${backend.label}${c2.reset} ${c2.teal}${tail(listing.path, 48)}${c2.reset}` + (showHidden ? ` ${c2.dim}\xB7 hidden shown${c2.reset}` : "");
|
|
7027
7037
|
const footer = (error) => error ? `${c2.yellow}${error}${c2.reset} ${c2.dim}${KEY_HINTS}${c2.reset}` : `${c2.dim}${KEY_HINTS}${c2.reset}`;
|
|
7028
7038
|
const buildItems = () => {
|
|
7029
7039
|
const pageSize = Math.max(5, Math.min(14, (process.stdout.rows || 24) - 9));
|
|
@@ -8625,7 +8635,7 @@ ${c4.dim}Press Control-C again to exit${c4.reset}
|
|
|
8625
8635
|
if (result.hint) stdout.write(` ${c4.dim}${result.hint}${c4.reset}
|
|
8626
8636
|
`);
|
|
8627
8637
|
};
|
|
8628
|
-
stdout.write(`${c4.bold}
|
|
8638
|
+
stdout.write(`${c4.bold}Sign in to ${gradientText("Standard Code")}${c4.reset}
|
|
8629
8639
|
`);
|
|
8630
8640
|
if (`https://${host}` !== PRODUCTION_ENDPOINT) {
|
|
8631
8641
|
stdout.write(`${c4.dim}Connecting to${c4.reset} ${c4.teal}${host}${c4.reset}
|
|
@@ -8737,7 +8747,7 @@ ${c4.dim}Press Control-C again to exit${c4.reset}
|
|
|
8737
8747
|
flow: for (; ; ) {
|
|
8738
8748
|
if (step === "machine") {
|
|
8739
8749
|
const picked = await tui.select(
|
|
8740
|
-
`${c4.bold}
|
|
8750
|
+
`${c4.bold}Where should this session run?${c4.reset} ${c4.dim}\u2191\u2193 \xB7 enter \xB7 esc${c4.reset}`,
|
|
8741
8751
|
[
|
|
8742
8752
|
{
|
|
8743
8753
|
label: `This machine \u2014 ${self ? machineDisplayName(self) : machine}`,
|
|
@@ -8821,7 +8831,7 @@ ${c4.dim}Press Control-C again to exit${c4.reset}
|
|
|
8821
8831
|
items.push({ label: "\uFF0B Start a new session", value: null });
|
|
8822
8832
|
const whereLabel = session.mode === "remote" && session.runner ? `${session.runner.name}:${shortenPath(session.remotePath ?? "")}` : shortDir;
|
|
8823
8833
|
const picked = await tui.select(
|
|
8824
|
-
`${c4.bold}
|
|
8834
|
+
`${c4.bold}Resume a session${c4.reset} ${c4.gray}${whereLabel}${c4.reset} ${c4.dim}\u2191\u2193 \xB7 enter \xB7 esc${c4.reset}`,
|
|
8825
8835
|
items
|
|
8826
8836
|
);
|
|
8827
8837
|
if (picked === void 0) {
|
|
@@ -8847,7 +8857,7 @@ ${c4.dim}Press Control-C again to exit${c4.reset}
|
|
|
8847
8857
|
} else {
|
|
8848
8858
|
if (!agentOverride) {
|
|
8849
8859
|
const picked = await tui.select(
|
|
8850
|
-
`${c4.bold}
|
|
8860
|
+
`${c4.bold}Which agent?${c4.reset} ${c4.dim}\u2191\u2193 \xB7 enter \xB7 esc${c4.reset}`,
|
|
8851
8861
|
AGENT_CHOICES.map((choice) => ({
|
|
8852
8862
|
label: choice.title,
|
|
8853
8863
|
hint: choice.description,
|
|
@@ -8897,7 +8907,7 @@ async function ensureSamaAuth(tui, api) {
|
|
|
8897
8907
|
checking.stop();
|
|
8898
8908
|
if (already) return true;
|
|
8899
8909
|
const picked = await tui.select(
|
|
8900
|
-
`${c4.bold}
|
|
8910
|
+
`${c4.bold}Authenticate with ChatGPT${c4.reset} ${c4.dim}Sama One runs on OpenAI using your own ChatGPT Pro account${c4.reset}`,
|
|
8901
8911
|
[
|
|
8902
8912
|
{
|
|
8903
8913
|
label: "Continue with ChatGPT",
|
|
@@ -8932,7 +8942,7 @@ async function ensureSamaAuth(tui, api) {
|
|
|
8932
8942
|
}
|
|
8933
8943
|
async function runAgentSwitchMenu(tui, api, threadId) {
|
|
8934
8944
|
const picked = await tui.select(
|
|
8935
|
-
`${c4.bold}
|
|
8945
|
+
`${c4.bold}Switch agent${c4.reset} ${c4.dim}takes effect on the next message${c4.reset}`,
|
|
8936
8946
|
AGENT_CHOICES.map((choice) => ({
|
|
8937
8947
|
label: choice.title,
|
|
8938
8948
|
hint: choice.description,
|
|
@@ -8977,7 +8987,7 @@ async function pickLocalProject(tui, api, self, cwd, machineName) {
|
|
|
8977
8987
|
{ label: "\uFF0B New project", hint: "browse or create a directory", value: NEW }
|
|
8978
8988
|
];
|
|
8979
8989
|
const picked = await tui.select(
|
|
8980
|
-
`${c4.bold}
|
|
8990
|
+
`${c4.bold}Project on ${label}${c4.reset} ${c4.dim}\u2191\u2193 \xB7 enter \xB7 esc${c4.reset}`,
|
|
8981
8991
|
items,
|
|
8982
8992
|
{ spaced: true }
|
|
8983
8993
|
);
|
|
@@ -9001,7 +9011,7 @@ async function pickRemoteProject(tui, api, runner) {
|
|
|
9001
9011
|
);
|
|
9002
9012
|
items.push({ label: "\uFF0B New project", hint: "browse or create a directory", value: ENTER_PATH });
|
|
9003
9013
|
const picked = await tui.select(
|
|
9004
|
-
`${c4.bold}
|
|
9014
|
+
`${c4.bold}Project on ${runner.name}${c4.reset} ${c4.dim}\u2191\u2193 \xB7 enter \xB7 esc${c4.reset}`,
|
|
9005
9015
|
items,
|
|
9006
9016
|
{ spaced: true }
|
|
9007
9017
|
);
|
|
@@ -9080,6 +9090,7 @@ async function runInteractive(tui, api, threadId, projectDir, machine, resumed,
|
|
|
9080
9090
|
const runnerName = session.runner?.name ?? "the remote machine";
|
|
9081
9091
|
let currentOwner = null;
|
|
9082
9092
|
let ownershipKnown = false;
|
|
9093
|
+
let ownershipWasOurs = false;
|
|
9083
9094
|
const describeExecOwner = (o) => o?.client_kind === "daemon" ? "the daemon on this machine" : o?.client_name || "another client";
|
|
9084
9095
|
const registry = new ProcessRegistry(api, threadId, machine);
|
|
9085
9096
|
const refreshBgCount = () => {
|
|
@@ -9168,13 +9179,15 @@ async function runInteractive(tui, api, threadId, projectDir, machine, resumed,
|
|
|
9168
9179
|
},
|
|
9169
9180
|
onOwnership: (isOwner, owner2) => {
|
|
9170
9181
|
const wasKnown = ownershipKnown;
|
|
9182
|
+
const moved = !wasKnown || ownershipWasOurs !== isOwner || (currentOwner?.client_id ?? null) !== (owner2?.client_id ?? null);
|
|
9171
9183
|
ownershipKnown = true;
|
|
9184
|
+
ownershipWasOurs = isOwner;
|
|
9172
9185
|
currentOwner = owner2;
|
|
9173
9186
|
if (isOwner) {
|
|
9174
9187
|
bridge?.setClaim("takeover");
|
|
9175
9188
|
exec?.writeSessionInfo();
|
|
9176
|
-
if (wasKnown) tui.print(`${c4.dim}Tool execution moved to this terminal.${c4.reset}`);
|
|
9177
|
-
} else if (wasKnown) {
|
|
9189
|
+
if (wasKnown && moved) tui.print(`${c4.dim}Tool execution moved to this terminal.${c4.reset}`);
|
|
9190
|
+
} else if (wasKnown && moved) {
|
|
9178
9191
|
tui.print(`${c4.dim}Tool execution moved to ${describeExecOwner(owner2)}.${c4.reset}`);
|
|
9179
9192
|
}
|
|
9180
9193
|
},
|
|
@@ -9577,7 +9590,7 @@ why: ${req.requestPermission}` : ""}`,
|
|
|
9577
9590
|
const cost = fmtCost(q);
|
|
9578
9591
|
const lines = [
|
|
9579
9592
|
"",
|
|
9580
|
-
`${c4.bold}
|
|
9593
|
+
`${c4.bold}\u2726 Add a parallel session${c4.reset}`,
|
|
9581
9594
|
"",
|
|
9582
9595
|
`${dots.join(" ")} ${c4.dim}${q.current} of ${q.current} session${q.current === 1 ? "" : "s"} in use${c4.reset}`
|
|
9583
9596
|
];
|