squads-cli 0.4.7 → 0.4.9
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/{chunk-EGOVJOZJ.js → chunk-HIQ2APYR.js} +13 -227
- package/dist/chunk-HIQ2APYR.js.map +1 -0
- package/dist/chunk-HKWCBCEK.js +225 -0
- package/dist/chunk-HKWCBCEK.js.map +1 -0
- package/dist/chunk-NA3IECJA.js +288 -0
- package/dist/chunk-NA3IECJA.js.map +1 -0
- package/dist/cli.js +261 -418
- package/dist/cli.js.map +1 -1
- package/dist/{sessions-SEITSWEV.js → sessions-R4VWIGFR.js} +3 -2
- package/dist/terminal-JZSAQSN7.js +53 -0
- package/dist/terminal-JZSAQSN7.js.map +1 -0
- package/dist/update-MAY6EXFQ.js +17 -0
- package/dist/update-MAY6EXFQ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-EGOVJOZJ.js.map +0 -1
- /package/dist/{sessions-SEITSWEV.js.map → sessions-R4VWIGFR.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
autoUpdateOnStartup,
|
|
4
|
+
checkForUpdate,
|
|
5
|
+
performUpdate,
|
|
6
|
+
refreshVersionCache
|
|
7
|
+
} from "./chunk-HKWCBCEK.js";
|
|
2
8
|
import {
|
|
3
9
|
appendToMemory,
|
|
4
10
|
findMemoryDir,
|
|
@@ -6,38 +12,40 @@ import {
|
|
|
6
12
|
listMemoryEntries,
|
|
7
13
|
searchMemory
|
|
8
14
|
} from "./chunk-FUHBEL3L.js";
|
|
15
|
+
import {
|
|
16
|
+
cleanupStaleSessions,
|
|
17
|
+
detectSquad,
|
|
18
|
+
getLiveSessionSummaryAsync,
|
|
19
|
+
sessionsCommand,
|
|
20
|
+
sessionsHistoryCommand,
|
|
21
|
+
sessionsSummaryCommand,
|
|
22
|
+
startSession,
|
|
23
|
+
stopSession,
|
|
24
|
+
updateHeartbeat
|
|
25
|
+
} from "./chunk-HIQ2APYR.js";
|
|
9
26
|
import {
|
|
10
27
|
RESET,
|
|
11
28
|
barChart,
|
|
12
29
|
bold,
|
|
13
30
|
box,
|
|
14
|
-
cleanupStaleSessions,
|
|
15
31
|
colors,
|
|
16
|
-
detectSquad,
|
|
17
|
-
getLiveSessionSummaryAsync,
|
|
18
32
|
gradient,
|
|
19
33
|
icons,
|
|
20
34
|
padEnd,
|
|
21
35
|
progressBar,
|
|
22
|
-
sessionsCommand,
|
|
23
|
-
sessionsHistoryCommand,
|
|
24
|
-
sessionsSummaryCommand,
|
|
25
36
|
sparkline,
|
|
26
|
-
startSession,
|
|
27
|
-
stopSession,
|
|
28
37
|
truncate,
|
|
29
|
-
updateHeartbeat,
|
|
30
38
|
writeLine
|
|
31
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-NA3IECJA.js";
|
|
32
40
|
import {
|
|
33
41
|
__require
|
|
34
42
|
} from "./chunk-7OCVIDC7.js";
|
|
35
43
|
|
|
36
44
|
// src/cli.ts
|
|
37
45
|
import { config } from "dotenv";
|
|
38
|
-
import { existsSync as
|
|
39
|
-
import { join as
|
|
40
|
-
import { homedir as
|
|
46
|
+
import { existsSync as existsSync18 } from "fs";
|
|
47
|
+
import { join as join20 } from "path";
|
|
48
|
+
import { homedir as homedir4 } from "os";
|
|
41
49
|
import { Command } from "commander";
|
|
42
50
|
import chalk4 from "chalk";
|
|
43
51
|
|
|
@@ -2357,160 +2365,8 @@ async function listCommand(options) {
|
|
|
2357
2365
|
}
|
|
2358
2366
|
|
|
2359
2367
|
// src/commands/status.ts
|
|
2360
|
-
import { existsSync as
|
|
2361
|
-
import { join as
|
|
2362
|
-
|
|
2363
|
-
// src/lib/update.ts
|
|
2364
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, unlinkSync } from "fs";
|
|
2365
|
-
import { join as join5, dirname as dirname2 } from "path";
|
|
2366
|
-
import { homedir as homedir2 } from "os";
|
|
2367
|
-
import { execSync as execSync3 } from "child_process";
|
|
2368
|
-
import { fileURLToPath } from "url";
|
|
2369
|
-
function getPackageVersion() {
|
|
2370
|
-
try {
|
|
2371
|
-
const __filename3 = fileURLToPath(import.meta.url);
|
|
2372
|
-
const __dirname3 = dirname2(__filename3);
|
|
2373
|
-
const possiblePaths = [
|
|
2374
|
-
join5(__dirname3, "..", "..", "package.json"),
|
|
2375
|
-
// From dist/lib/
|
|
2376
|
-
join5(__dirname3, "..", "package.json"),
|
|
2377
|
-
// From dist/
|
|
2378
|
-
join5(__dirname3, "package.json")
|
|
2379
|
-
// Same dir
|
|
2380
|
-
];
|
|
2381
|
-
for (const pkgPath of possiblePaths) {
|
|
2382
|
-
if (existsSync5(pkgPath)) {
|
|
2383
|
-
const pkg2 = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
2384
|
-
return pkg2.version || "0.0.0";
|
|
2385
|
-
}
|
|
2386
|
-
}
|
|
2387
|
-
} catch {
|
|
2388
|
-
}
|
|
2389
|
-
return "0.0.0";
|
|
2390
|
-
}
|
|
2391
|
-
var CURRENT_VERSION = getPackageVersion();
|
|
2392
|
-
var CACHE_DIR = join5(homedir2(), ".squads");
|
|
2393
|
-
var CACHE_FILE = join5(CACHE_DIR, "update-check.json");
|
|
2394
|
-
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2395
|
-
function isNewerVersion(v1, v2) {
|
|
2396
|
-
const parts1 = v1.replace(/^v/, "").split(".").map(Number);
|
|
2397
|
-
const parts2 = v2.replace(/^v/, "").split(".").map(Number);
|
|
2398
|
-
for (let i = 0; i < 3; i++) {
|
|
2399
|
-
const p1 = parts1[i] || 0;
|
|
2400
|
-
const p2 = parts2[i] || 0;
|
|
2401
|
-
if (p2 > p1) return true;
|
|
2402
|
-
if (p2 < p1) return false;
|
|
2403
|
-
}
|
|
2404
|
-
return false;
|
|
2405
|
-
}
|
|
2406
|
-
function readCache() {
|
|
2407
|
-
try {
|
|
2408
|
-
if (!existsSync5(CACHE_FILE)) return null;
|
|
2409
|
-
const data = JSON.parse(readFileSync4(CACHE_FILE, "utf-8"));
|
|
2410
|
-
return data;
|
|
2411
|
-
} catch {
|
|
2412
|
-
return null;
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
function writeCache(latestVersion) {
|
|
2416
|
-
try {
|
|
2417
|
-
if (!existsSync5(CACHE_DIR)) {
|
|
2418
|
-
mkdirSync3(CACHE_DIR, { recursive: true });
|
|
2419
|
-
}
|
|
2420
|
-
const cache = {
|
|
2421
|
-
latestVersion,
|
|
2422
|
-
checkedAt: Date.now()
|
|
2423
|
-
};
|
|
2424
|
-
writeFileSync4(CACHE_FILE, JSON.stringify(cache, null, 2));
|
|
2425
|
-
} catch {
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
function fetchLatestVersion() {
|
|
2429
|
-
try {
|
|
2430
|
-
const result = execSync3("npm view squads-cli version 2>/dev/null", {
|
|
2431
|
-
encoding: "utf-8",
|
|
2432
|
-
timeout: 5e3
|
|
2433
|
-
}).trim();
|
|
2434
|
-
return result || null;
|
|
2435
|
-
} catch {
|
|
2436
|
-
return null;
|
|
2437
|
-
}
|
|
2438
|
-
}
|
|
2439
|
-
function checkForUpdate() {
|
|
2440
|
-
const result = {
|
|
2441
|
-
currentVersion: CURRENT_VERSION,
|
|
2442
|
-
latestVersion: CURRENT_VERSION,
|
|
2443
|
-
updateAvailable: false
|
|
2444
|
-
};
|
|
2445
|
-
const cache = readCache();
|
|
2446
|
-
const now = Date.now();
|
|
2447
|
-
if (cache) {
|
|
2448
|
-
result.latestVersion = cache.latestVersion;
|
|
2449
|
-
result.updateAvailable = isNewerVersion(CURRENT_VERSION, cache.latestVersion);
|
|
2450
|
-
if (now - cache.checkedAt >= CACHE_TTL_MS) {
|
|
2451
|
-
triggerBackgroundRefresh();
|
|
2452
|
-
}
|
|
2453
|
-
return result;
|
|
2454
|
-
}
|
|
2455
|
-
triggerBackgroundRefresh();
|
|
2456
|
-
return result;
|
|
2457
|
-
}
|
|
2458
|
-
function triggerBackgroundRefresh() {
|
|
2459
|
-
try {
|
|
2460
|
-
const { spawn: spawn8 } = __require("child_process");
|
|
2461
|
-
const child = spawn8("npm", ["view", "squads-cli", "version"], {
|
|
2462
|
-
detached: true,
|
|
2463
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
2464
|
-
shell: true
|
|
2465
|
-
});
|
|
2466
|
-
let output = "";
|
|
2467
|
-
child.stdout?.on("data", (data) => {
|
|
2468
|
-
output += data.toString();
|
|
2469
|
-
});
|
|
2470
|
-
child.on("close", () => {
|
|
2471
|
-
const version2 = output.trim();
|
|
2472
|
-
if (version2 && /^\d+\.\d+\.\d+/.test(version2)) {
|
|
2473
|
-
writeCache(version2);
|
|
2474
|
-
}
|
|
2475
|
-
});
|
|
2476
|
-
child.unref();
|
|
2477
|
-
} catch {
|
|
2478
|
-
}
|
|
2479
|
-
}
|
|
2480
|
-
function performUpdate() {
|
|
2481
|
-
try {
|
|
2482
|
-
execSync3("npm update -g squads-cli", {
|
|
2483
|
-
encoding: "utf-8",
|
|
2484
|
-
stdio: "inherit",
|
|
2485
|
-
timeout: 12e4
|
|
2486
|
-
// 2 minutes
|
|
2487
|
-
});
|
|
2488
|
-
try {
|
|
2489
|
-
unlinkSync(CACHE_FILE);
|
|
2490
|
-
} catch {
|
|
2491
|
-
}
|
|
2492
|
-
return { success: true };
|
|
2493
|
-
} catch (err) {
|
|
2494
|
-
return {
|
|
2495
|
-
success: false,
|
|
2496
|
-
error: err instanceof Error ? err.message : "Unknown error"
|
|
2497
|
-
};
|
|
2498
|
-
}
|
|
2499
|
-
}
|
|
2500
|
-
function refreshVersionCache() {
|
|
2501
|
-
const latestVersion = fetchLatestVersion();
|
|
2502
|
-
if (latestVersion) {
|
|
2503
|
-
writeCache(latestVersion);
|
|
2504
|
-
return {
|
|
2505
|
-
currentVersion: CURRENT_VERSION,
|
|
2506
|
-
latestVersion,
|
|
2507
|
-
updateAvailable: isNewerVersion(CURRENT_VERSION, latestVersion)
|
|
2508
|
-
};
|
|
2509
|
-
}
|
|
2510
|
-
return checkForUpdate();
|
|
2511
|
-
}
|
|
2512
|
-
|
|
2513
|
-
// src/commands/status.ts
|
|
2368
|
+
import { existsSync as existsSync5, statSync } from "fs";
|
|
2369
|
+
import { join as join5 } from "path";
|
|
2514
2370
|
async function statusCommand(squadName, options = {}) {
|
|
2515
2371
|
await track(Events.CLI_STATUS, { squad: squadName || "all", verbose: options.verbose });
|
|
2516
2372
|
const squadsDir = findSquadsDir();
|
|
@@ -2563,8 +2419,8 @@ async function showOverallStatus(squadsDir, _options) {
|
|
|
2563
2419
|
let lastActivity = `${colors.dim}\u2014${RESET}`;
|
|
2564
2420
|
let activityColor = colors.dim;
|
|
2565
2421
|
if (memoryDir) {
|
|
2566
|
-
const squadMemoryPath =
|
|
2567
|
-
if (
|
|
2422
|
+
const squadMemoryPath = join5(memoryDir, squadName);
|
|
2423
|
+
if (existsSync5(squadMemoryPath)) {
|
|
2568
2424
|
const states = getSquadState(squadName);
|
|
2569
2425
|
memoryStatus = `${colors.green}${states.length} ${states.length === 1 ? "entry" : "entries"}${RESET}`;
|
|
2570
2426
|
let mostRecent = 0;
|
|
@@ -2666,14 +2522,14 @@ async function showSquadStatus(squadName, squadsDir, options) {
|
|
|
2666
2522
|
}
|
|
2667
2523
|
|
|
2668
2524
|
// src/commands/stack.ts
|
|
2669
|
-
import { existsSync as
|
|
2670
|
-
import { join as
|
|
2671
|
-
import { homedir as
|
|
2672
|
-
import { execSync as
|
|
2525
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, copyFileSync } from "fs";
|
|
2526
|
+
import { join as join6, dirname as dirname2 } from "path";
|
|
2527
|
+
import { homedir as homedir2 } from "os";
|
|
2528
|
+
import { execSync as execSync3, spawn as spawn3 } from "child_process";
|
|
2673
2529
|
import { createInterface as createInterface2 } from "readline";
|
|
2674
|
-
import { fileURLToPath
|
|
2675
|
-
var __filename2 =
|
|
2676
|
-
var __dirname2 =
|
|
2530
|
+
import { fileURLToPath } from "url";
|
|
2531
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
2532
|
+
var __dirname2 = dirname2(__filename2);
|
|
2677
2533
|
var DEFAULT_CONFIG = {
|
|
2678
2534
|
SQUADS_DATABASE_URL: "postgresql://squads:squads@localhost:5433/squads",
|
|
2679
2535
|
SQUADS_BRIDGE_URL: "http://localhost:8088",
|
|
@@ -2682,8 +2538,8 @@ var DEFAULT_CONFIG = {
|
|
|
2682
2538
|
LANGFUSE_SECRET_KEY: "",
|
|
2683
2539
|
REDIS_URL: "redis://localhost:6379"
|
|
2684
2540
|
};
|
|
2685
|
-
var CONFIG_PATH2 =
|
|
2686
|
-
var SQUADS_DATA_DIR =
|
|
2541
|
+
var CONFIG_PATH2 = join6(homedir2(), ".squadsrc");
|
|
2542
|
+
var SQUADS_DATA_DIR = join6(homedir2(), ".squads");
|
|
2687
2543
|
var SERVICES = {
|
|
2688
2544
|
bridge: {
|
|
2689
2545
|
name: "Bridge API",
|
|
@@ -2817,25 +2673,25 @@ async function confirm2(question, defaultYes = true) {
|
|
|
2817
2673
|
function findPackageDockerDir() {
|
|
2818
2674
|
const candidates = [
|
|
2819
2675
|
// From npm package (relative to dist/commands/stack.js)
|
|
2820
|
-
|
|
2676
|
+
join6(__dirname2, "..", "..", "docker"),
|
|
2821
2677
|
// Local development
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2678
|
+
join6(process.cwd(), "docker"),
|
|
2679
|
+
join6(process.cwd(), "..", "squads-cli", "docker"),
|
|
2680
|
+
join6(homedir2(), "agents-squads", "squads-cli", "docker")
|
|
2825
2681
|
];
|
|
2826
2682
|
for (const dir of candidates) {
|
|
2827
|
-
if (
|
|
2683
|
+
if (existsSync6(join6(dir, "docker-compose.yml"))) {
|
|
2828
2684
|
return dir;
|
|
2829
2685
|
}
|
|
2830
2686
|
}
|
|
2831
2687
|
return null;
|
|
2832
2688
|
}
|
|
2833
2689
|
function loadStackConfig() {
|
|
2834
|
-
if (!
|
|
2690
|
+
if (!existsSync6(CONFIG_PATH2)) {
|
|
2835
2691
|
return null;
|
|
2836
2692
|
}
|
|
2837
2693
|
try {
|
|
2838
|
-
const content =
|
|
2694
|
+
const content = readFileSync4(CONFIG_PATH2, "utf-8");
|
|
2839
2695
|
const config2 = {};
|
|
2840
2696
|
for (const line of content.split("\n")) {
|
|
2841
2697
|
const trimmed = line.trim();
|
|
@@ -2876,7 +2732,7 @@ function saveStackConfig(config2) {
|
|
|
2876
2732
|
"# To activate: source ~/.squadsrc",
|
|
2877
2733
|
""
|
|
2878
2734
|
];
|
|
2879
|
-
|
|
2735
|
+
writeFileSync4(CONFIG_PATH2, lines.join("\n"));
|
|
2880
2736
|
}
|
|
2881
2737
|
function applyStackConfig() {
|
|
2882
2738
|
const config2 = loadStackConfig();
|
|
@@ -2889,7 +2745,7 @@ function applyStackConfig() {
|
|
|
2889
2745
|
}
|
|
2890
2746
|
function isDockerRunning() {
|
|
2891
2747
|
try {
|
|
2892
|
-
|
|
2748
|
+
execSync3("docker info", { stdio: "ignore" });
|
|
2893
2749
|
return true;
|
|
2894
2750
|
} catch {
|
|
2895
2751
|
return false;
|
|
@@ -2897,7 +2753,7 @@ function isDockerRunning() {
|
|
|
2897
2753
|
}
|
|
2898
2754
|
function getContainerStatus(name) {
|
|
2899
2755
|
try {
|
|
2900
|
-
const runningOutput =
|
|
2756
|
+
const runningOutput = execSync3(
|
|
2901
2757
|
`docker inspect ${name} --format '{{.State.Running}}'`,
|
|
2902
2758
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }
|
|
2903
2759
|
).trim();
|
|
@@ -2907,7 +2763,7 @@ function getContainerStatus(name) {
|
|
|
2907
2763
|
}
|
|
2908
2764
|
let port;
|
|
2909
2765
|
try {
|
|
2910
|
-
const portOutput =
|
|
2766
|
+
const portOutput = execSync3(
|
|
2911
2767
|
`docker inspect ${name} --format '{{range .NetworkSettings.Ports}}{{range .}}{{.HostPort}}{{end}}{{end}}'`,
|
|
2912
2768
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }
|
|
2913
2769
|
).trim();
|
|
@@ -2916,7 +2772,7 @@ function getContainerStatus(name) {
|
|
|
2916
2772
|
}
|
|
2917
2773
|
let healthy = true;
|
|
2918
2774
|
try {
|
|
2919
|
-
const healthOutput =
|
|
2775
|
+
const healthOutput = execSync3(
|
|
2920
2776
|
`docker inspect ${name} --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}'`,
|
|
2921
2777
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }
|
|
2922
2778
|
).trim();
|
|
@@ -2948,13 +2804,13 @@ async function checkService(url, timeout = 2e3) {
|
|
|
2948
2804
|
}
|
|
2949
2805
|
function getLangfuseKeysFromDockerEnv() {
|
|
2950
2806
|
const envPaths2 = [
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2807
|
+
join6(process.cwd(), "docker", ".env"),
|
|
2808
|
+
join6(process.cwd(), "..", "squads-cli", "docker", ".env"),
|
|
2809
|
+
join6(homedir2(), "agents-squads", "squads-cli", "docker", ".env")
|
|
2954
2810
|
];
|
|
2955
2811
|
for (const envPath of envPaths2) {
|
|
2956
|
-
if (
|
|
2957
|
-
const content =
|
|
2812
|
+
if (existsSync6(envPath)) {
|
|
2813
|
+
const content = readFileSync4(envPath, "utf-8");
|
|
2958
2814
|
const publicMatch = content.match(/LANGFUSE_PUBLIC_KEY=(\S+)/);
|
|
2959
2815
|
const secretMatch = content.match(/LANGFUSE_SECRET_KEY=(\S+)/);
|
|
2960
2816
|
if (publicMatch && secretMatch) {
|
|
@@ -2969,12 +2825,12 @@ function getLangfuseKeysFromDockerEnv() {
|
|
|
2969
2825
|
}
|
|
2970
2826
|
function findDockerComposeDir() {
|
|
2971
2827
|
const candidates = [
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2828
|
+
join6(process.cwd(), "docker"),
|
|
2829
|
+
join6(process.cwd(), "..", "squads-cli", "docker"),
|
|
2830
|
+
join6(homedir2(), "agents-squads", "squads-cli", "docker")
|
|
2975
2831
|
];
|
|
2976
2832
|
for (const dir of candidates) {
|
|
2977
|
-
if (
|
|
2833
|
+
if (existsSync6(join6(dir, "docker-compose.yml"))) {
|
|
2978
2834
|
return dir;
|
|
2979
2835
|
}
|
|
2980
2836
|
}
|
|
@@ -3000,7 +2856,7 @@ async function stackInitCommand() {
|
|
|
3000
2856
|
writeLine();
|
|
3001
2857
|
writeLine(` ${bold}Step 2: Docker Compose Files${RESET}`);
|
|
3002
2858
|
let composeDir = findPackageDockerDir();
|
|
3003
|
-
const targetDir =
|
|
2859
|
+
const targetDir = join6(SQUADS_DATA_DIR, "docker");
|
|
3004
2860
|
if (!composeDir) {
|
|
3005
2861
|
writeLine(` ${colors.red}${icons.error}${RESET} Docker compose files not found`);
|
|
3006
2862
|
writeLine(` ${colors.dim}This shouldn't happen if you installed via npm.${RESET}`);
|
|
@@ -3008,20 +2864,20 @@ async function stackInitCommand() {
|
|
|
3008
2864
|
writeLine();
|
|
3009
2865
|
return;
|
|
3010
2866
|
}
|
|
3011
|
-
if (composeDir !== targetDir && !
|
|
2867
|
+
if (composeDir !== targetDir && !existsSync6(targetDir)) {
|
|
3012
2868
|
writeLine(` ${colors.cyan}${icons.progress}${RESET} Copying docker files to ${colors.dim}~/.squads/docker${RESET}`);
|
|
3013
2869
|
try {
|
|
3014
|
-
|
|
3015
|
-
|
|
2870
|
+
mkdirSync3(SQUADS_DATA_DIR, { recursive: true });
|
|
2871
|
+
mkdirSync3(targetDir, { recursive: true });
|
|
3016
2872
|
const filesToCopy = [
|
|
3017
2873
|
"docker-compose.yml",
|
|
3018
2874
|
"docker-compose.engram.yml",
|
|
3019
2875
|
".env.example"
|
|
3020
2876
|
];
|
|
3021
2877
|
for (const file of filesToCopy) {
|
|
3022
|
-
const src =
|
|
3023
|
-
const dst =
|
|
3024
|
-
if (
|
|
2878
|
+
const src = join6(composeDir, file);
|
|
2879
|
+
const dst = join6(targetDir, file);
|
|
2880
|
+
if (existsSync6(src)) {
|
|
3025
2881
|
copyFileSync(src, dst);
|
|
3026
2882
|
}
|
|
3027
2883
|
}
|
|
@@ -3030,7 +2886,7 @@ async function stackInitCommand() {
|
|
|
3030
2886
|
} catch {
|
|
3031
2887
|
writeLine(` ${colors.yellow}${icons.warning}${RESET} Could not copy files, using source location`);
|
|
3032
2888
|
}
|
|
3033
|
-
} else if (
|
|
2889
|
+
} else if (existsSync6(targetDir)) {
|
|
3034
2890
|
composeDir = targetDir;
|
|
3035
2891
|
writeLine(` ${colors.green}${icons.success}${RESET} Using ${colors.dim}~/.squads/docker${RESET}`);
|
|
3036
2892
|
} else {
|
|
@@ -3038,10 +2894,10 @@ async function stackInitCommand() {
|
|
|
3038
2894
|
}
|
|
3039
2895
|
writeLine();
|
|
3040
2896
|
writeLine(` ${bold}Step 3: Environment Configuration${RESET}`);
|
|
3041
|
-
const envPath =
|
|
3042
|
-
const envExamplePath =
|
|
3043
|
-
if (!
|
|
3044
|
-
if (
|
|
2897
|
+
const envPath = join6(composeDir, ".env");
|
|
2898
|
+
const envExamplePath = join6(composeDir, ".env.example");
|
|
2899
|
+
if (!existsSync6(envPath)) {
|
|
2900
|
+
if (existsSync6(envExamplePath)) {
|
|
3045
2901
|
copyFileSync(envExamplePath, envPath);
|
|
3046
2902
|
writeLine(` ${colors.cyan}${icons.progress}${RESET} Created .env from template`);
|
|
3047
2903
|
} else {
|
|
@@ -3070,13 +2926,13 @@ LANGFUSE_PORT=3100
|
|
|
3070
2926
|
OTEL_PORT=4318
|
|
3071
2927
|
BRIDGE_PORT=8088
|
|
3072
2928
|
`;
|
|
3073
|
-
|
|
2929
|
+
writeFileSync4(envPath, minimalEnv);
|
|
3074
2930
|
writeLine(` ${colors.cyan}${icons.progress}${RESET} Created default .env`);
|
|
3075
2931
|
}
|
|
3076
2932
|
} else {
|
|
3077
2933
|
writeLine(` ${colors.green}${icons.success}${RESET} .env exists`);
|
|
3078
2934
|
}
|
|
3079
|
-
const envContent =
|
|
2935
|
+
const envContent = readFileSync4(envPath, "utf-8");
|
|
3080
2936
|
const missingSecrets = [];
|
|
3081
2937
|
const llmProvider = envContent.match(/LLM_PROVIDER=(\w+)/)?.[1] || "ollama";
|
|
3082
2938
|
if (llmProvider === "openai") {
|
|
@@ -3117,7 +2973,7 @@ BRIDGE_PORT=8088
|
|
|
3117
2973
|
writeLine();
|
|
3118
2974
|
writeLine(` ${colors.cyan}${icons.progress}${RESET} Starting containers...`);
|
|
3119
2975
|
try {
|
|
3120
|
-
|
|
2976
|
+
execSync3("docker compose up -d", {
|
|
3121
2977
|
cwd: composeDir,
|
|
3122
2978
|
stdio: "inherit"
|
|
3123
2979
|
});
|
|
@@ -3317,7 +3173,7 @@ async function stackHealthCommand(verbose = false) {
|
|
|
3317
3173
|
let logs;
|
|
3318
3174
|
if (!ok && verbose) {
|
|
3319
3175
|
try {
|
|
3320
|
-
logs =
|
|
3176
|
+
logs = execSync3(`docker logs ${container.name} --tail 10 2>&1`, {
|
|
3321
3177
|
encoding: "utf-8",
|
|
3322
3178
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3323
3179
|
});
|
|
@@ -3368,7 +3224,7 @@ function stackLogsCommand(service, tail = 50) {
|
|
|
3368
3224
|
};
|
|
3369
3225
|
const container = containerMap[service] || `squads-${service}`;
|
|
3370
3226
|
try {
|
|
3371
|
-
|
|
3227
|
+
execSync3(`docker logs ${container} --tail ${tail}`, { stdio: "inherit" });
|
|
3372
3228
|
} catch {
|
|
3373
3229
|
writeLine(` ${colors.red}${icons.error}${RESET} Container ${container} not found`);
|
|
3374
3230
|
}
|
|
@@ -3755,9 +3611,9 @@ async function memoryExtractCommand(options = {}) {
|
|
|
3755
3611
|
}
|
|
3756
3612
|
|
|
3757
3613
|
// src/commands/sync.ts
|
|
3758
|
-
import { execSync as
|
|
3759
|
-
import { existsSync as
|
|
3760
|
-
import { join as
|
|
3614
|
+
import { execSync as execSync4 } from "child_process";
|
|
3615
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
3616
|
+
import { join as join7 } from "path";
|
|
3761
3617
|
var PATH_TO_SQUAD = {
|
|
3762
3618
|
"squads-cli": "product",
|
|
3763
3619
|
"agents-squads-web": "website",
|
|
@@ -3785,21 +3641,21 @@ var MESSAGE_TO_SQUAD = {
|
|
|
3785
3641
|
"infra": "engineering"
|
|
3786
3642
|
};
|
|
3787
3643
|
function getLastSyncTime(memoryDir) {
|
|
3788
|
-
const syncFile =
|
|
3789
|
-
if (
|
|
3790
|
-
return
|
|
3644
|
+
const syncFile = join7(memoryDir, ".last-sync");
|
|
3645
|
+
if (existsSync7(syncFile)) {
|
|
3646
|
+
return readFileSync5(syncFile, "utf-8").trim();
|
|
3791
3647
|
}
|
|
3792
3648
|
return null;
|
|
3793
3649
|
}
|
|
3794
3650
|
function updateLastSyncTime(memoryDir) {
|
|
3795
|
-
const syncFile =
|
|
3796
|
-
|
|
3651
|
+
const syncFile = join7(memoryDir, ".last-sync");
|
|
3652
|
+
writeFileSync5(syncFile, (/* @__PURE__ */ new Date()).toISOString());
|
|
3797
3653
|
}
|
|
3798
3654
|
function getRecentCommits(since) {
|
|
3799
3655
|
const commits = [];
|
|
3800
3656
|
try {
|
|
3801
3657
|
const sinceArg = since ? `--since="${since}"` : "-n 20";
|
|
3802
|
-
const logOutput =
|
|
3658
|
+
const logOutput = execSync4(
|
|
3803
3659
|
`git log ${sinceArg} --format="%H|%aI|%s" --name-only`,
|
|
3804
3660
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
3805
3661
|
).trim();
|
|
@@ -3865,22 +3721,22 @@ ${messages}
|
|
|
3865
3721
|
`;
|
|
3866
3722
|
}
|
|
3867
3723
|
function appendToSquadMemory(memoryDir, squad, summary) {
|
|
3868
|
-
const squadMemoryDir =
|
|
3869
|
-
if (!
|
|
3870
|
-
|
|
3724
|
+
const squadMemoryDir = join7(memoryDir, squad);
|
|
3725
|
+
if (!existsSync7(squadMemoryDir)) {
|
|
3726
|
+
mkdirSync4(squadMemoryDir, { recursive: true });
|
|
3871
3727
|
}
|
|
3872
3728
|
let agentDir;
|
|
3873
|
-
const existingDirs =
|
|
3729
|
+
const existingDirs = existsSync7(squadMemoryDir) ? readdirSync2(squadMemoryDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name) : [];
|
|
3874
3730
|
if (existingDirs.length > 0) {
|
|
3875
|
-
agentDir =
|
|
3731
|
+
agentDir = join7(squadMemoryDir, existingDirs[0]);
|
|
3876
3732
|
} else {
|
|
3877
|
-
agentDir =
|
|
3878
|
-
|
|
3733
|
+
agentDir = join7(squadMemoryDir, `${squad}-lead`);
|
|
3734
|
+
mkdirSync4(agentDir, { recursive: true });
|
|
3879
3735
|
}
|
|
3880
|
-
const statePath =
|
|
3736
|
+
const statePath = join7(agentDir, "state.md");
|
|
3881
3737
|
let content = "";
|
|
3882
|
-
if (
|
|
3883
|
-
content =
|
|
3738
|
+
if (existsSync7(statePath)) {
|
|
3739
|
+
content = readFileSync5(statePath, "utf-8");
|
|
3884
3740
|
} else {
|
|
3885
3741
|
content = `# ${squad} Squad - State
|
|
3886
3742
|
|
|
@@ -3892,13 +3748,13 @@ Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
|
3892
3748
|
`Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`
|
|
3893
3749
|
);
|
|
3894
3750
|
content += summary;
|
|
3895
|
-
|
|
3751
|
+
writeFileSync5(statePath, content);
|
|
3896
3752
|
return true;
|
|
3897
3753
|
}
|
|
3898
3754
|
function gitPullMemory() {
|
|
3899
3755
|
try {
|
|
3900
|
-
|
|
3901
|
-
const status =
|
|
3756
|
+
execSync4("git fetch origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
3757
|
+
const status = execSync4("git status -sb", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
3902
3758
|
const behindMatch = status.match(/behind (\d+)/);
|
|
3903
3759
|
const aheadMatch = status.match(/ahead (\d+)/);
|
|
3904
3760
|
const behind = behindMatch ? parseInt(behindMatch[1]) : 0;
|
|
@@ -3906,7 +3762,7 @@ function gitPullMemory() {
|
|
|
3906
3762
|
if (behind === 0) {
|
|
3907
3763
|
return { success: true, output: "Already up to date", behind: 0, ahead };
|
|
3908
3764
|
}
|
|
3909
|
-
const output =
|
|
3765
|
+
const output = execSync4("git pull --rebase origin main", {
|
|
3910
3766
|
encoding: "utf-8",
|
|
3911
3767
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3912
3768
|
});
|
|
@@ -3918,18 +3774,18 @@ function gitPullMemory() {
|
|
|
3918
3774
|
}
|
|
3919
3775
|
function gitPushMemory() {
|
|
3920
3776
|
try {
|
|
3921
|
-
const status =
|
|
3777
|
+
const status = execSync4("git status --porcelain .agents/memory/", {
|
|
3922
3778
|
encoding: "utf-8",
|
|
3923
3779
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3924
3780
|
}).trim();
|
|
3925
3781
|
if (status) {
|
|
3926
|
-
|
|
3927
|
-
|
|
3782
|
+
execSync4("git add .agents/memory/", { stdio: ["pipe", "pipe", "pipe"] });
|
|
3783
|
+
execSync4('git commit -m "chore: sync squad memory"', {
|
|
3928
3784
|
encoding: "utf-8",
|
|
3929
3785
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3930
3786
|
});
|
|
3931
3787
|
}
|
|
3932
|
-
const output =
|
|
3788
|
+
const output = execSync4("git push origin main", {
|
|
3933
3789
|
encoding: "utf-8",
|
|
3934
3790
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3935
3791
|
});
|
|
@@ -4169,28 +4025,28 @@ async function goalProgressCommand(squadName, goalIndex, progress2) {
|
|
|
4169
4025
|
}
|
|
4170
4026
|
|
|
4171
4027
|
// src/commands/feedback.ts
|
|
4172
|
-
import { readFileSync as
|
|
4173
|
-
import { join as
|
|
4028
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
|
|
4029
|
+
import { join as join8, dirname as dirname3 } from "path";
|
|
4174
4030
|
function getFeedbackPath(squadName) {
|
|
4175
4031
|
const memoryDir = findMemoryDir();
|
|
4176
4032
|
if (!memoryDir) return null;
|
|
4177
4033
|
const squad = loadSquad(squadName);
|
|
4178
4034
|
const agentName = squad?.agents[0]?.name || `${squadName}-lead`;
|
|
4179
|
-
return
|
|
4035
|
+
return join8(memoryDir, squadName, agentName, "feedback.md");
|
|
4180
4036
|
}
|
|
4181
4037
|
function getOutputPath(squadName) {
|
|
4182
4038
|
const memoryDir = findMemoryDir();
|
|
4183
4039
|
if (!memoryDir) return null;
|
|
4184
4040
|
const squad = loadSquad(squadName);
|
|
4185
4041
|
const agentName = squad?.agents[0]?.name || `${squadName}-lead`;
|
|
4186
|
-
return
|
|
4042
|
+
return join8(memoryDir, squadName, agentName, "output.md");
|
|
4187
4043
|
}
|
|
4188
4044
|
function getLastExecution(squadName) {
|
|
4189
4045
|
const outputPath = getOutputPath(squadName);
|
|
4190
|
-
if (!outputPath || !
|
|
4046
|
+
if (!outputPath || !existsSync8(outputPath)) {
|
|
4191
4047
|
return null;
|
|
4192
4048
|
}
|
|
4193
|
-
const content =
|
|
4049
|
+
const content = readFileSync6(outputPath, "utf-8");
|
|
4194
4050
|
const lines = content.split("\n");
|
|
4195
4051
|
let date = "unknown";
|
|
4196
4052
|
let summary = lines.slice(0, 5).join("\n");
|
|
@@ -4242,9 +4098,9 @@ async function feedbackAddCommand(squadName, rating, feedback2, options) {
|
|
|
4242
4098
|
return;
|
|
4243
4099
|
}
|
|
4244
4100
|
const lastExec = getLastExecution(squadName);
|
|
4245
|
-
const dir =
|
|
4246
|
-
if (!
|
|
4247
|
-
|
|
4101
|
+
const dir = dirname3(feedbackPath);
|
|
4102
|
+
if (!existsSync8(dir)) {
|
|
4103
|
+
mkdirSync5(dir, { recursive: true });
|
|
4248
4104
|
}
|
|
4249
4105
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
4250
4106
|
let entry = `
|
|
@@ -4272,15 +4128,15 @@ _Date: ${date}_
|
|
|
4272
4128
|
}
|
|
4273
4129
|
}
|
|
4274
4130
|
let existing = "";
|
|
4275
|
-
if (
|
|
4276
|
-
existing =
|
|
4131
|
+
if (existsSync8(feedbackPath)) {
|
|
4132
|
+
existing = readFileSync6(feedbackPath, "utf-8");
|
|
4277
4133
|
} else {
|
|
4278
4134
|
existing = `# ${squadName} - Feedback Log
|
|
4279
4135
|
|
|
4280
4136
|
> Execution feedback and learnings
|
|
4281
4137
|
`;
|
|
4282
4138
|
}
|
|
4283
|
-
|
|
4139
|
+
writeFileSync6(feedbackPath, existing + entry);
|
|
4284
4140
|
const stars = `${colors.yellow}${"\u2605".repeat(ratingNum)}${"\u2606".repeat(5 - ratingNum)}${RESET}`;
|
|
4285
4141
|
writeLine();
|
|
4286
4142
|
writeLine(` ${icons.success} Feedback recorded for ${colors.cyan}${squadName}${RESET}`);
|
|
@@ -4294,11 +4150,11 @@ _Date: ${date}_
|
|
|
4294
4150
|
async function feedbackShowCommand(squadName, options) {
|
|
4295
4151
|
await track(Events.CLI_FEEDBACK_SHOW, { squad: squadName });
|
|
4296
4152
|
const feedbackPath = getFeedbackPath(squadName);
|
|
4297
|
-
if (!feedbackPath || !
|
|
4153
|
+
if (!feedbackPath || !existsSync8(feedbackPath)) {
|
|
4298
4154
|
writeLine(` ${colors.yellow}No feedback recorded for ${squadName}${RESET}`);
|
|
4299
4155
|
return;
|
|
4300
4156
|
}
|
|
4301
|
-
const content =
|
|
4157
|
+
const content = readFileSync6(feedbackPath, "utf-8");
|
|
4302
4158
|
const entries = parseFeedbackHistory(content);
|
|
4303
4159
|
const limit = options.limit ? parseInt(options.limit) : 5;
|
|
4304
4160
|
const recent = entries.slice(-limit).reverse();
|
|
@@ -4343,10 +4199,10 @@ async function feedbackStatsCommand() {
|
|
|
4343
4199
|
writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);
|
|
4344
4200
|
for (const squad of squads) {
|
|
4345
4201
|
const feedbackPath = getFeedbackPath(squad);
|
|
4346
|
-
if (!feedbackPath || !
|
|
4202
|
+
if (!feedbackPath || !existsSync8(feedbackPath)) {
|
|
4347
4203
|
continue;
|
|
4348
4204
|
}
|
|
4349
|
-
const content =
|
|
4205
|
+
const content = readFileSync6(feedbackPath, "utf-8");
|
|
4350
4206
|
const entries = parseFeedbackHistory(content);
|
|
4351
4207
|
if (entries.length === 0) continue;
|
|
4352
4208
|
const avgRating = entries.reduce((sum, e) => sum + e.rating, 0) / entries.length;
|
|
@@ -4369,8 +4225,8 @@ async function feedbackStatsCommand() {
|
|
|
4369
4225
|
}
|
|
4370
4226
|
|
|
4371
4227
|
// src/commands/dashboard.ts
|
|
4372
|
-
import { readdirSync as readdirSync4, existsSync as
|
|
4373
|
-
import { join as
|
|
4228
|
+
import { readdirSync as readdirSync4, existsSync as existsSync9, statSync as statSync2 } from "fs";
|
|
4229
|
+
import { join as join9 } from "path";
|
|
4374
4230
|
|
|
4375
4231
|
// src/lib/providers.ts
|
|
4376
4232
|
var PROVIDERS = {
|
|
@@ -5229,16 +5085,16 @@ async function closeDatabase() {
|
|
|
5229
5085
|
function getLastActivityDate(squadName) {
|
|
5230
5086
|
const memoryDir = findMemoryDir();
|
|
5231
5087
|
if (!memoryDir) return "unknown";
|
|
5232
|
-
const squadMemory =
|
|
5233
|
-
if (!
|
|
5088
|
+
const squadMemory = join9(memoryDir, squadName);
|
|
5089
|
+
if (!existsSync9(squadMemory)) return "\u2014";
|
|
5234
5090
|
let latestTime = 0;
|
|
5235
5091
|
try {
|
|
5236
5092
|
const agents = readdirSync4(squadMemory, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
5237
5093
|
for (const agent of agents) {
|
|
5238
|
-
const agentPath =
|
|
5094
|
+
const agentPath = join9(squadMemory, agent.name);
|
|
5239
5095
|
const files = readdirSync4(agentPath).filter((f) => f.endsWith(".md"));
|
|
5240
5096
|
for (const file of files) {
|
|
5241
|
-
const filePath =
|
|
5097
|
+
const filePath = join9(agentPath, file);
|
|
5242
5098
|
const stats = statSync2(filePath);
|
|
5243
5099
|
if (stats.mtimeMs > latestTime) {
|
|
5244
5100
|
latestTime = stats.mtimeMs;
|
|
@@ -5485,11 +5341,11 @@ async function dashboardCommand(options = {}) {
|
|
|
5485
5341
|
await closeDatabase();
|
|
5486
5342
|
}
|
|
5487
5343
|
function findAgentsSquadsDir() {
|
|
5488
|
-
const parentDir =
|
|
5489
|
-
if (
|
|
5344
|
+
const parentDir = join9(process.cwd(), "..");
|
|
5345
|
+
if (existsSync9(join9(parentDir, "hq"))) {
|
|
5490
5346
|
return parentDir;
|
|
5491
5347
|
}
|
|
5492
|
-
if (
|
|
5348
|
+
if (existsSync9(join9(process.cwd(), ".git"))) {
|
|
5493
5349
|
return process.cwd();
|
|
5494
5350
|
}
|
|
5495
5351
|
return null;
|
|
@@ -5878,7 +5734,7 @@ function renderInsightsCached(cache) {
|
|
|
5878
5734
|
}
|
|
5879
5735
|
|
|
5880
5736
|
// src/commands/issues.ts
|
|
5881
|
-
import { execSync as
|
|
5737
|
+
import { execSync as execSync5 } from "child_process";
|
|
5882
5738
|
function getLabelName(label) {
|
|
5883
5739
|
return typeof label === "string" ? label : label.name;
|
|
5884
5740
|
}
|
|
@@ -5891,7 +5747,7 @@ async function issuesCommand(options = {}) {
|
|
|
5891
5747
|
writeLine(` ${gradient("squads")} ${colors.dim}issues${RESET}`);
|
|
5892
5748
|
writeLine();
|
|
5893
5749
|
try {
|
|
5894
|
-
|
|
5750
|
+
execSync5("gh --version", { stdio: "pipe" });
|
|
5895
5751
|
} catch {
|
|
5896
5752
|
writeLine(` ${colors.red}GitHub CLI (gh) not found${RESET}`);
|
|
5897
5753
|
writeLine(` ${colors.dim}Install: brew install gh${RESET}`);
|
|
@@ -5902,7 +5758,7 @@ async function issuesCommand(options = {}) {
|
|
|
5902
5758
|
let totalOpen = 0;
|
|
5903
5759
|
for (const repo of repos) {
|
|
5904
5760
|
try {
|
|
5905
|
-
const result =
|
|
5761
|
+
const result = execSync5(
|
|
5906
5762
|
`gh issue list -R ${org}/${repo} --state open --json number,title,state,labels,createdAt --limit 50`,
|
|
5907
5763
|
{ stdio: "pipe", encoding: "utf-8" }
|
|
5908
5764
|
);
|
|
@@ -5953,7 +5809,7 @@ async function issuesCommand(options = {}) {
|
|
|
5953
5809
|
}
|
|
5954
5810
|
|
|
5955
5811
|
// src/commands/solve-issues.ts
|
|
5956
|
-
import { execSync as
|
|
5812
|
+
import { execSync as execSync6, spawn as spawn4 } from "child_process";
|
|
5957
5813
|
import ora3 from "ora";
|
|
5958
5814
|
var DEFAULT_ORG2 = "agents-squads";
|
|
5959
5815
|
var DEFAULT_REPOS2 = ["hq", "agents-squads-web", "squads-cli", "agents-squads"];
|
|
@@ -5963,7 +5819,7 @@ async function solveIssuesCommand(options = {}) {
|
|
|
5963
5819
|
writeLine(` ${gradient("squads")} ${colors.dim}solve-issues${RESET}`);
|
|
5964
5820
|
writeLine();
|
|
5965
5821
|
try {
|
|
5966
|
-
|
|
5822
|
+
execSync6("gh --version", { stdio: "pipe" });
|
|
5967
5823
|
} catch {
|
|
5968
5824
|
writeLine(` ${colors.red}GitHub CLI (gh) not found${RESET}`);
|
|
5969
5825
|
writeLine(` ${colors.dim}Install: brew install gh${RESET}`);
|
|
@@ -5973,7 +5829,7 @@ async function solveIssuesCommand(options = {}) {
|
|
|
5973
5829
|
if (options.issue) {
|
|
5974
5830
|
const repo = options.repo || "hq";
|
|
5975
5831
|
try {
|
|
5976
|
-
const result =
|
|
5832
|
+
const result = execSync6(
|
|
5977
5833
|
`gh issue view ${options.issue} -R ${DEFAULT_ORG2}/${repo} --json number,title,labels,body`,
|
|
5978
5834
|
{ stdio: "pipe", encoding: "utf-8" }
|
|
5979
5835
|
);
|
|
@@ -5986,7 +5842,7 @@ async function solveIssuesCommand(options = {}) {
|
|
|
5986
5842
|
} else {
|
|
5987
5843
|
for (const repo of repos) {
|
|
5988
5844
|
try {
|
|
5989
|
-
const result =
|
|
5845
|
+
const result = execSync6(
|
|
5990
5846
|
`gh issue list -R ${DEFAULT_ORG2}/${repo} --label "ready-to-fix" --state open --json number,title,labels --limit 20`,
|
|
5991
5847
|
{ stdio: "pipe", encoding: "utf-8" }
|
|
5992
5848
|
);
|
|
@@ -6040,7 +5896,7 @@ function showSolveInstructions(issues) {
|
|
|
6040
5896
|
async function solveWithClaude(issues) {
|
|
6041
5897
|
const spinner = ora3("Starting issue solver...").start();
|
|
6042
5898
|
try {
|
|
6043
|
-
|
|
5899
|
+
execSync6("which claude", { stdio: "pipe" });
|
|
6044
5900
|
} catch {
|
|
6045
5901
|
spinner.fail("Claude CLI not found");
|
|
6046
5902
|
writeLine(` ${colors.dim}Install: npm install -g @anthropic-ai/claude-code${RESET}`);
|
|
@@ -6126,9 +5982,9 @@ function executeClaudePrompt(prompt2) {
|
|
|
6126
5982
|
}
|
|
6127
5983
|
|
|
6128
5984
|
// src/commands/open-issues.ts
|
|
6129
|
-
import { execSync as
|
|
5985
|
+
import { execSync as execSync7, spawn as spawn5 } from "child_process";
|
|
6130
5986
|
import { readdirSync as readdirSync5 } from "fs";
|
|
6131
|
-
import { join as
|
|
5987
|
+
import { join as join10 } from "path";
|
|
6132
5988
|
import ora4 from "ora";
|
|
6133
5989
|
var ISSUE_FINDER_PATTERNS = [
|
|
6134
5990
|
"*-eval.md",
|
|
@@ -6186,7 +6042,7 @@ function findEvalAgents(squadsDir, filterSquad) {
|
|
|
6186
6042
|
const agents = [];
|
|
6187
6043
|
const squads = readdirSync5(squadsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).filter((d) => !filterSquad || d.name === filterSquad).map((d) => d.name);
|
|
6188
6044
|
for (const squad of squads) {
|
|
6189
|
-
const squadPath =
|
|
6045
|
+
const squadPath = join10(squadsDir, squad);
|
|
6190
6046
|
const files = readdirSync5(squadPath).filter((f) => f.endsWith(".md"));
|
|
6191
6047
|
for (const file of files) {
|
|
6192
6048
|
const isEval = ISSUE_FINDER_PATTERNS.some((pattern) => {
|
|
@@ -6197,7 +6053,7 @@ function findEvalAgents(squadsDir, filterSquad) {
|
|
|
6197
6053
|
agents.push({
|
|
6198
6054
|
name: file,
|
|
6199
6055
|
squad,
|
|
6200
|
-
path:
|
|
6056
|
+
path: join10(squadPath, file)
|
|
6201
6057
|
});
|
|
6202
6058
|
}
|
|
6203
6059
|
}
|
|
@@ -6223,7 +6079,7 @@ function showRunInstructions(agents) {
|
|
|
6223
6079
|
async function runEvaluators(agents) {
|
|
6224
6080
|
const spinner = ora4("Starting evaluators...").start();
|
|
6225
6081
|
try {
|
|
6226
|
-
|
|
6082
|
+
execSync7("which claude", { stdio: "pipe" });
|
|
6227
6083
|
} catch {
|
|
6228
6084
|
spinner.fail("Claude CLI not found");
|
|
6229
6085
|
writeLine(` ${colors.dim}Install: npm install -g @anthropic-ai/claude-code${RESET}`);
|
|
@@ -6307,9 +6163,9 @@ import open from "open";
|
|
|
6307
6163
|
|
|
6308
6164
|
// src/lib/auth.ts
|
|
6309
6165
|
import { createClient } from "@supabase/supabase-js";
|
|
6310
|
-
import { existsSync as
|
|
6311
|
-
import { join as
|
|
6312
|
-
import { homedir as
|
|
6166
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6 } from "fs";
|
|
6167
|
+
import { join as join11 } from "path";
|
|
6168
|
+
import { homedir as homedir3 } from "os";
|
|
6313
6169
|
import "open";
|
|
6314
6170
|
import http from "http";
|
|
6315
6171
|
var PERSONAL_DOMAINS = [
|
|
@@ -6338,8 +6194,8 @@ var PERSONAL_DOMAINS = [
|
|
|
6338
6194
|
"tutanota.com",
|
|
6339
6195
|
"hey.com"
|
|
6340
6196
|
];
|
|
6341
|
-
var AUTH_DIR =
|
|
6342
|
-
var AUTH_PATH =
|
|
6197
|
+
var AUTH_DIR = join11(homedir3(), ".squads-cli");
|
|
6198
|
+
var AUTH_PATH = join11(AUTH_DIR, "auth.json");
|
|
6343
6199
|
function isPersonalEmail(email) {
|
|
6344
6200
|
const domain = email.split("@")[1]?.toLowerCase();
|
|
6345
6201
|
return PERSONAL_DOMAINS.includes(domain);
|
|
@@ -6348,22 +6204,22 @@ function getEmailDomain(email) {
|
|
|
6348
6204
|
return email.split("@")[1]?.toLowerCase() || "";
|
|
6349
6205
|
}
|
|
6350
6206
|
function saveSession(session2) {
|
|
6351
|
-
if (!
|
|
6352
|
-
|
|
6207
|
+
if (!existsSync10(AUTH_DIR)) {
|
|
6208
|
+
mkdirSync6(AUTH_DIR, { recursive: true });
|
|
6353
6209
|
}
|
|
6354
|
-
|
|
6210
|
+
writeFileSync7(AUTH_PATH, JSON.stringify(session2, null, 2));
|
|
6355
6211
|
}
|
|
6356
6212
|
function loadSession() {
|
|
6357
|
-
if (!
|
|
6213
|
+
if (!existsSync10(AUTH_PATH)) return null;
|
|
6358
6214
|
try {
|
|
6359
|
-
return JSON.parse(
|
|
6215
|
+
return JSON.parse(readFileSync7(AUTH_PATH, "utf-8"));
|
|
6360
6216
|
} catch {
|
|
6361
6217
|
return null;
|
|
6362
6218
|
}
|
|
6363
6219
|
}
|
|
6364
6220
|
function clearSession() {
|
|
6365
|
-
if (
|
|
6366
|
-
|
|
6221
|
+
if (existsSync10(AUTH_PATH)) {
|
|
6222
|
+
writeFileSync7(AUTH_PATH, "");
|
|
6367
6223
|
}
|
|
6368
6224
|
}
|
|
6369
6225
|
function startAuthCallbackServer(port = 54321) {
|
|
@@ -6585,26 +6441,26 @@ async function updateCommand(options = {}) {
|
|
|
6585
6441
|
}
|
|
6586
6442
|
|
|
6587
6443
|
// src/commands/progress.ts
|
|
6588
|
-
import { execSync as
|
|
6589
|
-
import { existsSync as
|
|
6590
|
-
import { join as
|
|
6444
|
+
import { execSync as execSync8 } from "child_process";
|
|
6445
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7 } from "fs";
|
|
6446
|
+
import { join as join12 } from "path";
|
|
6591
6447
|
function getTasksFilePath() {
|
|
6592
6448
|
const memoryDir = findMemoryDir();
|
|
6593
6449
|
if (!memoryDir) {
|
|
6594
6450
|
const cwd = process.cwd();
|
|
6595
|
-
const agentsDir =
|
|
6596
|
-
if (!
|
|
6597
|
-
|
|
6451
|
+
const agentsDir = join12(cwd, ".agents");
|
|
6452
|
+
if (!existsSync11(agentsDir)) {
|
|
6453
|
+
mkdirSync7(agentsDir, { recursive: true });
|
|
6598
6454
|
}
|
|
6599
|
-
return
|
|
6455
|
+
return join12(agentsDir, "tasks.json");
|
|
6600
6456
|
}
|
|
6601
|
-
return
|
|
6457
|
+
return join12(memoryDir, "..", "tasks.json");
|
|
6602
6458
|
}
|
|
6603
6459
|
function loadTasks() {
|
|
6604
6460
|
const tasksPath = getTasksFilePath();
|
|
6605
|
-
if (
|
|
6461
|
+
if (existsSync11(tasksPath)) {
|
|
6606
6462
|
try {
|
|
6607
|
-
return JSON.parse(
|
|
6463
|
+
return JSON.parse(readFileSync8(tasksPath, "utf-8"));
|
|
6608
6464
|
} catch {
|
|
6609
6465
|
return { tasks: [], lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
6610
6466
|
}
|
|
@@ -6614,7 +6470,7 @@ function loadTasks() {
|
|
|
6614
6470
|
function saveTasks(data) {
|
|
6615
6471
|
const tasksPath = getTasksFilePath();
|
|
6616
6472
|
data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
6617
|
-
|
|
6473
|
+
writeFileSync8(tasksPath, JSON.stringify(data, null, 2));
|
|
6618
6474
|
}
|
|
6619
6475
|
function getRecentActivity() {
|
|
6620
6476
|
const activity = [];
|
|
@@ -6630,7 +6486,7 @@ function getRecentActivity() {
|
|
|
6630
6486
|
marketing: ["marketing", "content", "social"]
|
|
6631
6487
|
};
|
|
6632
6488
|
try {
|
|
6633
|
-
const logOutput =
|
|
6489
|
+
const logOutput = execSync8(
|
|
6634
6490
|
'git log --since="24 hours ago" --format="%h|%aI|%s" 2>/dev/null',
|
|
6635
6491
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
6636
6492
|
).trim();
|
|
@@ -6764,7 +6620,7 @@ function getElapsedTime(startTime) {
|
|
|
6764
6620
|
}
|
|
6765
6621
|
|
|
6766
6622
|
// src/commands/results.ts
|
|
6767
|
-
import { execSync as
|
|
6623
|
+
import { execSync as execSync9 } from "child_process";
|
|
6768
6624
|
function getGitStats(days = 7) {
|
|
6769
6625
|
const stats = /* @__PURE__ */ new Map();
|
|
6770
6626
|
const squadKeywords = {
|
|
@@ -6779,7 +6635,7 @@ function getGitStats(days = 7) {
|
|
|
6779
6635
|
marketing: ["marketing"]
|
|
6780
6636
|
};
|
|
6781
6637
|
try {
|
|
6782
|
-
const logOutput =
|
|
6638
|
+
const logOutput = execSync9(
|
|
6783
6639
|
`git log --since="${days} days ago" --format="%s" --name-only 2>/dev/null`,
|
|
6784
6640
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
6785
6641
|
).trim();
|
|
@@ -6818,7 +6674,7 @@ function getGitHubStats(days = 7) {
|
|
|
6818
6674
|
const prsMerged = /* @__PURE__ */ new Map();
|
|
6819
6675
|
const issuesClosed = /* @__PURE__ */ new Map();
|
|
6820
6676
|
try {
|
|
6821
|
-
const prsOutput =
|
|
6677
|
+
const prsOutput = execSync9(
|
|
6822
6678
|
`gh pr list --state all --json title,createdAt,mergedAt --limit 50 2>/dev/null`,
|
|
6823
6679
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
6824
6680
|
);
|
|
@@ -6833,7 +6689,7 @@ function getGitHubStats(days = 7) {
|
|
|
6833
6689
|
prsMerged.set(squad, (prsMerged.get(squad) || 0) + 1);
|
|
6834
6690
|
}
|
|
6835
6691
|
}
|
|
6836
|
-
const issuesOutput =
|
|
6692
|
+
const issuesOutput = execSync9(
|
|
6837
6693
|
`gh issue list --state closed --json title,closedAt --limit 50 2>/dev/null`,
|
|
6838
6694
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
6839
6695
|
);
|
|
@@ -6966,8 +6822,8 @@ async function resultsCommand(options = {}) {
|
|
|
6966
6822
|
}
|
|
6967
6823
|
|
|
6968
6824
|
// src/commands/history.ts
|
|
6969
|
-
import { existsSync as
|
|
6970
|
-
import { join as
|
|
6825
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
6826
|
+
import { join as join13 } from "path";
|
|
6971
6827
|
var BRIDGE_URL2 = process.env.SQUADS_BRIDGE_URL || "http://localhost:8088";
|
|
6972
6828
|
var FETCH_TIMEOUT_MS2 = 3e3;
|
|
6973
6829
|
async function fetchWithTimeout2(url, timeoutMs = FETCH_TIMEOUT_MS2) {
|
|
@@ -7012,12 +6868,12 @@ async function fetchFromBridge2(days, squad) {
|
|
|
7012
6868
|
function fetchFromLocal(days, squad) {
|
|
7013
6869
|
const executions = [];
|
|
7014
6870
|
const historyPaths = [
|
|
7015
|
-
|
|
7016
|
-
|
|
6871
|
+
join13(process.cwd(), ".agents/sessions/history.jsonl"),
|
|
6872
|
+
join13(process.env.HOME || "", "agents-squads/hq/.agents/sessions/history.jsonl")
|
|
7017
6873
|
];
|
|
7018
6874
|
let historyPath;
|
|
7019
6875
|
for (const path3 of historyPaths) {
|
|
7020
|
-
if (
|
|
6876
|
+
if (existsSync12(path3)) {
|
|
7021
6877
|
historyPath = path3;
|
|
7022
6878
|
break;
|
|
7023
6879
|
}
|
|
@@ -7026,7 +6882,7 @@ function fetchFromLocal(days, squad) {
|
|
|
7026
6882
|
return [];
|
|
7027
6883
|
}
|
|
7028
6884
|
try {
|
|
7029
|
-
const content =
|
|
6885
|
+
const content = readFileSync9(historyPath, "utf-8");
|
|
7030
6886
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
7031
6887
|
const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
|
|
7032
6888
|
for (const line of lines) {
|
|
@@ -7362,19 +7218,19 @@ async function healthCommand(options = {}) {
|
|
|
7362
7218
|
}
|
|
7363
7219
|
|
|
7364
7220
|
// src/commands/workers.ts
|
|
7365
|
-
import { execSync as
|
|
7366
|
-
import { existsSync as
|
|
7367
|
-
import { join as
|
|
7221
|
+
import { execSync as execSync10 } from "child_process";
|
|
7222
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
7223
|
+
import { join as join14 } from "path";
|
|
7368
7224
|
function getTasksFilePath2() {
|
|
7369
7225
|
const memoryDir = findMemoryDir();
|
|
7370
7226
|
if (!memoryDir) return null;
|
|
7371
|
-
return
|
|
7227
|
+
return join14(memoryDir, "..", "tasks.json");
|
|
7372
7228
|
}
|
|
7373
7229
|
function loadActiveTasks() {
|
|
7374
7230
|
const tasksPath = getTasksFilePath2();
|
|
7375
|
-
if (!tasksPath || !
|
|
7231
|
+
if (!tasksPath || !existsSync13(tasksPath)) return [];
|
|
7376
7232
|
try {
|
|
7377
|
-
const data = JSON.parse(
|
|
7233
|
+
const data = JSON.parse(readFileSync10(tasksPath, "utf-8"));
|
|
7378
7234
|
return data.tasks?.filter((t) => t.status === "active") || [];
|
|
7379
7235
|
} catch {
|
|
7380
7236
|
return [];
|
|
@@ -7383,7 +7239,7 @@ function loadActiveTasks() {
|
|
|
7383
7239
|
function getRunningProcesses() {
|
|
7384
7240
|
const processes = [];
|
|
7385
7241
|
try {
|
|
7386
|
-
const psOutput =
|
|
7242
|
+
const psOutput = execSync10(
|
|
7387
7243
|
'ps aux | grep -E "claude|squads|astro|node.*agent" | grep -v grep',
|
|
7388
7244
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7389
7245
|
).trim();
|
|
@@ -7434,7 +7290,7 @@ async function workersCommand(options = {}) {
|
|
|
7434
7290
|
writeLine();
|
|
7435
7291
|
if (options.kill) {
|
|
7436
7292
|
try {
|
|
7437
|
-
|
|
7293
|
+
execSync10(`kill ${options.kill}`, { stdio: "pipe" });
|
|
7438
7294
|
writeLine(` ${icons.success} Killed process ${colors.cyan}${options.kill}${RESET}`);
|
|
7439
7295
|
writeLine();
|
|
7440
7296
|
return;
|
|
@@ -7521,8 +7377,8 @@ function getElapsedTime2(startTime) {
|
|
|
7521
7377
|
}
|
|
7522
7378
|
|
|
7523
7379
|
// src/commands/context-feed.ts
|
|
7524
|
-
import { existsSync as
|
|
7525
|
-
import { join as
|
|
7380
|
+
import { existsSync as existsSync14, statSync as statSync3, readdirSync as readdirSync6, readFileSync as readFileSync11 } from "fs";
|
|
7381
|
+
import { join as join15 } from "path";
|
|
7526
7382
|
var BRIDGE_URL3 = process.env.SQUADS_BRIDGE_URL || "http://localhost:8088";
|
|
7527
7383
|
async function syncBriefToBridge(brief, sourcePath) {
|
|
7528
7384
|
try {
|
|
@@ -7551,10 +7407,10 @@ async function syncBriefToBridge(brief, sourcePath) {
|
|
|
7551
7407
|
}
|
|
7552
7408
|
function readBusinessBrief(squadsDir) {
|
|
7553
7409
|
if (!squadsDir) return void 0;
|
|
7554
|
-
const briefPath =
|
|
7555
|
-
if (!
|
|
7410
|
+
const briefPath = join15(squadsDir, "..", "BUSINESS_BRIEF.md");
|
|
7411
|
+
if (!existsSync14(briefPath)) return void 0;
|
|
7556
7412
|
try {
|
|
7557
|
-
const content =
|
|
7413
|
+
const content = readFileSync11(briefPath, "utf-8");
|
|
7558
7414
|
const brief = { raw: content };
|
|
7559
7415
|
const priorityMatch = content.match(/##\s*#1 Priority\s*\n+\*\*([^*]+)\*\*/);
|
|
7560
7416
|
if (priorityMatch) {
|
|
@@ -7604,7 +7460,7 @@ function readBusinessBrief(squadsDir) {
|
|
|
7604
7460
|
async function collectBriefingData(options) {
|
|
7605
7461
|
const squadsDir = findSquadsDir();
|
|
7606
7462
|
const memoryDir = findMemoryDir();
|
|
7607
|
-
const baseDir = squadsDir ?
|
|
7463
|
+
const baseDir = squadsDir ? join15(squadsDir, "..", "..", "..") : null;
|
|
7608
7464
|
const allSquads = squadsDir ? listSquads(squadsDir) : [];
|
|
7609
7465
|
if (options.squad && !allSquads.includes(options.squad)) {
|
|
7610
7466
|
return {
|
|
@@ -7644,14 +7500,14 @@ async function collectBriefingData(options) {
|
|
|
7644
7500
|
}
|
|
7645
7501
|
let lastActivity;
|
|
7646
7502
|
if (memoryDir) {
|
|
7647
|
-
const squadMemoryPath =
|
|
7648
|
-
if (
|
|
7503
|
+
const squadMemoryPath = join15(memoryDir, squadName);
|
|
7504
|
+
if (existsSync14(squadMemoryPath)) {
|
|
7649
7505
|
let mostRecent = 0;
|
|
7650
7506
|
try {
|
|
7651
7507
|
const walkDir = (dir) => {
|
|
7652
7508
|
const entries = readdirSync6(dir, { withFileTypes: true });
|
|
7653
7509
|
for (const entry of entries) {
|
|
7654
|
-
const fullPath =
|
|
7510
|
+
const fullPath = join15(dir, entry.name);
|
|
7655
7511
|
if (entry.isDirectory()) {
|
|
7656
7512
|
walkDir(fullPath);
|
|
7657
7513
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -7731,7 +7587,7 @@ async function collectBriefingData(options) {
|
|
|
7731
7587
|
}
|
|
7732
7588
|
const brief = readBusinessBrief(squadsDir);
|
|
7733
7589
|
if (brief && squadsDir) {
|
|
7734
|
-
const briefPath =
|
|
7590
|
+
const briefPath = join15(squadsDir, "..", "BUSINESS_BRIEF.md");
|
|
7735
7591
|
syncBriefToBridge(brief, briefPath).catch(() => {
|
|
7736
7592
|
});
|
|
7737
7593
|
}
|
|
@@ -7939,7 +7795,7 @@ async function runCommand2(command, args, clear) {
|
|
|
7939
7795
|
// src/commands/live.ts
|
|
7940
7796
|
import blessed from "blessed";
|
|
7941
7797
|
import contrib from "blessed-contrib";
|
|
7942
|
-
import { execSync as
|
|
7798
|
+
import { execSync as execSync11 } from "child_process";
|
|
7943
7799
|
async function liveCommand(_options) {
|
|
7944
7800
|
const screen = blessed.screen({
|
|
7945
7801
|
smartCSR: true,
|
|
@@ -7982,7 +7838,7 @@ async function liveCommand(_options) {
|
|
|
7982
7838
|
});
|
|
7983
7839
|
function getAgents() {
|
|
7984
7840
|
try {
|
|
7985
|
-
const output =
|
|
7841
|
+
const output = execSync11('ps aux | grep -E "claude|node.*squads" | grep -v grep', {
|
|
7986
7842
|
encoding: "utf-8",
|
|
7987
7843
|
timeout: 5e3
|
|
7988
7844
|
});
|
|
@@ -8031,7 +7887,7 @@ async function liveCommand(_options) {
|
|
|
8031
7887
|
}
|
|
8032
7888
|
function getRecentActivity2() {
|
|
8033
7889
|
try {
|
|
8034
|
-
const output =
|
|
7890
|
+
const output = execSync11(
|
|
8035
7891
|
"gh issue list --repo agents-squads/squads-cli --state open --limit 5 --json number,title,createdAt 2>/dev/null",
|
|
8036
7892
|
{ encoding: "utf-8", timeout: 1e4 }
|
|
8037
7893
|
);
|
|
@@ -8045,7 +7901,7 @@ async function liveCommand(_options) {
|
|
|
8045
7901
|
}
|
|
8046
7902
|
function getMemoryUpdates() {
|
|
8047
7903
|
try {
|
|
8048
|
-
const output =
|
|
7904
|
+
const output = execSync11(
|
|
8049
7905
|
'find .agents/memory -name "state.md" -mmin -60 2>/dev/null | head -5',
|
|
8050
7906
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
8051
7907
|
);
|
|
@@ -8121,7 +7977,7 @@ async function liveCommand(_options) {
|
|
|
8121
7977
|
}
|
|
8122
7978
|
|
|
8123
7979
|
// src/commands/top.ts
|
|
8124
|
-
import { execSync as
|
|
7980
|
+
import { execSync as execSync12 } from "child_process";
|
|
8125
7981
|
var ESC = "\x1B";
|
|
8126
7982
|
var CLEAR_SCREEN = `${ESC}[2J`;
|
|
8127
7983
|
var CURSOR_HOME = `${ESC}[H`;
|
|
@@ -8155,7 +8011,7 @@ function getProcessData() {
|
|
|
8155
8011
|
let claudeCount = 0;
|
|
8156
8012
|
let agentCount = 0;
|
|
8157
8013
|
try {
|
|
8158
|
-
const psOutput =
|
|
8014
|
+
const psOutput = execSync12(
|
|
8159
8015
|
'ps aux | grep -E "[c]laude" | head -15',
|
|
8160
8016
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
8161
8017
|
);
|
|
@@ -8180,7 +8036,7 @@ function getProcessData() {
|
|
|
8180
8036
|
} catch {
|
|
8181
8037
|
}
|
|
8182
8038
|
try {
|
|
8183
|
-
const tmuxOutput =
|
|
8039
|
+
const tmuxOutput = execSync12("tmux ls 2>/dev/null | grep squads- | wc -l", { encoding: "utf-8" });
|
|
8184
8040
|
agentCount = parseInt(tmuxOutput.trim()) || 0;
|
|
8185
8041
|
} catch {
|
|
8186
8042
|
}
|
|
@@ -8283,7 +8139,7 @@ async function detectSquadCommand() {
|
|
|
8283
8139
|
|
|
8284
8140
|
// src/commands/trigger.ts
|
|
8285
8141
|
import chalk3 from "chalk";
|
|
8286
|
-
import { existsSync as
|
|
8142
|
+
import { existsSync as existsSync15 } from "fs";
|
|
8287
8143
|
var SCHEDULER_URL = process.env.SCHEDULER_URL || "http://localhost:8090";
|
|
8288
8144
|
async function fetchScheduler(path3, options) {
|
|
8289
8145
|
const res = await fetch(`${SCHEDULER_URL}${path3}`, {
|
|
@@ -8329,12 +8185,12 @@ async function listTriggers(squad) {
|
|
|
8329
8185
|
}
|
|
8330
8186
|
async function syncTriggers() {
|
|
8331
8187
|
console.log(chalk3.gray("Syncing triggers from SQUAD.md files...\n"));
|
|
8332
|
-
const { execSync:
|
|
8188
|
+
const { execSync: execSync14 } = await import("child_process");
|
|
8333
8189
|
const hqPath = process.env.HQ_PATH || `${process.env.HOME}/agents-squads/hq`;
|
|
8334
8190
|
try {
|
|
8335
8191
|
const venvPython = `${hqPath}/squads-scheduler/.venv/bin/python`;
|
|
8336
|
-
const pythonCmd =
|
|
8337
|
-
const output =
|
|
8192
|
+
const pythonCmd = existsSync15(venvPython) ? venvPython : "python3";
|
|
8193
|
+
const output = execSync14(
|
|
8338
8194
|
`${pythonCmd} ${hqPath}/squads-scheduler/sync_triggers.py`,
|
|
8339
8195
|
{ encoding: "utf-8", cwd: hqPath }
|
|
8340
8196
|
);
|
|
@@ -8417,13 +8273,13 @@ function registerTriggerCommand(program2) {
|
|
|
8417
8273
|
|
|
8418
8274
|
// src/commands/skill.ts
|
|
8419
8275
|
import ora6 from "ora";
|
|
8420
|
-
import { existsSync as
|
|
8421
|
-
import { join as
|
|
8276
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, readFileSync as readFileSync13 } from "fs";
|
|
8277
|
+
import { join as join17, basename as basename2, dirname as dirname4 } from "path";
|
|
8422
8278
|
|
|
8423
8279
|
// src/lib/anthropic.ts
|
|
8424
8280
|
import Anthropic from "@anthropic-ai/sdk";
|
|
8425
|
-
import { readFileSync as
|
|
8426
|
-
import { join as
|
|
8281
|
+
import { readFileSync as readFileSync12, readdirSync as readdirSync7 } from "fs";
|
|
8282
|
+
import { join as join16 } from "path";
|
|
8427
8283
|
var client = null;
|
|
8428
8284
|
function getClient() {
|
|
8429
8285
|
if (!client) {
|
|
@@ -8452,12 +8308,12 @@ function loadSkillFiles(skillPath) {
|
|
|
8452
8308
|
function walkDir(dir, prefix = "") {
|
|
8453
8309
|
const entries = readdirSync7(dir, { withFileTypes: true });
|
|
8454
8310
|
for (const entry of entries) {
|
|
8455
|
-
const fullPath =
|
|
8311
|
+
const fullPath = join16(dir, entry.name);
|
|
8456
8312
|
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
8457
8313
|
if (entry.isDirectory()) {
|
|
8458
8314
|
walkDir(fullPath, relativePath);
|
|
8459
8315
|
} else if (entry.isFile()) {
|
|
8460
|
-
const content =
|
|
8316
|
+
const content = readFileSync12(fullPath, "utf-8");
|
|
8461
8317
|
files.push({
|
|
8462
8318
|
name: relativePath,
|
|
8463
8319
|
content
|
|
@@ -8621,14 +8477,14 @@ async function skillUploadCommand(skillPath) {
|
|
|
8621
8477
|
writeLine();
|
|
8622
8478
|
return;
|
|
8623
8479
|
}
|
|
8624
|
-
const fullPath = skillPath.startsWith("/") ? skillPath :
|
|
8625
|
-
if (!
|
|
8480
|
+
const fullPath = skillPath.startsWith("/") ? skillPath : join17(process.cwd(), skillPath);
|
|
8481
|
+
if (!existsSync16(fullPath)) {
|
|
8626
8482
|
writeLine(` ${icons.error} ${colors.red}Directory not found: ${skillPath}${RESET}`);
|
|
8627
8483
|
writeLine();
|
|
8628
8484
|
return;
|
|
8629
8485
|
}
|
|
8630
|
-
const skillMdPath =
|
|
8631
|
-
if (!
|
|
8486
|
+
const skillMdPath = join17(fullPath, "SKILL.md");
|
|
8487
|
+
if (!existsSync16(skillMdPath)) {
|
|
8632
8488
|
writeLine(` ${icons.error} ${colors.red}SKILL.md not found in ${skillPath}${RESET}`);
|
|
8633
8489
|
writeLine();
|
|
8634
8490
|
writeLine(` ${colors.dim}Create a SKILL.md file or use:${RESET}`);
|
|
@@ -8739,7 +8595,7 @@ async function skillConvertCommand(agentPath, options) {
|
|
|
8739
8595
|
const [squad, agent] = agentPath.split("/");
|
|
8740
8596
|
squadName = squad;
|
|
8741
8597
|
agentName = agent.replace(".md", "");
|
|
8742
|
-
agentFilePath =
|
|
8598
|
+
agentFilePath = join17(squadsDir, squad, `${agentName}.md`);
|
|
8743
8599
|
} else {
|
|
8744
8600
|
agentName = agentPath.replace(".md", "");
|
|
8745
8601
|
const foundPath = findAgentFile(squadsDir, agentName);
|
|
@@ -8750,22 +8606,22 @@ async function skillConvertCommand(agentPath, options) {
|
|
|
8750
8606
|
return;
|
|
8751
8607
|
}
|
|
8752
8608
|
agentFilePath = foundPath;
|
|
8753
|
-
squadName = basename2(
|
|
8609
|
+
squadName = basename2(dirname4(agentFilePath));
|
|
8754
8610
|
}
|
|
8755
|
-
if (!
|
|
8611
|
+
if (!existsSync16(agentFilePath)) {
|
|
8756
8612
|
writeLine(` ${icons.error} ${colors.red}Agent file not found: ${agentFilePath}${RESET}`);
|
|
8757
8613
|
writeLine();
|
|
8758
8614
|
return;
|
|
8759
8615
|
}
|
|
8760
|
-
const agentContent =
|
|
8616
|
+
const agentContent = readFileSync13(agentFilePath, "utf-8");
|
|
8761
8617
|
const skillName = `${squadName}-${agentName}`;
|
|
8762
|
-
const outputDir = options.output ||
|
|
8763
|
-
if (!
|
|
8764
|
-
|
|
8618
|
+
const outputDir = options.output || join17(dirname4(squadsDir), "skills", skillName);
|
|
8619
|
+
if (!existsSync16(outputDir)) {
|
|
8620
|
+
mkdirSync8(outputDir, { recursive: true });
|
|
8765
8621
|
}
|
|
8766
8622
|
const skillMd = convertAgentToSkill(agentContent, squadName, agentName);
|
|
8767
|
-
const skillMdPath =
|
|
8768
|
-
|
|
8623
|
+
const skillMdPath = join17(outputDir, "SKILL.md");
|
|
8624
|
+
writeFileSync9(skillMdPath, skillMd);
|
|
8769
8625
|
writeLine(` ${icons.success} ${colors.green}Converted:${RESET} ${agentPath}`);
|
|
8770
8626
|
writeLine();
|
|
8771
8627
|
writeLine(` ${colors.dim}Output:${RESET} ${outputDir}`);
|
|
@@ -8782,8 +8638,8 @@ function findAgentFile(squadsDir, agentName) {
|
|
|
8782
8638
|
const { readdirSync: readdirSync9 } = __require("fs");
|
|
8783
8639
|
const squads = readdirSync9(squadsDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("_")).map((d) => d.name);
|
|
8784
8640
|
for (const squad of squads) {
|
|
8785
|
-
const agentPath =
|
|
8786
|
-
if (
|
|
8641
|
+
const agentPath = join17(squadsDir, squad, `${agentName}.md`);
|
|
8642
|
+
if (existsSync16(agentPath)) {
|
|
8787
8643
|
return agentPath;
|
|
8788
8644
|
}
|
|
8789
8645
|
}
|
|
@@ -8824,8 +8680,8 @@ function formatBytes(bytes) {
|
|
|
8824
8680
|
}
|
|
8825
8681
|
|
|
8826
8682
|
// src/commands/permissions.ts
|
|
8827
|
-
import { readFileSync as
|
|
8828
|
-
import { join as
|
|
8683
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
8684
|
+
import { join as join18 } from "path";
|
|
8829
8685
|
function registerPermissionsCommand(program2) {
|
|
8830
8686
|
const permissions = program2.command("permissions").alias("perms").description("Manage and validate squad permissions");
|
|
8831
8687
|
permissions.command("show <squad>").description("Show permission context for a squad").action(permissionsShowCommand);
|
|
@@ -8847,8 +8703,8 @@ async function permissionsShowCommand(squadName) {
|
|
|
8847
8703
|
writeLine();
|
|
8848
8704
|
return;
|
|
8849
8705
|
}
|
|
8850
|
-
const squadFilePath =
|
|
8851
|
-
const squadContent =
|
|
8706
|
+
const squadFilePath = join18(squadsDir, squadName, "SQUAD.md");
|
|
8707
|
+
const squadContent = readFileSync14(squadFilePath, "utf-8");
|
|
8852
8708
|
const context2 = buildContextFromSquad(squadName, squadContent);
|
|
8853
8709
|
const defaults = getDefaultContext(squadName);
|
|
8854
8710
|
const isDefault = JSON.stringify(context2.permissions) === JSON.stringify(defaults.permissions);
|
|
@@ -8942,8 +8798,8 @@ async function permissionsCheckCommand(squadName, options) {
|
|
|
8942
8798
|
writeLine();
|
|
8943
8799
|
return;
|
|
8944
8800
|
}
|
|
8945
|
-
const squadFilePath =
|
|
8946
|
-
const squadContent =
|
|
8801
|
+
const squadFilePath = join18(squadsDir, squadName, "SQUAD.md");
|
|
8802
|
+
const squadContent = readFileSync14(squadFilePath, "utf-8");
|
|
8947
8803
|
const context2 = buildContextFromSquad(squadName, squadContent, options.agent);
|
|
8948
8804
|
const request = {
|
|
8949
8805
|
mcpServers: options.mcp,
|
|
@@ -9376,8 +9232,8 @@ function createBudgetBar(percent, width = 10) {
|
|
|
9376
9232
|
}
|
|
9377
9233
|
|
|
9378
9234
|
// src/lib/executions.ts
|
|
9379
|
-
import { readFileSync as
|
|
9380
|
-
import { join as
|
|
9235
|
+
import { readFileSync as readFileSync15, existsSync as existsSync17, readdirSync as readdirSync8 } from "fs";
|
|
9236
|
+
import { join as join19 } from "path";
|
|
9381
9237
|
function parseExecutionEntry(content, squad, agent) {
|
|
9382
9238
|
const idMatch = content.match(/<!-- exec:(\S+) -->/);
|
|
9383
9239
|
if (!idMatch) return null;
|
|
@@ -9415,8 +9271,8 @@ function parseExecutionEntry(content, squad, agent) {
|
|
|
9415
9271
|
};
|
|
9416
9272
|
}
|
|
9417
9273
|
function parseExecutionLog(filePath, squad, agent) {
|
|
9418
|
-
if (!
|
|
9419
|
-
const content =
|
|
9274
|
+
if (!existsSync17(filePath)) return [];
|
|
9275
|
+
const content = readFileSync15(filePath, "utf-8");
|
|
9420
9276
|
const executions = [];
|
|
9421
9277
|
const entries = content.split(/\n---\n/);
|
|
9422
9278
|
for (const entry of entries) {
|
|
@@ -9454,11 +9310,11 @@ function listExecutions(options = {}) {
|
|
|
9454
9310
|
const squads = readdirSync8(memoryDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
9455
9311
|
for (const squad of squads) {
|
|
9456
9312
|
if (filterSquad && squad !== filterSquad) continue;
|
|
9457
|
-
const squadPath =
|
|
9313
|
+
const squadPath = join19(memoryDir, squad);
|
|
9458
9314
|
const agents = readdirSync8(squadPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
9459
9315
|
for (const agent of agents) {
|
|
9460
9316
|
if (filterAgent && agent !== filterAgent) continue;
|
|
9461
|
-
const logPath =
|
|
9317
|
+
const logPath = join19(squadPath, agent, "executions.md");
|
|
9462
9318
|
const agentExecutions = parseExecutionLog(logPath, squad, agent);
|
|
9463
9319
|
executions.push(...agentExecutions);
|
|
9464
9320
|
}
|
|
@@ -9708,12 +9564,12 @@ async function execStatsCommand(options = {}) {
|
|
|
9708
9564
|
// src/commands/tonight.ts
|
|
9709
9565
|
import ora7 from "ora";
|
|
9710
9566
|
import fs2 from "fs/promises";
|
|
9711
|
-
import path2, { dirname as
|
|
9712
|
-
import { execSync as
|
|
9567
|
+
import path2, { dirname as dirname5 } from "path";
|
|
9568
|
+
import { execSync as execSync13, spawn as spawn7 } from "child_process";
|
|
9713
9569
|
function getProjectRoot2() {
|
|
9714
9570
|
const squadsDir = findSquadsDir();
|
|
9715
9571
|
if (squadsDir) {
|
|
9716
|
-
return
|
|
9572
|
+
return dirname5(dirname5(squadsDir));
|
|
9717
9573
|
}
|
|
9718
9574
|
return process.cwd();
|
|
9719
9575
|
}
|
|
@@ -9732,10 +9588,10 @@ async function getCurrentCost() {
|
|
|
9732
9588
|
}
|
|
9733
9589
|
function killAllSessions() {
|
|
9734
9590
|
try {
|
|
9735
|
-
const sessions2 =
|
|
9591
|
+
const sessions2 = execSync13('tmux ls 2>/dev/null | grep "squads-tonight-" | cut -d: -f1', { encoding: "utf-8" }).trim().split("\n").filter(Boolean);
|
|
9736
9592
|
for (const session2 of sessions2) {
|
|
9737
9593
|
try {
|
|
9738
|
-
|
|
9594
|
+
execSync13(`tmux kill-session -t "${session2}"`, { stdio: "ignore" });
|
|
9739
9595
|
} catch {
|
|
9740
9596
|
}
|
|
9741
9597
|
}
|
|
@@ -9746,7 +9602,7 @@ function killAllSessions() {
|
|
|
9746
9602
|
}
|
|
9747
9603
|
function getRunningSessionCount() {
|
|
9748
9604
|
try {
|
|
9749
|
-
const output =
|
|
9605
|
+
const output = execSync13('tmux ls 2>/dev/null | grep "squads-tonight-" | wc -l', { encoding: "utf-8" });
|
|
9750
9606
|
return parseInt(output.trim()) || 0;
|
|
9751
9607
|
} catch {
|
|
9752
9608
|
return 0;
|
|
@@ -9961,7 +9817,7 @@ async function tonightStatusCommand() {
|
|
|
9961
9817
|
}
|
|
9962
9818
|
writeLine();
|
|
9963
9819
|
try {
|
|
9964
|
-
const sessions2 =
|
|
9820
|
+
const sessions2 = execSync13("tmux ls 2>/dev/null | grep squads-tonight", { encoding: "utf-8" }).trim().split("\n").filter(Boolean);
|
|
9965
9821
|
if (sessions2.length > 0) {
|
|
9966
9822
|
writeLine(` ${colors.dim}Sessions:${RESET}`);
|
|
9967
9823
|
for (const session2 of sessions2) {
|
|
@@ -10041,17 +9897,18 @@ process.stderr.on("error", (err) => {
|
|
|
10041
9897
|
throw err;
|
|
10042
9898
|
});
|
|
10043
9899
|
var envPaths = [
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
9900
|
+
join20(process.cwd(), ".env"),
|
|
9901
|
+
join20(process.cwd(), "..", "hq", ".env"),
|
|
9902
|
+
join20(homedir4(), "agents-squads", "hq", ".env")
|
|
10047
9903
|
];
|
|
10048
9904
|
for (const envPath of envPaths) {
|
|
10049
|
-
if (
|
|
9905
|
+
if (existsSync18(envPath)) {
|
|
10050
9906
|
config({ path: envPath, quiet: true });
|
|
10051
9907
|
break;
|
|
10052
9908
|
}
|
|
10053
9909
|
}
|
|
10054
9910
|
applyStackConfig();
|
|
9911
|
+
await autoUpdateOnStartup();
|
|
10055
9912
|
registerExitHandler();
|
|
10056
9913
|
var program = new Command();
|
|
10057
9914
|
program.name("squads").description("A CLI for humans and agents").version(version).showSuggestionAfterError(true).configureOutput({
|
|
@@ -10064,6 +9921,19 @@ program.name("squads").description("A CLI for humans and agents").version(versio
|
|
|
10064
9921
|
process.exit(err.exitCode);
|
|
10065
9922
|
}
|
|
10066
9923
|
throw err;
|
|
9924
|
+
}).action(async () => {
|
|
9925
|
+
const { gradient: gradient2, colors: colors2, RESET: RESET3 } = await import("./terminal-JZSAQSN7.js");
|
|
9926
|
+
const { checkForUpdate: checkForUpdate2 } = await import("./update-MAY6EXFQ.js");
|
|
9927
|
+
console.log();
|
|
9928
|
+
console.log(` ${gradient2("squads")} ${colors2.dim}v${version}${RESET3}`);
|
|
9929
|
+
console.log();
|
|
9930
|
+
const updateInfo = checkForUpdate2();
|
|
9931
|
+
if (updateInfo.updateAvailable) {
|
|
9932
|
+
console.log(` ${colors2.cyan}\u2B06${RESET3} Update available: ${colors2.dim}${updateInfo.currentVersion}${RESET3} \u2192 ${colors2.green}${updateInfo.latestVersion}${RESET3}`);
|
|
9933
|
+
console.log(` ${colors2.dim}Run \`squads update\` to install${RESET3}`);
|
|
9934
|
+
console.log();
|
|
9935
|
+
}
|
|
9936
|
+
await statusCommand(void 0, {});
|
|
10067
9937
|
});
|
|
10068
9938
|
program.command("init").description("Initialize a new squad project").option("-t, --template <template>", "Project template", "default").option("--skip-infra", "Skip infrastructure setup prompt").action(initCommand);
|
|
10069
9939
|
program.command("run <target>").description("Run a squad or agent").option("-v, --verbose", "Verbose output").option("-d, --dry-run", "Show what would be run without executing").option("-e, --execute", "Execute agent via Claude CLI (requires claude installed)").option("-a, --agent <agent>", "Run specific agent within squad").option("-t, --timeout <minutes>", "Execution timeout in minutes (default: 30)", "30").option("-p, --parallel", "Run all agents in parallel (N tmux sessions)").option("-l, --lead", "Lead mode: single orchestrator using Task tool for parallelization").option("-f, --foreground", "Run in foreground (no tmux, blocks terminal)").option("--use-api", "Use API credits instead of subscription").option("--effort <level>", "Effort level: high, medium, low (default: from SQUAD.md or high)").option("--skills <skills...>", "Skills to load (skill IDs or local paths)").action((target, options) => runCommand(target, { ...options, timeout: parseInt(options.timeout, 10) }));
|
|
@@ -10133,11 +10003,11 @@ sessions.command("history").description("Show session history and statistics").o
|
|
|
10133
10003
|
json: options.json
|
|
10134
10004
|
}));
|
|
10135
10005
|
sessions.command("summary").description("Show pretty session summary (auto-detects current session or pass JSON)").option("-d, --data <json>", "JSON data for summary (overrides auto-detection)").option("-f, --file <path>", "Path to JSON file with summary data").option("-j, --json", "Output as JSON instead of pretty format").action(async (options) => {
|
|
10136
|
-
const { buildCurrentSessionSummary } = await import("./sessions-
|
|
10006
|
+
const { buildCurrentSessionSummary } = await import("./sessions-R4VWIGFR.js");
|
|
10137
10007
|
let data;
|
|
10138
10008
|
if (options.file) {
|
|
10139
|
-
const { readFileSync:
|
|
10140
|
-
data = JSON.parse(
|
|
10009
|
+
const { readFileSync: readFileSync16 } = await import("fs");
|
|
10010
|
+
data = JSON.parse(readFileSync16(options.file, "utf-8"));
|
|
10141
10011
|
} else if (options.data) {
|
|
10142
10012
|
data = JSON.parse(options.data);
|
|
10143
10013
|
} else if (!process.stdin.isTTY) {
|
|
@@ -10233,31 +10103,4 @@ try {
|
|
|
10233
10103
|
} catch (error) {
|
|
10234
10104
|
handleError(error);
|
|
10235
10105
|
}
|
|
10236
|
-
if (!process.argv.slice(2).length) {
|
|
10237
|
-
console.log(`
|
|
10238
|
-
${chalk4.bold.magenta("squads")} - AI agent squad management
|
|
10239
|
-
|
|
10240
|
-
${chalk4.dim("Quick start:")}
|
|
10241
|
-
${chalk4.cyan("squads status")} View all squads status
|
|
10242
|
-
${chalk4.cyan("squads run <squad>")} Run a squad
|
|
10243
|
-
${chalk4.cyan('squads memory query "<term>"')} Search squad memory
|
|
10244
|
-
|
|
10245
|
-
${chalk4.dim("Goals & Feedback:")}
|
|
10246
|
-
${chalk4.cyan('squads goal set <squad> "<goal>"')} Set a goal
|
|
10247
|
-
${chalk4.cyan("squads goal list")} View active goals
|
|
10248
|
-
${chalk4.cyan('squads feedback add <squad> 4 "msg"')} Rate last execution
|
|
10249
|
-
|
|
10250
|
-
${chalk4.dim("Smart Triggers:")}
|
|
10251
|
-
${chalk4.cyan("squads trigger list")} View all triggers
|
|
10252
|
-
${chalk4.cyan("squads trigger sync")} Sync from SQUAD.md
|
|
10253
|
-
${chalk4.cyan("squads trigger fire <name>")} Manually fire trigger
|
|
10254
|
-
|
|
10255
|
-
${chalk4.dim("Examples:")}
|
|
10256
|
-
${chalk4.cyan("squads run website")} Run website squad
|
|
10257
|
-
${chalk4.cyan('squads goal set finance "Track costs"')} Set finance goal
|
|
10258
|
-
${chalk4.cyan("squads trigger status")} Scheduler health
|
|
10259
|
-
|
|
10260
|
-
${chalk4.dim("Run")} ${chalk4.cyan("squads --help")} ${chalk4.dim("for all commands.")}
|
|
10261
|
-
`);
|
|
10262
|
-
}
|
|
10263
10106
|
//# sourceMappingURL=cli.js.map
|