commonswarm 0.1.52 → 0.1.53
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 +300 -200
- package/package.json +1 -1
package/cswarm.cjs
CHANGED
|
@@ -13530,6 +13530,188 @@ var import_node_os10 = require("node:os");
|
|
|
13530
13530
|
var import_node_path21 = require("node:path");
|
|
13531
13531
|
var import_promises13 = require("node:readline/promises");
|
|
13532
13532
|
|
|
13533
|
+
// src/protocol/events.ts
|
|
13534
|
+
var SCHEMA_VERSION = 1;
|
|
13535
|
+
var EVENT_TYPES = [
|
|
13536
|
+
"TaskCreated",
|
|
13537
|
+
"LeaseAcquired",
|
|
13538
|
+
"LeaseRenewed",
|
|
13539
|
+
"LeaseHandedOff",
|
|
13540
|
+
"LeaseTakenOver",
|
|
13541
|
+
"TaskSubmitted",
|
|
13542
|
+
"TaskClosed",
|
|
13543
|
+
"TaskReopened",
|
|
13544
|
+
"CommandRejected"
|
|
13545
|
+
];
|
|
13546
|
+
|
|
13547
|
+
// src/protocol/reducer.ts
|
|
13548
|
+
function req(payload, keys, type, seq) {
|
|
13549
|
+
if (!payload || typeof payload !== "object") throw new StreamIntegrityError(`event "${type}" at seq ${seq} has a non-object payload`);
|
|
13550
|
+
for (const k of keys) {
|
|
13551
|
+
if (payload[k] === void 0) {
|
|
13552
|
+
throw new StreamIntegrityError(`event "${type}" at seq ${seq} is missing payload field "${String(k)}"`);
|
|
13553
|
+
}
|
|
13554
|
+
}
|
|
13555
|
+
return payload;
|
|
13556
|
+
}
|
|
13557
|
+
var UnknownEventTypeError = class extends Error {
|
|
13558
|
+
constructor(type, seq) {
|
|
13559
|
+
super(`unknown authoritative event type "${type}" at seq ${seq}; halting`);
|
|
13560
|
+
this.type = type;
|
|
13561
|
+
this.seq = seq;
|
|
13562
|
+
this.name = "UnknownEventTypeError";
|
|
13563
|
+
}
|
|
13564
|
+
type;
|
|
13565
|
+
seq;
|
|
13566
|
+
};
|
|
13567
|
+
var StreamIntegrityError = class extends Error {
|
|
13568
|
+
constructor(message) {
|
|
13569
|
+
super(message);
|
|
13570
|
+
this.name = "StreamIntegrityError";
|
|
13571
|
+
}
|
|
13572
|
+
};
|
|
13573
|
+
function reduceTask(prev, env) {
|
|
13574
|
+
if (!EVENT_TYPES.includes(env.type)) {
|
|
13575
|
+
throw new UnknownEventTypeError(env.type, env.seq);
|
|
13576
|
+
}
|
|
13577
|
+
if (env.schema_version !== SCHEMA_VERSION) {
|
|
13578
|
+
throw new StreamIntegrityError(`event "${env.type}" at seq ${env.seq} is schema v${env.schema_version}, expected v${SCHEMA_VERSION} (upcast before reduce)`);
|
|
13579
|
+
}
|
|
13580
|
+
if (env.type === "CommandRejected") {
|
|
13581
|
+
if (!prev) throw new StreamIntegrityError(`CommandRejected before task exists (seq ${env.seq})`);
|
|
13582
|
+
req(env.payload, ["task_id", "command", "reason", "detail"], env.type, env.seq);
|
|
13583
|
+
return prev;
|
|
13584
|
+
}
|
|
13585
|
+
if (env.type === "TaskCreated") {
|
|
13586
|
+
if (prev) throw new StreamIntegrityError(`TaskCreated for an already-existing task (seq ${env.seq})`);
|
|
13587
|
+
const p = req(env.payload, ["task_id", "slug"], env.type, env.seq);
|
|
13588
|
+
return {
|
|
13589
|
+
task_id: p.task_id,
|
|
13590
|
+
slug: p.slug,
|
|
13591
|
+
lifecycle: "open",
|
|
13592
|
+
version: 1,
|
|
13593
|
+
epoch: 0,
|
|
13594
|
+
owner: null,
|
|
13595
|
+
lease_expiry: null,
|
|
13596
|
+
submission: null,
|
|
13597
|
+
closed_disposition: null
|
|
13598
|
+
};
|
|
13599
|
+
}
|
|
13600
|
+
if (!prev) throw new StreamIntegrityError(`event "${env.type}" before TaskCreated (seq ${env.seq})`);
|
|
13601
|
+
const s = prev;
|
|
13602
|
+
function assertEpochIncrease(ep) {
|
|
13603
|
+
if (typeof ep !== "number" || ep <= s.epoch) {
|
|
13604
|
+
throw new StreamIntegrityError(`${env.type} at seq ${env.seq} has non-increasing epoch ${ep} (current ${s.epoch})`);
|
|
13605
|
+
}
|
|
13606
|
+
}
|
|
13607
|
+
const leaseLifecycle = s.submission ? "awaiting_review" : "active";
|
|
13608
|
+
switch (env.type) {
|
|
13609
|
+
case "LeaseAcquired": {
|
|
13610
|
+
const p = req(env.payload, ["task_id", "epoch", "owner", "lease_expiry"], env.type, env.seq);
|
|
13611
|
+
assertEpochIncrease(p.epoch);
|
|
13612
|
+
return { ...s, lifecycle: leaseLifecycle, epoch: p.epoch, owner: p.owner, lease_expiry: p.lease_expiry };
|
|
13613
|
+
}
|
|
13614
|
+
case "LeaseRenewed": {
|
|
13615
|
+
const p = req(env.payload, ["task_id", "epoch", "lease_expiry"], env.type, env.seq);
|
|
13616
|
+
if (p.epoch !== s.epoch) throw new StreamIntegrityError(`LeaseRenewed at seq ${env.seq} epoch ${p.epoch} != current ${s.epoch}`);
|
|
13617
|
+
return { ...s, lease_expiry: p.lease_expiry };
|
|
13618
|
+
}
|
|
13619
|
+
case "LeaseHandedOff": {
|
|
13620
|
+
const p = req(env.payload, ["task_id", "epoch", "from_owner", "to_owner", "lease_expiry"], env.type, env.seq);
|
|
13621
|
+
assertEpochIncrease(p.epoch);
|
|
13622
|
+
return { ...s, lifecycle: leaseLifecycle, epoch: p.epoch, owner: p.to_owner, lease_expiry: p.lease_expiry };
|
|
13623
|
+
}
|
|
13624
|
+
case "LeaseTakenOver": {
|
|
13625
|
+
const p = req(env.payload, ["task_id", "epoch", "owner", "lease_expiry", "grant_id"], env.type, env.seq);
|
|
13626
|
+
assertEpochIncrease(p.epoch);
|
|
13627
|
+
return { ...s, lifecycle: leaseLifecycle, epoch: p.epoch, owner: p.owner, lease_expiry: p.lease_expiry };
|
|
13628
|
+
}
|
|
13629
|
+
case "TaskSubmitted": {
|
|
13630
|
+
const p = req(env.payload, ["task_id", "epoch", "branch", "head_sha", "evidence_set"], env.type, env.seq);
|
|
13631
|
+
return {
|
|
13632
|
+
...s,
|
|
13633
|
+
lifecycle: "awaiting_review",
|
|
13634
|
+
submission: { epoch: p.epoch, branch: p.branch, head_sha: p.head_sha, evidence_set: [...p.evidence_set] }
|
|
13635
|
+
};
|
|
13636
|
+
}
|
|
13637
|
+
case "TaskClosed": {
|
|
13638
|
+
const p = req(env.payload, ["task_id", "epoch", "disposition", "grant_id"], env.type, env.seq);
|
|
13639
|
+
return { ...s, lifecycle: "done", closed_disposition: p.disposition };
|
|
13640
|
+
}
|
|
13641
|
+
case "TaskReopened": {
|
|
13642
|
+
const p = req(env.payload, ["task_id", "version"], env.type, env.seq);
|
|
13643
|
+
if (p.version <= s.version) throw new StreamIntegrityError(`TaskReopened at seq ${env.seq} version ${p.version} not > current ${s.version}`);
|
|
13644
|
+
return { ...s, lifecycle: "reopened", version: p.version, submission: null, owner: null, lease_expiry: null };
|
|
13645
|
+
}
|
|
13646
|
+
default: {
|
|
13647
|
+
throw new UnknownEventTypeError(env.type, env.seq);
|
|
13648
|
+
}
|
|
13649
|
+
}
|
|
13650
|
+
}
|
|
13651
|
+
|
|
13652
|
+
// src/protocol/idempotency.ts
|
|
13653
|
+
function canonicalJson(value) {
|
|
13654
|
+
return JSON.stringify(sortValue(value));
|
|
13655
|
+
}
|
|
13656
|
+
function sortValue(v) {
|
|
13657
|
+
if (Array.isArray(v)) return v.map(sortValue);
|
|
13658
|
+
if (v && typeof v === "object") {
|
|
13659
|
+
const out = {};
|
|
13660
|
+
for (const k of Object.keys(v).sort()) {
|
|
13661
|
+
out[k] = sortValue(v[k]);
|
|
13662
|
+
}
|
|
13663
|
+
return out;
|
|
13664
|
+
}
|
|
13665
|
+
return v;
|
|
13666
|
+
}
|
|
13667
|
+
|
|
13668
|
+
// src/protocol/upcasters.ts
|
|
13669
|
+
var registry = /* @__PURE__ */ new Map();
|
|
13670
|
+
function key(type, fromVersion) {
|
|
13671
|
+
return `${type}:${fromVersion}`;
|
|
13672
|
+
}
|
|
13673
|
+
function registerUpcaster(type, fromVersion, fn) {
|
|
13674
|
+
registry.set(key(type, fromVersion), fn);
|
|
13675
|
+
}
|
|
13676
|
+
var UpcastError = class extends Error {
|
|
13677
|
+
constructor(message) {
|
|
13678
|
+
super(message);
|
|
13679
|
+
this.name = "UpcastError";
|
|
13680
|
+
}
|
|
13681
|
+
};
|
|
13682
|
+
function upcastPayload(type, fromVersion, payload) {
|
|
13683
|
+
let v = fromVersion;
|
|
13684
|
+
let p = payload;
|
|
13685
|
+
if (v > SCHEMA_VERSION) {
|
|
13686
|
+
throw new UpcastError(`event "${type}" is schema v${v}, newer than supported v${SCHEMA_VERSION}; halting`);
|
|
13687
|
+
}
|
|
13688
|
+
while (v < SCHEMA_VERSION) {
|
|
13689
|
+
const fn = registry.get(key(type, v));
|
|
13690
|
+
if (!fn) throw new UpcastError(`no upcaster for "${type}" v${v}\u2192v${v + 1}`);
|
|
13691
|
+
p = fn(p);
|
|
13692
|
+
v += 1;
|
|
13693
|
+
}
|
|
13694
|
+
return { payload: p, schema_version: SCHEMA_VERSION };
|
|
13695
|
+
}
|
|
13696
|
+
function upcastEnvelope(raw) {
|
|
13697
|
+
const { payload, schema_version } = upcastPayload(raw.type, raw.schema_version, raw.payload);
|
|
13698
|
+
return { ...raw, payload, schema_version };
|
|
13699
|
+
}
|
|
13700
|
+
registerUpcaster("TaskCreated", 0, (p) => ({ task_id: p.id, slug: p.name }));
|
|
13701
|
+
|
|
13702
|
+
// src/protocol/workspace-commands.ts
|
|
13703
|
+
var INVITATION_MAX_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
13704
|
+
var AGENT_TOKEN_DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
13705
|
+
var AGENT_TOKEN_MAX_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
13706
|
+
var RENEWAL_HORIZON_DEFAULT_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
13707
|
+
var RENEWAL_HORIZON_MAX_MS = 90 * 24 * 60 * 60 * 1e3;
|
|
13708
|
+
|
|
13709
|
+
// src/protocol/brain-version-window.ts
|
|
13710
|
+
var BRAIN_FILE_PREFIX = "brain--";
|
|
13711
|
+
var BRAIN_FILE_SUFFIX = ".md";
|
|
13712
|
+
var BRAIN_TOPIC_MAX_LENGTH = 255 - BRAIN_FILE_PREFIX.length - BRAIN_FILE_SUFFIX.length;
|
|
13713
|
+
var FILE_VERSION_PRECONDITION_FAILED = "file_version_precondition_failed";
|
|
13714
|
+
|
|
13533
13715
|
// src/cloud/auth.ts
|
|
13534
13716
|
var import_node_crypto2 = require("node:crypto");
|
|
13535
13717
|
var import_node_http = require("node:http");
|
|
@@ -21959,189 +22141,6 @@ async function logout(target2, store2, scope = "local", options = {}) {
|
|
|
21959
22141
|
|
|
21960
22142
|
// src/cloud/command-client.ts
|
|
21961
22143
|
var import_node_crypto3 = require("node:crypto");
|
|
21962
|
-
|
|
21963
|
-
// src/protocol/events.ts
|
|
21964
|
-
var SCHEMA_VERSION = 1;
|
|
21965
|
-
var EVENT_TYPES = [
|
|
21966
|
-
"TaskCreated",
|
|
21967
|
-
"LeaseAcquired",
|
|
21968
|
-
"LeaseRenewed",
|
|
21969
|
-
"LeaseHandedOff",
|
|
21970
|
-
"LeaseTakenOver",
|
|
21971
|
-
"TaskSubmitted",
|
|
21972
|
-
"TaskClosed",
|
|
21973
|
-
"TaskReopened",
|
|
21974
|
-
"CommandRejected"
|
|
21975
|
-
];
|
|
21976
|
-
|
|
21977
|
-
// src/protocol/reducer.ts
|
|
21978
|
-
function req(payload, keys, type, seq) {
|
|
21979
|
-
if (!payload || typeof payload !== "object") throw new StreamIntegrityError(`event "${type}" at seq ${seq} has a non-object payload`);
|
|
21980
|
-
for (const k of keys) {
|
|
21981
|
-
if (payload[k] === void 0) {
|
|
21982
|
-
throw new StreamIntegrityError(`event "${type}" at seq ${seq} is missing payload field "${String(k)}"`);
|
|
21983
|
-
}
|
|
21984
|
-
}
|
|
21985
|
-
return payload;
|
|
21986
|
-
}
|
|
21987
|
-
var UnknownEventTypeError = class extends Error {
|
|
21988
|
-
constructor(type, seq) {
|
|
21989
|
-
super(`unknown authoritative event type "${type}" at seq ${seq}; halting`);
|
|
21990
|
-
this.type = type;
|
|
21991
|
-
this.seq = seq;
|
|
21992
|
-
this.name = "UnknownEventTypeError";
|
|
21993
|
-
}
|
|
21994
|
-
type;
|
|
21995
|
-
seq;
|
|
21996
|
-
};
|
|
21997
|
-
var StreamIntegrityError = class extends Error {
|
|
21998
|
-
constructor(message) {
|
|
21999
|
-
super(message);
|
|
22000
|
-
this.name = "StreamIntegrityError";
|
|
22001
|
-
}
|
|
22002
|
-
};
|
|
22003
|
-
function reduceTask(prev, env) {
|
|
22004
|
-
if (!EVENT_TYPES.includes(env.type)) {
|
|
22005
|
-
throw new UnknownEventTypeError(env.type, env.seq);
|
|
22006
|
-
}
|
|
22007
|
-
if (env.schema_version !== SCHEMA_VERSION) {
|
|
22008
|
-
throw new StreamIntegrityError(`event "${env.type}" at seq ${env.seq} is schema v${env.schema_version}, expected v${SCHEMA_VERSION} (upcast before reduce)`);
|
|
22009
|
-
}
|
|
22010
|
-
if (env.type === "CommandRejected") {
|
|
22011
|
-
if (!prev) throw new StreamIntegrityError(`CommandRejected before task exists (seq ${env.seq})`);
|
|
22012
|
-
req(env.payload, ["task_id", "command", "reason", "detail"], env.type, env.seq);
|
|
22013
|
-
return prev;
|
|
22014
|
-
}
|
|
22015
|
-
if (env.type === "TaskCreated") {
|
|
22016
|
-
if (prev) throw new StreamIntegrityError(`TaskCreated for an already-existing task (seq ${env.seq})`);
|
|
22017
|
-
const p = req(env.payload, ["task_id", "slug"], env.type, env.seq);
|
|
22018
|
-
return {
|
|
22019
|
-
task_id: p.task_id,
|
|
22020
|
-
slug: p.slug,
|
|
22021
|
-
lifecycle: "open",
|
|
22022
|
-
version: 1,
|
|
22023
|
-
epoch: 0,
|
|
22024
|
-
owner: null,
|
|
22025
|
-
lease_expiry: null,
|
|
22026
|
-
submission: null,
|
|
22027
|
-
closed_disposition: null
|
|
22028
|
-
};
|
|
22029
|
-
}
|
|
22030
|
-
if (!prev) throw new StreamIntegrityError(`event "${env.type}" before TaskCreated (seq ${env.seq})`);
|
|
22031
|
-
const s = prev;
|
|
22032
|
-
function assertEpochIncrease(ep) {
|
|
22033
|
-
if (typeof ep !== "number" || ep <= s.epoch) {
|
|
22034
|
-
throw new StreamIntegrityError(`${env.type} at seq ${env.seq} has non-increasing epoch ${ep} (current ${s.epoch})`);
|
|
22035
|
-
}
|
|
22036
|
-
}
|
|
22037
|
-
const leaseLifecycle = s.submission ? "awaiting_review" : "active";
|
|
22038
|
-
switch (env.type) {
|
|
22039
|
-
case "LeaseAcquired": {
|
|
22040
|
-
const p = req(env.payload, ["task_id", "epoch", "owner", "lease_expiry"], env.type, env.seq);
|
|
22041
|
-
assertEpochIncrease(p.epoch);
|
|
22042
|
-
return { ...s, lifecycle: leaseLifecycle, epoch: p.epoch, owner: p.owner, lease_expiry: p.lease_expiry };
|
|
22043
|
-
}
|
|
22044
|
-
case "LeaseRenewed": {
|
|
22045
|
-
const p = req(env.payload, ["task_id", "epoch", "lease_expiry"], env.type, env.seq);
|
|
22046
|
-
if (p.epoch !== s.epoch) throw new StreamIntegrityError(`LeaseRenewed at seq ${env.seq} epoch ${p.epoch} != current ${s.epoch}`);
|
|
22047
|
-
return { ...s, lease_expiry: p.lease_expiry };
|
|
22048
|
-
}
|
|
22049
|
-
case "LeaseHandedOff": {
|
|
22050
|
-
const p = req(env.payload, ["task_id", "epoch", "from_owner", "to_owner", "lease_expiry"], env.type, env.seq);
|
|
22051
|
-
assertEpochIncrease(p.epoch);
|
|
22052
|
-
return { ...s, lifecycle: leaseLifecycle, epoch: p.epoch, owner: p.to_owner, lease_expiry: p.lease_expiry };
|
|
22053
|
-
}
|
|
22054
|
-
case "LeaseTakenOver": {
|
|
22055
|
-
const p = req(env.payload, ["task_id", "epoch", "owner", "lease_expiry", "grant_id"], env.type, env.seq);
|
|
22056
|
-
assertEpochIncrease(p.epoch);
|
|
22057
|
-
return { ...s, lifecycle: leaseLifecycle, epoch: p.epoch, owner: p.owner, lease_expiry: p.lease_expiry };
|
|
22058
|
-
}
|
|
22059
|
-
case "TaskSubmitted": {
|
|
22060
|
-
const p = req(env.payload, ["task_id", "epoch", "branch", "head_sha", "evidence_set"], env.type, env.seq);
|
|
22061
|
-
return {
|
|
22062
|
-
...s,
|
|
22063
|
-
lifecycle: "awaiting_review",
|
|
22064
|
-
submission: { epoch: p.epoch, branch: p.branch, head_sha: p.head_sha, evidence_set: [...p.evidence_set] }
|
|
22065
|
-
};
|
|
22066
|
-
}
|
|
22067
|
-
case "TaskClosed": {
|
|
22068
|
-
const p = req(env.payload, ["task_id", "epoch", "disposition", "grant_id"], env.type, env.seq);
|
|
22069
|
-
return { ...s, lifecycle: "done", closed_disposition: p.disposition };
|
|
22070
|
-
}
|
|
22071
|
-
case "TaskReopened": {
|
|
22072
|
-
const p = req(env.payload, ["task_id", "version"], env.type, env.seq);
|
|
22073
|
-
if (p.version <= s.version) throw new StreamIntegrityError(`TaskReopened at seq ${env.seq} version ${p.version} not > current ${s.version}`);
|
|
22074
|
-
return { ...s, lifecycle: "reopened", version: p.version, submission: null, owner: null, lease_expiry: null };
|
|
22075
|
-
}
|
|
22076
|
-
default: {
|
|
22077
|
-
throw new UnknownEventTypeError(env.type, env.seq);
|
|
22078
|
-
}
|
|
22079
|
-
}
|
|
22080
|
-
}
|
|
22081
|
-
|
|
22082
|
-
// src/protocol/idempotency.ts
|
|
22083
|
-
function canonicalJson(value) {
|
|
22084
|
-
return JSON.stringify(sortValue(value));
|
|
22085
|
-
}
|
|
22086
|
-
function sortValue(v) {
|
|
22087
|
-
if (Array.isArray(v)) return v.map(sortValue);
|
|
22088
|
-
if (v && typeof v === "object") {
|
|
22089
|
-
const out = {};
|
|
22090
|
-
for (const k of Object.keys(v).sort()) {
|
|
22091
|
-
out[k] = sortValue(v[k]);
|
|
22092
|
-
}
|
|
22093
|
-
return out;
|
|
22094
|
-
}
|
|
22095
|
-
return v;
|
|
22096
|
-
}
|
|
22097
|
-
|
|
22098
|
-
// src/protocol/upcasters.ts
|
|
22099
|
-
var registry = /* @__PURE__ */ new Map();
|
|
22100
|
-
function key(type, fromVersion) {
|
|
22101
|
-
return `${type}:${fromVersion}`;
|
|
22102
|
-
}
|
|
22103
|
-
function registerUpcaster(type, fromVersion, fn) {
|
|
22104
|
-
registry.set(key(type, fromVersion), fn);
|
|
22105
|
-
}
|
|
22106
|
-
var UpcastError = class extends Error {
|
|
22107
|
-
constructor(message) {
|
|
22108
|
-
super(message);
|
|
22109
|
-
this.name = "UpcastError";
|
|
22110
|
-
}
|
|
22111
|
-
};
|
|
22112
|
-
function upcastPayload(type, fromVersion, payload) {
|
|
22113
|
-
let v = fromVersion;
|
|
22114
|
-
let p = payload;
|
|
22115
|
-
if (v > SCHEMA_VERSION) {
|
|
22116
|
-
throw new UpcastError(`event "${type}" is schema v${v}, newer than supported v${SCHEMA_VERSION}; halting`);
|
|
22117
|
-
}
|
|
22118
|
-
while (v < SCHEMA_VERSION) {
|
|
22119
|
-
const fn = registry.get(key(type, v));
|
|
22120
|
-
if (!fn) throw new UpcastError(`no upcaster for "${type}" v${v}\u2192v${v + 1}`);
|
|
22121
|
-
p = fn(p);
|
|
22122
|
-
v += 1;
|
|
22123
|
-
}
|
|
22124
|
-
return { payload: p, schema_version: SCHEMA_VERSION };
|
|
22125
|
-
}
|
|
22126
|
-
function upcastEnvelope(raw) {
|
|
22127
|
-
const { payload, schema_version } = upcastPayload(raw.type, raw.schema_version, raw.payload);
|
|
22128
|
-
return { ...raw, payload, schema_version };
|
|
22129
|
-
}
|
|
22130
|
-
registerUpcaster("TaskCreated", 0, (p) => ({ task_id: p.id, slug: p.name }));
|
|
22131
|
-
|
|
22132
|
-
// src/protocol/workspace-commands.ts
|
|
22133
|
-
var INVITATION_MAX_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
22134
|
-
var AGENT_TOKEN_DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
22135
|
-
var AGENT_TOKEN_MAX_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
22136
|
-
var RENEWAL_HORIZON_DEFAULT_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
22137
|
-
var RENEWAL_HORIZON_MAX_MS = 90 * 24 * 60 * 60 * 1e3;
|
|
22138
|
-
|
|
22139
|
-
// src/protocol/brain-version-window.ts
|
|
22140
|
-
var BRAIN_FILE_PREFIX = "brain--";
|
|
22141
|
-
var BRAIN_FILE_SUFFIX = ".md";
|
|
22142
|
-
var BRAIN_TOPIC_MAX_LENGTH = 255 - BRAIN_FILE_PREFIX.length - BRAIN_FILE_SUFFIX.length;
|
|
22143
|
-
|
|
22144
|
-
// src/cloud/command-client.ts
|
|
22145
22144
|
var AGENT_TOKEN_RE = /^swm_agt_[A-Za-z0-9_-]{43}$/;
|
|
22146
22145
|
var INVITATION_TOKEN_RE = /^swm_inv_[A-Za-z0-9_-]{43}$/;
|
|
22147
22146
|
var CAPABILITY_TOKEN_RE = /^swm_cap_[A-Za-z0-9_-]{43}$/;
|
|
@@ -22978,13 +22977,18 @@ async function sendFileCommand(options, command2) {
|
|
|
22978
22977
|
return body;
|
|
22979
22978
|
}
|
|
22980
22979
|
function fileVersionCreate(options, input) {
|
|
22980
|
+
const ifVersion = input.ifVersion ?? null;
|
|
22981
22981
|
return sendFileCommand(options, {
|
|
22982
22982
|
kind: "file_version_create",
|
|
22983
22983
|
file_id: input.fileId,
|
|
22984
22984
|
version_id: input.versionId,
|
|
22985
22985
|
name: input.name,
|
|
22986
22986
|
declared_size_bytes: input.declaredSizeBytes,
|
|
22987
|
-
content_type: input.contentType
|
|
22987
|
+
content_type: input.contentType,
|
|
22988
|
+
/* The server validates an exact key set, so the key is sent only when a
|
|
22989
|
+
* precondition was asked for. An unconditional write is byte-identical to
|
|
22990
|
+
* what every earlier client sent. */
|
|
22991
|
+
...ifVersion === null ? {} : { if_version: ifVersion }
|
|
22988
22992
|
});
|
|
22989
22993
|
}
|
|
22990
22994
|
function fileVersionCommit(options, input) {
|
|
@@ -41648,6 +41652,23 @@ var ListenerHttpClient = class {
|
|
|
41648
41652
|
|
|
41649
41653
|
// src/resume.ts
|
|
41650
41654
|
var import_node_child_process8 = require("node:child_process");
|
|
41655
|
+
var DEFAULT_PROCESS_TABLE_COMMAND = {
|
|
41656
|
+
file: "ps",
|
|
41657
|
+
args: ["-axo", "pid=,command="]
|
|
41658
|
+
};
|
|
41659
|
+
var ProcessTableError = class extends Error {
|
|
41660
|
+
constructor(command2, detail) {
|
|
41661
|
+
super(
|
|
41662
|
+
`could not read the host process table with ${command2.file}: ${detail}`
|
|
41663
|
+
);
|
|
41664
|
+
this.command = command2;
|
|
41665
|
+
this.detail = detail;
|
|
41666
|
+
this.name = "ProcessTableError";
|
|
41667
|
+
}
|
|
41668
|
+
command;
|
|
41669
|
+
detail;
|
|
41670
|
+
code = "process_table_unavailable";
|
|
41671
|
+
};
|
|
41651
41672
|
function execFileText(file, args) {
|
|
41652
41673
|
return new Promise((resolve3, reject) => {
|
|
41653
41674
|
(0, import_node_child_process8.execFile)(file, [...args], {
|
|
@@ -41659,15 +41680,76 @@ function execFileText(file, args) {
|
|
|
41659
41680
|
});
|
|
41660
41681
|
});
|
|
41661
41682
|
}
|
|
41662
|
-
function
|
|
41683
|
+
function parseProcessRow(line) {
|
|
41684
|
+
const match = /^\s*(\d+)\s+(.*)$/.exec(line);
|
|
41685
|
+
if (!match) return null;
|
|
41686
|
+
const pid = Number(match[1]);
|
|
41687
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return null;
|
|
41688
|
+
return { pid, command: match[2] };
|
|
41689
|
+
}
|
|
41690
|
+
var PROCESS_TABLE_STDERR_MAX_CHARS = 2e3;
|
|
41691
|
+
function systemProcessTable(options = {}) {
|
|
41692
|
+
const command2 = options.command ?? DEFAULT_PROCESS_TABLE_COMMAND;
|
|
41693
|
+
const retain = options.retain ?? (() => true);
|
|
41663
41694
|
return {
|
|
41664
|
-
|
|
41665
|
-
|
|
41666
|
-
|
|
41667
|
-
|
|
41668
|
-
|
|
41669
|
-
const
|
|
41670
|
-
|
|
41695
|
+
list() {
|
|
41696
|
+
return new Promise((resolve3, reject) => {
|
|
41697
|
+
const child = (0, import_node_child_process8.spawn)(command2.file, [...command2.args], {
|
|
41698
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
41699
|
+
});
|
|
41700
|
+
const rows3 = [];
|
|
41701
|
+
let pending = "";
|
|
41702
|
+
let stderr = "";
|
|
41703
|
+
let settled = false;
|
|
41704
|
+
const fail = (detail) => {
|
|
41705
|
+
if (settled) return;
|
|
41706
|
+
settled = true;
|
|
41707
|
+
child.stdout.destroy();
|
|
41708
|
+
reject(new ProcessTableError(command2, detail));
|
|
41709
|
+
};
|
|
41710
|
+
const take = (line) => {
|
|
41711
|
+
const row = parseProcessRow(line);
|
|
41712
|
+
if (row === null) return true;
|
|
41713
|
+
try {
|
|
41714
|
+
if (retain(row.command)) rows3.push(row);
|
|
41715
|
+
} catch {
|
|
41716
|
+
fail("its row filter threw");
|
|
41717
|
+
return false;
|
|
41718
|
+
}
|
|
41719
|
+
return true;
|
|
41720
|
+
};
|
|
41721
|
+
child.stdout.setEncoding("utf8");
|
|
41722
|
+
child.stdout.on("data", (chunk) => {
|
|
41723
|
+
if (settled) return;
|
|
41724
|
+
const lines = (pending + chunk).split("\n");
|
|
41725
|
+
pending = lines.pop() ?? "";
|
|
41726
|
+
for (const line of lines) {
|
|
41727
|
+
if (!take(line)) return;
|
|
41728
|
+
}
|
|
41729
|
+
});
|
|
41730
|
+
child.stderr.setEncoding("utf8");
|
|
41731
|
+
child.stderr.on("data", (chunk) => {
|
|
41732
|
+
const room = PROCESS_TABLE_STDERR_MAX_CHARS - stderr.length;
|
|
41733
|
+
if (room > 0) stderr += chunk.slice(0, room);
|
|
41734
|
+
});
|
|
41735
|
+
child.stdout.on("error", () => fail("its output stream failed"));
|
|
41736
|
+
child.stderr.on("error", () => fail("its error stream failed"));
|
|
41737
|
+
child.on("error", (error) => fail(error.name));
|
|
41738
|
+
child.on("close", (code, signal) => {
|
|
41739
|
+
if (settled) return;
|
|
41740
|
+
if (pending.length > 0 && !take(pending)) return;
|
|
41741
|
+
if (signal !== null) {
|
|
41742
|
+
fail(`it was stopped by ${signal}`);
|
|
41743
|
+
return;
|
|
41744
|
+
}
|
|
41745
|
+
if (code !== 0) {
|
|
41746
|
+
const trailer = stderr.trim().length > 0 ? `: ${stderr.trim().slice(0, PROCESS_TABLE_STDERR_MAX_CHARS)}` : "";
|
|
41747
|
+
fail(`it exited ${code}${trailer}`);
|
|
41748
|
+
return;
|
|
41749
|
+
}
|
|
41750
|
+
settled = true;
|
|
41751
|
+
resolve3(rows3);
|
|
41752
|
+
});
|
|
41671
41753
|
});
|
|
41672
41754
|
}
|
|
41673
41755
|
};
|
|
@@ -41717,7 +41799,10 @@ function isNotifyCommand(command2) {
|
|
|
41717
41799
|
return /(?:^|\s)inbox(?:\s|$)/.test(command2) && /(?:^|\s)--notify(?:\s|$)/.test(command2);
|
|
41718
41800
|
}
|
|
41719
41801
|
async function findNotifyWatchers(options) {
|
|
41720
|
-
const processTable = options.processTable ?? systemProcessTable(
|
|
41802
|
+
const processTable = options.processTable ?? systemProcessTable({
|
|
41803
|
+
retain: isNotifyCommand,
|
|
41804
|
+
...options.processTableCommand ? { command: options.processTableCommand } : {}
|
|
41805
|
+
});
|
|
41721
41806
|
const stdoutConsumer = options.stdoutConsumer ?? lsofStdoutConsumer();
|
|
41722
41807
|
const rows3 = await processTable.list();
|
|
41723
41808
|
const matches = rows3.flatMap((row) => {
|
|
@@ -41985,6 +42070,7 @@ var KNOWN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
41985
42070
|
"grok-executable",
|
|
41986
42071
|
"head-sha",
|
|
41987
42072
|
"help",
|
|
42073
|
+
"if-version",
|
|
41988
42074
|
"include-stale",
|
|
41989
42075
|
"include-tombstoned",
|
|
41990
42076
|
"invitation-id",
|
|
@@ -42056,8 +42142,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
42056
42142
|
]);
|
|
42057
42143
|
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;
|
|
42058
42144
|
function packageVersion() {
|
|
42059
|
-
if ("0.1.
|
|
42060
|
-
return "0.1.
|
|
42145
|
+
if ("0.1.53".length > 0) {
|
|
42146
|
+
return "0.1.53";
|
|
42061
42147
|
}
|
|
42062
42148
|
try {
|
|
42063
42149
|
const value = JSON.parse(
|
|
@@ -42192,7 +42278,7 @@ Usage:
|
|
|
42192
42278
|
cswarm file restore <name|file-id> [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--json]
|
|
42193
42279
|
cswarm brain ls [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--json]
|
|
42194
42280
|
cswarm brain get <topic>[@<version>] [--version <n>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--json]
|
|
42195
|
-
cswarm brain put <topic> [<markdown-path>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--json] # without a path, reads Markdown from stdin
|
|
42281
|
+
cswarm brain put <topic> [<markdown-path>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--if-version <n>] [--json] # without a path, reads Markdown from stdin; --if-version refuses the write unless the live version is still <n>
|
|
42196
42282
|
cswarm feedback "<text>" --kind bug|idea|friction [--about <ref>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--json]
|
|
42197
42283
|
cswarm listen start ${requiredAgentCredential} [--url <url> --anon-key <key>] --workspace-id <uuid> --provider grok|opencode|claude|codex [--cwd <absolute-path>] [--model <model>] [--effort <level>] [--permissions deny|allow] [--grok-executable <path>] [--opencode-executable <path>] [--claude-executable <path>] [--codex-executable <path>] [--turn-budget <duration>] [--route worker|main|split] [--defer-over <chars>] [--allow-unattended] [--foreground] [--json]
|
|
42198
42284
|
cswarm listen canary ${requiredAgentCredential} [--url <url> --anon-key <key>] --workspace-id <uuid> [--state-dir <path>] [--wait <seconds>] [--json]
|
|
@@ -46796,7 +46882,7 @@ async function resolveFileSelector(context, selector) {
|
|
|
46796
46882
|
}
|
|
46797
46883
|
return match.file_id;
|
|
46798
46884
|
}
|
|
46799
|
-
async function uploadNamedFile(context, name, bytes) {
|
|
46885
|
+
async function uploadNamedFile(context, name, bytes, options = {}) {
|
|
46800
46886
|
if (bytes.byteLength > FILE_MAX_VERSION_BYTES) {
|
|
46801
46887
|
throw new Error(
|
|
46802
46888
|
`this file is ${formatFileSize(bytes.byteLength)}; the per-file limit is ${formatFileSize(FILE_MAX_VERSION_BYTES)}, so the upload was not started`
|
|
@@ -46823,7 +46909,8 @@ async function uploadNamedFile(context, name, bytes) {
|
|
|
46823
46909
|
versionId,
|
|
46824
46910
|
name,
|
|
46825
46911
|
declaredSizeBytes: bytes.byteLength,
|
|
46826
|
-
contentType
|
|
46912
|
+
contentType,
|
|
46913
|
+
...options.ifVersion === void 0 ? {} : { ifVersion: options.ifVersion }
|
|
46827
46914
|
})
|
|
46828
46915
|
);
|
|
46829
46916
|
await onceRetried(
|
|
@@ -47117,7 +47204,8 @@ async function runBrainPut(args) {
|
|
|
47117
47204
|
"cswarm brain put cannot read both the credential and Markdown from stdin; use --agent-token-file or pass a Markdown path"
|
|
47118
47205
|
);
|
|
47119
47206
|
}
|
|
47120
|
-
const context = await fileContext(args, [], args.positionals.length);
|
|
47207
|
+
const context = await fileContext(args, ["if-version"], args.positionals.length);
|
|
47208
|
+
const ifVersion = args.optional("if-version") === void 0 ? void 0 : integer2(args, "if-version", { minimum: 0 });
|
|
47121
47209
|
let bytes;
|
|
47122
47210
|
if (localPath) {
|
|
47123
47211
|
try {
|
|
@@ -47132,7 +47220,19 @@ async function runBrainPut(args) {
|
|
|
47132
47220
|
bytes = await readBrainMarkdownFromStdin();
|
|
47133
47221
|
}
|
|
47134
47222
|
decodeBrainMarkdown(bytes);
|
|
47135
|
-
const committed = await uploadNamedFile(
|
|
47223
|
+
const committed = await uploadNamedFile(
|
|
47224
|
+
context,
|
|
47225
|
+
brainFileName(topic),
|
|
47226
|
+
bytes,
|
|
47227
|
+
ifVersion === void 0 ? {} : { ifVersion }
|
|
47228
|
+
).catch((error) => {
|
|
47229
|
+
if (error instanceof FileCommandRefused && error.code === FILE_VERSION_PRECONDITION_FAILED) {
|
|
47230
|
+
throw new Error(
|
|
47231
|
+
`${error.message}. Someone saved a new version after you read this topic. Re-read it, apply your change to that copy, then put it again: cswarm brain get ${topic}`
|
|
47232
|
+
);
|
|
47233
|
+
}
|
|
47234
|
+
throw error;
|
|
47235
|
+
});
|
|
47136
47236
|
if (args.has("json")) {
|
|
47137
47237
|
process.stdout.write(`${JSON.stringify({ topic, ...committed }, null, 2)}
|
|
47138
47238
|
`);
|