squads-cli 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +116 -95
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1655,6 +1655,72 @@ function buildContextFromSquad(squadName, squadContent, agentName) {
|
|
|
1655
1655
|
return context;
|
|
1656
1656
|
}
|
|
1657
1657
|
|
|
1658
|
+
// src/lib/cron.ts
|
|
1659
|
+
function cronMatches(cron, date) {
|
|
1660
|
+
const parts = cron.trim().split(/\s+/);
|
|
1661
|
+
if (parts.length < 5) return false;
|
|
1662
|
+
const fields = [
|
|
1663
|
+
{ value: date.getMinutes(), field: parts[0], min: 0, max: 59 },
|
|
1664
|
+
{ value: date.getHours(), field: parts[1], min: 0, max: 23 },
|
|
1665
|
+
{ value: date.getDate(), field: parts[2], min: 1, max: 31 },
|
|
1666
|
+
{ value: date.getMonth() + 1, field: parts[3], min: 1, max: 12 },
|
|
1667
|
+
{ value: date.getDay(), field: parts[4], min: 0, max: 6 }
|
|
1668
|
+
];
|
|
1669
|
+
return fields.every(
|
|
1670
|
+
({ value, field, min, max }) => fieldMatches(field, value, min, max)
|
|
1671
|
+
);
|
|
1672
|
+
}
|
|
1673
|
+
function fieldMatches(field, value, min, max) {
|
|
1674
|
+
if (field.includes(",")) {
|
|
1675
|
+
return field.split(",").some((part) => fieldMatches(part.trim(), value, min, max));
|
|
1676
|
+
}
|
|
1677
|
+
if (field.includes("/")) {
|
|
1678
|
+
const [range, stepStr] = field.split("/");
|
|
1679
|
+
const step = parseInt(stepStr);
|
|
1680
|
+
if (isNaN(step) || step <= 0) return false;
|
|
1681
|
+
let start = min;
|
|
1682
|
+
let end = max;
|
|
1683
|
+
if (range !== "*") {
|
|
1684
|
+
if (range.includes("-")) {
|
|
1685
|
+
[start, end] = range.split("-").map(Number);
|
|
1686
|
+
} else {
|
|
1687
|
+
start = parseInt(range);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
if (value < start || value > end) return false;
|
|
1691
|
+
return (value - start) % step === 0;
|
|
1692
|
+
}
|
|
1693
|
+
if (field.includes("-")) {
|
|
1694
|
+
const [start, end] = field.split("-").map(Number);
|
|
1695
|
+
return value >= start && value <= end;
|
|
1696
|
+
}
|
|
1697
|
+
if (field === "*") return true;
|
|
1698
|
+
return parseInt(field) === value;
|
|
1699
|
+
}
|
|
1700
|
+
function getNextCronRun(cron, after = /* @__PURE__ */ new Date()) {
|
|
1701
|
+
const next = new Date(after);
|
|
1702
|
+
next.setSeconds(0, 0);
|
|
1703
|
+
next.setMinutes(next.getMinutes() + 1);
|
|
1704
|
+
const maxIterations = 60 * 48;
|
|
1705
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
1706
|
+
if (cronMatches(cron, next)) return next;
|
|
1707
|
+
next.setMinutes(next.getMinutes() + 1);
|
|
1708
|
+
}
|
|
1709
|
+
const fallback = new Date(after);
|
|
1710
|
+
fallback.setDate(fallback.getDate() + 1);
|
|
1711
|
+
return fallback;
|
|
1712
|
+
}
|
|
1713
|
+
function parseCooldown(cooldown) {
|
|
1714
|
+
const match = cooldown.match(/^(\d+)\s*(m|min|minutes?|h|hours?|d|days?)$/i);
|
|
1715
|
+
if (!match) return 0;
|
|
1716
|
+
const value = parseInt(match[1]);
|
|
1717
|
+
const unit = match[2].toLowerCase();
|
|
1718
|
+
if (unit.startsWith("m")) return value * 60 * 1e3;
|
|
1719
|
+
if (unit.startsWith("h")) return value * 60 * 60 * 1e3;
|
|
1720
|
+
if (unit.startsWith("d")) return value * 24 * 60 * 60 * 1e3;
|
|
1721
|
+
return 0;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1658
1724
|
// src/lib/llm-clis.ts
|
|
1659
1725
|
import { execSync as execSync3 } from "child_process";
|
|
1660
1726
|
function commandExists2(command) {
|
|
@@ -2021,8 +2087,26 @@ function getProviderDisplayName(provider) {
|
|
|
2021
2087
|
|
|
2022
2088
|
// src/commands/run.ts
|
|
2023
2089
|
import { homedir as homedir3 } from "os";
|
|
2090
|
+
var DEFAULT_BRIDGE_URL = "http://localhost:8088";
|
|
2091
|
+
var DEFAULT_LEARNINGS_LIMIT = 5;
|
|
2092
|
+
var DEFAULT_CONTEXT_TOKENS = 8e3;
|
|
2093
|
+
var DEFAULT_FALLBACK_CHARS = 2e3;
|
|
2094
|
+
var MAX_AGENT_BRIEFS = 3;
|
|
2095
|
+
var MAX_SQUAD_BRIEFS = 2;
|
|
2096
|
+
var MAX_LEARNINGS_CHARS = 1500;
|
|
2097
|
+
var MAX_LEAD_STATE_CHARS = 1e3;
|
|
2098
|
+
var EXECUTION_EVENT_TIMEOUT_MS = 5e3;
|
|
2099
|
+
var VERIFICATION_STATE_MAX_CHARS = 2e3;
|
|
2100
|
+
var VERIFICATION_EXEC_TIMEOUT_MS = 3e4;
|
|
2101
|
+
var DRYRUN_DEF_MAX_CHARS = 500;
|
|
2102
|
+
var DRYRUN_CONTEXT_MAX_CHARS = 800;
|
|
2103
|
+
var DEFAULT_SCHEDULED_COOLDOWN_MS = 6 * 60 * 60 * 1e3;
|
|
2104
|
+
var DEFAULT_TIMEOUT_MINUTES = 30;
|
|
2105
|
+
var SOFT_DEADLINE_RATIO = 0.7;
|
|
2106
|
+
var LOG_FILE_INIT_DELAY_MS = 500;
|
|
2107
|
+
var VERBOSE_COMMAND_MAX_CHARS = 50;
|
|
2024
2108
|
async function registerContextWithBridge(ctx) {
|
|
2025
|
-
const bridgeUrl = process.env.SQUADS_BRIDGE_URL ||
|
|
2109
|
+
const bridgeUrl = process.env.SQUADS_BRIDGE_URL || DEFAULT_BRIDGE_URL;
|
|
2026
2110
|
try {
|
|
2027
2111
|
const response = await fetch(`${bridgeUrl}/api/context/register`, {
|
|
2028
2112
|
method: "POST",
|
|
@@ -2044,7 +2128,7 @@ async function registerContextWithBridge(ctx) {
|
|
|
2044
2128
|
}
|
|
2045
2129
|
}
|
|
2046
2130
|
async function checkPreflightGates(squad, agent) {
|
|
2047
|
-
const bridgeUrl = process.env.SQUADS_BRIDGE_URL ||
|
|
2131
|
+
const bridgeUrl = process.env.SQUADS_BRIDGE_URL || DEFAULT_BRIDGE_URL;
|
|
2048
2132
|
try {
|
|
2049
2133
|
const response = await fetch(`${bridgeUrl}/api/execution/preflight`, {
|
|
2050
2134
|
method: "POST",
|
|
@@ -2059,8 +2143,8 @@ async function checkPreflightGates(squad, agent) {
|
|
|
2059
2143
|
return { allowed: true, gates: {} };
|
|
2060
2144
|
}
|
|
2061
2145
|
}
|
|
2062
|
-
async function fetchLearnings(squad, limit =
|
|
2063
|
-
const bridgeUrl = process.env.SQUADS_BRIDGE_URL ||
|
|
2146
|
+
async function fetchLearnings(squad, limit = DEFAULT_LEARNINGS_LIMIT) {
|
|
2147
|
+
const bridgeUrl = process.env.SQUADS_BRIDGE_URL || DEFAULT_BRIDGE_URL;
|
|
2064
2148
|
try {
|
|
2065
2149
|
const response = await fetch(
|
|
2066
2150
|
`${bridgeUrl}/api/learnings/relevant?squad=${encodeURIComponent(squad)}&limit=${limit}`
|
|
@@ -2091,7 +2175,7 @@ function gatherSquadContext(squadName, agentName, options = {}) {
|
|
|
2091
2175
|
const squadsDir = findSquadsDir();
|
|
2092
2176
|
if (!squadsDir) return "";
|
|
2093
2177
|
const memoryDir = findMemoryDir();
|
|
2094
|
-
const maxTokens = options.maxTokens ||
|
|
2178
|
+
const maxTokens = options.maxTokens || DEFAULT_CONTEXT_TOKENS;
|
|
2095
2179
|
const sections = [];
|
|
2096
2180
|
let estimatedTokens = 0;
|
|
2097
2181
|
const estimateTokens = (text) => Math.ceil(text.length / 4);
|
|
@@ -2109,7 +2193,7 @@ function gatherSquadContext(squadName, agentName, options = {}) {
|
|
|
2109
2193
|
if (outputMatch) squadContext += outputMatch[0] + "\n";
|
|
2110
2194
|
if (contextMatch) squadContext += contextMatch[0] + "\n";
|
|
2111
2195
|
if (!squadContext && squadContent.length > 0) {
|
|
2112
|
-
squadContext = squadContent.substring(0,
|
|
2196
|
+
squadContext = squadContent.substring(0, DEFAULT_FALLBACK_CHARS);
|
|
2113
2197
|
}
|
|
2114
2198
|
if (squadContext) {
|
|
2115
2199
|
const tokens = estimateTokens(squadContext);
|
|
@@ -2143,7 +2227,7 @@ ${stateContent.trim()}`);
|
|
|
2143
2227
|
const briefsDir = join4(memoryDir, squadName, agentName, "briefs");
|
|
2144
2228
|
if (existsSync4(briefsDir)) {
|
|
2145
2229
|
try {
|
|
2146
|
-
const briefFiles = readdirSync2(briefsDir).filter((f) => f.endsWith(".md")).slice(0,
|
|
2230
|
+
const briefFiles = readdirSync2(briefsDir).filter((f) => f.endsWith(".md")).slice(0, MAX_AGENT_BRIEFS);
|
|
2147
2231
|
for (const briefFile of briefFiles) {
|
|
2148
2232
|
const briefPath = join4(briefsDir, briefFile);
|
|
2149
2233
|
const briefContent = readFileSync3(briefPath, "utf-8");
|
|
@@ -2164,7 +2248,7 @@ ${briefContent.trim()}`);
|
|
|
2164
2248
|
const squadBriefsDir = join4(memoryDir, squadName, "_briefs");
|
|
2165
2249
|
if (existsSync4(squadBriefsDir)) {
|
|
2166
2250
|
try {
|
|
2167
|
-
const squadBriefs = readdirSync2(squadBriefsDir).filter((f) => f.endsWith(".md")).slice(0,
|
|
2251
|
+
const squadBriefs = readdirSync2(squadBriefsDir).filter((f) => f.endsWith(".md")).slice(0, MAX_SQUAD_BRIEFS);
|
|
2168
2252
|
for (const briefFile of squadBriefs) {
|
|
2169
2253
|
const briefPath = join4(squadBriefsDir, briefFile);
|
|
2170
2254
|
const briefContent = readFileSync3(briefPath, "utf-8");
|
|
@@ -2207,8 +2291,8 @@ ${briefingContent.trim()}`);
|
|
|
2207
2291
|
try {
|
|
2208
2292
|
let learningsContent = readFileSync3(learningsPath, "utf-8");
|
|
2209
2293
|
if (learningsContent.trim()) {
|
|
2210
|
-
if (learningsContent.length >
|
|
2211
|
-
learningsContent = learningsContent.slice(0,
|
|
2294
|
+
if (learningsContent.length > MAX_LEARNINGS_CHARS) {
|
|
2295
|
+
learningsContent = learningsContent.slice(0, MAX_LEARNINGS_CHARS) + "\n...(truncated)";
|
|
2212
2296
|
}
|
|
2213
2297
|
const tokens = estimateTokens(learningsContent);
|
|
2214
2298
|
if (estimatedTokens + tokens < maxTokens) {
|
|
@@ -2225,8 +2309,8 @@ ${learningsContent.trim()}`);
|
|
|
2225
2309
|
try {
|
|
2226
2310
|
let leadState = readFileSync3(leadStatePath, "utf-8");
|
|
2227
2311
|
if (leadState.trim()) {
|
|
2228
|
-
if (leadState.length >
|
|
2229
|
-
leadState = leadState.slice(0,
|
|
2312
|
+
if (leadState.length > MAX_LEAD_STATE_CHARS) {
|
|
2313
|
+
leadState = leadState.slice(0, MAX_LEAD_STATE_CHARS) + "\n...(truncated)";
|
|
2230
2314
|
}
|
|
2231
2315
|
const tokens = estimateTokens(leadState);
|
|
2232
2316
|
if (estimatedTokens + tokens < maxTokens) {
|
|
@@ -2518,6 +2602,10 @@ function parseAgentFrontmatter(agentPath) {
|
|
|
2518
2602
|
if (retriesMatch) {
|
|
2519
2603
|
result.max_retries = parseInt(retriesMatch[1], 10);
|
|
2520
2604
|
}
|
|
2605
|
+
const cooldownMatch = yaml2.match(/cooldown:\s*["']?([^"'\n]+)["']?/);
|
|
2606
|
+
if (cooldownMatch) {
|
|
2607
|
+
result.cooldown = cooldownMatch[1].trim();
|
|
2608
|
+
}
|
|
2521
2609
|
return result;
|
|
2522
2610
|
}
|
|
2523
2611
|
async function emitExecutionEvent(eventType, data) {
|
|
@@ -2537,7 +2625,7 @@ async function emitExecutionEvent(eventType, data) {
|
|
|
2537
2625
|
...data.error ? { error: data.error } : {}
|
|
2538
2626
|
}
|
|
2539
2627
|
}),
|
|
2540
|
-
signal: AbortSignal.timeout(
|
|
2628
|
+
signal: AbortSignal.timeout(EXECUTION_EVENT_TIMEOUT_MS)
|
|
2541
2629
|
});
|
|
2542
2630
|
return;
|
|
2543
2631
|
} catch {
|
|
@@ -2573,7 +2661,7 @@ async function verifyExecution(squadName, agentName, criteria, options = {}) {
|
|
|
2573
2661
|
if (memDir) {
|
|
2574
2662
|
const statePath = join4(memDir, squadName, agentName, "state.md");
|
|
2575
2663
|
if (existsSync4(statePath)) {
|
|
2576
|
-
stateContent = readFileSync3(statePath, "utf-8").slice(0,
|
|
2664
|
+
stateContent = readFileSync3(statePath, "utf-8").slice(0, VERIFICATION_STATE_MAX_CHARS);
|
|
2577
2665
|
}
|
|
2578
2666
|
}
|
|
2579
2667
|
let recentCommits = "";
|
|
@@ -2610,7 +2698,7 @@ FAIL: <brief reason>`;
|
|
|
2610
2698
|
const escapedPrompt = verifyPrompt.replace(/'/g, "'\\''");
|
|
2611
2699
|
const result = execSync11(
|
|
2612
2700
|
`claude --print --model haiku -- '${escapedPrompt}'`,
|
|
2613
|
-
{ encoding: "utf-8", cwd: projectRoot, timeout:
|
|
2701
|
+
{ encoding: "utf-8", cwd: projectRoot, timeout: VERIFICATION_EXEC_TIMEOUT_MS }
|
|
2614
2702
|
).trim();
|
|
2615
2703
|
if (options.verbose) {
|
|
2616
2704
|
writeLine(` ${colors.dim}Verification: ${result}${RESET}`);
|
|
@@ -2801,7 +2889,7 @@ async function runLeadMode(squad, squadsDir, options) {
|
|
|
2801
2889
|
writeLine();
|
|
2802
2890
|
return;
|
|
2803
2891
|
}
|
|
2804
|
-
const timeoutMins = options.timeout ||
|
|
2892
|
+
const timeoutMins = options.timeout || DEFAULT_TIMEOUT_MINUTES;
|
|
2805
2893
|
const agentList = agentFiles.map((a) => `- ${a.name}: ${a.role}`).join("\n");
|
|
2806
2894
|
const agentPaths = agentFiles.map((a) => `- ${a.name}: ${a.path}`).join("\n");
|
|
2807
2895
|
const prompt2 = `You are the Lead of the ${squad.name} squad.
|
|
@@ -2921,7 +3009,7 @@ ${learnings.map((l) => `- ${l.content}`).join("\n")}
|
|
|
2921
3009
|
const dryRunContext = gatherSquadContext(squadName, agentName, { verbose: options.verbose, agentPath });
|
|
2922
3010
|
if (options.verbose) {
|
|
2923
3011
|
writeLine(` ${colors.dim}Agent definition:${RESET}`);
|
|
2924
|
-
writeLine(` ${colors.dim}${definition.slice(0,
|
|
3012
|
+
writeLine(` ${colors.dim}${definition.slice(0, DRYRUN_DEF_MAX_CHARS)}...${RESET}`);
|
|
2925
3013
|
if (learnings.length > 0) {
|
|
2926
3014
|
writeLine(` ${colors.dim}Learnings: ${learnings.length} from bridge${RESET}`);
|
|
2927
3015
|
}
|
|
@@ -2929,7 +3017,7 @@ ${learnings.map((l) => `- ${l.content}`).join("\n")}
|
|
|
2929
3017
|
const fullContext = `${dryRunContext}${learningContext}`;
|
|
2930
3018
|
writeLine();
|
|
2931
3019
|
writeLine(` ${colors.cyan}Context to inject (${Math.ceil(fullContext.length / 4)} tokens):${RESET}`);
|
|
2932
|
-
writeLine(` ${colors.dim}${fullContext.slice(0,
|
|
3020
|
+
writeLine(` ${colors.dim}${fullContext.slice(0, DRYRUN_CONTEXT_MAX_CHARS)}...${RESET}`);
|
|
2933
3021
|
}
|
|
2934
3022
|
}
|
|
2935
3023
|
return;
|
|
@@ -2982,8 +3070,9 @@ ${learnings.map((l) => `- ${l.content}`).join("\n")}
|
|
|
2982
3070
|
const isScheduledRun = options.trigger === "scheduled" || options.trigger === "smart";
|
|
2983
3071
|
const bridgeHasNoHistory = preflight.gates.cooldown?.elapsed_sec === null;
|
|
2984
3072
|
if (isScheduledRun && (!preflight.gates.cooldown || bridgeHasNoHistory)) {
|
|
2985
|
-
const
|
|
2986
|
-
const
|
|
3073
|
+
const frontmatterForCooldown = parseAgentFrontmatter(agentPath);
|
|
3074
|
+
const cooldownMs = frontmatterForCooldown.cooldown ? parseCooldown(frontmatterForCooldown.cooldown) || DEFAULT_SCHEDULED_COOLDOWN_MS : DEFAULT_SCHEDULED_COOLDOWN_MS;
|
|
3075
|
+
const localCooldown = checkLocalCooldown(squadName, agentName, cooldownMs);
|
|
2987
3076
|
if (!localCooldown.ok) {
|
|
2988
3077
|
spinner.stop();
|
|
2989
3078
|
writeLine();
|
|
@@ -3013,7 +3102,7 @@ ${learnings.map((l) => `- ${l.content}`).join("\n")}
|
|
|
3013
3102
|
${approvalInstructions}
|
|
3014
3103
|
` : "";
|
|
3015
3104
|
const squadContext = gatherSquadContext(squadName, agentName, { verbose: options.verbose, agentPath });
|
|
3016
|
-
const timeoutMins = options.timeout ||
|
|
3105
|
+
const timeoutMins = options.timeout || DEFAULT_TIMEOUT_MINUTES;
|
|
3017
3106
|
const prompt2 = `Execute the ${agentName} agent from squad ${squadName}.
|
|
3018
3107
|
|
|
3019
3108
|
Read the agent definition at ${agentPath} and follow its instructions exactly.
|
|
@@ -3034,7 +3123,7 @@ ${squadContext}${learningContext}${approvalContext}
|
|
|
3034
3123
|
TIME LIMIT: You have ${timeoutMins} minutes. Work efficiently:
|
|
3035
3124
|
- Focus on the most important tasks first
|
|
3036
3125
|
- If a task is taking too long, move on and note it for next run
|
|
3037
|
-
- Aim to complete within ${Math.floor(timeoutMins *
|
|
3126
|
+
- Aim to complete within ${Math.floor(timeoutMins * SOFT_DEADLINE_RATIO)} minutes
|
|
3038
3127
|
|
|
3039
3128
|
After completion:
|
|
3040
3129
|
|
|
@@ -3348,7 +3437,7 @@ async function executeWithClaude(prompt2, options) {
|
|
|
3348
3437
|
SQUADS_TASK_TYPE: execContext.taskType,
|
|
3349
3438
|
SQUADS_TRIGGER: execContext.trigger,
|
|
3350
3439
|
SQUADS_EXECUTION_ID: execContext.executionId,
|
|
3351
|
-
BRIDGE_API: process.env.SQUADS_BRIDGE_URL ||
|
|
3440
|
+
BRIDGE_API: process.env.SQUADS_BRIDGE_URL || DEFAULT_BRIDGE_URL,
|
|
3352
3441
|
OTEL_RESOURCE_ATTRIBUTES: `squads.squad=${execContext.squad},squads.agent=${execContext.agent},squads.task_type=${execContext.taskType},squads.trigger=${execContext.trigger},squads.execution_id=${execContext.executionId}`,
|
|
3353
3442
|
...effort ? { CLAUDE_EFFORT: effort } : {},
|
|
3354
3443
|
...skills && skills.length > 0 ? { CLAUDE_SKILLS: skills.join(",") } : {}
|
|
@@ -3420,7 +3509,7 @@ async function executeWithClaude(prompt2, options) {
|
|
|
3420
3509
|
SQUADS_TASK_TYPE: execContext.taskType,
|
|
3421
3510
|
SQUADS_TRIGGER: execContext.trigger,
|
|
3422
3511
|
SQUADS_EXECUTION_ID: execContext.executionId,
|
|
3423
|
-
BRIDGE_API: process.env.SQUADS_BRIDGE_URL ||
|
|
3512
|
+
BRIDGE_API: process.env.SQUADS_BRIDGE_URL || DEFAULT_BRIDGE_URL
|
|
3424
3513
|
};
|
|
3425
3514
|
const modelFlag2 = claudeModelAlias ? `--model ${claudeModelAlias}` : "";
|
|
3426
3515
|
const watchBranchName = `agent/${squadName}/${agentName}-${timestamp2}`;
|
|
@@ -3434,7 +3523,7 @@ async function executeWithClaude(prompt2, options) {
|
|
|
3434
3523
|
env: watchEnv
|
|
3435
3524
|
});
|
|
3436
3525
|
child2.unref();
|
|
3437
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3526
|
+
await new Promise((resolve) => setTimeout(resolve, LOG_FILE_INIT_DELAY_MS));
|
|
3438
3527
|
writeLine(` ${colors.dim}Tailing log (Ctrl+C to stop watching, agent continues)...${RESET}`);
|
|
3439
3528
|
writeLine();
|
|
3440
3529
|
const tail = spawn2("tail", ["-f", logFile2], { stdio: "inherit" });
|
|
@@ -3485,7 +3574,7 @@ async function executeWithClaude(prompt2, options) {
|
|
|
3485
3574
|
SQUADS_TASK_TYPE: execContext.taskType,
|
|
3486
3575
|
SQUADS_TRIGGER: execContext.trigger,
|
|
3487
3576
|
SQUADS_EXECUTION_ID: execContext.executionId,
|
|
3488
|
-
BRIDGE_API: process.env.SQUADS_BRIDGE_URL ||
|
|
3577
|
+
BRIDGE_API: process.env.SQUADS_BRIDGE_URL || DEFAULT_BRIDGE_URL,
|
|
3489
3578
|
OTEL_RESOURCE_ATTRIBUTES: `squads.squad=${execContext.squad},squads.agent=${execContext.agent},squads.task_type=${execContext.taskType},squads.trigger=${execContext.trigger},squads.execution_id=${execContext.executionId}`,
|
|
3490
3579
|
...effort ? { CLAUDE_EFFORT: effort } : {},
|
|
3491
3580
|
...skills && skills.length > 0 ? { CLAUDE_SKILLS: skills.join(",") } : {}
|
|
@@ -3538,7 +3627,7 @@ async function executeWithProvider(provider, prompt2, options) {
|
|
|
3538
3627
|
}
|
|
3539
3628
|
if (options.verbose) {
|
|
3540
3629
|
writeLine(` ${colors.dim}Provider: ${cliConfig.displayName}${RESET}`);
|
|
3541
|
-
writeLine(` ${colors.dim}Command: ${cliConfig.command} ${args.join(" ").slice(0,
|
|
3630
|
+
writeLine(` ${colors.dim}Command: ${cliConfig.command} ${args.join(" ").slice(0, VERBOSE_COMMAND_MAX_CHARS)}...${RESET}`);
|
|
3542
3631
|
writeLine(` ${colors.dim}CWD: ${workDir}${RESET}`);
|
|
3543
3632
|
if (workDir !== projectRoot) {
|
|
3544
3633
|
writeLine(` ${colors.dim}Worktree: ${branchName}${RESET}`);
|
|
@@ -10018,74 +10107,6 @@ import {
|
|
|
10018
10107
|
import { join as join17 } from "path";
|
|
10019
10108
|
import { homedir as homedir6 } from "os";
|
|
10020
10109
|
import { spawn as spawn3, execSync as execSync9 } from "child_process";
|
|
10021
|
-
|
|
10022
|
-
// src/lib/cron.ts
|
|
10023
|
-
function cronMatches(cron, date) {
|
|
10024
|
-
const parts = cron.trim().split(/\s+/);
|
|
10025
|
-
if (parts.length < 5) return false;
|
|
10026
|
-
const fields = [
|
|
10027
|
-
{ value: date.getMinutes(), field: parts[0], min: 0, max: 59 },
|
|
10028
|
-
{ value: date.getHours(), field: parts[1], min: 0, max: 23 },
|
|
10029
|
-
{ value: date.getDate(), field: parts[2], min: 1, max: 31 },
|
|
10030
|
-
{ value: date.getMonth() + 1, field: parts[3], min: 1, max: 12 },
|
|
10031
|
-
{ value: date.getDay(), field: parts[4], min: 0, max: 6 }
|
|
10032
|
-
];
|
|
10033
|
-
return fields.every(
|
|
10034
|
-
({ value, field, min, max }) => fieldMatches(field, value, min, max)
|
|
10035
|
-
);
|
|
10036
|
-
}
|
|
10037
|
-
function fieldMatches(field, value, min, max) {
|
|
10038
|
-
if (field.includes(",")) {
|
|
10039
|
-
return field.split(",").some((part) => fieldMatches(part.trim(), value, min, max));
|
|
10040
|
-
}
|
|
10041
|
-
if (field.includes("/")) {
|
|
10042
|
-
const [range, stepStr] = field.split("/");
|
|
10043
|
-
const step = parseInt(stepStr);
|
|
10044
|
-
if (isNaN(step) || step <= 0) return false;
|
|
10045
|
-
let start = min;
|
|
10046
|
-
let end = max;
|
|
10047
|
-
if (range !== "*") {
|
|
10048
|
-
if (range.includes("-")) {
|
|
10049
|
-
[start, end] = range.split("-").map(Number);
|
|
10050
|
-
} else {
|
|
10051
|
-
start = parseInt(range);
|
|
10052
|
-
}
|
|
10053
|
-
}
|
|
10054
|
-
if (value < start || value > end) return false;
|
|
10055
|
-
return (value - start) % step === 0;
|
|
10056
|
-
}
|
|
10057
|
-
if (field.includes("-")) {
|
|
10058
|
-
const [start, end] = field.split("-").map(Number);
|
|
10059
|
-
return value >= start && value <= end;
|
|
10060
|
-
}
|
|
10061
|
-
if (field === "*") return true;
|
|
10062
|
-
return parseInt(field) === value;
|
|
10063
|
-
}
|
|
10064
|
-
function getNextCronRun(cron, after = /* @__PURE__ */ new Date()) {
|
|
10065
|
-
const next = new Date(after);
|
|
10066
|
-
next.setSeconds(0, 0);
|
|
10067
|
-
next.setMinutes(next.getMinutes() + 1);
|
|
10068
|
-
const maxIterations = 60 * 48;
|
|
10069
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
10070
|
-
if (cronMatches(cron, next)) return next;
|
|
10071
|
-
next.setMinutes(next.getMinutes() + 1);
|
|
10072
|
-
}
|
|
10073
|
-
const fallback = new Date(after);
|
|
10074
|
-
fallback.setDate(fallback.getDate() + 1);
|
|
10075
|
-
return fallback;
|
|
10076
|
-
}
|
|
10077
|
-
function parseCooldown(cooldown) {
|
|
10078
|
-
const match = cooldown.match(/^(\d+)\s*(m|min|minutes?|h|hours?|d|days?)$/i);
|
|
10079
|
-
if (!match) return 0;
|
|
10080
|
-
const value = parseInt(match[1]);
|
|
10081
|
-
const unit = match[2].toLowerCase();
|
|
10082
|
-
if (unit.startsWith("m")) return value * 60 * 1e3;
|
|
10083
|
-
if (unit.startsWith("h")) return value * 60 * 60 * 1e3;
|
|
10084
|
-
if (unit.startsWith("d")) return value * 24 * 60 * 60 * 1e3;
|
|
10085
|
-
return 0;
|
|
10086
|
-
}
|
|
10087
|
-
|
|
10088
|
-
// src/commands/autonomous.ts
|
|
10089
10110
|
var DAEMON_DIR = join17(homedir6(), ".squads");
|
|
10090
10111
|
var PID_FILE = join17(DAEMON_DIR, "autonomous.pid");
|
|
10091
10112
|
var DAEMON_LOG = join17(DAEMON_DIR, "autonomous.log");
|