opencode-swarm 7.48.1 → 7.49.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/agents/critic.d.ts +2 -2
- package/dist/cli/index.js +1030 -1016
- package/dist/config/agent-names.d.ts +19 -0
- package/dist/config/constants.d.ts +4 -10
- package/dist/index.js +13819 -13722
- package/dist/services/tool-doctor.d.ts +28 -5
- package/dist/tools/manifest.d.ts +109 -0
- package/dist/tools/plugin-registration.d.ts +21 -0
- package/dist/tools/repo-graph/builder.d.ts +22 -0
- package/dist/tools/tool-metadata.d.ts +373 -0
- package/dist/tools/tool-names.d.ts +12 -7
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "opencode-swarm",
|
|
55
|
-
version: "7.
|
|
55
|
+
version: "7.49.1",
|
|
56
56
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
57
57
|
main: "dist/index.js",
|
|
58
58
|
types: "dist/index.d.ts",
|
|
@@ -16449,94 +16449,561 @@ var init_acknowledge_spec_drift = __esm(() => {
|
|
|
16449
16449
|
init_spec_hash();
|
|
16450
16450
|
});
|
|
16451
16451
|
|
|
16452
|
-
// src/
|
|
16453
|
-
var
|
|
16454
|
-
var
|
|
16455
|
-
|
|
16456
|
-
|
|
16457
|
-
|
|
16458
|
-
"
|
|
16459
|
-
"
|
|
16460
|
-
"
|
|
16461
|
-
"
|
|
16462
|
-
"
|
|
16463
|
-
"
|
|
16464
|
-
"
|
|
16465
|
-
"
|
|
16466
|
-
"
|
|
16467
|
-
"
|
|
16468
|
-
"
|
|
16469
|
-
"
|
|
16470
|
-
"
|
|
16471
|
-
"
|
|
16472
|
-
"
|
|
16473
|
-
|
|
16474
|
-
|
|
16475
|
-
"submit_phase_council_verdicts",
|
|
16476
|
-
"declare_council_criteria",
|
|
16477
|
-
"sbom_generate",
|
|
16478
|
-
"checkpoint",
|
|
16479
|
-
"pkg_audit",
|
|
16480
|
-
"test_runner",
|
|
16481
|
-
"test_impact",
|
|
16482
|
-
"mutation_test",
|
|
16483
|
-
"generate_mutants",
|
|
16484
|
-
"detect_domains",
|
|
16485
|
-
"gitingest",
|
|
16486
|
-
"retrieve_summary",
|
|
16487
|
-
"extract_code_blocks",
|
|
16488
|
-
"phase_complete",
|
|
16489
|
-
"save_plan",
|
|
16490
|
-
"update_task_status",
|
|
16491
|
-
"lint_spec",
|
|
16492
|
-
"write_retro",
|
|
16493
|
-
"write_drift_evidence",
|
|
16494
|
-
"write_hallucination_evidence",
|
|
16495
|
-
"write_mutation_evidence",
|
|
16496
|
-
"declare_scope",
|
|
16497
|
-
"knowledge_query",
|
|
16498
|
-
"doc_scan",
|
|
16499
|
-
"doc_extract",
|
|
16500
|
-
"curator_analyze",
|
|
16501
|
-
"knowledge_add",
|
|
16502
|
-
"knowledge_recall",
|
|
16503
|
-
"knowledge_remove",
|
|
16504
|
-
"co_change_analyzer",
|
|
16505
|
-
"search",
|
|
16506
|
-
"batch_symbols",
|
|
16507
|
-
"suggest_patch",
|
|
16508
|
-
"req_coverage",
|
|
16509
|
-
"get_approved_plan",
|
|
16510
|
-
"repo_map",
|
|
16511
|
-
"get_qa_gate_profile",
|
|
16512
|
-
"set_qa_gates",
|
|
16513
|
-
"web_search",
|
|
16514
|
-
"convene_general_council",
|
|
16515
|
-
"write_final_council_evidence",
|
|
16516
|
-
"skill_generate",
|
|
16517
|
-
"skill_list",
|
|
16518
|
-
"skill_apply",
|
|
16519
|
-
"skill_inspect",
|
|
16520
|
-
"skill_regenerate",
|
|
16521
|
-
"skill_retire",
|
|
16522
|
-
"skill_improve",
|
|
16523
|
-
"spec_write",
|
|
16524
|
-
"knowledge_ack",
|
|
16525
|
-
"knowledge_receipt",
|
|
16526
|
-
"knowledge_archive",
|
|
16527
|
-
"swarm_memory_recall",
|
|
16528
|
-
"swarm_memory_propose",
|
|
16529
|
-
"swarm_command",
|
|
16530
|
-
"summarize_work",
|
|
16531
|
-
"write_architecture_supervisor_evidence",
|
|
16532
|
-
"lean_turbo_plan_lanes",
|
|
16533
|
-
"lean_turbo_acquire_locks",
|
|
16534
|
-
"lean_turbo_runner_status",
|
|
16535
|
-
"lean_turbo_review",
|
|
16536
|
-
"lean_turbo_run_phase",
|
|
16537
|
-
"lean_turbo_status"
|
|
16452
|
+
// src/config/agent-names.ts
|
|
16453
|
+
var QA_AGENTS, PIPELINE_AGENTS, ORCHESTRATOR_NAME = "architect", ALL_SUBAGENT_NAMES, ALL_AGENT_NAMES;
|
|
16454
|
+
var init_agent_names = __esm(() => {
|
|
16455
|
+
QA_AGENTS = ["reviewer", "critic", "critic_oversight"];
|
|
16456
|
+
PIPELINE_AGENTS = ["explorer", "coder", "test_engineer"];
|
|
16457
|
+
ALL_SUBAGENT_NAMES = [
|
|
16458
|
+
"sme",
|
|
16459
|
+
"docs",
|
|
16460
|
+
"docs_design",
|
|
16461
|
+
"designer",
|
|
16462
|
+
"critic_sounding_board",
|
|
16463
|
+
"critic_drift_verifier",
|
|
16464
|
+
"critic_hallucination_verifier",
|
|
16465
|
+
"critic_architecture_supervisor",
|
|
16466
|
+
"curator_init",
|
|
16467
|
+
"curator_phase",
|
|
16468
|
+
"council_generalist",
|
|
16469
|
+
"council_skeptic",
|
|
16470
|
+
"council_domain_expert",
|
|
16471
|
+
"skill_improver",
|
|
16472
|
+
"spec_writer",
|
|
16473
|
+
...QA_AGENTS,
|
|
16474
|
+
...PIPELINE_AGENTS
|
|
16538
16475
|
];
|
|
16476
|
+
ALL_AGENT_NAMES = [
|
|
16477
|
+
ORCHESTRATOR_NAME,
|
|
16478
|
+
...ALL_SUBAGENT_NAMES
|
|
16479
|
+
];
|
|
16480
|
+
});
|
|
16481
|
+
|
|
16482
|
+
// src/tools/tool-metadata.ts
|
|
16483
|
+
var TOOL_METADATA, TOOL_NAMES, TOOL_NAME_SET, TOOL_DESCRIPTIONS, AGENT_TOOL_MAP;
|
|
16484
|
+
var init_tool_metadata = __esm(() => {
|
|
16485
|
+
init_agent_names();
|
|
16486
|
+
TOOL_METADATA = {
|
|
16487
|
+
diff: {
|
|
16488
|
+
description: "structured git diff with contract change detection",
|
|
16489
|
+
agents: [
|
|
16490
|
+
"architect",
|
|
16491
|
+
"reviewer",
|
|
16492
|
+
"critic_oversight",
|
|
16493
|
+
"coder",
|
|
16494
|
+
"test_engineer"
|
|
16495
|
+
]
|
|
16496
|
+
},
|
|
16497
|
+
diff_summary: {
|
|
16498
|
+
description: "filter classified AST changes by category, risk level, or file for reviewer drill-down",
|
|
16499
|
+
agents: ["architect", "reviewer", "critic_oversight"]
|
|
16500
|
+
},
|
|
16501
|
+
syntax_check: {
|
|
16502
|
+
description: "syntax validation",
|
|
16503
|
+
agents: ["architect", "coder", "test_engineer"]
|
|
16504
|
+
},
|
|
16505
|
+
placeholder_scan: {
|
|
16506
|
+
description: "todo and FIXME comment detection",
|
|
16507
|
+
agents: ["architect", "reviewer"]
|
|
16508
|
+
},
|
|
16509
|
+
imports: {
|
|
16510
|
+
description: "dependency audit",
|
|
16511
|
+
agents: [
|
|
16512
|
+
"architect",
|
|
16513
|
+
"sme",
|
|
16514
|
+
"docs",
|
|
16515
|
+
"docs_design",
|
|
16516
|
+
"critic_sounding_board",
|
|
16517
|
+
"critic_drift_verifier",
|
|
16518
|
+
"critic_hallucination_verifier",
|
|
16519
|
+
"reviewer",
|
|
16520
|
+
"critic",
|
|
16521
|
+
"critic_oversight",
|
|
16522
|
+
"explorer",
|
|
16523
|
+
"coder",
|
|
16524
|
+
"test_engineer"
|
|
16525
|
+
]
|
|
16526
|
+
},
|
|
16527
|
+
lint: {
|
|
16528
|
+
description: "code quality",
|
|
16529
|
+
agents: ["architect", "reviewer", "coder"]
|
|
16530
|
+
},
|
|
16531
|
+
secretscan: {
|
|
16532
|
+
description: "secret detection",
|
|
16533
|
+
agents: ["architect", "reviewer", "critic_oversight"]
|
|
16534
|
+
},
|
|
16535
|
+
sast_scan: {
|
|
16536
|
+
description: "static analysis security scan",
|
|
16537
|
+
agents: ["architect", "reviewer", "critic_oversight"]
|
|
16538
|
+
},
|
|
16539
|
+
build_check: {
|
|
16540
|
+
description: "build verification",
|
|
16541
|
+
agents: ["architect", "coder", "test_engineer"]
|
|
16542
|
+
},
|
|
16543
|
+
pre_check_batch: {
|
|
16544
|
+
description: "parallel verification: lint:check + secretscan + sast_scan + quality_budget",
|
|
16545
|
+
agents: ["architect", "reviewer"]
|
|
16546
|
+
},
|
|
16547
|
+
quality_budget: {
|
|
16548
|
+
description: "code quality budget check",
|
|
16549
|
+
agents: ["architect"]
|
|
16550
|
+
},
|
|
16551
|
+
symbols: {
|
|
16552
|
+
description: "code symbol search",
|
|
16553
|
+
agents: [
|
|
16554
|
+
"architect",
|
|
16555
|
+
"sme",
|
|
16556
|
+
"docs",
|
|
16557
|
+
"docs_design",
|
|
16558
|
+
"designer",
|
|
16559
|
+
"critic_sounding_board",
|
|
16560
|
+
"critic_drift_verifier",
|
|
16561
|
+
"critic_hallucination_verifier",
|
|
16562
|
+
"spec_writer",
|
|
16563
|
+
"reviewer",
|
|
16564
|
+
"critic",
|
|
16565
|
+
"critic_oversight",
|
|
16566
|
+
"explorer",
|
|
16567
|
+
"coder",
|
|
16568
|
+
"test_engineer"
|
|
16569
|
+
]
|
|
16570
|
+
},
|
|
16571
|
+
complexity_hotspots: {
|
|
16572
|
+
description: "git churn \xD7 complexity risk map",
|
|
16573
|
+
agents: [
|
|
16574
|
+
"architect",
|
|
16575
|
+
"sme",
|
|
16576
|
+
"critic_sounding_board",
|
|
16577
|
+
"critic_drift_verifier",
|
|
16578
|
+
"critic_hallucination_verifier",
|
|
16579
|
+
"reviewer",
|
|
16580
|
+
"critic",
|
|
16581
|
+
"critic_oversight",
|
|
16582
|
+
"explorer",
|
|
16583
|
+
"test_engineer"
|
|
16584
|
+
]
|
|
16585
|
+
},
|
|
16586
|
+
schema_drift: {
|
|
16587
|
+
description: "OpenAPI spec vs route drift",
|
|
16588
|
+
agents: ["architect", "sme", "docs", "explorer"]
|
|
16589
|
+
},
|
|
16590
|
+
todo_extract: {
|
|
16591
|
+
description: "structured TODO/FIXME extraction",
|
|
16592
|
+
agents: ["architect", "docs", "explorer"]
|
|
16593
|
+
},
|
|
16594
|
+
evidence_check: {
|
|
16595
|
+
description: "verify task evidence completeness",
|
|
16596
|
+
agents: ["architect", "critic_oversight"]
|
|
16597
|
+
},
|
|
16598
|
+
check_gate_status: {
|
|
16599
|
+
description: "check the gate status of a specific task",
|
|
16600
|
+
agents: ["architect", "critic_oversight"]
|
|
16601
|
+
},
|
|
16602
|
+
completion_verify: {
|
|
16603
|
+
description: "verify completed tasks have required evidence",
|
|
16604
|
+
agents: ["architect", "critic_oversight"]
|
|
16605
|
+
},
|
|
16606
|
+
submit_council_verdicts: {
|
|
16607
|
+
description: "submit pre-collected council member verdicts for synthesis (architect MUST dispatch critic/reviewer/sme/test_engineer/explorer as Agent tasks first; this tool synthesizes only, it does not contact members)",
|
|
16608
|
+
agents: ["architect"]
|
|
16609
|
+
},
|
|
16610
|
+
submit_phase_council_verdicts: {
|
|
16611
|
+
description: "submit pre-collected phase-level council member verdicts for holistic phase synthesis (architect MUST dispatch all 5 council members with phase-scoped context first; this tool synthesizes only, it does not contact members)",
|
|
16612
|
+
agents: ["architect"]
|
|
16613
|
+
},
|
|
16614
|
+
declare_council_criteria: {
|
|
16615
|
+
description: "pre-declare acceptance criteria for a task before the coder starts work; criteria are read back during council evaluation",
|
|
16616
|
+
agents: ["architect"]
|
|
16617
|
+
},
|
|
16618
|
+
sbom_generate: {
|
|
16619
|
+
description: "SBOM generation for dependency inventory",
|
|
16620
|
+
agents: ["architect"]
|
|
16621
|
+
},
|
|
16622
|
+
checkpoint: {
|
|
16623
|
+
description: "state snapshots",
|
|
16624
|
+
agents: ["architect"]
|
|
16625
|
+
},
|
|
16626
|
+
pkg_audit: {
|
|
16627
|
+
description: "dependency vulnerability scan \u2014 npm/pip/cargo",
|
|
16628
|
+
agents: [
|
|
16629
|
+
"architect",
|
|
16630
|
+
"critic_hallucination_verifier",
|
|
16631
|
+
"reviewer",
|
|
16632
|
+
"critic_oversight",
|
|
16633
|
+
"test_engineer"
|
|
16634
|
+
]
|
|
16635
|
+
},
|
|
16636
|
+
test_runner: {
|
|
16637
|
+
description: "auto-detect and run tests",
|
|
16638
|
+
agents: ["architect", "reviewer", "test_engineer"]
|
|
16639
|
+
},
|
|
16640
|
+
test_impact: {
|
|
16641
|
+
description: "identify test files impacted by changed source files via import analysis",
|
|
16642
|
+
agents: ["architect", "reviewer", "critic_oversight", "test_engineer"]
|
|
16643
|
+
},
|
|
16644
|
+
mutation_test: {
|
|
16645
|
+
description: "executes pre-generated mutation patches against tests, evaluates kill rate against quality gate thresholds",
|
|
16646
|
+
agents: ["architect", "test_engineer"]
|
|
16647
|
+
},
|
|
16648
|
+
generate_mutants: {
|
|
16649
|
+
description: "generate LLM-based mutation testing patches for source files; returns MutationPatch[] for direct consumption by the mutation_test tool",
|
|
16650
|
+
agents: ["architect"]
|
|
16651
|
+
},
|
|
16652
|
+
detect_domains: {
|
|
16653
|
+
description: "detect which SME domains are relevant for a given text",
|
|
16654
|
+
agents: [
|
|
16655
|
+
"architect",
|
|
16656
|
+
"sme",
|
|
16657
|
+
"docs",
|
|
16658
|
+
"docs_design",
|
|
16659
|
+
"critic_sounding_board",
|
|
16660
|
+
"critic_drift_verifier",
|
|
16661
|
+
"critic_hallucination_verifier",
|
|
16662
|
+
"critic",
|
|
16663
|
+
"critic_oversight",
|
|
16664
|
+
"explorer"
|
|
16665
|
+
]
|
|
16666
|
+
},
|
|
16667
|
+
gitingest: {
|
|
16668
|
+
description: "fetch a GitHub repository full content via gitingest.com",
|
|
16669
|
+
agents: ["architect", "docs", "explorer"]
|
|
16670
|
+
},
|
|
16671
|
+
retrieve_summary: {
|
|
16672
|
+
description: "retrieve the full content of a stored tool output summary",
|
|
16673
|
+
agents: [
|
|
16674
|
+
"architect",
|
|
16675
|
+
"sme",
|
|
16676
|
+
"docs",
|
|
16677
|
+
"docs_design",
|
|
16678
|
+
"designer",
|
|
16679
|
+
"critic_sounding_board",
|
|
16680
|
+
"critic_drift_verifier",
|
|
16681
|
+
"critic_hallucination_verifier",
|
|
16682
|
+
"critic_architecture_supervisor",
|
|
16683
|
+
"spec_writer",
|
|
16684
|
+
"reviewer",
|
|
16685
|
+
"critic",
|
|
16686
|
+
"critic_oversight",
|
|
16687
|
+
"explorer",
|
|
16688
|
+
"coder",
|
|
16689
|
+
"test_engineer"
|
|
16690
|
+
]
|
|
16691
|
+
},
|
|
16692
|
+
extract_code_blocks: {
|
|
16693
|
+
description: "extract code blocks from text content and save them to files",
|
|
16694
|
+
agents: [
|
|
16695
|
+
"architect",
|
|
16696
|
+
"sme",
|
|
16697
|
+
"docs",
|
|
16698
|
+
"docs_design",
|
|
16699
|
+
"designer",
|
|
16700
|
+
"spec_writer",
|
|
16701
|
+
"reviewer",
|
|
16702
|
+
"explorer",
|
|
16703
|
+
"coder",
|
|
16704
|
+
"test_engineer"
|
|
16705
|
+
]
|
|
16706
|
+
},
|
|
16707
|
+
phase_complete: {
|
|
16708
|
+
description: "mark a phase as complete and track dispatched agents",
|
|
16709
|
+
agents: ["architect"]
|
|
16710
|
+
},
|
|
16711
|
+
save_plan: {
|
|
16712
|
+
description: "save a structured implementation plan",
|
|
16713
|
+
agents: ["architect"]
|
|
16714
|
+
},
|
|
16715
|
+
update_task_status: {
|
|
16716
|
+
description: "mark tasks complete, track phase progress",
|
|
16717
|
+
agents: ["architect"]
|
|
16718
|
+
},
|
|
16719
|
+
lint_spec: {
|
|
16720
|
+
description: "validate .swarm/spec.md format and required fields",
|
|
16721
|
+
agents: ["architect", "spec_writer"]
|
|
16722
|
+
},
|
|
16723
|
+
write_retro: {
|
|
16724
|
+
description: "document phase retrospectives via phase_complete workflow, capture lessons learned",
|
|
16725
|
+
agents: ["architect"]
|
|
16726
|
+
},
|
|
16727
|
+
write_drift_evidence: {
|
|
16728
|
+
description: "write drift verification evidence for a completed phase",
|
|
16729
|
+
agents: ["architect"]
|
|
16730
|
+
},
|
|
16731
|
+
write_hallucination_evidence: {
|
|
16732
|
+
description: "write hallucination verification evidence for a completed phase",
|
|
16733
|
+
agents: ["architect"]
|
|
16734
|
+
},
|
|
16735
|
+
write_mutation_evidence: {
|
|
16736
|
+
description: "write mutation gate evidence for a completed phase; normalizes PASS/WARN/FAIL/SKIP verdicts and writes .swarm/evidence/{phase}/mutation-gate.json",
|
|
16737
|
+
agents: ["architect"]
|
|
16738
|
+
},
|
|
16739
|
+
declare_scope: {
|
|
16740
|
+
description: "declare file scope for next coder delegation",
|
|
16741
|
+
agents: ["architect"]
|
|
16742
|
+
},
|
|
16743
|
+
knowledge_query: {
|
|
16744
|
+
description: "query swarm or hive knowledge with optional filters",
|
|
16745
|
+
agents: ["architect", "skill_improver", "spec_writer"]
|
|
16746
|
+
},
|
|
16747
|
+
doc_scan: {
|
|
16748
|
+
description: "scan project documentation files and build an index manifest",
|
|
16749
|
+
agents: [
|
|
16750
|
+
"architect",
|
|
16751
|
+
"docs_design",
|
|
16752
|
+
"skill_improver",
|
|
16753
|
+
"spec_writer",
|
|
16754
|
+
"explorer"
|
|
16755
|
+
]
|
|
16756
|
+
},
|
|
16757
|
+
doc_extract: {
|
|
16758
|
+
description: "extract actionable constraints from project documentation",
|
|
16759
|
+
agents: ["architect", "docs_design", "skill_improver", "spec_writer"]
|
|
16760
|
+
},
|
|
16761
|
+
curator_analyze: {
|
|
16762
|
+
description: "run curator phase analysis and optionally apply knowledge recommendations",
|
|
16763
|
+
agents: ["architect"]
|
|
16764
|
+
},
|
|
16765
|
+
knowledge_add: {
|
|
16766
|
+
description: "store a new lesson in the knowledge base",
|
|
16767
|
+
agents: ["architect", "coder"]
|
|
16768
|
+
},
|
|
16769
|
+
knowledge_recall: {
|
|
16770
|
+
description: "search the knowledge base for relevant past decisions",
|
|
16771
|
+
agents: [
|
|
16772
|
+
"architect",
|
|
16773
|
+
"sme",
|
|
16774
|
+
"docs",
|
|
16775
|
+
"docs_design",
|
|
16776
|
+
"designer",
|
|
16777
|
+
"critic_sounding_board",
|
|
16778
|
+
"critic_drift_verifier",
|
|
16779
|
+
"critic_hallucination_verifier",
|
|
16780
|
+
"critic_architecture_supervisor",
|
|
16781
|
+
"curator_init",
|
|
16782
|
+
"curator_phase",
|
|
16783
|
+
"skill_improver",
|
|
16784
|
+
"spec_writer",
|
|
16785
|
+
"reviewer",
|
|
16786
|
+
"critic",
|
|
16787
|
+
"critic_oversight",
|
|
16788
|
+
"explorer",
|
|
16789
|
+
"coder",
|
|
16790
|
+
"test_engineer"
|
|
16791
|
+
]
|
|
16792
|
+
},
|
|
16793
|
+
knowledge_remove: {
|
|
16794
|
+
description: "delete an outdated swarm knowledge entry by ID (swarm tier only)",
|
|
16795
|
+
agents: ["architect"]
|
|
16796
|
+
},
|
|
16797
|
+
co_change_analyzer: {
|
|
16798
|
+
description: "detect hidden couplings by analyzing git history",
|
|
16799
|
+
agents: ["architect"]
|
|
16800
|
+
},
|
|
16801
|
+
search: {
|
|
16802
|
+
description: "Workspace-scoped ripgrep-style text search with structured JSON output. Supports literal and regex modes, glob filtering, and result limits. NOTE: This is text search, not structural AST search \u2014 use symbols and imports tools for structural queries.",
|
|
16803
|
+
agents: [
|
|
16804
|
+
"architect",
|
|
16805
|
+
"sme",
|
|
16806
|
+
"docs",
|
|
16807
|
+
"docs_design",
|
|
16808
|
+
"designer",
|
|
16809
|
+
"critic_hallucination_verifier",
|
|
16810
|
+
"skill_improver",
|
|
16811
|
+
"spec_writer",
|
|
16812
|
+
"reviewer",
|
|
16813
|
+
"critic_oversight",
|
|
16814
|
+
"explorer",
|
|
16815
|
+
"coder",
|
|
16816
|
+
"test_engineer"
|
|
16817
|
+
]
|
|
16818
|
+
},
|
|
16819
|
+
batch_symbols: {
|
|
16820
|
+
description: "Batched symbol extraction across multiple files. Returns per-file symbol summaries with isolated error handling.",
|
|
16821
|
+
agents: [
|
|
16822
|
+
"architect",
|
|
16823
|
+
"critic_hallucination_verifier",
|
|
16824
|
+
"reviewer",
|
|
16825
|
+
"critic_oversight",
|
|
16826
|
+
"explorer"
|
|
16827
|
+
]
|
|
16828
|
+
},
|
|
16829
|
+
suggest_patch: {
|
|
16830
|
+
description: "Reviewer-safe structured patch suggestion tool. Produces context-anchored patch artifacts without file modification. Returns structured diagnostics on context mismatch.",
|
|
16831
|
+
agents: ["architect", "reviewer"]
|
|
16832
|
+
},
|
|
16833
|
+
req_coverage: {
|
|
16834
|
+
description: "query requirement coverage status for tracked functional requirements",
|
|
16835
|
+
agents: [
|
|
16836
|
+
"critic_sounding_board",
|
|
16837
|
+
"critic_drift_verifier",
|
|
16838
|
+
"critic_hallucination_verifier",
|
|
16839
|
+
"spec_writer",
|
|
16840
|
+
"critic",
|
|
16841
|
+
"critic_oversight"
|
|
16842
|
+
]
|
|
16843
|
+
},
|
|
16844
|
+
get_approved_plan: {
|
|
16845
|
+
description: "retrieve the last critic-approved immutable plan snapshot for baseline drift comparison",
|
|
16846
|
+
agents: ["critic_drift_verifier", "critic", "critic_oversight"]
|
|
16847
|
+
},
|
|
16848
|
+
repo_map: {
|
|
16849
|
+
description: "query the repo code graph: importers, dependencies, blast radius, and localization context for structural awareness before refactoring",
|
|
16850
|
+
agents: [
|
|
16851
|
+
"architect",
|
|
16852
|
+
"critic_sounding_board",
|
|
16853
|
+
"critic_drift_verifier",
|
|
16854
|
+
"critic_hallucination_verifier",
|
|
16855
|
+
"critic_architecture_supervisor",
|
|
16856
|
+
"reviewer",
|
|
16857
|
+
"critic",
|
|
16858
|
+
"critic_oversight",
|
|
16859
|
+
"explorer",
|
|
16860
|
+
"coder"
|
|
16861
|
+
]
|
|
16862
|
+
},
|
|
16863
|
+
get_qa_gate_profile: {
|
|
16864
|
+
description: "retrieve the QA gate profile for the current plan: gates (reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, council_general_review, drift_check, final_council), lock state, and profile hash. Read-only.",
|
|
16865
|
+
agents: ["architect"]
|
|
16866
|
+
},
|
|
16867
|
+
set_qa_gates: {
|
|
16868
|
+
description: "configure the QA gate profile for the current plan. Architect-only. Ratchet-tighter only \u2014 rejected once the profile is locked after critic approval. Supports: reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, council_general_review, drift_check, final_council.",
|
|
16869
|
+
agents: ["architect"]
|
|
16870
|
+
},
|
|
16871
|
+
web_search: {
|
|
16872
|
+
description: "External web search (Tavily or Brave) for architect-driven council research. Returns titled results with snippets and URLs. Config-gated on council.general.enabled; requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents.",
|
|
16873
|
+
agents: ["architect", "skill_improver"]
|
|
16874
|
+
},
|
|
16875
|
+
convene_general_council: {
|
|
16876
|
+
description: "Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled.",
|
|
16877
|
+
agents: ["architect"]
|
|
16878
|
+
},
|
|
16879
|
+
write_final_council_evidence: {
|
|
16880
|
+
description: "write final council evidence for project completion",
|
|
16881
|
+
agents: ["architect"]
|
|
16882
|
+
},
|
|
16883
|
+
skill_generate: {
|
|
16884
|
+
description: "compile knowledge entries into a structured SKILL.md draft",
|
|
16885
|
+
agents: ["architect", "skill_improver"]
|
|
16886
|
+
},
|
|
16887
|
+
skill_list: {
|
|
16888
|
+
description: "list generated skill files and their status",
|
|
16889
|
+
agents: ["architect", "skill_improver"]
|
|
16890
|
+
},
|
|
16891
|
+
skill_apply: {
|
|
16892
|
+
description: "activate a draft skill proposal",
|
|
16893
|
+
agents: ["architect"]
|
|
16894
|
+
},
|
|
16895
|
+
skill_inspect: {
|
|
16896
|
+
description: "inspect the content and source entries of a skill file",
|
|
16897
|
+
agents: ["architect", "skill_improver"]
|
|
16898
|
+
},
|
|
16899
|
+
skill_regenerate: {
|
|
16900
|
+
description: "regenerate an active skill by re-clustering its source knowledge entries and updating the SKILL.md in place",
|
|
16901
|
+
agents: ["architect"]
|
|
16902
|
+
},
|
|
16903
|
+
skill_retire: {
|
|
16904
|
+
description: "retire a generated skill by adding a retired.marker file; retired skills are excluded from scoring and injection",
|
|
16905
|
+
agents: ["architect"]
|
|
16906
|
+
},
|
|
16907
|
+
skill_improve: {
|
|
16908
|
+
description: "run the skill_improver agent to review and refine skills",
|
|
16909
|
+
agents: ["architect", "skill_improver"]
|
|
16910
|
+
},
|
|
16911
|
+
spec_write: {
|
|
16912
|
+
description: "author or update .swarm/spec.md for the current project",
|
|
16913
|
+
agents: ["spec_writer"]
|
|
16914
|
+
},
|
|
16915
|
+
knowledge_ack: {
|
|
16916
|
+
description: "record an explicit KNOWLEDGE_APPLIED/IGNORED/VIOLATED acknowledgment",
|
|
16917
|
+
agents: ["architect"]
|
|
16918
|
+
},
|
|
16919
|
+
knowledge_receipt: {
|
|
16920
|
+
description: "file a receipt for retrieved knowledge (applied/ignored/contradicted + new lessons), recorded as immutable knowledge events",
|
|
16921
|
+
agents: ["architect", "coder"]
|
|
16922
|
+
},
|
|
16923
|
+
knowledge_archive: {
|
|
16924
|
+
description: "archive (default), quarantine, or purge a swarm knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",
|
|
16925
|
+
agents: ["architect"]
|
|
16926
|
+
},
|
|
16927
|
+
swarm_memory_recall: {
|
|
16928
|
+
description: "recall scoped Swarm memory for the current repository as untrusted background",
|
|
16929
|
+
agents: []
|
|
16930
|
+
},
|
|
16931
|
+
swarm_memory_propose: {
|
|
16932
|
+
description: "create a pending Swarm memory proposal; does not write durable memory directly",
|
|
16933
|
+
agents: []
|
|
16934
|
+
},
|
|
16935
|
+
swarm_command: {
|
|
16936
|
+
description: "run supported /swarm commands through the canonical command registry",
|
|
16937
|
+
agents: [
|
|
16938
|
+
"architect",
|
|
16939
|
+
"sme",
|
|
16940
|
+
"docs",
|
|
16941
|
+
"docs_design",
|
|
16942
|
+
"designer",
|
|
16943
|
+
"reviewer",
|
|
16944
|
+
"critic",
|
|
16945
|
+
"explorer",
|
|
16946
|
+
"coder",
|
|
16947
|
+
"test_engineer"
|
|
16948
|
+
]
|
|
16949
|
+
},
|
|
16950
|
+
summarize_work: {
|
|
16951
|
+
description: "emit a short structured summary of completed work (key decisions, assumptions, risks, constraints) at task completion; rolls up per phase for architecture-supervisor review. Advisory, never blocks.",
|
|
16952
|
+
agents: [
|
|
16953
|
+
"architect",
|
|
16954
|
+
"sme",
|
|
16955
|
+
"docs",
|
|
16956
|
+
"docs_design",
|
|
16957
|
+
"designer",
|
|
16958
|
+
"explorer",
|
|
16959
|
+
"coder",
|
|
16960
|
+
"test_engineer"
|
|
16961
|
+
]
|
|
16962
|
+
},
|
|
16963
|
+
write_architecture_supervisor_evidence: {
|
|
16964
|
+
description: "persist the architecture supervisor verdict for a phase (architect MUST dispatch critic_architecture_supervisor first and collect its JSON verdict; this tool persists only, it does not contact the supervisor)",
|
|
16965
|
+
agents: ["architect"]
|
|
16966
|
+
},
|
|
16967
|
+
lean_turbo_plan_lanes: {
|
|
16968
|
+
description: "partition phase tasks into parallel lanes based on file-scope conflicts for Lean Turbo execution",
|
|
16969
|
+
agents: ["architect"]
|
|
16970
|
+
},
|
|
16971
|
+
lean_turbo_acquire_locks: {
|
|
16972
|
+
description: "acquire file locks for all files in a lane (all-or-nothing) before lane execution",
|
|
16973
|
+
agents: ["architect"]
|
|
16974
|
+
},
|
|
16975
|
+
lean_turbo_runner_status: {
|
|
16976
|
+
description: "read Lean Turbo run state from .swarm/turbo-state.json",
|
|
16977
|
+
agents: ["architect"]
|
|
16978
|
+
},
|
|
16979
|
+
lean_turbo_review: {
|
|
16980
|
+
description: "dispatch a read-only reviewer agent to evaluate a completed Lean Turbo phase",
|
|
16981
|
+
agents: ["architect"]
|
|
16982
|
+
},
|
|
16983
|
+
lean_turbo_run_phase: {
|
|
16984
|
+
description: "Execute a phase using Lean Turbo parallel lane execution. Plans lanes, acquires file locks, and dispatches coder agents concurrently. Use when Lean Turbo is active and you want to execute all tasks in a phase in parallel lanes.",
|
|
16985
|
+
agents: ["architect"]
|
|
16986
|
+
},
|
|
16987
|
+
lean_turbo_status: {
|
|
16988
|
+
description: "returns Lean Turbo configuration and active status for the current session",
|
|
16989
|
+
agents: ["architect"]
|
|
16990
|
+
}
|
|
16991
|
+
};
|
|
16992
|
+
TOOL_NAMES = Object.keys(TOOL_METADATA);
|
|
16539
16993
|
TOOL_NAME_SET = new Set(TOOL_NAMES);
|
|
16994
|
+
TOOL_DESCRIPTIONS = Object.fromEntries(Object.entries(TOOL_METADATA).map(([name, meta3]) => [
|
|
16995
|
+
name,
|
|
16996
|
+
meta3.description
|
|
16997
|
+
]));
|
|
16998
|
+
AGENT_TOOL_MAP = (() => {
|
|
16999
|
+
const map2 = Object.fromEntries(ALL_AGENT_NAMES.map((agent) => [agent, []]));
|
|
17000
|
+
for (const [name, meta3] of Object.entries(TOOL_METADATA)) {
|
|
17001
|
+
for (const agent of meta3.agents) {
|
|
17002
|
+
map2[agent].push(name);
|
|
17003
|
+
}
|
|
17004
|
+
}
|
|
17005
|
+
return map2;
|
|
17006
|
+
})();
|
|
16540
17007
|
});
|
|
16541
17008
|
|
|
16542
17009
|
// src/config/constants.ts
|
|
@@ -16573,34 +17040,11 @@ function freezeSet(items) {
|
|
|
16573
17040
|
});
|
|
16574
17041
|
return proxy;
|
|
16575
17042
|
}
|
|
16576
|
-
var
|
|
17043
|
+
var OPENCODE_NATIVE_AGENTS, CLAUDE_CODE_NATIVE_COMMANDS, DEFAULT_AGENT_CONFIGS;
|
|
16577
17044
|
var init_constants = __esm(() => {
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
ALL_SUBAGENT_NAMES = [
|
|
16582
|
-
"sme",
|
|
16583
|
-
"docs",
|
|
16584
|
-
"docs_design",
|
|
16585
|
-
"designer",
|
|
16586
|
-
"critic_sounding_board",
|
|
16587
|
-
"critic_drift_verifier",
|
|
16588
|
-
"critic_hallucination_verifier",
|
|
16589
|
-
"critic_architecture_supervisor",
|
|
16590
|
-
"curator_init",
|
|
16591
|
-
"curator_phase",
|
|
16592
|
-
"council_generalist",
|
|
16593
|
-
"council_skeptic",
|
|
16594
|
-
"council_domain_expert",
|
|
16595
|
-
"skill_improver",
|
|
16596
|
-
"spec_writer",
|
|
16597
|
-
...QA_AGENTS,
|
|
16598
|
-
...PIPELINE_AGENTS
|
|
16599
|
-
];
|
|
16600
|
-
ALL_AGENT_NAMES = [
|
|
16601
|
-
ORCHESTRATOR_NAME,
|
|
16602
|
-
...ALL_SUBAGENT_NAMES
|
|
16603
|
-
];
|
|
17045
|
+
init_agent_names();
|
|
17046
|
+
init_tool_metadata();
|
|
17047
|
+
init_agent_names();
|
|
16604
17048
|
OPENCODE_NATIVE_AGENTS = new Set([
|
|
16605
17049
|
"build",
|
|
16606
17050
|
"plan",
|
|
@@ -16717,405 +17161,6 @@ var init_constants = __esm(() => {
|
|
|
16717
17161
|
"team-onboarding",
|
|
16718
17162
|
"bashes"
|
|
16719
17163
|
]);
|
|
16720
|
-
AGENT_TOOL_MAP = {
|
|
16721
|
-
architect: [
|
|
16722
|
-
"checkpoint",
|
|
16723
|
-
"check_gate_status",
|
|
16724
|
-
"completion_verify",
|
|
16725
|
-
"complexity_hotspots",
|
|
16726
|
-
"submit_council_verdicts",
|
|
16727
|
-
"submit_phase_council_verdicts",
|
|
16728
|
-
"declare_council_criteria",
|
|
16729
|
-
"detect_domains",
|
|
16730
|
-
"evidence_check",
|
|
16731
|
-
"extract_code_blocks",
|
|
16732
|
-
"gitingest",
|
|
16733
|
-
"imports",
|
|
16734
|
-
"knowledge_query",
|
|
16735
|
-
"lint",
|
|
16736
|
-
"diff",
|
|
16737
|
-
"diff_summary",
|
|
16738
|
-
"pkg_audit",
|
|
16739
|
-
"pre_check_batch",
|
|
16740
|
-
"quality_budget",
|
|
16741
|
-
"retrieve_summary",
|
|
16742
|
-
"save_plan",
|
|
16743
|
-
"search",
|
|
16744
|
-
"batch_symbols",
|
|
16745
|
-
"schema_drift",
|
|
16746
|
-
"secretscan",
|
|
16747
|
-
"symbols",
|
|
16748
|
-
"test_runner",
|
|
16749
|
-
"test_impact",
|
|
16750
|
-
"mutation_test",
|
|
16751
|
-
"generate_mutants",
|
|
16752
|
-
"write_mutation_evidence",
|
|
16753
|
-
"todo_extract",
|
|
16754
|
-
"update_task_status",
|
|
16755
|
-
"lint_spec",
|
|
16756
|
-
"write_retro",
|
|
16757
|
-
"write_drift_evidence",
|
|
16758
|
-
"write_hallucination_evidence",
|
|
16759
|
-
"declare_scope",
|
|
16760
|
-
"sast_scan",
|
|
16761
|
-
"sbom_generate",
|
|
16762
|
-
"build_check",
|
|
16763
|
-
"syntax_check",
|
|
16764
|
-
"placeholder_scan",
|
|
16765
|
-
"phase_complete",
|
|
16766
|
-
"doc_scan",
|
|
16767
|
-
"doc_extract",
|
|
16768
|
-
"curator_analyze",
|
|
16769
|
-
"knowledge_add",
|
|
16770
|
-
"knowledge_recall",
|
|
16771
|
-
"knowledge_remove",
|
|
16772
|
-
"knowledge_archive",
|
|
16773
|
-
"co_change_analyzer",
|
|
16774
|
-
"suggest_patch",
|
|
16775
|
-
"repo_map",
|
|
16776
|
-
"get_qa_gate_profile",
|
|
16777
|
-
"set_qa_gates",
|
|
16778
|
-
"convene_general_council",
|
|
16779
|
-
"web_search",
|
|
16780
|
-
"write_final_council_evidence",
|
|
16781
|
-
"skill_generate",
|
|
16782
|
-
"skill_list",
|
|
16783
|
-
"skill_apply",
|
|
16784
|
-
"skill_inspect",
|
|
16785
|
-
"skill_regenerate",
|
|
16786
|
-
"skill_retire",
|
|
16787
|
-
"skill_improve",
|
|
16788
|
-
"knowledge_ack",
|
|
16789
|
-
"knowledge_receipt",
|
|
16790
|
-
"summarize_work",
|
|
16791
|
-
"write_architecture_supervisor_evidence",
|
|
16792
|
-
"swarm_command",
|
|
16793
|
-
"lean_turbo_plan_lanes",
|
|
16794
|
-
"lean_turbo_acquire_locks",
|
|
16795
|
-
"lean_turbo_runner_status",
|
|
16796
|
-
"lean_turbo_review",
|
|
16797
|
-
"lean_turbo_run_phase",
|
|
16798
|
-
"lean_turbo_status"
|
|
16799
|
-
],
|
|
16800
|
-
explorer: [
|
|
16801
|
-
"complexity_hotspots",
|
|
16802
|
-
"detect_domains",
|
|
16803
|
-
"extract_code_blocks",
|
|
16804
|
-
"gitingest",
|
|
16805
|
-
"imports",
|
|
16806
|
-
"retrieve_summary",
|
|
16807
|
-
"schema_drift",
|
|
16808
|
-
"search",
|
|
16809
|
-
"batch_symbols",
|
|
16810
|
-
"symbols",
|
|
16811
|
-
"todo_extract",
|
|
16812
|
-
"doc_scan",
|
|
16813
|
-
"knowledge_recall",
|
|
16814
|
-
"repo_map",
|
|
16815
|
-
"summarize_work",
|
|
16816
|
-
"swarm_command"
|
|
16817
|
-
],
|
|
16818
|
-
coder: [
|
|
16819
|
-
"diff",
|
|
16820
|
-
"imports",
|
|
16821
|
-
"lint",
|
|
16822
|
-
"symbols",
|
|
16823
|
-
"extract_code_blocks",
|
|
16824
|
-
"retrieve_summary",
|
|
16825
|
-
"search",
|
|
16826
|
-
"build_check",
|
|
16827
|
-
"syntax_check",
|
|
16828
|
-
"knowledge_add",
|
|
16829
|
-
"knowledge_recall",
|
|
16830
|
-
"knowledge_receipt",
|
|
16831
|
-
"repo_map",
|
|
16832
|
-
"summarize_work",
|
|
16833
|
-
"swarm_command"
|
|
16834
|
-
],
|
|
16835
|
-
test_engineer: [
|
|
16836
|
-
"test_runner",
|
|
16837
|
-
"test_impact",
|
|
16838
|
-
"mutation_test",
|
|
16839
|
-
"diff",
|
|
16840
|
-
"symbols",
|
|
16841
|
-
"extract_code_blocks",
|
|
16842
|
-
"retrieve_summary",
|
|
16843
|
-
"imports",
|
|
16844
|
-
"complexity_hotspots",
|
|
16845
|
-
"pkg_audit",
|
|
16846
|
-
"build_check",
|
|
16847
|
-
"syntax_check",
|
|
16848
|
-
"search",
|
|
16849
|
-
"summarize_work",
|
|
16850
|
-
"knowledge_recall",
|
|
16851
|
-
"swarm_command"
|
|
16852
|
-
],
|
|
16853
|
-
sme: [
|
|
16854
|
-
"complexity_hotspots",
|
|
16855
|
-
"detect_domains",
|
|
16856
|
-
"extract_code_blocks",
|
|
16857
|
-
"imports",
|
|
16858
|
-
"retrieve_summary",
|
|
16859
|
-
"schema_drift",
|
|
16860
|
-
"search",
|
|
16861
|
-
"symbols",
|
|
16862
|
-
"knowledge_recall",
|
|
16863
|
-
"summarize_work",
|
|
16864
|
-
"swarm_command"
|
|
16865
|
-
],
|
|
16866
|
-
reviewer: [
|
|
16867
|
-
"diff",
|
|
16868
|
-
"diff_summary",
|
|
16869
|
-
"imports",
|
|
16870
|
-
"lint",
|
|
16871
|
-
"pkg_audit",
|
|
16872
|
-
"pre_check_batch",
|
|
16873
|
-
"secretscan",
|
|
16874
|
-
"symbols",
|
|
16875
|
-
"complexity_hotspots",
|
|
16876
|
-
"retrieve_summary",
|
|
16877
|
-
"extract_code_blocks",
|
|
16878
|
-
"test_runner",
|
|
16879
|
-
"test_impact",
|
|
16880
|
-
"sast_scan",
|
|
16881
|
-
"placeholder_scan",
|
|
16882
|
-
"knowledge_recall",
|
|
16883
|
-
"search",
|
|
16884
|
-
"batch_symbols",
|
|
16885
|
-
"suggest_patch",
|
|
16886
|
-
"repo_map",
|
|
16887
|
-
"swarm_command"
|
|
16888
|
-
],
|
|
16889
|
-
critic: [
|
|
16890
|
-
"complexity_hotspots",
|
|
16891
|
-
"detect_domains",
|
|
16892
|
-
"imports",
|
|
16893
|
-
"retrieve_summary",
|
|
16894
|
-
"symbols",
|
|
16895
|
-
"knowledge_recall",
|
|
16896
|
-
"req_coverage",
|
|
16897
|
-
"get_approved_plan",
|
|
16898
|
-
"repo_map",
|
|
16899
|
-
"swarm_command"
|
|
16900
|
-
],
|
|
16901
|
-
critic_sounding_board: [
|
|
16902
|
-
"complexity_hotspots",
|
|
16903
|
-
"detect_domains",
|
|
16904
|
-
"imports",
|
|
16905
|
-
"retrieve_summary",
|
|
16906
|
-
"symbols",
|
|
16907
|
-
"knowledge_recall",
|
|
16908
|
-
"req_coverage",
|
|
16909
|
-
"repo_map"
|
|
16910
|
-
],
|
|
16911
|
-
critic_drift_verifier: [
|
|
16912
|
-
"complexity_hotspots",
|
|
16913
|
-
"detect_domains",
|
|
16914
|
-
"imports",
|
|
16915
|
-
"retrieve_summary",
|
|
16916
|
-
"symbols",
|
|
16917
|
-
"knowledge_recall",
|
|
16918
|
-
"req_coverage",
|
|
16919
|
-
"get_approved_plan",
|
|
16920
|
-
"repo_map"
|
|
16921
|
-
],
|
|
16922
|
-
critic_hallucination_verifier: [
|
|
16923
|
-
"complexity_hotspots",
|
|
16924
|
-
"detect_domains",
|
|
16925
|
-
"imports",
|
|
16926
|
-
"retrieve_summary",
|
|
16927
|
-
"symbols",
|
|
16928
|
-
"batch_symbols",
|
|
16929
|
-
"search",
|
|
16930
|
-
"pkg_audit",
|
|
16931
|
-
"knowledge_recall",
|
|
16932
|
-
"req_coverage",
|
|
16933
|
-
"repo_map"
|
|
16934
|
-
],
|
|
16935
|
-
critic_architecture_supervisor: [
|
|
16936
|
-
"retrieve_summary",
|
|
16937
|
-
"knowledge_recall",
|
|
16938
|
-
"repo_map"
|
|
16939
|
-
],
|
|
16940
|
-
critic_oversight: [
|
|
16941
|
-
"diff",
|
|
16942
|
-
"diff_summary",
|
|
16943
|
-
"evidence_check",
|
|
16944
|
-
"check_gate_status",
|
|
16945
|
-
"completion_verify",
|
|
16946
|
-
"get_approved_plan",
|
|
16947
|
-
"req_coverage",
|
|
16948
|
-
"test_impact",
|
|
16949
|
-
"pkg_audit",
|
|
16950
|
-
"secretscan",
|
|
16951
|
-
"sast_scan",
|
|
16952
|
-
"repo_map",
|
|
16953
|
-
"retrieve_summary",
|
|
16954
|
-
"knowledge_recall",
|
|
16955
|
-
"symbols",
|
|
16956
|
-
"batch_symbols",
|
|
16957
|
-
"search",
|
|
16958
|
-
"imports",
|
|
16959
|
-
"complexity_hotspots",
|
|
16960
|
-
"detect_domains"
|
|
16961
|
-
],
|
|
16962
|
-
docs: [
|
|
16963
|
-
"detect_domains",
|
|
16964
|
-
"extract_code_blocks",
|
|
16965
|
-
"gitingest",
|
|
16966
|
-
"imports",
|
|
16967
|
-
"retrieve_summary",
|
|
16968
|
-
"schema_drift",
|
|
16969
|
-
"search",
|
|
16970
|
-
"symbols",
|
|
16971
|
-
"todo_extract",
|
|
16972
|
-
"knowledge_recall",
|
|
16973
|
-
"summarize_work",
|
|
16974
|
-
"swarm_command"
|
|
16975
|
-
],
|
|
16976
|
-
docs_design: [
|
|
16977
|
-
"detect_domains",
|
|
16978
|
-
"extract_code_blocks",
|
|
16979
|
-
"imports",
|
|
16980
|
-
"retrieve_summary",
|
|
16981
|
-
"search",
|
|
16982
|
-
"symbols",
|
|
16983
|
-
"doc_scan",
|
|
16984
|
-
"doc_extract",
|
|
16985
|
-
"knowledge_recall",
|
|
16986
|
-
"summarize_work",
|
|
16987
|
-
"swarm_command"
|
|
16988
|
-
],
|
|
16989
|
-
designer: [
|
|
16990
|
-
"extract_code_blocks",
|
|
16991
|
-
"retrieve_summary",
|
|
16992
|
-
"search",
|
|
16993
|
-
"symbols",
|
|
16994
|
-
"knowledge_recall",
|
|
16995
|
-
"summarize_work",
|
|
16996
|
-
"swarm_command"
|
|
16997
|
-
],
|
|
16998
|
-
curator_init: ["knowledge_recall"],
|
|
16999
|
-
curator_phase: ["knowledge_recall"],
|
|
17000
|
-
council_generalist: [],
|
|
17001
|
-
council_skeptic: [],
|
|
17002
|
-
council_domain_expert: [],
|
|
17003
|
-
skill_improver: [
|
|
17004
|
-
"knowledge_recall",
|
|
17005
|
-
"knowledge_query",
|
|
17006
|
-
"skill_list",
|
|
17007
|
-
"skill_inspect",
|
|
17008
|
-
"skill_generate",
|
|
17009
|
-
"skill_improve",
|
|
17010
|
-
"search",
|
|
17011
|
-
"doc_scan",
|
|
17012
|
-
"doc_extract",
|
|
17013
|
-
"web_search"
|
|
17014
|
-
],
|
|
17015
|
-
spec_writer: [
|
|
17016
|
-
"search",
|
|
17017
|
-
"knowledge_recall",
|
|
17018
|
-
"knowledge_query",
|
|
17019
|
-
"doc_scan",
|
|
17020
|
-
"doc_extract",
|
|
17021
|
-
"req_coverage",
|
|
17022
|
-
"lint_spec",
|
|
17023
|
-
"retrieve_summary",
|
|
17024
|
-
"symbols",
|
|
17025
|
-
"extract_code_blocks",
|
|
17026
|
-
"spec_write"
|
|
17027
|
-
]
|
|
17028
|
-
};
|
|
17029
|
-
TOOL_DESCRIPTIONS = {
|
|
17030
|
-
symbols: "code symbol search",
|
|
17031
|
-
checkpoint: "state snapshots",
|
|
17032
|
-
diff: "structured git diff with contract change detection",
|
|
17033
|
-
diff_summary: "filter classified AST changes by category, risk level, or file for reviewer drill-down",
|
|
17034
|
-
imports: "dependency audit",
|
|
17035
|
-
lint: "code quality",
|
|
17036
|
-
placeholder_scan: "todo and FIXME comment detection",
|
|
17037
|
-
secretscan: "secret detection",
|
|
17038
|
-
sast_scan: "static analysis security scan",
|
|
17039
|
-
syntax_check: "syntax validation",
|
|
17040
|
-
test_runner: "auto-detect and run tests",
|
|
17041
|
-
test_impact: "identify test files impacted by changed source files via import analysis",
|
|
17042
|
-
mutation_test: "executes pre-generated mutation patches against tests, evaluates kill rate against quality gate thresholds",
|
|
17043
|
-
generate_mutants: "generate LLM-based mutation testing patches for source files; returns MutationPatch[] for direct consumption by the mutation_test tool",
|
|
17044
|
-
write_mutation_evidence: "write mutation gate evidence for a completed phase; normalizes PASS/WARN/FAIL/SKIP verdicts and writes .swarm/evidence/{phase}/mutation-gate.json",
|
|
17045
|
-
pkg_audit: "dependency vulnerability scan \u2014 npm/pip/cargo",
|
|
17046
|
-
complexity_hotspots: "git churn \xD7 complexity risk map",
|
|
17047
|
-
schema_drift: "OpenAPI spec vs route drift",
|
|
17048
|
-
todo_extract: "structured TODO/FIXME extraction",
|
|
17049
|
-
evidence_check: "verify task evidence completeness",
|
|
17050
|
-
sbom_generate: "SBOM generation for dependency inventory",
|
|
17051
|
-
build_check: "build verification",
|
|
17052
|
-
quality_budget: "code quality budget check",
|
|
17053
|
-
pre_check_batch: "parallel verification: lint:check + secretscan + sast_scan + quality_budget",
|
|
17054
|
-
update_task_status: "mark tasks complete, track phase progress",
|
|
17055
|
-
write_retro: "document phase retrospectives via phase_complete workflow, capture lessons learned",
|
|
17056
|
-
write_drift_evidence: "write drift verification evidence for a completed phase",
|
|
17057
|
-
write_hallucination_evidence: "write hallucination verification evidence for a completed phase",
|
|
17058
|
-
write_final_council_evidence: "write final council evidence for project completion",
|
|
17059
|
-
declare_scope: "declare file scope for next coder delegation",
|
|
17060
|
-
phase_complete: "mark a phase as complete and track dispatched agents",
|
|
17061
|
-
save_plan: "save a structured implementation plan",
|
|
17062
|
-
doc_scan: "scan project documentation files and build an index manifest",
|
|
17063
|
-
doc_extract: "extract actionable constraints from project documentation",
|
|
17064
|
-
curator_analyze: "run curator phase analysis and optionally apply knowledge recommendations",
|
|
17065
|
-
knowledge_add: "store a new lesson in the knowledge base",
|
|
17066
|
-
knowledge_recall: "search the knowledge base for relevant past decisions",
|
|
17067
|
-
knowledge_remove: "delete an outdated swarm knowledge entry by ID (swarm tier only)",
|
|
17068
|
-
knowledge_archive: "archive (default), quarantine, or purge a swarm knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",
|
|
17069
|
-
knowledge_query: "query swarm or hive knowledge with optional filters",
|
|
17070
|
-
co_change_analyzer: "detect hidden couplings by analyzing git history",
|
|
17071
|
-
check_gate_status: "check the gate status of a specific task",
|
|
17072
|
-
completion_verify: "verify completed tasks have required evidence",
|
|
17073
|
-
submit_council_verdicts: "submit pre-collected council member verdicts for synthesis (architect MUST dispatch critic/reviewer/sme/test_engineer/explorer as Agent tasks first; this tool synthesizes only, it does not contact members)",
|
|
17074
|
-
submit_phase_council_verdicts: "submit pre-collected phase-level council member verdicts for holistic phase synthesis (architect MUST dispatch all 5 council members with phase-scoped context first; this tool synthesizes only, it does not contact members)",
|
|
17075
|
-
declare_council_criteria: "pre-declare acceptance criteria for a task before the coder starts work; criteria are read back during council evaluation",
|
|
17076
|
-
detect_domains: "detect which SME domains are relevant for a given text",
|
|
17077
|
-
summarize_work: "emit a short structured summary of completed work (key decisions, assumptions, risks, constraints) at task completion; rolls up per phase for architecture-supervisor review. Advisory, never blocks.",
|
|
17078
|
-
write_architecture_supervisor_evidence: "persist the architecture supervisor verdict for a phase (architect MUST dispatch critic_architecture_supervisor first and collect its JSON verdict; this tool persists only, it does not contact the supervisor)",
|
|
17079
|
-
extract_code_blocks: "extract code blocks from text content and save them to files",
|
|
17080
|
-
gitingest: "fetch a GitHub repository full content via gitingest.com",
|
|
17081
|
-
retrieve_summary: "retrieve the full content of a stored tool output summary",
|
|
17082
|
-
search: "Workspace-scoped ripgrep-style text search with structured JSON output. Supports literal and regex modes, glob filtering, and result limits. NOTE: This is text search, not structural AST search \u2014 use symbols and imports tools for structural queries.",
|
|
17083
|
-
web_search: "External web search (Tavily or Brave) for architect-driven council research. Returns titled results with snippets and URLs. Config-gated on council.general.enabled; requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents.",
|
|
17084
|
-
convene_general_council: "Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled.",
|
|
17085
|
-
batch_symbols: "Batched symbol extraction across multiple files. Returns per-file symbol summaries with isolated error handling.",
|
|
17086
|
-
suggest_patch: "Reviewer-safe structured patch suggestion tool. Produces context-anchored patch artifacts without file modification. Returns structured diagnostics on context mismatch.",
|
|
17087
|
-
lint_spec: "validate .swarm/spec.md format and required fields",
|
|
17088
|
-
get_approved_plan: "retrieve the last critic-approved immutable plan snapshot for baseline drift comparison",
|
|
17089
|
-
repo_map: "query the repo code graph: importers, dependencies, blast radius, and localization context for structural awareness before refactoring",
|
|
17090
|
-
get_qa_gate_profile: "retrieve the QA gate profile for the current plan: gates (reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, council_general_review, drift_check, final_council), lock state, and profile hash. Read-only.",
|
|
17091
|
-
set_qa_gates: "configure the QA gate profile for the current plan. Architect-only. Ratchet-tighter only \u2014 rejected once the profile is locked after critic approval. Supports: reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, council_general_review, drift_check, final_council.",
|
|
17092
|
-
req_coverage: "query requirement coverage status for tracked functional requirements",
|
|
17093
|
-
skill_generate: "compile knowledge entries into a structured SKILL.md draft",
|
|
17094
|
-
skill_list: "list generated skill files and their status",
|
|
17095
|
-
skill_apply: "activate a draft skill proposal",
|
|
17096
|
-
skill_inspect: "inspect the content and source entries of a skill file",
|
|
17097
|
-
skill_improve: "run the skill_improver agent to review and refine skills",
|
|
17098
|
-
skill_regenerate: "regenerate an active skill by re-clustering its source knowledge entries and updating the SKILL.md in place",
|
|
17099
|
-
skill_retire: "retire a generated skill by adding a retired.marker file; retired skills are excluded from scoring and injection",
|
|
17100
|
-
spec_write: "author or update .swarm/spec.md for the current project",
|
|
17101
|
-
knowledge_ack: "record an explicit KNOWLEDGE_APPLIED/IGNORED/VIOLATED acknowledgment",
|
|
17102
|
-
knowledge_receipt: "file a receipt for retrieved knowledge (applied/ignored/contradicted + new lessons), recorded as immutable knowledge events",
|
|
17103
|
-
swarm_memory_recall: "recall scoped Swarm memory for the current repository as untrusted background",
|
|
17104
|
-
swarm_memory_propose: "create a pending Swarm memory proposal; does not write durable memory directly",
|
|
17105
|
-
swarm_command: "run supported /swarm commands through the canonical command registry",
|
|
17106
|
-
lean_turbo_plan_lanes: "partition phase tasks into parallel lanes based on file-scope conflicts for Lean Turbo execution",
|
|
17107
|
-
lean_turbo_acquire_locks: "acquire file locks for all files in a lane (all-or-nothing) before lane execution",
|
|
17108
|
-
lean_turbo_runner_status: "read Lean Turbo run state from .swarm/turbo-state.json",
|
|
17109
|
-
lean_turbo_review: "dispatch a read-only reviewer agent to evaluate a completed Lean Turbo phase",
|
|
17110
|
-
lean_turbo_run_phase: "Execute a phase using Lean Turbo parallel lane execution. " + "Plans lanes, acquires file locks, and dispatches coder agents concurrently. " + "Use when Lean Turbo is active and you want to execute all tasks in a phase in parallel lanes.",
|
|
17111
|
-
lean_turbo_status: "returns Lean Turbo configuration and active status for the current session"
|
|
17112
|
-
};
|
|
17113
|
-
for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
|
|
17114
|
-
const invalidTools = tools.filter((tool) => !TOOL_NAME_SET.has(tool));
|
|
17115
|
-
if (invalidTools.length > 0) {
|
|
17116
|
-
throw new Error(`Agent '${agentName}' has invalid tool names: [${invalidTools.join(", ")}]. ` + `All tools must be registered in TOOL_NAME_SET.`);
|
|
17117
|
-
}
|
|
17118
|
-
}
|
|
17119
17164
|
DEFAULT_AGENT_CONFIGS = {
|
|
17120
17165
|
coder: {
|
|
17121
17166
|
model: "opencode/minimax-m2.5-free",
|
|
@@ -43831,24 +43876,14 @@ var init_discovery = __esm(() => {
|
|
|
43831
43876
|
});
|
|
43832
43877
|
});
|
|
43833
43878
|
|
|
43879
|
+
// src/tools/tool-names.ts
|
|
43880
|
+
var init_tool_names = __esm(() => {
|
|
43881
|
+
init_tool_metadata();
|
|
43882
|
+
});
|
|
43883
|
+
|
|
43834
43884
|
// src/services/tool-doctor.ts
|
|
43835
|
-
|
|
43836
|
-
|
|
43837
|
-
function extractRegisteredToolKeys(indexPath) {
|
|
43838
|
-
const registeredKeys = new Set;
|
|
43839
|
-
try {
|
|
43840
|
-
const content = fs11.readFileSync(indexPath, "utf-8");
|
|
43841
|
-
const toolBlockMatch = content.match(/tool:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
|
|
43842
|
-
if (!toolBlockMatch) {
|
|
43843
|
-
return registeredKeys;
|
|
43844
|
-
}
|
|
43845
|
-
const toolBlock = toolBlockMatch[1];
|
|
43846
|
-
const keyPattern = /^\s*(\w+)(?:\s*:|,)/gm;
|
|
43847
|
-
for (const match of toolBlock.matchAll(keyPattern)) {
|
|
43848
|
-
registeredKeys.add(match[1]);
|
|
43849
|
-
}
|
|
43850
|
-
} catch (_error) {}
|
|
43851
|
-
return registeredKeys;
|
|
43885
|
+
function getRegisteredToolKeys() {
|
|
43886
|
+
return new Set(TOOL_NAME_SET);
|
|
43852
43887
|
}
|
|
43853
43888
|
function checkAgentToolMapAlignment(registeredKeys) {
|
|
43854
43889
|
const findings = [];
|
|
@@ -43858,7 +43893,7 @@ function checkAgentToolMapAlignment(registeredKeys) {
|
|
|
43858
43893
|
findings.push({
|
|
43859
43894
|
id: `agent-tool-map-mismatch-${agentName}-${toolName}`,
|
|
43860
43895
|
title: "AGENT_TOOL_MAP alignment gap",
|
|
43861
|
-
description: `Tool "${toolName}" is assigned to agent "${agentName}" in AGENT_TOOL_MAP but is not registered
|
|
43896
|
+
description: `Tool "${toolName}" is assigned to agent "${agentName}" in AGENT_TOOL_MAP but is not a registered tool name. The agent will not be able to use this tool.`,
|
|
43862
43897
|
severity: "error",
|
|
43863
43898
|
path: `AGENT_TOOL_MAP.${agentName}`,
|
|
43864
43899
|
currentValue: toolName,
|
|
@@ -43886,36 +43921,15 @@ function checkBinaryReadiness() {
|
|
|
43886
43921
|
}
|
|
43887
43922
|
return findings;
|
|
43888
43923
|
}
|
|
43889
|
-
function runToolDoctor(_directory,
|
|
43924
|
+
function runToolDoctor(_directory, _pluginRoot) {
|
|
43890
43925
|
const findings = [];
|
|
43891
|
-
const
|
|
43892
|
-
const indexPath = path27.join(resolvedPluginRoot, "src", "index.ts");
|
|
43893
|
-
if (!fs11.existsSync(indexPath)) {
|
|
43894
|
-
return {
|
|
43895
|
-
findings: [
|
|
43896
|
-
{
|
|
43897
|
-
id: "plugin-src-unavailable",
|
|
43898
|
-
title: "Plugin source not available",
|
|
43899
|
-
description: `Tool registration check requires plugin source files. Expected: ${indexPath}. This check is available in development environments; in production npm installs, only compiled dist/ is present.`,
|
|
43900
|
-
severity: "warn",
|
|
43901
|
-
path: indexPath,
|
|
43902
|
-
currentValue: undefined,
|
|
43903
|
-
autoFixable: false
|
|
43904
|
-
}
|
|
43905
|
-
],
|
|
43906
|
-
summary: { info: 0, warn: 1, error: 0 },
|
|
43907
|
-
hasAutoFixableIssues: false,
|
|
43908
|
-
timestamp: Date.now(),
|
|
43909
|
-
configSource: indexPath
|
|
43910
|
-
};
|
|
43911
|
-
}
|
|
43912
|
-
const registeredKeys = extractRegisteredToolKeys(indexPath);
|
|
43926
|
+
const registeredKeys = getRegisteredToolKeys();
|
|
43913
43927
|
for (const toolName of TOOL_NAMES) {
|
|
43914
43928
|
if (!registeredKeys.has(toolName)) {
|
|
43915
43929
|
findings.push({
|
|
43916
43930
|
id: `missing-tool-registration-${toolName}`,
|
|
43917
43931
|
title: "Missing tool registration",
|
|
43918
|
-
description: `Tool "${toolName}" is defined in TOOL_NAMES but is not
|
|
43932
|
+
description: `Tool "${toolName}" is defined in TOOL_NAMES but is not present in the plugin tool object derived from TOOL_MANIFEST. This means the tool will not be available at runtime.`,
|
|
43919
43933
|
severity: "error",
|
|
43920
43934
|
path: `tool.${toolName}`,
|
|
43921
43935
|
currentValue: undefined,
|
|
@@ -43936,7 +43950,7 @@ function runToolDoctor(_directory, pluginRoot) {
|
|
|
43936
43950
|
summary,
|
|
43937
43951
|
hasAutoFixableIssues,
|
|
43938
43952
|
timestamp: Date.now(),
|
|
43939
|
-
configSource:
|
|
43953
|
+
configSource: "src/tools/manifest.ts"
|
|
43940
43954
|
};
|
|
43941
43955
|
}
|
|
43942
43956
|
var BINARY_CHECKLIST;
|
|
@@ -44646,15 +44660,15 @@ var init_export = __esm(() => {
|
|
|
44646
44660
|
});
|
|
44647
44661
|
|
|
44648
44662
|
// src/full-auto/state.ts
|
|
44649
|
-
import * as
|
|
44650
|
-
import * as
|
|
44663
|
+
import * as fs11 from "fs";
|
|
44664
|
+
import * as path27 from "path";
|
|
44651
44665
|
function nowISO() {
|
|
44652
44666
|
return new Date().toISOString();
|
|
44653
44667
|
}
|
|
44654
44668
|
function ensureSwarmDir(directory) {
|
|
44655
|
-
const swarmDir =
|
|
44656
|
-
if (!
|
|
44657
|
-
|
|
44669
|
+
const swarmDir = path27.resolve(directory, ".swarm");
|
|
44670
|
+
if (!fs11.existsSync(swarmDir)) {
|
|
44671
|
+
fs11.mkdirSync(swarmDir, { recursive: true });
|
|
44658
44672
|
}
|
|
44659
44673
|
return swarmDir;
|
|
44660
44674
|
}
|
|
@@ -44686,7 +44700,7 @@ function withStateLock(directory, fn) {
|
|
|
44686
44700
|
let release;
|
|
44687
44701
|
try {
|
|
44688
44702
|
const lockTarget = validateSwarmPath(directory, STATE_FILE);
|
|
44689
|
-
if (!
|
|
44703
|
+
if (!fs11.existsSync(lockTarget)) {
|
|
44690
44704
|
ensureSwarmDir(directory);
|
|
44691
44705
|
const seed = {
|
|
44692
44706
|
version: 2,
|
|
@@ -44694,7 +44708,7 @@ function withStateLock(directory, fn) {
|
|
|
44694
44708
|
oversightSequence: 0,
|
|
44695
44709
|
sessions: {}
|
|
44696
44710
|
};
|
|
44697
|
-
|
|
44711
|
+
fs11.writeFileSync(lockTarget, `${JSON.stringify(seed, null, 2)}
|
|
44698
44712
|
`, "utf-8");
|
|
44699
44713
|
}
|
|
44700
44714
|
release = lockfile7.lockSync(lockTarget, {
|
|
@@ -44736,11 +44750,11 @@ function clearStateUnreadable() {
|
|
|
44736
44750
|
function readPersisted(directory) {
|
|
44737
44751
|
try {
|
|
44738
44752
|
const filePath = validateSwarmPath(directory, STATE_FILE);
|
|
44739
|
-
if (!
|
|
44753
|
+
if (!fs11.existsSync(filePath)) {
|
|
44740
44754
|
clearStateUnreadable();
|
|
44741
44755
|
return emptyPersisted();
|
|
44742
44756
|
}
|
|
44743
|
-
const raw =
|
|
44757
|
+
const raw = fs11.readFileSync(filePath, "utf-8");
|
|
44744
44758
|
const parsed = JSON.parse(raw);
|
|
44745
44759
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 2 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
44746
44760
|
markStateUnreadable(`malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -44758,8 +44772,8 @@ function readPersisted(directory) {
|
|
|
44758
44772
|
error(`[full-auto/state] Failed to read ${STATE_FILE}: ${reason} \u2014 attempting .bak recovery`);
|
|
44759
44773
|
try {
|
|
44760
44774
|
const bakPath = validateSwarmPath(directory, `${STATE_FILE}.bak`);
|
|
44761
|
-
if (
|
|
44762
|
-
const raw =
|
|
44775
|
+
if (fs11.existsSync(bakPath)) {
|
|
44776
|
+
const raw = fs11.readFileSync(bakPath, "utf-8");
|
|
44763
44777
|
const parsed = JSON.parse(raw);
|
|
44764
44778
|
if (parsed?.version === 2 && parsed.sessions && !Array.isArray(parsed.sessions)) {
|
|
44765
44779
|
warn(`[full-auto/state] Recovered from ${STATE_FILE}.bak`);
|
|
@@ -44798,22 +44812,22 @@ function writePersisted(directory, persisted) {
|
|
|
44798
44812
|
throw new Error(`Full-Auto state persistence prepare failed: ${msg}`);
|
|
44799
44813
|
}
|
|
44800
44814
|
try {
|
|
44801
|
-
if (
|
|
44802
|
-
|
|
44815
|
+
if (fs11.existsSync(filePath)) {
|
|
44816
|
+
fs11.copyFileSync(filePath, bakPath);
|
|
44803
44817
|
}
|
|
44804
44818
|
} catch {}
|
|
44805
44819
|
try {
|
|
44806
|
-
|
|
44820
|
+
fs11.writeFileSync(tmpPath, payload, "utf-8");
|
|
44807
44821
|
try {
|
|
44808
|
-
const fd =
|
|
44822
|
+
const fd = fs11.openSync(tmpPath, "r+");
|
|
44809
44823
|
try {
|
|
44810
|
-
|
|
44824
|
+
fs11.fsyncSync(fd);
|
|
44811
44825
|
} finally {
|
|
44812
|
-
|
|
44826
|
+
fs11.closeSync(fd);
|
|
44813
44827
|
}
|
|
44814
44828
|
} catch {}
|
|
44815
|
-
|
|
44816
|
-
const readback =
|
|
44829
|
+
fs11.renameSync(tmpPath, filePath);
|
|
44830
|
+
const readback = fs11.readFileSync(filePath, "utf-8");
|
|
44817
44831
|
const parsed = JSON.parse(readback);
|
|
44818
44832
|
if (parsed?.version !== 2) {
|
|
44819
44833
|
throw new Error("Round-trip readback returned wrong version");
|
|
@@ -45353,7 +45367,7 @@ var init_handoff_service = __esm(() => {
|
|
|
45353
45367
|
|
|
45354
45368
|
// src/session/snapshot-writer.ts
|
|
45355
45369
|
import { closeSync as closeSync4, fsyncSync as fsyncSync2, mkdirSync as mkdirSync12, openSync as openSync4, renameSync as renameSync8 } from "fs";
|
|
45356
|
-
import * as
|
|
45370
|
+
import * as path28 from "path";
|
|
45357
45371
|
function serializeAgentSession(s) {
|
|
45358
45372
|
const gateLog = {};
|
|
45359
45373
|
const rawGateLog = s.gateLog ?? new Map;
|
|
@@ -45453,7 +45467,7 @@ async function writeSnapshot(directory, state) {
|
|
|
45453
45467
|
}
|
|
45454
45468
|
const content = JSON.stringify(snapshot, null, 2);
|
|
45455
45469
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
45456
|
-
const dir =
|
|
45470
|
+
const dir = path28.dirname(resolvedPath);
|
|
45457
45471
|
mkdirSync12(dir, { recursive: true });
|
|
45458
45472
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
45459
45473
|
await bunWrite(tempPath, content);
|
|
@@ -45913,9 +45927,9 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
|
|
|
45913
45927
|
|
|
45914
45928
|
// src/hooks/knowledge-migrator.ts
|
|
45915
45929
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
45916
|
-
import { existsSync as
|
|
45930
|
+
import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
|
|
45917
45931
|
import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile9 } from "fs/promises";
|
|
45918
|
-
import * as
|
|
45932
|
+
import * as path29 from "path";
|
|
45919
45933
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
45920
45934
|
return {
|
|
45921
45935
|
migrated: false,
|
|
@@ -45926,10 +45940,10 @@ async function migrateKnowledgeToExternal(_directory, _config) {
|
|
|
45926
45940
|
};
|
|
45927
45941
|
}
|
|
45928
45942
|
async function migrateContextToKnowledge(directory, config3) {
|
|
45929
|
-
const sentinelPath =
|
|
45930
|
-
const contextPath =
|
|
45943
|
+
const sentinelPath = path29.join(directory, ".swarm", ".knowledge-migrated");
|
|
45944
|
+
const contextPath = path29.join(directory, ".swarm", "context.md");
|
|
45931
45945
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
45932
|
-
if (
|
|
45946
|
+
if (existsSync19(sentinelPath)) {
|
|
45933
45947
|
return {
|
|
45934
45948
|
migrated: false,
|
|
45935
45949
|
entriesMigrated: 0,
|
|
@@ -45938,7 +45952,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
45938
45952
|
skippedReason: "sentinel-exists"
|
|
45939
45953
|
};
|
|
45940
45954
|
}
|
|
45941
|
-
if (!
|
|
45955
|
+
if (!existsSync19(contextPath)) {
|
|
45942
45956
|
return {
|
|
45943
45957
|
migrated: false,
|
|
45944
45958
|
entriesMigrated: 0,
|
|
@@ -46123,16 +46137,16 @@ function truncateLesson(text) {
|
|
|
46123
46137
|
return `${text.slice(0, 277)}...`;
|
|
46124
46138
|
}
|
|
46125
46139
|
function inferProjectName(directory) {
|
|
46126
|
-
const packageJsonPath =
|
|
46127
|
-
if (
|
|
46140
|
+
const packageJsonPath = path29.join(directory, "package.json");
|
|
46141
|
+
if (existsSync19(packageJsonPath)) {
|
|
46128
46142
|
try {
|
|
46129
|
-
const pkg = JSON.parse(
|
|
46143
|
+
const pkg = JSON.parse(readFileSync13(packageJsonPath, "utf-8"));
|
|
46130
46144
|
if (pkg.name && typeof pkg.name === "string") {
|
|
46131
46145
|
return pkg.name;
|
|
46132
46146
|
}
|
|
46133
46147
|
} catch {}
|
|
46134
46148
|
}
|
|
46135
|
-
return
|
|
46149
|
+
return path29.basename(directory);
|
|
46136
46150
|
}
|
|
46137
46151
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
46138
46152
|
const sentinel = {
|
|
@@ -46144,7 +46158,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
46144
46158
|
schema_version: 1,
|
|
46145
46159
|
migration_tool: "knowledge-migrator.ts"
|
|
46146
46160
|
};
|
|
46147
|
-
await mkdir8(
|
|
46161
|
+
await mkdir8(path29.dirname(sentinelPath), { recursive: true });
|
|
46148
46162
|
await writeFile9(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
46149
46163
|
}
|
|
46150
46164
|
var _internals19;
|
|
@@ -46166,7 +46180,7 @@ var init_knowledge_migrator = __esm(() => {
|
|
|
46166
46180
|
});
|
|
46167
46181
|
|
|
46168
46182
|
// src/commands/knowledge.ts
|
|
46169
|
-
import { join as
|
|
46183
|
+
import { join as join27 } from "path";
|
|
46170
46184
|
function resolveEntryByPrefix(entries, inputId) {
|
|
46171
46185
|
const exact = entries.find((e) => e.id === inputId);
|
|
46172
46186
|
if (exact)
|
|
@@ -46217,7 +46231,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
46217
46231
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
46218
46232
|
}
|
|
46219
46233
|
try {
|
|
46220
|
-
const quarantinePath =
|
|
46234
|
+
const quarantinePath = join27(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
46221
46235
|
const entries = await readKnowledge(quarantinePath);
|
|
46222
46236
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
46223
46237
|
if ("error" in resolved) {
|
|
@@ -47192,7 +47206,7 @@ var init_scoring = __esm(() => {
|
|
|
47192
47206
|
|
|
47193
47207
|
// src/memory/local-jsonl-provider.ts
|
|
47194
47208
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
47195
|
-
import { existsSync as
|
|
47209
|
+
import { existsSync as existsSync20 } from "fs";
|
|
47196
47210
|
import {
|
|
47197
47211
|
appendFile as appendFile5,
|
|
47198
47212
|
mkdir as mkdir9,
|
|
@@ -47200,7 +47214,7 @@ import {
|
|
|
47200
47214
|
rename as rename6,
|
|
47201
47215
|
writeFile as writeFile10
|
|
47202
47216
|
} from "fs/promises";
|
|
47203
|
-
import * as
|
|
47217
|
+
import * as path30 from "path";
|
|
47204
47218
|
|
|
47205
47219
|
class LocalJsonlMemoryProvider {
|
|
47206
47220
|
name = "local-jsonl";
|
|
@@ -47216,7 +47230,7 @@ class LocalJsonlMemoryProvider {
|
|
|
47216
47230
|
pathFor(file3) {
|
|
47217
47231
|
const storageDir = this.config.storageDir.replace(/^\.swarm[/\\]?/, "");
|
|
47218
47232
|
const filename = file3 === "memories" ? "memories.jsonl" : file3 === "proposals" ? "proposals.jsonl" : "audit.jsonl";
|
|
47219
|
-
return validateSwarmPath(this.rootDirectory,
|
|
47233
|
+
return validateSwarmPath(this.rootDirectory, path30.join(storageDir, filename));
|
|
47220
47234
|
}
|
|
47221
47235
|
async initialize() {
|
|
47222
47236
|
if (this.initialized)
|
|
@@ -47543,7 +47557,7 @@ function validateLoadedProposals(values, config3) {
|
|
|
47543
47557
|
return { records, invalidCount };
|
|
47544
47558
|
}
|
|
47545
47559
|
async function readJsonl(filePath) {
|
|
47546
|
-
if (!
|
|
47560
|
+
if (!existsSync20(filePath))
|
|
47547
47561
|
return [];
|
|
47548
47562
|
const content = await readFile10(filePath, "utf-8");
|
|
47549
47563
|
const records = [];
|
|
@@ -47599,12 +47613,12 @@ function parseRecallUsageEvent(event) {
|
|
|
47599
47613
|
}
|
|
47600
47614
|
}
|
|
47601
47615
|
async function appendJsonl(filePath, value) {
|
|
47602
|
-
await mkdir9(
|
|
47616
|
+
await mkdir9(path30.dirname(filePath), { recursive: true });
|
|
47603
47617
|
await appendFile5(filePath, `${JSON.stringify(value)}
|
|
47604
47618
|
`, "utf-8");
|
|
47605
47619
|
}
|
|
47606
47620
|
async function writeJsonlAtomic(filePath, values) {
|
|
47607
|
-
await mkdir9(
|
|
47621
|
+
await mkdir9(path30.dirname(filePath), { recursive: true });
|
|
47608
47622
|
const tmp = `${filePath}.tmp.${randomUUID4()}`;
|
|
47609
47623
|
const content = values.map((value) => JSON.stringify(value)).join(`
|
|
47610
47624
|
`) + (values.length > 0 ? `
|
|
@@ -47629,9 +47643,9 @@ var init_prompt_block = __esm(() => {
|
|
|
47629
47643
|
});
|
|
47630
47644
|
|
|
47631
47645
|
// src/memory/jsonl-migration.ts
|
|
47632
|
-
import { existsSync as
|
|
47646
|
+
import { existsSync as existsSync21 } from "fs";
|
|
47633
47647
|
import { copyFile, mkdir as mkdir10, readFile as readFile11, stat as stat3, writeFile as writeFile11 } from "fs/promises";
|
|
47634
|
-
import * as
|
|
47648
|
+
import * as path31 from "path";
|
|
47635
47649
|
function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
|
|
47636
47650
|
const resolved = resolveConfig(config3);
|
|
47637
47651
|
const storageDir = resolved.storageDir.replace(/^\.swarm[/\\]?/, "");
|
|
@@ -47645,8 +47659,8 @@ function resolveSqliteDatabasePath(rootDirectory, config3 = {}) {
|
|
|
47645
47659
|
async function readLegacyJsonl(rootDirectory, config3 = {}) {
|
|
47646
47660
|
const resolved = resolveConfig(config3);
|
|
47647
47661
|
const storageDir = resolveMemoryStorageDir(rootDirectory, resolved);
|
|
47648
|
-
const memoryLoad = await readMemoryJsonl(
|
|
47649
|
-
const proposalLoad = await readProposalJsonl(
|
|
47662
|
+
const memoryLoad = await readMemoryJsonl(path31.join(storageDir, "memories.jsonl"), resolved);
|
|
47663
|
+
const proposalLoad = await readProposalJsonl(path31.join(storageDir, "proposals.jsonl"), resolved);
|
|
47650
47664
|
return {
|
|
47651
47665
|
memories: memoryLoad.records,
|
|
47652
47666
|
proposals: proposalLoad.records,
|
|
@@ -47656,15 +47670,15 @@ async function readLegacyJsonl(rootDirectory, config3 = {}) {
|
|
|
47656
47670
|
}
|
|
47657
47671
|
async function backupLegacyJsonl(rootDirectory, config3 = {}) {
|
|
47658
47672
|
const storageDir = resolveMemoryStorageDir(rootDirectory, config3);
|
|
47659
|
-
const backupDir =
|
|
47673
|
+
const backupDir = path31.join(storageDir, "backups");
|
|
47660
47674
|
await mkdir10(backupDir, { recursive: true });
|
|
47661
47675
|
const results = [];
|
|
47662
47676
|
for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
|
|
47663
|
-
const source =
|
|
47664
|
-
if (!
|
|
47677
|
+
const source = path31.join(storageDir, filename);
|
|
47678
|
+
if (!existsSync21(source))
|
|
47665
47679
|
continue;
|
|
47666
|
-
const backup =
|
|
47667
|
-
if (
|
|
47680
|
+
const backup = path31.join(backupDir, `${filename}.pre-sqlite-migration`);
|
|
47681
|
+
if (existsSync21(backup)) {
|
|
47668
47682
|
results.push({ source, backup, created: false });
|
|
47669
47683
|
continue;
|
|
47670
47684
|
}
|
|
@@ -47674,24 +47688,24 @@ async function backupLegacyJsonl(rootDirectory, config3 = {}) {
|
|
|
47674
47688
|
return results;
|
|
47675
47689
|
}
|
|
47676
47690
|
async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
|
|
47677
|
-
const exportDir =
|
|
47691
|
+
const exportDir = path31.join(resolveMemoryStorageDir(rootDirectory, config3), "export");
|
|
47678
47692
|
await mkdir10(exportDir, { recursive: true });
|
|
47679
|
-
const memoriesPath =
|
|
47680
|
-
const proposalsPath =
|
|
47693
|
+
const memoriesPath = path31.join(exportDir, "memories.jsonl");
|
|
47694
|
+
const proposalsPath = path31.join(exportDir, "proposals.jsonl");
|
|
47681
47695
|
await writeFile11(memoriesPath, toJsonl(memories), "utf-8");
|
|
47682
47696
|
await writeFile11(proposalsPath, toJsonl(proposals), "utf-8");
|
|
47683
47697
|
return { directory: exportDir, memoriesPath, proposalsPath };
|
|
47684
47698
|
}
|
|
47685
47699
|
async function writeMigrationReport(rootDirectory, report, config3 = {}) {
|
|
47686
|
-
const reportPath =
|
|
47687
|
-
await mkdir10(
|
|
47700
|
+
const reportPath = path31.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
|
|
47701
|
+
await mkdir10(path31.dirname(reportPath), { recursive: true });
|
|
47688
47702
|
await writeFile11(reportPath, `${JSON.stringify(report, null, 2)}
|
|
47689
47703
|
`, "utf-8");
|
|
47690
47704
|
return reportPath;
|
|
47691
47705
|
}
|
|
47692
47706
|
async function readMigrationReport(rootDirectory, config3 = {}) {
|
|
47693
|
-
const reportPath =
|
|
47694
|
-
if (!
|
|
47707
|
+
const reportPath = path31.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
|
|
47708
|
+
if (!existsSync21(reportPath))
|
|
47695
47709
|
return null;
|
|
47696
47710
|
try {
|
|
47697
47711
|
return JSON.parse(await readFile11(reportPath, "utf-8"));
|
|
@@ -47703,15 +47717,15 @@ async function getLegacyJsonlFileStatus(rootDirectory, config3 = {}) {
|
|
|
47703
47717
|
const storageDir = resolveMemoryStorageDir(rootDirectory, config3);
|
|
47704
47718
|
const statuses = [];
|
|
47705
47719
|
for (const file3 of ["memories.jsonl", "proposals.jsonl"]) {
|
|
47706
|
-
const filePath =
|
|
47720
|
+
const filePath = path31.join(storageDir, file3);
|
|
47707
47721
|
let sizeBytes = 0;
|
|
47708
|
-
if (
|
|
47722
|
+
if (existsSync21(filePath)) {
|
|
47709
47723
|
sizeBytes = (await stat3(filePath)).size;
|
|
47710
47724
|
}
|
|
47711
47725
|
statuses.push({
|
|
47712
47726
|
file: file3,
|
|
47713
47727
|
path: filePath,
|
|
47714
|
-
exists:
|
|
47728
|
+
exists: existsSync21(filePath),
|
|
47715
47729
|
sizeBytes
|
|
47716
47730
|
});
|
|
47717
47731
|
}
|
|
@@ -47792,7 +47806,7 @@ async function readProposalJsonl(filePath, config3) {
|
|
|
47792
47806
|
return { records, invalidRows, totalRows: rows.totalRows };
|
|
47793
47807
|
}
|
|
47794
47808
|
async function readJsonlRows(filePath) {
|
|
47795
|
-
if (!
|
|
47809
|
+
if (!existsSync21(filePath)) {
|
|
47796
47810
|
return { rows: [], invalidRows: [], totalRows: 0 };
|
|
47797
47811
|
}
|
|
47798
47812
|
const content = await readFile11(filePath, "utf-8");
|
|
@@ -47832,7 +47846,7 @@ var init_jsonl_migration = __esm(() => {
|
|
|
47832
47846
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
47833
47847
|
import { mkdirSync as mkdirSync13 } from "fs";
|
|
47834
47848
|
import { createRequire as createRequire2 } from "module";
|
|
47835
|
-
import * as
|
|
47849
|
+
import * as path32 from "path";
|
|
47836
47850
|
function loadDatabaseCtor2() {
|
|
47837
47851
|
if (_DatabaseCtor2)
|
|
47838
47852
|
return _DatabaseCtor2;
|
|
@@ -47890,7 +47904,7 @@ class SQLiteMemoryProvider {
|
|
|
47890
47904
|
if (this.initialized)
|
|
47891
47905
|
return;
|
|
47892
47906
|
const dbPath = this.databasePath();
|
|
47893
|
-
mkdirSync13(
|
|
47907
|
+
mkdirSync13(path32.dirname(dbPath), { recursive: true });
|
|
47894
47908
|
const Db = loadDatabaseCtor2();
|
|
47895
47909
|
this.db = new Db(dbPath);
|
|
47896
47910
|
this.db.run("PRAGMA journal_mode = WAL;");
|
|
@@ -48774,11 +48788,11 @@ var init_gateway = __esm(() => {
|
|
|
48774
48788
|
});
|
|
48775
48789
|
|
|
48776
48790
|
// src/memory/evaluation.ts
|
|
48777
|
-
import * as
|
|
48791
|
+
import * as fs12 from "fs/promises";
|
|
48778
48792
|
import * as os7 from "os";
|
|
48779
|
-
import * as
|
|
48793
|
+
import * as path33 from "path";
|
|
48780
48794
|
async function evaluateMemoryRecallFixtures(options) {
|
|
48781
|
-
const fixtureDirectory =
|
|
48795
|
+
const fixtureDirectory = path33.resolve(options.fixtureDirectory);
|
|
48782
48796
|
const providers = options.providers ?? DEFAULT_PROVIDERS;
|
|
48783
48797
|
const modes = options.modes ?? DEFAULT_MODES;
|
|
48784
48798
|
const generatedAt = new Date().toISOString();
|
|
@@ -48787,7 +48801,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
48787
48801
|
for (const fixture of fixtures) {
|
|
48788
48802
|
const materialized = materializeFixture(fixture);
|
|
48789
48803
|
for (const providerName of providers) {
|
|
48790
|
-
const tempRoot = await
|
|
48804
|
+
const tempRoot = await fs12.realpath(await fs12.mkdtemp(path33.join(os7.tmpdir(), "swarm-memory-eval-")));
|
|
48791
48805
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
48792
48806
|
try {
|
|
48793
48807
|
await provider.initialize?.();
|
|
@@ -48811,7 +48825,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
48811
48825
|
} finally {
|
|
48812
48826
|
await provider.close?.();
|
|
48813
48827
|
if (!options.keepTempRoots) {
|
|
48814
|
-
await
|
|
48828
|
+
await fs12.rm(tempRoot, { recursive: true, force: true });
|
|
48815
48829
|
}
|
|
48816
48830
|
}
|
|
48817
48831
|
}
|
|
@@ -48827,11 +48841,11 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
48827
48841
|
};
|
|
48828
48842
|
}
|
|
48829
48843
|
async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
48830
|
-
const entries = await
|
|
48844
|
+
const entries = await fs12.readdir(fixtureDirectory, { withFileTypes: true });
|
|
48831
48845
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
48832
48846
|
const fixtures = [];
|
|
48833
48847
|
for (const file3 of files) {
|
|
48834
|
-
const raw = await
|
|
48848
|
+
const raw = await fs12.readFile(path33.join(fixtureDirectory, file3), "utf-8");
|
|
48835
48849
|
fixtures.push(validateFixture(JSON.parse(raw), file3));
|
|
48836
48850
|
}
|
|
48837
48851
|
return fixtures;
|
|
@@ -49169,8 +49183,8 @@ var init_memory = __esm(() => {
|
|
|
49169
49183
|
});
|
|
49170
49184
|
|
|
49171
49185
|
// src/commands/memory.ts
|
|
49172
|
-
import { existsSync as
|
|
49173
|
-
import * as
|
|
49186
|
+
import { existsSync as existsSync22 } from "fs";
|
|
49187
|
+
import * as path34 from "path";
|
|
49174
49188
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
49175
49189
|
async function handleMemoryCommand(_directory, _args) {
|
|
49176
49190
|
return [
|
|
@@ -49201,7 +49215,7 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
49201
49215
|
`- Provider: \`${config3.provider}\``,
|
|
49202
49216
|
`- Storage: \`${storageDir}\``,
|
|
49203
49217
|
`- SQLite path: \`${sqlitePath}\``,
|
|
49204
|
-
`- SQLite database exists: \`${
|
|
49218
|
+
`- SQLite database exists: \`${existsSync22(sqlitePath)}\``,
|
|
49205
49219
|
`- Automatic destructive cleanup: \`disabled\``,
|
|
49206
49220
|
"",
|
|
49207
49221
|
"### Legacy JSONL"
|
|
@@ -49440,7 +49454,7 @@ function resolveCommandMemoryConfig(directory) {
|
|
|
49440
49454
|
}
|
|
49441
49455
|
function parseEvaluateArgs(directory, args) {
|
|
49442
49456
|
let json3 = false;
|
|
49443
|
-
let fixtureDirectory =
|
|
49457
|
+
let fixtureDirectory = path34.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
|
|
49444
49458
|
for (let i = 0;i < args.length; i++) {
|
|
49445
49459
|
const arg = args[i];
|
|
49446
49460
|
if (arg === "--json") {
|
|
@@ -49454,7 +49468,7 @@ function parseEvaluateArgs(directory, args) {
|
|
|
49454
49468
|
error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
|
|
49455
49469
|
};
|
|
49456
49470
|
}
|
|
49457
|
-
fixtureDirectory =
|
|
49471
|
+
fixtureDirectory = path34.resolve(directory, next);
|
|
49458
49472
|
i++;
|
|
49459
49473
|
continue;
|
|
49460
49474
|
}
|
|
@@ -49487,15 +49501,15 @@ function parseMaintenanceArgs(args, options) {
|
|
|
49487
49501
|
return { limit, confirm };
|
|
49488
49502
|
}
|
|
49489
49503
|
function resolvePackageRootFromModule(modulePath) {
|
|
49490
|
-
const moduleDir =
|
|
49491
|
-
const leaf =
|
|
49504
|
+
const moduleDir = path34.dirname(modulePath);
|
|
49505
|
+
const leaf = path34.basename(moduleDir);
|
|
49492
49506
|
if (leaf === "commands" || leaf === "cli") {
|
|
49493
|
-
return
|
|
49507
|
+
return path34.resolve(moduleDir, "..", "..");
|
|
49494
49508
|
}
|
|
49495
49509
|
if (leaf === "dist") {
|
|
49496
|
-
return
|
|
49510
|
+
return path34.resolve(moduleDir, "..");
|
|
49497
49511
|
}
|
|
49498
|
-
return
|
|
49512
|
+
return path34.resolve(moduleDir, "..");
|
|
49499
49513
|
}
|
|
49500
49514
|
function formatMigrationResult(label, report) {
|
|
49501
49515
|
if (!report) {
|
|
@@ -49614,7 +49628,7 @@ var PACKAGE_ROOT;
|
|
|
49614
49628
|
var init_memory2 = __esm(() => {
|
|
49615
49629
|
init_loader();
|
|
49616
49630
|
init_memory();
|
|
49617
|
-
PACKAGE_ROOT =
|
|
49631
|
+
PACKAGE_ROOT = path34.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
|
|
49618
49632
|
});
|
|
49619
49633
|
|
|
49620
49634
|
// src/services/plan-service.ts
|
|
@@ -50001,8 +50015,8 @@ function containsControlChars(str) {
|
|
|
50001
50015
|
var init_path_security = () => {};
|
|
50002
50016
|
|
|
50003
50017
|
// src/tools/lint.ts
|
|
50004
|
-
import * as
|
|
50005
|
-
import * as
|
|
50018
|
+
import * as fs13 from "fs";
|
|
50019
|
+
import * as path35 from "path";
|
|
50006
50020
|
function validateArgs(args) {
|
|
50007
50021
|
if (typeof args !== "object" || args === null)
|
|
50008
50022
|
return false;
|
|
@@ -50013,9 +50027,9 @@ function validateArgs(args) {
|
|
|
50013
50027
|
}
|
|
50014
50028
|
function getLinterCommand(linter, mode, projectDir) {
|
|
50015
50029
|
const isWindows = process.platform === "win32";
|
|
50016
|
-
const binDir =
|
|
50017
|
-
const biomeBin = isWindows ?
|
|
50018
|
-
const eslintBin = isWindows ?
|
|
50030
|
+
const binDir = path35.join(projectDir, "node_modules", ".bin");
|
|
50031
|
+
const biomeBin = isWindows ? path35.join(binDir, "biome.EXE") : path35.join(binDir, "biome");
|
|
50032
|
+
const eslintBin = isWindows ? path35.join(binDir, "eslint.cmd") : path35.join(binDir, "eslint");
|
|
50019
50033
|
switch (linter) {
|
|
50020
50034
|
case "biome":
|
|
50021
50035
|
if (mode === "fix") {
|
|
@@ -50031,7 +50045,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
50031
50045
|
}
|
|
50032
50046
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
50033
50047
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
50034
|
-
const gradlew =
|
|
50048
|
+
const gradlew = fs13.existsSync(path35.join(cwd, gradlewName)) ? path35.join(cwd, gradlewName) : null;
|
|
50035
50049
|
switch (linter) {
|
|
50036
50050
|
case "ruff":
|
|
50037
50051
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -50065,12 +50079,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
50065
50079
|
}
|
|
50066
50080
|
}
|
|
50067
50081
|
function detectRuff(cwd) {
|
|
50068
|
-
if (
|
|
50082
|
+
if (fs13.existsSync(path35.join(cwd, "ruff.toml")))
|
|
50069
50083
|
return isCommandAvailable("ruff");
|
|
50070
50084
|
try {
|
|
50071
|
-
const pyproject =
|
|
50072
|
-
if (
|
|
50073
|
-
const content =
|
|
50085
|
+
const pyproject = path35.join(cwd, "pyproject.toml");
|
|
50086
|
+
if (fs13.existsSync(pyproject)) {
|
|
50087
|
+
const content = fs13.readFileSync(pyproject, "utf-8");
|
|
50074
50088
|
if (content.includes("[tool.ruff]"))
|
|
50075
50089
|
return isCommandAvailable("ruff");
|
|
50076
50090
|
}
|
|
@@ -50078,21 +50092,21 @@ function detectRuff(cwd) {
|
|
|
50078
50092
|
return false;
|
|
50079
50093
|
}
|
|
50080
50094
|
function detectClippy(cwd) {
|
|
50081
|
-
return
|
|
50095
|
+
return fs13.existsSync(path35.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
50082
50096
|
}
|
|
50083
50097
|
function detectGolangciLint(cwd) {
|
|
50084
|
-
return
|
|
50098
|
+
return fs13.existsSync(path35.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
50085
50099
|
}
|
|
50086
50100
|
function detectCheckstyle(cwd) {
|
|
50087
|
-
const hasMaven =
|
|
50088
|
-
const hasGradle =
|
|
50089
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (
|
|
50101
|
+
const hasMaven = fs13.existsSync(path35.join(cwd, "pom.xml"));
|
|
50102
|
+
const hasGradle = fs13.existsSync(path35.join(cwd, "build.gradle")) || fs13.existsSync(path35.join(cwd, "build.gradle.kts"));
|
|
50103
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs13.existsSync(path35.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
50090
50104
|
return (hasMaven || hasGradle) && hasBinary;
|
|
50091
50105
|
}
|
|
50092
50106
|
function detectKtlint(cwd) {
|
|
50093
|
-
const hasKotlin =
|
|
50107
|
+
const hasKotlin = fs13.existsSync(path35.join(cwd, "build.gradle.kts")) || fs13.existsSync(path35.join(cwd, "build.gradle")) || (() => {
|
|
50094
50108
|
try {
|
|
50095
|
-
return
|
|
50109
|
+
return fs13.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
50096
50110
|
} catch {
|
|
50097
50111
|
return false;
|
|
50098
50112
|
}
|
|
@@ -50101,7 +50115,7 @@ function detectKtlint(cwd) {
|
|
|
50101
50115
|
}
|
|
50102
50116
|
function detectDotnetFormat(cwd) {
|
|
50103
50117
|
try {
|
|
50104
|
-
const files =
|
|
50118
|
+
const files = fs13.readdirSync(cwd);
|
|
50105
50119
|
const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
|
|
50106
50120
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
50107
50121
|
} catch {
|
|
@@ -50109,14 +50123,14 @@ function detectDotnetFormat(cwd) {
|
|
|
50109
50123
|
}
|
|
50110
50124
|
}
|
|
50111
50125
|
function detectCppcheck(cwd) {
|
|
50112
|
-
if (
|
|
50126
|
+
if (fs13.existsSync(path35.join(cwd, "CMakeLists.txt"))) {
|
|
50113
50127
|
return isCommandAvailable("cppcheck");
|
|
50114
50128
|
}
|
|
50115
50129
|
try {
|
|
50116
|
-
const dirsToCheck = [cwd,
|
|
50130
|
+
const dirsToCheck = [cwd, path35.join(cwd, "src")];
|
|
50117
50131
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
50118
50132
|
try {
|
|
50119
|
-
return
|
|
50133
|
+
return fs13.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
50120
50134
|
} catch {
|
|
50121
50135
|
return false;
|
|
50122
50136
|
}
|
|
@@ -50127,13 +50141,13 @@ function detectCppcheck(cwd) {
|
|
|
50127
50141
|
}
|
|
50128
50142
|
}
|
|
50129
50143
|
function detectSwiftlint(cwd) {
|
|
50130
|
-
return
|
|
50144
|
+
return fs13.existsSync(path35.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
50131
50145
|
}
|
|
50132
50146
|
function detectDartAnalyze(cwd) {
|
|
50133
|
-
return
|
|
50147
|
+
return fs13.existsSync(path35.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
50134
50148
|
}
|
|
50135
50149
|
function detectRubocop(cwd) {
|
|
50136
|
-
return (
|
|
50150
|
+
return (fs13.existsSync(path35.join(cwd, "Gemfile")) || fs13.existsSync(path35.join(cwd, "gems.rb")) || fs13.existsSync(path35.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
50137
50151
|
}
|
|
50138
50152
|
function detectAdditionalLinter(cwd) {
|
|
50139
50153
|
if (detectRuff(cwd))
|
|
@@ -50161,10 +50175,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
50161
50175
|
function findBinInAncestors(startDir, binName) {
|
|
50162
50176
|
let dir = startDir;
|
|
50163
50177
|
while (true) {
|
|
50164
|
-
const candidate =
|
|
50165
|
-
if (
|
|
50178
|
+
const candidate = path35.join(dir, "node_modules", ".bin", binName);
|
|
50179
|
+
if (fs13.existsSync(candidate))
|
|
50166
50180
|
return candidate;
|
|
50167
|
-
const parent =
|
|
50181
|
+
const parent = path35.dirname(dir);
|
|
50168
50182
|
if (parent === dir)
|
|
50169
50183
|
break;
|
|
50170
50184
|
dir = parent;
|
|
@@ -50173,11 +50187,11 @@ function findBinInAncestors(startDir, binName) {
|
|
|
50173
50187
|
}
|
|
50174
50188
|
function findBinInEnvPath(binName) {
|
|
50175
50189
|
const searchPath = process.env.PATH ?? "";
|
|
50176
|
-
for (const dir of searchPath.split(
|
|
50190
|
+
for (const dir of searchPath.split(path35.delimiter)) {
|
|
50177
50191
|
if (!dir)
|
|
50178
50192
|
continue;
|
|
50179
|
-
const candidate =
|
|
50180
|
-
if (
|
|
50193
|
+
const candidate = path35.join(dir, binName);
|
|
50194
|
+
if (fs13.existsSync(candidate))
|
|
50181
50195
|
return candidate;
|
|
50182
50196
|
}
|
|
50183
50197
|
return null;
|
|
@@ -50185,17 +50199,17 @@ function findBinInEnvPath(binName) {
|
|
|
50185
50199
|
async function detectAvailableLinter(directory) {
|
|
50186
50200
|
if (!directory)
|
|
50187
50201
|
return null;
|
|
50188
|
-
if (!
|
|
50202
|
+
if (!fs13.existsSync(directory))
|
|
50189
50203
|
return null;
|
|
50190
50204
|
const projectDir = directory;
|
|
50191
50205
|
const isWindows = process.platform === "win32";
|
|
50192
|
-
const biomeBin = isWindows ?
|
|
50193
|
-
const eslintBin = isWindows ?
|
|
50206
|
+
const biomeBin = isWindows ? path35.join(projectDir, "node_modules", ".bin", "biome.EXE") : path35.join(projectDir, "node_modules", ".bin", "biome");
|
|
50207
|
+
const eslintBin = isWindows ? path35.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path35.join(projectDir, "node_modules", ".bin", "eslint");
|
|
50194
50208
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
50195
50209
|
if (localResult)
|
|
50196
50210
|
return localResult;
|
|
50197
|
-
const biomeAncestor = findBinInAncestors(
|
|
50198
|
-
const eslintAncestor = findBinInAncestors(
|
|
50211
|
+
const biomeAncestor = findBinInAncestors(path35.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
50212
|
+
const eslintAncestor = findBinInAncestors(path35.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
50199
50213
|
if (biomeAncestor || eslintAncestor) {
|
|
50200
50214
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
50201
50215
|
}
|
|
@@ -50214,11 +50228,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
50214
50228
|
stderr: "pipe"
|
|
50215
50229
|
});
|
|
50216
50230
|
const biomeExit = biomeProc.exited;
|
|
50217
|
-
const timeout = new Promise((
|
|
50231
|
+
const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
|
|
50218
50232
|
const result = await Promise.race([biomeExit, timeout]);
|
|
50219
50233
|
if (result === "timeout") {
|
|
50220
50234
|
biomeProc.kill();
|
|
50221
|
-
} else if (biomeProc.exitCode === 0 &&
|
|
50235
|
+
} else if (biomeProc.exitCode === 0 && fs13.existsSync(biomeBin)) {
|
|
50222
50236
|
return "biome";
|
|
50223
50237
|
}
|
|
50224
50238
|
} catch {}
|
|
@@ -50228,11 +50242,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
50228
50242
|
stderr: "pipe"
|
|
50229
50243
|
});
|
|
50230
50244
|
const eslintExit = eslintProc.exited;
|
|
50231
|
-
const timeout = new Promise((
|
|
50245
|
+
const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
|
|
50232
50246
|
const result = await Promise.race([eslintExit, timeout]);
|
|
50233
50247
|
if (result === "timeout") {
|
|
50234
50248
|
eslintProc.kill();
|
|
50235
|
-
} else if (eslintProc.exitCode === 0 &&
|
|
50249
|
+
} else if (eslintProc.exitCode === 0 && fs13.existsSync(eslintBin)) {
|
|
50236
50250
|
return "eslint";
|
|
50237
50251
|
}
|
|
50238
50252
|
} catch {}
|
|
@@ -50417,8 +50431,8 @@ For Rust: rustup component add clippy`
|
|
|
50417
50431
|
});
|
|
50418
50432
|
|
|
50419
50433
|
// src/tools/secretscan.ts
|
|
50420
|
-
import * as
|
|
50421
|
-
import * as
|
|
50434
|
+
import * as fs14 from "fs";
|
|
50435
|
+
import * as path36 from "path";
|
|
50422
50436
|
function calculateShannonEntropy(str) {
|
|
50423
50437
|
if (str.length === 0)
|
|
50424
50438
|
return 0;
|
|
@@ -50466,11 +50480,11 @@ function isGlobOrPathPattern(pattern) {
|
|
|
50466
50480
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
50467
50481
|
}
|
|
50468
50482
|
function loadSecretScanIgnore(scanDir) {
|
|
50469
|
-
const ignorePath =
|
|
50483
|
+
const ignorePath = path36.join(scanDir, ".secretscanignore");
|
|
50470
50484
|
try {
|
|
50471
|
-
if (!
|
|
50485
|
+
if (!fs14.existsSync(ignorePath))
|
|
50472
50486
|
return [];
|
|
50473
|
-
const content =
|
|
50487
|
+
const content = fs14.readFileSync(ignorePath, "utf8");
|
|
50474
50488
|
const patterns = [];
|
|
50475
50489
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
50476
50490
|
const line = rawLine.trim();
|
|
@@ -50489,7 +50503,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
50489
50503
|
if (exactNames.has(entry))
|
|
50490
50504
|
return true;
|
|
50491
50505
|
for (const pattern of globPatterns) {
|
|
50492
|
-
if (
|
|
50506
|
+
if (path36.matchesGlob(relPath, pattern))
|
|
50493
50507
|
return true;
|
|
50494
50508
|
}
|
|
50495
50509
|
return false;
|
|
@@ -50510,7 +50524,7 @@ function validateDirectoryInput(dir) {
|
|
|
50510
50524
|
return null;
|
|
50511
50525
|
}
|
|
50512
50526
|
function isBinaryFile(filePath, buffer) {
|
|
50513
|
-
const ext =
|
|
50527
|
+
const ext = path36.extname(filePath).toLowerCase();
|
|
50514
50528
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
50515
50529
|
return true;
|
|
50516
50530
|
}
|
|
@@ -50588,7 +50602,7 @@ function createRedactedContext(line, findings) {
|
|
|
50588
50602
|
function scanFileForSecrets(filePath) {
|
|
50589
50603
|
const findings = [];
|
|
50590
50604
|
try {
|
|
50591
|
-
const lstat =
|
|
50605
|
+
const lstat = fs14.lstatSync(filePath);
|
|
50592
50606
|
if (lstat.isSymbolicLink()) {
|
|
50593
50607
|
return findings;
|
|
50594
50608
|
}
|
|
@@ -50597,14 +50611,14 @@ function scanFileForSecrets(filePath) {
|
|
|
50597
50611
|
}
|
|
50598
50612
|
let buffer;
|
|
50599
50613
|
if (O_NOFOLLOW !== undefined) {
|
|
50600
|
-
const fd =
|
|
50614
|
+
const fd = fs14.openSync(filePath, "r", O_NOFOLLOW);
|
|
50601
50615
|
try {
|
|
50602
|
-
buffer =
|
|
50616
|
+
buffer = fs14.readFileSync(fd);
|
|
50603
50617
|
} finally {
|
|
50604
|
-
|
|
50618
|
+
fs14.closeSync(fd);
|
|
50605
50619
|
}
|
|
50606
50620
|
} else {
|
|
50607
|
-
buffer =
|
|
50621
|
+
buffer = fs14.readFileSync(filePath);
|
|
50608
50622
|
}
|
|
50609
50623
|
if (isBinaryFile(filePath, buffer)) {
|
|
50610
50624
|
return findings;
|
|
@@ -50646,9 +50660,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
50646
50660
|
return false;
|
|
50647
50661
|
}
|
|
50648
50662
|
function isPathWithinScope(realPath, scanDir) {
|
|
50649
|
-
const resolvedScanDir =
|
|
50650
|
-
const resolvedRealPath =
|
|
50651
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
50663
|
+
const resolvedScanDir = path36.resolve(scanDir);
|
|
50664
|
+
const resolvedRealPath = path36.resolve(realPath);
|
|
50665
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path36.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
50652
50666
|
}
|
|
50653
50667
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
50654
50668
|
skippedDirs: 0,
|
|
@@ -50659,7 +50673,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
50659
50673
|
const files = [];
|
|
50660
50674
|
let entries;
|
|
50661
50675
|
try {
|
|
50662
|
-
entries =
|
|
50676
|
+
entries = fs14.readdirSync(dir);
|
|
50663
50677
|
} catch {
|
|
50664
50678
|
stats.fileErrors++;
|
|
50665
50679
|
return files;
|
|
@@ -50674,15 +50688,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
50674
50688
|
return a.localeCompare(b);
|
|
50675
50689
|
});
|
|
50676
50690
|
for (const entry of entries) {
|
|
50677
|
-
const fullPath =
|
|
50678
|
-
const relPath =
|
|
50691
|
+
const fullPath = path36.join(dir, entry);
|
|
50692
|
+
const relPath = path36.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
50679
50693
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
50680
50694
|
stats.skippedDirs++;
|
|
50681
50695
|
continue;
|
|
50682
50696
|
}
|
|
50683
50697
|
let lstat;
|
|
50684
50698
|
try {
|
|
50685
|
-
lstat =
|
|
50699
|
+
lstat = fs14.lstatSync(fullPath);
|
|
50686
50700
|
} catch {
|
|
50687
50701
|
stats.fileErrors++;
|
|
50688
50702
|
continue;
|
|
@@ -50694,7 +50708,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
50694
50708
|
if (lstat.isDirectory()) {
|
|
50695
50709
|
let realPath;
|
|
50696
50710
|
try {
|
|
50697
|
-
realPath =
|
|
50711
|
+
realPath = fs14.realpathSync(fullPath);
|
|
50698
50712
|
} catch {
|
|
50699
50713
|
stats.fileErrors++;
|
|
50700
50714
|
continue;
|
|
@@ -50710,7 +50724,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
50710
50724
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
50711
50725
|
files.push(...subFiles);
|
|
50712
50726
|
} else if (lstat.isFile()) {
|
|
50713
|
-
const ext =
|
|
50727
|
+
const ext = path36.extname(fullPath).toLowerCase();
|
|
50714
50728
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
50715
50729
|
files.push(fullPath);
|
|
50716
50730
|
} else {
|
|
@@ -50913,7 +50927,7 @@ var init_secretscan = __esm(() => {
|
|
|
50913
50927
|
redactTemplate: () => "SK[REDACTED]"
|
|
50914
50928
|
}
|
|
50915
50929
|
];
|
|
50916
|
-
O_NOFOLLOW = process.platform !== "win32" ?
|
|
50930
|
+
O_NOFOLLOW = process.platform !== "win32" ? fs14.constants.O_NOFOLLOW : undefined;
|
|
50917
50931
|
secretscan = createSwarmTool({
|
|
50918
50932
|
description: "Scan directory for potential secrets (API keys, tokens, passwords) using regex patterns and entropy heuristics. Returns metadata-only findings with redacted previews - NEVER returns raw secrets. Excludes common directories (node_modules, .git, dist, etc.) by default. Supports glob patterns (e.g. **/.svelte-kit/**, **/*.test.ts) and reads .secretscanignore at the scan root.",
|
|
50919
50933
|
args: {
|
|
@@ -50970,15 +50984,15 @@ var init_secretscan = __esm(() => {
|
|
|
50970
50984
|
}
|
|
50971
50985
|
}
|
|
50972
50986
|
try {
|
|
50973
|
-
const _scanDirRaw =
|
|
50987
|
+
const _scanDirRaw = path36.resolve(directory);
|
|
50974
50988
|
const scanDir = (() => {
|
|
50975
50989
|
try {
|
|
50976
|
-
return
|
|
50990
|
+
return fs14.realpathSync(_scanDirRaw);
|
|
50977
50991
|
} catch {
|
|
50978
50992
|
return _scanDirRaw;
|
|
50979
50993
|
}
|
|
50980
50994
|
})();
|
|
50981
|
-
if (!
|
|
50995
|
+
if (!fs14.existsSync(scanDir)) {
|
|
50982
50996
|
const errorResult = {
|
|
50983
50997
|
error: "directory not found",
|
|
50984
50998
|
scan_dir: directory,
|
|
@@ -50989,7 +51003,7 @@ var init_secretscan = __esm(() => {
|
|
|
50989
51003
|
};
|
|
50990
51004
|
return JSON.stringify(errorResult, null, 2);
|
|
50991
51005
|
}
|
|
50992
|
-
const dirStat =
|
|
51006
|
+
const dirStat = fs14.statSync(scanDir);
|
|
50993
51007
|
if (!dirStat.isDirectory()) {
|
|
50994
51008
|
const errorResult = {
|
|
50995
51009
|
error: "target must be a directory, not a file",
|
|
@@ -51040,7 +51054,7 @@ var init_secretscan = __esm(() => {
|
|
|
51040
51054
|
break;
|
|
51041
51055
|
const fileFindings = scanFileForSecrets(filePath);
|
|
51042
51056
|
try {
|
|
51043
|
-
const stat4 =
|
|
51057
|
+
const stat4 = fs14.statSync(filePath);
|
|
51044
51058
|
if (stat4.size > MAX_FILE_SIZE_BYTES) {
|
|
51045
51059
|
skippedFiles++;
|
|
51046
51060
|
continue;
|
|
@@ -51116,12 +51130,12 @@ var init_secretscan = __esm(() => {
|
|
|
51116
51130
|
});
|
|
51117
51131
|
|
|
51118
51132
|
// src/lang/default-backend.ts
|
|
51119
|
-
import * as
|
|
51120
|
-
import * as
|
|
51133
|
+
import * as fs15 from "fs";
|
|
51134
|
+
import * as path37 from "path";
|
|
51121
51135
|
function detectFileExists(dir, pattern) {
|
|
51122
51136
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
51123
51137
|
try {
|
|
51124
|
-
const files =
|
|
51138
|
+
const files = fs15.readdirSync(dir);
|
|
51125
51139
|
const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
|
|
51126
51140
|
return files.some((f) => regex.test(f));
|
|
51127
51141
|
} catch {
|
|
@@ -51129,7 +51143,7 @@ function detectFileExists(dir, pattern) {
|
|
|
51129
51143
|
}
|
|
51130
51144
|
}
|
|
51131
51145
|
try {
|
|
51132
|
-
|
|
51146
|
+
fs15.accessSync(path37.join(dir, pattern));
|
|
51133
51147
|
return true;
|
|
51134
51148
|
} catch {
|
|
51135
51149
|
return false;
|
|
@@ -51257,8 +51271,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
51257
51271
|
return ["mvn", "test"];
|
|
51258
51272
|
case "gradle": {
|
|
51259
51273
|
const isWindows = process.platform === "win32";
|
|
51260
|
-
const hasGradlewBat =
|
|
51261
|
-
const hasGradlew =
|
|
51274
|
+
const hasGradlewBat = fs15.existsSync(path37.join(dir, "gradlew.bat"));
|
|
51275
|
+
const hasGradlew = fs15.existsSync(path37.join(dir, "gradlew"));
|
|
51262
51276
|
if (hasGradlewBat && isWindows)
|
|
51263
51277
|
return ["gradlew.bat", "test"];
|
|
51264
51278
|
if (hasGradlew)
|
|
@@ -51275,7 +51289,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
51275
51289
|
"cmake-build-release",
|
|
51276
51290
|
"out"
|
|
51277
51291
|
];
|
|
51278
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
51292
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs15.existsSync(path37.join(dir, d, "CMakeCache.txt"))) ?? "build";
|
|
51279
51293
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
51280
51294
|
}
|
|
51281
51295
|
case "swift-test":
|
|
@@ -51562,23 +51576,23 @@ async function defaultSelectBuildCommand(profile, dir) {
|
|
|
51562
51576
|
return null;
|
|
51563
51577
|
}
|
|
51564
51578
|
async function defaultTestFilesFor(profile, sourceFile, dir) {
|
|
51565
|
-
const ext =
|
|
51579
|
+
const ext = path37.extname(sourceFile);
|
|
51566
51580
|
if (!profile.extensions.includes(ext))
|
|
51567
51581
|
return [];
|
|
51568
|
-
const base =
|
|
51569
|
-
const rel =
|
|
51570
|
-
const relDir =
|
|
51582
|
+
const base = path37.basename(sourceFile, ext);
|
|
51583
|
+
const rel = path37.relative(dir, sourceFile);
|
|
51584
|
+
const relDir = path37.dirname(rel);
|
|
51571
51585
|
const stripSrc = relDir.replace(/^src(\/|\\)/, "");
|
|
51572
51586
|
const candidates = new Set;
|
|
51573
51587
|
for (const tDir of ["tests", "test", "__tests__", "spec"]) {
|
|
51574
51588
|
for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
|
|
51575
|
-
candidates.add(
|
|
51589
|
+
candidates.add(path37.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
|
|
51576
51590
|
}
|
|
51577
51591
|
}
|
|
51578
51592
|
const existing = [];
|
|
51579
51593
|
for (const c of candidates) {
|
|
51580
51594
|
try {
|
|
51581
|
-
|
|
51595
|
+
fs15.accessSync(c);
|
|
51582
51596
|
existing.push(c);
|
|
51583
51597
|
} catch {}
|
|
51584
51598
|
}
|
|
@@ -51612,8 +51626,8 @@ var init_default_backend = __esm(() => {
|
|
|
51612
51626
|
});
|
|
51613
51627
|
|
|
51614
51628
|
// src/lang/backends/go.ts
|
|
51615
|
-
import * as
|
|
51616
|
-
import * as
|
|
51629
|
+
import * as fs16 from "fs";
|
|
51630
|
+
import * as path38 from "path";
|
|
51617
51631
|
function extractImports(_sourceFile, source) {
|
|
51618
51632
|
const out = new Set;
|
|
51619
51633
|
IMPORT_REGEX_SINGLE.lastIndex = 0;
|
|
@@ -51639,7 +51653,7 @@ function extractImports(_sourceFile, source) {
|
|
|
51639
51653
|
async function selectFramework(dir) {
|
|
51640
51654
|
let content;
|
|
51641
51655
|
try {
|
|
51642
|
-
content =
|
|
51656
|
+
content = fs16.readFileSync(path38.join(dir, "go.mod"), "utf-8");
|
|
51643
51657
|
} catch {
|
|
51644
51658
|
return null;
|
|
51645
51659
|
}
|
|
@@ -51660,16 +51674,16 @@ async function selectFramework(dir) {
|
|
|
51660
51674
|
async function selectEntryPoints(dir) {
|
|
51661
51675
|
const points = [];
|
|
51662
51676
|
try {
|
|
51663
|
-
|
|
51677
|
+
fs16.accessSync(path38.join(dir, "main.go"));
|
|
51664
51678
|
points.push("main.go");
|
|
51665
51679
|
} catch {}
|
|
51666
51680
|
try {
|
|
51667
|
-
const cmdDir =
|
|
51668
|
-
const subdirs =
|
|
51681
|
+
const cmdDir = path38.join(dir, "cmd");
|
|
51682
|
+
const subdirs = fs16.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
51669
51683
|
for (const sub of subdirs) {
|
|
51670
|
-
const main =
|
|
51684
|
+
const main = path38.join("cmd", sub.name, "main.go");
|
|
51671
51685
|
try {
|
|
51672
|
-
|
|
51686
|
+
fs16.accessSync(path38.join(dir, main));
|
|
51673
51687
|
points.push(main);
|
|
51674
51688
|
} catch {}
|
|
51675
51689
|
}
|
|
@@ -51699,8 +51713,8 @@ var init_go = __esm(() => {
|
|
|
51699
51713
|
});
|
|
51700
51714
|
|
|
51701
51715
|
// src/lang/backends/python.ts
|
|
51702
|
-
import * as
|
|
51703
|
-
import * as
|
|
51716
|
+
import * as fs17 from "fs";
|
|
51717
|
+
import * as path39 from "path";
|
|
51704
51718
|
function parseImportTargets(rawTargets) {
|
|
51705
51719
|
const cleaned = rawTargets.replace(/[()]/g, "").split(`
|
|
51706
51720
|
`).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
|
|
@@ -51760,7 +51774,7 @@ async function selectFramework2(dir) {
|
|
|
51760
51774
|
];
|
|
51761
51775
|
for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
|
|
51762
51776
|
try {
|
|
51763
|
-
const content =
|
|
51777
|
+
const content = fs17.readFileSync(path39.join(dir, candidate), "utf-8");
|
|
51764
51778
|
const lower = content.toLowerCase();
|
|
51765
51779
|
for (const [pkg, name] of candidates) {
|
|
51766
51780
|
if (lower.includes(pkg)) {
|
|
@@ -51774,7 +51788,7 @@ async function selectFramework2(dir) {
|
|
|
51774
51788
|
async function selectEntryPoints2(dir) {
|
|
51775
51789
|
const points = new Set;
|
|
51776
51790
|
try {
|
|
51777
|
-
const content =
|
|
51791
|
+
const content = fs17.readFileSync(path39.join(dir, "pyproject.toml"), "utf-8");
|
|
51778
51792
|
const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
|
|
51779
51793
|
if (scriptsBlock) {
|
|
51780
51794
|
for (const line of scriptsBlock[0].split(`
|
|
@@ -51789,7 +51803,7 @@ async function selectEntryPoints2(dir) {
|
|
|
51789
51803
|
} catch {}
|
|
51790
51804
|
for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
|
|
51791
51805
|
try {
|
|
51792
|
-
|
|
51806
|
+
fs17.accessSync(path39.join(dir, name));
|
|
51793
51807
|
points.add(name);
|
|
51794
51808
|
} catch {}
|
|
51795
51809
|
}
|
|
@@ -51817,8 +51831,8 @@ var init_python = __esm(() => {
|
|
|
51817
51831
|
});
|
|
51818
51832
|
|
|
51819
51833
|
// src/test-impact/analyzer.ts
|
|
51820
|
-
import
|
|
51821
|
-
import
|
|
51834
|
+
import fs18 from "fs";
|
|
51835
|
+
import path40 from "path";
|
|
51822
51836
|
function normalizePath(p) {
|
|
51823
51837
|
return p.replace(/\\/g, "/");
|
|
51824
51838
|
}
|
|
@@ -51838,7 +51852,7 @@ function sharedTrailingSegments(a, b) {
|
|
|
51838
51852
|
function isCacheStale(impactMap, generatedAtMs) {
|
|
51839
51853
|
for (const sourcePath of Object.keys(impactMap)) {
|
|
51840
51854
|
try {
|
|
51841
|
-
const stat4 =
|
|
51855
|
+
const stat4 = fs18.statSync(sourcePath);
|
|
51842
51856
|
if (stat4.mtimeMs > generatedAtMs) {
|
|
51843
51857
|
return true;
|
|
51844
51858
|
}
|
|
@@ -51852,15 +51866,15 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
51852
51866
|
if (!importPath.startsWith(".")) {
|
|
51853
51867
|
return null;
|
|
51854
51868
|
}
|
|
51855
|
-
const resolved =
|
|
51856
|
-
if (
|
|
51857
|
-
if (
|
|
51869
|
+
const resolved = path40.resolve(fromDir, importPath);
|
|
51870
|
+
if (path40.extname(resolved)) {
|
|
51871
|
+
if (fs18.existsSync(resolved) && fs18.statSync(resolved).isFile()) {
|
|
51858
51872
|
return normalizePath(resolved);
|
|
51859
51873
|
}
|
|
51860
51874
|
} else {
|
|
51861
51875
|
for (const ext of EXTENSIONS_TO_TRY) {
|
|
51862
51876
|
const withExt = resolved + ext;
|
|
51863
|
-
if (
|
|
51877
|
+
if (fs18.existsSync(withExt) && fs18.statSync(withExt).isFile()) {
|
|
51864
51878
|
return normalizePath(withExt);
|
|
51865
51879
|
}
|
|
51866
51880
|
}
|
|
@@ -51873,29 +51887,29 @@ function resolvePythonImport(fromDir, module) {
|
|
|
51873
51887
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
51874
51888
|
let baseDir = fromDir;
|
|
51875
51889
|
for (let i = 1;i < leadingDots; i++) {
|
|
51876
|
-
baseDir =
|
|
51890
|
+
baseDir = path40.dirname(baseDir);
|
|
51877
51891
|
}
|
|
51878
51892
|
const rest = module.slice(leadingDots);
|
|
51879
51893
|
if (rest.length === 0) {
|
|
51880
|
-
const initPath =
|
|
51881
|
-
if (
|
|
51894
|
+
const initPath = path40.join(baseDir, "__init__.py");
|
|
51895
|
+
if (fs18.existsSync(initPath) && fs18.statSync(initPath).isFile()) {
|
|
51882
51896
|
return normalizePath(initPath);
|
|
51883
51897
|
}
|
|
51884
51898
|
return null;
|
|
51885
51899
|
}
|
|
51886
|
-
const subpath = rest.replace(/\./g,
|
|
51900
|
+
const subpath = rest.replace(/\./g, path40.sep);
|
|
51887
51901
|
const candidates = [
|
|
51888
|
-
`${
|
|
51889
|
-
|
|
51902
|
+
`${path40.join(baseDir, subpath)}.py`,
|
|
51903
|
+
path40.join(baseDir, subpath, "__init__.py")
|
|
51890
51904
|
];
|
|
51891
51905
|
for (const c of candidates) {
|
|
51892
|
-
if (
|
|
51906
|
+
if (fs18.existsSync(c) && fs18.statSync(c).isFile())
|
|
51893
51907
|
return normalizePath(c);
|
|
51894
51908
|
}
|
|
51895
51909
|
return null;
|
|
51896
51910
|
}
|
|
51897
51911
|
function findGoModule(fromDir) {
|
|
51898
|
-
const resolved =
|
|
51912
|
+
const resolved = path40.resolve(fromDir);
|
|
51899
51913
|
let cur = resolved;
|
|
51900
51914
|
const walked = [];
|
|
51901
51915
|
for (let i = 0;i < 16; i++) {
|
|
@@ -51907,8 +51921,8 @@ function findGoModule(fromDir) {
|
|
|
51907
51921
|
}
|
|
51908
51922
|
walked.push(cur);
|
|
51909
51923
|
try {
|
|
51910
|
-
const goMod =
|
|
51911
|
-
const content =
|
|
51924
|
+
const goMod = path40.join(cur, "go.mod");
|
|
51925
|
+
const content = fs18.readFileSync(goMod, "utf-8");
|
|
51912
51926
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
51913
51927
|
if (moduleMatch) {
|
|
51914
51928
|
const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
|
|
@@ -51918,10 +51932,10 @@ function findGoModule(fromDir) {
|
|
|
51918
51932
|
}
|
|
51919
51933
|
} catch {}
|
|
51920
51934
|
try {
|
|
51921
|
-
|
|
51935
|
+
fs18.accessSync(path40.join(cur, ".git"));
|
|
51922
51936
|
break;
|
|
51923
51937
|
} catch {}
|
|
51924
|
-
const parent =
|
|
51938
|
+
const parent = path40.dirname(cur);
|
|
51925
51939
|
if (parent === cur)
|
|
51926
51940
|
break;
|
|
51927
51941
|
cur = parent;
|
|
@@ -51933,20 +51947,20 @@ function findGoModule(fromDir) {
|
|
|
51933
51947
|
function resolveGoImport(fromDir, importPath) {
|
|
51934
51948
|
let dir = null;
|
|
51935
51949
|
if (importPath.startsWith(".")) {
|
|
51936
|
-
dir =
|
|
51950
|
+
dir = path40.resolve(fromDir, importPath);
|
|
51937
51951
|
} else {
|
|
51938
51952
|
const mod = findGoModule(fromDir);
|
|
51939
51953
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
51940
51954
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
51941
|
-
dir =
|
|
51955
|
+
dir = path40.join(mod.moduleRoot, subpath);
|
|
51942
51956
|
}
|
|
51943
51957
|
}
|
|
51944
51958
|
if (dir === null)
|
|
51945
51959
|
return [];
|
|
51946
|
-
if (!
|
|
51960
|
+
if (!fs18.existsSync(dir) || !fs18.statSync(dir).isDirectory())
|
|
51947
51961
|
return [];
|
|
51948
51962
|
try {
|
|
51949
|
-
return
|
|
51963
|
+
return fs18.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path40.join(dir, f)));
|
|
51950
51964
|
} catch {
|
|
51951
51965
|
return [];
|
|
51952
51966
|
}
|
|
@@ -51966,13 +51980,13 @@ function findTestFilesSync(cwd) {
|
|
|
51966
51980
|
function walk(dir, visitedInodes) {
|
|
51967
51981
|
let entries;
|
|
51968
51982
|
try {
|
|
51969
|
-
entries =
|
|
51983
|
+
entries = fs18.readdirSync(dir, { withFileTypes: true });
|
|
51970
51984
|
} catch {
|
|
51971
51985
|
return;
|
|
51972
51986
|
}
|
|
51973
51987
|
let dirInode;
|
|
51974
51988
|
try {
|
|
51975
|
-
dirInode =
|
|
51989
|
+
dirInode = fs18.statSync(dir).ino;
|
|
51976
51990
|
} catch {
|
|
51977
51991
|
return;
|
|
51978
51992
|
}
|
|
@@ -51985,15 +51999,15 @@ function findTestFilesSync(cwd) {
|
|
|
51985
51999
|
for (const entry of entries) {
|
|
51986
52000
|
if (entry.isDirectory()) {
|
|
51987
52001
|
if (!skipDirs.has(entry.name)) {
|
|
51988
|
-
walk(
|
|
52002
|
+
walk(path40.join(dir, entry.name), visitedInodes);
|
|
51989
52003
|
}
|
|
51990
52004
|
} else if (entry.isFile()) {
|
|
51991
52005
|
const name = entry.name;
|
|
51992
52006
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
51993
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
52007
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path40.sep}tests${path40.sep}`) && name.endsWith(".py");
|
|
51994
52008
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
51995
52009
|
if (isTsTest || isPyTest || isGoTest) {
|
|
51996
|
-
testFiles.push(normalizePath(
|
|
52010
|
+
testFiles.push(normalizePath(path40.join(dir, entry.name)));
|
|
51997
52011
|
}
|
|
51998
52012
|
}
|
|
51999
52013
|
}
|
|
@@ -52018,8 +52032,8 @@ function extractImports3(content) {
|
|
|
52018
52032
|
];
|
|
52019
52033
|
}
|
|
52020
52034
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
52021
|
-
const ext =
|
|
52022
|
-
const testDir =
|
|
52035
|
+
const ext = path40.extname(testFile).toLowerCase();
|
|
52036
|
+
const testDir = path40.dirname(testFile);
|
|
52023
52037
|
function addEdge(source) {
|
|
52024
52038
|
if (!impactMap[source])
|
|
52025
52039
|
impactMap[source] = [];
|
|
@@ -52061,7 +52075,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
52061
52075
|
for (const testFile of testFiles) {
|
|
52062
52076
|
let content;
|
|
52063
52077
|
try {
|
|
52064
|
-
content =
|
|
52078
|
+
content = fs18.readFileSync(testFile, "utf-8");
|
|
52065
52079
|
} catch {
|
|
52066
52080
|
continue;
|
|
52067
52081
|
}
|
|
@@ -52078,10 +52092,10 @@ async function buildImpactMap(cwd) {
|
|
|
52078
52092
|
return impactMap;
|
|
52079
52093
|
}
|
|
52080
52094
|
async function loadImpactMap(cwd, options) {
|
|
52081
|
-
const cachePath =
|
|
52082
|
-
if (
|
|
52095
|
+
const cachePath = path40.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
52096
|
+
if (fs18.existsSync(cachePath)) {
|
|
52083
52097
|
try {
|
|
52084
|
-
const content =
|
|
52098
|
+
const content = fs18.readFileSync(cachePath, "utf-8");
|
|
52085
52099
|
const data = JSON.parse(content);
|
|
52086
52100
|
if (data.map !== null && typeof data.map === "object" && !Array.isArray(data.map)) {
|
|
52087
52101
|
const map3 = data.map;
|
|
@@ -52111,21 +52125,21 @@ async function loadImpactMap(cwd, options) {
|
|
|
52111
52125
|
return _internals25.buildImpactMap(cwd);
|
|
52112
52126
|
}
|
|
52113
52127
|
async function saveImpactMap(cwd, impactMap) {
|
|
52114
|
-
if (!
|
|
52128
|
+
if (!path40.isAbsolute(cwd)) {
|
|
52115
52129
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
52116
52130
|
}
|
|
52117
52131
|
_internals25.validateProjectRoot(cwd);
|
|
52118
|
-
const cacheDir2 =
|
|
52119
|
-
const cachePath =
|
|
52120
|
-
if (!
|
|
52121
|
-
|
|
52132
|
+
const cacheDir2 = path40.join(cwd, ".swarm", "cache");
|
|
52133
|
+
const cachePath = path40.join(cacheDir2, "impact-map.json");
|
|
52134
|
+
if (!fs18.existsSync(cacheDir2)) {
|
|
52135
|
+
fs18.mkdirSync(cacheDir2, { recursive: true });
|
|
52122
52136
|
}
|
|
52123
52137
|
const data = {
|
|
52124
52138
|
generatedAt: new Date().toISOString(),
|
|
52125
52139
|
fileCount: Object.keys(impactMap).length,
|
|
52126
52140
|
map: impactMap
|
|
52127
52141
|
};
|
|
52128
|
-
|
|
52142
|
+
fs18.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
|
|
52129
52143
|
}
|
|
52130
52144
|
async function analyzeImpact(changedFiles, cwd, budget) {
|
|
52131
52145
|
if (!Array.isArray(changedFiles)) {
|
|
@@ -52148,7 +52162,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
52148
52162
|
budgetExceeded = true;
|
|
52149
52163
|
break;
|
|
52150
52164
|
}
|
|
52151
|
-
const normalizedChanged = normalizePath(
|
|
52165
|
+
const normalizedChanged = normalizePath(path40.resolve(changedFile));
|
|
52152
52166
|
const tests = impactMap[normalizedChanged];
|
|
52153
52167
|
if (tests && tests.length > 0) {
|
|
52154
52168
|
for (const test of tests) {
|
|
@@ -52162,13 +52176,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
52162
52176
|
if (budgetExceeded)
|
|
52163
52177
|
break;
|
|
52164
52178
|
} else {
|
|
52165
|
-
const changedDir = normalizePath(
|
|
52166
|
-
const changedInputDir = normalizePath(
|
|
52179
|
+
const changedDir = normalizePath(path40.dirname(normalizedChanged));
|
|
52180
|
+
const changedInputDir = normalizePath(path40.dirname(changedFile));
|
|
52167
52181
|
const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
|
|
52168
52182
|
return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
|
|
52169
52183
|
}).sort(([sourceA], [sourceB]) => {
|
|
52170
|
-
const sourceDirA = normalizePath(
|
|
52171
|
-
const sourceDirB = normalizePath(
|
|
52184
|
+
const sourceDirA = normalizePath(path40.dirname(sourceA));
|
|
52185
|
+
const sourceDirB = normalizePath(path40.dirname(sourceB));
|
|
52172
52186
|
const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
|
|
52173
52187
|
const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
|
|
52174
52188
|
if (exactA !== exactB)
|
|
@@ -52458,16 +52472,16 @@ function detectFlakyTests(allHistory) {
|
|
|
52458
52472
|
var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
|
|
52459
52473
|
|
|
52460
52474
|
// src/test-impact/history-store.ts
|
|
52461
|
-
import
|
|
52462
|
-
import
|
|
52475
|
+
import fs19 from "fs";
|
|
52476
|
+
import path41 from "path";
|
|
52463
52477
|
function getHistoryPath(workingDir) {
|
|
52464
52478
|
if (!workingDir) {
|
|
52465
52479
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
52466
52480
|
}
|
|
52467
|
-
if (!
|
|
52481
|
+
if (!path41.isAbsolute(workingDir)) {
|
|
52468
52482
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
52469
52483
|
}
|
|
52470
|
-
return
|
|
52484
|
+
return path41.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
52471
52485
|
}
|
|
52472
52486
|
function sanitizeErrorMessage(errorMessage) {
|
|
52473
52487
|
if (errorMessage === undefined) {
|
|
@@ -52554,10 +52568,10 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
52554
52568
|
}
|
|
52555
52569
|
}
|
|
52556
52570
|
const historyPath = getHistoryPath(workingDir);
|
|
52557
|
-
const historyDir =
|
|
52571
|
+
const historyDir = path41.dirname(historyPath);
|
|
52558
52572
|
_internals26.validateProjectRoot(workingDir);
|
|
52559
|
-
if (!
|
|
52560
|
-
|
|
52573
|
+
if (!fs19.existsSync(historyDir)) {
|
|
52574
|
+
fs19.mkdirSync(historyDir, { recursive: true });
|
|
52561
52575
|
}
|
|
52562
52576
|
const existingRecords = readAllRecords(historyPath);
|
|
52563
52577
|
const sanitizedRecords = records.map((record3) => ({
|
|
@@ -52590,24 +52604,24 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
52590
52604
|
`)}
|
|
52591
52605
|
`;
|
|
52592
52606
|
const tempPath = `${historyPath}.tmp`;
|
|
52593
|
-
|
|
52594
|
-
|
|
52607
|
+
fs19.writeFileSync(tempPath, content, "utf-8");
|
|
52608
|
+
fs19.renameSync(tempPath, historyPath);
|
|
52595
52609
|
} catch (err) {
|
|
52596
52610
|
try {
|
|
52597
52611
|
const tempPath = `${historyPath}.tmp`;
|
|
52598
|
-
if (
|
|
52599
|
-
|
|
52612
|
+
if (fs19.existsSync(tempPath)) {
|
|
52613
|
+
fs19.unlinkSync(tempPath);
|
|
52600
52614
|
}
|
|
52601
52615
|
} catch {}
|
|
52602
52616
|
throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
|
|
52603
52617
|
}
|
|
52604
52618
|
}
|
|
52605
52619
|
function readAllRecords(historyPath) {
|
|
52606
|
-
if (!
|
|
52620
|
+
if (!fs19.existsSync(historyPath)) {
|
|
52607
52621
|
return [];
|
|
52608
52622
|
}
|
|
52609
52623
|
try {
|
|
52610
|
-
const content =
|
|
52624
|
+
const content = fs19.readFileSync(historyPath, "utf-8");
|
|
52611
52625
|
const lines = content.split(`
|
|
52612
52626
|
`);
|
|
52613
52627
|
const records = [];
|
|
@@ -52649,8 +52663,8 @@ var init_history_store = __esm(() => {
|
|
|
52649
52663
|
});
|
|
52650
52664
|
|
|
52651
52665
|
// src/tools/resolve-working-directory.ts
|
|
52652
|
-
import * as
|
|
52653
|
-
import * as
|
|
52666
|
+
import * as fs20 from "fs";
|
|
52667
|
+
import * as path42 from "path";
|
|
52654
52668
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
52655
52669
|
if (workingDirectory == null || workingDirectory === "") {
|
|
52656
52670
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -52670,18 +52684,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
52670
52684
|
};
|
|
52671
52685
|
}
|
|
52672
52686
|
}
|
|
52673
|
-
const normalizedDir =
|
|
52674
|
-
const pathParts = normalizedDir.split(
|
|
52687
|
+
const normalizedDir = path42.normalize(workingDirectory);
|
|
52688
|
+
const pathParts = normalizedDir.split(path42.sep);
|
|
52675
52689
|
if (pathParts.includes("..")) {
|
|
52676
52690
|
return {
|
|
52677
52691
|
success: false,
|
|
52678
52692
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
52679
52693
|
};
|
|
52680
52694
|
}
|
|
52681
|
-
const resolvedDir =
|
|
52695
|
+
const resolvedDir = path42.resolve(normalizedDir);
|
|
52682
52696
|
let statResult;
|
|
52683
52697
|
try {
|
|
52684
|
-
statResult =
|
|
52698
|
+
statResult = fs20.statSync(resolvedDir);
|
|
52685
52699
|
} catch {
|
|
52686
52700
|
return {
|
|
52687
52701
|
success: false,
|
|
@@ -52694,17 +52708,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
52694
52708
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
52695
52709
|
};
|
|
52696
52710
|
}
|
|
52697
|
-
const resolvedFallback =
|
|
52711
|
+
const resolvedFallback = path42.resolve(fallbackDirectory);
|
|
52698
52712
|
let fallbackExists = false;
|
|
52699
52713
|
try {
|
|
52700
|
-
|
|
52714
|
+
fs20.statSync(resolvedFallback);
|
|
52701
52715
|
fallbackExists = true;
|
|
52702
52716
|
} catch {
|
|
52703
52717
|
fallbackExists = false;
|
|
52704
52718
|
}
|
|
52705
52719
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
52706
52720
|
if (fallbackExists) {
|
|
52707
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
52721
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path42.sep);
|
|
52708
52722
|
if (isSubdirectory) {
|
|
52709
52723
|
return {
|
|
52710
52724
|
success: false,
|
|
@@ -52758,11 +52772,11 @@ var init_registry_backend = __esm(() => {
|
|
|
52758
52772
|
});
|
|
52759
52773
|
|
|
52760
52774
|
// src/lang/backends/typescript.ts
|
|
52761
|
-
import * as
|
|
52762
|
-
import * as
|
|
52775
|
+
import * as fs21 from "fs";
|
|
52776
|
+
import * as path43 from "path";
|
|
52763
52777
|
function readPackageJsonRaw(dir) {
|
|
52764
52778
|
try {
|
|
52765
|
-
const content =
|
|
52779
|
+
const content = fs21.readFileSync(path43.join(dir, "package.json"), "utf-8");
|
|
52766
52780
|
return JSON.parse(content);
|
|
52767
52781
|
} catch {
|
|
52768
52782
|
return null;
|
|
@@ -52981,11 +52995,11 @@ __export(exports_dispatch, {
|
|
|
52981
52995
|
clearDispatchCache: () => clearDispatchCache,
|
|
52982
52996
|
_internals: () => _internals28
|
|
52983
52997
|
});
|
|
52984
|
-
import * as
|
|
52985
|
-
import * as
|
|
52998
|
+
import * as fs22 from "fs";
|
|
52999
|
+
import * as path44 from "path";
|
|
52986
53000
|
function safeReaddirSet(dir) {
|
|
52987
53001
|
try {
|
|
52988
|
-
return new Set(
|
|
53002
|
+
return new Set(fs22.readdirSync(dir));
|
|
52989
53003
|
} catch {
|
|
52990
53004
|
return new Set;
|
|
52991
53005
|
}
|
|
@@ -52999,14 +53013,14 @@ function manifestHash(dir) {
|
|
|
52999
53013
|
if (!entries.has(name))
|
|
53000
53014
|
continue;
|
|
53001
53015
|
try {
|
|
53002
|
-
const stat4 =
|
|
53016
|
+
const stat4 = fs22.statSync(path44.join(dir, name));
|
|
53003
53017
|
parts.push(`${name}:${stat4.size}:${stat4.mtimeMs}:${stat4.ino}`);
|
|
53004
53018
|
} catch {}
|
|
53005
53019
|
}
|
|
53006
53020
|
return parts.join("|");
|
|
53007
53021
|
}
|
|
53008
53022
|
function findManifestRoot(start) {
|
|
53009
|
-
const resolved =
|
|
53023
|
+
const resolved = path44.resolve(start);
|
|
53010
53024
|
const cached3 = manifestRootCache.get(resolved);
|
|
53011
53025
|
if (cached3 !== undefined)
|
|
53012
53026
|
return cached3;
|
|
@@ -53025,7 +53039,7 @@ function findManifestRoot(start) {
|
|
|
53025
53039
|
return cur;
|
|
53026
53040
|
}
|
|
53027
53041
|
}
|
|
53028
|
-
const parent =
|
|
53042
|
+
const parent = path44.dirname(cur);
|
|
53029
53043
|
if (parent === cur)
|
|
53030
53044
|
break;
|
|
53031
53045
|
cur = parent;
|
|
@@ -53134,14 +53148,14 @@ var init_dispatch = __esm(() => {
|
|
|
53134
53148
|
});
|
|
53135
53149
|
|
|
53136
53150
|
// src/tools/test-runner.ts
|
|
53137
|
-
import * as
|
|
53138
|
-
import * as
|
|
53151
|
+
import * as fs23 from "fs";
|
|
53152
|
+
import * as path45 from "path";
|
|
53139
53153
|
async function estimateFanOut(sourceFiles, cwd) {
|
|
53140
53154
|
try {
|
|
53141
53155
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
53142
53156
|
const uniqueTestFiles = new Set;
|
|
53143
53157
|
for (const sourceFile of sourceFiles) {
|
|
53144
|
-
const resolvedPath =
|
|
53158
|
+
const resolvedPath = path45.resolve(cwd, sourceFile);
|
|
53145
53159
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
53146
53160
|
const testFiles = impactMap[normalizedPath];
|
|
53147
53161
|
if (testFiles) {
|
|
@@ -53219,19 +53233,19 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
53219
53233
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
53220
53234
|
}
|
|
53221
53235
|
function detectGoTest(cwd) {
|
|
53222
|
-
return
|
|
53236
|
+
return fs23.existsSync(path45.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
53223
53237
|
}
|
|
53224
53238
|
function detectJavaMaven(cwd) {
|
|
53225
|
-
return
|
|
53239
|
+
return fs23.existsSync(path45.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
53226
53240
|
}
|
|
53227
53241
|
function detectGradle(cwd) {
|
|
53228
|
-
const hasBuildFile =
|
|
53229
|
-
const hasGradlew =
|
|
53242
|
+
const hasBuildFile = fs23.existsSync(path45.join(cwd, "build.gradle")) || fs23.existsSync(path45.join(cwd, "build.gradle.kts"));
|
|
53243
|
+
const hasGradlew = fs23.existsSync(path45.join(cwd, "gradlew")) || fs23.existsSync(path45.join(cwd, "gradlew.bat"));
|
|
53230
53244
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
53231
53245
|
}
|
|
53232
53246
|
function detectDotnetTest(cwd) {
|
|
53233
53247
|
try {
|
|
53234
|
-
const files =
|
|
53248
|
+
const files = fs23.readdirSync(cwd);
|
|
53235
53249
|
const hasCsproj = files.some((f) => f.endsWith(".csproj"));
|
|
53236
53250
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
53237
53251
|
} catch {
|
|
@@ -53239,25 +53253,25 @@ function detectDotnetTest(cwd) {
|
|
|
53239
53253
|
}
|
|
53240
53254
|
}
|
|
53241
53255
|
function detectCTest(cwd) {
|
|
53242
|
-
const hasSource =
|
|
53243
|
-
const hasBuildCache =
|
|
53256
|
+
const hasSource = fs23.existsSync(path45.join(cwd, "CMakeLists.txt"));
|
|
53257
|
+
const hasBuildCache = fs23.existsSync(path45.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path45.join(cwd, "build", "CMakeCache.txt"));
|
|
53244
53258
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
53245
53259
|
}
|
|
53246
53260
|
function detectSwiftTest(cwd) {
|
|
53247
|
-
return
|
|
53261
|
+
return fs23.existsSync(path45.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
53248
53262
|
}
|
|
53249
53263
|
function detectDartTest(cwd) {
|
|
53250
|
-
return
|
|
53264
|
+
return fs23.existsSync(path45.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
53251
53265
|
}
|
|
53252
53266
|
function detectRSpec(cwd) {
|
|
53253
|
-
const hasRSpecFile =
|
|
53254
|
-
const hasGemfile =
|
|
53255
|
-
const hasSpecDir =
|
|
53267
|
+
const hasRSpecFile = fs23.existsSync(path45.join(cwd, ".rspec"));
|
|
53268
|
+
const hasGemfile = fs23.existsSync(path45.join(cwd, "Gemfile"));
|
|
53269
|
+
const hasSpecDir = fs23.existsSync(path45.join(cwd, "spec"));
|
|
53256
53270
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
53257
53271
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
53258
53272
|
}
|
|
53259
53273
|
function detectMinitest(cwd) {
|
|
53260
|
-
return
|
|
53274
|
+
return fs23.existsSync(path45.join(cwd, "test")) && (fs23.existsSync(path45.join(cwd, "Gemfile")) || fs23.existsSync(path45.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
53261
53275
|
}
|
|
53262
53276
|
async function detectTestFrameworkViaDispatch(cwd) {
|
|
53263
53277
|
try {
|
|
@@ -53319,9 +53333,9 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
53319
53333
|
async function detectTestFramework(cwd) {
|
|
53320
53334
|
const baseDir = cwd;
|
|
53321
53335
|
try {
|
|
53322
|
-
const packageJsonPath =
|
|
53323
|
-
if (
|
|
53324
|
-
const content =
|
|
53336
|
+
const packageJsonPath = path45.join(baseDir, "package.json");
|
|
53337
|
+
if (fs23.existsSync(packageJsonPath)) {
|
|
53338
|
+
const content = fs23.readFileSync(packageJsonPath, "utf-8");
|
|
53325
53339
|
const pkg = JSON.parse(content);
|
|
53326
53340
|
const _deps = pkg.dependencies || {};
|
|
53327
53341
|
const devDeps = pkg.devDependencies || {};
|
|
@@ -53340,38 +53354,38 @@ async function detectTestFramework(cwd) {
|
|
|
53340
53354
|
return "jest";
|
|
53341
53355
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
53342
53356
|
return "mocha";
|
|
53343
|
-
if (
|
|
53357
|
+
if (fs23.existsSync(path45.join(baseDir, "bun.lockb")) || fs23.existsSync(path45.join(baseDir, "bun.lock"))) {
|
|
53344
53358
|
if (scripts.test?.includes("bun"))
|
|
53345
53359
|
return "bun";
|
|
53346
53360
|
}
|
|
53347
53361
|
}
|
|
53348
53362
|
} catch {}
|
|
53349
53363
|
try {
|
|
53350
|
-
const pyprojectTomlPath =
|
|
53351
|
-
const setupCfgPath =
|
|
53352
|
-
const requirementsTxtPath =
|
|
53353
|
-
if (
|
|
53354
|
-
const content =
|
|
53364
|
+
const pyprojectTomlPath = path45.join(baseDir, "pyproject.toml");
|
|
53365
|
+
const setupCfgPath = path45.join(baseDir, "setup.cfg");
|
|
53366
|
+
const requirementsTxtPath = path45.join(baseDir, "requirements.txt");
|
|
53367
|
+
if (fs23.existsSync(pyprojectTomlPath)) {
|
|
53368
|
+
const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
|
|
53355
53369
|
if (content.includes("[tool.pytest"))
|
|
53356
53370
|
return "pytest";
|
|
53357
53371
|
if (content.includes("pytest"))
|
|
53358
53372
|
return "pytest";
|
|
53359
53373
|
}
|
|
53360
|
-
if (
|
|
53361
|
-
const content =
|
|
53374
|
+
if (fs23.existsSync(setupCfgPath)) {
|
|
53375
|
+
const content = fs23.readFileSync(setupCfgPath, "utf-8");
|
|
53362
53376
|
if (content.includes("[pytest]"))
|
|
53363
53377
|
return "pytest";
|
|
53364
53378
|
}
|
|
53365
|
-
if (
|
|
53366
|
-
const content =
|
|
53379
|
+
if (fs23.existsSync(requirementsTxtPath)) {
|
|
53380
|
+
const content = fs23.readFileSync(requirementsTxtPath, "utf-8");
|
|
53367
53381
|
if (content.includes("pytest"))
|
|
53368
53382
|
return "pytest";
|
|
53369
53383
|
}
|
|
53370
53384
|
} catch {}
|
|
53371
53385
|
try {
|
|
53372
|
-
const cargoTomlPath =
|
|
53373
|
-
if (
|
|
53374
|
-
const content =
|
|
53386
|
+
const cargoTomlPath = path45.join(baseDir, "Cargo.toml");
|
|
53387
|
+
if (fs23.existsSync(cargoTomlPath)) {
|
|
53388
|
+
const content = fs23.readFileSync(cargoTomlPath, "utf-8");
|
|
53375
53389
|
if (content.includes("[dev-dependencies]")) {
|
|
53376
53390
|
if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
|
|
53377
53391
|
return "cargo";
|
|
@@ -53380,10 +53394,10 @@ async function detectTestFramework(cwd) {
|
|
|
53380
53394
|
}
|
|
53381
53395
|
} catch {}
|
|
53382
53396
|
try {
|
|
53383
|
-
const pesterConfigPath =
|
|
53384
|
-
const pesterConfigJsonPath =
|
|
53385
|
-
const pesterPs1Path =
|
|
53386
|
-
if (
|
|
53397
|
+
const pesterConfigPath = path45.join(baseDir, "pester.config.ps1");
|
|
53398
|
+
const pesterConfigJsonPath = path45.join(baseDir, "pester.config.ps1.json");
|
|
53399
|
+
const pesterPs1Path = path45.join(baseDir, "tests.ps1");
|
|
53400
|
+
if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
|
|
53387
53401
|
return "pester";
|
|
53388
53402
|
}
|
|
53389
53403
|
} catch {}
|
|
@@ -53411,12 +53425,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
53411
53425
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
53412
53426
|
}
|
|
53413
53427
|
function resolveWorkspacePath(file3, workingDir) {
|
|
53414
|
-
return
|
|
53428
|
+
return path45.isAbsolute(file3) ? path45.resolve(file3) : path45.resolve(workingDir, file3);
|
|
53415
53429
|
}
|
|
53416
53430
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
53417
53431
|
if (!preferRelative)
|
|
53418
53432
|
return absolutePath;
|
|
53419
|
-
return
|
|
53433
|
+
return path45.relative(workingDir, absolutePath);
|
|
53420
53434
|
}
|
|
53421
53435
|
function dedupePush(target, value) {
|
|
53422
53436
|
if (!target.includes(value)) {
|
|
@@ -53453,18 +53467,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
53453
53467
|
}
|
|
53454
53468
|
}
|
|
53455
53469
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
53456
|
-
const relativeDir =
|
|
53470
|
+
const relativeDir = path45.dirname(relativePath);
|
|
53457
53471
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
53458
53472
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
53459
|
-
const rootDir =
|
|
53460
|
-
return nestedRelativeDir ? [rootDir,
|
|
53473
|
+
const rootDir = path45.join(workingDir, dirName);
|
|
53474
|
+
return nestedRelativeDir ? [rootDir, path45.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
53461
53475
|
});
|
|
53462
53476
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
53463
53477
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
53464
|
-
directories.push(
|
|
53478
|
+
directories.push(path45.join(workingDir, "src/test/java", path45.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
53465
53479
|
}
|
|
53466
53480
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
53467
|
-
directories.push(
|
|
53481
|
+
directories.push(path45.join(workingDir, "src/test/kotlin", path45.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
53468
53482
|
}
|
|
53469
53483
|
return [...new Set(directories)];
|
|
53470
53484
|
}
|
|
@@ -53492,23 +53506,23 @@ function isLanguageSpecificTestFile(basename7) {
|
|
|
53492
53506
|
}
|
|
53493
53507
|
function isConventionTestFilePath(filePath) {
|
|
53494
53508
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
53495
|
-
const basename7 =
|
|
53509
|
+
const basename7 = path45.basename(filePath);
|
|
53496
53510
|
return hasCompoundTestExtension(basename7) || basename7.includes(".spec.") || basename7.includes(".test.") || isLanguageSpecificTestFile(basename7) || isTestDirectoryPath(normalizedPath);
|
|
53497
53511
|
}
|
|
53498
53512
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
53499
53513
|
const testFiles = [];
|
|
53500
53514
|
for (const file3 of sourceFiles) {
|
|
53501
53515
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
53502
|
-
const relativeFile =
|
|
53503
|
-
const basename7 =
|
|
53504
|
-
const dirname23 =
|
|
53505
|
-
const preferRelativeOutput = !
|
|
53516
|
+
const relativeFile = path45.relative(workingDir, absoluteFile);
|
|
53517
|
+
const basename7 = path45.basename(absoluteFile);
|
|
53518
|
+
const dirname23 = path45.dirname(absoluteFile);
|
|
53519
|
+
const preferRelativeOutput = !path45.isAbsolute(file3);
|
|
53506
53520
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
53507
53521
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
53508
53522
|
continue;
|
|
53509
53523
|
}
|
|
53510
53524
|
const nameWithoutExt = basename7.replace(/\.[^.]+$/, "");
|
|
53511
|
-
const ext =
|
|
53525
|
+
const ext = path45.extname(basename7);
|
|
53512
53526
|
const genericTestNames = [
|
|
53513
53527
|
`${nameWithoutExt}.spec${ext}`,
|
|
53514
53528
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -53517,7 +53531,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
53517
53531
|
const colocatedCandidates = [
|
|
53518
53532
|
...genericTestNames,
|
|
53519
53533
|
...languageSpecificTestNames
|
|
53520
|
-
].map((candidateName) =>
|
|
53534
|
+
].map((candidateName) => path45.join(dirname23, candidateName));
|
|
53521
53535
|
const testDirectoryNames = [
|
|
53522
53536
|
basename7,
|
|
53523
53537
|
...genericTestNames,
|
|
@@ -53526,11 +53540,11 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
53526
53540
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
53527
53541
|
const possibleTestFiles = [
|
|
53528
53542
|
...colocatedCandidates,
|
|
53529
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
53530
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
53543
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path45.join(dirname23, dirName, candidateName))),
|
|
53544
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path45.join(candidateDir, candidateName)))
|
|
53531
53545
|
];
|
|
53532
53546
|
for (const testFile of possibleTestFiles) {
|
|
53533
|
-
if (
|
|
53547
|
+
if (fs23.existsSync(testFile)) {
|
|
53534
53548
|
dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
|
|
53535
53549
|
}
|
|
53536
53550
|
}
|
|
@@ -53547,8 +53561,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53547
53561
|
for (const testFile of candidateTestFiles) {
|
|
53548
53562
|
try {
|
|
53549
53563
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
53550
|
-
const content =
|
|
53551
|
-
const testDir =
|
|
53564
|
+
const content = fs23.readFileSync(absoluteTestFile, "utf-8");
|
|
53565
|
+
const testDir = path45.dirname(absoluteTestFile);
|
|
53552
53566
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
53553
53567
|
let match;
|
|
53554
53568
|
match = importRegex.exec(content);
|
|
@@ -53556,8 +53570,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53556
53570
|
const importPath = match[1];
|
|
53557
53571
|
let resolvedImport;
|
|
53558
53572
|
if (importPath.startsWith(".")) {
|
|
53559
|
-
resolvedImport =
|
|
53560
|
-
const existingExt =
|
|
53573
|
+
resolvedImport = path45.resolve(testDir, importPath);
|
|
53574
|
+
const existingExt = path45.extname(resolvedImport);
|
|
53561
53575
|
if (!existingExt) {
|
|
53562
53576
|
for (const extToTry of [
|
|
53563
53577
|
".ts",
|
|
@@ -53568,7 +53582,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53568
53582
|
".cjs"
|
|
53569
53583
|
]) {
|
|
53570
53584
|
const withExt = resolvedImport + extToTry;
|
|
53571
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
53585
|
+
if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
|
|
53572
53586
|
resolvedImport = withExt;
|
|
53573
53587
|
break;
|
|
53574
53588
|
}
|
|
@@ -53577,12 +53591,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53577
53591
|
} else {
|
|
53578
53592
|
continue;
|
|
53579
53593
|
}
|
|
53580
|
-
const importBasename =
|
|
53581
|
-
const importDir =
|
|
53594
|
+
const importBasename = path45.basename(resolvedImport, path45.extname(resolvedImport));
|
|
53595
|
+
const importDir = path45.dirname(resolvedImport);
|
|
53582
53596
|
for (const sourceFile of absoluteSourceFiles) {
|
|
53583
|
-
const sourceDir =
|
|
53584
|
-
const sourceBasename =
|
|
53585
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
53597
|
+
const sourceDir = path45.dirname(sourceFile);
|
|
53598
|
+
const sourceBasename = path45.basename(sourceFile, path45.extname(sourceFile));
|
|
53599
|
+
const isRelatedDir = importDir === sourceDir || importDir === path45.join(sourceDir, "__tests__") || importDir === path45.join(sourceDir, "tests") || importDir === path45.join(sourceDir, "test") || importDir === path45.join(sourceDir, "spec");
|
|
53586
53600
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
53587
53601
|
dedupePush(testFiles, testFile);
|
|
53588
53602
|
break;
|
|
@@ -53595,8 +53609,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53595
53609
|
while (match !== null) {
|
|
53596
53610
|
const importPath = match[1];
|
|
53597
53611
|
if (importPath.startsWith(".")) {
|
|
53598
|
-
let resolvedImport =
|
|
53599
|
-
const existingExt =
|
|
53612
|
+
let resolvedImport = path45.resolve(testDir, importPath);
|
|
53613
|
+
const existingExt = path45.extname(resolvedImport);
|
|
53600
53614
|
if (!existingExt) {
|
|
53601
53615
|
for (const extToTry of [
|
|
53602
53616
|
".ts",
|
|
@@ -53607,18 +53621,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
53607
53621
|
".cjs"
|
|
53608
53622
|
]) {
|
|
53609
53623
|
const withExt = resolvedImport + extToTry;
|
|
53610
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
53624
|
+
if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
|
|
53611
53625
|
resolvedImport = withExt;
|
|
53612
53626
|
break;
|
|
53613
53627
|
}
|
|
53614
53628
|
}
|
|
53615
53629
|
}
|
|
53616
|
-
const importDir =
|
|
53617
|
-
const importBasename =
|
|
53630
|
+
const importDir = path45.dirname(resolvedImport);
|
|
53631
|
+
const importBasename = path45.basename(resolvedImport, path45.extname(resolvedImport));
|
|
53618
53632
|
for (const sourceFile of absoluteSourceFiles) {
|
|
53619
|
-
const sourceDir =
|
|
53620
|
-
const sourceBasename =
|
|
53621
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
53633
|
+
const sourceDir = path45.dirname(sourceFile);
|
|
53634
|
+
const sourceBasename = path45.basename(sourceFile, path45.extname(sourceFile));
|
|
53635
|
+
const isRelatedDir = importDir === sourceDir || importDir === path45.join(sourceDir, "__tests__") || importDir === path45.join(sourceDir, "tests") || importDir === path45.join(sourceDir, "test") || importDir === path45.join(sourceDir, "spec");
|
|
53622
53636
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
53623
53637
|
dedupePush(testFiles, testFile);
|
|
53624
53638
|
break;
|
|
@@ -53728,8 +53742,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
53728
53742
|
return ["mvn", "test"];
|
|
53729
53743
|
case "gradle": {
|
|
53730
53744
|
const isWindows = process.platform === "win32";
|
|
53731
|
-
const hasGradlewBat =
|
|
53732
|
-
const hasGradlew =
|
|
53745
|
+
const hasGradlewBat = fs23.existsSync(path45.join(baseDir, "gradlew.bat"));
|
|
53746
|
+
const hasGradlew = fs23.existsSync(path45.join(baseDir, "gradlew"));
|
|
53733
53747
|
if (hasGradlewBat && isWindows)
|
|
53734
53748
|
return ["gradlew.bat", "test"];
|
|
53735
53749
|
if (hasGradlew)
|
|
@@ -53746,7 +53760,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
|
53746
53760
|
"cmake-build-release",
|
|
53747
53761
|
"out"
|
|
53748
53762
|
];
|
|
53749
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
53763
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path45.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
53750
53764
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
53751
53765
|
}
|
|
53752
53766
|
case "swift-test":
|
|
@@ -54178,13 +54192,13 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
54178
54192
|
};
|
|
54179
54193
|
}
|
|
54180
54194
|
const startTime = Date.now();
|
|
54181
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
54195
|
+
const vitestJsonOutputPath = framework === "vitest" ? path45.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
54182
54196
|
try {
|
|
54183
54197
|
if (vitestJsonOutputPath) {
|
|
54184
54198
|
try {
|
|
54185
|
-
|
|
54186
|
-
if (
|
|
54187
|
-
|
|
54199
|
+
fs23.mkdirSync(path45.dirname(vitestJsonOutputPath), { recursive: true });
|
|
54200
|
+
if (fs23.existsSync(vitestJsonOutputPath)) {
|
|
54201
|
+
fs23.unlinkSync(vitestJsonOutputPath);
|
|
54188
54202
|
}
|
|
54189
54203
|
} catch {}
|
|
54190
54204
|
}
|
|
@@ -54193,9 +54207,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
54193
54207
|
stderr: "pipe",
|
|
54194
54208
|
cwd
|
|
54195
54209
|
});
|
|
54196
|
-
const timeoutPromise = new Promise((
|
|
54210
|
+
const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
|
|
54197
54211
|
proc.kill();
|
|
54198
|
-
|
|
54212
|
+
resolve16(-1);
|
|
54199
54213
|
}, timeout_ms));
|
|
54200
54214
|
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
54201
54215
|
Promise.race([proc.exited, timeoutPromise]),
|
|
@@ -54210,8 +54224,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
54210
54224
|
}
|
|
54211
54225
|
if (vitestJsonOutputPath) {
|
|
54212
54226
|
try {
|
|
54213
|
-
if (
|
|
54214
|
-
const vitestJsonOutput =
|
|
54227
|
+
if (fs23.existsSync(vitestJsonOutputPath)) {
|
|
54228
|
+
const vitestJsonOutput = fs23.readFileSync(vitestJsonOutputPath, "utf-8");
|
|
54215
54229
|
if (vitestJsonOutput.trim().length > 0) {
|
|
54216
54230
|
output += (output ? `
|
|
54217
54231
|
` : "") + vitestJsonOutput;
|
|
@@ -54298,10 +54312,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
54298
54312
|
}
|
|
54299
54313
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
54300
54314
|
const normalized = testFile.replace(/\\/g, "/");
|
|
54301
|
-
if (!
|
|
54315
|
+
if (!path45.isAbsolute(testFile))
|
|
54302
54316
|
return normalized;
|
|
54303
|
-
const relative9 =
|
|
54304
|
-
if (relative9.startsWith("..") ||
|
|
54317
|
+
const relative9 = path45.relative(workingDir, testFile);
|
|
54318
|
+
if (relative9.startsWith("..") || path45.isAbsolute(relative9)) {
|
|
54305
54319
|
return normalized;
|
|
54306
54320
|
}
|
|
54307
54321
|
return relative9.replace(/\\/g, "/");
|
|
@@ -54639,7 +54653,7 @@ var init_test_runner = __esm(() => {
|
|
|
54639
54653
|
const sourceFiles = args.files.filter((file3) => {
|
|
54640
54654
|
if (directTestFiles.includes(file3))
|
|
54641
54655
|
return false;
|
|
54642
|
-
const ext =
|
|
54656
|
+
const ext = path45.extname(file3).toLowerCase();
|
|
54643
54657
|
return SOURCE_EXTENSIONS.has(ext);
|
|
54644
54658
|
});
|
|
54645
54659
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -54685,7 +54699,7 @@ var init_test_runner = __esm(() => {
|
|
|
54685
54699
|
if (isConventionTestFilePath(f)) {
|
|
54686
54700
|
return false;
|
|
54687
54701
|
}
|
|
54688
|
-
const ext =
|
|
54702
|
+
const ext = path45.extname(f).toLowerCase();
|
|
54689
54703
|
return SOURCE_EXTENSIONS.has(ext);
|
|
54690
54704
|
});
|
|
54691
54705
|
if (sourceFiles.length === 0) {
|
|
@@ -54735,7 +54749,7 @@ var init_test_runner = __esm(() => {
|
|
|
54735
54749
|
if (isConventionTestFilePath(f)) {
|
|
54736
54750
|
return false;
|
|
54737
54751
|
}
|
|
54738
|
-
const ext =
|
|
54752
|
+
const ext = path45.extname(f).toLowerCase();
|
|
54739
54753
|
return SOURCE_EXTENSIONS.has(ext);
|
|
54740
54754
|
});
|
|
54741
54755
|
if (sourceFiles.length === 0) {
|
|
@@ -54787,8 +54801,8 @@ var init_test_runner = __esm(() => {
|
|
|
54787
54801
|
}
|
|
54788
54802
|
if (impactResult.impactedTests.length > 0) {
|
|
54789
54803
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
54790
|
-
const relativePath =
|
|
54791
|
-
return
|
|
54804
|
+
const relativePath = path45.relative(workingDir, absPath);
|
|
54805
|
+
return path45.isAbsolute(relativePath) ? absPath : relativePath;
|
|
54792
54806
|
});
|
|
54793
54807
|
} else {
|
|
54794
54808
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -54863,8 +54877,8 @@ var init_test_runner = __esm(() => {
|
|
|
54863
54877
|
});
|
|
54864
54878
|
|
|
54865
54879
|
// src/services/preflight-service.ts
|
|
54866
|
-
import * as
|
|
54867
|
-
import * as
|
|
54880
|
+
import * as fs24 from "fs";
|
|
54881
|
+
import * as path46 from "path";
|
|
54868
54882
|
function validateDirectoryPath(dir) {
|
|
54869
54883
|
if (!dir || typeof dir !== "string") {
|
|
54870
54884
|
throw new Error("Directory path is required");
|
|
@@ -54872,8 +54886,8 @@ function validateDirectoryPath(dir) {
|
|
|
54872
54886
|
if (dir.includes("..")) {
|
|
54873
54887
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
54874
54888
|
}
|
|
54875
|
-
const normalized =
|
|
54876
|
-
const absolutePath =
|
|
54889
|
+
const normalized = path46.normalize(dir);
|
|
54890
|
+
const absolutePath = path46.isAbsolute(normalized) ? normalized : path46.resolve(normalized);
|
|
54877
54891
|
return absolutePath;
|
|
54878
54892
|
}
|
|
54879
54893
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -54896,9 +54910,9 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
54896
54910
|
}
|
|
54897
54911
|
function getPackageVersion(dir) {
|
|
54898
54912
|
try {
|
|
54899
|
-
const packagePath =
|
|
54900
|
-
if (
|
|
54901
|
-
const content =
|
|
54913
|
+
const packagePath = path46.join(dir, "package.json");
|
|
54914
|
+
if (fs24.existsSync(packagePath)) {
|
|
54915
|
+
const content = fs24.readFileSync(packagePath, "utf-8");
|
|
54902
54916
|
const pkg = JSON.parse(content);
|
|
54903
54917
|
return pkg.version ?? null;
|
|
54904
54918
|
}
|
|
@@ -54907,9 +54921,9 @@ function getPackageVersion(dir) {
|
|
|
54907
54921
|
}
|
|
54908
54922
|
function getChangelogVersion(dir) {
|
|
54909
54923
|
try {
|
|
54910
|
-
const changelogPath =
|
|
54911
|
-
if (
|
|
54912
|
-
const content =
|
|
54924
|
+
const changelogPath = path46.join(dir, "CHANGELOG.md");
|
|
54925
|
+
if (fs24.existsSync(changelogPath)) {
|
|
54926
|
+
const content = fs24.readFileSync(changelogPath, "utf-8");
|
|
54913
54927
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
54914
54928
|
if (match) {
|
|
54915
54929
|
return match[1];
|
|
@@ -54921,10 +54935,10 @@ function getChangelogVersion(dir) {
|
|
|
54921
54935
|
function getVersionFileVersion(dir) {
|
|
54922
54936
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
54923
54937
|
for (const file3 of possibleFiles) {
|
|
54924
|
-
const filePath =
|
|
54925
|
-
if (
|
|
54938
|
+
const filePath = path46.join(dir, file3);
|
|
54939
|
+
if (fs24.existsSync(filePath)) {
|
|
54926
54940
|
try {
|
|
54927
|
-
const content =
|
|
54941
|
+
const content = fs24.readFileSync(filePath, "utf-8").trim();
|
|
54928
54942
|
const match = content.match(/(\d+\.\d+\.\d+)/);
|
|
54929
54943
|
if (match) {
|
|
54930
54944
|
return match[1];
|
|
@@ -55263,8 +55277,8 @@ async function runEvidenceCheck(dir) {
|
|
|
55263
55277
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
55264
55278
|
const startTime = Date.now();
|
|
55265
55279
|
try {
|
|
55266
|
-
const specPath =
|
|
55267
|
-
if (!
|
|
55280
|
+
const specPath = path46.join(dir, ".swarm", "spec.md");
|
|
55281
|
+
if (!fs24.existsSync(specPath)) {
|
|
55268
55282
|
return {
|
|
55269
55283
|
type: "req_coverage",
|
|
55270
55284
|
status: "skip",
|
|
@@ -55742,13 +55756,13 @@ class CircuitBreaker {
|
|
|
55742
55756
|
if (this.config.callTimeoutMs <= 0) {
|
|
55743
55757
|
return fn();
|
|
55744
55758
|
}
|
|
55745
|
-
return new Promise((
|
|
55759
|
+
return new Promise((resolve17, reject) => {
|
|
55746
55760
|
const timeout = setTimeout(() => {
|
|
55747
55761
|
reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
|
|
55748
55762
|
}, this.config.callTimeoutMs);
|
|
55749
55763
|
fn().then((result) => {
|
|
55750
55764
|
clearTimeout(timeout);
|
|
55751
|
-
|
|
55765
|
+
resolve17(result);
|
|
55752
55766
|
}).catch((error93) => {
|
|
55753
55767
|
clearTimeout(timeout);
|
|
55754
55768
|
reject(error93);
|
|
@@ -56035,7 +56049,7 @@ var init_queue = __esm(() => {
|
|
|
56035
56049
|
|
|
56036
56050
|
// src/background/worker.ts
|
|
56037
56051
|
function sleep(ms) {
|
|
56038
|
-
return new Promise((
|
|
56052
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
56039
56053
|
}
|
|
56040
56054
|
|
|
56041
56055
|
class WorkerManager {
|
|
@@ -56380,8 +56394,8 @@ var init_manager3 = __esm(() => {
|
|
|
56380
56394
|
});
|
|
56381
56395
|
|
|
56382
56396
|
// src/commands/reset.ts
|
|
56383
|
-
import * as
|
|
56384
|
-
import * as
|
|
56397
|
+
import * as fs25 from "fs";
|
|
56398
|
+
import * as path47 from "path";
|
|
56385
56399
|
async function handleResetCommand(directory, args) {
|
|
56386
56400
|
const hasConfirm = args.includes("--confirm");
|
|
56387
56401
|
if (!hasConfirm) {
|
|
@@ -56409,8 +56423,8 @@ async function handleResetCommand(directory, args) {
|
|
|
56409
56423
|
for (const filename of filesToReset) {
|
|
56410
56424
|
try {
|
|
56411
56425
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
56412
|
-
if (
|
|
56413
|
-
|
|
56426
|
+
if (fs25.existsSync(resolvedPath)) {
|
|
56427
|
+
fs25.unlinkSync(resolvedPath);
|
|
56414
56428
|
results.push(`- \u2705 Deleted ${filename}`);
|
|
56415
56429
|
} else {
|
|
56416
56430
|
results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
|
|
@@ -56421,9 +56435,9 @@ async function handleResetCommand(directory, args) {
|
|
|
56421
56435
|
}
|
|
56422
56436
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
56423
56437
|
try {
|
|
56424
|
-
const rootPath =
|
|
56425
|
-
if (
|
|
56426
|
-
|
|
56438
|
+
const rootPath = path47.join(directory, filename);
|
|
56439
|
+
if (fs25.existsSync(rootPath)) {
|
|
56440
|
+
fs25.unlinkSync(rootPath);
|
|
56427
56441
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
56428
56442
|
}
|
|
56429
56443
|
} catch {}
|
|
@@ -56436,8 +56450,8 @@ async function handleResetCommand(directory, args) {
|
|
|
56436
56450
|
}
|
|
56437
56451
|
try {
|
|
56438
56452
|
const summariesPath = validateSwarmPath(directory, "summaries");
|
|
56439
|
-
if (
|
|
56440
|
-
|
|
56453
|
+
if (fs25.existsSync(summariesPath)) {
|
|
56454
|
+
fs25.rmSync(summariesPath, { recursive: true, force: true });
|
|
56441
56455
|
results.push("- \u2705 Deleted summaries/ directory");
|
|
56442
56456
|
} else {
|
|
56443
56457
|
results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
|
|
@@ -56460,14 +56474,14 @@ var init_reset = __esm(() => {
|
|
|
56460
56474
|
});
|
|
56461
56475
|
|
|
56462
56476
|
// src/commands/reset-session.ts
|
|
56463
|
-
import * as
|
|
56464
|
-
import * as
|
|
56477
|
+
import * as fs26 from "fs";
|
|
56478
|
+
import * as path48 from "path";
|
|
56465
56479
|
async function handleResetSessionCommand(directory, _args) {
|
|
56466
56480
|
const results = [];
|
|
56467
56481
|
try {
|
|
56468
56482
|
const statePath = validateSwarmPath(directory, "session/state.json");
|
|
56469
|
-
if (
|
|
56470
|
-
|
|
56483
|
+
if (fs26.existsSync(statePath)) {
|
|
56484
|
+
fs26.unlinkSync(statePath);
|
|
56471
56485
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
56472
56486
|
} else {
|
|
56473
56487
|
results.push("\u23ED\uFE0F state.json not found (already clean)");
|
|
@@ -56476,15 +56490,15 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
56476
56490
|
results.push("\u274C Failed to delete state.json");
|
|
56477
56491
|
}
|
|
56478
56492
|
try {
|
|
56479
|
-
const sessionDir =
|
|
56480
|
-
if (
|
|
56481
|
-
const files =
|
|
56493
|
+
const sessionDir = path48.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
56494
|
+
if (fs26.existsSync(sessionDir)) {
|
|
56495
|
+
const files = fs26.readdirSync(sessionDir);
|
|
56482
56496
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
56483
56497
|
let deletedCount = 0;
|
|
56484
56498
|
for (const file3 of otherFiles) {
|
|
56485
|
-
const filePath =
|
|
56486
|
-
if (
|
|
56487
|
-
|
|
56499
|
+
const filePath = path48.join(sessionDir, file3);
|
|
56500
|
+
if (fs26.lstatSync(filePath).isFile()) {
|
|
56501
|
+
fs26.unlinkSync(filePath);
|
|
56488
56502
|
deletedCount++;
|
|
56489
56503
|
}
|
|
56490
56504
|
}
|
|
@@ -56514,7 +56528,7 @@ var init_reset_session = __esm(() => {
|
|
|
56514
56528
|
});
|
|
56515
56529
|
|
|
56516
56530
|
// src/summaries/manager.ts
|
|
56517
|
-
import * as
|
|
56531
|
+
import * as path49 from "path";
|
|
56518
56532
|
function sanitizeSummaryId(id) {
|
|
56519
56533
|
if (!id || id.length === 0) {
|
|
56520
56534
|
throw new Error("Invalid summary ID: empty string");
|
|
@@ -56537,7 +56551,7 @@ function sanitizeSummaryId(id) {
|
|
|
56537
56551
|
}
|
|
56538
56552
|
async function loadFullOutput(directory, id) {
|
|
56539
56553
|
const sanitizedId = sanitizeSummaryId(id);
|
|
56540
|
-
const relativePath =
|
|
56554
|
+
const relativePath = path49.join("summaries", `${sanitizedId}.json`);
|
|
56541
56555
|
validateSwarmPath(directory, relativePath);
|
|
56542
56556
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
56543
56557
|
if (content === null) {
|
|
@@ -56599,18 +56613,18 @@ var init_retrieve = __esm(() => {
|
|
|
56599
56613
|
});
|
|
56600
56614
|
|
|
56601
56615
|
// src/commands/rollback.ts
|
|
56602
|
-
import * as
|
|
56603
|
-
import * as
|
|
56616
|
+
import * as fs27 from "fs";
|
|
56617
|
+
import * as path50 from "path";
|
|
56604
56618
|
async function handleRollbackCommand(directory, args) {
|
|
56605
56619
|
const phaseArg = args[0];
|
|
56606
56620
|
if (!phaseArg) {
|
|
56607
56621
|
const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
56608
|
-
if (!
|
|
56622
|
+
if (!fs27.existsSync(manifestPath2)) {
|
|
56609
56623
|
return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
|
|
56610
56624
|
}
|
|
56611
56625
|
let manifest2;
|
|
56612
56626
|
try {
|
|
56613
|
-
manifest2 = JSON.parse(
|
|
56627
|
+
manifest2 = JSON.parse(fs27.readFileSync(manifestPath2, "utf-8"));
|
|
56614
56628
|
} catch {
|
|
56615
56629
|
return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
|
|
56616
56630
|
}
|
|
@@ -56632,12 +56646,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56632
56646
|
return "Error: Phase number must be a positive integer.";
|
|
56633
56647
|
}
|
|
56634
56648
|
const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
56635
|
-
if (!
|
|
56649
|
+
if (!fs27.existsSync(manifestPath)) {
|
|
56636
56650
|
return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
|
|
56637
56651
|
}
|
|
56638
56652
|
let manifest;
|
|
56639
56653
|
try {
|
|
56640
|
-
manifest = JSON.parse(
|
|
56654
|
+
manifest = JSON.parse(fs27.readFileSync(manifestPath, "utf-8"));
|
|
56641
56655
|
} catch {
|
|
56642
56656
|
return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
|
|
56643
56657
|
}
|
|
@@ -56647,10 +56661,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56647
56661
|
return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
|
|
56648
56662
|
}
|
|
56649
56663
|
const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
|
|
56650
|
-
if (!
|
|
56664
|
+
if (!fs27.existsSync(checkpointDir)) {
|
|
56651
56665
|
return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
|
|
56652
56666
|
}
|
|
56653
|
-
const checkpointFiles =
|
|
56667
|
+
const checkpointFiles = fs27.readdirSync(checkpointDir);
|
|
56654
56668
|
if (checkpointFiles.length === 0) {
|
|
56655
56669
|
return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
|
|
56656
56670
|
}
|
|
@@ -56665,10 +56679,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56665
56679
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
56666
56680
|
continue;
|
|
56667
56681
|
}
|
|
56668
|
-
const src =
|
|
56669
|
-
const dest =
|
|
56682
|
+
const src = path50.join(checkpointDir, file3);
|
|
56683
|
+
const dest = path50.join(swarmDir, file3);
|
|
56670
56684
|
try {
|
|
56671
|
-
|
|
56685
|
+
fs27.cpSync(src, dest, { recursive: true, force: true });
|
|
56672
56686
|
successes.push(file3);
|
|
56673
56687
|
} catch (error93) {
|
|
56674
56688
|
failures.push({ file: file3, error: error93.message });
|
|
@@ -56685,14 +56699,14 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56685
56699
|
].join(`
|
|
56686
56700
|
`);
|
|
56687
56701
|
}
|
|
56688
|
-
const existingLedgerPath =
|
|
56689
|
-
if (
|
|
56690
|
-
|
|
56702
|
+
const existingLedgerPath = path50.join(swarmDir, "plan-ledger.jsonl");
|
|
56703
|
+
if (fs27.existsSync(existingLedgerPath)) {
|
|
56704
|
+
fs27.unlinkSync(existingLedgerPath);
|
|
56691
56705
|
}
|
|
56692
56706
|
try {
|
|
56693
|
-
const planJsonPath =
|
|
56694
|
-
if (
|
|
56695
|
-
const planRaw =
|
|
56707
|
+
const planJsonPath = path50.join(swarmDir, "plan.json");
|
|
56708
|
+
if (fs27.existsSync(planJsonPath)) {
|
|
56709
|
+
const planRaw = fs27.readFileSync(planJsonPath, "utf-8");
|
|
56696
56710
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
56697
56711
|
const planId = derivePlanId(plan);
|
|
56698
56712
|
const planHash = computePlanHash(plan);
|
|
@@ -56719,7 +56733,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
56719
56733
|
timestamp: new Date().toISOString()
|
|
56720
56734
|
};
|
|
56721
56735
|
try {
|
|
56722
|
-
|
|
56736
|
+
fs27.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
56723
56737
|
`);
|
|
56724
56738
|
} catch (error93) {
|
|
56725
56739
|
console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
|
|
@@ -56780,11 +56794,11 @@ Ensure this is a git repository with commit history.`;
|
|
|
56780
56794
|
const report = reportLines.filter(Boolean).join(`
|
|
56781
56795
|
`);
|
|
56782
56796
|
try {
|
|
56783
|
-
const
|
|
56784
|
-
const
|
|
56785
|
-
const reportPath =
|
|
56786
|
-
await
|
|
56787
|
-
await
|
|
56797
|
+
const fs28 = await import("fs/promises");
|
|
56798
|
+
const path51 = await import("path");
|
|
56799
|
+
const reportPath = path51.join(directory, ".swarm", "simulate-report.md");
|
|
56800
|
+
await fs28.mkdir(path51.dirname(reportPath), { recursive: true });
|
|
56801
|
+
await fs28.writeFile(reportPath, report, "utf-8");
|
|
56788
56802
|
} catch (err) {
|
|
56789
56803
|
const writeErr = err instanceof Error ? err.message : String(err);
|
|
56790
56804
|
warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
|
|
@@ -56806,15 +56820,15 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
56806
56820
|
}
|
|
56807
56821
|
|
|
56808
56822
|
// src/turbo/lean/state.ts
|
|
56809
|
-
import * as
|
|
56810
|
-
import * as
|
|
56823
|
+
import * as fs28 from "fs";
|
|
56824
|
+
import * as path51 from "path";
|
|
56811
56825
|
function nowISO2() {
|
|
56812
56826
|
return new Date().toISOString();
|
|
56813
56827
|
}
|
|
56814
56828
|
function ensureSwarmDir2(directory) {
|
|
56815
|
-
const swarmDir =
|
|
56816
|
-
if (!
|
|
56817
|
-
|
|
56829
|
+
const swarmDir = path51.resolve(directory, ".swarm");
|
|
56830
|
+
if (!fs28.existsSync(swarmDir)) {
|
|
56831
|
+
fs28.mkdirSync(swarmDir, { recursive: true });
|
|
56818
56832
|
}
|
|
56819
56833
|
return swarmDir;
|
|
56820
56834
|
}
|
|
@@ -56856,17 +56870,17 @@ function markStateUnreadable2(directory, reason) {
|
|
|
56856
56870
|
}
|
|
56857
56871
|
function readPersisted2(directory) {
|
|
56858
56872
|
try {
|
|
56859
|
-
const filePath =
|
|
56860
|
-
if (!
|
|
56873
|
+
const filePath = path51.join(directory, ".swarm", STATE_FILE2);
|
|
56874
|
+
if (!fs28.existsSync(filePath)) {
|
|
56861
56875
|
const seed = emptyPersisted2();
|
|
56862
56876
|
try {
|
|
56863
56877
|
ensureSwarmDir2(directory);
|
|
56864
|
-
|
|
56878
|
+
fs28.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
|
|
56865
56879
|
`, "utf-8");
|
|
56866
56880
|
} catch {}
|
|
56867
56881
|
return seed;
|
|
56868
56882
|
}
|
|
56869
|
-
const raw =
|
|
56883
|
+
const raw = fs28.readFileSync(filePath, "utf-8");
|
|
56870
56884
|
const parsed = JSON.parse(raw);
|
|
56871
56885
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
56872
56886
|
markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -56892,7 +56906,7 @@ function writePersisted2(directory, persisted) {
|
|
|
56892
56906
|
let payload;
|
|
56893
56907
|
try {
|
|
56894
56908
|
ensureSwarmDir2(directory);
|
|
56895
|
-
filePath =
|
|
56909
|
+
filePath = path51.join(directory, ".swarm", STATE_FILE2);
|
|
56896
56910
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
56897
56911
|
persisted.updatedAt = nowISO2();
|
|
56898
56912
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -56903,14 +56917,14 @@ function writePersisted2(directory, persisted) {
|
|
|
56903
56917
|
throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
|
|
56904
56918
|
}
|
|
56905
56919
|
try {
|
|
56906
|
-
|
|
56907
|
-
|
|
56920
|
+
fs28.writeFileSync(tmpPath, payload, "utf-8");
|
|
56921
|
+
fs28.renameSync(tmpPath, filePath);
|
|
56908
56922
|
} catch (error93) {
|
|
56909
56923
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
56910
56924
|
error(`[turbo/lean/state] Failed to persist ${STATE_FILE2} atomically: ${msg}`);
|
|
56911
56925
|
try {
|
|
56912
|
-
if (
|
|
56913
|
-
|
|
56926
|
+
if (fs28.existsSync(tmpPath)) {
|
|
56927
|
+
fs28.unlinkSync(tmpPath);
|
|
56914
56928
|
}
|
|
56915
56929
|
} catch {}
|
|
56916
56930
|
throw new Error(`Lean Turbo state persistence failed: ${msg}`);
|
|
@@ -57019,10 +57033,10 @@ var init_context_budget_service = __esm(() => {
|
|
|
57019
57033
|
|
|
57020
57034
|
// src/services/status-service.ts
|
|
57021
57035
|
import * as fsSync2 from "fs";
|
|
57022
|
-
import * as
|
|
57036
|
+
import * as path52 from "path";
|
|
57023
57037
|
function readSpecStalenessSnapshot(directory) {
|
|
57024
57038
|
try {
|
|
57025
|
-
const p =
|
|
57039
|
+
const p = path52.join(directory, ".swarm", "spec-staleness.json");
|
|
57026
57040
|
if (!fsSync2.existsSync(p))
|
|
57027
57041
|
return { stale: false };
|
|
57028
57042
|
const raw = fsSync2.readFileSync(p, "utf-8");
|
|
@@ -57547,8 +57561,8 @@ var init_write_retro2 = __esm(() => {
|
|
|
57547
57561
|
});
|
|
57548
57562
|
|
|
57549
57563
|
// src/commands/command-dispatch.ts
|
|
57550
|
-
import
|
|
57551
|
-
import
|
|
57564
|
+
import fs29 from "fs";
|
|
57565
|
+
import path53 from "path";
|
|
57552
57566
|
function normalizeSwarmCommandInput(command, argumentText) {
|
|
57553
57567
|
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
57554
57568
|
return { isSwarmCommand: false, tokens: [] };
|
|
@@ -57584,11 +57598,11 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
|
57584
57598
|
`);
|
|
57585
57599
|
}
|
|
57586
57600
|
function maybeMarkFirstRun(directory) {
|
|
57587
|
-
const sentinelPath =
|
|
57601
|
+
const sentinelPath = path53.join(directory, ".swarm", ".first-run-complete");
|
|
57588
57602
|
try {
|
|
57589
|
-
const swarmDir =
|
|
57590
|
-
|
|
57591
|
-
|
|
57603
|
+
const swarmDir = path53.join(directory, ".swarm");
|
|
57604
|
+
fs29.mkdirSync(swarmDir, { recursive: true });
|
|
57605
|
+
fs29.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
57592
57606
|
`, { flag: "wx" });
|
|
57593
57607
|
return true;
|
|
57594
57608
|
} catch {
|
|
@@ -58323,24 +58337,24 @@ function validateAliases() {
|
|
|
58323
58337
|
}
|
|
58324
58338
|
aliasTargets.get(target).push(name);
|
|
58325
58339
|
const visited = new Set;
|
|
58326
|
-
const
|
|
58340
|
+
const path54 = [];
|
|
58327
58341
|
let current = target;
|
|
58328
58342
|
while (current) {
|
|
58329
58343
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
58330
58344
|
if (!currentEntry)
|
|
58331
58345
|
break;
|
|
58332
58346
|
if (visited.has(current)) {
|
|
58333
|
-
const cycleStart =
|
|
58347
|
+
const cycleStart = path54.indexOf(current);
|
|
58334
58348
|
const fullChain = [
|
|
58335
58349
|
name,
|
|
58336
|
-
...
|
|
58350
|
+
...path54.slice(0, cycleStart > 0 ? cycleStart : path54.length),
|
|
58337
58351
|
current
|
|
58338
58352
|
].join(" \u2192 ");
|
|
58339
58353
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
58340
58354
|
break;
|
|
58341
58355
|
}
|
|
58342
58356
|
visited.add(current);
|
|
58343
|
-
|
|
58357
|
+
path54.push(current);
|
|
58344
58358
|
current = currentEntry.aliasOf || "";
|
|
58345
58359
|
}
|
|
58346
58360
|
}
|
|
@@ -58951,68 +58965,68 @@ init_package();
|
|
|
58951
58965
|
init_registry();
|
|
58952
58966
|
init_cache_paths();
|
|
58953
58967
|
init_constants();
|
|
58954
|
-
import * as
|
|
58968
|
+
import * as fs30 from "fs";
|
|
58955
58969
|
import * as os8 from "os";
|
|
58956
|
-
import * as
|
|
58970
|
+
import * as path54 from "path";
|
|
58957
58971
|
var { version: version5 } = package_default;
|
|
58958
58972
|
var CONFIG_DIR = getPluginConfigDir();
|
|
58959
|
-
var OPENCODE_CONFIG_PATH =
|
|
58960
|
-
var PLUGIN_CONFIG_PATH =
|
|
58961
|
-
var PROMPTS_DIR =
|
|
58973
|
+
var OPENCODE_CONFIG_PATH = path54.join(CONFIG_DIR, "opencode.json");
|
|
58974
|
+
var PLUGIN_CONFIG_PATH = path54.join(CONFIG_DIR, "opencode-swarm.json");
|
|
58975
|
+
var PROMPTS_DIR = path54.join(CONFIG_DIR, "opencode-swarm");
|
|
58962
58976
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
58963
58977
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
58964
58978
|
function isSafeCachePath(p) {
|
|
58965
|
-
const resolved =
|
|
58966
|
-
const home =
|
|
58979
|
+
const resolved = path54.resolve(p);
|
|
58980
|
+
const home = path54.resolve(os8.homedir());
|
|
58967
58981
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
58968
58982
|
return false;
|
|
58969
58983
|
}
|
|
58970
|
-
const segments = resolved.split(
|
|
58984
|
+
const segments = resolved.split(path54.sep).filter((s) => s.length > 0);
|
|
58971
58985
|
if (segments.length < 4) {
|
|
58972
58986
|
return false;
|
|
58973
58987
|
}
|
|
58974
|
-
const leaf =
|
|
58988
|
+
const leaf = path54.basename(resolved);
|
|
58975
58989
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
58976
58990
|
return false;
|
|
58977
58991
|
}
|
|
58978
|
-
const parent =
|
|
58992
|
+
const parent = path54.basename(path54.dirname(resolved));
|
|
58979
58993
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
58980
58994
|
return false;
|
|
58981
58995
|
}
|
|
58982
|
-
const grandparent =
|
|
58996
|
+
const grandparent = path54.basename(path54.dirname(path54.dirname(resolved)));
|
|
58983
58997
|
if (grandparent !== "opencode") {
|
|
58984
58998
|
return false;
|
|
58985
58999
|
}
|
|
58986
59000
|
return true;
|
|
58987
59001
|
}
|
|
58988
59002
|
function isSafeLockFilePath(p) {
|
|
58989
|
-
const resolved =
|
|
58990
|
-
const home =
|
|
59003
|
+
const resolved = path54.resolve(p);
|
|
59004
|
+
const home = path54.resolve(os8.homedir());
|
|
58991
59005
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
58992
59006
|
return false;
|
|
58993
59007
|
}
|
|
58994
|
-
const segments = resolved.split(
|
|
59008
|
+
const segments = resolved.split(path54.sep).filter((s) => s.length > 0);
|
|
58995
59009
|
if (segments.length < 4) {
|
|
58996
59010
|
return false;
|
|
58997
59011
|
}
|
|
58998
|
-
const leaf =
|
|
59012
|
+
const leaf = path54.basename(resolved);
|
|
58999
59013
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
59000
59014
|
return false;
|
|
59001
59015
|
}
|
|
59002
|
-
const parent =
|
|
59016
|
+
const parent = path54.basename(path54.dirname(resolved));
|
|
59003
59017
|
if (parent !== "opencode") {
|
|
59004
59018
|
return false;
|
|
59005
59019
|
}
|
|
59006
59020
|
return true;
|
|
59007
59021
|
}
|
|
59008
59022
|
function ensureDir(dir) {
|
|
59009
|
-
if (!
|
|
59010
|
-
|
|
59023
|
+
if (!fs30.existsSync(dir)) {
|
|
59024
|
+
fs30.mkdirSync(dir, { recursive: true });
|
|
59011
59025
|
}
|
|
59012
59026
|
}
|
|
59013
59027
|
function loadJson(filepath) {
|
|
59014
59028
|
try {
|
|
59015
|
-
const content =
|
|
59029
|
+
const content = fs30.readFileSync(filepath, "utf-8");
|
|
59016
59030
|
const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
|
|
59017
59031
|
return JSON.parse(stripped);
|
|
59018
59032
|
} catch {
|
|
@@ -59020,14 +59034,14 @@ function loadJson(filepath) {
|
|
|
59020
59034
|
}
|
|
59021
59035
|
}
|
|
59022
59036
|
function saveJson(filepath, data) {
|
|
59023
|
-
|
|
59037
|
+
fs30.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
|
|
59024
59038
|
`, "utf-8");
|
|
59025
59039
|
}
|
|
59026
59040
|
function writeProjectConfigIfMissing(cwd) {
|
|
59027
59041
|
try {
|
|
59028
|
-
const opencodeDir =
|
|
59029
|
-
const projectConfigPath =
|
|
59030
|
-
if (
|
|
59042
|
+
const opencodeDir = path54.join(cwd, ".opencode");
|
|
59043
|
+
const projectConfigPath = path54.join(opencodeDir, "opencode-swarm.json");
|
|
59044
|
+
if (fs30.existsSync(projectConfigPath)) {
|
|
59031
59045
|
return;
|
|
59032
59046
|
}
|
|
59033
59047
|
ensureDir(opencodeDir);
|
|
@@ -59043,7 +59057,7 @@ async function install() {
|
|
|
59043
59057
|
`);
|
|
59044
59058
|
ensureDir(CONFIG_DIR);
|
|
59045
59059
|
ensureDir(PROMPTS_DIR);
|
|
59046
|
-
const LEGACY_CONFIG_PATH =
|
|
59060
|
+
const LEGACY_CONFIG_PATH = path54.join(CONFIG_DIR, "config.json");
|
|
59047
59061
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
59048
59062
|
if (!opencodeConfig) {
|
|
59049
59063
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|
|
@@ -59090,7 +59104,7 @@ async function install() {
|
|
|
59090
59104
|
console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
|
|
59091
59105
|
${failed}`);
|
|
59092
59106
|
}
|
|
59093
|
-
if (!
|
|
59107
|
+
if (!fs30.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
59094
59108
|
const defaultConfig = {
|
|
59095
59109
|
agents: { ...DEFAULT_AGENT_CONFIGS },
|
|
59096
59110
|
max_iterations: 5
|
|
@@ -59169,14 +59183,14 @@ function evictPluginCaches() {
|
|
|
59169
59183
|
const cleared = [];
|
|
59170
59184
|
const failed = [];
|
|
59171
59185
|
for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
|
|
59172
|
-
if (!
|
|
59186
|
+
if (!fs30.existsSync(cachePath))
|
|
59173
59187
|
continue;
|
|
59174
59188
|
if (!isSafeCachePath(cachePath)) {
|
|
59175
59189
|
failed.push(`${cachePath} (refused: failed safety check)`);
|
|
59176
59190
|
continue;
|
|
59177
59191
|
}
|
|
59178
59192
|
try {
|
|
59179
|
-
|
|
59193
|
+
fs30.rmSync(cachePath, { recursive: true, force: true });
|
|
59180
59194
|
cleared.push(cachePath);
|
|
59181
59195
|
} catch (err) {
|
|
59182
59196
|
failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -59188,14 +59202,14 @@ function evictLockFiles() {
|
|
|
59188
59202
|
const cleared = [];
|
|
59189
59203
|
const failed = [];
|
|
59190
59204
|
for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
|
|
59191
|
-
if (!
|
|
59205
|
+
if (!fs30.existsSync(lockPath))
|
|
59192
59206
|
continue;
|
|
59193
59207
|
if (!isSafeLockFilePath(lockPath)) {
|
|
59194
59208
|
failed.push(`${lockPath} (refused: failed safety check)`);
|
|
59195
59209
|
continue;
|
|
59196
59210
|
}
|
|
59197
59211
|
try {
|
|
59198
|
-
|
|
59212
|
+
fs30.unlinkSync(lockPath);
|
|
59199
59213
|
cleared.push(lockPath);
|
|
59200
59214
|
} catch (err) {
|
|
59201
59215
|
const code = err?.code;
|
|
@@ -59214,7 +59228,7 @@ async function uninstall() {
|
|
|
59214
59228
|
`);
|
|
59215
59229
|
const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
59216
59230
|
if (!opencodeConfig) {
|
|
59217
|
-
if (
|
|
59231
|
+
if (fs30.existsSync(OPENCODE_CONFIG_PATH)) {
|
|
59218
59232
|
console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
|
|
59219
59233
|
return 1;
|
|
59220
59234
|
} else {
|
|
@@ -59246,13 +59260,13 @@ async function uninstall() {
|
|
|
59246
59260
|
console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
|
|
59247
59261
|
if (process.argv.includes("--clean")) {
|
|
59248
59262
|
let cleaned = false;
|
|
59249
|
-
if (
|
|
59250
|
-
|
|
59263
|
+
if (fs30.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
59264
|
+
fs30.unlinkSync(PLUGIN_CONFIG_PATH);
|
|
59251
59265
|
console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
|
|
59252
59266
|
cleaned = true;
|
|
59253
59267
|
}
|
|
59254
|
-
if (
|
|
59255
|
-
|
|
59268
|
+
if (fs30.existsSync(PROMPTS_DIR)) {
|
|
59269
|
+
fs30.rmSync(PROMPTS_DIR, { recursive: true });
|
|
59256
59270
|
console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
|
|
59257
59271
|
cleaned = true;
|
|
59258
59272
|
}
|