@proagentstore/cli 0.4.59 → 0.4.61
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/browser-runner/coding/repo-write.js +19 -14
- package/dist/index.js +39 -10
- package/package.json +1 -1
|
@@ -159,10 +159,13 @@ export function switchRepoBranch(workDir, branch) {
|
|
|
159
159
|
* `switchRepoBranch` follows and for the same reason: the cloud's picture of the tree is a read
|
|
160
160
|
* taken moments earlier over a relay, and the write has to be safe against the tree as it IS.
|
|
161
161
|
*
|
|
162
|
-
* dirty refused
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
162
|
+
* dirty NOT refused (#804 — it was at 0.4.59). Unlike a checkout, a fast-forward carries
|
|
163
|
+
* nothing across: an uncommitted edit to a file the incoming commits do not touch is
|
|
164
|
+
* the same edit afterwards, and one they DO touch makes git abort before writing a
|
|
165
|
+
* byte ("Your local changes … would be overwritten"). Untracked files likewise —
|
|
166
|
+
* left alone, unless an incoming commit adds that path, which git refuses by name.
|
|
167
|
+
* The check is therefore git's own, against the real history, and arrives as
|
|
168
|
+
* `error`. Nothing here stashes, cleans or commits on the owner's behalf.
|
|
166
169
|
* off-branch refused when `branch` is given and HEAD is elsewhere. The declared branch is the
|
|
167
170
|
* one the cloud judged stale; pulling whatever the checkout happens to be on would
|
|
168
171
|
* be acting on a verdict about a different ref.
|
|
@@ -193,26 +196,26 @@ export function fastForwardRepo(workDir, opts = {}) {
|
|
|
193
196
|
if (abbrev === "HEAD")
|
|
194
197
|
return { ...base, refused: "detached" };
|
|
195
198
|
const branch = abbrev;
|
|
199
|
+
// Read, reported, never a refusal (see the doc above). A status git will not give is `null`,
|
|
200
|
+
// not `false` — "clean" is a claim, and this is the field the owner's sentence is built from.
|
|
196
201
|
let dirty;
|
|
197
202
|
try {
|
|
198
203
|
dirty = isDirty(workDir);
|
|
199
204
|
}
|
|
200
|
-
catch
|
|
201
|
-
|
|
205
|
+
catch {
|
|
206
|
+
dirty = null;
|
|
202
207
|
}
|
|
203
|
-
if (dirty)
|
|
204
|
-
return { ...base, branch, dirty: true, refused: "dirty" };
|
|
205
208
|
if (want !== null && branch !== want)
|
|
206
|
-
return { ...base, branch, refused: "off-branch" };
|
|
209
|
+
return { ...base, branch, dirty, refused: "off-branch" };
|
|
207
210
|
let upstream;
|
|
208
211
|
try {
|
|
209
212
|
upstream = git(workDir, ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"]).trim();
|
|
210
213
|
}
|
|
211
214
|
catch {
|
|
212
|
-
return { ...base, branch, refused: "no-upstream" };
|
|
215
|
+
return { ...base, branch, dirty, refused: "no-upstream" };
|
|
213
216
|
}
|
|
214
217
|
if (!upstream)
|
|
215
|
-
return { ...base, branch, refused: "no-upstream" };
|
|
218
|
+
return { ...base, branch, dirty, refused: "no-upstream" };
|
|
216
219
|
let from;
|
|
217
220
|
try {
|
|
218
221
|
from = git(workDir, ["rev-parse", "HEAD"]).trim() || null;
|
|
@@ -226,9 +229,11 @@ export function fastForwardRepo(workDir, opts = {}) {
|
|
|
226
229
|
git(workDir, gitWriteArgv("fast-forward"), { timeout: 30_000, env: networkGitEnv() });
|
|
227
230
|
}
|
|
228
231
|
catch (e) {
|
|
229
|
-
// `--ff-only` refused,
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
+
// `--ff-only` refused, an incoming commit would overwrite a local change or an untracked
|
|
233
|
+
// path, the network failed, or auth was needed and (correctly) not prompted for. In every
|
|
234
|
+
// case git left the tree as it was; the sentence says which, and names the file when there
|
|
235
|
+
// is one.
|
|
236
|
+
return { ...base, branch, upstream, from, to: from, dirty, error: gitFailureLine(e) };
|
|
232
237
|
}
|
|
233
238
|
// CONFIRM, do not assume — read HEAD back and count what arrived from git, not from the
|
|
234
239
|
// exit code.
|
package/dist/index.js
CHANGED
|
@@ -1220,6 +1220,18 @@ function shouldRegisterOnOpen(reconnect, alreadyRegistered) {
|
|
|
1220
1220
|
function pendingRegistrations(attached, registered) {
|
|
1221
1221
|
return [...attached].filter((id) => !registered.has(id));
|
|
1222
1222
|
}
|
|
1223
|
+
function partitionByPin(instances, thisNode, alsoKnownAs = []) {
|
|
1224
|
+
const here = [];
|
|
1225
|
+
const elsewhere = [];
|
|
1226
|
+
for (const inst of instances) (isEligible(inst, thisNode, alsoKnownAs) ? here : elsewhere).push(inst);
|
|
1227
|
+
return { here, elsewhere };
|
|
1228
|
+
}
|
|
1229
|
+
function registrationStatus(attached, registered) {
|
|
1230
|
+
const ids = [...attached];
|
|
1231
|
+
const have = ids.filter((id) => registered.has(id)).length;
|
|
1232
|
+
const total = ids.length;
|
|
1233
|
+
return { agents: `${have}/${total}`, state: have === total ? "ok" : have === 0 ? "fail" : "partial" };
|
|
1234
|
+
}
|
|
1223
1235
|
function instanceLabel(inst) {
|
|
1224
1236
|
const short = `${inst.id.slice(0, 8)}\u2026`;
|
|
1225
1237
|
return inst.name ? `${inst.name} (${short})` : short;
|
|
@@ -1289,14 +1301,13 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
|
|
|
1289
1301
|
return false;
|
|
1290
1302
|
}
|
|
1291
1303
|
};
|
|
1304
|
+
const attached = /* @__PURE__ */ new Map();
|
|
1305
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
1292
1306
|
const reportRegistration = () => {
|
|
1293
|
-
const agents =
|
|
1294
|
-
const state = registered.size === instanceIds.length ? "ok" : registered.size === 0 ? "fail" : "partial";
|
|
1307
|
+
const { agents, state } = registrationStatus(attached.keys(), registered);
|
|
1295
1308
|
writeLine(formatStatusLine({ registration: state, agents, reason: state === "ok" ? void 0 : lastRegisterError }));
|
|
1296
1309
|
};
|
|
1297
1310
|
for (const id of instanceIds) await registerRuntime(id);
|
|
1298
|
-
const attached = /* @__PURE__ */ new Map();
|
|
1299
|
-
const blocked = /* @__PURE__ */ new Set();
|
|
1300
1311
|
const attach = (id, label = `${id.slice(0, 8)}\u2026`) => {
|
|
1301
1312
|
if (attached.has(id)) return;
|
|
1302
1313
|
const mintToken = () => requestPags("POST", `/v1/relay/${apiPathSegment(id)}/token`, { ...opts, pagsToken }, {}).then((r) => r.token);
|
|
@@ -1339,7 +1350,8 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
|
|
|
1339
1350
|
};
|
|
1340
1351
|
for (const id of instanceIds) attach(id, "");
|
|
1341
1352
|
reportRegistration();
|
|
1342
|
-
|
|
1353
|
+
const startup = registrationStatus(attached.keys(), registered);
|
|
1354
|
+
writeLine(startup.state === "ok" ? `Runtime registered with PAGS \u2713 (${startup.agents} agents)` : `Runtime registration incomplete: ${startup.agents} agents \u2014 retried on each relay (re)connect${watchInstances ? " and every 20s while this runs" : ""}.`);
|
|
1343
1355
|
writeLine("");
|
|
1344
1356
|
writeLine("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
1345
1357
|
writeLine(` \u2705 CONNECTED \u2014 WebSocket relay \xB7 ${hostname3()}`);
|
|
@@ -1717,6 +1729,7 @@ var runnerCommand = createRunnerCommand();
|
|
|
1717
1729
|
// src/commands/up.ts
|
|
1718
1730
|
import { createRequire as createRequire2 } from "module";
|
|
1719
1731
|
import { Command as Command8 } from "commander";
|
|
1732
|
+
import { hostname as hostname5 } from "os";
|
|
1720
1733
|
|
|
1721
1734
|
// src/tui.ts
|
|
1722
1735
|
import chalk from "chalk";
|
|
@@ -1888,6 +1901,7 @@ var upCommand = new Command8("up").description("Start the browser runner for all
|
|
|
1888
1901
|
const data = await res.json();
|
|
1889
1902
|
const active = (data.instances || []).filter((i) => i.status === "active");
|
|
1890
1903
|
let instances = active;
|
|
1904
|
+
let elsewhere = [];
|
|
1891
1905
|
if (opts.instance) {
|
|
1892
1906
|
instances = instances.filter((i) => i.id === opts.instance || i.slug === opts.instance);
|
|
1893
1907
|
} else {
|
|
@@ -1904,16 +1918,31 @@ var upCommand = new Command8("up").description("Start the browser runner for all
|
|
|
1904
1918
|
writeLine(" Subscribe to an agent at https://proagentstore.online");
|
|
1905
1919
|
process.exit(1);
|
|
1906
1920
|
}
|
|
1907
|
-
state.instances = instances.map((i) => ({ id: i.id, name: i.name || i.slug || i.id.slice(0, 8) }));
|
|
1908
|
-
printStep(`Found ${instances.length} instance${instances.length === 1 ? "" : "s"}`, "ok");
|
|
1909
|
-
for (const inst of state.instances) {
|
|
1910
|
-
writeLine(` ${inst.name} (${inst.id.slice(0, 8)}...)`);
|
|
1911
|
-
}
|
|
1912
1921
|
await maybeClaimMachineNames({
|
|
1913
1922
|
token: session.token,
|
|
1914
1923
|
apiBase: API_BASE3,
|
|
1915
1924
|
headless: opts.headless
|
|
1916
1925
|
}).catch(() => void 0);
|
|
1926
|
+
if (!opts.instance) {
|
|
1927
|
+
const split = partitionByPin(instances, hostname5(), loadMachineIdentity(hostname5()).names);
|
|
1928
|
+
instances = split.here;
|
|
1929
|
+
elsewhere = split.elsewhere;
|
|
1930
|
+
}
|
|
1931
|
+
if (instances.length === 0) {
|
|
1932
|
+
printStep(`All ${elsewhere.length} of your runtime agents are pinned to other machines`, "ok");
|
|
1933
|
+
for (const inst of elsewhere) writeLine(` ${inst.name || inst.slug || inst.id.slice(0, 8)} \u2192 ${inst.config?.runnerNode}`);
|
|
1934
|
+
writeLine(' They are served there. To run one from this machine, change its "Runs on" pin in the console, then `pags up` again.');
|
|
1935
|
+
process.exit(0);
|
|
1936
|
+
}
|
|
1937
|
+
state.instances = instances.map((i) => ({ id: i.id, name: i.name || i.slug || i.id.slice(0, 8) }));
|
|
1938
|
+
printStep(`Found ${instances.length} instance${instances.length === 1 ? "" : "s"}`, "ok");
|
|
1939
|
+
for (const inst of state.instances) {
|
|
1940
|
+
writeLine(` ${inst.name} (${inst.id.slice(0, 8)}...)`);
|
|
1941
|
+
}
|
|
1942
|
+
if (elsewhere.length) {
|
|
1943
|
+
printStep(`${elsewhere.length} more pinned to other machines \u2014 served there, not attached here`, "ok");
|
|
1944
|
+
for (const inst of elsewhere) writeLine(` ${inst.name || inst.slug || inst.id.slice(0, 8)} \u2192 ${inst.config?.runnerNode}`);
|
|
1945
|
+
}
|
|
1917
1946
|
state.activeInstance = instances.length === 1 ? instances[0].name || instances[0].slug || instances[0].id.slice(0, 8) : `${instances.length} agents`;
|
|
1918
1947
|
printStep(`Connecting ${state.activeInstance}\u2026`, "wait");
|
|
1919
1948
|
await stopRunnerProcesses();
|