@centralu/win32-x64 0.1.0-beta.50 → 0.1.0-beta.51
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/Centralu/centralu.exe
CHANGED
|
Binary file
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
2
|
+
"commit": "5f99652",
|
|
3
3
|
"protocolVersion": 1,
|
|
4
4
|
"hostProof": 1,
|
|
5
5
|
"tokenOnStdin": 1,
|
|
6
6
|
"verifiers": 1,
|
|
7
7
|
"keyPairing": 1,
|
|
8
|
-
"builtAt": "2026-11-
|
|
8
|
+
"builtAt": "2026-11-07T05:43:02.116Z",
|
|
9
9
|
"runtime": "system-node",
|
|
10
10
|
"platform": "win32",
|
|
11
11
|
"arch": "x64"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "centralu",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.51",
|
|
4
4
|
"description": "Run, watch and steer several Claude Code and Codex CLI sessions from one window",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ijun17",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"win32"
|
|
39
39
|
],
|
|
40
40
|
"optionalDependencies": {
|
|
41
|
-
"@centralu/darwin-arm64": "0.1.0-beta.
|
|
42
|
-
"@centralu/linux-arm64": "0.1.0-beta.
|
|
43
|
-
"@centralu/linux-x64": "0.1.0-beta.
|
|
44
|
-
"@centralu/win32-x64": "0.1.0-beta.
|
|
41
|
+
"@centralu/darwin-arm64": "0.1.0-beta.51",
|
|
42
|
+
"@centralu/linux-arm64": "0.1.0-beta.51",
|
|
43
|
+
"@centralu/linux-x64": "0.1.0-beta.51",
|
|
44
|
+
"@centralu/win32-x64": "0.1.0-beta.51"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -43050,7 +43050,7 @@ import { dirname as dirname27, join as join59 } from "node:path";
|
|
|
43050
43050
|
import { mkdirSync as mkdirSync21, readFileSync as readFileSync27, writeSync as writeSync4 } from "node:fs";
|
|
43051
43051
|
|
|
43052
43052
|
// packages/protocol/src/version.generated.ts
|
|
43053
|
-
var APP_VERSION = "0.1.0-beta.
|
|
43053
|
+
var APP_VERSION = "0.1.0-beta.51";
|
|
43054
43054
|
|
|
43055
43055
|
// packages/protocol/src/brand.ts
|
|
43056
43056
|
var APP_NAME = "Centralu";
|
|
@@ -108241,6 +108241,9 @@ function lowestPreset(...presets) {
|
|
|
108241
108241
|
function presetWithin(child, parent) {
|
|
108242
108242
|
return PRESET_RANK[child] <= PRESET_RANK[parent];
|
|
108243
108243
|
}
|
|
108244
|
+
function aboveCallerError(name, child, caller) {
|
|
108245
|
+
return presetWithin(child, caller) ? null : `"${name}" now has more permissions (${child}) than this session (${caller}), so this session cannot give it work. Tell the person.`;
|
|
108246
|
+
}
|
|
108244
108247
|
var PARENT_MAIL = 'To write to it before you finish, call mail with `to: "parent"`. ';
|
|
108245
108248
|
function canMailParent(child, senderId) {
|
|
108246
108249
|
return child.askedBy === senderId && !!child.projectId;
|
|
@@ -114345,6 +114348,7 @@ var START_AGENT_MODEL_CHECK_MS = 3e3;
|
|
|
114345
114348
|
var START_AGENT_SETUP_MS = 2e5;
|
|
114346
114349
|
var START_AGENT_CALL_MS = 27e4;
|
|
114347
114350
|
var ASK_THE_PERSON = "Do not do this with your own subagents instead: tell the person what stopped it and let them decide.";
|
|
114351
|
+
var UNTRUSTED_START = `This session's project is not trusted, so it cannot start agents \u2014 the person can trust it from the project menu. ${ASK_THE_PERSON}`;
|
|
114348
114352
|
function agentStartPending(req, lowMemory) {
|
|
114349
114353
|
return { ok: true, state: "pending", sessionId: req.requestId, sessionName: "", tool: req.detail.tool, ...lowMemory ? { lowMemory } : {} };
|
|
114350
114354
|
}
|
|
@@ -114385,21 +114389,6 @@ var AgentStartGates = class {
|
|
|
114385
114389
|
* many. Counted by `agentCeilingError` with the running children, so starts at once cannot pass the ceiling together.
|
|
114386
114390
|
*/
|
|
114387
114391
|
agentStartReserved = /* @__PURE__ */ new Map();
|
|
114388
|
-
/**
|
|
114389
|
-
* What a child's start rests on in its caller, read once the person allowed it and again once its session exists,
|
|
114390
|
-
* right before its delegation is registered: the caller is still here, its project still registered and trusted
|
|
114391
|
-
* (or the caller is `auto`), and it is still above the agent depth (#867), which `auto` does not open.
|
|
114392
|
-
*/
|
|
114393
|
-
agentStartGateError(callerId, projectId) {
|
|
114394
|
-
const caller = this.host.meta.get(callerId);
|
|
114395
|
-
if (!caller) return "The session that asked is no longer here.";
|
|
114396
|
-
if (projectId === ORCHESTRATOR_PLACE && caller.kind === "orchestrator") return agentDepthRefusal(this.host, callerId, "start agents");
|
|
114397
|
-
const now = this.host.store.projects.listProjects().find((p) => p.id === projectId);
|
|
114398
|
-
if (!now) return "This session's project is no longer registered.";
|
|
114399
|
-
const auto = caller.permissionPreset === "auto";
|
|
114400
|
-
if (now.trusted !== true && !auto) return `This session's project is no longer trusted, so it cannot start agents. ${ASK_THE_PERSON}`;
|
|
114401
|
-
return agentDepthRefusal(this.host, callerId, "start agents");
|
|
114402
|
-
}
|
|
114403
114392
|
/**
|
|
114404
114393
|
* A place under the per-project ceiling, checked and taken in one synchronous step (`agentStartReserved`), for a start
|
|
114405
114394
|
* (`createAgentChild`) or a fork (`forkFor`) that waits on something before its delegation counts the child.
|
|
@@ -114439,6 +114428,16 @@ var AgentStartGates = class {
|
|
|
114439
114428
|
return `${running2} agents ${whose} are already working, the most at once. Wait for one (${wait}) or stop one, then try again.`;
|
|
114440
114429
|
}
|
|
114441
114430
|
};
|
|
114431
|
+
function agentStartGateError(host, callerId, projectId) {
|
|
114432
|
+
const caller = host.meta.get(callerId);
|
|
114433
|
+
if (!caller) return "The session that asked is no longer here.";
|
|
114434
|
+
if (projectId === ORCHESTRATOR_PLACE && caller.kind === "orchestrator") return agentDepthRefusal(host, callerId, "start agents");
|
|
114435
|
+
const now = host.store.projects.listProjects().find((p) => p.id === projectId);
|
|
114436
|
+
if (!now) return "This session's project is no longer registered.";
|
|
114437
|
+
const auto = caller.permissionPreset === "auto";
|
|
114438
|
+
if (now.trusted !== true && !auto) return `This session's project is no longer trusted, so it cannot start agents. ${ASK_THE_PERSON}`;
|
|
114439
|
+
return agentDepthRefusal(host, callerId, "start agents");
|
|
114440
|
+
}
|
|
114442
114441
|
|
|
114443
114442
|
// packages/agent-host/src/sessions/agent-consents.ts
|
|
114444
114443
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
@@ -114866,7 +114865,7 @@ var AgentStartFlow = class {
|
|
|
114866
114865
|
return done2({ ok: false, error: "A session the orchestrator starts works outside any project, so it has no worktree. Start it without one, or hand the work to a project's session with send_to_session." });
|
|
114867
114866
|
}
|
|
114868
114867
|
if (project2.trusted !== true && !this.host.autoBoundaryOpen(callerId, "start in an untrusted project")) {
|
|
114869
|
-
return done2({ ok: false, error:
|
|
114868
|
+
return done2({ ok: false, error: UNTRUSTED_START });
|
|
114870
114869
|
}
|
|
114871
114870
|
const waiting = [...this.host.children.agentStarts.values()].find(
|
|
114872
114871
|
(r5) => !r5.ended && r5.req.callerId === callerId && r5.req.task === opts.task && (!opts.tool || r5.req.tool === opts.tool)
|
|
@@ -114978,7 +114977,7 @@ var AgentStartFlow = class {
|
|
|
114978
114977
|
*/
|
|
114979
114978
|
async createAgentChild(callerId, project2, choice, progress, approvedPreset, requestId) {
|
|
114980
114979
|
const done2 = (r) => ({ done: r });
|
|
114981
|
-
const refused2 = this.
|
|
114980
|
+
const refused2 = agentStartGateError(this.host, callerId, project2.id);
|
|
114982
114981
|
if (refused2) return done2({ ok: false, error: refused2 });
|
|
114983
114982
|
const caller = this.host.meta.get(callerId);
|
|
114984
114983
|
if (approvedPreset && !presetWithin(caller.permissionPreset, approvedPreset)) {
|
|
@@ -115007,10 +115006,6 @@ var AgentStartFlow = class {
|
|
|
115007
115006
|
release();
|
|
115008
115007
|
}
|
|
115009
115008
|
}
|
|
115010
|
-
/** `AgentStartGates.agentStartGateError` (agent-start-gates.ts), kept on the flow for its callers */
|
|
115011
|
-
agentStartGateError(...a) {
|
|
115012
|
-
return this.gates.agentStartGateError(...a);
|
|
115013
|
-
}
|
|
115014
115009
|
/** `AgentStartGates.reservePlace` (agent-start-gates.ts), kept on the flow for its callers */
|
|
115015
115010
|
reservePlace(...a) {
|
|
115016
115011
|
return this.gates.reservePlace(...a);
|
|
@@ -115082,7 +115077,7 @@ var AgentStartFlow = class {
|
|
|
115082
115077
|
recordAgentDepth(this.host, child.id, callerId);
|
|
115083
115078
|
const callerNow = this.host.meta.get(callerId);
|
|
115084
115079
|
const withdrawn = requestId ? this.host.children.agentStarts.get(requestId)?.ended : void 0;
|
|
115085
|
-
const late = (withdrawn && "error" in withdrawn ? `The request was withdrawn while its session was being made. ${withdrawn.error}` : null) ?? this.
|
|
115080
|
+
const late = (withdrawn && "error" in withdrawn ? `The request was withdrawn while its session was being made. ${withdrawn.error}` : null) ?? agentStartGateError(this.host, callerId, project2.id) ?? (callerNow && !presetWithin(child.permissionPreset, callerNow.permissionPreset) ? `This session's permissions were lowered to ${callerNow.permissionPreset} while the session was being made.` : null);
|
|
115086
115081
|
const name = choice.name ?? (worktree ? void 0 : agentName(choice.task));
|
|
115087
115082
|
if (late) return done2(await this.abandonChild(child, late, name));
|
|
115088
115083
|
progress.stage = "created";
|
|
@@ -115757,7 +115752,7 @@ var AgentSessionActions = class {
|
|
|
115757
115752
|
const seat = caller?.projectId ? "project" : caller?.kind === "orchestrator" ? "orchestrator" : null;
|
|
115758
115753
|
const owns = seat === "orchestrator" ? child?.askedBy === callerId : startedHere || !deletingWithoutWorktree && this.host.autoBoundaryOpen(callerId, "session ownership");
|
|
115759
115754
|
if (!caller || !seat || !child || !owns || child.projectId !== caller.projectId) {
|
|
115760
|
-
return { ok: false, error: `${opts.sessionId} is not a session this session started. agent_session works only on sessions start_agent started here.${child ? "" : staleSessionHint(this.host, opts.sessionId, (s) => s.projectId === caller?.projectId && s.id !== callerId && (seat !== "orchestrator" || s.askedBy === callerId))}` };
|
|
115755
|
+
return { ok: false, error: `${opts.sessionId} is not a session this session started. agent_session works only on sessions start_agent started from here.${child ? "" : staleSessionHint(this.host, opts.sessionId, (s) => s.projectId === caller?.projectId && s.id !== callerId && (seat !== "orchestrator" || s.askedBy === callerId))}` };
|
|
115761
115756
|
}
|
|
115762
115757
|
if (opts.sessionId === callerId) return this.flow.agentAtRest(child);
|
|
115763
115758
|
if (opts.action === "answer") return this.host.answerRoutedCard(callerId, child.id, opts.card, opts.text ?? "");
|
|
@@ -115829,12 +115824,8 @@ var AgentSessionActions = class {
|
|
|
115829
115824
|
return { ok: true, state: "deleted", sessionId: child.id, sessionName: child.name, tool: child.tool, branch: r.branch, setAside: r.setAside, ...r.warning ? { warning: r.warning } : {}, ...note2 ? { note: note2 } : {} };
|
|
115830
115825
|
}
|
|
115831
115826
|
case "send": {
|
|
115832
|
-
|
|
115833
|
-
|
|
115834
|
-
ok: false,
|
|
115835
|
-
error: `"${child.name}" now has more permissions (${child.permissionPreset}) than this session (${caller.permissionPreset}), so this session cannot give it work. Tell the person.`
|
|
115836
|
-
};
|
|
115837
|
-
}
|
|
115827
|
+
const above = aboveCallerError(child.name, child.permissionPreset, caller.permissionPreset);
|
|
115828
|
+
if (above) return { ok: false, error: above };
|
|
115838
115829
|
const refused2 = this.host.refusesDelegation(callerId, { sessionId: child.id, projectId: child.projectId }, { tool: "agent_session", target: child.name || child.id, text: opts.text ?? "" });
|
|
115839
115830
|
if (refused2) return { ok: false, error: refused2 };
|
|
115840
115831
|
const from = { sessionId: callerId, name: labelOf(this.host.store.messages, caller) };
|
|
@@ -116182,9 +116173,11 @@ var RemoteAgents = class {
|
|
|
116182
116173
|
if (!caller?.projectId) {
|
|
116183
116174
|
return { ok: false, error: caller?.kind === "orchestrator" ? "The orchestrator starts a session on a linked machine with create_session; start_agent with a machine is for a project's session." : "This session belongs to no project, so it cannot start agents." };
|
|
116184
116175
|
}
|
|
116176
|
+
const project2 = this.host.store.projects.listProjects().find((p) => p.id === caller.projectId);
|
|
116177
|
+
if (!project2) return { ok: false, error: "This session's project is no longer registered." };
|
|
116178
|
+
if (project2.trusted !== true && !this.host.autoBoundaryOpen(callerId, "start in an untrusted project")) return { ok: false, error: UNTRUSTED_START };
|
|
116185
116179
|
const refused2 = this.gateError(callerId);
|
|
116186
116180
|
if (refused2) return { ok: false, error: refused2 };
|
|
116187
|
-
const project2 = this.host.store.projects.listProjects().find((p) => p.id === caller.projectId);
|
|
116188
116181
|
const full = this.places.agentCeilingError(callerId, project2.id);
|
|
116189
116182
|
if (full) return { ok: false, error: full };
|
|
116190
116183
|
const reader = this.host.linkedReader;
|
|
@@ -116377,11 +116370,8 @@ var RemoteAgents = class {
|
|
|
116377
116370
|
case "send": {
|
|
116378
116371
|
const text3 = opts.text?.trim();
|
|
116379
116372
|
if (!text3) return { ok: false, error: "Give the text to send." };
|
|
116380
|
-
const
|
|
116381
|
-
|
|
116382
|
-
if (!presetWithin(childPreset, own)) {
|
|
116383
|
-
return { ok: false, error: `"${rec.name}" now has more permissions (${childPreset}) than this session (${own}), so this session cannot give it work. Tell the person.` };
|
|
116384
|
-
}
|
|
116373
|
+
const above = aboveCallerError(rec.name, rec.preset ?? "normal", this.callerPreset(callerId));
|
|
116374
|
+
if (above) return { ok: false, error: above };
|
|
116385
116375
|
const now = await stateOf();
|
|
116386
116376
|
if (!now.ok) return now;
|
|
116387
116377
|
if (now.running) {
|
|
@@ -116413,16 +116403,8 @@ var RemoteAgents = class {
|
|
|
116413
116403
|
return this.sendAtRest(rec, callerId, text3, label, reader);
|
|
116414
116404
|
}
|
|
116415
116405
|
case "stop": {
|
|
116416
|
-
const
|
|
116417
|
-
if (
|
|
116418
|
-
const held3 = rec.queued;
|
|
116419
|
-
this.setQueued(rec.sessionId, []);
|
|
116420
|
-
const r = await reader.interrupt(rec.sessionId);
|
|
116421
|
-
if (!r.ok) {
|
|
116422
|
-
if (held3) this.setQueued(rec.sessionId, held3);
|
|
116423
|
-
if (owed?.orchestratorId === callerId && !this.host.children.linkedReports.has(rec.sessionId)) this.host.children.setLinkedReport(rec.sessionId, owed);
|
|
116424
|
-
return { ok: false, error: `Could not stop "${rec.name}" on ${rec.machine}: ${bare(r.error)}.` };
|
|
116425
|
-
}
|
|
116406
|
+
const r = await this.interruptFor(rec, callerId, reader);
|
|
116407
|
+
if (!r.ok) return { ok: false, error: `Could not stop "${rec.name}" on ${rec.machine}: ${bare(r.error)}.` };
|
|
116426
116408
|
return { ok: true, state: "stopped", sessionId: rec.sessionId, sessionName: rec.name, tool: rec.tool };
|
|
116427
116409
|
}
|
|
116428
116410
|
case "delete": {
|
|
@@ -116441,14 +116423,9 @@ var RemoteAgents = class {
|
|
|
116441
116423
|
const now = await stateOf();
|
|
116442
116424
|
if (!now.ok) return now;
|
|
116443
116425
|
if (now.running) {
|
|
116444
|
-
const
|
|
116445
|
-
if (
|
|
116446
|
-
|
|
116447
|
-
if (!stopped.ok) {
|
|
116448
|
-
if (owed?.orchestratorId === callerId && !this.host.children.linkedReports.has(rec.sessionId)) this.host.children.setLinkedReport(rec.sessionId, owed);
|
|
116449
|
-
return { ok: false, error: `Could not stop "${rec.name}" on ${rec.machine} before deleting it: ${bare(stopped.error)}.` };
|
|
116450
|
-
}
|
|
116451
|
-
}
|
|
116426
|
+
const stopped = await this.interruptFor(rec, callerId, reader);
|
|
116427
|
+
if (!stopped.ok) return { ok: false, error: `Could not stop "${rec.name}" on ${rec.machine} before deleting it: ${bare(stopped.error)}.` };
|
|
116428
|
+
} else this.setQueued(rec.sessionId, []);
|
|
116452
116429
|
const canClean = typeof reader.deleteAgentChild === "function";
|
|
116453
116430
|
const withWorktree = rec.worktree && canClean ? await reader.deleteAgentChild(rec.sessionId, rec.worktree).catch((e) => ({ ok: false, error: e instanceof Error ? e.message : String(e) })) : void 0;
|
|
116454
116431
|
if (withWorktree && !withWorktree.ok) return { ok: false, error: `Could not delete "${rec.name}" on ${rec.machine}: ${bare(withWorktree.error)}.` };
|
|
@@ -116713,6 +116690,22 @@ var RemoteAgents = class {
|
|
|
116713
116690
|
this.scheduleDrain(rec.sessionId);
|
|
116714
116691
|
return { ok: true, tool: rec.tool, state: "queued", sessionId: rec.sessionId, sessionName: rec.name, queueId: entry.id, position: (same ? held3.indexOf(same) : held3.length) + 1 };
|
|
116715
116692
|
}
|
|
116693
|
+
/**
|
|
116694
|
+
* Stops the child's turn there for a stop or a deletion by the one it would report to: nothing more is owed, and its
|
|
116695
|
+
* end must not send what was held for it. Both are taken down first, as the stopped turn's end can reach the hub before
|
|
116696
|
+
* the machine's answer does, and put back if the stop does not go
|
|
116697
|
+
*/
|
|
116698
|
+
async interruptFor(rec, callerId, reader) {
|
|
116699
|
+
const owed = this.host.children.linkedReports.get(rec.sessionId);
|
|
116700
|
+
if (owed?.orchestratorId === callerId) this.host.children.dropLinkedReport(rec.sessionId);
|
|
116701
|
+
const held3 = this.of(rec.sessionId)?.queued;
|
|
116702
|
+
this.setQueued(rec.sessionId, []);
|
|
116703
|
+
const r = await reader.interrupt(rec.sessionId);
|
|
116704
|
+
if (r.ok) return r;
|
|
116705
|
+
if (held3) this.setQueued(rec.sessionId, held3);
|
|
116706
|
+
if (owed?.orchestratorId === callerId && !this.host.children.linkedReports.has(rec.sessionId)) this.host.children.setLinkedReport(rec.sessionId, owed);
|
|
116707
|
+
return r;
|
|
116708
|
+
}
|
|
116716
116709
|
setQueued(sessionId, queued) {
|
|
116717
116710
|
if (!queued.length && !this.of(sessionId)?.queued) return;
|
|
116718
116711
|
this.save(this.records().map((r) => r.sessionId === sessionId ? { ...r, queued: queued.length ? queued : void 0 } : r));
|
|
@@ -117100,16 +117093,9 @@ Reason, by kind: ${errorKind(why2)} (its words are an error's, kept in this noti
|
|
|
117100
117093
|
for (const key of [...this.toldCards]) if (key.startsWith(`${sessionId}\0`)) this.toldCards.delete(key);
|
|
117101
117094
|
if (this.host.children.linkedReports.has(sessionId)) this.host.children.dropLinkedReport(sessionId);
|
|
117102
117095
|
}
|
|
117103
|
-
/** What start_agent and a send rest on in the caller, read again after a card
|
|
117096
|
+
/** What start_agent and a send rest on in the caller, read again after a card and before each send: a local start's (`agentStartGateError`) */
|
|
117104
117097
|
gateError(callerId) {
|
|
117105
|
-
|
|
117106
|
-
if (!caller) return "The session that asked is no longer here.";
|
|
117107
|
-
const project2 = this.host.store.projects.listProjects().find((p) => p.id === caller.projectId);
|
|
117108
|
-
if (!project2) return "This session's project is no longer registered.";
|
|
117109
|
-
if (project2.trusted !== true && !this.host.autoBoundaryOpen(callerId, "start in an untrusted project")) {
|
|
117110
|
-
return `This session's project is not trusted, so it cannot start agents \u2014 the person can trust it from the project menu. ${ASK_THE_PERSON}`;
|
|
117111
|
-
}
|
|
117112
|
-
return agentDepthRefusal(this.host, callerId, "start agents");
|
|
117098
|
+
return agentStartGateError(this.host, callerId, this.host.meta.get(callerId)?.projectId || null);
|
|
117113
117099
|
}
|
|
117114
117100
|
/** The caller's preset as it is now; `safe` for one gone, so nothing is decided on a preset no one has */
|
|
117115
117101
|
callerPreset(callerId) {
|
|
@@ -122730,10 +122716,6 @@ var MailboxRecords = class {
|
|
|
122730
122716
|
markDelivered(recipient, ids, at2, turnSeq) {
|
|
122731
122717
|
this.update("delivered_at = ?, last_error = NULL, turn_seq = ?", [at2, turnSeq], recipient, ids);
|
|
122732
122718
|
}
|
|
122733
|
-
/** These delivered rows were delivered in the turn `turnSeq` (the delivery began it after it delivered them) */
|
|
122734
|
-
markTurn(recipient, ids, turnSeq) {
|
|
122735
|
-
this.update("turn_seq = ?", [turnSeq], recipient, ids, "delivered_at IS NOT NULL");
|
|
122736
|
-
}
|
|
122737
122719
|
/** Sets why mail waits for the person (`policy`, `loop`, `budget`, `failed`, `uncertain`), or clears it with null */
|
|
122738
122720
|
hold(recipient, ids, why2) {
|
|
122739
122721
|
this.update("held = ?", [why2], recipient, ids);
|
|
@@ -125182,11 +125164,6 @@ var MessageService = class {
|
|
|
125182
125164
|
});
|
|
125183
125165
|
return { needReply, unread: unread2, waiting, held: held3 };
|
|
125184
125166
|
}
|
|
125185
|
-
/** The messages to or from `address`, newest first, as the address reads them (the person's Inbox feed, M6's `mail.inbox`, §12.2). Marks nothing */
|
|
125186
|
-
feed(address, opts) {
|
|
125187
|
-
const found = this.records.feedOf(address, { ...opts.before === void 0 ? {} : { before: opts.before }, limit: opts.limit + 1 });
|
|
125188
|
-
return { items: found.slice(0, opts.limit).map((m) => this.item(m, address, null)), older: found.length > opts.limit };
|
|
125189
|
-
}
|
|
125190
125167
|
/**
|
|
125191
125168
|
* Whether mail that wakes `recipient` waits for it, due or not yet (the debounce makes a message wait a moment before it is due): a turn of its own is
|
|
125192
125169
|
* coming, which a note of the host's should follow. Reads only; mail that is held out or settled is not waiting
|
|
@@ -125270,10 +125247,6 @@ var MessageService = class {
|
|
|
125270
125247
|
asker: turnStarts && toOrchestrator ? picked : null
|
|
125271
125248
|
};
|
|
125272
125249
|
}
|
|
125273
|
-
/** The delivery began a turn for `recipient` (it called `MailTurns.begin`): the rows it delivered were delivered in that turn */
|
|
125274
|
-
turnStarted(recipient, messageIds, turnSeq) {
|
|
125275
|
-
this.run(() => this.records.markTurn(recipient, messageIds, turnSeq));
|
|
125276
|
-
}
|
|
125277
125250
|
/**
|
|
125278
125251
|
* What a host that died left half done (§7.6.5 of the old plan): a delivery whose attempt was written and whose acceptance was not. It is not sent
|
|
125279
125252
|
* again on its own, since an inline task the tool took just before the host died would start the same work twice: it is held `uncertain`, for the
|
|
@@ -125435,29 +125408,6 @@ var MessageService = class {
|
|
|
125435
125408
|
return rows3.length;
|
|
125436
125409
|
});
|
|
125437
125410
|
}
|
|
125438
|
-
/** One line for the person's guidance per project with mail held for its trust or delegations refused (§7.4) */
|
|
125439
|
-
heldByProject() {
|
|
125440
|
-
const byProject = /* @__PURE__ */ new Map();
|
|
125441
|
-
const entry = (projectId) => {
|
|
125442
|
-
const kept = byProject.get(projectId) ?? { count: 0, refused: 0, recipients: /* @__PURE__ */ new Set() };
|
|
125443
|
-
byProject.set(projectId, kept);
|
|
125444
|
-
return kept;
|
|
125445
|
-
};
|
|
125446
|
-
for (const { row, senderProject } of this.records.heldPolicy()) {
|
|
125447
|
-
if (senderProject === null) continue;
|
|
125448
|
-
const e = entry(senderProject);
|
|
125449
|
-
e.count++;
|
|
125450
|
-
e.recipients.add(row.recipient);
|
|
125451
|
-
}
|
|
125452
|
-
for (const { message } of this.records.refusedRecords()) {
|
|
125453
|
-
const e = message.facts.refused ? entry(message.facts.refused.projectId) : void 0;
|
|
125454
|
-
if (e) {
|
|
125455
|
-
e.refused++;
|
|
125456
|
-
e.recipients.add(message.facts.refused?.target ?? "");
|
|
125457
|
-
}
|
|
125458
|
-
}
|
|
125459
|
-
return [...byProject].map(([projectId, e]) => ({ projectId, count: e.count, refused: e.refused, recipients: [...e.recipients] })).sort((a, b2) => a.projectId.localeCompare(b2.projectId));
|
|
125460
|
-
}
|
|
125461
125411
|
// ── Parties that go, parties that take over (§7.7) ──
|
|
125462
125412
|
/** A session went to the trash or was deleted: its watched rows are `gone`, its own watched messages `withdrawn`, and each sender whose needsReply message it leaves is told once (D25) */
|
|
125463
125413
|
partyGone(address) {
|
|
@@ -125477,6 +125427,8 @@ var MessageService = class {
|
|
|
125477
125427
|
* `needsReply` message, the person's too) is released with the cause, and each sender is told once, in one notice. The rows stay open, so a reply that
|
|
125478
125428
|
* comes after the person continues the session still answers them. A question delivered in an earlier turn is not this stop's: it was read, and the
|
|
125479
125429
|
* session may have answered it in conversation. A task is not released here: the old report path tells its owner until requests decide reports.
|
|
125430
|
+
* A request to the orchestrator is (owner: its sender always learns it will not be answered, #1186): the turn's report tells the asker it was owed to,
|
|
125431
|
+
* which the caller passes as `held`, and every other asker, or one that report misses (an asker the same quit cut), gets the stop notice.
|
|
125480
125432
|
* `turnSeq` is the cut turn (none: nothing is released, as for a turn the mailbox never recorded)
|
|
125481
125433
|
*
|
|
125482
125434
|
* Who is woken (Q1): a sender that is at rest and waits on the stopped session, by a task it gave it that is still open or by a wait (`waitsOn`).
|
|
@@ -125499,10 +125451,7 @@ var MessageService = class {
|
|
|
125499
125451
|
if (turnSeq === null) continue;
|
|
125500
125452
|
const rows3 = this.records.watchedTo(address);
|
|
125501
125453
|
const gave = new Set(rows3.filter((r) => this.records.message(r.messageId)?.kind === "task").flatMap((r) => this.records.message(r.messageId)?.sender ?? []));
|
|
125502
|
-
for (const row of
|
|
125503
|
-
if (row.releasedAt !== null || row.deliveredAt === null || row.answerId !== null || row.turnSeq !== turnSeq) continue;
|
|
125504
|
-
const m = this.records.message(row.messageId);
|
|
125505
|
-
if (!m || m.kind === "task" || !m.needsReply || m.sender === address || this.isRequest(m, address)) continue;
|
|
125454
|
+
for (const { row, message: m } of this.cutQuestions(address, turnSeq)) {
|
|
125506
125455
|
if (!this.records.markReleased(row.messageId, address, now, why2)) continue;
|
|
125507
125456
|
released++;
|
|
125508
125457
|
if (gave.has(m.sender) || this.opts.waitsOn?.(m.sender, address)) waiting.add(m.sender);
|
|
@@ -125580,14 +125529,22 @@ var MessageService = class {
|
|
|
125580
125529
|
turnsLost(close) {
|
|
125581
125530
|
this.releaseAndTell((now, senders) => {
|
|
125582
125531
|
for (const { address, turnSeq } of close()) {
|
|
125583
|
-
for (const row of this.records.
|
|
125584
|
-
if (row.turnSeq !== turnSeq || row.settled !== null) continue;
|
|
125585
|
-
const m = this.records.message(row.messageId);
|
|
125586
|
-
if (m && m.kind !== "task" && this.records.markReleased(row.messageId, address, now, "lost")) senders.add(m.sender);
|
|
125587
|
-
}
|
|
125532
|
+
for (const { row, message } of this.cutQuestions(address, turnSeq)) if (this.records.markReleased(row.messageId, address, now, "lost")) senders.add(message.sender);
|
|
125588
125533
|
}
|
|
125589
125534
|
});
|
|
125590
125535
|
}
|
|
125536
|
+
/**
|
|
125537
|
+
* The questions `address` left unanswered in its turn `turnSeq`, the rows a stop (`sessionsStopped`) or a lost turn (`turnsLost`) releases: each
|
|
125538
|
+
* `needsReply` message delivered into that turn and not answered, settled or released, a request to the orchestrator included. Not a task (the old
|
|
125539
|
+
* report path tells its owner, #698), nor a message the session sent itself (a handoff to the very session that asked leaves such a row)
|
|
125540
|
+
*/
|
|
125541
|
+
cutQuestions(address, turnSeq) {
|
|
125542
|
+
return this.records.unansweredTo(address).flatMap((row) => {
|
|
125543
|
+
if (row.turnSeq !== turnSeq || row.settled !== null || row.releasedAt !== null) return [];
|
|
125544
|
+
const message = this.records.message(row.messageId);
|
|
125545
|
+
return message && message.kind !== "task" && message.sender !== address ? [{ row, message }] : [];
|
|
125546
|
+
});
|
|
125547
|
+
}
|
|
125591
125548
|
/** One write: `release` releases rows and adds each released question's sender to `senders`; then each sender is told once, in one notice (D25) */
|
|
125592
125549
|
releaseAndTell(release, quiet = () => false) {
|
|
125593
125550
|
this.run(() => {
|
|
@@ -156054,7 +156011,6 @@ function updateNodeSentence(o) {
|
|
|
156054
156011
|
import { execFileSync as execFileSync5, spawn as spawn6 } from "node:child_process";
|
|
156055
156012
|
import { createHash as createHash14 } from "node:crypto";
|
|
156056
156013
|
import { createConnection as createConnection2, createServer as createServer3 } from "node:net";
|
|
156057
|
-
import { win32 as win329 } from "node:path";
|
|
156058
156014
|
import { hostname as hostname3 } from "node:os";
|
|
156059
156015
|
|
|
156060
156016
|
// packages/agent-host/src/links/ssh-run.ts
|
|
@@ -156468,7 +156424,7 @@ var SshTunnel = class {
|
|
|
156468
156424
|
const r = await this.run([...this.config(), "-T", "-o", "BatchMode=yes", "-o", "ConnectTimeout=15", "--", this.opts.target, detachCommand(remote, this.opts.hubName ?? hostname3())], void 0, this.opts.detachTimeoutMs ?? SSH_DETACH_TIMEOUT_MS);
|
|
156469
156425
|
this.ifClosed();
|
|
156470
156426
|
if (r.code === 255) throw new Error(`ssh could not reach ${this.opts.target}: ${lastLine(r.stderr) || "no answer"}`);
|
|
156471
|
-
if (r.stdout.includes(NOT_FOUND2)
|
|
156427
|
+
if (r.stdout.includes(NOT_FOUND2)) throw notInstalled(this.where, remote);
|
|
156472
156428
|
let answer;
|
|
156473
156429
|
try {
|
|
156474
156430
|
answer = parseDetachLine(r.stdout);
|
|
@@ -156597,7 +156553,7 @@ var SshTunnel = class {
|
|
|
156597
156553
|
return this.connectionLine();
|
|
156598
156554
|
}
|
|
156599
156555
|
if (r.code === 255) throw new Error(`ssh could not reach ${this.opts.target}: ${lastLine(r.stderr) || "no answer"}`);
|
|
156600
|
-
if (r.stdout.includes(NOT_FOUND2)
|
|
156556
|
+
if (r.stdout.includes(NOT_FOUND2)) throw notInstalled(this.where, remote);
|
|
156601
156557
|
try {
|
|
156602
156558
|
const line = parseConnectionLine(r.stdout, remote);
|
|
156603
156559
|
return pair && this.pairs && line.credential ? { ...line, pairedAs: oneLineText(pair, 80) } : line;
|
|
@@ -156746,8 +156702,7 @@ function ansiText(bytes2) {
|
|
|
156746
156702
|
ansiDecoder = null;
|
|
156747
156703
|
if (process.platform !== "win32") return null;
|
|
156748
156704
|
try {
|
|
156749
|
-
const
|
|
156750
|
-
const out = execFileSync5(win329.join(root3, "System32", "reg.exe"), ["query", "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage", "/v", "ACP"], { encoding: "utf8", timeout: 5e3, windowsHide: true });
|
|
156705
|
+
const out = execFileSync5(systemTool2(["reg.exe"]), ["query", "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage", "/v", "ACP"], { encoding: "utf8", timeout: 5e3, windowsHide: true });
|
|
156751
156706
|
const page = /\bACP\s+REG_SZ\s+(\d+)/.exec(out)?.[1];
|
|
156752
156707
|
if (page) ansiDecoder = new TextDecoder(CODE_PAGE_NAMES[page] ?? `windows-${page}`, { fatal: true });
|
|
156753
156708
|
} catch {
|
|
@@ -157401,6 +157356,17 @@ async function removeAutostart(c) {
|
|
|
157401
157356
|
}
|
|
157402
157357
|
}
|
|
157403
157358
|
|
|
157359
|
+
// packages/agent-host/src/links/hub-auto.ts
|
|
157360
|
+
async function askHubAuto(call2, allowed) {
|
|
157361
|
+
try {
|
|
157362
|
+
const r = asObj(await (allowed === void 0 ? call2("host.hubAuto", {}) : call2("host.setHubAuto", { allowed })));
|
|
157363
|
+
return r.allowed === true ? "on" : "off";
|
|
157364
|
+
} catch (err) {
|
|
157365
|
+
if (/^Unknown method/.test(errorMessage(err))) return "older";
|
|
157366
|
+
throw err;
|
|
157367
|
+
}
|
|
157368
|
+
}
|
|
157369
|
+
|
|
157404
157370
|
// packages/agent-host/src/links/linked-machine-connection.ts
|
|
157405
157371
|
import { randomBytes as randomBytes13 } from "node:crypto";
|
|
157406
157372
|
|
|
@@ -157722,6 +157688,11 @@ var RemoteClient = class {
|
|
|
157722
157688
|
attempt = 0;
|
|
157723
157689
|
reconnectTimer;
|
|
157724
157690
|
handshakeTimer;
|
|
157691
|
+
stableTimer;
|
|
157692
|
+
/** The hello of this socket is younger than `stableMs`: a drop now makes it short-lived */
|
|
157693
|
+
settling = false;
|
|
157694
|
+
/** The hellos in a row that dropped within `stableMs` */
|
|
157695
|
+
shortLived = 0;
|
|
157725
157696
|
/** The refusal that came before the close, if one did: it names why the host closes */
|
|
157726
157697
|
refusal;
|
|
157727
157698
|
WS;
|
|
@@ -157819,6 +157790,7 @@ var RemoteClient = class {
|
|
|
157819
157790
|
this.lastSeq = 0;
|
|
157820
157791
|
}
|
|
157821
157792
|
this.attempt = 0;
|
|
157793
|
+
this.shortLived = 0;
|
|
157822
157794
|
if (this.ws) {
|
|
157823
157795
|
const old = this.ws;
|
|
157824
157796
|
this.ws = null;
|
|
@@ -157887,6 +157859,14 @@ var RemoteClient = class {
|
|
|
157887
157859
|
this.cursorValid = true;
|
|
157888
157860
|
this.ready = true;
|
|
157889
157861
|
this.attempt = 0;
|
|
157862
|
+
if (this.opts.stableMs !== void 0) {
|
|
157863
|
+
this.settling = true;
|
|
157864
|
+
this.stableTimer = setTimeout(() => {
|
|
157865
|
+
this.settling = false;
|
|
157866
|
+
this.shortLived = 0;
|
|
157867
|
+
}, this.opts.stableMs);
|
|
157868
|
+
this.stableTimer.unref?.();
|
|
157869
|
+
}
|
|
157890
157870
|
this.on.hello?.({ resync, newLifetime: !sameLifetime, protocolVersion: frame.protocolVersion, ...frame.build ? { build: frame.build } : {}, ...typeof frame.elevated === "boolean" ? { elevated: frame.elevated } : {}, ...frame.logon ? { logon: frame.logon } : {}, ...frame.handover ? { handover: frame.handover } : {}, ...frame.updateContinued ? { updateContinued: frame.updateContinued } : {} });
|
|
157891
157871
|
return;
|
|
157892
157872
|
}
|
|
@@ -157958,11 +157938,13 @@ var RemoteClient = class {
|
|
|
157958
157938
|
this.ws = null;
|
|
157959
157939
|
const wasReady = this.ready;
|
|
157960
157940
|
this.ready = false;
|
|
157941
|
+
if (wasReady && this.settling) this.shortLived++;
|
|
157942
|
+
this.settling = false;
|
|
157961
157943
|
this.clearTimers();
|
|
157962
157944
|
this.failAll("The link dropped");
|
|
157963
157945
|
if (this.closed) return;
|
|
157964
157946
|
if (wasReady) this.on.down?.(reason, detail);
|
|
157965
|
-
if (this.opts.redials !== void 0 && this.attempt >= this.opts.redials) {
|
|
157947
|
+
if (this.opts.redials !== void 0 && (this.attempt >= this.opts.redials || this.shortLived >= this.opts.redials)) {
|
|
157966
157948
|
this.on.gaveUp?.(reason);
|
|
157967
157949
|
return;
|
|
157968
157950
|
}
|
|
@@ -157983,6 +157965,7 @@ var RemoteClient = class {
|
|
|
157983
157965
|
clearTimers() {
|
|
157984
157966
|
clearTimeout(this.reconnectTimer);
|
|
157985
157967
|
clearTimeout(this.handshakeTimer);
|
|
157968
|
+
clearTimeout(this.stableTimer);
|
|
157986
157969
|
this.reconnectTimer = void 0;
|
|
157987
157970
|
this.handshakeTimer = void 0;
|
|
157988
157971
|
}
|
|
@@ -158123,7 +158106,7 @@ async function follow(c, id3) {
|
|
|
158123
158106
|
const machine = c.machine ?? c.target;
|
|
158124
158107
|
throw new Error(`The update of ${machine} could not be followed to its end from this computer; how it ended is shown once ${machine} is reached again`);
|
|
158125
158108
|
}
|
|
158126
|
-
await
|
|
158109
|
+
await sleep(wait);
|
|
158127
158110
|
}
|
|
158128
158111
|
}
|
|
158129
158112
|
var restoredNote = (version2, machine) => `The store on ${machine} was put back as it was before the dev build first opened it, since Centralu ${version2} could not read it as the dev build left it; what was done on the dev build since is not in it`;
|
|
@@ -158321,9 +158304,8 @@ var LinkedMachineConnection = class {
|
|
|
158321
158304
|
client = null;
|
|
158322
158305
|
/** The client when it stopped redialling (`gaveUp`, #1143) and is waiting, idle, for the next opening */
|
|
158323
158306
|
gaveUp = null;
|
|
158324
|
-
/** Sessions of the remote the hub shows
|
|
158307
|
+
/** Sessions of the remote the hub shows, by the remote's id. Events of any other session are not passed on */
|
|
158325
158308
|
shown = /* @__PURE__ */ new Set();
|
|
158326
|
-
hidden = /* @__PURE__ */ new Set();
|
|
158327
158309
|
/** The remote's coordinators as it last gave them: not shown, but read by a reader (#1941, `unshown`) */
|
|
158328
158310
|
coordinators = /* @__PURE__ */ new Map();
|
|
158329
158311
|
retryTimer;
|
|
@@ -158650,23 +158632,23 @@ var LinkedMachineConnection = class {
|
|
|
158650
158632
|
return !!line.credential && c.id === line.credential && this.isPairedHere(c);
|
|
158651
158633
|
}
|
|
158652
158634
|
/**
|
|
158653
|
-
|
|
158654
|
-
|
|
158655
|
-
|
|
158656
|
-
|
|
158657
|
-
* not remember, are not taken for another's
|
|
158658
|
-
*/
|
|
158659
|
-
/**
|
|
158660
|
-
* Marks, in a list the host answered with `nonce`, the entries whose `check` is of the secret this hub holds under
|
|
158661
|
-
* their id (`own`). An entry without a check (a host from before it) or a credential this hub holds no secret of is not
|
|
158662
|
-
* marked, and is compared by id alone
|
|
158663
|
-
*/
|
|
158635
|
+
* Marks, in a list the host answered with `nonce`, the entries whose `check` is of the secret this hub holds under
|
|
158636
|
+
* their id (`own`). An entry without a check (a host from before it) or a credential this hub holds no secret of is not
|
|
158637
|
+
* marked, and is compared by id alone
|
|
158638
|
+
*/
|
|
158664
158639
|
ownOf(list2, nonce) {
|
|
158665
158640
|
return list2?.map((c) => {
|
|
158666
158641
|
const verifier = this.pairedHere.get(c.id);
|
|
158667
158642
|
return c.check === void 0 || !verifier ? c : { ...c, own: c.check === credentialCheck(verifier, nonce) };
|
|
158668
158643
|
}) ?? null;
|
|
158669
158644
|
}
|
|
158645
|
+
/**
|
|
158646
|
+
* The credentials used on the machine under this hub's own label that this hub did not pair (#1405 review), and that
|
|
158647
|
+
* `listed` does not name already, as used and gone. The machine's host leaves out a credential whose label's next one
|
|
158648
|
+
* was paired the same way, taking it for its pairer again; under a hub's label only the hub can tell. Counted from the
|
|
158649
|
+
* first use there of one this hub paired in its present run, so the credentials of its own earlier runs, which it does
|
|
158650
|
+
* not remember, are not taken for another's
|
|
158651
|
+
*/
|
|
158670
158652
|
notPairedHere(line, listed2) {
|
|
158671
158653
|
if (!line.pairedAs) return [];
|
|
158672
158654
|
const first = this.usedUnderHubLabels.findIndex((u) => this.isPairedHere(u));
|
|
@@ -158854,7 +158836,6 @@ var LinkedMachineConnection = class {
|
|
|
158854
158836
|
observe(kind, list2) {
|
|
158855
158837
|
if (kind === "sessions") {
|
|
158856
158838
|
this.shown.clear();
|
|
158857
|
-
this.hidden.clear();
|
|
158858
158839
|
this.coordinators.clear();
|
|
158859
158840
|
for (const s of list2) this.classify(s);
|
|
158860
158841
|
this.deps.mirror.replace(this.id, "sessions", list2.filter((s) => !hiddenKind(s)));
|
|
@@ -159208,6 +159189,7 @@ var LinkedMachineConnection = class {
|
|
|
159208
159189
|
// A host that can prove it holds the token is asked to, before the token goes out (#838)
|
|
159209
159190
|
{
|
|
159210
159191
|
redials: LINK_REDIALS,
|
|
159192
|
+
stableMs: this.deps.stableMs ?? STABLE_MS,
|
|
159211
159193
|
...this.deps.client,
|
|
159212
159194
|
url: endpoint.url,
|
|
159213
159195
|
token: endpoint.token,
|
|
@@ -159351,8 +159333,7 @@ var LinkedMachineConnection = class {
|
|
|
159351
159333
|
}
|
|
159352
159334
|
classify(s) {
|
|
159353
159335
|
if (!isObj(s) || typeof s.id !== "string") return;
|
|
159354
|
-
if (hiddenKind(s)) this.
|
|
159355
|
-
else this.shown.add(s.id);
|
|
159336
|
+
if (!hiddenKind(s)) this.shown.add(s.id);
|
|
159356
159337
|
if (s.kind === "coordinator") this.coordinators.set(s.id, s);
|
|
159357
159338
|
}
|
|
159358
159339
|
transportDown(reason) {
|
|
@@ -159367,14 +159348,6 @@ var LinkedMachineConnection = class {
|
|
|
159367
159348
|
nextStep() {
|
|
159368
159349
|
return this.autoReconnect ? KEEPS_TRYING : WAITS_FOR_PERSON;
|
|
159369
159350
|
}
|
|
159370
|
-
/**
|
|
159371
|
-
* Asks the machine again after a delay. `backoff` (the default): the next step of the backoff, and nothing at all
|
|
159372
|
-
* while Auto reconnect is off (#1341), where only the person's Connect tries again (after the client's quick redials,
|
|
159373
|
-
* which an off machine keeps). `within`: part of an attempt that
|
|
159374
|
-
* is under way or of the person's own request (a refusal asked again at once, a Connect that met an opening), so it
|
|
159375
|
-
* goes ahead either way. `reads`: the versions check looking again for a change on either side; with the switch off it
|
|
159376
|
-
* reads the line and connects nothing (`readsOnly`)
|
|
159377
|
-
*/
|
|
159378
159351
|
/** The link is up, or was just: remembers when, and keeps it for the next start of this host */
|
|
159379
159352
|
seen() {
|
|
159380
159353
|
this.lastConnectedAt = Date.now();
|
|
@@ -159385,6 +159358,14 @@ var LinkedMachineConnection = class {
|
|
|
159385
159358
|
clearTimeout(this.retryTimer);
|
|
159386
159359
|
this.nextAttemptAt = null;
|
|
159387
159360
|
}
|
|
159361
|
+
/**
|
|
159362
|
+
* Asks the machine again after a delay. `backoff` (the default): the next step of the backoff, and nothing at all
|
|
159363
|
+
* while Auto reconnect is off (#1341), where only the person's Connect tries again (after the client's quick redials,
|
|
159364
|
+
* which an off machine keeps). `within`: part of an attempt that
|
|
159365
|
+
* is under way or of the person's own request (a refusal asked again at once, a Connect that met an opening), so it
|
|
159366
|
+
* goes ahead either way. `reads`: the versions check looking again for a change on either side; with the switch off it
|
|
159367
|
+
* reads the line and connects nothing (`readsOnly`)
|
|
159368
|
+
*/
|
|
159388
159369
|
retryLater(fixedMs, mode = "backoff") {
|
|
159389
159370
|
if (this.stopped || this.held) return;
|
|
159390
159371
|
if (mode === "backoff" && !this.autoReconnect && !this.inOperation()) return;
|
|
@@ -159806,13 +159787,10 @@ var LinkedMachine = class extends LinkedMachineConnection {
|
|
|
159806
159787
|
const client = this.client;
|
|
159807
159788
|
if (!client?.connected) return "unreachable";
|
|
159808
159789
|
try {
|
|
159809
|
-
|
|
159810
|
-
return r?.allowed === true ? "on" : "off";
|
|
159790
|
+
return await askHubAuto((method, params) => client.call(method, params), allowed);
|
|
159811
159791
|
} catch (err) {
|
|
159812
|
-
const message = err?.message ?? String(err);
|
|
159813
|
-
if (/^Unknown method/.test(message)) return "older";
|
|
159814
159792
|
if (!client.connected) return "unreachable";
|
|
159815
|
-
throw rpcError(`${this.name} did not answer for its "Allow auto from a linked computer": ${
|
|
159793
|
+
throw rpcError(`${this.name} did not answer for its "Allow auto from a linked computer": ${errorMessage(err)}`);
|
|
159816
159794
|
}
|
|
159817
159795
|
}
|
|
159818
159796
|
/**
|
|
@@ -160243,8 +160221,8 @@ function linkedSessions(machines, route = notRouted, hubName2, options = {}) {
|
|
|
160243
160221
|
await settle(m);
|
|
160244
160222
|
return m.reachable ? null : { ok: false, error: awaySentence(m, tail) };
|
|
160245
160223
|
};
|
|
160246
|
-
const attempt = async (m, run4) => {
|
|
160247
|
-
const down = await reach(m,
|
|
160224
|
+
const attempt = async (m, run4, tail = TAIL.tryAgain) => {
|
|
160225
|
+
const down = await reach(m, tail);
|
|
160248
160226
|
if (down) return down;
|
|
160249
160227
|
try {
|
|
160250
160228
|
return { ok: true, ...await run4() };
|
|
@@ -160257,13 +160235,13 @@ function linkedSessions(machines, route = notRouted, hubName2, options = {}) {
|
|
|
160257
160235
|
const m = find(id3);
|
|
160258
160236
|
return m ? [m, null] : [null, { ok: false, error: refusal2(id3) }];
|
|
160259
160237
|
};
|
|
160260
|
-
const via = async (id3, run4) => {
|
|
160238
|
+
const via = async (id3, run4, tail) => {
|
|
160261
160239
|
const [m, refused2] = found(id3);
|
|
160262
|
-
return m ? attempt(m, () => run4(m)) : refused2;
|
|
160240
|
+
return m ? attempt(m, () => run4(m), tail) : refused2;
|
|
160263
160241
|
};
|
|
160264
160242
|
return [found, via];
|
|
160265
160243
|
};
|
|
160266
|
-
const [
|
|
160244
|
+
const [, viaSession] = reaching(owner, (id3) => `Not a session of a linked machine: ${id3}`);
|
|
160267
160245
|
const [findProject2, viaProject] = reaching(owner, (id3) => `Not a project of a linked machine: ${id3}`);
|
|
160268
160246
|
const [findMachineRef, viaMachine] = reaching(machineById, (id3) => `No linked machine ${id3}`);
|
|
160269
160247
|
const listOf = async (m, method) => {
|
|
@@ -160459,8 +160437,9 @@ function linkedSessions(machines, route = notRouted, hubName2, options = {}) {
|
|
|
160459
160437
|
},
|
|
160460
160438
|
hubAuto(machineId) {
|
|
160461
160439
|
return viaMachine(machineId, async (m) => {
|
|
160462
|
-
const
|
|
160463
|
-
|
|
160440
|
+
const state = await askHubAuto((method, params) => m.call(method, params));
|
|
160441
|
+
if (state === "older") throw new Error(`${m.name} runs a Centralu from before "Allow auto from a linked computer"`);
|
|
160442
|
+
return { allowed: state === "on" };
|
|
160464
160443
|
});
|
|
160465
160444
|
},
|
|
160466
160445
|
origin(project2) {
|
|
@@ -160625,20 +160604,18 @@ function linkedSessions(machines, route = notRouted, hubName2, options = {}) {
|
|
|
160625
160604
|
const p = (m.lastKnown("projects") ?? []).find((x) => isObj(x) && x.id === s.projectId);
|
|
160626
160605
|
return { name: oneLine4(s.name), project: `${isObj(p) ? oneLine4(p.name) : "(none)"} on ${m.name}` };
|
|
160627
160606
|
},
|
|
160628
|
-
|
|
160629
|
-
|
|
160630
|
-
|
|
160631
|
-
|
|
160632
|
-
|
|
160633
|
-
|
|
160634
|
-
|
|
160635
|
-
|
|
160636
|
-
|
|
160637
|
-
|
|
160638
|
-
|
|
160639
|
-
|
|
160640
|
-
return { ok: false, error: cause(err) };
|
|
160641
|
-
}
|
|
160607
|
+
lastWords(sessionId, maxChars, opts) {
|
|
160608
|
+
return viaSession(
|
|
160609
|
+
sessionId,
|
|
160610
|
+
async (m) => {
|
|
160611
|
+
const answer = await m.call("host.lastAnswer", { sessionId: m.q.strip(sessionId, "The session"), maxChars: Math.min(maxChars, ANSWER_MAX_CHARS2), ...opts?.turn ? { turn: true } : {}, ...opts?.since !== void 0 ? { since: opts.since } : {} });
|
|
160612
|
+
const r = HostLastAnswerResult.safeParse(answer);
|
|
160613
|
+
if (!r.success) throw new Error(`${m.name} answered in a shape this Centralu does not read`);
|
|
160614
|
+
const text3 = r.data.text.length > maxChars || r.data.length > r.data.text.length ? `${r.data.text.slice(0, maxChars)}\u2026` : r.data.text;
|
|
160615
|
+
return { text: text3, length: r.data.length, seq: r.data.seq };
|
|
160616
|
+
},
|
|
160617
|
+
TAIL.none
|
|
160618
|
+
);
|
|
160642
160619
|
},
|
|
160643
160620
|
async list() {
|
|
160644
160621
|
const perMachine = await Promise.all(
|
|
@@ -160656,42 +160633,40 @@ function linkedSessions(machines, route = notRouted, hubName2, options = {}) {
|
|
|
160656
160633
|
machineOf(sessionId) {
|
|
160657
160634
|
return owner(sessionId)?.name ?? null;
|
|
160658
160635
|
},
|
|
160659
|
-
|
|
160660
|
-
const [m, refusal2] = findSession(sessionId);
|
|
160661
|
-
if (!m) return refusal2;
|
|
160662
|
-
const down = await reach(m, TAIL.readAgain);
|
|
160663
|
-
if (down) return down;
|
|
160636
|
+
read(sessionId, limit, opts) {
|
|
160664
160637
|
const toolMode = toolLinesOf(opts?.tools);
|
|
160665
|
-
|
|
160666
|
-
|
|
160667
|
-
|
|
160668
|
-
|
|
160669
|
-
|
|
160670
|
-
|
|
160671
|
-
|
|
160672
|
-
|
|
160673
|
-
|
|
160674
|
-
|
|
160675
|
-
|
|
160676
|
-
|
|
160677
|
-
|
|
160678
|
-
|
|
160679
|
-
|
|
160680
|
-
|
|
160681
|
-
|
|
160682
|
-
|
|
160683
|
-
|
|
160684
|
-
|
|
160685
|
-
|
|
160686
|
-
|
|
160687
|
-
|
|
160638
|
+
return viaSession(
|
|
160639
|
+
sessionId,
|
|
160640
|
+
async (m) => {
|
|
160641
|
+
const answer = await m.call("host.readSession", {
|
|
160642
|
+
sessionId: m.q.strip(sessionId, "The session"),
|
|
160643
|
+
...limit !== void 0 ? { limit } : {},
|
|
160644
|
+
...opts?.around !== void 0 ? { around: opts.around } : {},
|
|
160645
|
+
...opts?.tools !== void 0 ? { toolLines: toolMode } : {},
|
|
160646
|
+
...opts?.maxChars !== void 0 ? { maxChars: budgetOf(opts.maxChars) } : {},
|
|
160647
|
+
...opts?.before !== void 0 ? { before: opts.before } : {},
|
|
160648
|
+
...opts?.from !== void 0 ? { from: opts.from } : {},
|
|
160649
|
+
...opts?.offset !== void 0 ? { offset: opts.offset } : {}
|
|
160650
|
+
});
|
|
160651
|
+
const r = HostReadSessionResult.safeParse(answer);
|
|
160652
|
+
if (!r.success) throw new Error(`${m.name} answered in a shape this Centralu does not read`);
|
|
160653
|
+
const all = r.data.lines;
|
|
160654
|
+
const kept = toolMode === "none" ? all.filter((l) => !isToolLine(l)) : all;
|
|
160655
|
+
const spot = Math.min(Math.floor(Math.min(limit ?? 40, 200) / 2), all.length - 1);
|
|
160656
|
+
const around = opts?.around !== void 0 && opts.before === void 0 && opts.from === void 0;
|
|
160657
|
+
const center = !around ? null : Math.min(toolMode === "none" ? all.slice(0, spot).filter((l) => !isToolLine(l)).length : spot, kept.length - 1);
|
|
160658
|
+
const lines = fitMachineLines(kept, budgetOf(opts?.maxChars), center);
|
|
160659
|
+
return { state: oneLine4(r.data.state, 40), lines: lines.map(fencedLine) };
|
|
160660
|
+
},
|
|
160661
|
+
TAIL.readAgain
|
|
160662
|
+
);
|
|
160688
160663
|
},
|
|
160689
160664
|
async recall(query, limit) {
|
|
160690
160665
|
const notSearched = [];
|
|
160691
160666
|
const hits = await Promise.all(
|
|
160692
160667
|
[...machines()].map(async (m) => {
|
|
160693
160668
|
if (!m.reachable) {
|
|
160694
|
-
notSearched.push(`${m.name} (not
|
|
160669
|
+
notSearched.push(`${m.name} (${m.waitsForPerson ? "not connected; ask the person to connect it in Settings, Machines, Connect" : NOT_REACHABLE})`);
|
|
160695
160670
|
return [];
|
|
160696
160671
|
}
|
|
160697
160672
|
try {
|
|
@@ -161100,7 +161075,7 @@ var Router = class {
|
|
|
161100
161075
|
if (method === "apps.list" && isObj(params) && typeof params.machine === "string") {
|
|
161101
161076
|
return this.byMachine(method, params, { result: (r, q2) => Array.isArray(r) ? r.map((a) => q2.app(a)) : r }, ctx);
|
|
161102
161077
|
}
|
|
161103
|
-
return this.merge(method, params);
|
|
161078
|
+
return this.merge(method, params, ctx);
|
|
161104
161079
|
}
|
|
161105
161080
|
};
|
|
161106
161081
|
/** The linked machine an id names, or null for the hub's own (an unprefixed id, or a prefix no link has) */
|
|
@@ -161213,7 +161188,7 @@ var Router = class {
|
|
|
161213
161188
|
* mirror for it, marked `unreachable` and with `live` as last known, so the UI neither drops
|
|
161214
161189
|
* them nor tries to wake them (§5, "Recovery").
|
|
161215
161190
|
*/
|
|
161216
|
-
async merge(method, params) {
|
|
161191
|
+
async merge(method, params, ctx) {
|
|
161217
161192
|
const machines = [...this.opts.machines()];
|
|
161218
161193
|
switch (method) {
|
|
161219
161194
|
case "sessions.list":
|
|
@@ -161221,9 +161196,9 @@ var Router = class {
|
|
|
161221
161196
|
case "projects.list":
|
|
161222
161197
|
return this.mergeLists(machines, "projects", params);
|
|
161223
161198
|
case "projects.reorder":
|
|
161224
|
-
return this.reorderProjects(machines, params);
|
|
161199
|
+
return this.reorderProjects(machines, params, ctx);
|
|
161225
161200
|
case "approvals.deleteRule":
|
|
161226
|
-
return this.deleteRule(machines, params);
|
|
161201
|
+
return this.deleteRule(machines, params, ctx);
|
|
161227
161202
|
default:
|
|
161228
161203
|
return this.mergeSimple(method, machines, params);
|
|
161229
161204
|
}
|
|
@@ -161285,7 +161260,7 @@ var Router = class {
|
|
|
161285
161260
|
* out of it: a stale window cannot move what it never saw. The kept order forgets a project the hub no longer lists,
|
|
161286
161261
|
* unless it is a linked machine's, which may only be out of reach.
|
|
161287
161262
|
*/
|
|
161288
|
-
async reorderProjects(machines, params) {
|
|
161263
|
+
async reorderProjects(machines, params, ctx) {
|
|
161289
161264
|
const { orderedIds } = RpcMethods["projects.reorder"].params.parse(params);
|
|
161290
161265
|
const kept = this.opts.order?.read() ?? [];
|
|
161291
161266
|
const full = keepUnseen(orderedIds, kept);
|
|
@@ -161302,7 +161277,7 @@ var Router = class {
|
|
|
161302
161277
|
const ordered = perMachine.get(m);
|
|
161303
161278
|
if (!ordered) return this.listOf(m, "projects");
|
|
161304
161279
|
try {
|
|
161305
|
-
return m.q.projects(await this.forward(m, "projects.reorder", { orderedIds: ordered }));
|
|
161280
|
+
return m.q.projects(await this.forward(m, "projects.reorder", { orderedIds: ordered }, ctx));
|
|
161306
161281
|
} catch {
|
|
161307
161282
|
return this.present(m, "projects", m.lastKnown("projects") ?? [], true);
|
|
161308
161283
|
}
|
|
@@ -161315,13 +161290,13 @@ var Router = class {
|
|
|
161315
161290
|
}
|
|
161316
161291
|
return machines.length > 0 ? this.inPersonsOrder(all) : all;
|
|
161317
161292
|
}
|
|
161318
|
-
async deleteRule(machines, params) {
|
|
161293
|
+
async deleteRule(machines, params, ctx) {
|
|
161319
161294
|
const id3 = isObj(params) ? params.id : void 0;
|
|
161320
161295
|
const folded = typeof id3 === "number" ? decodeNumber(id3) : null;
|
|
161321
161296
|
if (!folded) return this.opts.local("approvals.deleteRule", params);
|
|
161322
161297
|
const m = machines.find((x) => x.q.slot === folded.slot);
|
|
161323
161298
|
if (!m) throw rpcError("That rule belongs to a machine that is no longer linked");
|
|
161324
|
-
return this.forward(m, "approvals.deleteRule", { id: folded.n });
|
|
161299
|
+
return this.forward(m, "approvals.deleteRule", { id: folded.n }, ctx);
|
|
161325
161300
|
}
|
|
161326
161301
|
/** The other merges: every reachable machine, each answer in the hub's terms, combined by kind */
|
|
161327
161302
|
async mergeSimple(method, machines, params) {
|
|
@@ -161892,7 +161867,7 @@ var handedToken = launch.tokenOnStdin ? await readHandedToken(process.stdin).cat
|
|
|
161892
161867
|
console.error(`[agent-host] the launcher did not hand over the token: ${e.message}`);
|
|
161893
161868
|
process.exit(1);
|
|
161894
161869
|
}) : launch.token;
|
|
161895
|
-
var BUILD = true ? "
|
|
161870
|
+
var BUILD = true ? "5f99652" : "dev";
|
|
161896
161871
|
var { values } = parseArgs({
|
|
161897
161872
|
options: {
|
|
161898
161873
|
port: { type: "string", default: "5175" },
|