commonswarm 0.1.48 → 0.1.50
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/cswarm.cjs +289 -159
- package/package.json +1 -1
package/cswarm.cjs
CHANGED
|
@@ -21470,6 +21470,14 @@ var MemoryStorage = class {
|
|
|
21470
21470
|
this.values.delete(key2);
|
|
21471
21471
|
}
|
|
21472
21472
|
};
|
|
21473
|
+
var HumanSessionError = class extends Error {
|
|
21474
|
+
constructor(code, message) {
|
|
21475
|
+
super(message);
|
|
21476
|
+
this.code = code;
|
|
21477
|
+
}
|
|
21478
|
+
code;
|
|
21479
|
+
name = "HumanSessionError";
|
|
21480
|
+
};
|
|
21473
21481
|
function base64Url(bytes) {
|
|
21474
21482
|
return bytes.toString("base64url");
|
|
21475
21483
|
}
|
|
@@ -21848,7 +21856,12 @@ async function refreshedCredential(target2, store2) {
|
|
|
21848
21856
|
return await store2.withLock(async () => {
|
|
21849
21857
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
21850
21858
|
const before = await store2.read();
|
|
21851
|
-
if (!before)
|
|
21859
|
+
if (!before) {
|
|
21860
|
+
throw new HumanSessionError(
|
|
21861
|
+
"human_session_missing",
|
|
21862
|
+
"not logged in; run cswarm login"
|
|
21863
|
+
);
|
|
21864
|
+
}
|
|
21852
21865
|
const memory = new MemoryStorage();
|
|
21853
21866
|
const client = authClient(target2, memory);
|
|
21854
21867
|
const refreshed = await client.auth.refreshSession({
|
|
@@ -21857,7 +21870,10 @@ async function refreshedCredential(target2, store2) {
|
|
|
21857
21870
|
if (refreshed.error) {
|
|
21858
21871
|
const afterFailure = await store2.read();
|
|
21859
21872
|
if (afterFailure && afterFailure.generation !== before.generation) continue;
|
|
21860
|
-
throw new
|
|
21873
|
+
throw new HumanSessionError(
|
|
21874
|
+
"human_session_refresh_failed",
|
|
21875
|
+
"could not refresh your session; run cswarm login to sign in again"
|
|
21876
|
+
);
|
|
21861
21877
|
}
|
|
21862
21878
|
const session = requireSession(refreshed.data.session);
|
|
21863
21879
|
const current = await store2.read();
|
|
@@ -26463,6 +26479,149 @@ async function agentCredentialStore(options) {
|
|
|
26463
26479
|
};
|
|
26464
26480
|
}
|
|
26465
26481
|
|
|
26482
|
+
// src/cloud/agent-credential-input.ts
|
|
26483
|
+
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
26484
|
+
var AGENT_TOKEN_RE3 = /^swm_agt_[A-Za-z0-9_-]{43}$/;
|
|
26485
|
+
var AGENT_CREDENTIAL_MESSAGE = "Agent credential minted. It is bound to this task and run so the agent's work stays scoped and attributable.";
|
|
26486
|
+
var AGENT_CREDENTIAL_MESSAGE_D088 = "Agent credential minted. It is bound to this run, so the agent's work is attributable to it.";
|
|
26487
|
+
var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
|
|
26488
|
+
AGENT_CREDENTIAL_MESSAGE,
|
|
26489
|
+
AGENT_CREDENTIAL_MESSAGE_D088
|
|
26490
|
+
];
|
|
26491
|
+
var AgentCredentialInputError = class extends Error {
|
|
26492
|
+
constructor(code, message) {
|
|
26493
|
+
super(`[${code}] ${message}`);
|
|
26494
|
+
this.code = code;
|
|
26495
|
+
}
|
|
26496
|
+
code;
|
|
26497
|
+
name = "AgentCredentialInputError";
|
|
26498
|
+
};
|
|
26499
|
+
var AGENT_CREDENTIAL_REQUIRED_FIELDS = [
|
|
26500
|
+
"message",
|
|
26501
|
+
"status",
|
|
26502
|
+
"principal_id",
|
|
26503
|
+
"token_id",
|
|
26504
|
+
"run_id",
|
|
26505
|
+
"agent_token"
|
|
26506
|
+
];
|
|
26507
|
+
var AGENT_CREDENTIAL_OPTIONAL_FIELDS = ["expires_at"];
|
|
26508
|
+
var ALLOWED_ARTIFACT_KEYS = /* @__PURE__ */ new Set([
|
|
26509
|
+
...AGENT_CREDENTIAL_REQUIRED_FIELDS,
|
|
26510
|
+
...AGENT_CREDENTIAL_OPTIONAL_FIELDS
|
|
26511
|
+
]);
|
|
26512
|
+
function sourceName(source) {
|
|
26513
|
+
return source.kind === "file" ? `agent credential file ${source.path}` : "agent credential input from stdin";
|
|
26514
|
+
}
|
|
26515
|
+
function nextStep(source) {
|
|
26516
|
+
return source.kind === "file" ? `Next step: copy the minted JSON line again and replace ${source.path}.` : "Next step: copy the minted JSON line again and send that line to stdin.";
|
|
26517
|
+
}
|
|
26518
|
+
function credentialInputError(code, source, found) {
|
|
26519
|
+
return new AgentCredentialInputError(
|
|
26520
|
+
code,
|
|
26521
|
+
`${sourceName(source)} ${found}. It must be the JSON line CommonSwarm minted, copied unchanged: ${AGENT_CREDENTIAL_REQUIRED_FIELDS.join(", ")} (${AGENT_CREDENTIAL_OPTIONAL_FIELDS.join(", ")} is optional). ${nextStep(source)}`
|
|
26522
|
+
);
|
|
26523
|
+
}
|
|
26524
|
+
function jsonKind(value) {
|
|
26525
|
+
if (value === null) return "JSON null";
|
|
26526
|
+
if (Array.isArray(value)) return "a JSON array";
|
|
26527
|
+
return `a JSON ${typeof value}`;
|
|
26528
|
+
}
|
|
26529
|
+
function parseAgentCredentialInput(value, source) {
|
|
26530
|
+
if (AGENT_TOKEN_RE3.test(value)) {
|
|
26531
|
+
return {
|
|
26532
|
+
token: value,
|
|
26533
|
+
principalId: null,
|
|
26534
|
+
tokenId: null,
|
|
26535
|
+
runId: null,
|
|
26536
|
+
expiresAt: null,
|
|
26537
|
+
durable: false
|
|
26538
|
+
};
|
|
26539
|
+
}
|
|
26540
|
+
let parsed;
|
|
26541
|
+
try {
|
|
26542
|
+
parsed = JSON.parse(value);
|
|
26543
|
+
} catch {
|
|
26544
|
+
throw credentialInputError(
|
|
26545
|
+
"agent_credential_invalid_json",
|
|
26546
|
+
source,
|
|
26547
|
+
"contains text that is not valid JSON"
|
|
26548
|
+
);
|
|
26549
|
+
}
|
|
26550
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
26551
|
+
throw credentialInputError(
|
|
26552
|
+
"agent_credential_not_object",
|
|
26553
|
+
source,
|
|
26554
|
+
`contains ${jsonKind(parsed)} instead of a JSON object`
|
|
26555
|
+
);
|
|
26556
|
+
}
|
|
26557
|
+
const artifact = parsed;
|
|
26558
|
+
if (!Object.hasOwn(artifact, "agent_token")) {
|
|
26559
|
+
throw credentialInputError(
|
|
26560
|
+
"agent_credential_missing_agent_token",
|
|
26561
|
+
source,
|
|
26562
|
+
'is missing "agent_token"'
|
|
26563
|
+
);
|
|
26564
|
+
}
|
|
26565
|
+
if (typeof artifact.agent_token !== "string" || !AGENT_TOKEN_RE3.test(artifact.agent_token)) {
|
|
26566
|
+
const found = typeof artifact.agent_token === "string" ? 'has "agent_token" as a string that is not a swm_agt_ credential' : `has "agent_token" as ${jsonKind(artifact.agent_token)}`;
|
|
26567
|
+
throw credentialInputError(
|
|
26568
|
+
"agent_credential_invalid_agent_token",
|
|
26569
|
+
source,
|
|
26570
|
+
found
|
|
26571
|
+
);
|
|
26572
|
+
}
|
|
26573
|
+
const actualKeys = Object.keys(artifact);
|
|
26574
|
+
const missingKeys = AGENT_CREDENTIAL_REQUIRED_FIELDS.filter(
|
|
26575
|
+
(key2) => !Object.hasOwn(artifact, key2)
|
|
26576
|
+
);
|
|
26577
|
+
const unknownCount = actualKeys.filter(
|
|
26578
|
+
(key2) => !ALLOWED_ARTIFACT_KEYS.has(key2)
|
|
26579
|
+
).length;
|
|
26580
|
+
const invalidKeys = [];
|
|
26581
|
+
if (Object.hasOwn(artifact, "message") && !ACCEPTED_AGENT_CREDENTIAL_MESSAGES.includes(artifact.message)) {
|
|
26582
|
+
invalidKeys.push("message");
|
|
26583
|
+
}
|
|
26584
|
+
if (Object.hasOwn(artifact, "status") && artifact.status !== "accepted") {
|
|
26585
|
+
invalidKeys.push("status");
|
|
26586
|
+
}
|
|
26587
|
+
for (const key2 of ["principal_id", "token_id", "run_id"]) {
|
|
26588
|
+
if (Object.hasOwn(artifact, key2) && (typeof artifact[key2] !== "string" || !UUID_RE4.test(artifact[key2]))) {
|
|
26589
|
+
invalidKeys.push(key2);
|
|
26590
|
+
}
|
|
26591
|
+
}
|
|
26592
|
+
if (artifact.expires_at !== void 0) {
|
|
26593
|
+
if (typeof artifact.expires_at !== "string" || Number.isNaN(Date.parse(artifact.expires_at))) {
|
|
26594
|
+
invalidKeys.push("expires_at");
|
|
26595
|
+
}
|
|
26596
|
+
}
|
|
26597
|
+
if (missingKeys.length > 0 || unknownCount > 0 || invalidKeys.length > 0) {
|
|
26598
|
+
const faults = [];
|
|
26599
|
+
if (unknownCount > 0) {
|
|
26600
|
+
faults.push(`has ${unknownCount} unrecognized ${unknownCount === 1 ? "field" : "fields"}`);
|
|
26601
|
+
}
|
|
26602
|
+
if (missingKeys.length > 0) {
|
|
26603
|
+
faults.push(`is missing required ${missingKeys.length === 1 ? "field" : "fields"} ${missingKeys.map((key2) => `"${key2}"`).join(", ")}`);
|
|
26604
|
+
}
|
|
26605
|
+
if (invalidKeys.length > 0) {
|
|
26606
|
+
faults.push(`has invalid ${invalidKeys.length === 1 ? "field" : "fields"} ${invalidKeys.map((key2) => `"${key2}"`).join(", ")}`);
|
|
26607
|
+
}
|
|
26608
|
+
throw credentialInputError(
|
|
26609
|
+
"agent_credential_fields_invalid",
|
|
26610
|
+
source,
|
|
26611
|
+
faults.join(" and ")
|
|
26612
|
+
);
|
|
26613
|
+
}
|
|
26614
|
+
const expiresAt = artifact.expires_at === void 0 ? null : Date.parse(artifact.expires_at);
|
|
26615
|
+
return {
|
|
26616
|
+
token: artifact.agent_token,
|
|
26617
|
+
principalId: artifact.principal_id.toLowerCase(),
|
|
26618
|
+
tokenId: artifact.token_id.toLowerCase(),
|
|
26619
|
+
runId: artifact.run_id.toLowerCase(),
|
|
26620
|
+
expiresAt,
|
|
26621
|
+
durable: true
|
|
26622
|
+
};
|
|
26623
|
+
}
|
|
26624
|
+
|
|
26466
26625
|
// src/cloud/renewal.ts
|
|
26467
26626
|
var import_node_crypto9 = require("node:crypto");
|
|
26468
26627
|
var AGENT_TOKEN_DEFAULT_TTL_MS2 = 60 * 60 * 1e3;
|
|
@@ -26485,8 +26644,8 @@ var RENEWAL_LEAD_FLOOR_MS = 5 * 6e4;
|
|
|
26485
26644
|
var RENEWAL_LEAD_CEILING_MS = 15 * 6e4;
|
|
26486
26645
|
var RENEWAL_PENDING_RECOVERY_MS = 60 * 6e4;
|
|
26487
26646
|
var RENEW_TIMEOUT_MS = 3e4;
|
|
26488
|
-
var
|
|
26489
|
-
var
|
|
26647
|
+
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
26648
|
+
var AGENT_TOKEN_RE4 = /^swm_agt_[A-Za-z0-9_-]{43}$/;
|
|
26490
26649
|
function renewalDueAt(issuedAt, expiresAt) {
|
|
26491
26650
|
const lifetime = Math.max(0, expiresAt - issuedAt);
|
|
26492
26651
|
const lead = Math.min(
|
|
@@ -26644,7 +26803,7 @@ async function requestSuccessor(options) {
|
|
|
26644
26803
|
} catch {
|
|
26645
26804
|
body = {};
|
|
26646
26805
|
}
|
|
26647
|
-
const principalId = typeof body.principal_id === "string" &&
|
|
26806
|
+
const principalId = typeof body.principal_id === "string" && UUID_RE5.test(body.principal_id) ? body.principal_id.toLowerCase() : null;
|
|
26648
26807
|
if (response.status === 400 || response.status === 404) {
|
|
26649
26808
|
throw new RenewalUnsupported(
|
|
26650
26809
|
"this deployment does not offer credential renewal yet, so a credential here still has to be re-issued by hand when it expires"
|
|
@@ -26732,7 +26891,7 @@ async function requestSuccessor(options) {
|
|
|
26732
26891
|
if (!token) {
|
|
26733
26892
|
return null;
|
|
26734
26893
|
}
|
|
26735
|
-
if (!
|
|
26894
|
+
if (!AGENT_TOKEN_RE4.test(token)) {
|
|
26736
26895
|
throw new RenewalRefused(
|
|
26737
26896
|
response.status,
|
|
26738
26897
|
"malformed_successor",
|
|
@@ -26741,7 +26900,7 @@ async function requestSuccessor(options) {
|
|
|
26741
26900
|
}
|
|
26742
26901
|
const tokenId = typeof body.token_id === "string" ? body.token_id : "";
|
|
26743
26902
|
const runId = typeof body.run_id === "string" ? body.run_id : "";
|
|
26744
|
-
if (!
|
|
26903
|
+
if (!UUID_RE5.test(tokenId) || !UUID_RE5.test(runId) || principalId === null) {
|
|
26745
26904
|
throw new RenewalRefused(
|
|
26746
26905
|
response.status,
|
|
26747
26906
|
"incomplete_successor",
|
|
@@ -27250,7 +27409,7 @@ var MAX_LINK_PAYLOAD_BYTES = 8 * 1024;
|
|
|
27250
27409
|
var MAX_LABEL_INPUT_LENGTH = 1024;
|
|
27251
27410
|
var CONTROL_GLOBAL_RE = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g;
|
|
27252
27411
|
var ANSI_ESCAPE_GLOBAL_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
27253
|
-
var
|
|
27412
|
+
var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
27254
27413
|
var STRICT_BASE64URL_RE = /^[A-Za-z0-9_-]+$/;
|
|
27255
27414
|
var RAW_BASE64_PAYLOAD_CANDIDATE_RE = /^[A-Za-z0-9+/_=-]+$/;
|
|
27256
27415
|
var CURRENT_INVITE_SCHEME = "cswarm://accept/";
|
|
@@ -27301,7 +27460,7 @@ function validatedPayload(value) {
|
|
|
27301
27460
|
throw new Error("invite link target is malformed");
|
|
27302
27461
|
}
|
|
27303
27462
|
cloudTarget(value.url, value.anon_key);
|
|
27304
|
-
if (typeof value.workspace_id !== "string" || !
|
|
27463
|
+
if (typeof value.workspace_id !== "string" || !UUID_RE6.test(value.workspace_id)) {
|
|
27305
27464
|
throw new Error("invite link workspace_id must be a UUID");
|
|
27306
27465
|
}
|
|
27307
27466
|
if (typeof value.invitation_token !== "string") {
|
|
@@ -27311,7 +27470,7 @@ function validatedPayload(value) {
|
|
|
27311
27470
|
if (typeof value.workspace_name !== "string" || typeof value.inviter_display_name !== "string" || value.workspace_name.length > MAX_LABEL_INPUT_LENGTH || value.inviter_display_name.length > MAX_LABEL_INPUT_LENGTH) {
|
|
27312
27471
|
throw new Error("invite link display labels are malformed");
|
|
27313
27472
|
}
|
|
27314
|
-
if (value.inviter_user_id !== void 0 && (typeof value.inviter_user_id !== "string" || !
|
|
27473
|
+
if (value.inviter_user_id !== void 0 && (typeof value.inviter_user_id !== "string" || !UUID_RE6.test(value.inviter_user_id))) {
|
|
27315
27474
|
throw new Error("invite link inviter_user_id must be a UUID");
|
|
27316
27475
|
}
|
|
27317
27476
|
return value;
|
|
@@ -27969,7 +28128,7 @@ function renderCapabilityRevoke(capabilityId, revokedAt) {
|
|
|
27969
28128
|
}
|
|
27970
28129
|
|
|
27971
28130
|
// src/cloud/renewal-grants.ts
|
|
27972
|
-
var
|
|
28131
|
+
var UUID_RE7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
27973
28132
|
function nullableString(value, field) {
|
|
27974
28133
|
if (value === null) return null;
|
|
27975
28134
|
if (typeof value !== "string") {
|
|
@@ -27985,7 +28144,7 @@ function nullableTimestamp(value, field) {
|
|
|
27985
28144
|
return text;
|
|
27986
28145
|
}
|
|
27987
28146
|
function uuid3(value, field) {
|
|
27988
|
-
if (typeof value !== "string" || !
|
|
28147
|
+
if (typeof value !== "string" || !UUID_RE7.test(value)) {
|
|
27989
28148
|
throw new Error(`renewal grant read returned malformed ${field}`);
|
|
27990
28149
|
}
|
|
27991
28150
|
return value.toLowerCase();
|
|
@@ -28076,7 +28235,7 @@ function describeRenewalGrant(grant) {
|
|
|
28076
28235
|
}
|
|
28077
28236
|
|
|
28078
28237
|
// src/cloud/workspaces.ts
|
|
28079
|
-
var
|
|
28238
|
+
var UUID_RE8 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
28080
28239
|
var ROLES = /* @__PURE__ */ new Set(["owner", "admin", "member"]);
|
|
28081
28240
|
var MemberSelectionError = class extends Error {
|
|
28082
28241
|
constructor(code, message, matches = []) {
|
|
@@ -28089,7 +28248,7 @@ var MemberSelectionError = class extends Error {
|
|
|
28089
28248
|
matches;
|
|
28090
28249
|
};
|
|
28091
28250
|
function resolveWorkspaceMember(selector, members) {
|
|
28092
|
-
if (
|
|
28251
|
+
if (UUID_RE8.test(selector)) {
|
|
28093
28252
|
const selected = members.find(
|
|
28094
28253
|
(member) => member.user_id === selector.toLowerCase()
|
|
28095
28254
|
);
|
|
@@ -28188,7 +28347,7 @@ var WorkspaceAmbiguousNameError = class extends WorkspaceCliError {
|
|
|
28188
28347
|
}
|
|
28189
28348
|
};
|
|
28190
28349
|
function checkedUuid(value, field) {
|
|
28191
|
-
if (typeof value !== "string" || !
|
|
28350
|
+
if (typeof value !== "string" || !UUID_RE8.test(value)) {
|
|
28192
28351
|
throw new Error(`workspace read returned a malformed ${field}`);
|
|
28193
28352
|
}
|
|
28194
28353
|
return value.toLowerCase();
|
|
@@ -28507,13 +28666,13 @@ async function updateWorkspaceDefaultAfterClose(store2, userId, closedWorkspaceI
|
|
|
28507
28666
|
}
|
|
28508
28667
|
function workspaceOverride(explicit, environmental) {
|
|
28509
28668
|
if (explicit !== void 0) {
|
|
28510
|
-
if (!
|
|
28669
|
+
if (!UUID_RE8.test(explicit)) {
|
|
28511
28670
|
throw new Error("--workspace-id must be a UUID");
|
|
28512
28671
|
}
|
|
28513
28672
|
return explicit.toLowerCase();
|
|
28514
28673
|
}
|
|
28515
28674
|
if (environmental) {
|
|
28516
|
-
if (!
|
|
28675
|
+
if (!UUID_RE8.test(environmental)) {
|
|
28517
28676
|
throw new Error("SWARM_CLOUD_WORKSPACE_ID must be a UUID");
|
|
28518
28677
|
}
|
|
28519
28678
|
return environmental.toLowerCase();
|
|
@@ -28573,7 +28732,7 @@ async function selectWorkspace(selector, workspaces, store2, userId) {
|
|
|
28573
28732
|
function resolveWorkspaceSelector(selector, workspaces) {
|
|
28574
28733
|
const sorted = sortWorkspaces(workspaces);
|
|
28575
28734
|
let selected;
|
|
28576
|
-
if (
|
|
28735
|
+
if (UUID_RE8.test(selector)) {
|
|
28577
28736
|
const normalized = selector.toLowerCase();
|
|
28578
28737
|
selected = sorted.find(
|
|
28579
28738
|
(workspace) => workspace.workspace_id === normalized
|
|
@@ -28723,7 +28882,7 @@ function describeServerError(prefix, envelope) {
|
|
|
28723
28882
|
|
|
28724
28883
|
// src/cloud/attachments.ts
|
|
28725
28884
|
var SIGNAL_ATTACHMENT_MAX = 8;
|
|
28726
|
-
var
|
|
28885
|
+
var UUID_RE9 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
28727
28886
|
function parseSignalAttachments(value, options = {}) {
|
|
28728
28887
|
if (options.enabled === false || value === void 0) return [];
|
|
28729
28888
|
if (!Array.isArray(value) || value.length > SIGNAL_ATTACHMENT_MAX) {
|
|
@@ -28736,7 +28895,7 @@ function parseSignalAttachments(value, options = {}) {
|
|
|
28736
28895
|
throw new Error("signal read returned a malformed attachment");
|
|
28737
28896
|
}
|
|
28738
28897
|
const row = valueAtPosition;
|
|
28739
|
-
if (typeof row.file_id !== "string" || !
|
|
28898
|
+
if (typeof row.file_id !== "string" || !UUID_RE9.test(row.file_id) || typeof row.version_n !== "number" || !Number.isSafeInteger(row.version_n) || row.version_n < 1 || typeof row.name !== "string" || row.name.length < 1 || row.name.length > 255 || typeof row.content_type !== "string" || row.content_type.length < 1 || typeof row.size_bytes !== "number" || !Number.isSafeInteger(row.size_bytes) || row.size_bytes < 0) {
|
|
28740
28899
|
throw new Error("signal read returned malformed attachment metadata");
|
|
28741
28900
|
}
|
|
28742
28901
|
const fileId = row.file_id.toLowerCase();
|
|
@@ -28756,7 +28915,7 @@ function parseSignalAttachments(value, options = {}) {
|
|
|
28756
28915
|
return attachments;
|
|
28757
28916
|
}
|
|
28758
28917
|
function attachmentRetrievalCommand(workspaceId2, attachment) {
|
|
28759
|
-
if (!
|
|
28918
|
+
if (!UUID_RE9.test(workspaceId2) || !UUID_RE9.test(attachment.file_id)) {
|
|
28760
28919
|
throw new Error("attachment retrieval command needs UUID identifiers");
|
|
28761
28920
|
}
|
|
28762
28921
|
if (!Number.isSafeInteger(attachment.version_n) || attachment.version_n < 1) {
|
|
@@ -28772,7 +28931,7 @@ function formatAttachmentSize(bytes) {
|
|
|
28772
28931
|
}
|
|
28773
28932
|
|
|
28774
28933
|
// src/cloud/signals.ts
|
|
28775
|
-
var
|
|
28934
|
+
var UUID_RE10 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
28776
28935
|
var SIGNAL_KINDS = /* @__PURE__ */ new Set(["working-on", "note", "ask"]);
|
|
28777
28936
|
var SIGNAL_BODY_DISPLAY_MAX = 8e3;
|
|
28778
28937
|
var SIGNAL_ABOUT_DISPLAY_MAX = 500;
|
|
@@ -28843,7 +29002,7 @@ function plainMalformedError(message) {
|
|
|
28843
29002
|
return error;
|
|
28844
29003
|
}
|
|
28845
29004
|
function checkedUuid2(value, field) {
|
|
28846
|
-
if (typeof value !== "string" || !
|
|
29005
|
+
if (typeof value !== "string" || !UUID_RE10.test(value)) {
|
|
28847
29006
|
throw new Error(`signal read returned a malformed ${field}`);
|
|
28848
29007
|
}
|
|
28849
29008
|
return value.toLowerCase();
|
|
@@ -29474,7 +29633,7 @@ async function readAgentSignalDirectory(target2, token, workspaceId2, fetcherOrO
|
|
|
29474
29633
|
}
|
|
29475
29634
|
function resolveSignalRecipient(selector, directory) {
|
|
29476
29635
|
const resolved = Array.isArray(directory) ? { members: directory, agents: [] } : directory;
|
|
29477
|
-
if (
|
|
29636
|
+
if (UUID_RE10.test(selector)) {
|
|
29478
29637
|
const normalized = selector.toLowerCase();
|
|
29479
29638
|
const member = resolved.members.find((row) => row.user_id === normalized);
|
|
29480
29639
|
const agent = resolved.agents.find(
|
|
@@ -29560,10 +29719,10 @@ async function pollForSignals(options) {
|
|
|
29560
29719
|
return { signals: [], timedOut: true };
|
|
29561
29720
|
}
|
|
29562
29721
|
function normalizedSignalQuery(query) {
|
|
29563
|
-
if (!
|
|
29722
|
+
if (!UUID_RE10.test(query.workspaceId)) {
|
|
29564
29723
|
throw new Error("--workspace-id must be a UUID");
|
|
29565
29724
|
}
|
|
29566
|
-
if (query.in_reply_to !== void 0 && !
|
|
29725
|
+
if (query.in_reply_to !== void 0 && !UUID_RE10.test(query.in_reply_to)) {
|
|
29567
29726
|
throw new Error("in_reply_to must be a signal UUID");
|
|
29568
29727
|
}
|
|
29569
29728
|
const after = checkedAfter(query.after);
|
|
@@ -30081,7 +30240,7 @@ async function runInboxFollow(options) {
|
|
|
30081
30240
|
// src/cloud/arrival-watch.ts
|
|
30082
30241
|
var import_node_os4 = require("node:os");
|
|
30083
30242
|
var import_node_path4 = require("node:path");
|
|
30084
|
-
var
|
|
30243
|
+
var UUID_RE11 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
30085
30244
|
var CURSOR_MAX_BYTES = 4 * 1024;
|
|
30086
30245
|
var ARRIVAL_SNIPPET_MAX = 180;
|
|
30087
30246
|
var ARRIVAL_WATCH_POLL_MS = 25e3;
|
|
@@ -30149,7 +30308,7 @@ function parseCursor(raw, workspaceId2, principalId) {
|
|
|
30149
30308
|
}
|
|
30150
30309
|
const row = value;
|
|
30151
30310
|
const cursor = row.cursor;
|
|
30152
|
-
if (row.version !== 1 || row.workspace_id !== workspaceId2.toLowerCase() || row.principal_id !== principalId.toLowerCase() || !(cursor === null || typeof cursor === "object" && !Array.isArray(cursor) && typeof cursor.created_at === "string" && Number.isFinite(Date.parse(cursor.created_at)) && typeof cursor.id === "string" &&
|
|
30311
|
+
if (row.version !== 1 || row.workspace_id !== workspaceId2.toLowerCase() || row.principal_id !== principalId.toLowerCase() || !(cursor === null || typeof cursor === "object" && !Array.isArray(cursor) && typeof cursor.created_at === "string" && Number.isFinite(Date.parse(cursor.created_at)) && typeof cursor.id === "string" && UUID_RE11.test(cursor.id))) {
|
|
30153
30312
|
throw new Error("stored arrival cursor is malformed");
|
|
30154
30313
|
}
|
|
30155
30314
|
if (cursor === null) return null;
|
|
@@ -30161,7 +30320,7 @@ function parseCursor(raw, workspaceId2, principalId) {
|
|
|
30161
30320
|
function fileArrivalCursorStore(options) {
|
|
30162
30321
|
const workspaceId2 = options.workspaceId.toLowerCase();
|
|
30163
30322
|
const principalId = options.principalId.toLowerCase();
|
|
30164
|
-
if (!
|
|
30323
|
+
if (!UUID_RE11.test(workspaceId2) || !UUID_RE11.test(principalId)) {
|
|
30165
30324
|
throw new Error("arrival cursor identity must use workspace and principal UUIDs");
|
|
30166
30325
|
}
|
|
30167
30326
|
const location2 = arrivalCursorPath(
|
|
@@ -30343,7 +30502,7 @@ async function runArrivalWatch(options) {
|
|
|
30343
30502
|
}
|
|
30344
30503
|
|
|
30345
30504
|
// src/cloud/delivery-receipts.ts
|
|
30346
|
-
var
|
|
30505
|
+
var UUID_RE12 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
30347
30506
|
var DeliveryReceiptReadError = class extends Error {
|
|
30348
30507
|
constructor(code, message, status = null) {
|
|
30349
30508
|
super(message);
|
|
@@ -30362,7 +30521,7 @@ var ACK_OUTCOMES = /* @__PURE__ */ new Set([
|
|
|
30362
30521
|
"failed_terminal"
|
|
30363
30522
|
]);
|
|
30364
30523
|
function uuid4(value, field) {
|
|
30365
|
-
if (typeof value !== "string" || !
|
|
30524
|
+
if (typeof value !== "string" || !UUID_RE12.test(value)) {
|
|
30366
30525
|
throw new DeliveryReceiptReadError(
|
|
30367
30526
|
"protocol",
|
|
30368
30527
|
`delivery receipt returned a malformed ${field}`
|
|
@@ -31310,10 +31469,12 @@ var AcpHostError = class extends Error {
|
|
|
31310
31469
|
}
|
|
31311
31470
|
};
|
|
31312
31471
|
var AcpProtocolError = class extends AcpHostError {
|
|
31313
|
-
constructor(message, code = "protocol_error") {
|
|
31472
|
+
constructor(message, code = "protocol_error", peerError = null) {
|
|
31314
31473
|
super(code, message);
|
|
31474
|
+
this.peerError = peerError;
|
|
31315
31475
|
this.name = "AcpProtocolError";
|
|
31316
31476
|
}
|
|
31477
|
+
peerError;
|
|
31317
31478
|
};
|
|
31318
31479
|
var AcpTimeoutError = class extends AcpHostError {
|
|
31319
31480
|
constructor(message) {
|
|
@@ -31370,14 +31531,16 @@ var AcpVersionBelowFloorError = class extends AcpVersionError {
|
|
|
31370
31531
|
actual;
|
|
31371
31532
|
};
|
|
31372
31533
|
var AcpPermissionCanaryError = class extends AcpHostError {
|
|
31373
|
-
constructor(message, reasonCode = null, minimumRequiredVersion = null) {
|
|
31534
|
+
constructor(message, reasonCode = null, minimumRequiredVersion = null, peerError = null) {
|
|
31374
31535
|
super("permission_canary_failed", message);
|
|
31375
31536
|
this.reasonCode = reasonCode;
|
|
31376
31537
|
this.minimumRequiredVersion = minimumRequiredVersion;
|
|
31538
|
+
this.peerError = peerError;
|
|
31377
31539
|
this.name = "AcpPermissionCanaryError";
|
|
31378
31540
|
}
|
|
31379
31541
|
reasonCode;
|
|
31380
31542
|
minimumRequiredVersion;
|
|
31543
|
+
peerError;
|
|
31381
31544
|
};
|
|
31382
31545
|
var AcpPromptsBlockedError = class extends AcpHostError {
|
|
31383
31546
|
constructor() {
|
|
@@ -31657,7 +31820,11 @@ var AcpTransport = class extends import_node_events.EventEmitter {
|
|
|
31657
31820
|
if ("error" in rec && rec.error !== void 0) {
|
|
31658
31821
|
const errObj = rec.error;
|
|
31659
31822
|
const message = errObj && typeof errObj.message === "string" ? errObj.message : `RPC error for ${pending.method}`;
|
|
31660
|
-
|
|
31823
|
+
const peerError = errObj && typeof errObj.code === "number" && Number.isInteger(errObj.code) ? {
|
|
31824
|
+
code: errObj.code,
|
|
31825
|
+
...Object.prototype.hasOwnProperty.call(errObj, "data") ? { data: errObj.data } : {}
|
|
31826
|
+
} : null;
|
|
31827
|
+
pending.reject(new AcpProtocolError(message, "rpc_error", peerError));
|
|
31661
31828
|
return;
|
|
31662
31829
|
}
|
|
31663
31830
|
pending.resolve(rec.result);
|
|
@@ -31847,7 +32014,9 @@ var AcpHostSession = class _AcpHostSession {
|
|
|
31847
32014
|
const detail = last?.reason ?? "permission-boundary canary failed: need host reject + correlated terminal tool status";
|
|
31848
32015
|
throw new AcpPermissionCanaryError(
|
|
31849
32016
|
total === 1 ? detail : `${detail} (failed ${total} attempts)`,
|
|
31850
|
-
last?.reasonCode ?? null
|
|
32017
|
+
last?.reasonCode ?? null,
|
|
32018
|
+
null,
|
|
32019
|
+
last?.peerError ?? null
|
|
31851
32020
|
);
|
|
31852
32021
|
}
|
|
31853
32022
|
/** Test/helper: force-enable prompts without canary (never used by production open path). */
|
|
@@ -31893,7 +32062,8 @@ var AcpHostSession = class _AcpHostSession {
|
|
|
31893
32062
|
sawPermissionRequest: this.canaryState.sawPermissionRequest,
|
|
31894
32063
|
sawDeniedToolResult: this.canaryState.sawDeniedToolResult,
|
|
31895
32064
|
reason: err instanceof Error ? err.message : String(err),
|
|
31896
|
-
...err instanceof AcpHostError ? { reasonCode: err.code } : {}
|
|
32065
|
+
...err instanceof AcpHostError ? { reasonCode: err.code } : {},
|
|
32066
|
+
...err instanceof AcpProtocolError && err.peerError ? { peerError: err.peerError } : {}
|
|
31897
32067
|
};
|
|
31898
32068
|
}
|
|
31899
32069
|
}
|
|
@@ -33728,7 +33898,7 @@ async function resolveBudgetAndPrompt(session, prompt, budget) {
|
|
|
33728
33898
|
}
|
|
33729
33899
|
|
|
33730
33900
|
// src/listener/engine.ts
|
|
33731
|
-
var
|
|
33901
|
+
var UUID_RE13 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
33732
33902
|
var TERMINAL_STATES = /* @__PURE__ */ new Set(["done", "expired", "failed"]);
|
|
33733
33903
|
var REPLY_MAX_CODE_UNITS = 2e3;
|
|
33734
33904
|
var TRUNCATION_SUFFIX = "\n[Reply truncated by CommonSwarm]";
|
|
@@ -33736,7 +33906,7 @@ var UNSAFE_CONTROLS_RE = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u
|
|
|
33736
33906
|
var LISTENER_MAX_PROMPT_ATTEMPTS = 3;
|
|
33737
33907
|
var LISTENER_MAX_POST_ATTEMPTS = 5;
|
|
33738
33908
|
function listenerReplyCommandId(signalId, effectOrdinal = 0) {
|
|
33739
|
-
if (!
|
|
33909
|
+
if (!UUID_RE13.test(signalId)) {
|
|
33740
33910
|
throw new Error("listener signal id must be a UUID");
|
|
33741
33911
|
}
|
|
33742
33912
|
if (!Number.isSafeInteger(effectOrdinal) || effectOrdinal < 0) {
|
|
@@ -34229,7 +34399,7 @@ var import_node_crypto13 = require("node:crypto");
|
|
|
34229
34399
|
var import_node_os6 = require("node:os");
|
|
34230
34400
|
var import_node_path9 = require("node:path");
|
|
34231
34401
|
var import_node_util = require("node:util");
|
|
34232
|
-
var
|
|
34402
|
+
var UUID_RE14 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
34233
34403
|
var COMMAND_ID_RE2 = /^[A-Za-z0-9_-]{8,72}$/;
|
|
34234
34404
|
var MAX_EFFECT_BYTES = 1024 * 1024;
|
|
34235
34405
|
var STATES = /* @__PURE__ */ new Set([
|
|
@@ -34279,7 +34449,7 @@ function defaultListenerStateDirectory() {
|
|
|
34279
34449
|
return process.env.XDG_STATE_HOME ? (0, import_node_path9.join)(process.env.XDG_STATE_HOME, "cswarm", "listeners") : (0, import_node_path9.join)((0, import_node_os6.homedir)(), ".cswarm", "listeners");
|
|
34280
34450
|
}
|
|
34281
34451
|
function listenerInstanceKey(input) {
|
|
34282
|
-
if (!
|
|
34452
|
+
if (!UUID_RE14.test(input.workspaceId) || !UUID_RE14.test(input.principalId)) {
|
|
34283
34453
|
throw new Error("listener workspace and principal ids must be UUIDs");
|
|
34284
34454
|
}
|
|
34285
34455
|
if (!input.profileId || input.profileId.includes("\0")) {
|
|
@@ -34312,7 +34482,7 @@ function parseListenerEffectRecord(raw, expectedId) {
|
|
|
34312
34482
|
}
|
|
34313
34483
|
const row = value;
|
|
34314
34484
|
rejectSensitiveKeys(row);
|
|
34315
|
-
if (typeof row.version !== "number" || row.version !== 1 && row.version !== 2 || typeof row.signalId !== "string" || row.signalId.toLowerCase() !== expectedId || !
|
|
34485
|
+
if (typeof row.version !== "number" || row.version !== 1 && row.version !== 2 || typeof row.signalId !== "string" || row.signalId.toLowerCase() !== expectedId || !UUID_RE14.test(row.signalId)) {
|
|
34316
34486
|
throw new Error("stored listener effect is malformed");
|
|
34317
34487
|
}
|
|
34318
34488
|
if (row.version === 1) {
|
|
@@ -34327,7 +34497,7 @@ function upcastV1Ask(row) {
|
|
|
34327
34497
|
if (row.effectOrdinal !== 0 || typeof row.commandId !== "string" || !COMMAND_ID_RE2.test(row.commandId) || typeof row.askBody !== "string" || row.askBody.length < 1 || typeof row.askUntil !== "string" || !Number.isFinite(Date.parse(row.askUntil)) || typeof row.senderOwnerRelation !== "string" || !RELATIONS.has(row.senderOwnerRelation) || typeof row.state !== "string" || !STATES.has(row.state) || !integer(row.promptAttempts) || !integer(row.postAttempts) || !nullableString2(row.replyBody, 2e3) || typeof row.replyTruncated !== "boolean" || !nullableString2(row.replySignalId, 64) || !nullableString2(row.failureCode, 96) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt))) {
|
|
34328
34498
|
throw new Error("stored listener effect is malformed");
|
|
34329
34499
|
}
|
|
34330
|
-
if (row.replySignalId !== null && !
|
|
34500
|
+
if (row.replySignalId !== null && !UUID_RE14.test(row.replySignalId)) {
|
|
34331
34501
|
throw new Error("stored listener effect is malformed");
|
|
34332
34502
|
}
|
|
34333
34503
|
return {
|
|
@@ -34366,7 +34536,7 @@ function parseV2Record(row) {
|
|
|
34366
34536
|
if (typeof row.commandId !== "string" || !COMMAND_ID_RE2.test(row.commandId) || row.state === "observed") {
|
|
34367
34537
|
throw new Error("stored listener effect is malformed");
|
|
34368
34538
|
}
|
|
34369
|
-
if (row.replySignalId !== null && !
|
|
34539
|
+
if (row.replySignalId !== null && !UUID_RE14.test(row.replySignalId)) {
|
|
34370
34540
|
throw new Error("stored listener effect is malformed");
|
|
34371
34541
|
}
|
|
34372
34542
|
}
|
|
@@ -34390,7 +34560,7 @@ function parseV2Record(row) {
|
|
|
34390
34560
|
};
|
|
34391
34561
|
}
|
|
34392
34562
|
function newObservedNoteRecord(input) {
|
|
34393
|
-
if (!
|
|
34563
|
+
if (!UUID_RE14.test(input.signalId)) {
|
|
34394
34564
|
throw new Error("listener note signal id must be a UUID");
|
|
34395
34565
|
}
|
|
34396
34566
|
if (input.body.length < 1) {
|
|
@@ -34524,7 +34694,7 @@ var FileListenerEffectStore = class {
|
|
|
34524
34694
|
);
|
|
34525
34695
|
}
|
|
34526
34696
|
checkedId(signalId) {
|
|
34527
|
-
if (!
|
|
34697
|
+
if (!UUID_RE14.test(signalId)) {
|
|
34528
34698
|
throw new Error("listener signal id must be a UUID");
|
|
34529
34699
|
}
|
|
34530
34700
|
return signalId.toLowerCase();
|
|
@@ -35319,10 +35489,15 @@ var import_promises7 = require("node:fs/promises");
|
|
|
35319
35489
|
var import_node_os8 = require("node:os");
|
|
35320
35490
|
var import_node_path13 = require("node:path");
|
|
35321
35491
|
var CLAUDE_CODE_VERSION_REQUIRED_RE = /\bClaude Code (\d+\.\d+\.\d+) does not support this model; version (\d+\.\d+\.\d+) or newer is required\b/;
|
|
35322
|
-
var CLAUDE_AUTH_FAILURE_RE = /\b(?:authentication failed|authentication required|not authenticated|OAuth (?:sign-in|login|token)|keychain\/OAuth|please (?:log|sign) in)\b/i;
|
|
35492
|
+
var CLAUDE_AUTH_FAILURE_RE = /\b(?:authentication failed|failed to authenticate|authentication required|not authenticated|OAuth (?:sign-in|login|token)|OAuth session (?:expired|could not be refreshed)|keychain\/OAuth|please (?:log|sign) in)\b/i;
|
|
35323
35493
|
var CLAUDE_CANARY_TIMEOUT_RE = /^ACP request timed out: session\/prompt(?: \(failed \d+ attempts\))?$/;
|
|
35324
|
-
function classifyClaudeCanaryFailure(detail, typedReasonCode) {
|
|
35494
|
+
function classifyClaudeCanaryFailure(detail, typedReasonCode, peerError) {
|
|
35325
35495
|
const recorded = detail?.trim() ?? "";
|
|
35496
|
+
const peerData = peerError?.data;
|
|
35497
|
+
const peerErrorKind = peerData && typeof peerData === "object" && !Array.isArray(peerData) ? peerData.errorKind : void 0;
|
|
35498
|
+
if (typedReasonCode === "claude_canary_auth_failed" || (typedReasonCode === "rpc_error" || typedReasonCode === null || typedReasonCode === void 0) && (peerError?.code === -32e3 || peerErrorKind === "authentication_failed")) {
|
|
35499
|
+
return { code: "claude_canary_auth_failed", minimumRequiredVersion: null };
|
|
35500
|
+
}
|
|
35326
35501
|
const demanded = CLAUDE_CODE_VERSION_REQUIRED_RE.exec(recorded);
|
|
35327
35502
|
if (demanded?.[2]) {
|
|
35328
35503
|
return {
|
|
@@ -35333,9 +35508,6 @@ function classifyClaudeCanaryFailure(detail, typedReasonCode) {
|
|
|
35333
35508
|
if (typedReasonCode === "claude_canary_timeout" || typedReasonCode === "timeout" || (typedReasonCode === null || typedReasonCode === void 0) && CLAUDE_CANARY_TIMEOUT_RE.test(recorded)) {
|
|
35334
35509
|
return { code: "claude_canary_timeout", minimumRequiredVersion: null };
|
|
35335
35510
|
}
|
|
35336
|
-
if (typedReasonCode === "claude_canary_auth_failed") {
|
|
35337
|
-
return { code: "claude_canary_auth_failed", minimumRequiredVersion: null };
|
|
35338
|
-
}
|
|
35339
35511
|
if (typedReasonCode === "claude_bridge_version_required") {
|
|
35340
35512
|
return {
|
|
35341
35513
|
code: "claude_bridge_version_required",
|
|
@@ -35518,7 +35690,8 @@ var ClaudeListenerModel = class {
|
|
|
35518
35690
|
if (canaryError instanceof AcpPermissionCanaryError) {
|
|
35519
35691
|
const shape = classifyClaudeCanaryFailure(
|
|
35520
35692
|
canaryError.message,
|
|
35521
|
-
canaryError.reasonCode
|
|
35693
|
+
canaryError.reasonCode,
|
|
35694
|
+
canaryError.peerError
|
|
35522
35695
|
);
|
|
35523
35696
|
throw new AcpPermissionCanaryError(
|
|
35524
35697
|
canaryError.message,
|
|
@@ -35754,7 +35927,7 @@ var CodexListenerModel = class {
|
|
|
35754
35927
|
var import_node_crypto18 = require("node:crypto");
|
|
35755
35928
|
|
|
35756
35929
|
// src/cloud/delivery.ts
|
|
35757
|
-
var
|
|
35930
|
+
var UUID_RE15 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
35758
35931
|
var RFC3339_TIMESTAMP_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))$/i;
|
|
35759
35932
|
var DELIVERY_KINDS = /* @__PURE__ */ new Set(["ask", "note"]);
|
|
35760
35933
|
var SENDER_OWNER_RELATIONS2 = /* @__PURE__ */ new Set([
|
|
@@ -35841,7 +36014,7 @@ var DeliveryProtocolError = class extends Error {
|
|
|
35841
36014
|
}
|
|
35842
36015
|
};
|
|
35843
36016
|
function checkedUuid3(value, field) {
|
|
35844
|
-
if (typeof value !== "string" || !
|
|
36017
|
+
if (typeof value !== "string" || !UUID_RE15.test(value)) {
|
|
35845
36018
|
throw new DeliveryProtocolError(
|
|
35846
36019
|
`delivery response returned a malformed ${field}`
|
|
35847
36020
|
);
|
|
@@ -35952,7 +36125,7 @@ function checkedClaimCapabilities(value) {
|
|
|
35952
36125
|
}
|
|
35953
36126
|
function checkedOptionalUuidArray(value, field) {
|
|
35954
36127
|
if (value === void 0) return;
|
|
35955
|
-
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !
|
|
36128
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !UUID_RE15.test(item))) {
|
|
35956
36129
|
throw new DeliveryProtocolError(
|
|
35957
36130
|
`delivery response returned a malformed ${field}`
|
|
35958
36131
|
);
|
|
@@ -36099,7 +36272,7 @@ function checkedCommandId(value) {
|
|
|
36099
36272
|
return value;
|
|
36100
36273
|
}
|
|
36101
36274
|
function checkedUuidRequest(value, field) {
|
|
36102
|
-
if (!
|
|
36275
|
+
if (!UUID_RE15.test(value)) {
|
|
36103
36276
|
throw new Error(`${field} must be a UUID for an agent delivery command`);
|
|
36104
36277
|
}
|
|
36105
36278
|
}
|
|
@@ -36336,7 +36509,7 @@ var DeliveryCommandClient = class {
|
|
|
36336
36509
|
|
|
36337
36510
|
// src/listener/main-routing.ts
|
|
36338
36511
|
var import_node_path15 = require("node:path");
|
|
36339
|
-
var
|
|
36512
|
+
var UUID_RE16 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
36340
36513
|
var MAX_QUEUE_BYTES = 1024 * 1024;
|
|
36341
36514
|
var QUEUE_FILE = "pending-for-main.json";
|
|
36342
36515
|
var QUEUE_LOCK = "pending-for-main";
|
|
@@ -36393,7 +36566,7 @@ function parseEntry(value, rejectUnknownKeys) {
|
|
|
36393
36566
|
if (rejectUnknownKeys && Object.keys(row).some((key2) => !ENTRY_KEYS.has(key2))) {
|
|
36394
36567
|
throw new Error("stored pending-for-main entry is malformed");
|
|
36395
36568
|
}
|
|
36396
|
-
if (typeof row.signalId !== "string" || !
|
|
36569
|
+
if (typeof row.signalId !== "string" || !UUID_RE16.test(row.signalId) || typeof row.workspaceId !== "string" || !UUID_RE16.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE16.test(row.principalId) || typeof row.fromId !== "string" || !UUID_RE16.test(row.fromId) || row.fromKind !== "user" && row.fromKind !== "agent" || !(row.kind === void 0 || row.kind === "ask" || row.kind === "note") || !(row.senderName === null || typeof row.senderName === "string" && row.senderName.length <= 200) || typeof row.body !== "string" || row.body.length < 1 || !(row.attachmentCount === void 0 || typeof row.attachmentCount === "number" && Number.isSafeInteger(row.attachmentCount) && row.attachmentCount >= 1 && row.attachmentCount <= 8) || !checkedTimestamp2(row.createdAt) || !checkedTimestamp2(row.queuedAt) || !(row.observationPending === void 0 || row.observationPending === true)) {
|
|
36397
36570
|
throw new Error("stored pending-for-main entry is malformed");
|
|
36398
36571
|
}
|
|
36399
36572
|
return {
|
|
@@ -36533,7 +36706,7 @@ var LISTENER_PROMPT_START_MINIMUM_MS = SIGNAL_READ_TIMEOUT_MS + ACP_DEFAULT_REQU
|
|
|
36533
36706
|
var LISTENER_DELIVERY_RETRY_INITIAL_MS = 500;
|
|
36534
36707
|
var LISTENER_DELIVERY_RETRY_MAX_MS = 3e4;
|
|
36535
36708
|
var LISTENER_HOST_PORTS_PROBE_MS = 6e4;
|
|
36536
|
-
var
|
|
36709
|
+
var UUID_RE17 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
36537
36710
|
var ListenerCapabilityError = class extends Error {
|
|
36538
36711
|
code;
|
|
36539
36712
|
constructor(code, message) {
|
|
@@ -36811,7 +36984,7 @@ async function runListenerRuntime(options) {
|
|
|
36811
36984
|
new Error("listener instance id and delivery journal must be configured together")
|
|
36812
36985
|
);
|
|
36813
36986
|
}
|
|
36814
|
-
if (hasInstanceId && !
|
|
36987
|
+
if (hasInstanceId && !UUID_RE17.test(options.listenerInstanceId)) {
|
|
36815
36988
|
return await closeBeforeStart(
|
|
36816
36989
|
options.model,
|
|
36817
36990
|
new Error("listener instance id must be a UUID")
|
|
@@ -37923,7 +38096,7 @@ var import_node_crypto19 = require("node:crypto");
|
|
|
37923
38096
|
var import_node_net = require("node:net");
|
|
37924
38097
|
var import_promises9 = require("node:fs/promises");
|
|
37925
38098
|
var import_node_path16 = require("node:path");
|
|
37926
|
-
var
|
|
38099
|
+
var UUID_RE18 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
37927
38100
|
var SEMVER_RE2 = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
37928
38101
|
var MAX_STATUS_BYTES = 32 * 1024;
|
|
37929
38102
|
var MAX_CONTROL_BYTES = 8 * 1024;
|
|
@@ -38052,11 +38225,11 @@ function parseStatus(raw, rejectUnknownKeys = false) {
|
|
|
38052
38225
|
throw new Error("stored listener status is malformed");
|
|
38053
38226
|
}
|
|
38054
38227
|
}
|
|
38055
|
-
const nullableUuid3 = (candidate) => candidate === null || typeof candidate === "string" &&
|
|
38228
|
+
const nullableUuid3 = (candidate) => candidate === null || typeof candidate === "string" && UUID_RE18.test(candidate);
|
|
38056
38229
|
const nullableCount = (candidate) => candidate === null || typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate >= 0;
|
|
38057
38230
|
const nullableTimestamp3 = (candidate) => candidate === null || typeof candidate === "string" && Number.isFinite(Date.parse(candidate));
|
|
38058
38231
|
const readHealth = row.readHealth === void 0 ? void 0 : parseListenerReadHealth(row.readHealth, rejectUnknownKeys);
|
|
38059
|
-
if (row.version !== 1 || typeof row.instanceId !== "string" || !
|
|
38232
|
+
if (row.version !== 1 || typeof row.instanceId !== "string" || !UUID_RE18.test(row.instanceId) || row.provider !== "grok" && row.provider !== "opencode" && row.provider !== "claude" && row.provider !== "codex" || typeof row.profileId !== "string" || typeof row.workspaceId !== "string" || !UUID_RE18.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE18.test(row.principalId) || !Number.isSafeInteger(row.pid) || row.pid < 1 || typeof row.state !== "string" || !["starting", "ready", "stopping", "stopped", "failed"].includes(row.state) || typeof row.startedAt !== "string" || !Number.isFinite(Date.parse(row.startedAt)) || !(row.readyAt === null || typeof row.readyAt === "string" && Number.isFinite(Date.parse(row.readyAt))) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt)) || !(row.stoppedAt === null || typeof row.stoppedAt === "string" && Number.isFinite(Date.parse(row.stoppedAt))) || !nullableUuid3(row.lastSignalId) || !(row.lastErrorCode === null || typeof row.lastErrorCode === "string" && /^[a-z0-9_-]{1,96}$/.test(row.lastErrorCode)) || !(row.lastErrorDetail === void 0 || row.lastErrorDetail === null || typeof row.lastErrorDetail === "string" && row.lastErrorDetail.length > 0 && row.lastErrorDetail.length <= 2048 && !/swm_(?:agt|inv|cap)_/i.test(row.lastErrorDetail)) || !(row.lastErrorReasonCode === void 0 || row.lastErrorReasonCode === null || typeof row.lastErrorReasonCode === "string" && /^[a-z0-9_-]{1,96}$/.test(row.lastErrorReasonCode)) || !(row.providerExecutable === void 0 || row.providerExecutable === null || typeof row.providerExecutable === "string" && (0, import_node_path16.isAbsolute)(row.providerExecutable)) || !(row.providerVersion === void 0 || row.providerVersion === null || typeof row.providerVersion === "string" && SEMVER_RE2.test(row.providerVersion)) || !(row.providerLastMeasuredVersion === void 0 || row.providerLastMeasuredVersion === null || typeof row.providerLastMeasuredVersion === "string" && SEMVER_RE2.test(row.providerLastMeasuredVersion)) || !(row.providerBundledAgentSdkVersion === void 0 || row.providerBundledAgentSdkVersion === null || typeof row.providerBundledAgentSdkVersion === "string" && SEMVER_RE2.test(row.providerBundledAgentSdkVersion)) || !(row.providerBundledClaudeCodeVersion === void 0 || row.providerBundledClaudeCodeVersion === null || typeof row.providerBundledClaudeCodeVersion === "string" && SEMVER_RE2.test(row.providerBundledClaudeCodeVersion)) || !(row.providerMinimumRequiredVersion === void 0 || row.providerMinimumRequiredVersion === null || typeof row.providerMinimumRequiredVersion === "string" && SEMVER_RE2.test(row.providerMinimumRequiredVersion)) || !(row.cswarmVersion === void 0 || row.cswarmVersion === null || typeof row.cswarmVersion === "string" && SEMVER_RE2.test(row.cswarmVersion)) || (row.providerVersion === null || row.providerVersion === void 0) !== (row.providerLastMeasuredVersion === null || row.providerLastMeasuredVersion === void 0) || !(row.lastWorkerStderrTail === void 0 || row.lastWorkerStderrTail === null || typeof row.lastWorkerStderrTail === "string" && row.lastWorkerStderrTail.length > 0 && row.lastWorkerStderrTail.length <= 2048 && !/swm_(?:agt|inv|cap)_/i.test(row.lastWorkerStderrTail)) || typeof row.logPath !== "string" || !(0, import_node_path16.isAbsolute)(row.logPath) || !(row.deliveryMode === void 0 || row.deliveryMode === null || typeof row.deliveryMode === "string" && STATUS_DELIVERY_MODES.has(row.deliveryMode)) || !(row.pendingDeliveryCount === void 0 || nullableCount(row.pendingDeliveryCount)) || !(row.lastTerminalDeliveryFailureCount === void 0 || nullableCount(row.lastTerminalDeliveryFailureCount)) || !(row.lastTerminalDeliveryFailureAt === void 0 || nullableTimestamp3(row.lastTerminalDeliveryFailureAt)) || !(row.lastClaimAt === void 0 || nullableTimestamp3(row.lastClaimAt)) || !(row.lastAckAt === void 0 || nullableTimestamp3(row.lastAckAt)) || !(row.routeMode === void 0 || row.routeMode === "worker" || row.routeMode === "main" || row.routeMode === "split") || !(row.deferOverChars === void 0 || row.deferOverChars === null || typeof row.deferOverChars === "number" && Number.isSafeInteger(row.deferOverChars) && row.deferOverChars >= 1 && row.deferOverChars <= 1e4) || !(row.pendingForMainCount === void 0 || typeof row.pendingForMainCount === "number" && Number.isSafeInteger(row.pendingForMainCount) && row.pendingForMainCount >= 0) || !(row.droppedForMainCount === void 0 || typeof row.droppedForMainCount === "number" && Number.isSafeInteger(row.droppedForMainCount) && row.droppedForMainCount >= 0) || readHealth === null || !(row.connectionsOpened === void 0 || typeof row.connectionsOpened === "number" && Number.isSafeInteger(row.connectionsOpened) && row.connectionsOpened >= 0) || !(row.connectionReuseRatio === void 0 || typeof row.connectionReuseRatio === "number" && Number.isFinite(row.connectionReuseRatio) && row.connectionReuseRatio >= 0) || !(row.activityPublishFailures === void 0 || typeof row.activityPublishFailures === "number" && Number.isSafeInteger(row.activityPublishFailures) && row.activityPublishFailures >= 0) || !(row.activityLastErrorCode === void 0 || row.activityLastErrorCode === null || typeof row.activityLastErrorCode === "string" && STATUS_ACTIVITY_ERROR_CODES.has(
|
|
38060
38233
|
row.activityLastErrorCode
|
|
38061
38234
|
))) {
|
|
38062
38235
|
throw new Error("stored listener status is malformed");
|
|
@@ -38474,7 +38647,7 @@ async function queryListenerControl(paths, command2, timeoutMs = CONTROL_TIMEOUT
|
|
|
38474
38647
|
|
|
38475
38648
|
// src/listener/supervisor.ts
|
|
38476
38649
|
var import_node_crypto20 = require("node:crypto");
|
|
38477
|
-
var
|
|
38650
|
+
var UUID_RE19 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
38478
38651
|
var LISTENER_RESTART_MAX_ATTEMPTS = 5;
|
|
38479
38652
|
var LISTENER_RESTART_INITIAL_MS = 1e3;
|
|
38480
38653
|
var LISTENER_RESTART_MAX_MS = 6e4;
|
|
@@ -38658,7 +38831,7 @@ async function runListenerSupervisor(options) {
|
|
|
38658
38831
|
// before the socket can answer, before any status/event persistence.
|
|
38659
38832
|
initialize: prepare ? async () => {
|
|
38660
38833
|
const selected = await prepare(proposedInstanceId);
|
|
38661
|
-
if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !
|
|
38834
|
+
if (!selected || typeof selected !== "object" || typeof selected.instanceId !== "string" || !UUID_RE19.test(selected.instanceId)) {
|
|
38662
38835
|
throw new Error("listener prepare returned an invalid instance id");
|
|
38663
38836
|
}
|
|
38664
38837
|
status = { ...status, instanceId: selected.instanceId };
|
|
@@ -39103,7 +39276,7 @@ async function waitForListenerReady(paths, options = {}) {
|
|
|
39103
39276
|
// src/listener/delivery-journal.ts
|
|
39104
39277
|
var import_node_path17 = require("node:path");
|
|
39105
39278
|
var import_node_util2 = require("node:util");
|
|
39106
|
-
var
|
|
39279
|
+
var UUID_RE20 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
39107
39280
|
var COMMAND_ID_RE3 = /^[A-Za-z0-9_-]{8,72}$/;
|
|
39108
39281
|
var SIGNAL_FINGERPRINT_RE = /^[0-9a-f]{64}$/;
|
|
39109
39282
|
var MAX_JOURNAL_BYTES = 8192;
|
|
@@ -39198,7 +39371,7 @@ var ALLOWED_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
|
39198
39371
|
"credential_unavailable"
|
|
39199
39372
|
]);
|
|
39200
39373
|
function claimCommandId(listenerInstanceId, claimOrdinal) {
|
|
39201
|
-
if (!
|
|
39374
|
+
if (!UUID_RE20.test(listenerInstanceId)) {
|
|
39202
39375
|
throw new Error("stored delivery journal is malformed");
|
|
39203
39376
|
}
|
|
39204
39377
|
if (!Number.isSafeInteger(claimOrdinal) || claimOrdinal < 0) {
|
|
@@ -39213,7 +39386,7 @@ function claimCommandId(listenerInstanceId, claimOrdinal) {
|
|
|
39213
39386
|
return id;
|
|
39214
39387
|
}
|
|
39215
39388
|
function ackCommandId(leaseId) {
|
|
39216
|
-
if (!
|
|
39389
|
+
if (!UUID_RE20.test(leaseId)) {
|
|
39217
39390
|
throw new Error("stored delivery journal is malformed");
|
|
39218
39391
|
}
|
|
39219
39392
|
const cleanLease = leaseId.toLowerCase().replace(/-/g, "");
|
|
@@ -39296,19 +39469,19 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId, rejec
|
|
|
39296
39469
|
if (row.version !== 1) {
|
|
39297
39470
|
throw new Error("stored delivery journal is malformed");
|
|
39298
39471
|
}
|
|
39299
|
-
if (typeof row.workspaceId !== "string" || !
|
|
39472
|
+
if (typeof row.workspaceId !== "string" || !UUID_RE20.test(row.workspaceId) || row.workspaceId !== row.workspaceId.toLowerCase()) {
|
|
39300
39473
|
throw new Error("stored delivery journal is malformed");
|
|
39301
39474
|
}
|
|
39302
39475
|
if (expectedWorkspaceId && row.workspaceId !== expectedWorkspaceId.toLowerCase()) {
|
|
39303
39476
|
throw new Error("stored delivery journal is malformed");
|
|
39304
39477
|
}
|
|
39305
|
-
if (typeof row.principalId !== "string" || !
|
|
39478
|
+
if (typeof row.principalId !== "string" || !UUID_RE20.test(row.principalId) || row.principalId !== row.principalId.toLowerCase()) {
|
|
39306
39479
|
throw new Error("stored delivery journal is malformed");
|
|
39307
39480
|
}
|
|
39308
39481
|
if (expectedPrincipalId && row.principalId !== expectedPrincipalId.toLowerCase()) {
|
|
39309
39482
|
throw new Error("stored delivery journal is malformed");
|
|
39310
39483
|
}
|
|
39311
|
-
if (typeof row.listenerInstanceId !== "string" || !
|
|
39484
|
+
if (typeof row.listenerInstanceId !== "string" || !UUID_RE20.test(row.listenerInstanceId) || row.listenerInstanceId !== row.listenerInstanceId.toLowerCase()) {
|
|
39312
39485
|
throw new Error("stored delivery journal is malformed");
|
|
39313
39486
|
}
|
|
39314
39487
|
if (!Number.isSafeInteger(row.nextClaimOrdinal) || row.nextClaimOrdinal < 0) {
|
|
@@ -39382,10 +39555,10 @@ function parseJournalRecord(raw, expectedWorkspaceId, expectedPrincipalId, rejec
|
|
|
39382
39555
|
if (active.claimLastAttemptAt === null) {
|
|
39383
39556
|
throw new Error("stored delivery journal is malformed");
|
|
39384
39557
|
}
|
|
39385
|
-
if (typeof active.signalId !== "string" || !
|
|
39558
|
+
if (typeof active.signalId !== "string" || !UUID_RE20.test(active.signalId) || active.signalId !== active.signalId.toLowerCase()) {
|
|
39386
39559
|
throw new Error("stored delivery journal is malformed");
|
|
39387
39560
|
}
|
|
39388
|
-
if (typeof active.leaseId !== "string" || !
|
|
39561
|
+
if (typeof active.leaseId !== "string" || !UUID_RE20.test(active.leaseId) || active.leaseId !== active.leaseId.toLowerCase()) {
|
|
39389
39562
|
throw new Error("stored delivery journal is malformed");
|
|
39390
39563
|
}
|
|
39391
39564
|
if (!isValidIsoTimestamp(active.leasedUntil) || Date.parse(active.leasedUntil) <= Date.parse(active.claimCreatedAt)) {
|
|
@@ -39477,7 +39650,7 @@ var FileListenerDeliveryJournal = class {
|
|
|
39477
39650
|
["profileId", "workspaceId", "principalId"],
|
|
39478
39651
|
"delivery journal configuration rejected"
|
|
39479
39652
|
);
|
|
39480
|
-
if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !
|
|
39653
|
+
if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE20.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE20.test(options.principalId)) {
|
|
39481
39654
|
throw new Error("delivery journal configuration rejected");
|
|
39482
39655
|
}
|
|
39483
39656
|
if (options.stateDirectory !== void 0) {
|
|
@@ -39599,7 +39772,7 @@ var FileListenerDeliveryJournal = class {
|
|
|
39599
39772
|
["signalId", "leaseId", "leasedUntil"],
|
|
39600
39773
|
"delivery journal mutation rejected"
|
|
39601
39774
|
);
|
|
39602
|
-
if (typeof input.signalId !== "string" || !
|
|
39775
|
+
if (typeof input.signalId !== "string" || !UUID_RE20.test(input.signalId) || typeof input.leaseId !== "string" || !UUID_RE20.test(input.leaseId) || !isValidIsoTimestamp(input.leasedUntil) || input.signalFingerprint !== void 0 && (typeof input.signalFingerprint !== "string" || !SIGNAL_FINGERPRINT_RE.test(input.signalFingerprint))) {
|
|
39603
39776
|
throw new Error("delivery journal mutation rejected");
|
|
39604
39777
|
}
|
|
39605
39778
|
const canonicalSignalId = input.signalId.toLowerCase();
|
|
@@ -39731,7 +39904,7 @@ async function openListenerDeliveryJournal(options) {
|
|
|
39731
39904
|
["profileId", "workspaceId", "principalId", "proposedListenerInstanceId"],
|
|
39732
39905
|
"delivery journal configuration rejected"
|
|
39733
39906
|
);
|
|
39734
|
-
if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !
|
|
39907
|
+
if (typeof options.profileId !== "string" || !options.profileId || options.profileId.includes("\0") || typeof options.workspaceId !== "string" || !UUID_RE20.test(options.workspaceId) || typeof options.principalId !== "string" || !UUID_RE20.test(options.principalId) || typeof options.proposedListenerInstanceId !== "string" || !UUID_RE20.test(options.proposedListenerInstanceId)) {
|
|
39735
39908
|
throw new Error("delivery journal configuration rejected");
|
|
39736
39909
|
}
|
|
39737
39910
|
if (options.stateDirectory !== void 0) {
|
|
@@ -39951,7 +40124,7 @@ var import_node_path20 = require("node:path");
|
|
|
39951
40124
|
|
|
39952
40125
|
// src/listener/brain-digest.ts
|
|
39953
40126
|
var import_node_path19 = require("node:path");
|
|
39954
|
-
var
|
|
40127
|
+
var UUID_RE21 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
39955
40128
|
var TOPIC_RE = /^[a-z0-9][a-z0-9._-]*$/;
|
|
39956
40129
|
var BRAIN_DIGEST_FILE = "brain-digest.json";
|
|
39957
40130
|
var BRAIN_DIGEST_LOCK = "brain-digest";
|
|
@@ -39971,7 +40144,7 @@ function parseState(raw) {
|
|
|
39971
40144
|
}
|
|
39972
40145
|
const row = value;
|
|
39973
40146
|
const topicVersions = row.topicVersions;
|
|
39974
|
-
if (row.version !== 1 || typeof row.principalId !== "string" || !
|
|
40147
|
+
if (row.version !== 1 || typeof row.principalId !== "string" || !UUID_RE21.test(row.principalId) || !topicVersions || typeof topicVersions !== "object" || Array.isArray(topicVersions) || Object.keys(topicVersions).length > MAX_BRAIN_DIGEST_TOPICS) {
|
|
39975
40148
|
throw new Error("stored brain digest state is malformed");
|
|
39976
40149
|
}
|
|
39977
40150
|
for (const [topic, version3] of Object.entries(topicVersions)) {
|
|
@@ -40014,7 +40187,7 @@ function renderBrainDigest(topicCount, topics) {
|
|
|
40014
40187
|
var FileBrainDigestStore = class {
|
|
40015
40188
|
constructor(instanceDirectory, principalId) {
|
|
40016
40189
|
this.instanceDirectory = instanceDirectory;
|
|
40017
|
-
if (!(0, import_node_path19.isAbsolute)(instanceDirectory) || !
|
|
40190
|
+
if (!(0, import_node_path19.isAbsolute)(instanceDirectory) || !UUID_RE21.test(principalId)) {
|
|
40018
40191
|
throw new Error("brain digest state needs an absolute listener directory and principal UUID");
|
|
40019
40192
|
}
|
|
40020
40193
|
this.principalId = principalId.toLowerCase();
|
|
@@ -40061,7 +40234,7 @@ var FileBrainDigestStore = class {
|
|
|
40061
40234
|
};
|
|
40062
40235
|
|
|
40063
40236
|
// src/listener/hook.ts
|
|
40064
|
-
var
|
|
40237
|
+
var UUID_RE22 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
40065
40238
|
var TOKEN_RE = /^swm_agt_[A-Za-z0-9_-]{43}$/;
|
|
40066
40239
|
var INSTANCE_KEY_RE = /^[0-9a-f]{64}$/;
|
|
40067
40240
|
var MAX_HOOK_CREDENTIAL_BYTES = 8 * 1024;
|
|
@@ -40113,7 +40286,7 @@ function parseListenerCredential(raw, rejectUnknownKeys = false) {
|
|
|
40113
40286
|
throw new Error("stored listener hook credential is malformed");
|
|
40114
40287
|
}
|
|
40115
40288
|
const row = value;
|
|
40116
|
-
if (!(rejectUnknownKeys ? exactKeys2(row, LISTENER_CREDENTIAL_KEYS) : hasRequiredKeys(row, LISTENER_CREDENTIAL_KEYS)) || row.version !== 1 || typeof row.profileId !== "string" || !/^[0-9a-f]{24}$/.test(row.profileId) || typeof row.targetUrl !== "string" || typeof row.anonKey !== "string" || row.anonKey.length < 1 || row.anonKey.length > 4096 || typeof row.workspaceId !== "string" || !
|
|
40289
|
+
if (!(rejectUnknownKeys ? exactKeys2(row, LISTENER_CREDENTIAL_KEYS) : hasRequiredKeys(row, LISTENER_CREDENTIAL_KEYS)) || row.version !== 1 || typeof row.profileId !== "string" || !/^[0-9a-f]{24}$/.test(row.profileId) || typeof row.targetUrl !== "string" || typeof row.anonKey !== "string" || row.anonKey.length < 1 || row.anonKey.length > 4096 || typeof row.workspaceId !== "string" || !UUID_RE22.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE22.test(row.principalId) || typeof row.credential !== "string" || !TOKEN_RE.test(row.credential) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt))) {
|
|
40117
40290
|
throw new Error("stored listener hook credential is malformed");
|
|
40118
40291
|
}
|
|
40119
40292
|
const target2 = cloudTarget(row.targetUrl, row.anonKey);
|
|
@@ -40171,7 +40344,7 @@ function parseSurface(raw, rejectUnknownKeys = false) {
|
|
|
40171
40344
|
throw new Error("stored listener hook surface state is malformed");
|
|
40172
40345
|
}
|
|
40173
40346
|
const row = value;
|
|
40174
|
-
if (rejectUnknownKeys && Object.keys(row).some((key2) => !HOOK_SURFACE_KEYS.has(key2)) || row.version !== 1 || !Array.isArray(row.surfacedSignalIds) || row.surfacedSignalIds.length > HOOK_SURFACED_IDS_MAX || row.surfacedSignalIds.some((id) => typeof id !== "string" || !
|
|
40347
|
+
if (rejectUnknownKeys && Object.keys(row).some((key2) => !HOOK_SURFACE_KEYS.has(key2)) || row.version !== 1 || !Array.isArray(row.surfacedSignalIds) || row.surfacedSignalIds.length > HOOK_SURFACED_IDS_MAX || row.surfacedSignalIds.some((id) => typeof id !== "string" || !UUID_RE22.test(id)) || !(row.reportedDroppedCount === void 0 || typeof row.reportedDroppedCount === "number" && Number.isSafeInteger(row.reportedDroppedCount) && row.reportedDroppedCount >= 0) || !(row.credentialFailureReported === void 0 || typeof row.credentialFailureReported === "boolean")) {
|
|
40175
40348
|
throw new Error("stored listener hook surface state is malformed");
|
|
40176
40349
|
}
|
|
40177
40350
|
const ids = row.surfacedSignalIds.map((id) => String(id).toLowerCase());
|
|
@@ -40202,7 +40375,7 @@ var FileHookSurfaceStore = class {
|
|
|
40202
40375
|
const unseen = [];
|
|
40203
40376
|
for (const item of items) {
|
|
40204
40377
|
const signalId = item.signalId.toLowerCase();
|
|
40205
|
-
if (!
|
|
40378
|
+
if (!UUID_RE22.test(signalId) || seen.has(signalId)) continue;
|
|
40206
40379
|
seen.add(signalId);
|
|
40207
40380
|
unseen.push(item);
|
|
40208
40381
|
}
|
|
@@ -40233,7 +40406,7 @@ var FileHookSurfaceStore = class {
|
|
|
40233
40406
|
const unseen = [];
|
|
40234
40407
|
for (const item of items) {
|
|
40235
40408
|
const signalId = item.signalId.toLowerCase();
|
|
40236
|
-
if (!
|
|
40409
|
+
if (!UUID_RE22.test(signalId) || seen.has(signalId)) continue;
|
|
40237
40410
|
seen.add(signalId);
|
|
40238
40411
|
unseen.push(item);
|
|
40239
40412
|
}
|
|
@@ -40256,7 +40429,7 @@ var FileHookSurfaceStore = class {
|
|
|
40256
40429
|
const seen = new Set(state.surfacedSignalIds);
|
|
40257
40430
|
for (const signalId of options.signalIds ?? []) {
|
|
40258
40431
|
const checked = signalId.toLowerCase();
|
|
40259
|
-
if (
|
|
40432
|
+
if (UUID_RE22.test(checked)) seen.add(checked);
|
|
40260
40433
|
}
|
|
40261
40434
|
await writeSecureJsonFile(
|
|
40262
40435
|
this.path,
|
|
@@ -40385,7 +40558,7 @@ async function discoverContexts(stateDirectory2, principalIds, isListenerLive =
|
|
|
40385
40558
|
}
|
|
40386
40559
|
selectedPrincipals = availablePrincipals;
|
|
40387
40560
|
} else {
|
|
40388
|
-
if (principalIds.some((principalId) => !
|
|
40561
|
+
if (principalIds.some((principalId) => !UUID_RE22.test(principalId))) {
|
|
40389
40562
|
return { contexts: [], requiresPrincipalScope: false };
|
|
40390
40563
|
}
|
|
40391
40564
|
selectedPrincipals = new Set(principalIds.map((principalId) => principalId.toLowerCase()));
|
|
@@ -41814,16 +41987,10 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
41814
41987
|
"user",
|
|
41815
41988
|
"write"
|
|
41816
41989
|
]);
|
|
41817
|
-
var
|
|
41818
|
-
var AGENT_CREDENTIAL_MESSAGE = "Agent credential minted. It is bound to this task and run so the agent's work stays scoped and attributable.";
|
|
41819
|
-
var AGENT_CREDENTIAL_MESSAGE_D088 = "Agent credential minted. It is bound to this run, so the agent's work is attributable to it.";
|
|
41820
|
-
var ACCEPTED_AGENT_CREDENTIAL_MESSAGES = [
|
|
41821
|
-
AGENT_CREDENTIAL_MESSAGE,
|
|
41822
|
-
AGENT_CREDENTIAL_MESSAGE_D088
|
|
41823
|
-
];
|
|
41990
|
+
var UUID_RE23 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
41824
41991
|
function packageVersion() {
|
|
41825
|
-
if ("0.1.
|
|
41826
|
-
return "0.1.
|
|
41992
|
+
if ("0.1.50".length > 0) {
|
|
41993
|
+
return "0.1.50";
|
|
41827
41994
|
}
|
|
41828
41995
|
try {
|
|
41829
41996
|
const value = JSON.parse(
|
|
@@ -42168,58 +42335,6 @@ function agentCredentialArtifact(input) {
|
|
|
42168
42335
|
...input.expiresAt === void 0 || input.expiresAt === null ? {} : { expires_at: new Date(input.expiresAt).toISOString() }
|
|
42169
42336
|
};
|
|
42170
42337
|
}
|
|
42171
|
-
function parsedAgentCredential(value) {
|
|
42172
|
-
if (!value.startsWith("{")) {
|
|
42173
|
-
assertAgentToken(value);
|
|
42174
|
-
return {
|
|
42175
|
-
token: value,
|
|
42176
|
-
principalId: null,
|
|
42177
|
-
tokenId: null,
|
|
42178
|
-
runId: null,
|
|
42179
|
-
expiresAt: null,
|
|
42180
|
-
durable: false
|
|
42181
|
-
};
|
|
42182
|
-
}
|
|
42183
|
-
const parsed = JSON.parse(value);
|
|
42184
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
42185
|
-
throw new Error("agent credential JSON is malformed");
|
|
42186
|
-
}
|
|
42187
|
-
const artifact = parsed;
|
|
42188
|
-
const requiredKeys = [
|
|
42189
|
-
"agent_token",
|
|
42190
|
-
"message",
|
|
42191
|
-
"principal_id",
|
|
42192
|
-
"run_id",
|
|
42193
|
-
"status",
|
|
42194
|
-
"token_id"
|
|
42195
|
-
];
|
|
42196
|
-
const withExpiry = [...requiredKeys, "expires_at"].sort();
|
|
42197
|
-
const actualKeys = Object.keys(artifact).sort();
|
|
42198
|
-
const shape = actualKeys.length === requiredKeys.length ? requiredKeys : withExpiry;
|
|
42199
|
-
if (actualKeys.length !== shape.length || !actualKeys.every((key2, index) => key2 === shape[index]) || !ACCEPTED_AGENT_CREDENTIAL_MESSAGES.includes(artifact.message) || artifact.status !== "accepted" || typeof artifact.principal_id !== "string" || !UUID_RE22.test(artifact.principal_id) || typeof artifact.token_id !== "string" || !UUID_RE22.test(artifact.token_id) || typeof artifact.run_id !== "string" || !UUID_RE22.test(artifact.run_id) || typeof artifact.agent_token !== "string") {
|
|
42200
|
-
throw new Error("agent credential JSON is malformed");
|
|
42201
|
-
}
|
|
42202
|
-
let expiresAt = null;
|
|
42203
|
-
if (artifact.expires_at !== void 0) {
|
|
42204
|
-
if (typeof artifact.expires_at !== "string") {
|
|
42205
|
-
throw new Error("agent credential JSON is malformed");
|
|
42206
|
-
}
|
|
42207
|
-
const parsedExpiry = Date.parse(artifact.expires_at);
|
|
42208
|
-
if (Number.isNaN(parsedExpiry)) {
|
|
42209
|
-
throw new Error("agent credential JSON is malformed");
|
|
42210
|
-
}
|
|
42211
|
-
expiresAt = parsedExpiry;
|
|
42212
|
-
}
|
|
42213
|
-
assertAgentToken(artifact.agent_token);
|
|
42214
|
-
return {
|
|
42215
|
-
token: artifact.agent_token,
|
|
42216
|
-
principalId: artifact.principal_id.toLowerCase(),
|
|
42217
|
-
tokenId: artifact.token_id.toLowerCase(),
|
|
42218
|
-
runId: artifact.run_id.toLowerCase(),
|
|
42219
|
-
expiresAt,
|
|
42220
|
-
durable: true
|
|
42221
|
-
};
|
|
42222
|
-
}
|
|
42223
42338
|
async function stdinCredential() {
|
|
42224
42339
|
if (process.stdin.isTTY) {
|
|
42225
42340
|
throw new Error(
|
|
@@ -42234,7 +42349,7 @@ async function stdinCredential() {
|
|
|
42234
42349
|
}
|
|
42235
42350
|
}
|
|
42236
42351
|
const credential = value.trim();
|
|
42237
|
-
return
|
|
42352
|
+
return parseAgentCredentialInput(credential, { kind: "stdin" });
|
|
42238
42353
|
}
|
|
42239
42354
|
var AgentTokenFileError = class extends Error {
|
|
42240
42355
|
constructor(code, message) {
|
|
@@ -42272,7 +42387,10 @@ async function agentCredential(args, options = {}) {
|
|
|
42272
42387
|
`--agent-token-file does not exist: ${fromFile}`
|
|
42273
42388
|
);
|
|
42274
42389
|
}
|
|
42275
|
-
return
|
|
42390
|
+
return parseAgentCredentialInput(value.trim(), {
|
|
42391
|
+
kind: "file",
|
|
42392
|
+
path: fromFile
|
|
42393
|
+
});
|
|
42276
42394
|
}
|
|
42277
42395
|
if (fromStdin || options.implicitStdin === true) {
|
|
42278
42396
|
return await stdinCredential();
|
|
@@ -42340,6 +42458,18 @@ async function humanCredential(args, cloud) {
|
|
|
42340
42458
|
store: credentials
|
|
42341
42459
|
};
|
|
42342
42460
|
}
|
|
42461
|
+
async function dualAuthHumanCredential(args, cloud) {
|
|
42462
|
+
try {
|
|
42463
|
+
return await humanCredential(args, cloud);
|
|
42464
|
+
} catch (error) {
|
|
42465
|
+
if (!(error instanceof HumanSessionError)) throw error;
|
|
42466
|
+
const personPath = error.code === "human_session_missing" ? "not signed in. If you are a person, run cswarm login." : "could not refresh your session. If you are a person, run cswarm login to sign in again.";
|
|
42467
|
+
throw new HumanSessionError(
|
|
42468
|
+
error.code,
|
|
42469
|
+
`${personPath} If you are an agent, pass --agent-token-file <path to the credential CommonSwarm minted for you> (or --agent-token-stdin).`
|
|
42470
|
+
);
|
|
42471
|
+
}
|
|
42472
|
+
}
|
|
42343
42473
|
function writeWorkspaceWarning(warning) {
|
|
42344
42474
|
process.stderr.write(`cswarm: ${warning.message}
|
|
42345
42475
|
`);
|
|
@@ -42479,7 +42609,7 @@ async function runNew(args) {
|
|
|
42479
42609
|
project: {
|
|
42480
42610
|
workspace_id: created,
|
|
42481
42611
|
name,
|
|
42482
|
-
stream_id: typeof response.stream_id === "string" &&
|
|
42612
|
+
stream_id: typeof response.stream_id === "string" && UUID_RE23.test(response.stream_id) ? response.stream_id : null
|
|
42483
42613
|
}
|
|
42484
42614
|
});
|
|
42485
42615
|
return;
|
|
@@ -43221,7 +43351,7 @@ async function runTokenRevoke(args) {
|
|
|
43221
43351
|
2
|
|
43222
43352
|
);
|
|
43223
43353
|
const cloud = await target(args);
|
|
43224
|
-
const human = await
|
|
43354
|
+
const human = await dualAuthHumanCredential(args, cloud);
|
|
43225
43355
|
const workspace = await workspaceId(args, cloud, human);
|
|
43226
43356
|
const tokenId = args.required("token-id");
|
|
43227
43357
|
const response = (await sendConnectWithPending(
|
|
@@ -43288,7 +43418,7 @@ async function runLinkNew(args) {
|
|
|
43288
43418
|
2
|
|
43289
43419
|
);
|
|
43290
43420
|
const taskId = args.required("task-id");
|
|
43291
|
-
if (!
|
|
43421
|
+
if (!UUID_RE23.test(taskId)) {
|
|
43292
43422
|
throw new Error("--task-id must be the work item's UUID");
|
|
43293
43423
|
}
|
|
43294
43424
|
const site = capabilitySiteOrigin(
|
|
@@ -43348,7 +43478,7 @@ async function runLinkRevoke(args) {
|
|
|
43348
43478
|
2
|
|
43349
43479
|
);
|
|
43350
43480
|
const capabilityId = args.required("capability-id");
|
|
43351
|
-
if (!
|
|
43481
|
+
if (!UUID_RE23.test(capabilityId)) {
|
|
43352
43482
|
throw new Error(
|
|
43353
43483
|
"--capability-id must be the id printed when the link was created"
|
|
43354
43484
|
);
|
|
@@ -43521,7 +43651,7 @@ async function commandWorkspaceAndCredential(args, cloud, options = {}) {
|
|
|
43521
43651
|
session
|
|
43522
43652
|
};
|
|
43523
43653
|
}
|
|
43524
|
-
const human = await
|
|
43654
|
+
const human = await dualAuthHumanCredential(args, cloud);
|
|
43525
43655
|
return {
|
|
43526
43656
|
selectedWorkspace: await workspaceId(args, cloud, human, {
|
|
43527
43657
|
validateOverride: options.validateHumanWorkspace ?? false
|
|
@@ -44023,7 +44153,7 @@ async function runReply(args) {
|
|
|
44023
44153
|
"json"
|
|
44024
44154
|
], 3);
|
|
44025
44155
|
const signalId = args.positionals[1];
|
|
44026
|
-
if (signalId === void 0 || !
|
|
44156
|
+
if (signalId === void 0 || !UUID_RE23.test(signalId)) {
|
|
44027
44157
|
throw new Error("reply requires the signal UUID being answered");
|
|
44028
44158
|
}
|
|
44029
44159
|
const body = args.positionals[2];
|
|
@@ -44568,7 +44698,7 @@ async function runReceipt(args) {
|
|
|
44568
44698
|
"json"
|
|
44569
44699
|
], 2);
|
|
44570
44700
|
const signalId = args.positionals[1];
|
|
44571
|
-
if (!
|
|
44701
|
+
if (!UUID_RE23.test(signalId)) {
|
|
44572
44702
|
throw new Error("signal-id must be a UUID");
|
|
44573
44703
|
}
|
|
44574
44704
|
if (!hasAgentCredential(args)) {
|
|
@@ -44728,7 +44858,7 @@ async function runInboxFollowCommand(args) {
|
|
|
44728
44858
|
}
|
|
44729
44859
|
}
|
|
44730
44860
|
function listenerUuid(value, flag) {
|
|
44731
|
-
if (!value || !
|
|
44861
|
+
if (!value || !UUID_RE23.test(value)) {
|
|
44732
44862
|
throw new Error(`--${flag} must be a UUID`);
|
|
44733
44863
|
}
|
|
44734
44864
|
return value.toLowerCase();
|
|
@@ -45317,7 +45447,7 @@ function listenerFailureMessage(code, provider, detail, reasonCode, minimumRequi
|
|
|
45317
45447
|
return `${ran}. ${response}. Next: run claude -p and check for session-limit text, check host load, then retry`;
|
|
45318
45448
|
}
|
|
45319
45449
|
if (shape.code === "claude_canary_auth_failed") {
|
|
45320
|
-
return `${ran}. ${response}. Next:
|
|
45450
|
+
return `${ran}. ${response}. Next: as the operator, sign in with claude auth login on this host (or start claude interactively and complete the prompt), then run cswarm listen start again. Every Claude-provider listener on this host shares that session`;
|
|
45321
45451
|
}
|
|
45322
45452
|
return `${ran}. ${response}. The cause was not determined. Next: inspect the quoted bridge response and local worker stderr, then retry only after the cause is known or the failure appears transient`;
|
|
45323
45453
|
}
|
|
@@ -46391,7 +46521,7 @@ async function runHook(args) {
|
|
|
46391
46521
|
if (command2 === "check") {
|
|
46392
46522
|
args.assertShape(["cooldown", "principal-id"], 2);
|
|
46393
46523
|
const rawPrincipalIds = args.all("principal-id");
|
|
46394
|
-
if (rawPrincipalIds.some((principalId2) => !
|
|
46524
|
+
if (rawPrincipalIds.some((principalId2) => !UUID_RE23.test(principalId2))) return;
|
|
46395
46525
|
const principalIds = rawPrincipalIds.map((principalId2) => principalId2.toLowerCase());
|
|
46396
46526
|
const rawCooldown = args.optional("cooldown");
|
|
46397
46527
|
const cooldownSeconds = rawCooldown === void 0 ? void 0 : Number(rawCooldown);
|
|
@@ -46517,7 +46647,7 @@ async function fileRows(context) {
|
|
|
46517
46647
|
);
|
|
46518
46648
|
}
|
|
46519
46649
|
async function resolveFileSelector(context, selector) {
|
|
46520
|
-
if (
|
|
46650
|
+
if (UUID_RE23.test(selector)) return selector.toLowerCase();
|
|
46521
46651
|
const rows3 = await fileRows(context);
|
|
46522
46652
|
const match = rows3.find(
|
|
46523
46653
|
(row) => row.name.toLowerCase() === selector.toLowerCase()
|