opencode-swarm 6.31.4 → 6.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +12 -3
- package/dist/config/schema.d.ts +12 -0
- package/dist/hooks/guardrails.d.ts +4 -3
- package/dist/index.js +270 -186
- package/dist/utils/tool-output.d.ts +3 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14591,7 +14591,10 @@ var init_schema = __esm(() => {
|
|
|
14591
14591
|
enabled: exports_external.boolean().default(true),
|
|
14592
14592
|
required_agents: exports_external.array(exports_external.enum(["coder", "reviewer", "test_engineer"])).default(["coder", "reviewer", "test_engineer"]),
|
|
14593
14593
|
require_docs: exports_external.boolean().default(true),
|
|
14594
|
-
policy: exports_external.enum(["enforce", "warn"]).default("enforce")
|
|
14594
|
+
policy: exports_external.enum(["enforce", "warn"]).default("enforce"),
|
|
14595
|
+
regression_sweep: exports_external.object({
|
|
14596
|
+
enforce: exports_external.boolean().default(false)
|
|
14597
|
+
}).optional()
|
|
14595
14598
|
});
|
|
14596
14599
|
SummaryConfigSchema = exports_external.object({
|
|
14597
14600
|
enabled: exports_external.boolean().default(true),
|
|
@@ -14937,9 +14940,15 @@ var init_schema = __esm(() => {
|
|
|
14937
14940
|
tool_output: exports_external.object({
|
|
14938
14941
|
truncation_enabled: exports_external.boolean().default(true),
|
|
14939
14942
|
max_lines: exports_external.number().min(10).max(500).default(150),
|
|
14940
|
-
per_tool: exports_external.record(exports_external.string(), exports_external.number()).optional()
|
|
14943
|
+
per_tool: exports_external.record(exports_external.string(), exports_external.number()).optional(),
|
|
14944
|
+
truncation_tools: exports_external.array(exports_external.string()).optional().describe("Tools to apply output truncation to. Defaults to diff, symbols, bash, shell, test_runner, lint, pre_check_batch, complexity_hotspots, pkg_audit, sbom_generate, schema_drift.")
|
|
14941
14945
|
}).optional(),
|
|
14942
14946
|
slop_detector: SlopDetectorConfigSchema.optional(),
|
|
14947
|
+
todo_gate: exports_external.object({
|
|
14948
|
+
enabled: exports_external.boolean().default(true),
|
|
14949
|
+
max_high_priority: exports_external.number().int().min(-1).default(0).describe("Max new high-priority TODOs (FIXME/HACK/XXX) before warning. 0 = warn on any. Set to -1 to disable."),
|
|
14950
|
+
block_on_threshold: exports_external.boolean().default(false).describe("If true, block phase completion when threshold exceeded. Default: advisory only.")
|
|
14951
|
+
}).optional(),
|
|
14943
14952
|
incremental_verify: IncrementalVerifyConfigSchema.optional(),
|
|
14944
14953
|
compaction_service: CompactionConfigSchema.optional()
|
|
14945
14954
|
});
|
|
@@ -33429,7 +33438,7 @@ function detectAdditionalLinter(cwd) {
|
|
|
33429
33438
|
}
|
|
33430
33439
|
async function detectAvailableLinter(directory) {
|
|
33431
33440
|
const _DETECT_TIMEOUT = 2000;
|
|
33432
|
-
const projectDir = directory
|
|
33441
|
+
const projectDir = directory;
|
|
33433
33442
|
const isWindows = process.platform === "win32";
|
|
33434
33443
|
const biomeBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "biome.EXE") : path22.join(projectDir, "node_modules", ".bin", "biome");
|
|
33435
33444
|
const eslintBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path22.join(projectDir, "node_modules", ".bin", "eslint");
|
|
@@ -40049,6 +40058,8 @@ Your message MUST NOT contain:
|
|
|
40049
40058
|
|
|
40050
40059
|
Delegation is a handoff, not a negotiation. State facts, let agents decide.
|
|
40051
40060
|
|
|
40061
|
+
Before delegating to {{AGENT_PREFIX}}reviewer: call check_gate_status for the current task_id and include the gate results in the GATES field of the reviewer message. Format: GATES: lint=PASS/FAIL, sast_scan=PASS/FAIL, secretscan=PASS/FAIL (use PASS/FAIL/skipped for each gate). If no gates have been run yet, use GATES: none.
|
|
40062
|
+
|
|
40052
40063
|
<!-- BEHAVIORAL_GUIDANCE_START -->
|
|
40053
40064
|
PARTIAL GATE RATIONALIZATIONS \u2014 automated gates \u2260 agent review. Running SOME gates is NOT compliance:
|
|
40054
40065
|
\u2717 "I ran pre_check_batch so the code is verified" \u2192 pre_check_batch does NOT replace {{AGENT_PREFIX}}reviewer or {{AGENT_PREFIX}}test_engineer
|
|
@@ -40138,6 +40149,7 @@ CONSTRAINT: Do not modify other functions
|
|
|
40138
40149
|
TASK: Review login validation
|
|
40139
40150
|
FILE: src/auth/login.ts
|
|
40140
40151
|
CHECK: [security, correctness, edge-cases]
|
|
40152
|
+
GATES: lint=PASS, sast_scan=PASS, secretscan=PASS
|
|
40141
40153
|
OUTPUT: VERDICT + RISK + ISSUES
|
|
40142
40154
|
|
|
40143
40155
|
{{AGENT_PREFIX}}test_engineer
|
|
@@ -40155,6 +40167,7 @@ OUTPUT: VERDICT + CONFIDENCE + ISSUES + SUMMARY
|
|
|
40155
40167
|
TASK: Security-only review of login validation
|
|
40156
40168
|
FILE: src/auth/login.ts
|
|
40157
40169
|
CHECK: [security-only] \u2014 evaluate against OWASP Top 10, scan for hardcoded secrets, injection vectors, insecure crypto, missing input validation
|
|
40170
|
+
GATES: lint=PASS, sast_scan=PASS, secretscan=PASS
|
|
40158
40171
|
OUTPUT: VERDICT + RISK + SECURITY ISSUES ONLY
|
|
40159
40172
|
|
|
40160
40173
|
{{AGENT_PREFIX}}test_engineer
|
|
@@ -40591,6 +40604,10 @@ Treating pre_check_batch as a substitute for {{AGENT_PREFIX}}reviewer is a PROCE
|
|
|
40591
40604
|
|
|
40592
40605
|
IMPORTANT: The regression sweep runs test_runner DIRECTLY (architect calls the tool). Do NOT delegate to test_engineer for this \u2014 the test_engineer's EXECUTION BOUNDARY restricts it to its own test files. The architect has unrestricted test_runner access.
|
|
40593
40606
|
\u2192 REQUIRED: Print "regression-sweep: [PASS N additional tests | SKIPPED \u2014 no related tests beyond task scope | SKIPPED \u2014 test_runner error | FAIL \u2014 REGRESSION DETECTED in files]"
|
|
40607
|
+
|
|
40608
|
+
5n. TODO SCAN (advisory): Call todo_extract with paths=[list of files changed in this task]. If any results have priority HIGH \u2192 print "todo-scan: WARN \u2014 N high-priority TODOs in changed files: [list of TODO texts]". If no high-priority results \u2192 print "todo-scan: CLEAN". This is advisory only and does NOT block the pipeline.
|
|
40609
|
+
\u2192 REQUIRED: Print "todo-scan: [WARN \u2014 N high-priority TODOs | CLEAN]"
|
|
40610
|
+
|
|
40594
40611
|
{{ADVERSARIAL_TEST_STEP}}
|
|
40595
40612
|
5n. COVERAGE CHECK: If {{AGENT_PREFIX}}test_engineer reports coverage < 70% \u2192 delegate {{AGENT_PREFIX}}test_engineer for an additional test pass targeting uncovered paths. This is a soft guideline; use judgment for trivial tasks.
|
|
40596
40613
|
|
|
@@ -40873,6 +40890,9 @@ Before you report task completion, verify:
|
|
|
40873
40890
|
[ ] I did not skip or stub any acceptance criterion
|
|
40874
40891
|
[ ] I did not run tests, build commands, or validation tools \u2014 that is the reviewer's job
|
|
40875
40892
|
[ ] My changes compile/parse without errors (syntax check only)
|
|
40893
|
+
[ ] I did not use vague identifier names (result, data, temp, value, item, info, stuff, obj, ret, val)
|
|
40894
|
+
[ ] I did not write empty or tautological comments (e.g., "// sets the value", "// constructor", "// handle error")
|
|
40895
|
+
[ ] I did not leave placeholder JSDoc/docstring @param descriptions blank or copy-paste identical descriptions across functions
|
|
40876
40896
|
If ANY box is unchecked, fix it before reporting completion.
|
|
40877
40897
|
Print this checklist with your completion report.
|
|
40878
40898
|
|
|
@@ -41606,7 +41626,11 @@ TIER 2: SAFETY (mandatory for MODERATE+, always for COMPLEX)
|
|
|
41606
41626
|
Does the code introduce security vulnerabilities, data loss risks, or breaking changes? Check against: SAST findings, secret scan results, import analysis. Anti-rubber-stamp: "No issues found" requires evidence. State what you checked.
|
|
41607
41627
|
|
|
41608
41628
|
TIER 3: QUALITY (run only for COMPLEX, and only if Tiers 1-2 pass)
|
|
41609
|
-
Code style, naming, duplication, test coverage, documentation completeness. This tier is advisory \u2014 QUALITY findings do not block approval. Approval requires: Tier 1 PASS + Tier 2 PASS (where applicable). Tier 3 is informational.
|
|
41629
|
+
Code style, naming, duplication, test coverage, documentation completeness. This tier is advisory \u2014 QUALITY findings do not block approval. Approval requires: Tier 1 PASS + Tier 2 PASS (where applicable). Tier 3 is informational. Flag these slop patterns:
|
|
41630
|
+
- Vague identifiers (result, data, temp, value, item, info, stuff, obj, ret, val) \u2014 flag if a more descriptive name exists
|
|
41631
|
+
- Empty or tautological comments that describe syntax not intent (e.g., "// sets the value", "// constructor", "// handle error")
|
|
41632
|
+
- Copy-paste code blocks with only variable names changed
|
|
41633
|
+
- Blank or copy-pasted @param/@returns descriptions in JSDoc/docstrings
|
|
41610
41634
|
|
|
41611
41635
|
VERDICT FORMAT:
|
|
41612
41636
|
APPROVED: Tier 1 PASS, Tier 2 PASS [, Tier 3 notes if any]
|
|
@@ -41622,6 +41646,9 @@ FILE: [primary changed file or diff entry point]
|
|
|
41622
41646
|
DIFF: [changed files/functions, or "infer from FILE" if omitted]
|
|
41623
41647
|
AFFECTS: [callers/consumers/dependents to inspect, or "infer from diff"]
|
|
41624
41648
|
CHECK: [list of dimensions to evaluate]
|
|
41649
|
+
GATES: [pre-completed gate results (lint, SAST, secretscan, etc.), or "none" if unavailable]
|
|
41650
|
+
|
|
41651
|
+
PROCESSING: If GATES is provided and includes passing results for lint, SAST, placeholder-scan, or secret-scan: skip the corresponding Tier 2 checks that those gates already cover. Focus Tier 2 time on checks NOT covered by automated gates.
|
|
41625
41652
|
|
|
41626
41653
|
## OUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected)
|
|
41627
41654
|
Begin directly with VERDICT. Do NOT prepend "Here's my review..." or any conversational preamble.
|
|
@@ -42780,9 +42807,9 @@ class PlanSyncWorker {
|
|
|
42780
42807
|
disposed = false;
|
|
42781
42808
|
constructor(options = {}) {
|
|
42782
42809
|
if (!options.directory) {
|
|
42783
|
-
|
|
42810
|
+
throw new Error("[plan-sync-worker] No directory provided - options.directory is required");
|
|
42784
42811
|
}
|
|
42785
|
-
this.directory = options.directory
|
|
42812
|
+
this.directory = options.directory;
|
|
42786
42813
|
this.debounceMs = options.debounceMs ?? 300;
|
|
42787
42814
|
this.pollIntervalMs = options.pollIntervalMs ?? 2000;
|
|
42788
42815
|
this.syncTimeoutMs = options.syncTimeoutMs ?? 30000;
|
|
@@ -49183,6 +49210,8 @@ ${content.substring(endIndex + 1)}`;
|
|
|
49183
49210
|
}
|
|
49184
49211
|
// src/hooks/compaction-customizer.ts
|
|
49185
49212
|
init_manager2();
|
|
49213
|
+
import * as fs17 from "fs";
|
|
49214
|
+
import { join as join25 } from "path";
|
|
49186
49215
|
init_utils2();
|
|
49187
49216
|
function createCompactionCustomizerHook(config3, directory) {
|
|
49188
49217
|
const enabled = config3.hooks?.compaction !== false;
|
|
@@ -49227,6 +49256,15 @@ function createCompactionCustomizerHook(config3, directory) {
|
|
|
49227
49256
|
output.context.push(`[SWARM PATTERNS] ${patterns}`);
|
|
49228
49257
|
}
|
|
49229
49258
|
}
|
|
49259
|
+
try {
|
|
49260
|
+
const summariesDir = join25(directory, ".swarm", "summaries");
|
|
49261
|
+
const files = await fs17.promises.readdir(summariesDir);
|
|
49262
|
+
if (files.length > 0) {
|
|
49263
|
+
const count = files.length;
|
|
49264
|
+
output.context.push(`[CONTEXT OPTIMIZATION] Tool outputs from earlier in this session have been stored to disk. When compacting, replace any large tool output blocks (bash, test_runner, lint, diff results) with a one-line reference: "[Output stored \u2014 use /swarm retrieve to access full content]". Preserve the tool name, exit status, and any error messages. Discard raw output lines.`);
|
|
49265
|
+
output.context.push(`[STORED OUTPUTS] ${count} tool output${count === 1 ? "" : "s"} stored in .swarm/summaries/. These are retrievable via /swarm retrieve <id>.`);
|
|
49266
|
+
}
|
|
49267
|
+
} catch {}
|
|
49230
49268
|
output.context.push("[KNOWLEDGE TOOLS] You have persistent knowledge tools: knowledge_recall (search for relevant past decisions), knowledge_add (store a new lesson), knowledge_remove (delete outdated entries). Use knowledge_recall when past context would help.");
|
|
49231
49269
|
})
|
|
49232
49270
|
};
|
|
@@ -49705,7 +49743,7 @@ function maskToolOutput(msg, _threshold) {
|
|
|
49705
49743
|
}
|
|
49706
49744
|
// src/hooks/delegation-gate.ts
|
|
49707
49745
|
init_schema();
|
|
49708
|
-
import * as
|
|
49746
|
+
import * as fs18 from "fs";
|
|
49709
49747
|
import * as path31 from "path";
|
|
49710
49748
|
|
|
49711
49749
|
// src/hooks/guardrails.ts
|
|
@@ -49884,15 +49922,14 @@ function isInDeclaredScope(filePath, scopeEntries) {
|
|
|
49884
49922
|
return rel.length > 0 && !rel.startsWith("..") && !path29.isAbsolute(rel);
|
|
49885
49923
|
});
|
|
49886
49924
|
}
|
|
49887
|
-
function createGuardrailsHooks(directoryOrConfig, config3) {
|
|
49888
|
-
let directory;
|
|
49925
|
+
function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
49889
49926
|
let guardrailsConfig;
|
|
49890
|
-
if (
|
|
49927
|
+
if (directory && typeof directory === "object" && "enabled" in directory) {
|
|
49891
49928
|
console.warn("[guardrails] Legacy call without directory, falling back to process.cwd()");
|
|
49892
|
-
|
|
49929
|
+
guardrailsConfig = directory;
|
|
49930
|
+
} else if (directoryOrConfig && typeof directoryOrConfig === "object" && "enabled" in directoryOrConfig) {
|
|
49893
49931
|
guardrailsConfig = directoryOrConfig;
|
|
49894
49932
|
} else {
|
|
49895
|
-
directory = directoryOrConfig || process.cwd();
|
|
49896
49933
|
guardrailsConfig = config3;
|
|
49897
49934
|
}
|
|
49898
49935
|
if (guardrailsConfig?.enabled === false) {
|
|
@@ -50602,7 +50639,7 @@ function getEvidenceTaskId(session, directory) {
|
|
|
50602
50639
|
if (!resolvedPlanPath.startsWith(resolvedDirectory + path31.sep) && resolvedPlanPath !== resolvedDirectory) {
|
|
50603
50640
|
return null;
|
|
50604
50641
|
}
|
|
50605
|
-
const planContent =
|
|
50642
|
+
const planContent = fs18.readFileSync(resolvedPlanPath, "utf-8");
|
|
50606
50643
|
const plan = JSON.parse(planContent);
|
|
50607
50644
|
if (!plan || !Array.isArray(plan.phases)) {
|
|
50608
50645
|
return null;
|
|
@@ -51079,7 +51116,7 @@ ${warningLines.join(`
|
|
|
51079
51116
|
}
|
|
51080
51117
|
// src/hooks/delegation-sanitizer.ts
|
|
51081
51118
|
init_utils2();
|
|
51082
|
-
import * as
|
|
51119
|
+
import * as fs19 from "fs";
|
|
51083
51120
|
var SANITIZATION_PATTERNS = [
|
|
51084
51121
|
/\b\d+(st|nd|rd|th)\s+(attempt|try|time)\b/gi,
|
|
51085
51122
|
/\b(5th|fifth|final|last)\s+attempt\b/gi,
|
|
@@ -51150,7 +51187,7 @@ function createDelegationSanitizerHook(directory) {
|
|
|
51150
51187
|
stripped_patterns: result.stripped,
|
|
51151
51188
|
timestamp: new Date().toISOString()
|
|
51152
51189
|
};
|
|
51153
|
-
|
|
51190
|
+
fs19.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
51154
51191
|
`, "utf-8");
|
|
51155
51192
|
} catch {}
|
|
51156
51193
|
}
|
|
@@ -51383,7 +51420,7 @@ function createPipelineTrackerHook(config3, directory) {
|
|
|
51383
51420
|
return;
|
|
51384
51421
|
let phaseNumber = null;
|
|
51385
51422
|
try {
|
|
51386
|
-
const plan = await loadPlan(directory
|
|
51423
|
+
const plan = await loadPlan(directory);
|
|
51387
51424
|
if (plan) {
|
|
51388
51425
|
const phaseString = extractCurrentPhaseFromPlan2(plan);
|
|
51389
51426
|
phaseNumber = parsePhaseNumber(phaseString);
|
|
@@ -51407,12 +51444,12 @@ init_schema();
|
|
|
51407
51444
|
init_manager();
|
|
51408
51445
|
init_detector();
|
|
51409
51446
|
init_manager2();
|
|
51410
|
-
import * as
|
|
51447
|
+
import * as fs21 from "fs";
|
|
51411
51448
|
|
|
51412
51449
|
// src/services/decision-drift-analyzer.ts
|
|
51413
51450
|
init_utils2();
|
|
51414
51451
|
init_manager2();
|
|
51415
|
-
import * as
|
|
51452
|
+
import * as fs20 from "fs";
|
|
51416
51453
|
import * as path33 from "path";
|
|
51417
51454
|
var DEFAULT_DRIFT_CONFIG = {
|
|
51418
51455
|
staleThresholdPhases: 1,
|
|
@@ -51570,8 +51607,8 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
51570
51607
|
const contextPath = path33.join(directory, ".swarm", "context.md");
|
|
51571
51608
|
let contextContent = "";
|
|
51572
51609
|
try {
|
|
51573
|
-
if (
|
|
51574
|
-
contextContent =
|
|
51610
|
+
if (fs20.existsSync(contextPath)) {
|
|
51611
|
+
contextContent = fs20.readFileSync(contextPath, "utf-8");
|
|
51575
51612
|
}
|
|
51576
51613
|
} catch {
|
|
51577
51614
|
return {
|
|
@@ -52065,11 +52102,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
52065
52102
|
if (handoffContent) {
|
|
52066
52103
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
52067
52104
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
52068
|
-
if (
|
|
52105
|
+
if (fs21.existsSync(consumedPath)) {
|
|
52069
52106
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
52070
|
-
|
|
52107
|
+
fs21.unlinkSync(consumedPath);
|
|
52071
52108
|
}
|
|
52072
|
-
|
|
52109
|
+
fs21.renameSync(handoffPath, consumedPath);
|
|
52073
52110
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
52074
52111
|
The previous model's session ended. Here is your starting context:
|
|
52075
52112
|
|
|
@@ -52349,11 +52386,11 @@ ${budgetWarning}`);
|
|
|
52349
52386
|
if (handoffContent) {
|
|
52350
52387
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
52351
52388
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
52352
|
-
if (
|
|
52389
|
+
if (fs21.existsSync(consumedPath)) {
|
|
52353
52390
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
52354
|
-
|
|
52391
|
+
fs21.unlinkSync(consumedPath);
|
|
52355
52392
|
}
|
|
52356
|
-
|
|
52393
|
+
fs21.renameSync(handoffPath, consumedPath);
|
|
52357
52394
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
52358
52395
|
The previous model's session ended. Here is your starting context:
|
|
52359
52396
|
|
|
@@ -53122,7 +53159,7 @@ function isReadTool(toolName) {
|
|
|
53122
53159
|
}
|
|
53123
53160
|
|
|
53124
53161
|
// src/hooks/incremental-verify.ts
|
|
53125
|
-
import * as
|
|
53162
|
+
import * as fs22 from "fs";
|
|
53126
53163
|
import * as path34 from "path";
|
|
53127
53164
|
|
|
53128
53165
|
// src/hooks/spawn-helper.ts
|
|
@@ -53198,21 +53235,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
53198
53235
|
// src/hooks/incremental-verify.ts
|
|
53199
53236
|
var emittedSkipAdvisories = new Set;
|
|
53200
53237
|
function detectPackageManager(projectDir) {
|
|
53201
|
-
if (
|
|
53238
|
+
if (fs22.existsSync(path34.join(projectDir, "bun.lockb")))
|
|
53202
53239
|
return "bun";
|
|
53203
|
-
if (
|
|
53240
|
+
if (fs22.existsSync(path34.join(projectDir, "pnpm-lock.yaml")))
|
|
53204
53241
|
return "pnpm";
|
|
53205
|
-
if (
|
|
53242
|
+
if (fs22.existsSync(path34.join(projectDir, "yarn.lock")))
|
|
53206
53243
|
return "yarn";
|
|
53207
|
-
if (
|
|
53244
|
+
if (fs22.existsSync(path34.join(projectDir, "package-lock.json")))
|
|
53208
53245
|
return "npm";
|
|
53209
53246
|
return "bun";
|
|
53210
53247
|
}
|
|
53211
53248
|
function detectTypecheckCommand(projectDir) {
|
|
53212
53249
|
const pkgPath = path34.join(projectDir, "package.json");
|
|
53213
|
-
if (
|
|
53250
|
+
if (fs22.existsSync(pkgPath)) {
|
|
53214
53251
|
try {
|
|
53215
|
-
const pkg = JSON.parse(
|
|
53252
|
+
const pkg = JSON.parse(fs22.readFileSync(pkgPath, "utf8"));
|
|
53216
53253
|
const scripts = pkg.scripts;
|
|
53217
53254
|
if (scripts?.typecheck) {
|
|
53218
53255
|
const pm = detectPackageManager(projectDir);
|
|
@@ -53226,8 +53263,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
53226
53263
|
...pkg.dependencies,
|
|
53227
53264
|
...pkg.devDependencies
|
|
53228
53265
|
};
|
|
53229
|
-
if (!deps?.typescript && !
|
|
53230
|
-
const hasTSMarkers = deps?.typescript ||
|
|
53266
|
+
if (!deps?.typescript && !fs22.existsSync(path34.join(projectDir, "tsconfig.json"))) {}
|
|
53267
|
+
const hasTSMarkers = deps?.typescript || fs22.existsSync(path34.join(projectDir, "tsconfig.json"));
|
|
53231
53268
|
if (hasTSMarkers) {
|
|
53232
53269
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
53233
53270
|
}
|
|
@@ -53235,17 +53272,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
53235
53272
|
return null;
|
|
53236
53273
|
}
|
|
53237
53274
|
}
|
|
53238
|
-
if (
|
|
53275
|
+
if (fs22.existsSync(path34.join(projectDir, "go.mod"))) {
|
|
53239
53276
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
53240
53277
|
}
|
|
53241
|
-
if (
|
|
53278
|
+
if (fs22.existsSync(path34.join(projectDir, "Cargo.toml"))) {
|
|
53242
53279
|
return { command: ["cargo", "check"], language: "rust" };
|
|
53243
53280
|
}
|
|
53244
|
-
if (
|
|
53281
|
+
if (fs22.existsSync(path34.join(projectDir, "pyproject.toml")) || fs22.existsSync(path34.join(projectDir, "requirements.txt")) || fs22.existsSync(path34.join(projectDir, "setup.py"))) {
|
|
53245
53282
|
return { command: null, language: "python" };
|
|
53246
53283
|
}
|
|
53247
53284
|
try {
|
|
53248
|
-
const entries =
|
|
53285
|
+
const entries = fs22.readdirSync(projectDir);
|
|
53249
53286
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
53250
53287
|
return {
|
|
53251
53288
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -53939,12 +53976,12 @@ Use this data to avoid repeating known failure patterns.`;
|
|
|
53939
53976
|
// src/hooks/curator-drift.ts
|
|
53940
53977
|
init_event_bus();
|
|
53941
53978
|
init_utils2();
|
|
53942
|
-
import * as
|
|
53979
|
+
import * as fs23 from "fs";
|
|
53943
53980
|
import * as path36 from "path";
|
|
53944
53981
|
var DRIFT_REPORT_PREFIX = "drift-report-phase-";
|
|
53945
53982
|
async function readPriorDriftReports(directory) {
|
|
53946
53983
|
const swarmDir = path36.join(directory, ".swarm");
|
|
53947
|
-
const entries = await
|
|
53984
|
+
const entries = await fs23.promises.readdir(swarmDir).catch(() => null);
|
|
53948
53985
|
if (entries === null)
|
|
53949
53986
|
return [];
|
|
53950
53987
|
const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
|
|
@@ -53971,9 +54008,9 @@ async function writeDriftReport(directory, report) {
|
|
|
53971
54008
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
53972
54009
|
const filePath = validateSwarmPath(directory, filename);
|
|
53973
54010
|
const swarmDir = path36.dirname(filePath);
|
|
53974
|
-
await
|
|
54011
|
+
await fs23.promises.mkdir(swarmDir, { recursive: true });
|
|
53975
54012
|
try {
|
|
53976
|
-
await
|
|
54013
|
+
await fs23.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
53977
54014
|
} catch (err2) {
|
|
53978
54015
|
throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
|
|
53979
54016
|
}
|
|
@@ -54363,7 +54400,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
54363
54400
|
}
|
|
54364
54401
|
|
|
54365
54402
|
// src/hooks/slop-detector.ts
|
|
54366
|
-
import * as
|
|
54403
|
+
import * as fs24 from "fs";
|
|
54367
54404
|
import * as path38 from "path";
|
|
54368
54405
|
var WRITE_EDIT_TOOLS = new Set([
|
|
54369
54406
|
"write",
|
|
@@ -54409,7 +54446,7 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
54409
54446
|
function walkFiles(dir, exts, deadline) {
|
|
54410
54447
|
const results = [];
|
|
54411
54448
|
try {
|
|
54412
|
-
for (const entry of
|
|
54449
|
+
for (const entry of fs24.readdirSync(dir, { withFileTypes: true })) {
|
|
54413
54450
|
if (deadline !== undefined && Date.now() > deadline)
|
|
54414
54451
|
break;
|
|
54415
54452
|
if (entry.isSymbolicLink())
|
|
@@ -54429,7 +54466,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
54429
54466
|
return results;
|
|
54430
54467
|
}
|
|
54431
54468
|
function checkDeadExports(content, projectDir, startTime) {
|
|
54432
|
-
const hasPackageJson =
|
|
54469
|
+
const hasPackageJson = fs24.existsSync(path38.join(projectDir, "package.json"));
|
|
54433
54470
|
if (!hasPackageJson)
|
|
54434
54471
|
return null;
|
|
54435
54472
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -54452,7 +54489,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
54452
54489
|
if (found || Date.now() - startTime > 480)
|
|
54453
54490
|
break;
|
|
54454
54491
|
try {
|
|
54455
|
-
const text =
|
|
54492
|
+
const text = fs24.readFileSync(file3, "utf-8");
|
|
54456
54493
|
if (importPattern.test(text))
|
|
54457
54494
|
found = true;
|
|
54458
54495
|
importPattern.lastIndex = 0;
|
|
@@ -54585,7 +54622,7 @@ Review before proceeding.`;
|
|
|
54585
54622
|
|
|
54586
54623
|
// src/hooks/steering-consumed.ts
|
|
54587
54624
|
init_utils2();
|
|
54588
|
-
import * as
|
|
54625
|
+
import * as fs25 from "fs";
|
|
54589
54626
|
function recordSteeringConsumed(directory, directiveId) {
|
|
54590
54627
|
try {
|
|
54591
54628
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -54594,7 +54631,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
54594
54631
|
directiveId,
|
|
54595
54632
|
timestamp: new Date().toISOString()
|
|
54596
54633
|
};
|
|
54597
|
-
|
|
54634
|
+
fs25.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
54598
54635
|
`, "utf-8");
|
|
54599
54636
|
} catch {}
|
|
54600
54637
|
}
|
|
@@ -54951,7 +54988,7 @@ var build_check = createSwarmTool({
|
|
|
54951
54988
|
// src/tools/check-gate-status.ts
|
|
54952
54989
|
init_dist();
|
|
54953
54990
|
init_create_tool();
|
|
54954
|
-
import * as
|
|
54991
|
+
import * as fs26 from "fs";
|
|
54955
54992
|
import * as path39 from "path";
|
|
54956
54993
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
54957
54994
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -54975,12 +55012,12 @@ function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
|
54975
55012
|
return normalizedPath.startsWith(swarmPath);
|
|
54976
55013
|
}
|
|
54977
55014
|
function readEvidenceFile(evidencePath) {
|
|
54978
|
-
if (!
|
|
55015
|
+
if (!fs26.existsSync(evidencePath)) {
|
|
54979
55016
|
return null;
|
|
54980
55017
|
}
|
|
54981
55018
|
let content;
|
|
54982
55019
|
try {
|
|
54983
|
-
content =
|
|
55020
|
+
content = fs26.readFileSync(evidencePath, "utf-8");
|
|
54984
55021
|
} catch {
|
|
54985
55022
|
return null;
|
|
54986
55023
|
}
|
|
@@ -55016,7 +55053,8 @@ var check_gate_status = createSwarmTool({
|
|
|
55016
55053
|
passed_gates: [],
|
|
55017
55054
|
missing_gates: [],
|
|
55018
55055
|
gates: {},
|
|
55019
|
-
message: "Invalid task_id: task_id is required"
|
|
55056
|
+
message: "Invalid task_id: task_id is required",
|
|
55057
|
+
todo_scan: null
|
|
55020
55058
|
};
|
|
55021
55059
|
return JSON.stringify(errorResult, null, 2);
|
|
55022
55060
|
}
|
|
@@ -55028,7 +55066,8 @@ var check_gate_status = createSwarmTool({
|
|
|
55028
55066
|
passed_gates: [],
|
|
55029
55067
|
missing_gates: [],
|
|
55030
55068
|
gates: {},
|
|
55031
|
-
message: `Invalid task_id format: "${taskIdInput}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3", "1.2.3.4")
|
|
55069
|
+
message: `Invalid task_id format: "${taskIdInput}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3", "1.2.3.4")`,
|
|
55070
|
+
todo_scan: null
|
|
55032
55071
|
};
|
|
55033
55072
|
return JSON.stringify(errorResult, null, 2);
|
|
55034
55073
|
}
|
|
@@ -55041,7 +55080,8 @@ var check_gate_status = createSwarmTool({
|
|
|
55041
55080
|
passed_gates: [],
|
|
55042
55081
|
missing_gates: [],
|
|
55043
55082
|
gates: {},
|
|
55044
|
-
message: "Invalid path: evidence path validation failed"
|
|
55083
|
+
message: "Invalid path: evidence path validation failed",
|
|
55084
|
+
todo_scan: null
|
|
55045
55085
|
};
|
|
55046
55086
|
return JSON.stringify(errorResult, null, 2);
|
|
55047
55087
|
}
|
|
@@ -55054,7 +55094,8 @@ var check_gate_status = createSwarmTool({
|
|
|
55054
55094
|
passed_gates: [],
|
|
55055
55095
|
missing_gates: [],
|
|
55056
55096
|
gates: {},
|
|
55057
|
-
message: `No evidence file found for task "${taskIdInput}" at ${evidencePath}. Evidence file may be missing or invalid
|
|
55097
|
+
message: `No evidence file found for task "${taskIdInput}" at ${evidencePath}. Evidence file may be missing or invalid.`,
|
|
55098
|
+
todo_scan: null
|
|
55058
55099
|
};
|
|
55059
55100
|
return JSON.stringify(errorResult, null, 2);
|
|
55060
55101
|
}
|
|
@@ -55076,6 +55117,7 @@ var check_gate_status = createSwarmTool({
|
|
|
55076
55117
|
} else {
|
|
55077
55118
|
message = `Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;
|
|
55078
55119
|
}
|
|
55120
|
+
const todoScan = evidenceData.todo_scan;
|
|
55079
55121
|
const result = {
|
|
55080
55122
|
taskId: taskIdInput,
|
|
55081
55123
|
status,
|
|
@@ -55083,7 +55125,8 @@ var check_gate_status = createSwarmTool({
|
|
|
55083
55125
|
passed_gates: passedGates,
|
|
55084
55126
|
missing_gates: missingGates,
|
|
55085
55127
|
gates: gatesMap,
|
|
55086
|
-
message
|
|
55128
|
+
message,
|
|
55129
|
+
todo_scan: todoScan ?? null
|
|
55087
55130
|
};
|
|
55088
55131
|
return JSON.stringify(result, null, 2);
|
|
55089
55132
|
}
|
|
@@ -55091,7 +55134,7 @@ var check_gate_status = createSwarmTool({
|
|
|
55091
55134
|
// src/tools/complexity-hotspots.ts
|
|
55092
55135
|
init_dist();
|
|
55093
55136
|
init_create_tool();
|
|
55094
|
-
import * as
|
|
55137
|
+
import * as fs27 from "fs";
|
|
55095
55138
|
import * as path40 from "path";
|
|
55096
55139
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
55097
55140
|
var DEFAULT_DAYS = 90;
|
|
@@ -55221,11 +55264,11 @@ function estimateComplexity(content) {
|
|
|
55221
55264
|
}
|
|
55222
55265
|
function getComplexityForFile(filePath) {
|
|
55223
55266
|
try {
|
|
55224
|
-
const stat2 =
|
|
55267
|
+
const stat2 = fs27.statSync(filePath);
|
|
55225
55268
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
55226
55269
|
return null;
|
|
55227
55270
|
}
|
|
55228
|
-
const content =
|
|
55271
|
+
const content = fs27.readFileSync(filePath, "utf-8");
|
|
55229
55272
|
return estimateComplexity(content);
|
|
55230
55273
|
} catch {
|
|
55231
55274
|
return null;
|
|
@@ -55246,7 +55289,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
55246
55289
|
let analyzedFiles = 0;
|
|
55247
55290
|
for (const [file3, churnCount] of filteredChurn) {
|
|
55248
55291
|
let fullPath = file3;
|
|
55249
|
-
if (!
|
|
55292
|
+
if (!fs27.existsSync(fullPath)) {
|
|
55250
55293
|
fullPath = path40.join(cwd, file3);
|
|
55251
55294
|
}
|
|
55252
55295
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -55455,7 +55498,7 @@ var curator_analyze = createSwarmTool({
|
|
|
55455
55498
|
});
|
|
55456
55499
|
// src/tools/declare-scope.ts
|
|
55457
55500
|
init_tool();
|
|
55458
|
-
import * as
|
|
55501
|
+
import * as fs28 from "fs";
|
|
55459
55502
|
import * as path41 from "path";
|
|
55460
55503
|
init_create_tool();
|
|
55461
55504
|
function validateTaskIdFormat(taskId) {
|
|
@@ -55548,9 +55591,9 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
55548
55591
|
}
|
|
55549
55592
|
const resolvedDir = path41.resolve(normalizedDir);
|
|
55550
55593
|
try {
|
|
55551
|
-
const realPath =
|
|
55594
|
+
const realPath = fs28.realpathSync(resolvedDir);
|
|
55552
55595
|
const planPath2 = path41.join(realPath, ".swarm", "plan.json");
|
|
55553
|
-
if (!
|
|
55596
|
+
if (!fs28.existsSync(planPath2)) {
|
|
55554
55597
|
return {
|
|
55555
55598
|
success: false,
|
|
55556
55599
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -55572,9 +55615,9 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
55572
55615
|
if (!fallbackDir) {
|
|
55573
55616
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
55574
55617
|
}
|
|
55575
|
-
const directory = normalizedDir || fallbackDir
|
|
55618
|
+
const directory = normalizedDir || fallbackDir;
|
|
55576
55619
|
const planPath = path41.resolve(directory, ".swarm", "plan.json");
|
|
55577
|
-
if (!
|
|
55620
|
+
if (!fs28.existsSync(planPath)) {
|
|
55578
55621
|
return {
|
|
55579
55622
|
success: false,
|
|
55580
55623
|
message: "No plan found",
|
|
@@ -55583,7 +55626,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
55583
55626
|
}
|
|
55584
55627
|
let planContent;
|
|
55585
55628
|
try {
|
|
55586
|
-
planContent = JSON.parse(
|
|
55629
|
+
planContent = JSON.parse(fs28.readFileSync(planPath, "utf-8"));
|
|
55587
55630
|
} catch {
|
|
55588
55631
|
return {
|
|
55589
55632
|
success: false,
|
|
@@ -55988,7 +56031,7 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
55988
56031
|
// src/tools/evidence-check.ts
|
|
55989
56032
|
init_dist();
|
|
55990
56033
|
init_create_tool();
|
|
55991
|
-
import * as
|
|
56034
|
+
import * as fs29 from "fs";
|
|
55992
56035
|
import * as path42 from "path";
|
|
55993
56036
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
55994
56037
|
var MAX_EVIDENCE_FILES = 1000;
|
|
@@ -56037,12 +56080,12 @@ function parseCompletedTasks(planContent) {
|
|
|
56037
56080
|
}
|
|
56038
56081
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
56039
56082
|
const evidence = [];
|
|
56040
|
-
if (!
|
|
56083
|
+
if (!fs29.existsSync(evidenceDir) || !fs29.statSync(evidenceDir).isDirectory()) {
|
|
56041
56084
|
return evidence;
|
|
56042
56085
|
}
|
|
56043
56086
|
let files;
|
|
56044
56087
|
try {
|
|
56045
|
-
files =
|
|
56088
|
+
files = fs29.readdirSync(evidenceDir);
|
|
56046
56089
|
} catch {
|
|
56047
56090
|
return evidence;
|
|
56048
56091
|
}
|
|
@@ -56058,7 +56101,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56058
56101
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
56059
56102
|
continue;
|
|
56060
56103
|
}
|
|
56061
|
-
const stat2 =
|
|
56104
|
+
const stat2 = fs29.lstatSync(filePath);
|
|
56062
56105
|
if (!stat2.isFile()) {
|
|
56063
56106
|
continue;
|
|
56064
56107
|
}
|
|
@@ -56067,7 +56110,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56067
56110
|
}
|
|
56068
56111
|
let fileStat;
|
|
56069
56112
|
try {
|
|
56070
|
-
fileStat =
|
|
56113
|
+
fileStat = fs29.statSync(filePath);
|
|
56071
56114
|
if (fileStat.size > MAX_FILE_SIZE_BYTES3) {
|
|
56072
56115
|
continue;
|
|
56073
56116
|
}
|
|
@@ -56076,7 +56119,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56076
56119
|
}
|
|
56077
56120
|
let content;
|
|
56078
56121
|
try {
|
|
56079
|
-
content =
|
|
56122
|
+
content = fs29.readFileSync(filePath, "utf-8");
|
|
56080
56123
|
} catch {
|
|
56081
56124
|
continue;
|
|
56082
56125
|
}
|
|
@@ -56186,7 +56229,7 @@ var evidence_check = createSwarmTool({
|
|
|
56186
56229
|
}
|
|
56187
56230
|
let planContent;
|
|
56188
56231
|
try {
|
|
56189
|
-
planContent =
|
|
56232
|
+
planContent = fs29.readFileSync(planPath, "utf-8");
|
|
56190
56233
|
} catch {
|
|
56191
56234
|
const result2 = {
|
|
56192
56235
|
message: "No completed tasks found in plan.",
|
|
@@ -56221,7 +56264,7 @@ var evidence_check = createSwarmTool({
|
|
|
56221
56264
|
// src/tools/file-extractor.ts
|
|
56222
56265
|
init_tool();
|
|
56223
56266
|
init_create_tool();
|
|
56224
|
-
import * as
|
|
56267
|
+
import * as fs30 from "fs";
|
|
56225
56268
|
import * as path43 from "path";
|
|
56226
56269
|
var EXT_MAP = {
|
|
56227
56270
|
python: ".py",
|
|
@@ -56284,8 +56327,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
56284
56327
|
execute: async (args2, directory) => {
|
|
56285
56328
|
const { content, output_dir, prefix } = args2;
|
|
56286
56329
|
const targetDir = output_dir || directory;
|
|
56287
|
-
if (!
|
|
56288
|
-
|
|
56330
|
+
if (!fs30.existsSync(targetDir)) {
|
|
56331
|
+
fs30.mkdirSync(targetDir, { recursive: true });
|
|
56289
56332
|
}
|
|
56290
56333
|
if (!content) {
|
|
56291
56334
|
return "Error: content is required";
|
|
@@ -56307,12 +56350,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
56307
56350
|
const base = path43.basename(filepath, path43.extname(filepath));
|
|
56308
56351
|
const ext = path43.extname(filepath);
|
|
56309
56352
|
let counter = 1;
|
|
56310
|
-
while (
|
|
56353
|
+
while (fs30.existsSync(filepath)) {
|
|
56311
56354
|
filepath = path43.join(targetDir, `${base}_${counter}${ext}`);
|
|
56312
56355
|
counter++;
|
|
56313
56356
|
}
|
|
56314
56357
|
try {
|
|
56315
|
-
|
|
56358
|
+
fs30.writeFileSync(filepath, code.trim(), "utf-8");
|
|
56316
56359
|
savedFiles.push(filepath);
|
|
56317
56360
|
} catch (error93) {
|
|
56318
56361
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -56428,7 +56471,7 @@ var gitingest = createSwarmTool({
|
|
|
56428
56471
|
// src/tools/imports.ts
|
|
56429
56472
|
init_dist();
|
|
56430
56473
|
init_create_tool();
|
|
56431
|
-
import * as
|
|
56474
|
+
import * as fs31 from "fs";
|
|
56432
56475
|
import * as path44 from "path";
|
|
56433
56476
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
56434
56477
|
var MAX_SYMBOL_LENGTH = 256;
|
|
@@ -56597,7 +56640,7 @@ var SKIP_DIRECTORIES2 = new Set([
|
|
|
56597
56640
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
56598
56641
|
let entries;
|
|
56599
56642
|
try {
|
|
56600
|
-
entries =
|
|
56643
|
+
entries = fs31.readdirSync(dir);
|
|
56601
56644
|
} catch (e) {
|
|
56602
56645
|
stats.fileErrors.push({
|
|
56603
56646
|
path: dir,
|
|
@@ -56614,7 +56657,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56614
56657
|
const fullPath = path44.join(dir, entry);
|
|
56615
56658
|
let stat2;
|
|
56616
56659
|
try {
|
|
56617
|
-
stat2 =
|
|
56660
|
+
stat2 = fs31.statSync(fullPath);
|
|
56618
56661
|
} catch (e) {
|
|
56619
56662
|
stats.fileErrors.push({
|
|
56620
56663
|
path: fullPath,
|
|
@@ -56683,7 +56726,7 @@ var imports = createSwarmTool({
|
|
|
56683
56726
|
}
|
|
56684
56727
|
try {
|
|
56685
56728
|
const targetFile = path44.resolve(file3);
|
|
56686
|
-
if (!
|
|
56729
|
+
if (!fs31.existsSync(targetFile)) {
|
|
56687
56730
|
const errorResult = {
|
|
56688
56731
|
error: `target file not found: ${file3}`,
|
|
56689
56732
|
target: file3,
|
|
@@ -56693,7 +56736,7 @@ var imports = createSwarmTool({
|
|
|
56693
56736
|
};
|
|
56694
56737
|
return JSON.stringify(errorResult, null, 2);
|
|
56695
56738
|
}
|
|
56696
|
-
const targetStat =
|
|
56739
|
+
const targetStat = fs31.statSync(targetFile);
|
|
56697
56740
|
if (!targetStat.isFile()) {
|
|
56698
56741
|
const errorResult = {
|
|
56699
56742
|
error: "target must be a file, not a directory",
|
|
@@ -56719,12 +56762,12 @@ var imports = createSwarmTool({
|
|
|
56719
56762
|
if (consumers.length >= MAX_CONSUMERS)
|
|
56720
56763
|
break;
|
|
56721
56764
|
try {
|
|
56722
|
-
const stat2 =
|
|
56765
|
+
const stat2 = fs31.statSync(filePath);
|
|
56723
56766
|
if (stat2.size > MAX_FILE_SIZE_BYTES4) {
|
|
56724
56767
|
skippedFileCount++;
|
|
56725
56768
|
continue;
|
|
56726
56769
|
}
|
|
56727
|
-
const buffer =
|
|
56770
|
+
const buffer = fs31.readFileSync(filePath);
|
|
56728
56771
|
if (isBinaryFile2(filePath, buffer)) {
|
|
56729
56772
|
skippedFileCount++;
|
|
56730
56773
|
continue;
|
|
@@ -57273,7 +57316,7 @@ init_dist();
|
|
|
57273
57316
|
init_config();
|
|
57274
57317
|
init_schema();
|
|
57275
57318
|
init_manager();
|
|
57276
|
-
import * as
|
|
57319
|
+
import * as fs32 from "fs";
|
|
57277
57320
|
import * as path45 from "path";
|
|
57278
57321
|
init_utils2();
|
|
57279
57322
|
init_create_tool();
|
|
@@ -57359,7 +57402,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57359
57402
|
const phaseReferenceTimestamp = session.lastPhaseCompleteTimestamp ?? 0;
|
|
57360
57403
|
const crossSessionResult = collectCrossSessionDispatchedAgents(phaseReferenceTimestamp, sessionID);
|
|
57361
57404
|
const agentsDispatched = Array.from(crossSessionResult.agents).sort();
|
|
57362
|
-
const dir = workingDirectory || directory
|
|
57405
|
+
const dir = workingDirectory || directory;
|
|
57363
57406
|
const { config: config3 } = loadPluginConfigWithMeta(dir);
|
|
57364
57407
|
let phaseCompleteConfig;
|
|
57365
57408
|
try {
|
|
@@ -57532,7 +57575,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57532
57575
|
if (agentsMissing.length > 0) {
|
|
57533
57576
|
try {
|
|
57534
57577
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57535
|
-
const planRaw =
|
|
57578
|
+
const planRaw = fs32.readFileSync(planPath, "utf-8");
|
|
57536
57579
|
const plan = JSON.parse(planRaw);
|
|
57537
57580
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
57538
57581
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -57560,6 +57603,34 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57560
57603
|
warnings.push(`Warning: phase ${phase} missing required agents: ${agentsMissing.join(", ")}`);
|
|
57561
57604
|
}
|
|
57562
57605
|
}
|
|
57606
|
+
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
57607
|
+
try {
|
|
57608
|
+
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57609
|
+
const planRaw = fs32.readFileSync(planPath, "utf-8");
|
|
57610
|
+
const plan = JSON.parse(planRaw);
|
|
57611
|
+
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
57612
|
+
if (targetPhase) {
|
|
57613
|
+
let sweepFound = false;
|
|
57614
|
+
for (const task of targetPhase.tasks) {
|
|
57615
|
+
const taskEvidenceResult = await loadEvidence(dir, task.id);
|
|
57616
|
+
if (taskEvidenceResult.status === "found") {
|
|
57617
|
+
const entries = taskEvidenceResult.bundle.entries ?? [];
|
|
57618
|
+
for (const entry of entries) {
|
|
57619
|
+
if (entry.regression_sweep !== undefined) {
|
|
57620
|
+
sweepFound = true;
|
|
57621
|
+
break;
|
|
57622
|
+
}
|
|
57623
|
+
}
|
|
57624
|
+
}
|
|
57625
|
+
if (sweepFound)
|
|
57626
|
+
break;
|
|
57627
|
+
}
|
|
57628
|
+
if (!sweepFound) {
|
|
57629
|
+
warnings.push(`Warning: regression_sweep.enforce=true but no regression-sweep result found for any task in phase ${phase}. Run tests to populate regression-sweep results.`);
|
|
57630
|
+
}
|
|
57631
|
+
}
|
|
57632
|
+
} catch {}
|
|
57633
|
+
}
|
|
57563
57634
|
const now = Date.now();
|
|
57564
57635
|
const durationMs = now - phaseReferenceTimestamp;
|
|
57565
57636
|
const event = {
|
|
@@ -57573,7 +57644,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57573
57644
|
};
|
|
57574
57645
|
try {
|
|
57575
57646
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
57576
|
-
|
|
57647
|
+
fs32.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57577
57648
|
`, "utf-8");
|
|
57578
57649
|
} catch (writeError) {
|
|
57579
57650
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -57592,12 +57663,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57592
57663
|
}
|
|
57593
57664
|
try {
|
|
57594
57665
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57595
|
-
const planJson =
|
|
57666
|
+
const planJson = fs32.readFileSync(planPath, "utf-8");
|
|
57596
57667
|
const plan = JSON.parse(planJson);
|
|
57597
57668
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
57598
57669
|
if (phaseObj) {
|
|
57599
57670
|
phaseObj.status = "completed";
|
|
57600
|
-
|
|
57671
|
+
fs32.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
57601
57672
|
`, "utf-8");
|
|
57602
57673
|
}
|
|
57603
57674
|
} catch (error93) {
|
|
@@ -57650,7 +57721,7 @@ init_dist();
|
|
|
57650
57721
|
init_discovery();
|
|
57651
57722
|
init_utils();
|
|
57652
57723
|
init_create_tool();
|
|
57653
|
-
import * as
|
|
57724
|
+
import * as fs33 from "fs";
|
|
57654
57725
|
import * as path46 from "path";
|
|
57655
57726
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
57656
57727
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
@@ -57669,28 +57740,28 @@ function validateArgs3(args2) {
|
|
|
57669
57740
|
function detectEcosystems(directory) {
|
|
57670
57741
|
const ecosystems = [];
|
|
57671
57742
|
const cwd = directory;
|
|
57672
|
-
if (
|
|
57743
|
+
if (fs33.existsSync(path46.join(cwd, "package.json"))) {
|
|
57673
57744
|
ecosystems.push("npm");
|
|
57674
57745
|
}
|
|
57675
|
-
if (
|
|
57746
|
+
if (fs33.existsSync(path46.join(cwd, "pyproject.toml")) || fs33.existsSync(path46.join(cwd, "requirements.txt"))) {
|
|
57676
57747
|
ecosystems.push("pip");
|
|
57677
57748
|
}
|
|
57678
|
-
if (
|
|
57749
|
+
if (fs33.existsSync(path46.join(cwd, "Cargo.toml"))) {
|
|
57679
57750
|
ecosystems.push("cargo");
|
|
57680
57751
|
}
|
|
57681
|
-
if (
|
|
57752
|
+
if (fs33.existsSync(path46.join(cwd, "go.mod"))) {
|
|
57682
57753
|
ecosystems.push("go");
|
|
57683
57754
|
}
|
|
57684
57755
|
try {
|
|
57685
|
-
const files =
|
|
57756
|
+
const files = fs33.readdirSync(cwd);
|
|
57686
57757
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
57687
57758
|
ecosystems.push("dotnet");
|
|
57688
57759
|
}
|
|
57689
57760
|
} catch {}
|
|
57690
|
-
if (
|
|
57761
|
+
if (fs33.existsSync(path46.join(cwd, "Gemfile")) || fs33.existsSync(path46.join(cwd, "Gemfile.lock"))) {
|
|
57691
57762
|
ecosystems.push("ruby");
|
|
57692
57763
|
}
|
|
57693
|
-
if (
|
|
57764
|
+
if (fs33.existsSync(path46.join(cwd, "pubspec.yaml"))) {
|
|
57694
57765
|
ecosystems.push("dart");
|
|
57695
57766
|
}
|
|
57696
57767
|
return ecosystems;
|
|
@@ -58752,7 +58823,7 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
58752
58823
|
]);
|
|
58753
58824
|
// src/tools/pre-check-batch.ts
|
|
58754
58825
|
init_dist();
|
|
58755
|
-
import * as
|
|
58826
|
+
import * as fs36 from "fs";
|
|
58756
58827
|
import * as path49 from "path";
|
|
58757
58828
|
|
|
58758
58829
|
// node_modules/yocto-queue/index.js
|
|
@@ -58898,8 +58969,8 @@ function pLimit(concurrency) {
|
|
|
58898
58969
|
},
|
|
58899
58970
|
map: {
|
|
58900
58971
|
async value(iterable, function_) {
|
|
58901
|
-
const
|
|
58902
|
-
return Promise.all(
|
|
58972
|
+
const promises3 = Array.from(iterable, (value, index) => this(function_, value, index));
|
|
58973
|
+
return Promise.all(promises3);
|
|
58903
58974
|
}
|
|
58904
58975
|
}
|
|
58905
58976
|
});
|
|
@@ -58920,7 +58991,7 @@ init_lint();
|
|
|
58920
58991
|
init_manager();
|
|
58921
58992
|
|
|
58922
58993
|
// src/quality/metrics.ts
|
|
58923
|
-
import * as
|
|
58994
|
+
import * as fs34 from "fs";
|
|
58924
58995
|
import * as path47 from "path";
|
|
58925
58996
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
58926
58997
|
var MIN_DUPLICATION_LINES = 10;
|
|
@@ -58959,11 +59030,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
58959
59030
|
}
|
|
58960
59031
|
function getComplexityForFile2(filePath) {
|
|
58961
59032
|
try {
|
|
58962
|
-
const stat2 =
|
|
59033
|
+
const stat2 = fs34.statSync(filePath);
|
|
58963
59034
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
58964
59035
|
return null;
|
|
58965
59036
|
}
|
|
58966
|
-
const content =
|
|
59037
|
+
const content = fs34.readFileSync(filePath, "utf-8");
|
|
58967
59038
|
return estimateCyclomaticComplexity(content);
|
|
58968
59039
|
} catch {
|
|
58969
59040
|
return null;
|
|
@@ -58974,7 +59045,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
58974
59045
|
const analyzedFiles = [];
|
|
58975
59046
|
for (const file3 of files) {
|
|
58976
59047
|
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58977
|
-
if (!
|
|
59048
|
+
if (!fs34.existsSync(fullPath)) {
|
|
58978
59049
|
continue;
|
|
58979
59050
|
}
|
|
58980
59051
|
const complexity = getComplexityForFile2(fullPath);
|
|
@@ -59095,7 +59166,7 @@ function countGoExports(content) {
|
|
|
59095
59166
|
}
|
|
59096
59167
|
function getExportCountForFile(filePath) {
|
|
59097
59168
|
try {
|
|
59098
|
-
const content =
|
|
59169
|
+
const content = fs34.readFileSync(filePath, "utf-8");
|
|
59099
59170
|
const ext = path47.extname(filePath).toLowerCase();
|
|
59100
59171
|
switch (ext) {
|
|
59101
59172
|
case ".ts":
|
|
@@ -59123,7 +59194,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
59123
59194
|
const analyzedFiles = [];
|
|
59124
59195
|
for (const file3 of files) {
|
|
59125
59196
|
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
59126
|
-
if (!
|
|
59197
|
+
if (!fs34.existsSync(fullPath)) {
|
|
59127
59198
|
continue;
|
|
59128
59199
|
}
|
|
59129
59200
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -59157,15 +59228,15 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
59157
59228
|
const analyzedFiles = [];
|
|
59158
59229
|
for (const file3 of files) {
|
|
59159
59230
|
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
59160
|
-
if (!
|
|
59231
|
+
if (!fs34.existsSync(fullPath)) {
|
|
59161
59232
|
continue;
|
|
59162
59233
|
}
|
|
59163
59234
|
try {
|
|
59164
|
-
const stat2 =
|
|
59235
|
+
const stat2 = fs34.statSync(fullPath);
|
|
59165
59236
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
59166
59237
|
continue;
|
|
59167
59238
|
}
|
|
59168
|
-
const content =
|
|
59239
|
+
const content = fs34.readFileSync(fullPath, "utf-8");
|
|
59169
59240
|
const lines = content.split(`
|
|
59170
59241
|
`).filter((line) => line.trim().length > 0);
|
|
59171
59242
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -59341,7 +59412,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
59341
59412
|
let testLines = 0;
|
|
59342
59413
|
let codeLines = 0;
|
|
59343
59414
|
const srcDir = path47.join(workingDir, "src");
|
|
59344
|
-
if (
|
|
59415
|
+
if (fs34.existsSync(srcDir)) {
|
|
59345
59416
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
59346
59417
|
codeLines += lines;
|
|
59347
59418
|
});
|
|
@@ -59349,14 +59420,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
59349
59420
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
59350
59421
|
for (const dir of possibleSrcDirs) {
|
|
59351
59422
|
const dirPath = path47.join(workingDir, dir);
|
|
59352
|
-
if (
|
|
59423
|
+
if (fs34.existsSync(dirPath)) {
|
|
59353
59424
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
59354
59425
|
codeLines += lines;
|
|
59355
59426
|
});
|
|
59356
59427
|
}
|
|
59357
59428
|
}
|
|
59358
59429
|
const testsDir = path47.join(workingDir, "tests");
|
|
59359
|
-
if (
|
|
59430
|
+
if (fs34.existsSync(testsDir)) {
|
|
59360
59431
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
59361
59432
|
testLines += lines;
|
|
59362
59433
|
});
|
|
@@ -59364,7 +59435,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
59364
59435
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
59365
59436
|
for (const dir of possibleTestDirs) {
|
|
59366
59437
|
const dirPath = path47.join(workingDir, dir);
|
|
59367
|
-
if (
|
|
59438
|
+
if (fs34.existsSync(dirPath) && dirPath !== testsDir) {
|
|
59368
59439
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
59369
59440
|
testLines += lines;
|
|
59370
59441
|
});
|
|
@@ -59376,7 +59447,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
59376
59447
|
}
|
|
59377
59448
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
59378
59449
|
try {
|
|
59379
|
-
const entries =
|
|
59450
|
+
const entries = fs34.readdirSync(dirPath, { withFileTypes: true });
|
|
59380
59451
|
for (const entry of entries) {
|
|
59381
59452
|
const fullPath = path47.join(dirPath, entry.name);
|
|
59382
59453
|
if (entry.isDirectory()) {
|
|
@@ -59422,7 +59493,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
59422
59493
|
continue;
|
|
59423
59494
|
}
|
|
59424
59495
|
try {
|
|
59425
|
-
const content =
|
|
59496
|
+
const content = fs34.readFileSync(fullPath, "utf-8");
|
|
59426
59497
|
const lines = countCodeLines(content);
|
|
59427
59498
|
callback(lines);
|
|
59428
59499
|
} catch {}
|
|
@@ -59636,7 +59707,7 @@ async function qualityBudget(input, directory) {
|
|
|
59636
59707
|
init_dist();
|
|
59637
59708
|
init_manager();
|
|
59638
59709
|
init_detector();
|
|
59639
|
-
import * as
|
|
59710
|
+
import * as fs35 from "fs";
|
|
59640
59711
|
import * as path48 from "path";
|
|
59641
59712
|
import { extname as extname9 } from "path";
|
|
59642
59713
|
|
|
@@ -60504,17 +60575,17 @@ var SEVERITY_ORDER = {
|
|
|
60504
60575
|
};
|
|
60505
60576
|
function shouldSkipFile(filePath) {
|
|
60506
60577
|
try {
|
|
60507
|
-
const stats =
|
|
60578
|
+
const stats = fs35.statSync(filePath);
|
|
60508
60579
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
60509
60580
|
return { skip: true, reason: "file too large" };
|
|
60510
60581
|
}
|
|
60511
60582
|
if (stats.size === 0) {
|
|
60512
60583
|
return { skip: true, reason: "empty file" };
|
|
60513
60584
|
}
|
|
60514
|
-
const fd =
|
|
60585
|
+
const fd = fs35.openSync(filePath, "r");
|
|
60515
60586
|
const buffer = Buffer.alloc(8192);
|
|
60516
|
-
const bytesRead =
|
|
60517
|
-
|
|
60587
|
+
const bytesRead = fs35.readSync(fd, buffer, 0, 8192, 0);
|
|
60588
|
+
fs35.closeSync(fd);
|
|
60518
60589
|
if (bytesRead > 0) {
|
|
60519
60590
|
let nullCount = 0;
|
|
60520
60591
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -60553,7 +60624,7 @@ function countBySeverity(findings) {
|
|
|
60553
60624
|
}
|
|
60554
60625
|
function scanFileWithTierA(filePath, language) {
|
|
60555
60626
|
try {
|
|
60556
|
-
const content =
|
|
60627
|
+
const content = fs35.readFileSync(filePath, "utf-8");
|
|
60557
60628
|
const findings = executeRulesSync(filePath, content, language);
|
|
60558
60629
|
return findings.map((f) => ({
|
|
60559
60630
|
rule_id: f.rule_id,
|
|
@@ -60601,7 +60672,7 @@ async function sastScan(input, directory, config3) {
|
|
|
60601
60672
|
continue;
|
|
60602
60673
|
}
|
|
60603
60674
|
const resolvedPath = path48.isAbsolute(filePath) ? filePath : path48.resolve(directory, filePath);
|
|
60604
|
-
if (!
|
|
60675
|
+
if (!fs35.existsSync(resolvedPath)) {
|
|
60605
60676
|
_filesSkipped++;
|
|
60606
60677
|
continue;
|
|
60607
60678
|
}
|
|
@@ -61060,7 +61131,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61060
61131
|
}
|
|
61061
61132
|
let stat2;
|
|
61062
61133
|
try {
|
|
61063
|
-
stat2 =
|
|
61134
|
+
stat2 = fs36.statSync(file3);
|
|
61064
61135
|
} catch {
|
|
61065
61136
|
skippedFiles++;
|
|
61066
61137
|
continue;
|
|
@@ -61071,7 +61142,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61071
61142
|
}
|
|
61072
61143
|
let content;
|
|
61073
61144
|
try {
|
|
61074
|
-
const buffer =
|
|
61145
|
+
const buffer = fs36.readFileSync(file3);
|
|
61075
61146
|
if (buffer.includes(0)) {
|
|
61076
61147
|
skippedFiles++;
|
|
61077
61148
|
continue;
|
|
@@ -61471,7 +61542,7 @@ ${paginatedContent}`;
|
|
|
61471
61542
|
init_tool();
|
|
61472
61543
|
init_manager2();
|
|
61473
61544
|
init_create_tool();
|
|
61474
|
-
import * as
|
|
61545
|
+
import * as fs37 from "fs";
|
|
61475
61546
|
import * as path50 from "path";
|
|
61476
61547
|
function detectPlaceholderContent(args2) {
|
|
61477
61548
|
const issues = [];
|
|
@@ -61583,7 +61654,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
61583
61654
|
phases_count: plan.phases.length,
|
|
61584
61655
|
tasks_count: tasksCount
|
|
61585
61656
|
});
|
|
61586
|
-
await
|
|
61657
|
+
await fs37.promises.writeFile(markerPath, marker, "utf8");
|
|
61587
61658
|
} catch {}
|
|
61588
61659
|
return {
|
|
61589
61660
|
success: true,
|
|
@@ -61626,7 +61697,7 @@ var save_plan = createSwarmTool({
|
|
|
61626
61697
|
// src/tools/sbom-generate.ts
|
|
61627
61698
|
init_dist();
|
|
61628
61699
|
init_manager();
|
|
61629
|
-
import * as
|
|
61700
|
+
import * as fs38 from "fs";
|
|
61630
61701
|
import * as path51 from "path";
|
|
61631
61702
|
|
|
61632
61703
|
// src/sbom/detectors/index.ts
|
|
@@ -62473,7 +62544,7 @@ function findManifestFiles(rootDir) {
|
|
|
62473
62544
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
62474
62545
|
function searchDir(dir) {
|
|
62475
62546
|
try {
|
|
62476
|
-
const entries =
|
|
62547
|
+
const entries = fs38.readdirSync(dir, { withFileTypes: true });
|
|
62477
62548
|
for (const entry of entries) {
|
|
62478
62549
|
const fullPath = path51.join(dir, entry.name);
|
|
62479
62550
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
@@ -62500,7 +62571,7 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
62500
62571
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
62501
62572
|
for (const dir of directories) {
|
|
62502
62573
|
try {
|
|
62503
|
-
const entries =
|
|
62574
|
+
const entries = fs38.readdirSync(dir, { withFileTypes: true });
|
|
62504
62575
|
for (const entry of entries) {
|
|
62505
62576
|
const fullPath = path51.join(dir, entry.name);
|
|
62506
62577
|
if (entry.isFile()) {
|
|
@@ -62537,7 +62608,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
62537
62608
|
}
|
|
62538
62609
|
function ensureOutputDir(outputDir) {
|
|
62539
62610
|
try {
|
|
62540
|
-
|
|
62611
|
+
fs38.mkdirSync(outputDir, { recursive: true });
|
|
62541
62612
|
} catch (error93) {
|
|
62542
62613
|
if (!error93 || error93.code !== "EEXIST") {
|
|
62543
62614
|
throw error93;
|
|
@@ -62631,10 +62702,10 @@ var sbom_generate = createSwarmTool({
|
|
|
62631
62702
|
for (const manifestFile of manifestFiles) {
|
|
62632
62703
|
try {
|
|
62633
62704
|
const fullPath = path51.isAbsolute(manifestFile) ? manifestFile : path51.join(workingDir, manifestFile);
|
|
62634
|
-
if (!
|
|
62705
|
+
if (!fs38.existsSync(fullPath)) {
|
|
62635
62706
|
continue;
|
|
62636
62707
|
}
|
|
62637
|
-
const content =
|
|
62708
|
+
const content = fs38.readFileSync(fullPath, "utf-8");
|
|
62638
62709
|
const components = detectComponents(manifestFile, content);
|
|
62639
62710
|
processedFiles.push(manifestFile);
|
|
62640
62711
|
if (components.length > 0) {
|
|
@@ -62648,7 +62719,7 @@ var sbom_generate = createSwarmTool({
|
|
|
62648
62719
|
const bomJson = serializeCycloneDX(bom);
|
|
62649
62720
|
const filename = generateSbomFilename();
|
|
62650
62721
|
const outputPath = path51.join(outputDir, filename);
|
|
62651
|
-
|
|
62722
|
+
fs38.writeFileSync(outputPath, bomJson, "utf-8");
|
|
62652
62723
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
62653
62724
|
try {
|
|
62654
62725
|
const timestamp = new Date().toISOString();
|
|
@@ -62690,7 +62761,7 @@ var sbom_generate = createSwarmTool({
|
|
|
62690
62761
|
// src/tools/schema-drift.ts
|
|
62691
62762
|
init_dist();
|
|
62692
62763
|
init_create_tool();
|
|
62693
|
-
import * as
|
|
62764
|
+
import * as fs39 from "fs";
|
|
62694
62765
|
import * as path52 from "path";
|
|
62695
62766
|
var SPEC_CANDIDATES = [
|
|
62696
62767
|
"openapi.json",
|
|
@@ -62732,19 +62803,19 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
62732
62803
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
62733
62804
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
62734
62805
|
}
|
|
62735
|
-
const stats =
|
|
62806
|
+
const stats = fs39.statSync(resolvedPath);
|
|
62736
62807
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
62737
62808
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
62738
62809
|
}
|
|
62739
|
-
if (!
|
|
62810
|
+
if (!fs39.existsSync(resolvedPath)) {
|
|
62740
62811
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
62741
62812
|
}
|
|
62742
62813
|
return resolvedPath;
|
|
62743
62814
|
}
|
|
62744
62815
|
for (const candidate of SPEC_CANDIDATES) {
|
|
62745
62816
|
const candidatePath = path52.resolve(cwd, candidate);
|
|
62746
|
-
if (
|
|
62747
|
-
const stats =
|
|
62817
|
+
if (fs39.existsSync(candidatePath)) {
|
|
62818
|
+
const stats = fs39.statSync(candidatePath);
|
|
62748
62819
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
62749
62820
|
return candidatePath;
|
|
62750
62821
|
}
|
|
@@ -62753,7 +62824,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
62753
62824
|
return null;
|
|
62754
62825
|
}
|
|
62755
62826
|
function parseSpec(specFile) {
|
|
62756
|
-
const content =
|
|
62827
|
+
const content = fs39.readFileSync(specFile, "utf-8");
|
|
62757
62828
|
const ext = path52.extname(specFile).toLowerCase();
|
|
62758
62829
|
if (ext === ".json") {
|
|
62759
62830
|
return parseJsonSpec(content);
|
|
@@ -62825,7 +62896,7 @@ function extractRoutes(cwd) {
|
|
|
62825
62896
|
function walkDir(dir) {
|
|
62826
62897
|
let entries;
|
|
62827
62898
|
try {
|
|
62828
|
-
entries =
|
|
62899
|
+
entries = fs39.readdirSync(dir, { withFileTypes: true });
|
|
62829
62900
|
} catch {
|
|
62830
62901
|
return;
|
|
62831
62902
|
}
|
|
@@ -62858,7 +62929,7 @@ function extractRoutes(cwd) {
|
|
|
62858
62929
|
}
|
|
62859
62930
|
function extractRoutesFromFile(filePath) {
|
|
62860
62931
|
const routes = [];
|
|
62861
|
-
const content =
|
|
62932
|
+
const content = fs39.readFileSync(filePath, "utf-8");
|
|
62862
62933
|
const lines = content.split(/\r?\n/);
|
|
62863
62934
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
62864
62935
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -63009,7 +63080,7 @@ init_secretscan();
|
|
|
63009
63080
|
// src/tools/symbols.ts
|
|
63010
63081
|
init_tool();
|
|
63011
63082
|
init_create_tool();
|
|
63012
|
-
import * as
|
|
63083
|
+
import * as fs40 from "fs";
|
|
63013
63084
|
import * as path53 from "path";
|
|
63014
63085
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
63015
63086
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
@@ -63040,8 +63111,8 @@ function containsWindowsAttacks(str) {
|
|
|
63040
63111
|
function isPathInWorkspace(filePath, workspace) {
|
|
63041
63112
|
try {
|
|
63042
63113
|
const resolvedPath = path53.resolve(workspace, filePath);
|
|
63043
|
-
const realWorkspace =
|
|
63044
|
-
const realResolvedPath =
|
|
63114
|
+
const realWorkspace = fs40.realpathSync(workspace);
|
|
63115
|
+
const realResolvedPath = fs40.realpathSync(resolvedPath);
|
|
63045
63116
|
const relativePath = path53.relative(realWorkspace, realResolvedPath);
|
|
63046
63117
|
if (relativePath.startsWith("..") || path53.isAbsolute(relativePath)) {
|
|
63047
63118
|
return false;
|
|
@@ -63061,11 +63132,11 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
63061
63132
|
}
|
|
63062
63133
|
let content;
|
|
63063
63134
|
try {
|
|
63064
|
-
const stats =
|
|
63135
|
+
const stats = fs40.statSync(fullPath);
|
|
63065
63136
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
63066
63137
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
63067
63138
|
}
|
|
63068
|
-
content =
|
|
63139
|
+
content = fs40.readFileSync(fullPath, "utf-8");
|
|
63069
63140
|
} catch {
|
|
63070
63141
|
return [];
|
|
63071
63142
|
}
|
|
@@ -63213,11 +63284,11 @@ function extractPythonSymbols(filePath, cwd) {
|
|
|
63213
63284
|
}
|
|
63214
63285
|
let content;
|
|
63215
63286
|
try {
|
|
63216
|
-
const stats =
|
|
63287
|
+
const stats = fs40.statSync(fullPath);
|
|
63217
63288
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
63218
63289
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
63219
63290
|
}
|
|
63220
|
-
content =
|
|
63291
|
+
content = fs40.readFileSync(fullPath, "utf-8");
|
|
63221
63292
|
} catch {
|
|
63222
63293
|
return [];
|
|
63223
63294
|
}
|
|
@@ -63361,7 +63432,7 @@ init_test_runner();
|
|
|
63361
63432
|
init_dist();
|
|
63362
63433
|
init_utils();
|
|
63363
63434
|
init_create_tool();
|
|
63364
|
-
import * as
|
|
63435
|
+
import * as fs41 from "fs";
|
|
63365
63436
|
import * as path54 from "path";
|
|
63366
63437
|
var MAX_TEXT_LENGTH = 200;
|
|
63367
63438
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
@@ -63457,7 +63528,7 @@ function isSupportedExtension(filePath) {
|
|
|
63457
63528
|
function findSourceFiles2(dir, files = []) {
|
|
63458
63529
|
let entries;
|
|
63459
63530
|
try {
|
|
63460
|
-
entries =
|
|
63531
|
+
entries = fs41.readdirSync(dir);
|
|
63461
63532
|
} catch {
|
|
63462
63533
|
return files;
|
|
63463
63534
|
}
|
|
@@ -63469,7 +63540,7 @@ function findSourceFiles2(dir, files = []) {
|
|
|
63469
63540
|
const fullPath = path54.join(dir, entry);
|
|
63470
63541
|
let stat2;
|
|
63471
63542
|
try {
|
|
63472
|
-
stat2 =
|
|
63543
|
+
stat2 = fs41.statSync(fullPath);
|
|
63473
63544
|
} catch {
|
|
63474
63545
|
continue;
|
|
63475
63546
|
}
|
|
@@ -63562,7 +63633,7 @@ var todo_extract = createSwarmTool({
|
|
|
63562
63633
|
return JSON.stringify(errorResult, null, 2);
|
|
63563
63634
|
}
|
|
63564
63635
|
const scanPath = resolvedPath;
|
|
63565
|
-
if (!
|
|
63636
|
+
if (!fs41.existsSync(scanPath)) {
|
|
63566
63637
|
const errorResult = {
|
|
63567
63638
|
error: `path not found: ${pathsInput}`,
|
|
63568
63639
|
total: 0,
|
|
@@ -63572,7 +63643,7 @@ var todo_extract = createSwarmTool({
|
|
|
63572
63643
|
return JSON.stringify(errorResult, null, 2);
|
|
63573
63644
|
}
|
|
63574
63645
|
const filesToScan = [];
|
|
63575
|
-
const stat2 =
|
|
63646
|
+
const stat2 = fs41.statSync(scanPath);
|
|
63576
63647
|
if (stat2.isFile()) {
|
|
63577
63648
|
if (isSupportedExtension(scanPath)) {
|
|
63578
63649
|
filesToScan.push(scanPath);
|
|
@@ -63591,11 +63662,11 @@ var todo_extract = createSwarmTool({
|
|
|
63591
63662
|
const allEntries = [];
|
|
63592
63663
|
for (const filePath of filesToScan) {
|
|
63593
63664
|
try {
|
|
63594
|
-
const fileStat =
|
|
63665
|
+
const fileStat = fs41.statSync(filePath);
|
|
63595
63666
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
63596
63667
|
continue;
|
|
63597
63668
|
}
|
|
63598
|
-
const content =
|
|
63669
|
+
const content = fs41.readFileSync(filePath, "utf-8");
|
|
63599
63670
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
63600
63671
|
allEntries.push(...entries);
|
|
63601
63672
|
} catch {}
|
|
@@ -63623,18 +63694,18 @@ var todo_extract = createSwarmTool({
|
|
|
63623
63694
|
// src/tools/update-task-status.ts
|
|
63624
63695
|
init_tool();
|
|
63625
63696
|
init_schema();
|
|
63626
|
-
import * as
|
|
63697
|
+
import * as fs43 from "fs";
|
|
63627
63698
|
import * as path56 from "path";
|
|
63628
63699
|
|
|
63629
63700
|
// src/hooks/diff-scope.ts
|
|
63630
|
-
import * as
|
|
63701
|
+
import * as fs42 from "fs";
|
|
63631
63702
|
import * as path55 from "path";
|
|
63632
63703
|
function getDeclaredScope(taskId, directory) {
|
|
63633
63704
|
try {
|
|
63634
63705
|
const planPath = path55.join(directory, ".swarm", "plan.json");
|
|
63635
|
-
if (!
|
|
63706
|
+
if (!fs42.existsSync(planPath))
|
|
63636
63707
|
return null;
|
|
63637
|
-
const raw =
|
|
63708
|
+
const raw = fs42.readFileSync(planPath, "utf-8");
|
|
63638
63709
|
const plan = JSON.parse(raw);
|
|
63639
63710
|
for (const phase of plan.phases ?? []) {
|
|
63640
63711
|
for (const task of phase.tasks ?? []) {
|
|
@@ -63766,10 +63837,10 @@ function hasActiveTurboMode2() {
|
|
|
63766
63837
|
function checkReviewerGate(taskId, workingDirectory) {
|
|
63767
63838
|
try {
|
|
63768
63839
|
if (hasActiveTurboMode2()) {
|
|
63769
|
-
const resolvedDir2 = workingDirectory
|
|
63840
|
+
const resolvedDir2 = workingDirectory;
|
|
63770
63841
|
try {
|
|
63771
63842
|
const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
|
|
63772
|
-
const planRaw =
|
|
63843
|
+
const planRaw = fs43.readFileSync(planPath, "utf-8");
|
|
63773
63844
|
const plan = JSON.parse(planRaw);
|
|
63774
63845
|
for (const planPhase of plan.phases ?? []) {
|
|
63775
63846
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -63786,10 +63857,10 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63786
63857
|
}
|
|
63787
63858
|
} catch {}
|
|
63788
63859
|
}
|
|
63789
|
-
const resolvedDir = workingDirectory
|
|
63860
|
+
const resolvedDir = workingDirectory;
|
|
63790
63861
|
try {
|
|
63791
63862
|
const evidencePath = path56.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
|
|
63792
|
-
const raw =
|
|
63863
|
+
const raw = fs43.readFileSync(evidencePath, "utf-8");
|
|
63793
63864
|
const evidence = JSON.parse(raw);
|
|
63794
63865
|
if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
|
|
63795
63866
|
const allGatesMet = evidence.required_gates.every((gate) => evidence.gates[gate] != null);
|
|
@@ -63828,9 +63899,9 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63828
63899
|
stateEntries.push(`${sessionId}: ${state2}`);
|
|
63829
63900
|
}
|
|
63830
63901
|
try {
|
|
63831
|
-
const resolvedDir2 = workingDirectory
|
|
63902
|
+
const resolvedDir2 = workingDirectory;
|
|
63832
63903
|
const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
|
|
63833
|
-
const planRaw =
|
|
63904
|
+
const planRaw = fs43.readFileSync(planPath, "utf-8");
|
|
63834
63905
|
const plan = JSON.parse(planRaw);
|
|
63835
63906
|
for (const planPhase of plan.phases ?? []) {
|
|
63836
63907
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -63890,7 +63961,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63890
63961
|
}
|
|
63891
63962
|
async function checkReviewerGateWithScope(taskId, workingDirectory) {
|
|
63892
63963
|
const result = checkReviewerGate(taskId, workingDirectory);
|
|
63893
|
-
const scopeWarning = await validateDiffScope(taskId, workingDirectory
|
|
63964
|
+
const scopeWarning = await validateDiffScope(taskId, workingDirectory).catch(() => null);
|
|
63894
63965
|
if (!scopeWarning)
|
|
63895
63966
|
return result;
|
|
63896
63967
|
return {
|
|
@@ -64024,9 +64095,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
64024
64095
|
}
|
|
64025
64096
|
const resolvedDir = path56.resolve(normalizedDir);
|
|
64026
64097
|
try {
|
|
64027
|
-
const realPath =
|
|
64098
|
+
const realPath = fs43.realpathSync(resolvedDir);
|
|
64028
64099
|
const planPath = path56.join(realPath, ".swarm", "plan.json");
|
|
64029
|
-
if (!
|
|
64100
|
+
if (!fs43.existsSync(planPath)) {
|
|
64030
64101
|
return {
|
|
64031
64102
|
success: false,
|
|
64032
64103
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -64047,9 +64118,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
64047
64118
|
}
|
|
64048
64119
|
} else {
|
|
64049
64120
|
if (!fallbackDir) {
|
|
64050
|
-
console.warn("[update-task-status] fallbackDir is undefined
|
|
64121
|
+
console.warn("[update-task-status] fallbackDir is undefined");
|
|
64051
64122
|
}
|
|
64052
|
-
directory = fallbackDir
|
|
64123
|
+
directory = fallbackDir;
|
|
64053
64124
|
}
|
|
64054
64125
|
if (args2.status === "completed") {
|
|
64055
64126
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
@@ -64107,17 +64178,21 @@ var update_task_status = createSwarmTool({
|
|
|
64107
64178
|
init_utils();
|
|
64108
64179
|
|
|
64109
64180
|
// src/utils/tool-output.ts
|
|
64110
|
-
function truncateToolOutput(output, maxLines, toolName) {
|
|
64181
|
+
function truncateToolOutput(output, maxLines, toolName, tailLines = 10) {
|
|
64111
64182
|
if (!output) {
|
|
64112
64183
|
return output;
|
|
64113
64184
|
}
|
|
64185
|
+
if (tailLines >= maxLines) {
|
|
64186
|
+
tailLines = Math.floor(maxLines / 2);
|
|
64187
|
+
}
|
|
64114
64188
|
const lines = output.split(`
|
|
64115
64189
|
`);
|
|
64116
64190
|
if (lines.length <= maxLines) {
|
|
64117
64191
|
return output;
|
|
64118
64192
|
}
|
|
64119
64193
|
const omittedCount = lines.length - maxLines;
|
|
64120
|
-
const
|
|
64194
|
+
const headLines = lines.slice(0, maxLines - tailLines);
|
|
64195
|
+
const tailContent = lines.slice(-tailLines);
|
|
64121
64196
|
const footerLines = [];
|
|
64122
64197
|
footerLines.push("");
|
|
64123
64198
|
footerLines.push(`[... ${omittedCount} line${omittedCount === 1 ? "" : "s"} omitted ...]`);
|
|
@@ -64125,7 +64200,9 @@ function truncateToolOutput(output, maxLines, toolName) {
|
|
|
64125
64200
|
footerLines.push(`Tool: ${toolName}`);
|
|
64126
64201
|
}
|
|
64127
64202
|
footerLines.push("Use /swarm retrieve <id> to get the full content");
|
|
64128
|
-
return `${
|
|
64203
|
+
return `${headLines.join(`
|
|
64204
|
+
`)}
|
|
64205
|
+
${tailContent.join(`
|
|
64129
64206
|
`)}
|
|
64130
64207
|
${footerLines.join(`
|
|
64131
64208
|
`)}`;
|
|
@@ -64166,7 +64243,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64166
64243
|
console.warn("");
|
|
64167
64244
|
}
|
|
64168
64245
|
const delegationHandler = createDelegationTrackerHook(config3, guardrailsConfig.enabled);
|
|
64169
|
-
const guardrailsHooks = createGuardrailsHooks(ctx.directory, guardrailsConfig);
|
|
64246
|
+
const guardrailsHooks = createGuardrailsHooks(ctx.directory, undefined, guardrailsConfig);
|
|
64170
64247
|
const watchdogConfig = WatchdogConfigSchema.parse(config3.watchdog ?? {});
|
|
64171
64248
|
const advisoryInjector = (sessionId, message) => {
|
|
64172
64249
|
const s = swarmState.agentSessions.get(sessionId);
|
|
@@ -64556,17 +64633,24 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64556
64633
|
await compactionServiceHook.toolAfter(input, output);
|
|
64557
64634
|
const toolOutputConfig = config3.tool_output;
|
|
64558
64635
|
if (toolOutputConfig && toolOutputConfig.truncation_enabled !== false && typeof output.output === "string") {
|
|
64559
|
-
const
|
|
64636
|
+
const defaultTruncatableTools = new Set([
|
|
64637
|
+
"diff",
|
|
64638
|
+
"symbols",
|
|
64639
|
+
"bash",
|
|
64640
|
+
"shell",
|
|
64641
|
+
"test_runner",
|
|
64642
|
+
"lint",
|
|
64560
64643
|
"pre_check_batch",
|
|
64644
|
+
"complexity_hotspots",
|
|
64561
64645
|
"pkg_audit",
|
|
64562
|
-
"
|
|
64563
|
-
"
|
|
64564
|
-
];
|
|
64565
|
-
|
|
64566
|
-
|
|
64567
|
-
|
|
64568
|
-
|
|
64569
|
-
|
|
64646
|
+
"sbom_generate",
|
|
64647
|
+
"schema_drift"
|
|
64648
|
+
]);
|
|
64649
|
+
const configuredTools = toolOutputConfig.truncation_tools;
|
|
64650
|
+
const truncatableTools = configuredTools && configuredTools.length > 0 ? new Set(configuredTools) : defaultTruncatableTools;
|
|
64651
|
+
const maxLines = toolOutputConfig.per_tool?.[input.tool] ?? toolOutputConfig.max_lines ?? 150;
|
|
64652
|
+
if (truncatableTools.has(input.tool)) {
|
|
64653
|
+
output.output = truncateToolOutput(output.output, maxLines, input.tool, 10);
|
|
64570
64654
|
}
|
|
64571
64655
|
}
|
|
64572
64656
|
const normalizedTool = input.tool.replace(/^[^:]+[:.]/, "");
|