squadrant 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +228 -150
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +55 -41
- package/dist/squadrantd.js.map +1 -1
- package/package.json +3 -2
- package/plugin/skills/captain-ops/SKILL.md +1 -1
- package/scripts/heavy-lock.mjs +129 -0
package/dist/squadrantd.js
CHANGED
|
@@ -430,13 +430,14 @@ var FAILURE_RETRY_MS = 60 * 60 * 1e3;
|
|
|
430
430
|
|
|
431
431
|
// packages/shared/dist/lib/git-worktree.js
|
|
432
432
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
433
|
+
import fs4 from "fs";
|
|
433
434
|
import path4 from "path";
|
|
434
435
|
|
|
435
436
|
// packages/shared/dist/lib/resolve-text-input.js
|
|
436
|
-
import
|
|
437
|
+
import fs5 from "fs";
|
|
437
438
|
|
|
438
439
|
// packages/shared/dist/lib/runtime-sync.js
|
|
439
|
-
import
|
|
440
|
+
import fs6 from "fs";
|
|
440
441
|
import path5 from "path";
|
|
441
442
|
|
|
442
443
|
// packages/shared/dist/lib/tool-compat.js
|
|
@@ -471,12 +472,12 @@ function checkToolCompat(name, rawVersion, entry) {
|
|
|
471
472
|
}
|
|
472
473
|
|
|
473
474
|
// packages/shared/dist/lib/canonical-source.js
|
|
474
|
-
import
|
|
475
|
+
import fs7 from "fs";
|
|
475
476
|
import path6 from "path";
|
|
476
477
|
|
|
477
478
|
// packages/shared/dist/lib/daily-logs.js
|
|
478
479
|
import { execSync } from "child_process";
|
|
479
|
-
import
|
|
480
|
+
import fs8 from "fs";
|
|
480
481
|
import path7 from "path";
|
|
481
482
|
import matter from "gray-matter";
|
|
482
483
|
|
|
@@ -1019,7 +1020,7 @@ function createDaemon(deps) {
|
|
|
1019
1020
|
}
|
|
1020
1021
|
|
|
1021
1022
|
// packages/core/dist/mailbox.js
|
|
1022
|
-
import { promises as
|
|
1023
|
+
import { promises as fs9 } from "fs";
|
|
1023
1024
|
import { join as join5 } from "path";
|
|
1024
1025
|
import { randomUUID } from "crypto";
|
|
1025
1026
|
function inboxDir(stateRoot) {
|
|
@@ -1036,7 +1037,7 @@ async function listRotatedOldestFirst(stateRoot, project) {
|
|
|
1036
1037
|
const dir = inboxDir(stateRoot);
|
|
1037
1038
|
let entries;
|
|
1038
1039
|
try {
|
|
1039
|
-
entries = await
|
|
1040
|
+
entries = await fs9.readdir(dir);
|
|
1040
1041
|
} catch {
|
|
1041
1042
|
return [];
|
|
1042
1043
|
}
|
|
@@ -1045,7 +1046,7 @@ async function listRotatedOldestFirst(stateRoot, project) {
|
|
|
1045
1046
|
}
|
|
1046
1047
|
async function readMaxSeqFromFile(file) {
|
|
1047
1048
|
try {
|
|
1048
|
-
const buf = await
|
|
1049
|
+
const buf = await fs9.readFile(file, "utf-8");
|
|
1049
1050
|
if (!buf.trim())
|
|
1050
1051
|
return 0;
|
|
1051
1052
|
const lines = buf.trim().split("\n");
|
|
@@ -1087,12 +1088,12 @@ function withProjectLock(project, fn) {
|
|
|
1087
1088
|
function appendEntry(stateRoot, project, build) {
|
|
1088
1089
|
return withProjectLock(project, async () => {
|
|
1089
1090
|
const dir = inboxDir(stateRoot);
|
|
1090
|
-
await
|
|
1091
|
+
await fs9.mkdir(dir, { recursive: true });
|
|
1091
1092
|
const file = logPath(stateRoot, project);
|
|
1092
1093
|
const lastSeq = await readMaxSeq(stateRoot, project);
|
|
1093
1094
|
const seq = lastSeq + 1;
|
|
1094
1095
|
const entry = build(seq);
|
|
1095
|
-
await
|
|
1096
|
+
await fs9.appendFile(file, JSON.stringify(entry) + "\n", { encoding: "utf-8" });
|
|
1096
1097
|
return seq;
|
|
1097
1098
|
});
|
|
1098
1099
|
}
|
|
@@ -1109,7 +1110,7 @@ async function appendToMailbox(opts) {
|
|
|
1109
1110
|
}));
|
|
1110
1111
|
}
|
|
1111
1112
|
async function appendCaptainMessage(opts) {
|
|
1112
|
-
|
|
1113
|
+
return appendEntry(opts.stateRoot, opts.project, (seq) => ({
|
|
1113
1114
|
seq,
|
|
1114
1115
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1115
1116
|
kind: "captain.message",
|
|
@@ -1123,7 +1124,7 @@ function cursorPath(stateRoot, project, subscriber) {
|
|
|
1123
1124
|
async function readCursor(opts) {
|
|
1124
1125
|
let buf;
|
|
1125
1126
|
try {
|
|
1126
|
-
buf = await
|
|
1127
|
+
buf = await fs9.readFile(cursorPath(opts.stateRoot, opts.project, opts.subscriber), "utf-8");
|
|
1127
1128
|
} catch (e) {
|
|
1128
1129
|
if (e.code === "ENOENT")
|
|
1129
1130
|
return null;
|
|
@@ -1138,7 +1139,7 @@ async function readCursor(opts) {
|
|
|
1138
1139
|
}
|
|
1139
1140
|
}
|
|
1140
1141
|
async function writeCursor(opts) {
|
|
1141
|
-
await
|
|
1142
|
+
await fs9.mkdir(inboxDir(opts.stateRoot), { recursive: true });
|
|
1142
1143
|
const dest = cursorPath(opts.stateRoot, opts.project, opts.subscriber);
|
|
1143
1144
|
const tmp = `${dest}.${process.pid}.${randomUUID()}.tmp`;
|
|
1144
1145
|
const data = {
|
|
@@ -1146,7 +1147,7 @@ async function writeCursor(opts) {
|
|
|
1146
1147
|
subscriber: opts.subscriber,
|
|
1147
1148
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1148
1149
|
};
|
|
1149
|
-
const handle = await
|
|
1150
|
+
const handle = await fs9.open(tmp, "w");
|
|
1150
1151
|
try {
|
|
1151
1152
|
await handle.writeFile(JSON.stringify(data), { encoding: "utf-8" });
|
|
1152
1153
|
await handle.sync();
|
|
@@ -1154,9 +1155,9 @@ async function writeCursor(opts) {
|
|
|
1154
1155
|
await handle.close();
|
|
1155
1156
|
}
|
|
1156
1157
|
try {
|
|
1157
|
-
await
|
|
1158
|
+
await fs9.rename(tmp, dest);
|
|
1158
1159
|
} catch (e) {
|
|
1159
|
-
await
|
|
1160
|
+
await fs9.unlink(tmp).catch(() => {
|
|
1160
1161
|
});
|
|
1161
1162
|
throw e;
|
|
1162
1163
|
}
|
|
@@ -1167,7 +1168,7 @@ async function* readFromCursor(opts) {
|
|
|
1167
1168
|
for (const file of files) {
|
|
1168
1169
|
let buf;
|
|
1169
1170
|
try {
|
|
1170
|
-
buf = await
|
|
1171
|
+
buf = await fs9.readFile(file, "utf-8");
|
|
1171
1172
|
} catch (e) {
|
|
1172
1173
|
if (e.code === "ENOENT")
|
|
1173
1174
|
continue;
|
|
@@ -1193,7 +1194,7 @@ async function mailboxStats(stateRoot, project) {
|
|
|
1193
1194
|
let sizeBytes = 0;
|
|
1194
1195
|
for (const f of [file, ...rotated]) {
|
|
1195
1196
|
try {
|
|
1196
|
-
sizeBytes += (await
|
|
1197
|
+
sizeBytes += (await fs9.stat(f)).size;
|
|
1197
1198
|
} catch (e) {
|
|
1198
1199
|
if (e.code !== "ENOENT")
|
|
1199
1200
|
throw e;
|
|
@@ -1209,7 +1210,7 @@ async function mailboxStats(stateRoot, project) {
|
|
|
1209
1210
|
}
|
|
1210
1211
|
async function oldestEntryAgeMs(file) {
|
|
1211
1212
|
try {
|
|
1212
|
-
const buf = await
|
|
1213
|
+
const buf = await fs9.readFile(file, "utf-8");
|
|
1213
1214
|
const firstLine = buf.split("\n").find((l) => l.trim());
|
|
1214
1215
|
if (!firstLine)
|
|
1215
1216
|
return 0;
|
|
@@ -1224,7 +1225,7 @@ async function rotateIfNeeded(opts) {
|
|
|
1224
1225
|
const file = logPath(opts.stateRoot, opts.project);
|
|
1225
1226
|
let size = 0;
|
|
1226
1227
|
try {
|
|
1227
|
-
size = (await
|
|
1228
|
+
size = (await fs9.stat(file)).size;
|
|
1228
1229
|
} catch (e) {
|
|
1229
1230
|
if (e.code === "ENOENT")
|
|
1230
1231
|
return { rotated: false };
|
|
@@ -1240,22 +1241,22 @@ async function rotateIfNeeded(opts) {
|
|
|
1240
1241
|
const dst = `${file}.${n + 1}`;
|
|
1241
1242
|
if (n + 1 > opts.keepCount) {
|
|
1242
1243
|
try {
|
|
1243
|
-
await
|
|
1244
|
+
await fs9.unlink(src);
|
|
1244
1245
|
} catch (e) {
|
|
1245
1246
|
if (e.code !== "ENOENT")
|
|
1246
1247
|
throw e;
|
|
1247
1248
|
}
|
|
1248
1249
|
} else {
|
|
1249
1250
|
try {
|
|
1250
|
-
await
|
|
1251
|
+
await fs9.rename(src, dst);
|
|
1251
1252
|
} catch (e) {
|
|
1252
1253
|
if (e.code !== "ENOENT")
|
|
1253
1254
|
throw e;
|
|
1254
1255
|
}
|
|
1255
1256
|
}
|
|
1256
1257
|
}
|
|
1257
|
-
await
|
|
1258
|
-
await
|
|
1258
|
+
await fs9.rename(file, `${file}.1`);
|
|
1259
|
+
await fs9.writeFile(file, "", { encoding: "utf-8" });
|
|
1259
1260
|
return { rotated: true, from: file, to: `${file}.1` };
|
|
1260
1261
|
});
|
|
1261
1262
|
}
|
|
@@ -1511,6 +1512,9 @@ function reconcileLiveness(prev, next) {
|
|
|
1511
1512
|
}
|
|
1512
1513
|
if (next.startedAt >= prev.startedAt || next.lastState === "end")
|
|
1513
1514
|
return next;
|
|
1515
|
+
const prevAlive = prev.lastState === "start" && prev.pidAlive;
|
|
1516
|
+
if (!prevAlive && next.lastState === "start" && next.pidAlive)
|
|
1517
|
+
return next;
|
|
1514
1518
|
return prev;
|
|
1515
1519
|
}
|
|
1516
1520
|
|
|
@@ -2167,9 +2171,15 @@ async function runLivenessTick(deps) {
|
|
|
2167
2171
|
return;
|
|
2168
2172
|
}
|
|
2169
2173
|
const seen = /* @__PURE__ */ new Set();
|
|
2174
|
+
const knownCaptainSessions = /* @__PURE__ */ new Map();
|
|
2175
|
+
for (const e of deps.registry.all()) {
|
|
2176
|
+
if (e.role === "captain")
|
|
2177
|
+
knownCaptainSessions.set(e.sessionId, e.project);
|
|
2178
|
+
}
|
|
2170
2179
|
const byProject = /* @__PURE__ */ new Map();
|
|
2171
2180
|
for (const r of records) {
|
|
2172
|
-
|
|
2181
|
+
const role = r.role === "captain" || knownCaptainSessions.get(r.sessionId) === r.project ? "captain" : r.role;
|
|
2182
|
+
if (role !== "captain")
|
|
2173
2183
|
continue;
|
|
2174
2184
|
let arr = byProject.get(r.project);
|
|
2175
2185
|
if (!arr) {
|
|
@@ -2201,10 +2211,14 @@ async function runLivenessTick(deps) {
|
|
|
2201
2211
|
logEntry(deps.log, project, deps.registry.get(project));
|
|
2202
2212
|
}
|
|
2203
2213
|
for (const e of deps.registry.all()) {
|
|
2204
|
-
if (e.role
|
|
2205
|
-
|
|
2206
|
-
|
|
2214
|
+
if (e.role !== "captain" || e.lastState !== "start" || seen.has(e.project))
|
|
2215
|
+
continue;
|
|
2216
|
+
if (e.pid == null || deps.isPidAlive(e.pid)) {
|
|
2217
|
+
deps.log?.(`[${e.role}/runtime] ${e.project} pid=${e.pid} missing from snapshot but not confirmed dead \u2014 leaving alive`);
|
|
2218
|
+
continue;
|
|
2207
2219
|
}
|
|
2220
|
+
deps.registry.markEnded(e.project, now);
|
|
2221
|
+
logEntry(deps.log, e.project, deps.registry.get(e.project));
|
|
2208
2222
|
}
|
|
2209
2223
|
if (deps.reap) {
|
|
2210
2224
|
for (const e of deps.registry.all()) {
|
|
@@ -2756,7 +2770,7 @@ function startDaemon(ctx, opts, pkgVersion) {
|
|
|
2756
2770
|
|
|
2757
2771
|
// packages/core/dist/session-freshness.js
|
|
2758
2772
|
import crypto from "crypto";
|
|
2759
|
-
import
|
|
2773
|
+
import fs10 from "fs";
|
|
2760
2774
|
import path8 from "path";
|
|
2761
2775
|
|
|
2762
2776
|
// packages/core/dist/crew-protocol.js
|
|
@@ -3012,7 +3026,7 @@ function formatInbound(text) {
|
|
|
3012
3026
|
}
|
|
3013
3027
|
|
|
3014
3028
|
// packages/core/dist/telegram/state.js
|
|
3015
|
-
import
|
|
3029
|
+
import fs11 from "fs";
|
|
3016
3030
|
import path9 from "path";
|
|
3017
3031
|
function statePath(stateRoot) {
|
|
3018
3032
|
return path9.join(stateRoot, "telegram-state.json");
|
|
@@ -3022,7 +3036,7 @@ function topicKey(project, scope = "project") {
|
|
|
3022
3036
|
}
|
|
3023
3037
|
function loadState(stateRoot) {
|
|
3024
3038
|
try {
|
|
3025
|
-
const raw =
|
|
3039
|
+
const raw = fs11.readFileSync(statePath(stateRoot), "utf-8");
|
|
3026
3040
|
const data = JSON.parse(raw);
|
|
3027
3041
|
const result = {
|
|
3028
3042
|
offset: typeof data.offset === "number" ? data.offset : 0,
|
|
@@ -3037,8 +3051,8 @@ function loadState(stateRoot) {
|
|
|
3037
3051
|
}
|
|
3038
3052
|
}
|
|
3039
3053
|
function saveState(stateRoot, s) {
|
|
3040
|
-
|
|
3041
|
-
|
|
3054
|
+
fs11.mkdirSync(stateRoot, { recursive: true });
|
|
3055
|
+
fs11.writeFileSync(statePath(stateRoot), JSON.stringify(s, null, 2) + "\n");
|
|
3042
3056
|
}
|
|
3043
3057
|
function setTopic(stateRoot, project, topicId, scope = "project") {
|
|
3044
3058
|
const s = loadState(stateRoot);
|
|
@@ -3573,7 +3587,7 @@ function createTelegramBridge(opts) {
|
|
|
3573
3587
|
}
|
|
3574
3588
|
|
|
3575
3589
|
// packages/core/dist/telegram/setup.js
|
|
3576
|
-
import
|
|
3590
|
+
import fs12 from "fs";
|
|
3577
3591
|
|
|
3578
3592
|
// packages/core/dist/restart-daemon.js
|
|
3579
3593
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
@@ -3589,10 +3603,10 @@ import { join as join12 } from "path";
|
|
|
3589
3603
|
var DEFAULT_SOCK_PATH2 = join12(homedir7(), ".config", "squadrant", "squadrant.sock");
|
|
3590
3604
|
|
|
3591
3605
|
// packages/core/dist/side-session.js
|
|
3592
|
-
import
|
|
3606
|
+
import fs13 from "fs";
|
|
3593
3607
|
|
|
3594
3608
|
// packages/core/dist/crew-spawn.js
|
|
3595
|
-
import
|
|
3609
|
+
import fs14 from "fs";
|
|
3596
3610
|
import os5 from "os";
|
|
3597
3611
|
import path11 from "path";
|
|
3598
3612
|
var TEMPLATES_DIR = path11.join(os5.homedir(), ".config", "squadrant", "templates");
|
|
@@ -3628,7 +3642,7 @@ import { execSync as execSync4 } from "child_process";
|
|
|
3628
3642
|
import { execSync as execSync5 } from "child_process";
|
|
3629
3643
|
|
|
3630
3644
|
// packages/agents/dist/drivers/launch-cmd.js
|
|
3631
|
-
import
|
|
3645
|
+
import fs15 from "fs";
|
|
3632
3646
|
import path12 from "path";
|
|
3633
3647
|
|
|
3634
3648
|
// packages/agents/dist/projection/cursor.js
|
|
@@ -5078,7 +5092,7 @@ var RuntimeRegistry = class {
|
|
|
5078
5092
|
import { execFileSync as execFileSync6, execSync as execSync7 } from "child_process";
|
|
5079
5093
|
|
|
5080
5094
|
// packages/workspaces/dist/workspaces/obsidian.js
|
|
5081
|
-
import
|
|
5095
|
+
import fs16 from "fs/promises";
|
|
5082
5096
|
import { existsSync as existsSync9 } from "fs";
|
|
5083
5097
|
import path17 from "path";
|
|
5084
5098
|
|
|
@@ -5764,7 +5778,7 @@ async function resendCrewFirstTurn(runtime, captainName, project, name, message)
|
|
|
5764
5778
|
}
|
|
5765
5779
|
|
|
5766
5780
|
// packages/cli/src/lib/daemon-restart-broadcast.ts
|
|
5767
|
-
import
|
|
5781
|
+
import fs17 from "fs";
|
|
5768
5782
|
import path18 from "path";
|
|
5769
5783
|
function statePath2(stateRoot) {
|
|
5770
5784
|
return path18.join(stateRoot, "daemon-restart-state.json");
|
|
@@ -5774,7 +5788,7 @@ function computeRestartSignature(version, buildMtimeMs) {
|
|
|
5774
5788
|
}
|
|
5775
5789
|
function readPersistedRestartSignature(stateRoot) {
|
|
5776
5790
|
try {
|
|
5777
|
-
const raw =
|
|
5791
|
+
const raw = fs17.readFileSync(statePath2(stateRoot), "utf-8");
|
|
5778
5792
|
const data = JSON.parse(raw);
|
|
5779
5793
|
return typeof data.signature === "string" ? data.signature : null;
|
|
5780
5794
|
} catch {
|
|
@@ -5782,8 +5796,8 @@ function readPersistedRestartSignature(stateRoot) {
|
|
|
5782
5796
|
}
|
|
5783
5797
|
}
|
|
5784
5798
|
function writePersistedRestartSignature(stateRoot, signature) {
|
|
5785
|
-
|
|
5786
|
-
|
|
5799
|
+
fs17.mkdirSync(stateRoot, { recursive: true });
|
|
5800
|
+
fs17.writeFileSync(statePath2(stateRoot), JSON.stringify({ signature }, null, 2) + "\n");
|
|
5787
5801
|
}
|
|
5788
5802
|
function restartNotice(version, isDevRebuild) {
|
|
5789
5803
|
const suffix = isDevRebuild ? " (dev build)" : "";
|