squadrant 0.18.0 → 0.18.1
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 +609 -418
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +211 -134
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,15 +9,87 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
// packages/shared/dist/config.js
|
|
12
|
+
// packages/shared/dist/lib/config-io.js
|
|
13
13
|
import fs from "fs";
|
|
14
14
|
import path from "path";
|
|
15
|
+
function tightenModeSync(p, expectedMode) {
|
|
16
|
+
try {
|
|
17
|
+
if (!fs.existsSync(p))
|
|
18
|
+
return;
|
|
19
|
+
const stat2 = fs.statSync(p);
|
|
20
|
+
const currentMode = stat2.mode & 4095;
|
|
21
|
+
if ((currentMode & ~expectedMode) !== 0) {
|
|
22
|
+
fs.chmodSync(p, expectedMode);
|
|
23
|
+
if (!didLogMigration) {
|
|
24
|
+
console.warn(`\x1B[33m\u26A0\x1B[0m squadrant: tightened config file permissions (security fix #668)`);
|
|
25
|
+
didLogMigration = true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function writeConfigFileSync(filePath, content) {
|
|
32
|
+
ensureDirSync(path.dirname(filePath));
|
|
33
|
+
fs.writeFileSync(filePath, content, { mode: 384 });
|
|
34
|
+
tightenModeSync(filePath, 384);
|
|
35
|
+
}
|
|
36
|
+
function ensureDirSync(dirPath) {
|
|
37
|
+
if (dirPath !== CONFIG_DIR && !dirPath.startsWith(CONFIG_DIR + path.sep)) {
|
|
38
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
fs.mkdirSync(dirPath, { recursive: true, mode: 448 });
|
|
42
|
+
let current = dirPath;
|
|
43
|
+
while (current === CONFIG_DIR || current.startsWith(CONFIG_DIR + path.sep)) {
|
|
44
|
+
tightenModeSync(current, 448);
|
|
45
|
+
if (current === CONFIG_DIR)
|
|
46
|
+
break;
|
|
47
|
+
const parent = path.dirname(current);
|
|
48
|
+
if (parent === current)
|
|
49
|
+
break;
|
|
50
|
+
current = parent;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function readConfigFileSync(filePath) {
|
|
54
|
+
return fs.readFileSync(filePath, "utf-8");
|
|
55
|
+
}
|
|
56
|
+
function migrateConfigPermsSync() {
|
|
57
|
+
if (migrationRun)
|
|
58
|
+
return;
|
|
59
|
+
migrationRun = true;
|
|
60
|
+
tightenModeSync(CONFIG_DIR, 448);
|
|
61
|
+
tightenModeSync(path.join(CONFIG_DIR, "config.json"), 384);
|
|
62
|
+
const projectsDir = path.join(CONFIG_DIR, "projects");
|
|
63
|
+
tightenModeSync(projectsDir, 448);
|
|
64
|
+
try {
|
|
65
|
+
if (fs.existsSync(projectsDir)) {
|
|
66
|
+
const files = fs.readdirSync(projectsDir);
|
|
67
|
+
for (const file of files) {
|
|
68
|
+
if (file.endsWith(".json")) {
|
|
69
|
+
tightenModeSync(path.join(projectsDir, file), 384);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
var didLogMigration, migrationRun;
|
|
77
|
+
var init_config_io = __esm({
|
|
78
|
+
"packages/shared/dist/lib/config-io.js"() {
|
|
79
|
+
init_config();
|
|
80
|
+
didLogMigration = false;
|
|
81
|
+
migrationRun = false;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// packages/shared/dist/config.js
|
|
86
|
+
import path2 from "path";
|
|
15
87
|
import os from "os";
|
|
16
88
|
import chalk from "chalk";
|
|
17
89
|
function getDefaultConfig() {
|
|
18
90
|
return {
|
|
19
91
|
commandName: "\u{1F3DB}\uFE0F command",
|
|
20
|
-
hubVault:
|
|
92
|
+
hubVault: path2.join(os.homedir(), "squadrant-hub"),
|
|
21
93
|
projects: {},
|
|
22
94
|
agents: {
|
|
23
95
|
claude: { cli: "claude", driver: "claude" }
|
|
@@ -61,13 +133,14 @@ function getDefaultConfig() {
|
|
|
61
133
|
},
|
|
62
134
|
metrics: {
|
|
63
135
|
enabled: true,
|
|
64
|
-
path:
|
|
136
|
+
path: path2.join(CONFIG_DIR, "metrics.json")
|
|
65
137
|
}
|
|
66
138
|
};
|
|
67
139
|
}
|
|
68
140
|
function loadConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
141
|
+
migrateConfigPermsSync();
|
|
69
142
|
try {
|
|
70
|
-
const raw =
|
|
143
|
+
const raw = readConfigFileSync(configPath);
|
|
71
144
|
const config = JSON.parse(raw);
|
|
72
145
|
if (config.defaults.models && !config.defaults.roles) {
|
|
73
146
|
const m = config.defaults.models;
|
|
@@ -92,34 +165,32 @@ function loadConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
|
92
165
|
}
|
|
93
166
|
}
|
|
94
167
|
function saveConfig(config, configPath = DEFAULT_CONFIG_PATH) {
|
|
95
|
-
|
|
96
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
97
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
168
|
+
writeConfigFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
98
169
|
}
|
|
99
170
|
function resolveHome(p) {
|
|
100
171
|
return p.startsWith("~") ? p.replace("~", os.homedir()) : p;
|
|
101
172
|
}
|
|
102
|
-
var
|
|
173
|
+
var DEFAULT_CONFIG_PATH, CONFIG_DIR;
|
|
103
174
|
var init_config = __esm({
|
|
104
175
|
"packages/shared/dist/config.js"() {
|
|
105
|
-
|
|
106
|
-
DEFAULT_CONFIG_PATH =
|
|
176
|
+
init_config_io();
|
|
177
|
+
DEFAULT_CONFIG_PATH = process.env.SQUADRANT_CONFIG || path2.join(os.homedir(), ".config", "squadrant", "config.json");
|
|
178
|
+
CONFIG_DIR = path2.dirname(DEFAULT_CONFIG_PATH);
|
|
107
179
|
}
|
|
108
180
|
});
|
|
109
181
|
|
|
110
182
|
// packages/shared/dist/project-config.js
|
|
111
|
-
import fs2 from "fs";
|
|
112
183
|
import os2 from "os";
|
|
113
|
-
import
|
|
184
|
+
import path3 from "path";
|
|
114
185
|
function defaultRoot() {
|
|
115
|
-
return
|
|
186
|
+
return path3.join(os2.homedir(), ".config", "squadrant");
|
|
116
187
|
}
|
|
117
188
|
function projectConfigPath(name, root = defaultRoot()) {
|
|
118
|
-
return
|
|
189
|
+
return path3.join(root, "projects", `${name}.json`);
|
|
119
190
|
}
|
|
120
191
|
function loadProjectOverride(name, root = defaultRoot()) {
|
|
121
192
|
try {
|
|
122
|
-
return JSON.parse(
|
|
193
|
+
return JSON.parse(readConfigFileSync(projectConfigPath(name, root)));
|
|
123
194
|
} catch {
|
|
124
195
|
return {};
|
|
125
196
|
}
|
|
@@ -136,8 +207,7 @@ function deepMerge(base, patch) {
|
|
|
136
207
|
function saveProjectOverride(name, patch, root = defaultRoot()) {
|
|
137
208
|
const merged = deepMerge(loadProjectOverride(name, root), patch);
|
|
138
209
|
const file = projectConfigPath(name, root);
|
|
139
|
-
|
|
140
|
-
fs2.writeFileSync(file, JSON.stringify(merged, null, 2) + "\n");
|
|
210
|
+
writeConfigFileSync(file, JSON.stringify(merged, null, 2) + "\n");
|
|
141
211
|
}
|
|
142
212
|
function crewRank(tier) {
|
|
143
213
|
return CREW_RANK[tier];
|
|
@@ -162,6 +232,7 @@ function resolveNotify(globalNotify, override) {
|
|
|
162
232
|
var DEFAULT_NOTIFY, CREW_RANK;
|
|
163
233
|
var init_project_config = __esm({
|
|
164
234
|
"packages/shared/dist/project-config.js"() {
|
|
235
|
+
init_config_io();
|
|
165
236
|
DEFAULT_NOTIFY = { active: false, cap: true, crew: "alert_only" };
|
|
166
237
|
CREW_RANK = { none: 0, done_only: 1, alert_only: 2, all: 3 };
|
|
167
238
|
}
|
|
@@ -234,22 +305,22 @@ function defaultCmuxConfigPath() {
|
|
|
234
305
|
return join(homedir(), ".config", "cmux", "cmux.json");
|
|
235
306
|
}
|
|
236
307
|
function ensureSocketAutomation(opts = {}) {
|
|
237
|
-
const
|
|
238
|
-
if (!existsSync(
|
|
239
|
-
mkdirSync(dirname(
|
|
240
|
-
writeFileSync(
|
|
241
|
-
return { path:
|
|
308
|
+
const path35 = opts.path ?? defaultCmuxConfigPath();
|
|
309
|
+
if (!existsSync(path35)) {
|
|
310
|
+
mkdirSync(dirname(path35), { recursive: true });
|
|
311
|
+
writeFileSync(path35, MINIMAL_TEMPLATE);
|
|
312
|
+
return { path: path35, changed: true, alreadySet: false };
|
|
242
313
|
}
|
|
243
|
-
const text = readFileSync(
|
|
314
|
+
const text = readFileSync(path35, "utf-8");
|
|
244
315
|
const current = parse(text)?.automation?.socketControlMode;
|
|
245
316
|
if (current === AUTOMATION_MODE) {
|
|
246
|
-
return { path:
|
|
317
|
+
return { path: path35, changed: false, alreadySet: true };
|
|
247
318
|
}
|
|
248
319
|
const edits = modify(text, [...SOCKET_CONTROL_MODE_PATH], AUTOMATION_MODE, {
|
|
249
320
|
formattingOptions: { insertSpaces: true, tabSize: 2 }
|
|
250
321
|
});
|
|
251
|
-
writeFileSync(
|
|
252
|
-
return { path:
|
|
322
|
+
writeFileSync(path35, applyEdits(text, edits));
|
|
323
|
+
return { path: path35, changed: true, alreadySet: false };
|
|
253
324
|
}
|
|
254
325
|
var SOCKET_CONTROL_MODE_PATH, AUTOMATION_MODE, MINIMAL_TEMPLATE;
|
|
255
326
|
var init_cmux_config = __esm({
|
|
@@ -396,15 +467,15 @@ writeFileSync(resultFile, JSON.stringify(result));
|
|
|
396
467
|
});
|
|
397
468
|
|
|
398
469
|
// packages/shared/dist/lib/cmux-autoconfig.js
|
|
399
|
-
import { existsSync as existsSync4,
|
|
470
|
+
import { existsSync as existsSync4, rmSync as rmSync2 } from "fs";
|
|
400
471
|
import { homedir as homedir3 } from "os";
|
|
401
|
-
import {
|
|
472
|
+
import { join as join4 } from "path";
|
|
402
473
|
function defaultStatePath() {
|
|
403
474
|
return join4(homedir3(), ".config", "squadrant", "state", "cmux-autoconfig.json");
|
|
404
475
|
}
|
|
405
|
-
function readState(
|
|
476
|
+
function readState(path35) {
|
|
406
477
|
try {
|
|
407
|
-
return JSON.parse(
|
|
478
|
+
return JSON.parse(readConfigFileSync(path35));
|
|
408
479
|
} catch {
|
|
409
480
|
return {};
|
|
410
481
|
}
|
|
@@ -420,8 +491,7 @@ async function ensureCmuxAutoConfig(opts = {}) {
|
|
|
420
491
|
if (needsRestart) {
|
|
421
492
|
const already = readState(statePath2).promptedRestart === true;
|
|
422
493
|
if (!already) {
|
|
423
|
-
|
|
424
|
-
writeFileSync3(statePath2, JSON.stringify({ promptedRestart: true }));
|
|
494
|
+
writeConfigFileSync(statePath2, JSON.stringify({ promptedRestart: true }));
|
|
425
495
|
promptedThisRun = true;
|
|
426
496
|
}
|
|
427
497
|
} else if (verdict === "reachable") {
|
|
@@ -441,6 +511,7 @@ var init_cmux_autoconfig = __esm({
|
|
|
441
511
|
"packages/shared/dist/lib/cmux-autoconfig.js"() {
|
|
442
512
|
init_cmux_config();
|
|
443
513
|
init_cmux_probe();
|
|
514
|
+
init_config_io();
|
|
444
515
|
}
|
|
445
516
|
});
|
|
446
517
|
|
|
@@ -624,8 +695,8 @@ var init_config_version = __esm({
|
|
|
624
695
|
});
|
|
625
696
|
|
|
626
697
|
// packages/shared/dist/lib/update-check.js
|
|
627
|
-
import
|
|
628
|
-
import
|
|
698
|
+
import fs2 from "fs";
|
|
699
|
+
import path4 from "path";
|
|
629
700
|
import os3 from "os";
|
|
630
701
|
import https from "https";
|
|
631
702
|
function isUpdateCheckDisabled(config, env = process.env) {
|
|
@@ -648,8 +719,25 @@ function isNewerVersion(latest, current) {
|
|
|
648
719
|
return lb > cb;
|
|
649
720
|
return lc > cc;
|
|
650
721
|
}
|
|
651
|
-
function
|
|
652
|
-
|
|
722
|
+
function detectInstallManager(modulePath = import.meta.url) {
|
|
723
|
+
if (modulePath.includes("Library/pnpm/") || modulePath.includes("/pnpm/"))
|
|
724
|
+
return "pnpm";
|
|
725
|
+
if (modulePath.includes("/yarn/global/node_modules/"))
|
|
726
|
+
return "yarn";
|
|
727
|
+
return "npm";
|
|
728
|
+
}
|
|
729
|
+
function upgradeCommandFor(manager) {
|
|
730
|
+
switch (manager) {
|
|
731
|
+
case "pnpm":
|
|
732
|
+
return "pnpm add -g squadrant@latest";
|
|
733
|
+
case "yarn":
|
|
734
|
+
return "yarn global add squadrant@latest";
|
|
735
|
+
case "npm":
|
|
736
|
+
return "npm i -g squadrant@latest";
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
function formatUpdateNotice(latest, current, modulePath = import.meta.url) {
|
|
740
|
+
return `\u2B06 squadrant ${latest} available (you have ${current}) \u2014 ${upgradeCommandFor(detectInstallManager(modulePath))}`;
|
|
653
741
|
}
|
|
654
742
|
async function fetchLatestVersion(requestFn = requestJson, timeoutMs = FETCH_TIMEOUT_MS) {
|
|
655
743
|
const timeout = new Promise((resolve4) => {
|
|
@@ -681,15 +769,15 @@ async function checkForUpdate(opts) {
|
|
|
681
769
|
}
|
|
682
770
|
function readUpdateCheckState(statePath2 = UPDATE_CHECK_STATE_PATH) {
|
|
683
771
|
try {
|
|
684
|
-
return JSON.parse(
|
|
772
|
+
return JSON.parse(fs2.readFileSync(statePath2, "utf-8"));
|
|
685
773
|
} catch {
|
|
686
774
|
return void 0;
|
|
687
775
|
}
|
|
688
776
|
}
|
|
689
777
|
function writeUpdateCheckState(state, statePath2 = UPDATE_CHECK_STATE_PATH) {
|
|
690
778
|
try {
|
|
691
|
-
|
|
692
|
-
|
|
779
|
+
fs2.mkdirSync(path4.dirname(statePath2), { recursive: true });
|
|
780
|
+
fs2.writeFileSync(statePath2, JSON.stringify(state, null, 2) + "\n");
|
|
693
781
|
} catch {
|
|
694
782
|
}
|
|
695
783
|
}
|
|
@@ -720,7 +808,7 @@ ${line}
|
|
|
720
808
|
var UPDATE_CHECK_STATE_PATH, REGISTRY_URL, CHECK_INTERVAL_MS, FAILURE_RETRY_MS, FETCH_TIMEOUT_MS, requestJson;
|
|
721
809
|
var init_update_check = __esm({
|
|
722
810
|
"packages/shared/dist/lib/update-check.js"() {
|
|
723
|
-
UPDATE_CHECK_STATE_PATH =
|
|
811
|
+
UPDATE_CHECK_STATE_PATH = path4.join(os3.homedir(), ".config", "squadrant", "update-check.json");
|
|
724
812
|
REGISTRY_URL = "https://registry.npmjs.org/squadrant/latest";
|
|
725
813
|
CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
726
814
|
FAILURE_RETRY_MS = 60 * 60 * 1e3;
|
|
@@ -752,10 +840,10 @@ var init_update_check = __esm({
|
|
|
752
840
|
|
|
753
841
|
// packages/shared/dist/lib/git-worktree.js
|
|
754
842
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
755
|
-
import
|
|
756
|
-
import
|
|
843
|
+
import fs3 from "fs";
|
|
844
|
+
import path5 from "path";
|
|
757
845
|
function worktreePath(repoRoot, worktreeDir, project, name) {
|
|
758
|
-
return
|
|
846
|
+
return path5.resolve(repoRoot, worktreeDir, `${project}-${name}`);
|
|
759
847
|
}
|
|
760
848
|
function crewBranch(name) {
|
|
761
849
|
return `crew/${name}`;
|
|
@@ -764,11 +852,11 @@ function ensureSpotlightExcluded(repoRoot, worktreeDir) {
|
|
|
764
852
|
if (process.platform !== "darwin")
|
|
765
853
|
return;
|
|
766
854
|
try {
|
|
767
|
-
const dir =
|
|
768
|
-
|
|
769
|
-
const marker =
|
|
770
|
-
if (!
|
|
771
|
-
|
|
855
|
+
const dir = path5.resolve(repoRoot, worktreeDir);
|
|
856
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
857
|
+
const marker = path5.join(dir, ".metadata_never_index");
|
|
858
|
+
if (!fs3.existsSync(marker))
|
|
859
|
+
fs3.writeFileSync(marker, "");
|
|
772
860
|
} catch {
|
|
773
861
|
}
|
|
774
862
|
}
|
|
@@ -830,15 +918,15 @@ function addWorktree(spec) {
|
|
|
830
918
|
return wt;
|
|
831
919
|
}
|
|
832
920
|
function installWorktreeDependencies(wt) {
|
|
833
|
-
if (!
|
|
921
|
+
if (!fs3.existsSync(path5.join(wt, "package.json")))
|
|
834
922
|
return;
|
|
835
|
-
if (
|
|
923
|
+
if (fs3.existsSync(path5.join(wt, "pnpm-lock.yaml"))) {
|
|
836
924
|
execFileSync2("pnpm", ["-C", wt, "install", "--frozen-lockfile"], { stdio: "pipe" });
|
|
837
|
-
} else if (
|
|
925
|
+
} else if (fs3.existsSync(path5.join(wt, "yarn.lock"))) {
|
|
838
926
|
execFileSync2("yarn", ["install", "--frozen-lockfile"], { cwd: wt, stdio: "pipe" });
|
|
839
|
-
} else if (
|
|
927
|
+
} else if (fs3.existsSync(path5.join(wt, "package-lock.json"))) {
|
|
840
928
|
execFileSync2("npm", ["ci"], { cwd: wt, stdio: "pipe" });
|
|
841
|
-
} else if (
|
|
929
|
+
} else if (fs3.existsSync(path5.join(wt, "bun.lockb"))) {
|
|
842
930
|
execFileSync2("bun", ["install", "--frozen-lockfile"], { cwd: wt, stdio: "pipe" });
|
|
843
931
|
} else {
|
|
844
932
|
process.stderr.write(`worktree ${wt}: package.json present but no lockfile \u2014 dependencies not installed; local typechecks/tests may resolve against the main checkout instead of this worktree.
|
|
@@ -862,7 +950,7 @@ var init_git_worktree = __esm({
|
|
|
862
950
|
});
|
|
863
951
|
|
|
864
952
|
// packages/shared/dist/lib/resolve-text-input.js
|
|
865
|
-
import
|
|
953
|
+
import fs4 from "fs";
|
|
866
954
|
async function readAllStdin() {
|
|
867
955
|
const chunks = [];
|
|
868
956
|
for await (const chunk of process.stdin) {
|
|
@@ -874,7 +962,7 @@ function flagName(label) {
|
|
|
874
962
|
return label === "task" ? "--task-file" : "--message-file";
|
|
875
963
|
}
|
|
876
964
|
async function resolveTextInput(opts, deps) {
|
|
877
|
-
const readFile6 = deps?.readFile ?? ((p) =>
|
|
965
|
+
const readFile6 = deps?.readFile ?? ((p) => fs4.readFileSync(p, "utf8"));
|
|
878
966
|
const readStdin3 = deps?.readStdin ?? readAllStdin;
|
|
879
967
|
if (opts.filePath) {
|
|
880
968
|
if (opts.filePath === "-") {
|
|
@@ -902,75 +990,75 @@ var init_resolve_text_input = __esm({
|
|
|
902
990
|
});
|
|
903
991
|
|
|
904
992
|
// packages/shared/dist/lib/runtime-sync.js
|
|
905
|
-
import
|
|
906
|
-
import
|
|
993
|
+
import fs5 from "fs";
|
|
994
|
+
import path6 from "path";
|
|
907
995
|
function copyIfDifferent(src, dest) {
|
|
908
|
-
if (
|
|
909
|
-
if (
|
|
996
|
+
if (fs5.existsSync(dest)) {
|
|
997
|
+
if (fs5.readFileSync(src).equals(fs5.readFileSync(dest)))
|
|
910
998
|
return false;
|
|
911
999
|
}
|
|
912
|
-
|
|
1000
|
+
fs5.copyFileSync(src, dest);
|
|
913
1001
|
return true;
|
|
914
1002
|
}
|
|
915
1003
|
function mirrorDir(src, dest) {
|
|
916
|
-
|
|
917
|
-
const srcEntries =
|
|
1004
|
+
fs5.mkdirSync(dest, { recursive: true });
|
|
1005
|
+
const srcEntries = fs5.readdirSync(src, { withFileTypes: true });
|
|
918
1006
|
const srcNames = new Set(srcEntries.map((e) => e.name));
|
|
919
1007
|
for (const entry of srcEntries) {
|
|
920
|
-
const srcPath =
|
|
921
|
-
const destPath =
|
|
1008
|
+
const srcPath = path6.join(src, entry.name);
|
|
1009
|
+
const destPath = path6.join(dest, entry.name);
|
|
922
1010
|
if (entry.isDirectory()) {
|
|
923
1011
|
mirrorDir(srcPath, destPath);
|
|
924
1012
|
} else {
|
|
925
1013
|
copyIfDifferent(srcPath, destPath);
|
|
926
1014
|
}
|
|
927
1015
|
}
|
|
928
|
-
for (const entry of
|
|
1016
|
+
for (const entry of fs5.readdirSync(dest, { withFileTypes: true })) {
|
|
929
1017
|
if (!srcNames.has(entry.name)) {
|
|
930
|
-
|
|
1018
|
+
fs5.rmSync(path6.join(dest, entry.name), { recursive: true, force: true });
|
|
931
1019
|
}
|
|
932
1020
|
}
|
|
933
1021
|
}
|
|
934
1022
|
function mirrorFlat(src, dest, match, chmod) {
|
|
935
|
-
|
|
936
|
-
const matched =
|
|
1023
|
+
fs5.mkdirSync(dest, { recursive: true });
|
|
1024
|
+
const matched = fs5.readdirSync(src, { withFileTypes: true }).filter((e) => e.isFile() && match.test(e.name)).map((e) => e.name);
|
|
937
1025
|
const matchedSet = new Set(matched);
|
|
938
1026
|
for (const name of matched) {
|
|
939
|
-
const destPath =
|
|
940
|
-
const copied = copyIfDifferent(
|
|
1027
|
+
const destPath = path6.join(dest, name);
|
|
1028
|
+
const copied = copyIfDifferent(path6.join(src, name), destPath);
|
|
941
1029
|
if (copied && chmod !== void 0)
|
|
942
|
-
|
|
1030
|
+
fs5.chmodSync(destPath, chmod);
|
|
943
1031
|
}
|
|
944
|
-
for (const entry of
|
|
1032
|
+
for (const entry of fs5.readdirSync(dest, { withFileTypes: true })) {
|
|
945
1033
|
if (!matchedSet.has(entry.name)) {
|
|
946
|
-
|
|
1034
|
+
fs5.rmSync(path6.join(dest, entry.name), { recursive: true, force: true });
|
|
947
1035
|
}
|
|
948
1036
|
}
|
|
949
1037
|
}
|
|
950
1038
|
function mirrorPluginSubset(src, dest, skills) {
|
|
951
|
-
|
|
952
|
-
mirrorDir(
|
|
953
|
-
const skillsDest =
|
|
954
|
-
|
|
1039
|
+
fs5.mkdirSync(dest, { recursive: true });
|
|
1040
|
+
mirrorDir(path6.join(src, ".claude-plugin"), path6.join(dest, ".claude-plugin"));
|
|
1041
|
+
const skillsDest = path6.join(dest, "skills");
|
|
1042
|
+
fs5.mkdirSync(skillsDest, { recursive: true });
|
|
955
1043
|
for (const name of skills) {
|
|
956
|
-
const skillSrc =
|
|
957
|
-
if (
|
|
958
|
-
mirrorDir(skillSrc,
|
|
1044
|
+
const skillSrc = path6.join(src, "skills", name);
|
|
1045
|
+
if (fs5.existsSync(skillSrc))
|
|
1046
|
+
mirrorDir(skillSrc, path6.join(skillsDest, name));
|
|
959
1047
|
}
|
|
960
|
-
for (const entry of
|
|
1048
|
+
for (const entry of fs5.readdirSync(skillsDest, { withFileTypes: true })) {
|
|
961
1049
|
if (!skills.includes(entry.name)) {
|
|
962
|
-
|
|
1050
|
+
fs5.rmSync(path6.join(skillsDest, entry.name), { recursive: true, force: true });
|
|
963
1051
|
}
|
|
964
1052
|
}
|
|
965
1053
|
}
|
|
966
1054
|
function ensureRuntimeSynced(opts) {
|
|
967
1055
|
const targets = opts.targets ?? MANAGED_TARGETS;
|
|
968
1056
|
for (const t of targets) {
|
|
969
|
-
const srcDir =
|
|
1057
|
+
const srcDir = path6.join(opts.sourceRoot, t.srcRel);
|
|
970
1058
|
try {
|
|
971
|
-
if (!
|
|
1059
|
+
if (!fs5.existsSync(srcDir))
|
|
972
1060
|
continue;
|
|
973
|
-
const destDir =
|
|
1061
|
+
const destDir = path6.join(opts.runtimeRoot, t.name);
|
|
974
1062
|
if (t.mode === "tree") {
|
|
975
1063
|
mirrorDir(srcDir, destDir);
|
|
976
1064
|
} else if (t.mode === "flat") {
|
|
@@ -1038,8 +1126,8 @@ var init_tool_compat = __esm({
|
|
|
1038
1126
|
});
|
|
1039
1127
|
|
|
1040
1128
|
// packages/shared/dist/lib/canonical-source.js
|
|
1041
|
-
import
|
|
1042
|
-
import
|
|
1129
|
+
import fs6 from "fs";
|
|
1130
|
+
import path7 from "path";
|
|
1043
1131
|
function parseSkill(raw) {
|
|
1044
1132
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
1045
1133
|
if (!match)
|
|
@@ -1080,10 +1168,10 @@ async function readSkills(driver, skillsDir) {
|
|
|
1080
1168
|
function readRoleTemplates(opts) {
|
|
1081
1169
|
if (!opts.pkgRoot)
|
|
1082
1170
|
return "";
|
|
1083
|
-
const reader = opts.readFile ?? ((p) =>
|
|
1171
|
+
const reader = opts.readFile ?? ((p) => fs6.readFileSync(p, "utf-8"));
|
|
1084
1172
|
const sections = [];
|
|
1085
1173
|
for (const { file, heading } of ROLE_TEMPLATES) {
|
|
1086
|
-
const full =
|
|
1174
|
+
const full = path7.join(opts.pkgRoot, "templates", file);
|
|
1087
1175
|
let body = "";
|
|
1088
1176
|
try {
|
|
1089
1177
|
body = reader(full);
|
|
@@ -1120,8 +1208,8 @@ var init_canonical_source = __esm({
|
|
|
1120
1208
|
|
|
1121
1209
|
// packages/shared/dist/lib/daily-logs.js
|
|
1122
1210
|
import { execSync } from "child_process";
|
|
1123
|
-
import
|
|
1124
|
-
import
|
|
1211
|
+
import fs7 from "fs";
|
|
1212
|
+
import path8 from "path";
|
|
1125
1213
|
import matter from "gray-matter";
|
|
1126
1214
|
function iso(d) {
|
|
1127
1215
|
return d.toISOString().slice(0, 10);
|
|
@@ -1173,7 +1261,7 @@ function getGitCommits(projectPath, dateStr) {
|
|
|
1173
1261
|
}
|
|
1174
1262
|
function getGitCommitsInRange(projectPath, since, until) {
|
|
1175
1263
|
const resolved = resolveHome(projectPath);
|
|
1176
|
-
if (!
|
|
1264
|
+
if (!fs7.existsSync(path8.join(resolved, ".git")))
|
|
1177
1265
|
return [];
|
|
1178
1266
|
const untilArg = until ? ` --until="${until}"` : "";
|
|
1179
1267
|
try {
|
|
@@ -1187,7 +1275,7 @@ function getGitCommitsInRange(projectPath, since, until) {
|
|
|
1187
1275
|
}
|
|
1188
1276
|
function getMergedPRsInRange(projectPath, since, until) {
|
|
1189
1277
|
const resolved = resolveHome(projectPath);
|
|
1190
|
-
if (!
|
|
1278
|
+
if (!fs7.existsSync(path8.join(resolved, ".git")))
|
|
1191
1279
|
return [];
|
|
1192
1280
|
const untilArg = until ? ` --until="${until}"` : "";
|
|
1193
1281
|
try {
|
|
@@ -1247,6 +1335,7 @@ var init_daemon_keys = __esm({
|
|
|
1247
1335
|
var dist_exports = {};
|
|
1248
1336
|
__export(dist_exports, {
|
|
1249
1337
|
AUTOMATION_MODE: () => AUTOMATION_MODE,
|
|
1338
|
+
CONFIG_DIR: () => CONFIG_DIR,
|
|
1250
1339
|
CREW_SKILLS: () => CREW_SKILLS,
|
|
1251
1340
|
DEFAULT_CONFIG_PATH: () => DEFAULT_CONFIG_PATH,
|
|
1252
1341
|
DEFAULT_NOTIFY: () => DEFAULT_NOTIFY,
|
|
@@ -1270,7 +1359,9 @@ __export(dist_exports, {
|
|
|
1270
1359
|
defaultCmuxConfigPath: () => defaultCmuxConfigPath,
|
|
1271
1360
|
defaultStatePath: () => defaultStatePath,
|
|
1272
1361
|
detectDrift: () => detectDrift,
|
|
1362
|
+
detectInstallManager: () => detectInstallManager,
|
|
1273
1363
|
ensureCmuxAutoConfig: () => ensureCmuxAutoConfig,
|
|
1364
|
+
ensureDirSync: () => ensureDirSync,
|
|
1274
1365
|
ensureRuntimeSynced: () => ensureRuntimeSynced,
|
|
1275
1366
|
ensureSocketAutomation: () => ensureSocketAutomation,
|
|
1276
1367
|
ensureSpokeLayout: () => ensureSpokeLayout,
|
|
@@ -1289,6 +1380,7 @@ __export(dist_exports, {
|
|
|
1289
1380
|
iso: () => iso,
|
|
1290
1381
|
loadConfig: () => loadConfig,
|
|
1291
1382
|
loadProjectOverride: () => loadProjectOverride,
|
|
1383
|
+
migrateConfigPermsSync: () => migrateConfigPermsSync,
|
|
1292
1384
|
mirrorDir: () => mirrorDir,
|
|
1293
1385
|
mirrorFlat: () => mirrorFlat,
|
|
1294
1386
|
needsCheck: () => needsCheck,
|
|
@@ -1296,6 +1388,7 @@ __export(dist_exports, {
|
|
|
1296
1388
|
parseSection: () => parseSection,
|
|
1297
1389
|
probeCmuxDaemonDirect: () => probeCmuxDaemonDirect,
|
|
1298
1390
|
projectConfigPath: () => projectConfigPath,
|
|
1391
|
+
readConfigFileSync: () => readConfigFileSync,
|
|
1299
1392
|
readDailyLog: () => readDailyLog,
|
|
1300
1393
|
readProjectLevelSource: () => readProjectLevelSource,
|
|
1301
1394
|
readStamp: () => readStamp,
|
|
@@ -1314,6 +1407,7 @@ __export(dist_exports, {
|
|
|
1314
1407
|
withStamp: () => withStamp,
|
|
1315
1408
|
worktreeDirtyFiles: () => worktreeDirtyFiles,
|
|
1316
1409
|
worktreePath: () => worktreePath,
|
|
1410
|
+
writeConfigFileSync: () => writeConfigFileSync,
|
|
1317
1411
|
writeUpdateCheckState: () => writeUpdateCheckState
|
|
1318
1412
|
});
|
|
1319
1413
|
var init_dist = __esm({
|
|
@@ -1335,6 +1429,7 @@ var init_dist = __esm({
|
|
|
1335
1429
|
init_config_drift();
|
|
1336
1430
|
init_config_version();
|
|
1337
1431
|
init_update_check();
|
|
1432
|
+
init_config_io();
|
|
1338
1433
|
init_git_worktree();
|
|
1339
1434
|
init_resolve_text_input();
|
|
1340
1435
|
init_runtime_sync();
|
|
@@ -1974,7 +2069,7 @@ var init_reduce = __esm({
|
|
|
1974
2069
|
});
|
|
1975
2070
|
|
|
1976
2071
|
// packages/core/dist/mailbox.js
|
|
1977
|
-
import { promises as
|
|
2072
|
+
import { promises as fs8 } from "fs";
|
|
1978
2073
|
import { join as join5 } from "path";
|
|
1979
2074
|
import { randomUUID } from "crypto";
|
|
1980
2075
|
function inboxDir(stateRoot) {
|
|
@@ -1991,7 +2086,7 @@ async function listRotatedOldestFirst(stateRoot, project) {
|
|
|
1991
2086
|
const dir = inboxDir(stateRoot);
|
|
1992
2087
|
let entries;
|
|
1993
2088
|
try {
|
|
1994
|
-
entries = await
|
|
2089
|
+
entries = await fs8.readdir(dir);
|
|
1995
2090
|
} catch {
|
|
1996
2091
|
return [];
|
|
1997
2092
|
}
|
|
@@ -2000,7 +2095,7 @@ async function listRotatedOldestFirst(stateRoot, project) {
|
|
|
2000
2095
|
}
|
|
2001
2096
|
async function readMaxSeqFromFile(file) {
|
|
2002
2097
|
try {
|
|
2003
|
-
const buf = await
|
|
2098
|
+
const buf = await fs8.readFile(file, "utf-8");
|
|
2004
2099
|
if (!buf.trim())
|
|
2005
2100
|
return 0;
|
|
2006
2101
|
const lines = buf.trim().split("\n");
|
|
@@ -2041,12 +2136,12 @@ function withProjectLock(project, fn) {
|
|
|
2041
2136
|
function appendEntry(stateRoot, project, build) {
|
|
2042
2137
|
return withProjectLock(project, async () => {
|
|
2043
2138
|
const dir = inboxDir(stateRoot);
|
|
2044
|
-
await
|
|
2139
|
+
await fs8.mkdir(dir, { recursive: true });
|
|
2045
2140
|
const file = logPath(stateRoot, project);
|
|
2046
2141
|
const lastSeq = await readMaxSeq(stateRoot, project);
|
|
2047
2142
|
const seq = lastSeq + 1;
|
|
2048
2143
|
const entry = build(seq);
|
|
2049
|
-
await
|
|
2144
|
+
await fs8.appendFile(file, JSON.stringify(entry) + "\n", { encoding: "utf-8" });
|
|
2050
2145
|
return seq;
|
|
2051
2146
|
});
|
|
2052
2147
|
}
|
|
@@ -2077,7 +2172,7 @@ function cursorPath(stateRoot, project, subscriber) {
|
|
|
2077
2172
|
async function readCursor(opts) {
|
|
2078
2173
|
let buf;
|
|
2079
2174
|
try {
|
|
2080
|
-
buf = await
|
|
2175
|
+
buf = await fs8.readFile(cursorPath(opts.stateRoot, opts.project, opts.subscriber), "utf-8");
|
|
2081
2176
|
} catch (e) {
|
|
2082
2177
|
if (e.code === "ENOENT")
|
|
2083
2178
|
return null;
|
|
@@ -2104,7 +2199,7 @@ async function waitForCaptainDelivery(opts) {
|
|
|
2104
2199
|
}
|
|
2105
2200
|
}
|
|
2106
2201
|
async function writeCursor(opts) {
|
|
2107
|
-
await
|
|
2202
|
+
await fs8.mkdir(inboxDir(opts.stateRoot), { recursive: true });
|
|
2108
2203
|
const dest = cursorPath(opts.stateRoot, opts.project, opts.subscriber);
|
|
2109
2204
|
const tmp = `${dest}.${process.pid}.${randomUUID()}.tmp`;
|
|
2110
2205
|
const data = {
|
|
@@ -2112,7 +2207,7 @@ async function writeCursor(opts) {
|
|
|
2112
2207
|
subscriber: opts.subscriber,
|
|
2113
2208
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2114
2209
|
};
|
|
2115
|
-
const handle = await
|
|
2210
|
+
const handle = await fs8.open(tmp, "w");
|
|
2116
2211
|
try {
|
|
2117
2212
|
await handle.writeFile(JSON.stringify(data), { encoding: "utf-8" });
|
|
2118
2213
|
await handle.sync();
|
|
@@ -2120,9 +2215,9 @@ async function writeCursor(opts) {
|
|
|
2120
2215
|
await handle.close();
|
|
2121
2216
|
}
|
|
2122
2217
|
try {
|
|
2123
|
-
await
|
|
2218
|
+
await fs8.rename(tmp, dest);
|
|
2124
2219
|
} catch (e) {
|
|
2125
|
-
await
|
|
2220
|
+
await fs8.unlink(tmp).catch(() => {
|
|
2126
2221
|
});
|
|
2127
2222
|
throw e;
|
|
2128
2223
|
}
|
|
@@ -2133,7 +2228,7 @@ async function* readFromCursor(opts) {
|
|
|
2133
2228
|
for (const file of files) {
|
|
2134
2229
|
let buf;
|
|
2135
2230
|
try {
|
|
2136
|
-
buf = await
|
|
2231
|
+
buf = await fs8.readFile(file, "utf-8");
|
|
2137
2232
|
} catch (e) {
|
|
2138
2233
|
if (e.code === "ENOENT")
|
|
2139
2234
|
continue;
|
|
@@ -2159,7 +2254,7 @@ async function mailboxStats(stateRoot, project) {
|
|
|
2159
2254
|
let sizeBytes = 0;
|
|
2160
2255
|
for (const f of [file, ...rotated]) {
|
|
2161
2256
|
try {
|
|
2162
|
-
sizeBytes += (await
|
|
2257
|
+
sizeBytes += (await fs8.stat(f)).size;
|
|
2163
2258
|
} catch (e) {
|
|
2164
2259
|
if (e.code !== "ENOENT")
|
|
2165
2260
|
throw e;
|
|
@@ -2175,7 +2270,7 @@ async function mailboxStats(stateRoot, project) {
|
|
|
2175
2270
|
}
|
|
2176
2271
|
async function oldestEntryAgeMs(file) {
|
|
2177
2272
|
try {
|
|
2178
|
-
const buf = await
|
|
2273
|
+
const buf = await fs8.readFile(file, "utf-8");
|
|
2179
2274
|
const firstLine2 = buf.split("\n").find((l) => l.trim());
|
|
2180
2275
|
if (!firstLine2)
|
|
2181
2276
|
return 0;
|
|
@@ -2190,7 +2285,7 @@ async function rotateIfNeeded(opts) {
|
|
|
2190
2285
|
const file = logPath(opts.stateRoot, opts.project);
|
|
2191
2286
|
let size = 0;
|
|
2192
2287
|
try {
|
|
2193
|
-
size = (await
|
|
2288
|
+
size = (await fs8.stat(file)).size;
|
|
2194
2289
|
} catch (e) {
|
|
2195
2290
|
if (e.code === "ENOENT")
|
|
2196
2291
|
return { rotated: false };
|
|
@@ -2206,22 +2301,22 @@ async function rotateIfNeeded(opts) {
|
|
|
2206
2301
|
const dst = `${file}.${n + 1}`;
|
|
2207
2302
|
if (n + 1 > opts.keepCount) {
|
|
2208
2303
|
try {
|
|
2209
|
-
await
|
|
2304
|
+
await fs8.unlink(src);
|
|
2210
2305
|
} catch (e) {
|
|
2211
2306
|
if (e.code !== "ENOENT")
|
|
2212
2307
|
throw e;
|
|
2213
2308
|
}
|
|
2214
2309
|
} else {
|
|
2215
2310
|
try {
|
|
2216
|
-
await
|
|
2311
|
+
await fs8.rename(src, dst);
|
|
2217
2312
|
} catch (e) {
|
|
2218
2313
|
if (e.code !== "ENOENT")
|
|
2219
2314
|
throw e;
|
|
2220
2315
|
}
|
|
2221
2316
|
}
|
|
2222
2317
|
}
|
|
2223
|
-
await
|
|
2224
|
-
await
|
|
2318
|
+
await fs8.rename(file, `${file}.1`);
|
|
2319
|
+
await fs8.writeFile(file, "", { encoding: "utf-8" });
|
|
2225
2320
|
return { rotated: true, from: file, to: `${file}.1` };
|
|
2226
2321
|
});
|
|
2227
2322
|
}
|
|
@@ -2234,7 +2329,7 @@ var init_mailbox = __esm({
|
|
|
2234
2329
|
|
|
2235
2330
|
// packages/core/dist/protocol.js
|
|
2236
2331
|
import { createServer, createConnection } from "net";
|
|
2237
|
-
import { existsSync as existsSync5, unlinkSync } from "fs";
|
|
2332
|
+
import { existsSync as existsSync5, unlinkSync, chmodSync } from "fs";
|
|
2238
2333
|
function encodeMsg(obj) {
|
|
2239
2334
|
return JSON.stringify(obj) + "\n";
|
|
2240
2335
|
}
|
|
@@ -2347,6 +2442,12 @@ function startServer(sockPath, handlerOrCallbacks, onListenError = defaultListen
|
|
|
2347
2442
|
});
|
|
2348
2443
|
});
|
|
2349
2444
|
server.on("error", onListenError);
|
|
2445
|
+
server.on("listening", () => {
|
|
2446
|
+
try {
|
|
2447
|
+
chmodSync(sockPath, 384);
|
|
2448
|
+
} catch {
|
|
2449
|
+
}
|
|
2450
|
+
});
|
|
2350
2451
|
server.listen(sockPath);
|
|
2351
2452
|
return server;
|
|
2352
2453
|
}
|
|
@@ -2530,7 +2631,7 @@ var init_liveness2 = __esm({
|
|
|
2530
2631
|
});
|
|
2531
2632
|
|
|
2532
2633
|
// packages/core/dist/store.js
|
|
2533
|
-
import { mkdirSync as
|
|
2634
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, readdirSync, renameSync, writeFileSync as writeFileSync3, existsSync as existsSync6, rmSync as rmSync3, statSync } from "fs";
|
|
2534
2635
|
import { join as join6, resolve, sep } from "path";
|
|
2535
2636
|
function safeSegment(kind, s) {
|
|
2536
2637
|
if (typeof s !== "string" || s.length === 0) {
|
|
@@ -2556,10 +2657,10 @@ function createStore(root) {
|
|
|
2556
2657
|
const taskFile = (p, id) => assertUnderRoot(join6(projDir(p), `${safeSegment("id", id)}.json`));
|
|
2557
2658
|
return {
|
|
2558
2659
|
put(rec) {
|
|
2559
|
-
|
|
2660
|
+
mkdirSync2(projDir(rec.project), { recursive: true });
|
|
2560
2661
|
const dest = taskFile(rec.project, rec.id);
|
|
2561
2662
|
const tmp = `${dest}.tmp`;
|
|
2562
|
-
|
|
2663
|
+
writeFileSync3(tmp, JSON.stringify(rec, null, 2));
|
|
2563
2664
|
renameSync(tmp, dest);
|
|
2564
2665
|
},
|
|
2565
2666
|
get(project, id) {
|
|
@@ -2567,7 +2668,7 @@ function createStore(root) {
|
|
|
2567
2668
|
if (!existsSync6(f))
|
|
2568
2669
|
return void 0;
|
|
2569
2670
|
try {
|
|
2570
|
-
return JSON.parse(
|
|
2671
|
+
return JSON.parse(readFileSync4(f, "utf-8"));
|
|
2571
2672
|
} catch {
|
|
2572
2673
|
return void 0;
|
|
2573
2674
|
}
|
|
@@ -2578,7 +2679,7 @@ function createStore(root) {
|
|
|
2578
2679
|
return [];
|
|
2579
2680
|
return readdirSync(d).filter((n) => n.endsWith(".json")).map((n) => {
|
|
2580
2681
|
try {
|
|
2581
|
-
return JSON.parse(
|
|
2682
|
+
return JSON.parse(readFileSync4(join6(d, n), "utf-8"));
|
|
2582
2683
|
} catch {
|
|
2583
2684
|
return void 0;
|
|
2584
2685
|
}
|
|
@@ -2616,7 +2717,7 @@ var init_store = __esm({
|
|
|
2616
2717
|
import { homedir as homedir4 } from "os";
|
|
2617
2718
|
import { join as join7, resolve as resolve2, sep as sep2 } from "path";
|
|
2618
2719
|
import { randomBytes } from "crypto";
|
|
2619
|
-
import { mkdirSync as
|
|
2720
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, renameSync as renameSync2, writeFileSync as writeFileSync4, existsSync as existsSync7, rmSync as rmSync4, statSync as statSync2 } from "fs";
|
|
2620
2721
|
function defaultWorkRoot() {
|
|
2621
2722
|
return join7(homedir4(), ".config", "squadrant", "work");
|
|
2622
2723
|
}
|
|
@@ -2644,10 +2745,10 @@ function createWorkStore(root = defaultWorkRoot()) {
|
|
|
2644
2745
|
const itemFile = (p, id) => assertUnderRoot(join7(projDir(p), `${safeSegment2("id", id)}.json`));
|
|
2645
2746
|
return {
|
|
2646
2747
|
put(item) {
|
|
2647
|
-
|
|
2748
|
+
mkdirSync3(projDir(item.project), { recursive: true });
|
|
2648
2749
|
const dest = itemFile(item.project, item.id);
|
|
2649
2750
|
const tmp = `${dest}.tmp`;
|
|
2650
|
-
|
|
2751
|
+
writeFileSync4(tmp, JSON.stringify(item, null, 2));
|
|
2651
2752
|
renameSync2(tmp, dest);
|
|
2652
2753
|
},
|
|
2653
2754
|
get(project, id) {
|
|
@@ -2655,7 +2756,7 @@ function createWorkStore(root = defaultWorkRoot()) {
|
|
|
2655
2756
|
if (!existsSync7(f))
|
|
2656
2757
|
return void 0;
|
|
2657
2758
|
try {
|
|
2658
|
-
return JSON.parse(
|
|
2759
|
+
return JSON.parse(readFileSync5(f, "utf-8"));
|
|
2659
2760
|
} catch {
|
|
2660
2761
|
return void 0;
|
|
2661
2762
|
}
|
|
@@ -2666,7 +2767,7 @@ function createWorkStore(root = defaultWorkRoot()) {
|
|
|
2666
2767
|
return [];
|
|
2667
2768
|
return readdirSync2(d).filter((n) => n.endsWith(".json") && !n.endsWith(".json.tmp")).map((n) => {
|
|
2668
2769
|
try {
|
|
2669
|
-
return JSON.parse(
|
|
2770
|
+
return JSON.parse(readFileSync5(join7(d, n), "utf-8"));
|
|
2670
2771
|
} catch {
|
|
2671
2772
|
return void 0;
|
|
2672
2773
|
}
|
|
@@ -2810,15 +2911,15 @@ var init_snapshot = __esm({
|
|
|
2810
2911
|
|
|
2811
2912
|
// packages/core/dist/launchd.js
|
|
2812
2913
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
2813
|
-
import { mkdirSync as
|
|
2914
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5, readFileSync as readFileSync6, existsSync as existsSync8, openSync, writeSync, closeSync, unlinkSync as unlinkSync2, constants } from "fs";
|
|
2814
2915
|
import { homedir as homedir5 } from "os";
|
|
2815
|
-
import { dirname as
|
|
2916
|
+
import { dirname as dirname2, join as join8 } from "path";
|
|
2816
2917
|
import { fileURLToPath } from "url";
|
|
2817
2918
|
function plistPath() {
|
|
2818
2919
|
return join8(homedir5(), "Library", "LaunchAgents", `${LABEL}.plist`);
|
|
2819
2920
|
}
|
|
2820
2921
|
function daemonEntryPath() {
|
|
2821
|
-
const p = join8(
|
|
2922
|
+
const p = join8(dirname2(fileURLToPath(import.meta.url)), "squadrantd.js");
|
|
2822
2923
|
if (!existsSync8(p)) {
|
|
2823
2924
|
throw new Error(`daemonEntryPath: compiled entry not found at '${p}'; run 'npm run build' \u2014 a src-tree or missing path in the launchd plist causes a MODULE_NOT_FOUND crash-loop (#259)`);
|
|
2824
2925
|
}
|
|
@@ -2827,10 +2928,28 @@ function daemonEntryPath() {
|
|
|
2827
2928
|
function xmlEscape(s) {
|
|
2828
2929
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
2829
2930
|
}
|
|
2830
|
-
function
|
|
2931
|
+
function xmlUnescape(s) {
|
|
2932
|
+
return s.replace(/"/g, '"').replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
2933
|
+
}
|
|
2934
|
+
function parseProgramArgs(plistXml) {
|
|
2935
|
+
const m = plistXml.match(/<key>ProgramArguments<\/key>\s*<array><string>([^<]*)<\/string><string>([^<]*)<\/string><\/array>/);
|
|
2936
|
+
if (!m)
|
|
2937
|
+
return null;
|
|
2938
|
+
return { nodeBin: xmlUnescape(m[1]), daemonEntry: xmlUnescape(m[2]) };
|
|
2939
|
+
}
|
|
2940
|
+
function detectForeignInstall(parsed, thisEntry, registeredEntryExists) {
|
|
2941
|
+
if (!parsed)
|
|
2942
|
+
return null;
|
|
2943
|
+
if (parsed.daemonEntry === thisEntry)
|
|
2944
|
+
return null;
|
|
2945
|
+
if (!registeredEntryExists)
|
|
2946
|
+
return null;
|
|
2947
|
+
return { registeredEntry: parsed.daemonEntry, thisEntry };
|
|
2948
|
+
}
|
|
2949
|
+
function sanitizePathForPlist(path35) {
|
|
2831
2950
|
const seen = /* @__PURE__ */ new Set();
|
|
2832
2951
|
const stable = [];
|
|
2833
|
-
for (const p of
|
|
2952
|
+
for (const p of path35.split(":")) {
|
|
2834
2953
|
if (!p)
|
|
2835
2954
|
continue;
|
|
2836
2955
|
if (p.includes("/.claude/plugins/"))
|
|
@@ -2849,7 +2968,7 @@ function resolveAgentBinDirs() {
|
|
|
2849
2968
|
const out = execFileSync3("which", [bin], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
|
|
2850
2969
|
const resolved = out.trim();
|
|
2851
2970
|
if (resolved)
|
|
2852
|
-
dirs.push(
|
|
2971
|
+
dirs.push(dirname2(resolved));
|
|
2853
2972
|
} catch {
|
|
2854
2973
|
}
|
|
2855
2974
|
}
|
|
@@ -2911,7 +3030,7 @@ function tryAcquireDaemonLock() {
|
|
|
2911
3030
|
const lp = daemonLockPath();
|
|
2912
3031
|
if (existsSync8(lp)) {
|
|
2913
3032
|
try {
|
|
2914
|
-
const pid = parseInt(
|
|
3033
|
+
const pid = parseInt(readFileSync6(lp, "utf-8").trim(), 10);
|
|
2915
3034
|
if (!Number.isFinite(pid) || pid <= 0) {
|
|
2916
3035
|
unlinkSync2(lp);
|
|
2917
3036
|
} else {
|
|
@@ -2948,17 +3067,19 @@ function computeDaemonDrift(nodeBin) {
|
|
|
2948
3067
|
const p = plistPath();
|
|
2949
3068
|
const entry = daemonEntryPath();
|
|
2950
3069
|
const desired = renderPlist(nodeBin, entry, buildDaemonPath(process.env.PATH ?? ""));
|
|
2951
|
-
const current = existsSync8(p) ?
|
|
3070
|
+
const current = existsSync8(p) ? readFileSync6(p, "utf-8") : null;
|
|
2952
3071
|
const uid = process.getuid?.() ?? 0;
|
|
2953
3072
|
const target = `gui/${uid}/${LABEL}`;
|
|
2954
3073
|
const changed = current !== desired;
|
|
2955
3074
|
const programChanged = current !== null && changed && !current.includes(programArgsBlock(nodeBin, entry));
|
|
2956
|
-
|
|
3075
|
+
const parsedCurrent = current !== null ? parseProgramArgs(current) : null;
|
|
3076
|
+
const foreignInstall = detectForeignInstall(parsedCurrent, entry, parsedCurrent !== null && existsSync8(parsedCurrent.daemonEntry));
|
|
3077
|
+
return { plistPath: p, target, desired, current, changed, programChanged, foreignInstall };
|
|
2957
3078
|
}
|
|
2958
3079
|
function applyDaemonDrift(drift) {
|
|
2959
3080
|
if (drift.changed) {
|
|
2960
|
-
|
|
2961
|
-
|
|
3081
|
+
mkdirSync4(dirname2(drift.plistPath), { recursive: true });
|
|
3082
|
+
writeFileSync5(drift.plistPath, drift.desired);
|
|
2962
3083
|
}
|
|
2963
3084
|
if (drift.programChanged) {
|
|
2964
3085
|
try {
|
|
@@ -2994,7 +3115,12 @@ function ensureDaemon(nodeBin = process.execPath, opts = {}) {
|
|
|
2994
3115
|
return;
|
|
2995
3116
|
}
|
|
2996
3117
|
try {
|
|
2997
|
-
|
|
3118
|
+
const drift = computeDaemonDrift(nodeBin);
|
|
3119
|
+
if (drift.foreignInstall) {
|
|
3120
|
+
process.stderr.write(printForeignInstallError(drift.foreignInstall));
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3123
|
+
applyDaemonDrift(drift);
|
|
2998
3124
|
} catch (e) {
|
|
2999
3125
|
process.stderr.write(`[squadrant] warn: ensureDaemon failed (${e instanceof Error ? e.message : e})
|
|
3000
3126
|
`);
|
|
@@ -3002,6 +3128,13 @@ function ensureDaemon(nodeBin = process.execPath, opts = {}) {
|
|
|
3002
3128
|
releaseDaemonLock();
|
|
3003
3129
|
}
|
|
3004
3130
|
}
|
|
3131
|
+
function printForeignInstallError(foreign) {
|
|
3132
|
+
return `[squadrant] refusing to restart the daemon: the registered launchd config belongs to a DIFFERENT squadrant install than this one.
|
|
3133
|
+
registered install: ${foreign.registeredEntry}
|
|
3134
|
+
this install: ${foreign.thisEntry}
|
|
3135
|
+
Two squadrant installs on this machine will keep fighting over the daemon (#670). Uninstall the one you don't use, then run \`squadrant heal daemon\` to reconcile.
|
|
3136
|
+
`;
|
|
3137
|
+
}
|
|
3005
3138
|
function reregisterDaemon(nodeBin = process.execPath) {
|
|
3006
3139
|
if (!tryAcquireDaemonLock())
|
|
3007
3140
|
return;
|
|
@@ -3165,7 +3298,7 @@ var init_gate = __esm({
|
|
|
3165
3298
|
});
|
|
3166
3299
|
|
|
3167
3300
|
// packages/core/dist/daemon/liveness-registry.js
|
|
3168
|
-
import { writeFileSync as
|
|
3301
|
+
import { writeFileSync as writeFileSync6, readFileSync as readFileSync7, renameSync as renameSync3 } from "fs";
|
|
3169
3302
|
var LivenessRegistry;
|
|
3170
3303
|
var init_liveness_registry = __esm({
|
|
3171
3304
|
"packages/core/dist/daemon/liveness-registry.js"() {
|
|
@@ -3179,13 +3312,13 @@ var init_liveness_registry = __esm({
|
|
|
3179
3312
|
this.path = opts.path;
|
|
3180
3313
|
this.readFile = opts.readFile ?? ((p) => {
|
|
3181
3314
|
try {
|
|
3182
|
-
return
|
|
3315
|
+
return readFileSync7(p, "utf-8");
|
|
3183
3316
|
} catch {
|
|
3184
3317
|
return void 0;
|
|
3185
3318
|
}
|
|
3186
3319
|
});
|
|
3187
3320
|
this.writeFile = opts.writeFile ?? ((p, c) => {
|
|
3188
|
-
|
|
3321
|
+
writeFileSync6(`${p}.tmp`, c);
|
|
3189
3322
|
renameSync3(`${p}.tmp`, p);
|
|
3190
3323
|
});
|
|
3191
3324
|
}
|
|
@@ -3238,7 +3371,7 @@ var init_liveness_registry = __esm({
|
|
|
3238
3371
|
import { homedir as homedir6 } from "os";
|
|
3239
3372
|
import { join as join9 } from "path";
|
|
3240
3373
|
import { spawn as realSpawn } from "child_process";
|
|
3241
|
-
import { writeFileSync as
|
|
3374
|
+
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync5 } from "fs";
|
|
3242
3375
|
function defaultIsPidAlive(pid) {
|
|
3243
3376
|
try {
|
|
3244
3377
|
process.kill(pid, 0);
|
|
@@ -3258,10 +3391,10 @@ function buildContext(opts) {
|
|
|
3258
3391
|
const isPidAlive = opts.isPidAlive ?? defaultIsPidAlive;
|
|
3259
3392
|
const spawn2 = opts.spawn ?? realSpawn;
|
|
3260
3393
|
const resultsDir = join9(stateRoot, "_results");
|
|
3261
|
-
|
|
3394
|
+
mkdirSync5(resultsDir, { recursive: true });
|
|
3262
3395
|
const writeResult = (id, payload) => {
|
|
3263
3396
|
const p = join9(resultsDir, `${id}.txt`);
|
|
3264
|
-
|
|
3397
|
+
writeFileSync7(p, payload);
|
|
3265
3398
|
return p;
|
|
3266
3399
|
};
|
|
3267
3400
|
const log = (m) => process.stderr.write(`[squadrantd] ${(/* @__PURE__ */ new Date()).toISOString()} ${m}
|
|
@@ -4007,7 +4140,7 @@ var init_server = __esm({
|
|
|
4007
4140
|
// packages/core/dist/daemon/snapshot-gather.js
|
|
4008
4141
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4009
4142
|
import { join as join10 } from "path";
|
|
4010
|
-
import { statSync as statSync3, openSync as openSync2, readSync, closeSync as closeSync2, readdirSync as readdirSync3, readFileSync as
|
|
4143
|
+
import { statSync as statSync3, openSync as openSync2, readSync, closeSync as closeSync2, readdirSync as readdirSync3, readFileSync as readFileSync8 } from "fs";
|
|
4011
4144
|
function distBuiltAt() {
|
|
4012
4145
|
try {
|
|
4013
4146
|
return statSync3(SELF_PATH).mtimeMs;
|
|
@@ -4015,10 +4148,10 @@ function distBuiltAt() {
|
|
|
4015
4148
|
return 0;
|
|
4016
4149
|
}
|
|
4017
4150
|
}
|
|
4018
|
-
function gatherLogStats(
|
|
4151
|
+
function gatherLogStats(path35, now, windowMs) {
|
|
4019
4152
|
let sizeBytes = 0;
|
|
4020
4153
|
try {
|
|
4021
|
-
sizeBytes = statSync3(
|
|
4154
|
+
sizeBytes = statSync3(path35).size;
|
|
4022
4155
|
} catch {
|
|
4023
4156
|
return { errorCount: 0, sizeBytes: 0, windowMs };
|
|
4024
4157
|
}
|
|
@@ -4029,7 +4162,7 @@ function gatherLogStats(path34, now, windowMs) {
|
|
|
4029
4162
|
const len = sizeBytes - start;
|
|
4030
4163
|
let text = "";
|
|
4031
4164
|
try {
|
|
4032
|
-
const fd = openSync2(
|
|
4165
|
+
const fd = openSync2(path35, "r");
|
|
4033
4166
|
try {
|
|
4034
4167
|
const buf = Buffer.alloc(len);
|
|
4035
4168
|
readSync(fd, buf, 0, len, start);
|
|
@@ -4070,7 +4203,7 @@ function gatherStoreStats(store, stateRoot, project) {
|
|
|
4070
4203
|
if (!n.endsWith(".json"))
|
|
4071
4204
|
continue;
|
|
4072
4205
|
try {
|
|
4073
|
-
JSON.parse(
|
|
4206
|
+
JSON.parse(readFileSync8(join10(dir, n), "utf-8"));
|
|
4074
4207
|
} catch {
|
|
4075
4208
|
corruptCount++;
|
|
4076
4209
|
}
|
|
@@ -4105,7 +4238,7 @@ var init_snapshot_gather = __esm({
|
|
|
4105
4238
|
});
|
|
4106
4239
|
|
|
4107
4240
|
// packages/core/dist/daemon/start.js
|
|
4108
|
-
import { join as join11, dirname as
|
|
4241
|
+
import { join as join11, dirname as dirname3 } from "path";
|
|
4109
4242
|
import { readdir } from "fs/promises";
|
|
4110
4243
|
function startDaemon(ctx, opts, pkgVersion) {
|
|
4111
4244
|
const { stateRoot, store, log, isPidAlive, resultsDir, taskTimeoutMs, inFlightHeadlessIds, activeHeadlessKills, broadcast, cancelPromotionsFor } = ctx;
|
|
@@ -4181,7 +4314,7 @@ function startDaemon(ctx, opts, pkgVersion) {
|
|
|
4181
4314
|
return out;
|
|
4182
4315
|
}
|
|
4183
4316
|
async function gatherSnapshotInputs(now) {
|
|
4184
|
-
const logPath2 = join11(
|
|
4317
|
+
const logPath2 = join11(dirname3(stateRoot), "squadrantd.log");
|
|
4185
4318
|
const tier2Projects = opts.registeredProjects ?? Object.keys(loadConfig().projects);
|
|
4186
4319
|
const projects = await Promise.all(tier2Projects.map(async (project) => {
|
|
4187
4320
|
const cursor = await readCursor({ stateRoot, project, subscriber: CURSOR_SUBSCRIBER2 });
|
|
@@ -4386,35 +4519,33 @@ var init_start = __esm({
|
|
|
4386
4519
|
|
|
4387
4520
|
// packages/core/dist/session-freshness.js
|
|
4388
4521
|
import crypto from "crypto";
|
|
4389
|
-
import
|
|
4390
|
-
import
|
|
4522
|
+
import fs9 from "fs";
|
|
4523
|
+
import path9 from "path";
|
|
4391
4524
|
function loadSessions(sessionsPath) {
|
|
4392
4525
|
try {
|
|
4393
|
-
return JSON.parse(
|
|
4526
|
+
return JSON.parse(readConfigFileSync(sessionsPath));
|
|
4394
4527
|
} catch {
|
|
4395
4528
|
return { workspaces: {} };
|
|
4396
4529
|
}
|
|
4397
4530
|
}
|
|
4398
4531
|
function saveSessions(sessionsPath, sessions) {
|
|
4399
|
-
|
|
4400
|
-
fs10.mkdirSync(dir, { recursive: true });
|
|
4401
|
-
fs10.writeFileSync(sessionsPath, JSON.stringify(sessions, null, 2) + "\n");
|
|
4532
|
+
writeConfigFileSync(sessionsPath, JSON.stringify(sessions, null, 2) + "\n");
|
|
4402
4533
|
}
|
|
4403
4534
|
function computeTemplateHash(role, templatesDir) {
|
|
4404
4535
|
const hash = crypto.createHash("sha256");
|
|
4405
|
-
const roleFile =
|
|
4406
|
-
const legacyRoleFile =
|
|
4407
|
-
if (
|
|
4408
|
-
hash.update(
|
|
4409
|
-
} else if (
|
|
4410
|
-
hash.update(
|
|
4536
|
+
const roleFile = path9.join(templatesDir, `${role}.claude.md`);
|
|
4537
|
+
const legacyRoleFile = path9.join(templatesDir, `${role}.CLAUDE.md`);
|
|
4538
|
+
if (fs9.existsSync(roleFile)) {
|
|
4539
|
+
hash.update(fs9.readFileSync(roleFile, "utf-8"));
|
|
4540
|
+
} else if (fs9.existsSync(legacyRoleFile)) {
|
|
4541
|
+
hash.update(fs9.readFileSync(legacyRoleFile, "utf-8"));
|
|
4411
4542
|
}
|
|
4412
|
-
const pluginSkillsDir =
|
|
4413
|
-
if (
|
|
4414
|
-
for (const skill of
|
|
4415
|
-
const skillFile =
|
|
4416
|
-
if (
|
|
4417
|
-
hash.update(
|
|
4543
|
+
const pluginSkillsDir = path9.join(templatesDir, "..", "plugin", "skills");
|
|
4544
|
+
if (fs9.existsSync(pluginSkillsDir)) {
|
|
4545
|
+
for (const skill of fs9.readdirSync(pluginSkillsDir).sort()) {
|
|
4546
|
+
const skillFile = path9.join(pluginSkillsDir, skill, "SKILL.md");
|
|
4547
|
+
if (fs9.existsSync(skillFile)) {
|
|
4548
|
+
hash.update(fs9.readFileSync(skillFile, "utf-8"));
|
|
4418
4549
|
}
|
|
4419
4550
|
}
|
|
4420
4551
|
}
|
|
@@ -4446,6 +4577,7 @@ function recordSession(workspaceName, role, opts) {
|
|
|
4446
4577
|
}
|
|
4447
4578
|
var init_session_freshness = __esm({
|
|
4448
4579
|
"packages/core/dist/session-freshness.js"() {
|
|
4580
|
+
init_dist();
|
|
4449
4581
|
}
|
|
4450
4582
|
});
|
|
4451
4583
|
|
|
@@ -4835,17 +4967,16 @@ var init_format = __esm({
|
|
|
4835
4967
|
});
|
|
4836
4968
|
|
|
4837
4969
|
// packages/core/dist/telegram/state.js
|
|
4838
|
-
import
|
|
4839
|
-
import path9 from "path";
|
|
4970
|
+
import path10 from "path";
|
|
4840
4971
|
function statePath(stateRoot) {
|
|
4841
|
-
return
|
|
4972
|
+
return path10.join(stateRoot, "telegram-state.json");
|
|
4842
4973
|
}
|
|
4843
4974
|
function topicKey(project, scope = "project") {
|
|
4844
4975
|
return `${project}::${scope}`;
|
|
4845
4976
|
}
|
|
4846
4977
|
function loadState(stateRoot) {
|
|
4847
4978
|
try {
|
|
4848
|
-
const raw =
|
|
4979
|
+
const raw = readConfigFileSync(statePath(stateRoot));
|
|
4849
4980
|
const data = JSON.parse(raw);
|
|
4850
4981
|
const result = {
|
|
4851
4982
|
offset: typeof data.offset === "number" ? data.offset : 0,
|
|
@@ -4860,8 +4991,7 @@ function loadState(stateRoot) {
|
|
|
4860
4991
|
}
|
|
4861
4992
|
}
|
|
4862
4993
|
function saveState(stateRoot, s) {
|
|
4863
|
-
|
|
4864
|
-
fs11.writeFileSync(statePath(stateRoot), JSON.stringify(s, null, 2) + "\n");
|
|
4994
|
+
writeConfigFileSync(statePath(stateRoot), JSON.stringify(s, null, 2) + "\n");
|
|
4865
4995
|
}
|
|
4866
4996
|
function setTopic(stateRoot, project, topicId, scope = "project") {
|
|
4867
4997
|
const s = loadState(stateRoot);
|
|
@@ -4895,6 +5025,7 @@ function findProjectByThread(stateRoot, threadId) {
|
|
|
4895
5025
|
}
|
|
4896
5026
|
var init_state = __esm({
|
|
4897
5027
|
"packages/core/dist/telegram/state.js"() {
|
|
5028
|
+
init_dist();
|
|
4898
5029
|
}
|
|
4899
5030
|
});
|
|
4900
5031
|
|
|
@@ -5046,7 +5177,7 @@ var init_tiers = __esm({
|
|
|
5046
5177
|
|
|
5047
5178
|
// packages/core/dist/telegram/bridge.js
|
|
5048
5179
|
import os4 from "os";
|
|
5049
|
-
import
|
|
5180
|
+
import path11 from "path";
|
|
5050
5181
|
function parseNotifyPref(text) {
|
|
5051
5182
|
const parts = text.trim().split(/\s+/);
|
|
5052
5183
|
if (stripBotMention(parts[0] ?? "").toLowerCase() !== "/notify")
|
|
@@ -5073,7 +5204,7 @@ function notifyToggle(text) {
|
|
|
5073
5204
|
}
|
|
5074
5205
|
function createTelegramBridge(opts) {
|
|
5075
5206
|
const { cfg, stateRoot, client, appendCaptainMessage: appendCaptainMessage2, log, ensureCaptainAlive, runCommand, sendReply } = opts;
|
|
5076
|
-
const configRoot = opts.configRoot ??
|
|
5207
|
+
const configRoot = opts.configRoot ?? path11.join(os4.homedir(), ".config", "squadrant");
|
|
5077
5208
|
const pollMs = cfg.pollMs ?? 1e3;
|
|
5078
5209
|
let running = false;
|
|
5079
5210
|
let lastSuccessfulPollAt = null;
|
|
@@ -5204,14 +5335,14 @@ function createTelegramBridge(opts) {
|
|
|
5204
5335
|
}
|
|
5205
5336
|
function currentEffort() {
|
|
5206
5337
|
try {
|
|
5207
|
-
return loadConfig(
|
|
5338
|
+
return loadConfig(path11.join(configRoot, "config.json")).defaults.effort ?? "balance";
|
|
5208
5339
|
} catch {
|
|
5209
5340
|
return "balance";
|
|
5210
5341
|
}
|
|
5211
5342
|
}
|
|
5212
5343
|
function projectNames() {
|
|
5213
5344
|
try {
|
|
5214
|
-
return Object.keys(loadConfig(
|
|
5345
|
+
return Object.keys(loadConfig(path11.join(configRoot, "config.json")).projects);
|
|
5215
5346
|
} catch {
|
|
5216
5347
|
return [];
|
|
5217
5348
|
}
|
|
@@ -5479,7 +5610,7 @@ var init_restart_daemon = __esm({
|
|
|
5479
5610
|
});
|
|
5480
5611
|
|
|
5481
5612
|
// packages/core/dist/telegram/setup.js
|
|
5482
|
-
import
|
|
5613
|
+
import fs10 from "fs";
|
|
5483
5614
|
function resolveSetupGroup(existingSupergroupId, opts) {
|
|
5484
5615
|
if (existingSupergroupId !== void 0 && !opts.redetect)
|
|
5485
5616
|
return "reuse";
|
|
@@ -5530,7 +5661,7 @@ function writeTelegramConfig(configPath, opts) {
|
|
|
5530
5661
|
let config;
|
|
5531
5662
|
let raw = null;
|
|
5532
5663
|
try {
|
|
5533
|
-
raw =
|
|
5664
|
+
raw = fs10.readFileSync(configPath, "utf-8");
|
|
5534
5665
|
} catch (err) {
|
|
5535
5666
|
if (err.code !== "ENOENT") {
|
|
5536
5667
|
throw new Error(`refusing to overwrite unreadable config at ${configPath}: ${String(err)}`);
|
|
@@ -5558,10 +5689,11 @@ function writeTelegramConfig(configPath, opts) {
|
|
|
5558
5689
|
if (remoteControl !== void 0)
|
|
5559
5690
|
next.remoteControl = remoteControl;
|
|
5560
5691
|
config.telegram = next;
|
|
5561
|
-
|
|
5692
|
+
writeConfigFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
5562
5693
|
}
|
|
5563
5694
|
var init_setup = __esm({
|
|
5564
5695
|
"packages/core/dist/telegram/setup.js"() {
|
|
5696
|
+
init_dist();
|
|
5565
5697
|
init_state();
|
|
5566
5698
|
init_bot_commands();
|
|
5567
5699
|
init_restart_daemon();
|
|
@@ -5887,7 +6019,7 @@ var init_launch_workspace = __esm({
|
|
|
5887
6019
|
});
|
|
5888
6020
|
|
|
5889
6021
|
// packages/core/dist/side-session.js
|
|
5890
|
-
import
|
|
6022
|
+
import fs11 from "fs";
|
|
5891
6023
|
function sideTitleFor(project, name) {
|
|
5892
6024
|
return `\u{1F5D2} ${project}:${name}`;
|
|
5893
6025
|
}
|
|
@@ -5989,7 +6121,7 @@ async function runSideClose(runtime, workspaceId, project, name, projPath, workt
|
|
|
5989
6121
|
await runtime.closePane(pane);
|
|
5990
6122
|
if (projPath) {
|
|
5991
6123
|
const wtPath = worktreePath(projPath, worktreeDir, project, name);
|
|
5992
|
-
if (
|
|
6124
|
+
if (fs11.existsSync(wtPath)) {
|
|
5993
6125
|
try {
|
|
5994
6126
|
removeWorktree(projPath, wtPath);
|
|
5995
6127
|
} catch (e) {
|
|
@@ -6009,9 +6141,9 @@ var init_side_session = __esm({
|
|
|
6009
6141
|
});
|
|
6010
6142
|
|
|
6011
6143
|
// packages/core/dist/crew-spawn.js
|
|
6012
|
-
import
|
|
6144
|
+
import fs12 from "fs";
|
|
6013
6145
|
import os5 from "os";
|
|
6014
|
-
import
|
|
6146
|
+
import path12 from "path";
|
|
6015
6147
|
async function listCrewPanes(runtime, workspaceId, project) {
|
|
6016
6148
|
const surfaces = await runtime.listSurfaces(workspaceId);
|
|
6017
6149
|
return surfaces.filter((s) => s.title && isCrewTitle(project, s.title));
|
|
@@ -6080,9 +6212,9 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
6080
6212
|
}) : proj.path;
|
|
6081
6213
|
let firstTurnTask = input.task;
|
|
6082
6214
|
if (input.taskFile && input.taskFile !== "-" && !input.shared) {
|
|
6083
|
-
const absTaskFile =
|
|
6084
|
-
const basename =
|
|
6085
|
-
|
|
6215
|
+
const absTaskFile = path12.resolve(input.taskFile);
|
|
6216
|
+
const basename = path12.basename(absTaskFile);
|
|
6217
|
+
fs12.copyFileSync(absTaskFile, path12.join(spawnCwd, basename));
|
|
6086
6218
|
firstTurnTask = `Read ./${basename} to get your task brief, then execute it.`;
|
|
6087
6219
|
}
|
|
6088
6220
|
const route = !input.agentExplicit && !input.model ? resolveCrewRoute(input.task, config) : null;
|
|
@@ -6095,8 +6227,8 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
6095
6227
|
throw new Error(`Unknown agent '${agentName}'. Known: claude, codex, gemini, opencode.`);
|
|
6096
6228
|
}
|
|
6097
6229
|
if (agentName === "codex") {
|
|
6098
|
-
const codexRoleFile =
|
|
6099
|
-
const roleInstructions =
|
|
6230
|
+
const codexRoleFile = path12.join(TEMPLATES_DIR, `crew.${agent.templateSuffix}.md`);
|
|
6231
|
+
const roleInstructions = fs12.existsSync(codexRoleFile) ? fs12.readFileSync(codexRoleFile, "utf8") : void 0;
|
|
6100
6232
|
return runCodexInteractiveSpawn({
|
|
6101
6233
|
project: input.project,
|
|
6102
6234
|
task: input.task,
|
|
@@ -6112,7 +6244,7 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
6112
6244
|
sendCodexFirstTurn: deps.sendCodexFirstTurn
|
|
6113
6245
|
});
|
|
6114
6246
|
}
|
|
6115
|
-
const promptFile =
|
|
6247
|
+
const promptFile = path12.join(TEMPLATES_DIR, `crew.${agent.templateSuffix}.md`);
|
|
6116
6248
|
const interactive = agent.name === "claude" || agent.name === "opencode";
|
|
6117
6249
|
const crewRole = config.defaults.roles?.crew;
|
|
6118
6250
|
const configModel = crewRole && crewRole.agent === agent.name ? crewRole.model : void 0;
|
|
@@ -6294,7 +6426,7 @@ function buildRecoveryHint(sessId, provider, worktreeCwd) {
|
|
|
6294
6426
|
return "";
|
|
6295
6427
|
if (provider === "claude") {
|
|
6296
6428
|
const escaped = worktreeCwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
6297
|
-
const transcriptPath =
|
|
6429
|
+
const transcriptPath = path12.join(os5.homedir(), ".claude", "projects", escaped, `${sessId}.jsonl`);
|
|
6298
6430
|
return `
|
|
6299
6431
|
transcript: ${transcriptPath}
|
|
6300
6432
|
resume: claude --resume ${sessId} (run from the worktree path above)
|
|
@@ -6390,8 +6522,8 @@ var init_crew_spawn = __esm({
|
|
|
6390
6522
|
init_crew_routing();
|
|
6391
6523
|
init_crew_protocol();
|
|
6392
6524
|
init_crew_lifecycle();
|
|
6393
|
-
TEMPLATES_DIR =
|
|
6394
|
-
STATE_ROOT =
|
|
6525
|
+
TEMPLATES_DIR = path12.join(os5.homedir(), ".config", "squadrant", "templates");
|
|
6526
|
+
STATE_ROOT = path12.join(os5.homedir(), ".config", "squadrant", "state");
|
|
6395
6527
|
CLOSE_LOOKUP_RETRIES = 3;
|
|
6396
6528
|
CLOSE_LOOKUP_RETRY_DELAY_MS = 150;
|
|
6397
6529
|
}
|
|
@@ -6489,6 +6621,7 @@ __export(dist_exports2, {
|
|
|
6489
6621
|
deliverStartupPrompt: () => deliverStartupPrompt,
|
|
6490
6622
|
deliverable: () => deliverable,
|
|
6491
6623
|
deriveCaptainState: () => deriveCaptainState,
|
|
6624
|
+
detectForeignInstall: () => detectForeignInstall,
|
|
6492
6625
|
detectGroupAndUser: () => detectGroupAndUser,
|
|
6493
6626
|
detectGroupId: () => detectGroupId,
|
|
6494
6627
|
discoverCaptainSurface: () => discoverCaptainSurface,
|
|
@@ -6528,7 +6661,9 @@ __export(dist_exports2, {
|
|
|
6528
6661
|
notifyToggle: () => notifyToggle,
|
|
6529
6662
|
parseCommand: () => parseCommand,
|
|
6530
6663
|
parseNotifyPref: () => parseNotifyPref,
|
|
6664
|
+
parseProgramArgs: () => parseProgramArgs,
|
|
6531
6665
|
plistPath: () => plistPath,
|
|
6666
|
+
printForeignInstallError: () => printForeignInstallError,
|
|
6532
6667
|
programArgsBlock: () => programArgsBlock,
|
|
6533
6668
|
projectHealth: () => projectHealth,
|
|
6534
6669
|
purgeExpiredWorkItems: () => purgeExpiredWorkItems,
|
|
@@ -7280,13 +7415,13 @@ var init_notifiers = __esm({
|
|
|
7280
7415
|
});
|
|
7281
7416
|
|
|
7282
7417
|
// packages/workspaces/dist/workspaces/obsidian.js
|
|
7283
|
-
import
|
|
7418
|
+
import fs13 from "fs/promises";
|
|
7284
7419
|
import { existsSync as existsSync10 } from "fs";
|
|
7285
|
-
import
|
|
7420
|
+
import path13 from "path";
|
|
7286
7421
|
function resolveInRoot(root, relative) {
|
|
7287
|
-
const joined =
|
|
7288
|
-
const normalized =
|
|
7289
|
-
if (joined !==
|
|
7422
|
+
const joined = path13.resolve(root, relative);
|
|
7423
|
+
const normalized = path13.resolve(root) + path13.sep;
|
|
7424
|
+
if (joined !== path13.resolve(root) && !joined.startsWith(normalized)) {
|
|
7290
7425
|
throw new Error(`Path '${relative}' escapes workspace root`);
|
|
7291
7426
|
}
|
|
7292
7427
|
return joined;
|
|
@@ -7305,16 +7440,16 @@ function createObsidianDriver(scope) {
|
|
|
7305
7440
|
};
|
|
7306
7441
|
},
|
|
7307
7442
|
async read(rel) {
|
|
7308
|
-
return
|
|
7443
|
+
return fs13.readFile(resolveInRoot(root, rel), "utf-8");
|
|
7309
7444
|
},
|
|
7310
7445
|
async write(rel, content) {
|
|
7311
7446
|
const abs = resolveInRoot(root, rel);
|
|
7312
|
-
await
|
|
7313
|
-
await
|
|
7447
|
+
await fs13.mkdir(path13.dirname(abs), { recursive: true });
|
|
7448
|
+
await fs13.writeFile(abs, content);
|
|
7314
7449
|
},
|
|
7315
7450
|
async exists(rel) {
|
|
7316
7451
|
try {
|
|
7317
|
-
await
|
|
7452
|
+
await fs13.access(resolveInRoot(root, rel));
|
|
7318
7453
|
return true;
|
|
7319
7454
|
} catch {
|
|
7320
7455
|
return false;
|
|
@@ -7322,13 +7457,13 @@ function createObsidianDriver(scope) {
|
|
|
7322
7457
|
},
|
|
7323
7458
|
async list(rel) {
|
|
7324
7459
|
try {
|
|
7325
|
-
return await
|
|
7460
|
+
return await fs13.readdir(resolveInRoot(root, rel));
|
|
7326
7461
|
} catch {
|
|
7327
7462
|
return [];
|
|
7328
7463
|
}
|
|
7329
7464
|
},
|
|
7330
7465
|
async mkdir(rel) {
|
|
7331
|
-
await
|
|
7466
|
+
await fs13.mkdir(resolveInRoot(root, rel), { recursive: true });
|
|
7332
7467
|
}
|
|
7333
7468
|
};
|
|
7334
7469
|
}
|
|
@@ -7592,7 +7727,7 @@ var init_store_fingerprint = __esm({
|
|
|
7592
7727
|
});
|
|
7593
7728
|
|
|
7594
7729
|
// packages/workspaces/dist/cmux-daemon/daemon-cmux.js
|
|
7595
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
7730
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync9 } from "fs";
|
|
7596
7731
|
import { join as join14 } from "path";
|
|
7597
7732
|
import { homedir as homedir9 } from "os";
|
|
7598
7733
|
var DaemonCmux;
|
|
@@ -7665,7 +7800,7 @@ var init_daemon_cmux = __esm({
|
|
|
7665
7800
|
} catch (e) {
|
|
7666
7801
|
throw new Error(`liveness: could not read cmux state dir ${dir}: ${e.message}`);
|
|
7667
7802
|
}
|
|
7668
|
-
return readLivenessSnapshot(files, (f) =>
|
|
7803
|
+
return readLivenessSnapshot(files, (f) => readFileSync9(join14(dir, f), "utf-8"), projects);
|
|
7669
7804
|
}
|
|
7670
7805
|
};
|
|
7671
7806
|
}
|
|
@@ -7674,7 +7809,7 @@ var init_daemon_cmux = __esm({
|
|
|
7674
7809
|
// packages/workspaces/dist/cmux-daemon/cmux-store-source.js
|
|
7675
7810
|
import { join as join15 } from "path";
|
|
7676
7811
|
import { homedir as homedir10 } from "os";
|
|
7677
|
-
import { watch, readdirSync as readdirSync5, readFileSync as
|
|
7812
|
+
import { watch, readdirSync as readdirSync5, readFileSync as readFileSync10, existsSync as existsSync11 } from "fs";
|
|
7678
7813
|
function parseLifecycleState(s) {
|
|
7679
7814
|
if (s === "running" || s === "idle" || s === "needsInput" || s === "unknown") {
|
|
7680
7815
|
return s;
|
|
@@ -7696,9 +7831,9 @@ function defaultListFiles(dir) {
|
|
|
7696
7831
|
return [];
|
|
7697
7832
|
}
|
|
7698
7833
|
}
|
|
7699
|
-
function defaultReadFile(
|
|
7834
|
+
function defaultReadFile(path35) {
|
|
7700
7835
|
try {
|
|
7701
|
-
return
|
|
7836
|
+
return readFileSync10(path35, "utf-8");
|
|
7702
7837
|
} catch {
|
|
7703
7838
|
return void 0;
|
|
7704
7839
|
}
|
|
@@ -7852,7 +7987,7 @@ var init_cmux_store_source = __esm({
|
|
|
7852
7987
|
// packages/workspaces/dist/native-hooks/native-hook-source.js
|
|
7853
7988
|
import { join as join16 } from "path";
|
|
7854
7989
|
import { homedir as homedir11 } from "os";
|
|
7855
|
-
import { mkdirSync as
|
|
7990
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
|
|
7856
7991
|
function installClaudeHooks(opts = {}) {
|
|
7857
7992
|
const settingsPath = opts.settingsPath ?? join16(homedir11(), ".claude", "settings.json");
|
|
7858
7993
|
const hookCmd = opts.hookCmd ?? DEFAULT_HOOK_CMD;
|
|
@@ -7948,16 +8083,16 @@ function extractDetail(sub, payload) {
|
|
|
7948
8083
|
}
|
|
7949
8084
|
return void 0;
|
|
7950
8085
|
}
|
|
7951
|
-
function defaultReadFile2(
|
|
8086
|
+
function defaultReadFile2(path35) {
|
|
7952
8087
|
try {
|
|
7953
|
-
return
|
|
8088
|
+
return readFileSync11(path35, "utf-8");
|
|
7954
8089
|
} catch {
|
|
7955
8090
|
return void 0;
|
|
7956
8091
|
}
|
|
7957
8092
|
}
|
|
7958
|
-
function defaultWriteFile(
|
|
7959
|
-
|
|
7960
|
-
|
|
8093
|
+
function defaultWriteFile(path35, content) {
|
|
8094
|
+
mkdirSync6(path35.replace(/\/[^/]+$/, ""), { recursive: true });
|
|
8095
|
+
writeFileSync8(path35, content, "utf-8");
|
|
7961
8096
|
}
|
|
7962
8097
|
var CLAUDE_HOOK_EVENTS, DEFAULT_HOOK_CMD, NativeHookSource;
|
|
7963
8098
|
var init_native_hook_source = __esm({
|
|
@@ -8576,8 +8711,8 @@ var init_registry4 = __esm({
|
|
|
8576
8711
|
});
|
|
8577
8712
|
|
|
8578
8713
|
// packages/agents/dist/drivers/launch-cmd.js
|
|
8579
|
-
import
|
|
8580
|
-
import
|
|
8714
|
+
import fs14 from "fs";
|
|
8715
|
+
import path14 from "path";
|
|
8581
8716
|
function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model, templatesDir) {
|
|
8582
8717
|
const driver = registry.getDriver(agentName);
|
|
8583
8718
|
if (driver.name === "claude") {
|
|
@@ -8593,27 +8728,27 @@ function buildAgentCmd(agentName, registry, role, fresh, permissionMode, model,
|
|
|
8593
8728
|
cmd += ` --model ${model}`;
|
|
8594
8729
|
}
|
|
8595
8730
|
if (templatesDir) {
|
|
8596
|
-
const roleFile2 =
|
|
8597
|
-
const legacyRoleFile =
|
|
8598
|
-
const actualRoleFile =
|
|
8731
|
+
const roleFile2 = path14.join(templatesDir, `${role}.claude.md`);
|
|
8732
|
+
const legacyRoleFile = path14.join(templatesDir, `${role}.CLAUDE.md`);
|
|
8733
|
+
const actualRoleFile = fs14.existsSync(roleFile2) ? roleFile2 : fs14.existsSync(legacyRoleFile) ? legacyRoleFile : null;
|
|
8599
8734
|
if (actualRoleFile) {
|
|
8600
8735
|
cmd += ` --append-system-prompt-file ${actualRoleFile}`;
|
|
8601
8736
|
}
|
|
8602
|
-
const pluginDir =
|
|
8603
|
-
if (
|
|
8737
|
+
const pluginDir = path14.join(templatesDir, "..", "plugin");
|
|
8738
|
+
if (fs14.existsSync(pluginDir)) {
|
|
8604
8739
|
cmd += ` --plugin-dir ${pluginDir}`;
|
|
8605
8740
|
}
|
|
8606
8741
|
}
|
|
8607
8742
|
return cmd;
|
|
8608
8743
|
}
|
|
8609
|
-
const roleFile = templatesDir ?
|
|
8744
|
+
const roleFile = templatesDir ? path14.join(templatesDir, `${role}.${driver.templateSuffix}.md`) : void 0;
|
|
8610
8745
|
return driver.buildCommand({
|
|
8611
8746
|
prompt: `You are a squadrant ${role}. Read your instructions from ${roleFile ?? role} and begin.`,
|
|
8612
8747
|
workdir: process.cwd(),
|
|
8613
8748
|
role,
|
|
8614
8749
|
model,
|
|
8615
8750
|
autoApprove: true,
|
|
8616
|
-
promptFile: roleFile &&
|
|
8751
|
+
promptFile: roleFile && fs14.existsSync(roleFile) ? roleFile : void 0
|
|
8617
8752
|
});
|
|
8618
8753
|
}
|
|
8619
8754
|
var init_launch_cmd = __esm({
|
|
@@ -8636,7 +8771,7 @@ var init_drivers = __esm({
|
|
|
8636
8771
|
|
|
8637
8772
|
// packages/agents/dist/projection/cursor.js
|
|
8638
8773
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
8639
|
-
import
|
|
8774
|
+
import path15 from "path";
|
|
8640
8775
|
import os6 from "os";
|
|
8641
8776
|
function renderMdc(source) {
|
|
8642
8777
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
@@ -8685,7 +8820,7 @@ function createCursorEmitter() {
|
|
|
8685
8820
|
if (scope === "user") {
|
|
8686
8821
|
return [
|
|
8687
8822
|
{
|
|
8688
|
-
path:
|
|
8823
|
+
path: path15.join(os6.homedir(), ".cursor/rules/squadrant-global.mdc"),
|
|
8689
8824
|
shared: false,
|
|
8690
8825
|
format: "mdc"
|
|
8691
8826
|
}
|
|
@@ -8695,7 +8830,7 @@ function createCursorEmitter() {
|
|
|
8695
8830
|
return [];
|
|
8696
8831
|
return [
|
|
8697
8832
|
{
|
|
8698
|
-
path:
|
|
8833
|
+
path: path15.join(projectRoot, ".cursor/rules/squadrant.mdc"),
|
|
8699
8834
|
shared: false,
|
|
8700
8835
|
format: "mdc"
|
|
8701
8836
|
}
|
|
@@ -8712,7 +8847,7 @@ function createCursorEmitter() {
|
|
|
8712
8847
|
diff: buildDiff(existing, generated)
|
|
8713
8848
|
};
|
|
8714
8849
|
}
|
|
8715
|
-
await mkdir(
|
|
8850
|
+
await mkdir(path15.dirname(dest.path), { recursive: true });
|
|
8716
8851
|
await writeFile(dest.path, generated, "utf-8");
|
|
8717
8852
|
return {
|
|
8718
8853
|
written: true,
|
|
@@ -8763,7 +8898,7 @@ var init_marker = __esm({
|
|
|
8763
8898
|
|
|
8764
8899
|
// packages/agents/dist/projection/codex.js
|
|
8765
8900
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
8766
|
-
import
|
|
8901
|
+
import path16 from "path";
|
|
8767
8902
|
import os7 from "os";
|
|
8768
8903
|
function renderMarkdown(source) {
|
|
8769
8904
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
@@ -8788,7 +8923,7 @@ function createCodexEmitter() {
|
|
|
8788
8923
|
destinations(scope, projectRoot) {
|
|
8789
8924
|
if (scope === "user") {
|
|
8790
8925
|
return [{
|
|
8791
|
-
path:
|
|
8926
|
+
path: path16.join(os7.homedir(), ".codex/AGENTS.md"),
|
|
8792
8927
|
shared: true,
|
|
8793
8928
|
format: "markdown"
|
|
8794
8929
|
}];
|
|
@@ -8796,7 +8931,7 @@ function createCodexEmitter() {
|
|
|
8796
8931
|
if (!projectRoot)
|
|
8797
8932
|
return [];
|
|
8798
8933
|
return [{
|
|
8799
|
-
path:
|
|
8934
|
+
path: path16.join(projectRoot, "AGENTS.md"),
|
|
8800
8935
|
shared: true,
|
|
8801
8936
|
format: "markdown"
|
|
8802
8937
|
}];
|
|
@@ -8817,7 +8952,7 @@ ${existing ?? ""}
|
|
|
8817
8952
|
${generated}`
|
|
8818
8953
|
};
|
|
8819
8954
|
}
|
|
8820
|
-
await mkdir2(
|
|
8955
|
+
await mkdir2(path16.dirname(dest.path), { recursive: true });
|
|
8821
8956
|
await writeFile2(dest.path, generated, "utf-8");
|
|
8822
8957
|
return {
|
|
8823
8958
|
written: true,
|
|
@@ -8835,7 +8970,7 @@ var init_codex2 = __esm({
|
|
|
8835
8970
|
|
|
8836
8971
|
// packages/agents/dist/projection/gemini.js
|
|
8837
8972
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
8838
|
-
import
|
|
8973
|
+
import path17 from "path";
|
|
8839
8974
|
import os8 from "os";
|
|
8840
8975
|
function renderMarkdown2(source) {
|
|
8841
8976
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
@@ -8860,7 +8995,7 @@ function createGeminiEmitter() {
|
|
|
8860
8995
|
destinations(scope, projectRoot) {
|
|
8861
8996
|
if (scope === "user") {
|
|
8862
8997
|
return [{
|
|
8863
|
-
path:
|
|
8998
|
+
path: path17.join(os8.homedir(), ".gemini/GEMINI.md"),
|
|
8864
8999
|
shared: true,
|
|
8865
9000
|
format: "markdown"
|
|
8866
9001
|
}];
|
|
@@ -8868,7 +9003,7 @@ function createGeminiEmitter() {
|
|
|
8868
9003
|
if (!projectRoot)
|
|
8869
9004
|
return [];
|
|
8870
9005
|
return [{
|
|
8871
|
-
path:
|
|
9006
|
+
path: path17.join(projectRoot, "GEMINI.md"),
|
|
8872
9007
|
shared: true,
|
|
8873
9008
|
format: "markdown"
|
|
8874
9009
|
}];
|
|
@@ -8889,7 +9024,7 @@ ${existing ?? ""}
|
|
|
8889
9024
|
${generated}`
|
|
8890
9025
|
};
|
|
8891
9026
|
}
|
|
8892
|
-
await mkdir3(
|
|
9027
|
+
await mkdir3(path17.dirname(dest.path), { recursive: true });
|
|
8893
9028
|
await writeFile3(dest.path, generated, "utf-8");
|
|
8894
9029
|
return {
|
|
8895
9030
|
written: true,
|
|
@@ -8907,7 +9042,7 @@ var init_gemini2 = __esm({
|
|
|
8907
9042
|
|
|
8908
9043
|
// packages/agents/dist/projection/opencode.js
|
|
8909
9044
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
8910
|
-
import
|
|
9045
|
+
import path18 from "path";
|
|
8911
9046
|
import os9 from "os";
|
|
8912
9047
|
function renderMarkdown3(source) {
|
|
8913
9048
|
const skillSections = source.skills.map((s) => `## Skill: ${s.name}
|
|
@@ -8932,7 +9067,7 @@ function createOpencodeEmitter() {
|
|
|
8932
9067
|
destinations(scope, projectRoot) {
|
|
8933
9068
|
if (scope === "user") {
|
|
8934
9069
|
return [{
|
|
8935
|
-
path:
|
|
9070
|
+
path: path18.join(os9.homedir(), ".config", "opencode", "AGENTS.md"),
|
|
8936
9071
|
shared: true,
|
|
8937
9072
|
format: "markdown"
|
|
8938
9073
|
}];
|
|
@@ -8940,7 +9075,7 @@ function createOpencodeEmitter() {
|
|
|
8940
9075
|
if (!projectRoot)
|
|
8941
9076
|
return [];
|
|
8942
9077
|
return [{
|
|
8943
|
-
path:
|
|
9078
|
+
path: path18.join(projectRoot, "AGENTS.md"),
|
|
8944
9079
|
shared: true,
|
|
8945
9080
|
format: "markdown"
|
|
8946
9081
|
}];
|
|
@@ -8961,7 +9096,7 @@ ${existing ?? ""}
|
|
|
8961
9096
|
${generated}`
|
|
8962
9097
|
};
|
|
8963
9098
|
}
|
|
8964
|
-
await mkdir4(
|
|
9099
|
+
await mkdir4(path18.dirname(dest.path), { recursive: true });
|
|
8965
9100
|
await writeFile4(dest.path, generated, "utf-8");
|
|
8966
9101
|
return {
|
|
8967
9102
|
written: true,
|
|
@@ -9820,7 +9955,7 @@ var init_sse_bridge = __esm({
|
|
|
9820
9955
|
|
|
9821
9956
|
// packages/agents/dist/interactive/claude.js
|
|
9822
9957
|
import { execSync as execSync7 } from "child_process";
|
|
9823
|
-
import { readFileSync as
|
|
9958
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
9824
9959
|
import { homedir as homedir14 } from "os";
|
|
9825
9960
|
import { join as join19 } from "path";
|
|
9826
9961
|
function probeClaudeSettingsFlag() {
|
|
@@ -9884,7 +10019,7 @@ function deriveTranscriptPath(sessionId, cwd) {
|
|
|
9884
10019
|
}
|
|
9885
10020
|
function readLastAssistantText(transcriptPath) {
|
|
9886
10021
|
try {
|
|
9887
|
-
const raw =
|
|
10022
|
+
const raw = readFileSync12(transcriptPath, "utf-8");
|
|
9888
10023
|
const lines = raw.split(/\r?\n/);
|
|
9889
10024
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
9890
10025
|
const line = lines[i].trim();
|
|
@@ -9926,8 +10061,8 @@ function resolveLastAssistantText(payload) {
|
|
|
9926
10061
|
const derived = deriveTranscriptPath(p?.session_id, cwd);
|
|
9927
10062
|
if (derived)
|
|
9928
10063
|
candidates.push(derived);
|
|
9929
|
-
for (const
|
|
9930
|
-
const text = readLastAssistantText(
|
|
10064
|
+
for (const path35 of candidates) {
|
|
10065
|
+
const text = readLastAssistantText(path35);
|
|
9931
10066
|
if (text != null)
|
|
9932
10067
|
return text;
|
|
9933
10068
|
}
|
|
@@ -10454,9 +10589,9 @@ async function runRuntimeSend(arg1, arg2, opts, confirmOpts) {
|
|
|
10454
10589
|
const resolved = resolveTarget(registry, config, target, !!opts.command);
|
|
10455
10590
|
await needRef(resolved);
|
|
10456
10591
|
const finalProject = opts.command ? config.commandName : target;
|
|
10457
|
-
const { join: join31, dirname:
|
|
10592
|
+
const { join: join31, dirname: dirname9 } = await import("path");
|
|
10458
10593
|
const { DEFAULT_CONFIG_PATH: DEFAULT_CONFIG_PATH2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
10459
|
-
const stateRoot = join31(
|
|
10594
|
+
const stateRoot = join31(dirname9(DEFAULT_CONFIG_PATH2), "state");
|
|
10460
10595
|
const seq = await appendCaptainMessage2({
|
|
10461
10596
|
stateRoot,
|
|
10462
10597
|
project: finalProject,
|
|
@@ -10562,9 +10697,9 @@ var init_runtime2 = __esm({
|
|
|
10562
10697
|
init_dist();
|
|
10563
10698
|
init_dist2();
|
|
10564
10699
|
import { Command as Command35 } from "commander";
|
|
10565
|
-
import {
|
|
10700
|
+
import { existsSync as existsSync13, readFileSync as readFileSync15 } from "fs";
|
|
10566
10701
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
10567
|
-
import { dirname as
|
|
10702
|
+
import { dirname as dirname8, join as join30 } from "path";
|
|
10568
10703
|
import { homedir as homedir22 } from "os";
|
|
10569
10704
|
|
|
10570
10705
|
// packages/cli/src/commands/doctor.ts
|
|
@@ -10574,9 +10709,9 @@ init_dist();
|
|
|
10574
10709
|
init_dist3();
|
|
10575
10710
|
import { Command } from "commander";
|
|
10576
10711
|
import { execSync as execSync8 } from "child_process";
|
|
10577
|
-
import
|
|
10712
|
+
import fs15 from "fs";
|
|
10578
10713
|
import { stat } from "fs/promises";
|
|
10579
|
-
import
|
|
10714
|
+
import path19 from "path";
|
|
10580
10715
|
import chalk3 from "chalk";
|
|
10581
10716
|
|
|
10582
10717
|
// packages/cli/src/commands/health-view.ts
|
|
@@ -10679,7 +10814,7 @@ function settingsHaveAgentTeams() {
|
|
|
10679
10814
|
try {
|
|
10680
10815
|
const home = process.env.HOME || "";
|
|
10681
10816
|
const settings = JSON.parse(
|
|
10682
|
-
|
|
10817
|
+
fs15.readFileSync(`${home}/.claude/settings.json`, "utf-8")
|
|
10683
10818
|
);
|
|
10684
10819
|
return settings?.env?.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === "1";
|
|
10685
10820
|
} catch {
|
|
@@ -10690,7 +10825,7 @@ function pluginInstalled(pluginKey) {
|
|
|
10690
10825
|
try {
|
|
10691
10826
|
const home = process.env.HOME || "";
|
|
10692
10827
|
const plugins = JSON.parse(
|
|
10693
|
-
|
|
10828
|
+
fs15.readFileSync(
|
|
10694
10829
|
`${home}/.claude/plugins/installed_plugins.json`,
|
|
10695
10830
|
"utf-8"
|
|
10696
10831
|
)
|
|
@@ -10712,6 +10847,43 @@ function tryGetVersion(cmd) {
|
|
|
10712
10847
|
return "";
|
|
10713
10848
|
}
|
|
10714
10849
|
}
|
|
10850
|
+
function candidateGlobalInstalls(roots) {
|
|
10851
|
+
const out = [];
|
|
10852
|
+
if (roots.npm) out.push({ manager: "npm", packageJsonPath: path19.join(roots.npm, "squadrant", "package.json") });
|
|
10853
|
+
if (roots.pnpm) out.push({ manager: "pnpm", packageJsonPath: path19.join(roots.pnpm, "squadrant", "package.json") });
|
|
10854
|
+
if (roots.yarn) out.push({ manager: "yarn", packageJsonPath: path19.join(roots.yarn, "node_modules", "squadrant", "package.json") });
|
|
10855
|
+
return out;
|
|
10856
|
+
}
|
|
10857
|
+
function findInstalledSquadrants(candidates, readVersion) {
|
|
10858
|
+
const out = [];
|
|
10859
|
+
for (const c of candidates) {
|
|
10860
|
+
const version = readVersion(c.packageJsonPath);
|
|
10861
|
+
if (version) out.push({ manager: c.manager, packageJsonPath: c.packageJsonPath, version });
|
|
10862
|
+
}
|
|
10863
|
+
return out;
|
|
10864
|
+
}
|
|
10865
|
+
function formatDuplicateInstallWarning(installs) {
|
|
10866
|
+
if (installs.length <= 1) return null;
|
|
10867
|
+
const lines = installs.map((i) => ` ${i.manager}: ${i.packageJsonPath} (v${i.version})`);
|
|
10868
|
+
return `Multiple squadrant installs detected:
|
|
10869
|
+
${lines.join("\n")}
|
|
10870
|
+
Two installs fight over the daemon plist (#670) \u2014 uninstall the one you don't use, then run \`squadrant heal daemon\`.`;
|
|
10871
|
+
}
|
|
10872
|
+
function readPackageVersion(packageJsonPath) {
|
|
10873
|
+
try {
|
|
10874
|
+
const pkg2 = JSON.parse(fs15.readFileSync(packageJsonPath, "utf-8"));
|
|
10875
|
+
return typeof pkg2.version === "string" ? pkg2.version : null;
|
|
10876
|
+
} catch {
|
|
10877
|
+
return null;
|
|
10878
|
+
}
|
|
10879
|
+
}
|
|
10880
|
+
function tryGetGlobalRoot(cmd, args) {
|
|
10881
|
+
try {
|
|
10882
|
+
return execSync8(`${cmd} ${args.join(" ")}`, { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }).trim() || void 0;
|
|
10883
|
+
} catch {
|
|
10884
|
+
return void 0;
|
|
10885
|
+
}
|
|
10886
|
+
}
|
|
10715
10887
|
function check(label, pass, hint) {
|
|
10716
10888
|
const icon = pass ? chalk3.green("\u2714 PASS") : chalk3.red("\u2718 FAIL");
|
|
10717
10889
|
console.log(` ${icon} ${label}`);
|
|
@@ -10735,7 +10907,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
|
|
|
10735
10907
|
));
|
|
10736
10908
|
results.push(check(
|
|
10737
10909
|
"Obsidian installed",
|
|
10738
|
-
commandExists("obsidian") ||
|
|
10910
|
+
commandExists("obsidian") || fs15.existsSync("/Applications/Obsidian.app"),
|
|
10739
10911
|
"Install from: https://obsidian.md"
|
|
10740
10912
|
));
|
|
10741
10913
|
results.push(check(
|
|
@@ -10829,7 +11001,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
|
|
|
10829
11001
|
const emitter = projectionRegistry.get(name);
|
|
10830
11002
|
const [userDest] = emitter.destinations("user");
|
|
10831
11003
|
if (!userDest) continue;
|
|
10832
|
-
const dir =
|
|
11004
|
+
const dir = path19.dirname(userDest.path);
|
|
10833
11005
|
let status;
|
|
10834
11006
|
try {
|
|
10835
11007
|
await stat(dir);
|
|
@@ -10842,7 +11014,7 @@ var doctorCommand = new Command("doctor").description("Check system health and p
|
|
|
10842
11014
|
results.push(
|
|
10843
11015
|
check(
|
|
10844
11016
|
"Squadrant config exists",
|
|
10845
|
-
|
|
11017
|
+
fs15.existsSync(
|
|
10846
11018
|
process.env.SQUADRANT_CONFIG || `${process.env.HOME}/.config/squadrant/config.json`
|
|
10847
11019
|
),
|
|
10848
11020
|
"Run: squadrant init"
|
|
@@ -10855,6 +11027,16 @@ var doctorCommand = new Command("doctor").description("Check system health and p
|
|
|
10855
11027
|
${passed === total ? chalk3.green("All checks passed") : chalk3.yellow(`${passed}/${total} checks passed`)}
|
|
10856
11028
|
`
|
|
10857
11029
|
);
|
|
11030
|
+
const installCandidates = candidateGlobalInstalls({
|
|
11031
|
+
npm: tryGetGlobalRoot("npm", ["root", "-g"]),
|
|
11032
|
+
pnpm: tryGetGlobalRoot("pnpm", ["root", "-g"]),
|
|
11033
|
+
yarn: tryGetGlobalRoot("yarn", ["global", "dir"])
|
|
11034
|
+
});
|
|
11035
|
+
const duplicateWarning = formatDuplicateInstallWarning(findInstalledSquadrants(installCandidates, readPackageVersion));
|
|
11036
|
+
if (duplicateWarning) {
|
|
11037
|
+
console.log(`
|
|
11038
|
+
${chalk3.yellow("\u26A0 WARN")} ${duplicateWarning}`);
|
|
11039
|
+
}
|
|
10858
11040
|
printServiceHealth(await queryHealth());
|
|
10859
11041
|
console.log(chalk3.bold("\nTool Version Compat\n"));
|
|
10860
11042
|
const toolVersionMap = {
|
|
@@ -10916,16 +11098,16 @@ init_dist();
|
|
|
10916
11098
|
init_dist3();
|
|
10917
11099
|
init_dist();
|
|
10918
11100
|
import { Command as Command2 } from "commander";
|
|
10919
|
-
import
|
|
10920
|
-
import
|
|
11101
|
+
import fs16 from "fs";
|
|
11102
|
+
import path20 from "path";
|
|
10921
11103
|
import os10 from "os";
|
|
10922
11104
|
import readline from "readline";
|
|
10923
11105
|
import chalk4 from "chalk";
|
|
10924
11106
|
|
|
10925
11107
|
// packages/cli/src/lib/per-crew-settings.ts
|
|
10926
11108
|
init_dist4();
|
|
10927
|
-
import { mkdirSync as
|
|
10928
|
-
import { dirname as
|
|
11109
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
|
|
11110
|
+
import { dirname as dirname4, join as join20 } from "path";
|
|
10929
11111
|
import { homedir as homedir15 } from "os";
|
|
10930
11112
|
var CREW_PERMISSION_ALLOWLIST = [
|
|
10931
11113
|
// git — read + safe mutations (reset/clean/config intentionally excluded)
|
|
@@ -11018,28 +11200,28 @@ function mergeCrewPermissions(settings) {
|
|
|
11018
11200
|
}
|
|
11019
11201
|
function writePerCrewSettingsLocal(o) {
|
|
11020
11202
|
const dir = join20(o.projectCwd, ".claude");
|
|
11021
|
-
|
|
11203
|
+
mkdirSync7(dir, { recursive: true });
|
|
11022
11204
|
const file = join20(dir, "settings.local.json");
|
|
11023
11205
|
let existing = {};
|
|
11024
11206
|
try {
|
|
11025
|
-
const raw = healStaleCockpitRefs(
|
|
11207
|
+
const raw = healStaleCockpitRefs(readFileSync13(file, "utf-8"));
|
|
11026
11208
|
existing = JSON.parse(raw);
|
|
11027
11209
|
} catch {
|
|
11028
11210
|
}
|
|
11029
11211
|
const withHooks = mergeClaudeHooks(existing, o.hookCmd ?? "squadrant crew _hook");
|
|
11030
11212
|
const merged = mergeCrewPermissions(withHooks);
|
|
11031
|
-
|
|
11213
|
+
writeFileSync9(file, JSON.stringify(merged, null, 2));
|
|
11032
11214
|
return file;
|
|
11033
11215
|
}
|
|
11034
11216
|
var DEFAULT_GLOBAL_OPENCODE_CONFIG_PATH = join20(homedir15(), ".config", "opencode", "opencode.json");
|
|
11035
11217
|
function ensureGlobalOpencodeConfig(configPath = DEFAULT_GLOBAL_OPENCODE_CONFIG_PATH) {
|
|
11036
|
-
|
|
11218
|
+
mkdirSync7(dirname4(configPath), { recursive: true });
|
|
11037
11219
|
const defaultConfig = {
|
|
11038
11220
|
$schema: "https://opencode.ai/config.json",
|
|
11039
11221
|
model: "anthropic/claude-sonnet-4-5"
|
|
11040
11222
|
};
|
|
11041
11223
|
try {
|
|
11042
|
-
|
|
11224
|
+
writeFileSync9(configPath, JSON.stringify(defaultConfig, null, 2) + "\n", { flag: "wx" });
|
|
11043
11225
|
return configPath;
|
|
11044
11226
|
} catch (err) {
|
|
11045
11227
|
if (err.code === "EEXIST") return null;
|
|
@@ -11048,7 +11230,7 @@ function ensureGlobalOpencodeConfig(configPath = DEFAULT_GLOBAL_OPENCODE_CONFIG_
|
|
|
11048
11230
|
}
|
|
11049
11231
|
function writePerCrewOpencodeConfig(o) {
|
|
11050
11232
|
const dir = join20(o.stateRoot, o.project, o.taskId);
|
|
11051
|
-
|
|
11233
|
+
mkdirSync7(dir, { recursive: true });
|
|
11052
11234
|
const file = join20(dir, "opencode.json");
|
|
11053
11235
|
const config = {
|
|
11054
11236
|
permission: {
|
|
@@ -11064,29 +11246,29 @@ function writePerCrewOpencodeConfig(o) {
|
|
|
11064
11246
|
external_directory: { "**": "allow" }
|
|
11065
11247
|
}
|
|
11066
11248
|
};
|
|
11067
|
-
|
|
11249
|
+
writeFileSync9(file, JSON.stringify(config, null, 2));
|
|
11068
11250
|
return file;
|
|
11069
11251
|
}
|
|
11070
11252
|
|
|
11071
11253
|
// packages/cli/src/commands/init.ts
|
|
11072
11254
|
init_dist4();
|
|
11073
11255
|
function findPackageRoot() {
|
|
11074
|
-
let dir =
|
|
11256
|
+
let dir = path20.dirname(new URL(import.meta.url).pathname);
|
|
11075
11257
|
while (dir !== "/") {
|
|
11076
|
-
if (
|
|
11077
|
-
dir =
|
|
11258
|
+
if (fs16.existsSync(path20.join(dir, "package.json"))) return dir;
|
|
11259
|
+
dir = path20.dirname(dir);
|
|
11078
11260
|
}
|
|
11079
11261
|
return process.cwd();
|
|
11080
11262
|
}
|
|
11081
11263
|
function copyDirRecursive(src, dest) {
|
|
11082
|
-
|
|
11083
|
-
for (const entry of
|
|
11084
|
-
const srcPath =
|
|
11085
|
-
const destPath =
|
|
11264
|
+
fs16.mkdirSync(dest, { recursive: true });
|
|
11265
|
+
for (const entry of fs16.readdirSync(src, { withFileTypes: true })) {
|
|
11266
|
+
const srcPath = path20.join(src, entry.name);
|
|
11267
|
+
const destPath = path20.join(dest, entry.name);
|
|
11086
11268
|
if (entry.isDirectory()) {
|
|
11087
11269
|
copyDirRecursive(srcPath, destPath);
|
|
11088
11270
|
} else {
|
|
11089
|
-
|
|
11271
|
+
fs16.copyFileSync(srcPath, destPath);
|
|
11090
11272
|
}
|
|
11091
11273
|
}
|
|
11092
11274
|
}
|
|
@@ -11106,7 +11288,7 @@ function promptLine(question) {
|
|
|
11106
11288
|
var initCommand = new Command2("init").description("Guided first-time setup: hub vault, agents, plugins, projects (re-run-safe)").option("--hub <path>", "Hub vault path", "~/squadrant-hub").action(async (opts) => {
|
|
11107
11289
|
const hubPath = resolveHome(opts.hub);
|
|
11108
11290
|
const pkgRoot = findPackageRoot();
|
|
11109
|
-
const configDir =
|
|
11291
|
+
const configDir = path20.join(os10.homedir(), ".config", "squadrant");
|
|
11110
11292
|
const isTTY = process.stdin.isTTY === true;
|
|
11111
11293
|
console.log(chalk4.bold("\nSquadrant Init\n"));
|
|
11112
11294
|
if (!isTTY) {
|
|
@@ -11132,8 +11314,8 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
11132
11314
|
}
|
|
11133
11315
|
const wsRegistry = new WorkspaceRegistry({ obsidian: createObsidianDriver });
|
|
11134
11316
|
try {
|
|
11135
|
-
if (
|
|
11136
|
-
const existing = JSON.parse(
|
|
11317
|
+
if (fs16.existsSync(DEFAULT_CONFIG_PATH)) {
|
|
11318
|
+
const existing = JSON.parse(fs16.readFileSync(DEFAULT_CONFIG_PATH, "utf-8"));
|
|
11137
11319
|
wsRegistry.get(existing.workspace ?? "obsidian");
|
|
11138
11320
|
}
|
|
11139
11321
|
} catch (err) {
|
|
@@ -11141,7 +11323,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
11141
11323
|
return;
|
|
11142
11324
|
}
|
|
11143
11325
|
stepHeader(1, 5, "Hub vault");
|
|
11144
|
-
if (
|
|
11326
|
+
if (fs16.existsSync(DEFAULT_CONFIG_PATH)) {
|
|
11145
11327
|
console.log(chalk4.yellow(" \u26A0 Config already exists, skipping creation"));
|
|
11146
11328
|
} else {
|
|
11147
11329
|
const config = getDefaultConfig();
|
|
@@ -11149,37 +11331,37 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
11149
11331
|
saveConfig(config);
|
|
11150
11332
|
console.log(chalk4.green(` \u2714 Config created at ${DEFAULT_CONFIG_PATH}`));
|
|
11151
11333
|
}
|
|
11152
|
-
const hubTemplate =
|
|
11153
|
-
if (
|
|
11334
|
+
const hubTemplate = path20.join(pkgRoot, "obsidian", "hub");
|
|
11335
|
+
if (fs16.existsSync(hubPath)) {
|
|
11154
11336
|
console.log(chalk4.yellow(` \u26A0 Hub vault already exists at ${hubPath}`));
|
|
11155
|
-
} else if (
|
|
11337
|
+
} else if (fs16.existsSync(hubTemplate)) {
|
|
11156
11338
|
copyDirRecursive(hubTemplate, hubPath);
|
|
11157
11339
|
console.log(chalk4.green(` \u2714 Hub vault scaffolded at ${hubPath}`));
|
|
11158
11340
|
} else {
|
|
11159
|
-
|
|
11341
|
+
fs16.mkdirSync(hubPath, { recursive: true });
|
|
11160
11342
|
console.log(chalk4.yellow(` \u26A0 Hub template not found; created empty directory at ${hubPath}`));
|
|
11161
11343
|
}
|
|
11162
|
-
const hubDashboardSrc =
|
|
11163
|
-
const hubDashboardDest =
|
|
11164
|
-
if (
|
|
11165
|
-
|
|
11344
|
+
const hubDashboardSrc = path20.join(pkgRoot, "obsidian", "hub", "dashboard.md");
|
|
11345
|
+
const hubDashboardDest = path20.join(hubPath, "dashboard.md");
|
|
11346
|
+
if (fs16.existsSync(hubDashboardSrc)) {
|
|
11347
|
+
fs16.copyFileSync(hubDashboardSrc, hubDashboardDest);
|
|
11166
11348
|
console.log(chalk4.green(` \u2714 Dashboard refreshed`));
|
|
11167
11349
|
}
|
|
11168
|
-
|
|
11350
|
+
fs16.mkdirSync(path20.join(hubPath, "projects"), { recursive: true });
|
|
11169
11351
|
ensureRuntimeSynced({ sourceRoot: pkgRoot, runtimeRoot: configDir });
|
|
11170
11352
|
console.log(chalk4.green(` \u2714 Runtime assets synced to ${configDir}`));
|
|
11171
11353
|
stepHeader(2, 5, "Agent + projection setup");
|
|
11172
|
-
const settingsPath =
|
|
11354
|
+
const settingsPath = path20.join(os10.homedir(), ".claude", "settings.json");
|
|
11173
11355
|
try {
|
|
11174
11356
|
let settings = {};
|
|
11175
|
-
if (
|
|
11176
|
-
settings = JSON.parse(
|
|
11357
|
+
if (fs16.existsSync(settingsPath)) {
|
|
11358
|
+
settings = JSON.parse(fs16.readFileSync(settingsPath, "utf-8"));
|
|
11177
11359
|
}
|
|
11178
11360
|
const env = settings.env || {};
|
|
11179
11361
|
if (env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS !== "1") {
|
|
11180
11362
|
settings.env = { ...env, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1" };
|
|
11181
|
-
|
|
11182
|
-
|
|
11363
|
+
fs16.mkdirSync(path20.dirname(settingsPath), { recursive: true });
|
|
11364
|
+
fs16.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
11183
11365
|
console.log(chalk4.green(" \u2714 Agent Teams enabled in ~/.claude/settings.json"));
|
|
11184
11366
|
} else {
|
|
11185
11367
|
console.log(chalk4.green(" \u2714 Agent Teams already enabled"));
|
|
@@ -11231,7 +11413,7 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
11231
11413
|
chalk4.cyan(" Absolute path to your first project (Enter to skip): ")
|
|
11232
11414
|
);
|
|
11233
11415
|
if (projectPath) {
|
|
11234
|
-
const projectName =
|
|
11416
|
+
const projectName = path20.basename(projectPath);
|
|
11235
11417
|
console.log(chalk4.bold(`
|
|
11236
11418
|
Run this to register it:`));
|
|
11237
11419
|
console.log(chalk4.cyan(` squadrant projects add ${projectName} ${projectPath}
|
|
@@ -11259,8 +11441,8 @@ var initCommand = new Command2("init").description("Guided first-time setup: hub
|
|
|
11259
11441
|
init_dist();
|
|
11260
11442
|
init_dist2();
|
|
11261
11443
|
import { Command as Command3 } from "commander";
|
|
11262
|
-
import
|
|
11263
|
-
import
|
|
11444
|
+
import fs17 from "fs";
|
|
11445
|
+
import path21 from "path";
|
|
11264
11446
|
import chalk5 from "chalk";
|
|
11265
11447
|
function restartAfterProjectsAdd(opts) {
|
|
11266
11448
|
const doRestart = opts.doRestart ?? restartDaemonIfRunning;
|
|
@@ -11272,22 +11454,22 @@ function restartAfterProjectsAdd(opts) {
|
|
|
11272
11454
|
}
|
|
11273
11455
|
}
|
|
11274
11456
|
function findPackageRoot2() {
|
|
11275
|
-
let dir =
|
|
11457
|
+
let dir = path21.dirname(new URL(import.meta.url).pathname);
|
|
11276
11458
|
while (dir !== "/") {
|
|
11277
|
-
if (
|
|
11278
|
-
dir =
|
|
11459
|
+
if (fs17.existsSync(path21.join(dir, "package.json"))) return dir;
|
|
11460
|
+
dir = path21.dirname(dir);
|
|
11279
11461
|
}
|
|
11280
11462
|
return process.cwd();
|
|
11281
11463
|
}
|
|
11282
11464
|
function copyDirRecursive2(src, dest) {
|
|
11283
|
-
|
|
11284
|
-
for (const entry of
|
|
11285
|
-
const srcPath =
|
|
11286
|
-
const destPath =
|
|
11465
|
+
fs17.mkdirSync(dest, { recursive: true });
|
|
11466
|
+
for (const entry of fs17.readdirSync(src, { withFileTypes: true })) {
|
|
11467
|
+
const srcPath = path21.join(src, entry.name);
|
|
11468
|
+
const destPath = path21.join(dest, entry.name);
|
|
11287
11469
|
if (entry.isDirectory()) {
|
|
11288
11470
|
copyDirRecursive2(srcPath, destPath);
|
|
11289
11471
|
} else {
|
|
11290
|
-
|
|
11472
|
+
fs17.copyFileSync(srcPath, destPath);
|
|
11291
11473
|
}
|
|
11292
11474
|
}
|
|
11293
11475
|
}
|
|
@@ -11323,7 +11505,7 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
|
|
|
11323
11505
|
process.exit(1);
|
|
11324
11506
|
}
|
|
11325
11507
|
const resolvedPath = resolveHome(projectPath);
|
|
11326
|
-
if (!
|
|
11508
|
+
if (!fs17.existsSync(path21.join(resolvedPath, ".git"))) {
|
|
11327
11509
|
console.log(chalk5.yellow(`
|
|
11328
11510
|
\u26A0 No .git found at ${resolvedPath}. Make sure this is the project root, not a parent directory.
|
|
11329
11511
|
`));
|
|
@@ -11376,7 +11558,7 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
|
|
|
11376
11558
|
\u26A0 Group '${group}' already has '${primary[0]}' as primary. Overriding.`));
|
|
11377
11559
|
}
|
|
11378
11560
|
}
|
|
11379
|
-
const spokeVault = opts.spoke ? resolveHome(opts.spoke) :
|
|
11561
|
+
const spokeVault = opts.spoke ? resolveHome(opts.spoke) : path21.join(config.hubVault, "spokes", name);
|
|
11380
11562
|
const project = {
|
|
11381
11563
|
path: resolvedPath,
|
|
11382
11564
|
captainName,
|
|
@@ -11391,20 +11573,20 @@ var addCmd = new Command3("add").description("Register a project").argument("<na
|
|
|
11391
11573
|
\u2714 Project '${name}' registered`));
|
|
11392
11574
|
restartAfterProjectsAdd({ noRestart: opts.restart === false });
|
|
11393
11575
|
const pkgRoot = findPackageRoot2();
|
|
11394
|
-
const spokeTemplate =
|
|
11395
|
-
if (
|
|
11576
|
+
const spokeTemplate = path21.join(pkgRoot, "obsidian", "spoke");
|
|
11577
|
+
if (fs17.existsSync(spokeVault)) {
|
|
11396
11578
|
console.log(chalk5.yellow(` \u26A0 Spoke vault already exists at ${spokeVault}, skipping scaffold`));
|
|
11397
|
-
} else if (
|
|
11579
|
+
} else if (fs17.existsSync(spokeTemplate)) {
|
|
11398
11580
|
copyDirRecursive2(spokeTemplate, spokeVault);
|
|
11399
|
-
const statusPath =
|
|
11400
|
-
if (
|
|
11401
|
-
const content =
|
|
11581
|
+
const statusPath = path21.join(spokeVault, "status.md");
|
|
11582
|
+
if (fs17.existsSync(statusPath)) {
|
|
11583
|
+
const content = fs17.readFileSync(statusPath, "utf-8");
|
|
11402
11584
|
const updated = content.replace(/^project: unnamed/m, `project: ${name}`);
|
|
11403
|
-
|
|
11585
|
+
fs17.writeFileSync(statusPath, updated);
|
|
11404
11586
|
}
|
|
11405
11587
|
console.log(chalk5.green(` \u2714 Spoke vault scaffolded at ${spokeVault}`));
|
|
11406
11588
|
} else {
|
|
11407
|
-
|
|
11589
|
+
fs17.mkdirSync(spokeVault, { recursive: true });
|
|
11408
11590
|
console.log(chalk5.yellow(` \u26A0 Spoke template not found; created empty dir at ${spokeVault}`));
|
|
11409
11591
|
}
|
|
11410
11592
|
console.log("");
|
|
@@ -11473,10 +11655,10 @@ init_dist4();
|
|
|
11473
11655
|
init_dist();
|
|
11474
11656
|
import { Command as Command5 } from "commander";
|
|
11475
11657
|
import { execSync as execSync9 } from "child_process";
|
|
11476
|
-
import
|
|
11658
|
+
import path22 from "path";
|
|
11477
11659
|
import os11 from "os";
|
|
11478
11660
|
import chalk7 from "chalk";
|
|
11479
|
-
var TEMPLATES_DIR2 =
|
|
11661
|
+
var TEMPLATES_DIR2 = path22.join(os11.homedir(), ".config", "squadrant", "templates");
|
|
11480
11662
|
var TASK_PROMPTS = {
|
|
11481
11663
|
briefing: "Run your daily briefing using the squadrant:command-ops skill. Read all spoke handoffs, yesterday's logs, current status; produce a concise cross-project briefing; save to {hubVault}/daily-logs/YYYY-MM-DD.md; then exit.",
|
|
11482
11664
|
"learnings-review": "Run a learnings review using the squadrant:command-ops skill. Scan {spokeVault}/learnings across all projects, identify cross-project patterns, propose captured-skill or fix actions, and exit when done.",
|
|
@@ -11509,7 +11691,7 @@ async function runCommandSpawn(input) {
|
|
|
11509
11691
|
if (!agent) {
|
|
11510
11692
|
throw new Error(`Unknown agent '${agentName}'. Known: claude, codex, gemini, opencode.`);
|
|
11511
11693
|
}
|
|
11512
|
-
const promptFile =
|
|
11694
|
+
const promptFile = path22.join(TEMPLATES_DIR2, `command.${agent.templateSuffix}.md`);
|
|
11513
11695
|
const cliCommand = agent.buildCommand({
|
|
11514
11696
|
prompt,
|
|
11515
11697
|
workdir: process.cwd(),
|
|
@@ -11551,7 +11733,7 @@ import { randomUUID as randomUUID4 } from "crypto";
|
|
|
11551
11733
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
11552
11734
|
import { homedir as homedir18 } from "os";
|
|
11553
11735
|
import { join as join23 } from "path";
|
|
11554
|
-
import { mkdirSync as
|
|
11736
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync10 } from "fs";
|
|
11555
11737
|
|
|
11556
11738
|
// packages/cli/src/commands/crew-output.ts
|
|
11557
11739
|
function tailLines(text, maxLines = 40, maxBytes = 4096) {
|
|
@@ -12010,9 +12192,9 @@ function buildSignalRequest(signal, o) {
|
|
|
12010
12192
|
}
|
|
12011
12193
|
function defaultWriteResult(id, payload) {
|
|
12012
12194
|
const dir = join23(homedir18(), ".config", "squadrant", "state", "_results");
|
|
12013
|
-
|
|
12195
|
+
mkdirSync8(dir, { recursive: true });
|
|
12014
12196
|
const file = join23(dir, `${id}.txt`);
|
|
12015
|
-
|
|
12197
|
+
writeFileSync10(file, payload);
|
|
12016
12198
|
return file;
|
|
12017
12199
|
}
|
|
12018
12200
|
async function runCrewSignal(signal, o, deps) {
|
|
@@ -12628,11 +12810,11 @@ init_dist3();
|
|
|
12628
12810
|
init_dist();
|
|
12629
12811
|
init_dist2();
|
|
12630
12812
|
import { Command as Command12 } from "commander";
|
|
12631
|
-
import
|
|
12632
|
-
import
|
|
12813
|
+
import fs18 from "fs";
|
|
12814
|
+
import path23 from "path";
|
|
12633
12815
|
import os12 from "os";
|
|
12634
12816
|
import chalk12 from "chalk";
|
|
12635
|
-
var TEMPLATES_DIR3 =
|
|
12817
|
+
var TEMPLATES_DIR3 = path23.join(os12.homedir(), ".config", "squadrant", "templates");
|
|
12636
12818
|
async function runSideSpawn2(input) {
|
|
12637
12819
|
const config = loadConfig();
|
|
12638
12820
|
const proj = config.projects[input.project];
|
|
@@ -12656,7 +12838,7 @@ async function runSideSpawn2(input) {
|
|
|
12656
12838
|
throw new Error(`Unknown agent '${agentName}'. Known: claude, codex, gemini, opencode.`);
|
|
12657
12839
|
}
|
|
12658
12840
|
const sideModel = sideRole?.model;
|
|
12659
|
-
const promptFile =
|
|
12841
|
+
const promptFile = path23.join(
|
|
12660
12842
|
TEMPLATES_DIR3,
|
|
12661
12843
|
`side.${input.role}.${agent.templateSuffix}.md`
|
|
12662
12844
|
);
|
|
@@ -12664,7 +12846,7 @@ async function runSideSpawn2(input) {
|
|
|
12664
12846
|
prompt: input.topic,
|
|
12665
12847
|
workdir: spawnCwd,
|
|
12666
12848
|
role: "side",
|
|
12667
|
-
promptFile:
|
|
12849
|
+
promptFile: fs18.existsSync(promptFile) ? promptFile : void 0,
|
|
12668
12850
|
interactive: true,
|
|
12669
12851
|
permissionMode: config.defaults.permissions?.crew ?? "auto",
|
|
12670
12852
|
...sideModel ? { model: sideModel } : {}
|
|
@@ -12928,8 +13110,8 @@ function renderDashboard(rows, opts) {
|
|
|
12928
13110
|
|
|
12929
13111
|
// packages/web/dist/sync-hub.js
|
|
12930
13112
|
init_dist();
|
|
12931
|
-
import
|
|
12932
|
-
import
|
|
13113
|
+
import fs19 from "fs";
|
|
13114
|
+
import path24 from "path";
|
|
12933
13115
|
function buildMirrorMarkdown(s) {
|
|
12934
13116
|
const fenced = "```";
|
|
12935
13117
|
return [
|
|
@@ -12955,15 +13137,15 @@ function buildMirrorMarkdown(s) {
|
|
|
12955
13137
|
function syncHub(deps) {
|
|
12956
13138
|
if (!deps.config.hubVault)
|
|
12957
13139
|
return [];
|
|
12958
|
-
const writeFile5 = deps.writeFile ?? ((p, c) =>
|
|
12959
|
-
const mkdir5 = deps.mkdir ?? ((p) =>
|
|
12960
|
-
const projectsDir =
|
|
13140
|
+
const writeFile5 = deps.writeFile ?? ((p, c) => fs19.writeFileSync(p, c));
|
|
13141
|
+
const mkdir5 = deps.mkdir ?? ((p) => fs19.mkdirSync(p, { recursive: true }));
|
|
13142
|
+
const projectsDir = path24.join(resolveHome(deps.config.hubVault), "projects");
|
|
12961
13143
|
mkdir5(projectsDir);
|
|
12962
13144
|
const out = [];
|
|
12963
13145
|
for (const s of deps.statuses) {
|
|
12964
13146
|
if (s.state === "unknown")
|
|
12965
13147
|
continue;
|
|
12966
|
-
const hubPath =
|
|
13148
|
+
const hubPath = path24.join(projectsDir, `${s.project}.md`);
|
|
12967
13149
|
try {
|
|
12968
13150
|
writeFile5(hubPath, buildMirrorMarkdown(s));
|
|
12969
13151
|
out.push({ project: s.project, hubPath });
|
|
@@ -12987,7 +13169,7 @@ init_dist();
|
|
|
12987
13169
|
init_dist();
|
|
12988
13170
|
import { join as join24 } from "path";
|
|
12989
13171
|
import { homedir as homedir19 } from "os";
|
|
12990
|
-
import { existsSync as existsSync12, readFileSync as
|
|
13172
|
+
import { existsSync as existsSync12, readFileSync as readFileSync14 } from "fs";
|
|
12991
13173
|
import { execFile as execFile4 } from "child_process";
|
|
12992
13174
|
var DEFAULT_TIMEOUT_MS = 2e3;
|
|
12993
13175
|
var AGENT_CLIS = ["claude", "codex", "gemini", "opencode"];
|
|
@@ -13097,7 +13279,7 @@ function onPath(cli) {
|
|
|
13097
13279
|
return dirs.some((d) => existsSync12(join24(d, cli)));
|
|
13098
13280
|
}
|
|
13099
13281
|
function readSessionsHashes() {
|
|
13100
|
-
const raw = JSON.parse(
|
|
13282
|
+
const raw = JSON.parse(readFileSync14(SESSIONS_PATH, "utf-8"));
|
|
13101
13283
|
const hashes = Object.values(raw.workspaces ?? {}).map((w) => w.templateHash).filter((h) => typeof h === "string" && h.length > 0);
|
|
13102
13284
|
return [...new Set(hashes)];
|
|
13103
13285
|
}
|
|
@@ -14088,8 +14270,8 @@ init_dist3();
|
|
|
14088
14270
|
init_dist2();
|
|
14089
14271
|
import { Command as Command14 } from "commander";
|
|
14090
14272
|
import { execSync as execSync11 } from "child_process";
|
|
14091
|
-
import
|
|
14092
|
-
import
|
|
14273
|
+
import fs20 from "fs";
|
|
14274
|
+
import path25 from "path";
|
|
14093
14275
|
import os13 from "os";
|
|
14094
14276
|
import chalk15 from "chalk";
|
|
14095
14277
|
|
|
@@ -14168,8 +14350,8 @@ async function selectCaptainsInteractive(entries, yesterday = getYesterday()) {
|
|
|
14168
14350
|
// packages/cli/src/commands/launch.ts
|
|
14169
14351
|
init_dist2();
|
|
14170
14352
|
var CMUX_APP = "/Applications/cmux.app";
|
|
14171
|
-
var TEMPLATES_DIR4 =
|
|
14172
|
-
var SESSIONS_PATH2 =
|
|
14353
|
+
var TEMPLATES_DIR4 = path25.join(os13.homedir(), ".config", "squadrant", "templates");
|
|
14354
|
+
var SESSIONS_PATH2 = path25.join(os13.homedir(), ".config", "squadrant", "sessions.json");
|
|
14173
14355
|
function ensureCmuxReady(headless) {
|
|
14174
14356
|
if (headless || isInsideCmux()) return;
|
|
14175
14357
|
console.log(chalk15.yellow("\n Not running inside cmux. Opening cmux app...\n"));
|
|
@@ -14241,12 +14423,12 @@ var launchCommand = new Command14("launch").description(
|
|
|
14241
14423
|
}
|
|
14242
14424
|
if (opts.all) {
|
|
14243
14425
|
const hubPath = resolveHome(config.hubVault);
|
|
14244
|
-
|
|
14426
|
+
fs20.mkdirSync(hubPath, { recursive: true });
|
|
14245
14427
|
console.log(chalk15.bold("\nLaunching all captain workspaces\n"));
|
|
14246
14428
|
for (const [name, proj] of Object.entries(config.projects)) {
|
|
14247
14429
|
const projPath = resolveHome(proj.path);
|
|
14248
14430
|
const spokePath = resolveHome(proj.spokeVault);
|
|
14249
|
-
if (!
|
|
14431
|
+
if (!fs20.existsSync(spokePath)) {
|
|
14250
14432
|
const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(name, config);
|
|
14251
14433
|
await ensureSpokeLayout(spokeDriver);
|
|
14252
14434
|
console.log(chalk15.cyan(` \u2714 Created spoke vault at ${spokePath}`));
|
|
@@ -14284,7 +14466,7 @@ Launching ${selected.length} captain workspace(s) in parallel
|
|
|
14284
14466
|
const proj = config.projects[name];
|
|
14285
14467
|
const projPath = resolveHome(proj.path);
|
|
14286
14468
|
const spokePath = resolveHome(proj.spokeVault);
|
|
14287
|
-
if (!
|
|
14469
|
+
if (!fs20.existsSync(spokePath)) {
|
|
14288
14470
|
const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(name, config);
|
|
14289
14471
|
await ensureSpokeLayout(spokeDriver);
|
|
14290
14472
|
console.log(chalk15.cyan(` \u2714 Created spoke vault at ${spokePath}`));
|
|
@@ -14308,7 +14490,7 @@ Launching ${selected.length} captain workspace(s) in parallel
|
|
|
14308
14490
|
const proj = config.projects[project];
|
|
14309
14491
|
const projPath = resolveHome(proj.path);
|
|
14310
14492
|
const spokePath = resolveHome(proj.spokeVault);
|
|
14311
|
-
if (!
|
|
14493
|
+
if (!fs20.existsSync(spokePath)) {
|
|
14312
14494
|
const spokeDriver = new WorkspaceRegistry({ obsidian: createObsidianDriver }).forProject(project, config);
|
|
14313
14495
|
await ensureSpokeLayout(spokeDriver);
|
|
14314
14496
|
console.log(chalk15.cyan(` \u2714 Created spoke vault at ${spokePath}`));
|
|
@@ -14444,24 +14626,24 @@ Shutting down captain workspace for '${project}'...
|
|
|
14444
14626
|
// packages/cli/src/commands/feedback.ts
|
|
14445
14627
|
init_dist();
|
|
14446
14628
|
import { Command as Command16 } from "commander";
|
|
14447
|
-
import
|
|
14629
|
+
import fs21 from "fs";
|
|
14448
14630
|
import os14 from "os";
|
|
14449
|
-
import
|
|
14631
|
+
import path26 from "path";
|
|
14450
14632
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
14451
14633
|
import { execSync as execSync12 } from "child_process";
|
|
14452
14634
|
import chalk17 from "chalk";
|
|
14453
14635
|
var REPO_URL = "https://github.com/tu11aa/squadrant";
|
|
14454
14636
|
function readPkgVersion() {
|
|
14455
14637
|
try {
|
|
14456
|
-
const pkgPath =
|
|
14457
|
-
return JSON.parse(
|
|
14638
|
+
const pkgPath = path26.join(path26.dirname(fileURLToPath3(import.meta.url)), "..", "package.json");
|
|
14639
|
+
return JSON.parse(fs21.readFileSync(pkgPath, "utf-8")).version ?? "unknown";
|
|
14458
14640
|
} catch {
|
|
14459
14641
|
return "unknown";
|
|
14460
14642
|
}
|
|
14461
14643
|
}
|
|
14462
14644
|
function readMetrics(metricsPath) {
|
|
14463
14645
|
try {
|
|
14464
|
-
return JSON.parse(
|
|
14646
|
+
return JSON.parse(fs21.readFileSync(metricsPath, "utf-8"));
|
|
14465
14647
|
} catch {
|
|
14466
14648
|
return {};
|
|
14467
14649
|
}
|
|
@@ -14499,7 +14681,7 @@ function buildIssueUrl(metrics, squadrantVersion) {
|
|
|
14499
14681
|
}
|
|
14500
14682
|
var feedbackCommand = new Command16("feedback").description("Open a pre-filled GitHub issue for feedback or bug reports").action(() => {
|
|
14501
14683
|
const config = loadConfig();
|
|
14502
|
-
const metricsPath = config.metrics?.path ||
|
|
14684
|
+
const metricsPath = config.metrics?.path || path26.join(os14.homedir(), ".config", "squadrant", "metrics.json");
|
|
14503
14685
|
const metrics = readMetrics(metricsPath);
|
|
14504
14686
|
const version = readStamp(config) ?? readPkgVersion();
|
|
14505
14687
|
const issueUrl = buildIssueUrl(metrics, version);
|
|
@@ -14799,9 +14981,9 @@ workspaceCommand.command("read").description("Print the contents of a scope-rela
|
|
|
14799
14981
|
const config = loadConfig();
|
|
14800
14982
|
const registry = buildRegistry2();
|
|
14801
14983
|
try {
|
|
14802
|
-
const { projectTarget, path:
|
|
14984
|
+
const { projectTarget, path: path35 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
|
|
14803
14985
|
const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
|
|
14804
|
-
const content = await driver.read(
|
|
14986
|
+
const content = await driver.read(path35);
|
|
14805
14987
|
process.stdout.write(content);
|
|
14806
14988
|
} catch (err) {
|
|
14807
14989
|
console.error(chalk20.red(err.message));
|
|
@@ -14813,26 +14995,26 @@ workspaceCommand.command("write").description("Write content to a scope-relative
|
|
|
14813
14995
|
const registry = buildRegistry2();
|
|
14814
14996
|
try {
|
|
14815
14997
|
let projectTarget;
|
|
14816
|
-
let
|
|
14998
|
+
let path35;
|
|
14817
14999
|
let rawContent;
|
|
14818
15000
|
if (opts.hub) {
|
|
14819
15001
|
if (arg3 !== void 0) {
|
|
14820
15002
|
throw new Error("With --hub, pass only the path and content");
|
|
14821
15003
|
}
|
|
14822
15004
|
projectTarget = void 0;
|
|
14823
|
-
|
|
15005
|
+
path35 = arg1;
|
|
14824
15006
|
rawContent = arg2;
|
|
14825
15007
|
} else {
|
|
14826
15008
|
if (arg3 === void 0) {
|
|
14827
15009
|
throw new Error("Missing content \u2014 usage: <project> <path> <content>");
|
|
14828
15010
|
}
|
|
14829
15011
|
projectTarget = arg1;
|
|
14830
|
-
|
|
15012
|
+
path35 = arg2;
|
|
14831
15013
|
rawContent = arg3;
|
|
14832
15014
|
}
|
|
14833
15015
|
const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
|
|
14834
15016
|
const payload = rawContent === "-" ? await readStdin() : rawContent;
|
|
14835
|
-
await driver.write(
|
|
15017
|
+
await driver.write(path35, payload);
|
|
14836
15018
|
} catch (err) {
|
|
14837
15019
|
console.error(chalk20.red(err.message));
|
|
14838
15020
|
process.exit(1);
|
|
@@ -14842,9 +15024,9 @@ workspaceCommand.command("list").description("List entries in a scope-relative d
|
|
|
14842
15024
|
const config = loadConfig();
|
|
14843
15025
|
const registry = buildRegistry2();
|
|
14844
15026
|
try {
|
|
14845
|
-
const { projectTarget, path:
|
|
15027
|
+
const { projectTarget, path: path35 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
|
|
14846
15028
|
const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
|
|
14847
|
-
const entries = await driver.list(
|
|
15029
|
+
const entries = await driver.list(path35);
|
|
14848
15030
|
for (const entry of entries) console.log(entry);
|
|
14849
15031
|
} catch (err) {
|
|
14850
15032
|
console.error(chalk20.red(err.message));
|
|
@@ -14855,9 +15037,9 @@ workspaceCommand.command("exists").description("Exit 0 if path exists, 1 if not"
|
|
|
14855
15037
|
const config = loadConfig();
|
|
14856
15038
|
const registry = buildRegistry2();
|
|
14857
15039
|
try {
|
|
14858
|
-
const { projectTarget, path:
|
|
15040
|
+
const { projectTarget, path: path35 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
|
|
14859
15041
|
const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
|
|
14860
|
-
const ok2 = await driver.exists(
|
|
15042
|
+
const ok2 = await driver.exists(path35);
|
|
14861
15043
|
process.exit(ok2 ? 0 : 1);
|
|
14862
15044
|
} catch (err) {
|
|
14863
15045
|
console.error(chalk20.red(err.message));
|
|
@@ -14868,9 +15050,9 @@ workspaceCommand.command("mkdir").description("Recursively create a scope-relati
|
|
|
14868
15050
|
const config = loadConfig();
|
|
14869
15051
|
const registry = buildRegistry2();
|
|
14870
15052
|
try {
|
|
14871
|
-
const { projectTarget, path:
|
|
15053
|
+
const { projectTarget, path: path35 } = resolveTargetAndPath(arg1, arg2, !!opts.hub);
|
|
14872
15054
|
const driver = resolveDriver(registry, config, projectTarget, !!opts.hub);
|
|
14873
|
-
await driver.mkdir(
|
|
15055
|
+
await driver.mkdir(path35);
|
|
14874
15056
|
} catch (err) {
|
|
14875
15057
|
console.error(chalk20.red(err.message));
|
|
14876
15058
|
process.exit(1);
|
|
@@ -14909,8 +15091,8 @@ init_dist3();
|
|
|
14909
15091
|
init_dist();
|
|
14910
15092
|
import { Command as Command21 } from "commander";
|
|
14911
15093
|
import chalk22 from "chalk";
|
|
14912
|
-
import
|
|
14913
|
-
import
|
|
15094
|
+
import fs22 from "fs";
|
|
15095
|
+
import path27 from "path";
|
|
14914
15096
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
14915
15097
|
function parseScope(v) {
|
|
14916
15098
|
if (v !== "user" && v !== "project") {
|
|
@@ -14919,10 +15101,10 @@ function parseScope(v) {
|
|
|
14919
15101
|
return v;
|
|
14920
15102
|
}
|
|
14921
15103
|
function findPackageRoot3() {
|
|
14922
|
-
let dir =
|
|
15104
|
+
let dir = path27.dirname(fileURLToPath4(import.meta.url));
|
|
14923
15105
|
while (dir !== "/" && dir !== "") {
|
|
14924
|
-
if (
|
|
14925
|
-
dir =
|
|
15106
|
+
if (fs22.existsSync(path27.join(dir, "package.json"))) return dir;
|
|
15107
|
+
dir = path27.dirname(dir);
|
|
14926
15108
|
}
|
|
14927
15109
|
return process.cwd();
|
|
14928
15110
|
}
|
|
@@ -15117,12 +15299,12 @@ init_dist();
|
|
|
15117
15299
|
init_dist();
|
|
15118
15300
|
init_dist2();
|
|
15119
15301
|
import { Command as Command23 } from "commander";
|
|
15120
|
-
import
|
|
15302
|
+
import fs23 from "fs";
|
|
15121
15303
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
15122
|
-
import { dirname as
|
|
15304
|
+
import { dirname as dirname5, join as join26 } from "path";
|
|
15123
15305
|
import chalk23 from "chalk";
|
|
15124
15306
|
function runConfigCheck(opts) {
|
|
15125
|
-
const raw = JSON.parse(
|
|
15307
|
+
const raw = JSON.parse(fs23.readFileSync(opts.configPath, "utf-8"));
|
|
15126
15308
|
const def = getDefaultConfig();
|
|
15127
15309
|
const items = detectDrift(raw, def);
|
|
15128
15310
|
let working = raw;
|
|
@@ -15139,7 +15321,7 @@ function runConfigCheck(opts) {
|
|
|
15139
15321
|
stamped = true;
|
|
15140
15322
|
}
|
|
15141
15323
|
if (opts.fix || opts.accept || stamped) {
|
|
15142
|
-
|
|
15324
|
+
writeConfigFileSync(opts.configPath, JSON.stringify(working, null, 2) + "\n");
|
|
15143
15325
|
}
|
|
15144
15326
|
return { items, applied, remaining, stamped };
|
|
15145
15327
|
}
|
|
@@ -15210,7 +15392,7 @@ function printItems(items) {
|
|
|
15210
15392
|
var configCommand = new Command23("config").description("Inspect and reconcile squadrant config");
|
|
15211
15393
|
configCommand.command("check").description("Detect config drift vs the current default schema").option("--fix", "Apply the safe tier (add missing, remove deprecated)", false).option("--accept", "Stamp the current version without changing config (dismiss advisories)", false).option("--json", "Output drift items as JSON", false).action((opts) => {
|
|
15212
15394
|
const pkgVersion = readPkgVersion2();
|
|
15213
|
-
if (!
|
|
15395
|
+
if (!fs23.existsSync(DEFAULT_CONFIG_PATH)) {
|
|
15214
15396
|
console.log(chalk23.yellow("No config found \u2014 run `squadrant init` first."));
|
|
15215
15397
|
return;
|
|
15216
15398
|
}
|
|
@@ -15255,8 +15437,8 @@ configCommand.command("set").description("Write a config value by dotted key (e.
|
|
|
15255
15437
|
}
|
|
15256
15438
|
});
|
|
15257
15439
|
function readPkgVersion2() {
|
|
15258
|
-
const pkgPath = join26(
|
|
15259
|
-
return JSON.parse(
|
|
15440
|
+
const pkgPath = join26(dirname5(fileURLToPath5(import.meta.url)), "..", "package.json");
|
|
15441
|
+
return JSON.parse(fs23.readFileSync(pkgPath, "utf-8")).version;
|
|
15260
15442
|
}
|
|
15261
15443
|
|
|
15262
15444
|
// packages/cli/src/commands/heal.ts
|
|
@@ -15280,6 +15462,15 @@ function buildHealStatus(components) {
|
|
|
15280
15462
|
}
|
|
15281
15463
|
async function runHealStatus(opts) {
|
|
15282
15464
|
const { project, json, stdout, stderr } = opts;
|
|
15465
|
+
const isDaemonAlive = opts.isDaemonAlive ?? (() => isDaemonSocketLive(SOCK));
|
|
15466
|
+
if (!await isDaemonAlive()) {
|
|
15467
|
+
if (json) {
|
|
15468
|
+
stdout.write(JSON.stringify({ healthy: false, daemonUnreachable: true, components: [] }) + "\n");
|
|
15469
|
+
} else {
|
|
15470
|
+
stderr.write("daemon unreachable \u2014 start the daemon first (squadrant heal daemon)\n");
|
|
15471
|
+
}
|
|
15472
|
+
return 1;
|
|
15473
|
+
}
|
|
15283
15474
|
let rows;
|
|
15284
15475
|
try {
|
|
15285
15476
|
rows = await opts.queryHealth(project);
|
|
@@ -15411,7 +15602,7 @@ init_dist();
|
|
|
15411
15602
|
init_dist2();
|
|
15412
15603
|
init_runtime2();
|
|
15413
15604
|
init_require_daemon();
|
|
15414
|
-
import { join as join27, dirname as
|
|
15605
|
+
import { join as join27, dirname as dirname6 } from "path";
|
|
15415
15606
|
import { Command as Command27 } from "commander";
|
|
15416
15607
|
import chalk27 from "chalk";
|
|
15417
15608
|
async function runPing(project, message) {
|
|
@@ -15420,7 +15611,7 @@ async function runPing(project, message) {
|
|
|
15420
15611
|
const resolved = resolveTarget(registry, config, project, false);
|
|
15421
15612
|
await requireDaemon();
|
|
15422
15613
|
await needRef(resolved);
|
|
15423
|
-
const stateRoot = join27(
|
|
15614
|
+
const stateRoot = join27(dirname6(DEFAULT_CONFIG_PATH), "state");
|
|
15424
15615
|
await appendCaptainMessage({
|
|
15425
15616
|
stateRoot,
|
|
15426
15617
|
project,
|
|
@@ -15497,8 +15688,8 @@ var cmuxCommand = new Command28("cmux").description("cmux integration helpers").
|
|
|
15497
15688
|
// packages/cli/src/commands/effort.ts
|
|
15498
15689
|
init_dist();
|
|
15499
15690
|
init_dist2();
|
|
15500
|
-
import
|
|
15501
|
-
import
|
|
15691
|
+
import fs24 from "fs";
|
|
15692
|
+
import path28 from "path";
|
|
15502
15693
|
import { Command as Command29 } from "commander";
|
|
15503
15694
|
import chalk29 from "chalk";
|
|
15504
15695
|
var VALID_EFFORTS = ["max", "balance", "low"];
|
|
@@ -15541,9 +15732,9 @@ function effortScopeLabel(projectName) {
|
|
|
15541
15732
|
}
|
|
15542
15733
|
function canonical(p) {
|
|
15543
15734
|
try {
|
|
15544
|
-
return
|
|
15735
|
+
return fs24.realpathSync(p);
|
|
15545
15736
|
} catch {
|
|
15546
|
-
return
|
|
15737
|
+
return path28.resolve(p);
|
|
15547
15738
|
}
|
|
15548
15739
|
}
|
|
15549
15740
|
async function notifyCaptainsOfEffort(effort, config, driver, cwd = process.cwd(), append, scopeProject, projectConfigRoot) {
|
|
@@ -15593,7 +15784,7 @@ var effortCommand = new Command29("effort").description("Get or set the crew tok
|
|
|
15593
15784
|
const config = loadConfig();
|
|
15594
15785
|
const registry = new RuntimeRegistry2({ cmux: createCmuxDriver2() });
|
|
15595
15786
|
const driver = registry.global(config);
|
|
15596
|
-
const stateRoot =
|
|
15787
|
+
const stateRoot = path28.join(path28.dirname(DEFAULT_CONFIG_PATH), "state");
|
|
15597
15788
|
const append = (project, text) => appendCaptainMessage({ stateRoot, project, text, source: "daemon" });
|
|
15598
15789
|
await notifyCaptainsOfEffort(effort, config, driver, process.cwd(), append, options.project);
|
|
15599
15790
|
} catch {
|
|
@@ -15603,13 +15794,13 @@ var effortCommand = new Command29("effort").description("Get or set the crew tok
|
|
|
15603
15794
|
|
|
15604
15795
|
// packages/cli/src/commands/tokens.ts
|
|
15605
15796
|
init_dist();
|
|
15606
|
-
import
|
|
15607
|
-
import
|
|
15797
|
+
import fs25 from "fs";
|
|
15798
|
+
import path29 from "path";
|
|
15608
15799
|
import os15 from "os";
|
|
15609
15800
|
import readline3 from "readline";
|
|
15610
15801
|
import { Command as Command30 } from "commander";
|
|
15611
15802
|
import chalk30 from "chalk";
|
|
15612
|
-
var CLAUDE_PROJECTS_DIR =
|
|
15803
|
+
var CLAUDE_PROJECTS_DIR = path29.join(os15.homedir(), ".claude", "projects");
|
|
15613
15804
|
function parseTranscriptLine(rawLine) {
|
|
15614
15805
|
const line = rawLine.trim();
|
|
15615
15806
|
if (!line) return { timestamp: null, usage: null };
|
|
@@ -15659,7 +15850,7 @@ function foldTranscriptLine(agg, rawLine, state) {
|
|
|
15659
15850
|
async function aggregateTranscriptFile(filePath) {
|
|
15660
15851
|
const agg = emptySessionAggregate();
|
|
15661
15852
|
const state = { lastCacheRead: null };
|
|
15662
|
-
const rl = readline3.createInterface({ input:
|
|
15853
|
+
const rl = readline3.createInterface({ input: fs25.createReadStream(filePath), crlfDelay: Infinity });
|
|
15663
15854
|
for await (const line of rl) {
|
|
15664
15855
|
foldTranscriptLine(agg, line, state);
|
|
15665
15856
|
}
|
|
@@ -15727,22 +15918,22 @@ function buildRoleReport(role, sessions) {
|
|
|
15727
15918
|
}
|
|
15728
15919
|
async function readdirSafe(dir) {
|
|
15729
15920
|
try {
|
|
15730
|
-
return await
|
|
15921
|
+
return await fs25.promises.readdir(dir);
|
|
15731
15922
|
} catch {
|
|
15732
15923
|
return [];
|
|
15733
15924
|
}
|
|
15734
15925
|
}
|
|
15735
15926
|
async function listJsonlFiles(dir) {
|
|
15736
15927
|
const entries = await readdirSafe(dir);
|
|
15737
|
-
return entries.filter((e) => e.endsWith(".jsonl")).map((e) =>
|
|
15928
|
+
return entries.filter((e) => e.endsWith(".jsonl")).map((e) => path29.join(dir, e));
|
|
15738
15929
|
}
|
|
15739
15930
|
async function findTranscriptDirs(claudeProjectsDir, captainSlug) {
|
|
15740
15931
|
const entries = await readdirSafe(claudeProjectsDir);
|
|
15741
15932
|
const captainDirs = [];
|
|
15742
15933
|
const crewDirs = [];
|
|
15743
15934
|
for (const entry of entries) {
|
|
15744
|
-
if (entry === captainSlug) captainDirs.push(
|
|
15745
|
-
else if (isCrewDirName(entry, captainSlug)) crewDirs.push(
|
|
15935
|
+
if (entry === captainSlug) captainDirs.push(path29.join(claudeProjectsDir, entry));
|
|
15936
|
+
else if (isCrewDirName(entry, captainSlug)) crewDirs.push(path29.join(claudeProjectsDir, entry));
|
|
15746
15937
|
}
|
|
15747
15938
|
return { captainDirs, crewDirs };
|
|
15748
15939
|
}
|
|
@@ -15894,12 +16085,12 @@ var tokensCommand = new Command30("tokens").description(
|
|
|
15894
16085
|
// packages/cli/src/commands/telegram.ts
|
|
15895
16086
|
init_dist();
|
|
15896
16087
|
init_dist2();
|
|
15897
|
-
import { join as join28, dirname as
|
|
16088
|
+
import { join as join28, dirname as dirname7 } from "path";
|
|
15898
16089
|
import { emitKeypressEvents } from "readline";
|
|
15899
16090
|
import { Command as Command31 } from "commander";
|
|
15900
16091
|
import chalk31 from "chalk";
|
|
15901
16092
|
function defaultStateRoot() {
|
|
15902
|
-
return join28(
|
|
16093
|
+
return join28(dirname7(DEFAULT_CONFIG_PATH), "state");
|
|
15903
16094
|
}
|
|
15904
16095
|
async function questionMasked() {
|
|
15905
16096
|
return new Promise((resolve4) => {
|
|
@@ -16229,8 +16420,8 @@ import { join as join29 } from "path";
|
|
|
16229
16420
|
import { homedir as homedir21 } from "os";
|
|
16230
16421
|
|
|
16231
16422
|
// packages/cli/src/lib/captain-session-registry.ts
|
|
16232
|
-
import
|
|
16233
|
-
import
|
|
16423
|
+
import fs26 from "fs";
|
|
16424
|
+
import path30 from "path";
|
|
16234
16425
|
|
|
16235
16426
|
// packages/cli/src/lib/handoff-facts.ts
|
|
16236
16427
|
var STALE_FETCH_WARNING_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -16281,15 +16472,15 @@ function assembleHandoffFacts(live, claudeMem, gapSessions, checkpoint, now, ext
|
|
|
16281
16472
|
// packages/cli/src/lib/captain-session-registry.ts
|
|
16282
16473
|
var CAPTAIN_SESSION_REGISTRY_FILE = "captain-sessions.jsonl";
|
|
16283
16474
|
function appendCaptainSession(spokeVault, record) {
|
|
16284
|
-
|
|
16285
|
-
const file =
|
|
16286
|
-
|
|
16475
|
+
fs26.mkdirSync(spokeVault, { recursive: true });
|
|
16476
|
+
const file = path30.join(spokeVault, CAPTAIN_SESSION_REGISTRY_FILE);
|
|
16477
|
+
fs26.appendFileSync(file, JSON.stringify(record) + "\n");
|
|
16287
16478
|
}
|
|
16288
16479
|
function readCaptainSessionRegistry(spokeVault) {
|
|
16289
|
-
const file =
|
|
16290
|
-
if (!
|
|
16480
|
+
const file = path30.join(spokeVault, CAPTAIN_SESSION_REGISTRY_FILE);
|
|
16481
|
+
if (!fs26.existsSync(file)) return [];
|
|
16291
16482
|
const records = [];
|
|
16292
|
-
for (const line of
|
|
16483
|
+
for (const line of fs26.readFileSync(file, "utf-8").split("\n")) {
|
|
16293
16484
|
if (!line.trim()) continue;
|
|
16294
16485
|
try {
|
|
16295
16486
|
records.push(JSON.parse(line));
|
|
@@ -16392,13 +16583,13 @@ function hooksCommand() {
|
|
|
16392
16583
|
// packages/cli/src/commands/work.ts
|
|
16393
16584
|
init_dist();
|
|
16394
16585
|
init_dist2();
|
|
16395
|
-
import
|
|
16586
|
+
import path31 from "path";
|
|
16396
16587
|
import { Command as Command33 } from "commander";
|
|
16397
16588
|
import chalk32 from "chalk";
|
|
16398
16589
|
function detectCurrentProject(config, cwd = process.cwd()) {
|
|
16399
16590
|
for (const [name, proj] of Object.entries(config.projects)) {
|
|
16400
16591
|
const projPath = resolveHome(proj.path);
|
|
16401
|
-
if (cwd === projPath || cwd.startsWith(projPath +
|
|
16592
|
+
if (cwd === projPath || cwd.startsWith(projPath + path31.sep)) return name;
|
|
16402
16593
|
}
|
|
16403
16594
|
return void 0;
|
|
16404
16595
|
}
|
|
@@ -16530,14 +16721,14 @@ var workCommand = new Command33("work").description("Track your own in-flight wo
|
|
|
16530
16721
|
// packages/cli/src/commands/handoff.ts
|
|
16531
16722
|
init_dist();
|
|
16532
16723
|
import { Command as Command34 } from "commander";
|
|
16533
|
-
import
|
|
16724
|
+
import path34 from "path";
|
|
16534
16725
|
import os16 from "os";
|
|
16535
16726
|
|
|
16536
16727
|
// packages/cli/src/lib/handoff-live-repo.ts
|
|
16537
16728
|
init_dist();
|
|
16538
16729
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
16539
|
-
import
|
|
16540
|
-
import
|
|
16730
|
+
import fs27 from "fs";
|
|
16731
|
+
import path32 from "path";
|
|
16541
16732
|
|
|
16542
16733
|
// packages/cli/src/lib/handoff-branch-state.ts
|
|
16543
16734
|
function tryRun(runner, cmd, args, cwd) {
|
|
@@ -16676,7 +16867,7 @@ function localAheadOfBase(runner, projectPath, base) {
|
|
|
16676
16867
|
}
|
|
16677
16868
|
function readFetchAgeMs(projectPath, now) {
|
|
16678
16869
|
try {
|
|
16679
|
-
const stat2 =
|
|
16870
|
+
const stat2 = fs27.statSync(path32.join(projectPath, ".git", "FETCH_HEAD"));
|
|
16680
16871
|
return Math.max(0, now - stat2.mtime.getTime());
|
|
16681
16872
|
} catch {
|
|
16682
16873
|
return null;
|
|
@@ -16747,7 +16938,7 @@ function gatherLiveRepoState(projectPath, fallbackBaseBranch, tasks, runner = de
|
|
|
16747
16938
|
|
|
16748
16939
|
// packages/cli/src/lib/handoff-claude-mem.ts
|
|
16749
16940
|
import { createRequire } from "module";
|
|
16750
|
-
import
|
|
16941
|
+
import fs28 from "fs";
|
|
16751
16942
|
var { DatabaseSync } = createRequire(import.meta.url)("node:sqlite");
|
|
16752
16943
|
var CLAUDE_MEM_RECENCY_LIMIT = 20;
|
|
16753
16944
|
function decisionText(row) {
|
|
@@ -16761,7 +16952,7 @@ function decisionText(row) {
|
|
|
16761
16952
|
return row.narrative ?? "";
|
|
16762
16953
|
}
|
|
16763
16954
|
function queryClaudeMem(dbPath, project) {
|
|
16764
|
-
if (!
|
|
16955
|
+
if (!fs28.existsSync(dbPath)) return null;
|
|
16765
16956
|
let db;
|
|
16766
16957
|
try {
|
|
16767
16958
|
db = new DatabaseSync(dbPath, { readOnly: true });
|
|
@@ -16804,7 +16995,7 @@ function queryClaudeMem(dbPath, project) {
|
|
|
16804
16995
|
}
|
|
16805
16996
|
|
|
16806
16997
|
// packages/cli/src/lib/handoff-transcript.ts
|
|
16807
|
-
import
|
|
16998
|
+
import fs29 from "fs";
|
|
16808
16999
|
var TRANSCRIPT_BYTE_CAP = 2e5;
|
|
16809
17000
|
function tailOf(content, byteCap) {
|
|
16810
17001
|
const buf = Buffer.from(content, "utf-8");
|
|
@@ -16833,27 +17024,27 @@ function extractMessages(tailText) {
|
|
|
16833
17024
|
return { lastUserMessage, lastAssistantText };
|
|
16834
17025
|
}
|
|
16835
17026
|
function extractTranscriptTail(transcriptPath, byteCap = TRANSCRIPT_BYTE_CAP) {
|
|
16836
|
-
if (!
|
|
16837
|
-
const content =
|
|
17027
|
+
if (!fs29.existsSync(transcriptPath)) return null;
|
|
17028
|
+
const content = fs29.readFileSync(transcriptPath, "utf-8");
|
|
16838
17029
|
const { lastUserMessage, lastAssistantText } = extractMessages(tailOf(content, byteCap));
|
|
16839
|
-
const mtimeIso =
|
|
17030
|
+
const mtimeIso = fs29.statSync(transcriptPath).mtime.toISOString();
|
|
16840
17031
|
return { path: transcriptPath, mtimeIso, lastUserMessage, lastAssistantText };
|
|
16841
17032
|
}
|
|
16842
17033
|
|
|
16843
17034
|
// packages/cli/src/lib/handoff-archive.ts
|
|
16844
|
-
import
|
|
16845
|
-
import
|
|
17035
|
+
import fs30 from "fs";
|
|
17036
|
+
import path33 from "path";
|
|
16846
17037
|
function readNewestArchivedHandoff(spokeVault, now) {
|
|
16847
|
-
const dir =
|
|
16848
|
-
if (!
|
|
16849
|
-
const candidates =
|
|
16850
|
-
const full =
|
|
16851
|
-
return { name: e.name, full, mtime:
|
|
17038
|
+
const dir = path33.join(spokeVault, "handoffs");
|
|
17039
|
+
if (!fs30.existsSync(dir)) return null;
|
|
17040
|
+
const candidates = fs30.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".json")).map((e) => {
|
|
17041
|
+
const full = path33.join(dir, e.name);
|
|
17042
|
+
return { name: e.name, full, mtime: fs30.statSync(full).mtime };
|
|
16852
17043
|
}).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
16853
17044
|
for (const candidate of candidates) {
|
|
16854
17045
|
let content;
|
|
16855
17046
|
try {
|
|
16856
|
-
content = JSON.parse(
|
|
17047
|
+
content = JSON.parse(fs30.readFileSync(candidate.full, "utf-8"));
|
|
16857
17048
|
} catch {
|
|
16858
17049
|
continue;
|
|
16859
17050
|
}
|
|
@@ -16863,7 +17054,7 @@ function readNewestArchivedHandoff(spokeVault, now) {
|
|
|
16863
17054
|
}
|
|
16864
17055
|
|
|
16865
17056
|
// packages/cli/src/commands/handoff.ts
|
|
16866
|
-
var CLAUDE_MEM_DB_PATH =
|
|
17057
|
+
var CLAUDE_MEM_DB_PATH = path34.join(os16.homedir(), ".claude-mem", "claude-mem.db");
|
|
16867
17058
|
async function defaultFetchTasks(project) {
|
|
16868
17059
|
return await squadrantdCall({ kind: "list", project });
|
|
16869
17060
|
}
|
|
@@ -16922,8 +17113,8 @@ init_dist();
|
|
|
16922
17113
|
init_dist();
|
|
16923
17114
|
init_dist();
|
|
16924
17115
|
init_dist();
|
|
16925
|
-
var __dirname =
|
|
16926
|
-
var pkg = JSON.parse(
|
|
17116
|
+
var __dirname = dirname8(fileURLToPath6(import.meta.url));
|
|
17117
|
+
var pkg = JSON.parse(readFileSync15(join30(__dirname, "..", "package.json"), "utf-8"));
|
|
16927
17118
|
ensureRuntimeSynced({
|
|
16928
17119
|
sourceRoot: join30(__dirname, ".."),
|
|
16929
17120
|
runtimeRoot: join30(homedir22(), ".config", "squadrant")
|
|
@@ -16932,11 +17123,11 @@ if (process.argv[2] !== "config") {
|
|
|
16932
17123
|
try {
|
|
16933
17124
|
const cfgPath = join30(homedir22(), ".config", "squadrant", "config.json");
|
|
16934
17125
|
if (existsSync13(cfgPath)) {
|
|
16935
|
-
const cfg = JSON.parse(
|
|
17126
|
+
const cfg = JSON.parse(readConfigFileSync(cfgPath));
|
|
16936
17127
|
if (needsCheck(cfg, pkg.version)) {
|
|
16937
17128
|
const items = detectDrift(cfg, getDefaultConfig());
|
|
16938
17129
|
if (items.length === 0) {
|
|
16939
|
-
|
|
17130
|
+
writeConfigFileSync(cfgPath, JSON.stringify(withStamp(cfg, pkg.version), null, 2) + "\n");
|
|
16940
17131
|
} else {
|
|
16941
17132
|
const from = cfg._squadrantVersion ?? "an earlier version";
|
|
16942
17133
|
process.stderr.write(
|