opencode-swarm 7.18.3 → 7.19.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/README.md +22 -35
- package/dist/cli/index.js +755 -480
- package/dist/commands/command-dispatch.d.ts +33 -0
- package/dist/commands/council.d.ts +1 -1
- package/dist/commands/doctor.d.ts +2 -7
- package/dist/commands/index.d.ts +11 -2
- package/dist/commands/registry.d.ts +0 -1
- package/dist/commands/tool-policy.d.ts +6 -0
- package/dist/config/plan-schema.d.ts +8 -0
- package/dist/evidence/lock.d.ts +1 -1
- package/dist/gate-evidence.d.ts +2 -2
- package/dist/hooks/guardrails.d.ts +21 -0
- package/dist/hooks/system-enhancer.d.ts +19 -0
- package/dist/index.js +2318 -2370
- package/dist/plan/ledger.d.ts +8 -3
- package/dist/plan/manager.d.ts +52 -0
- package/dist/services/config-doctor.d.ts +2 -15
- package/dist/services/evidence-service.d.ts +8 -0
- package/dist/services/plan-service.d.ts +16 -0
- package/dist/services/status-service.d.ts +8 -0
- package/dist/state/agent-run-context.d.ts +4 -4
- package/dist/state.d.ts +13 -8
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/save-plan.d.ts +19 -0
- package/dist/tools/swarm-command.d.ts +3 -0
- package/dist/tools/tool-names.d.ts +1 -1
- package/dist/tools/update-task-status.d.ts +1 -1
- package/dist/tools/write-final-council-evidence.d.ts +0 -12
- package/dist/types/events.d.ts +21 -1
- package/package.json +1 -1
- package/dist/parallel/runtime-config.d.ts +0 -11
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.
|
|
37
|
+
version: "7.19.1",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -14893,6 +14893,17 @@ function applyEventToPlan(plan, event) {
|
|
|
14893
14893
|
return plan;
|
|
14894
14894
|
case "task_added":
|
|
14895
14895
|
return plan;
|
|
14896
|
+
case "task_removed":
|
|
14897
|
+
if (event.task_id) {
|
|
14898
|
+
for (const phase of plan.phases) {
|
|
14899
|
+
const idx = phase.tasks.findIndex((t) => t.id === event.task_id);
|
|
14900
|
+
if (idx !== -1) {
|
|
14901
|
+
phase.tasks.splice(idx, 1);
|
|
14902
|
+
break;
|
|
14903
|
+
}
|
|
14904
|
+
}
|
|
14905
|
+
}
|
|
14906
|
+
return plan;
|
|
14896
14907
|
case "task_updated":
|
|
14897
14908
|
return plan;
|
|
14898
14909
|
case "plan_rebuilt":
|
|
@@ -15000,7 +15011,7 @@ async function loadLastApprovedPlan(directory, expectedPlanId) {
|
|
|
15000
15011
|
}
|
|
15001
15012
|
return null;
|
|
15002
15013
|
}
|
|
15003
|
-
var LEDGER_SCHEMA_VERSION = "1.
|
|
15014
|
+
var LEDGER_SCHEMA_VERSION = "1.1.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
|
|
15004
15015
|
var init_ledger = __esm(() => {
|
|
15005
15016
|
init_plan_schema();
|
|
15006
15017
|
LedgerStaleWriterError = class LedgerStaleWriterError extends Error {
|
|
@@ -15290,7 +15301,13 @@ async function loadPlan(directory) {
|
|
|
15290
15301
|
const planMdContent2 = await readSwarmFileAsync(directory, "plan.md");
|
|
15291
15302
|
if (planMdContent2 !== null) {
|
|
15292
15303
|
const migrated = migrateLegacyPlan(planMdContent2);
|
|
15293
|
-
await
|
|
15304
|
+
const { removedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, migrated, "load_plan_migration_from_md", "migrate legacy plan.md to plan.json");
|
|
15305
|
+
if (removedCount > 0) {
|
|
15306
|
+
migrated._midLoadRemovals = {
|
|
15307
|
+
count: removedCount,
|
|
15308
|
+
source: "load_plan_migration_from_md"
|
|
15309
|
+
};
|
|
15310
|
+
}
|
|
15294
15311
|
return migrated;
|
|
15295
15312
|
}
|
|
15296
15313
|
}
|
|
@@ -15319,7 +15336,13 @@ async function loadPlan(directory) {
|
|
|
15319
15336
|
try {
|
|
15320
15337
|
const rebuilt = await replayFromLedger(directory);
|
|
15321
15338
|
if (rebuilt) {
|
|
15322
|
-
await
|
|
15339
|
+
const { removedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, rebuilt, "load_plan_rebuild_from_ledger", "rebuild plan from ledger replay");
|
|
15340
|
+
if (removedCount > 0) {
|
|
15341
|
+
rebuilt._midLoadRemovals = {
|
|
15342
|
+
count: removedCount,
|
|
15343
|
+
source: "load_plan_rebuild_from_ledger"
|
|
15344
|
+
};
|
|
15345
|
+
}
|
|
15323
15346
|
return rebuilt;
|
|
15324
15347
|
}
|
|
15325
15348
|
try {
|
|
@@ -15333,7 +15356,13 @@ async function loadPlan(directory) {
|
|
|
15333
15356
|
if (approved) {
|
|
15334
15357
|
const approvedPhase = approved.approval && typeof approved.approval === "object" && "phase" in approved.approval ? approved.approval.phase : undefined;
|
|
15335
15358
|
warn(`[loadPlan] Ledger replay returned no plan \u2014 recovered from critic-approved snapshot seq=${approved.seq} timestamp=${approved.timestamp} (approval phase=${approvedPhase ?? "unknown"}). This may roll the plan back to an earlier phase \u2014 verify before continuing.`);
|
|
15336
|
-
await
|
|
15359
|
+
const { removedCount: snapshotRemovedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, approved.plan, "load_plan_recovery_from_approved_snapshot", "restore from critic-approved snapshot");
|
|
15360
|
+
if (snapshotRemovedCount > 0) {
|
|
15361
|
+
approved.plan._midLoadRemovals = {
|
|
15362
|
+
count: snapshotRemovedCount,
|
|
15363
|
+
source: "load_plan_recovery_from_approved_snapshot"
|
|
15364
|
+
};
|
|
15365
|
+
}
|
|
15337
15366
|
try {
|
|
15338
15367
|
await takeSnapshotEvent(directory, approved.plan, {
|
|
15339
15368
|
source: "recovery_from_approved_snapshot",
|
|
@@ -15354,6 +15383,28 @@ async function loadPlan(directory) {
|
|
|
15354
15383
|
}
|
|
15355
15384
|
return null;
|
|
15356
15385
|
}
|
|
15386
|
+
async function savePlanWithAutoAcknowledgedRemovals(directory, plan, source, reason, options) {
|
|
15387
|
+
const existing = await _internals3.loadPlanJsonOnly(directory);
|
|
15388
|
+
const newIds = new Set;
|
|
15389
|
+
for (const phase of plan.phases) {
|
|
15390
|
+
for (const task of phase.tasks)
|
|
15391
|
+
newIds.add(task.id);
|
|
15392
|
+
}
|
|
15393
|
+
const removedIds = [];
|
|
15394
|
+
if (existing) {
|
|
15395
|
+
for (const phase of existing.phases) {
|
|
15396
|
+
for (const task of phase.tasks) {
|
|
15397
|
+
if (!newIds.has(task.id))
|
|
15398
|
+
removedIds.push(task.id);
|
|
15399
|
+
}
|
|
15400
|
+
}
|
|
15401
|
+
}
|
|
15402
|
+
await savePlan(directory, plan, {
|
|
15403
|
+
...options ?? {},
|
|
15404
|
+
acknowledged_removals: { ids: removedIds, reason, source }
|
|
15405
|
+
});
|
|
15406
|
+
return { removedCount: removedIds.length };
|
|
15407
|
+
}
|
|
15357
15408
|
async function savePlan(directory, plan, options) {
|
|
15358
15409
|
if (directory === null || directory === undefined || typeof directory !== "string" || directory.trim().length === 0) {
|
|
15359
15410
|
throw new Error(`Invalid directory: directory must be a non-empty string`);
|
|
@@ -15490,6 +15541,73 @@ async function savePlan(directory, plan, options) {
|
|
|
15490
15541
|
oldTaskMap.set(task.id, { phase: task.phase, status: task.status });
|
|
15491
15542
|
}
|
|
15492
15543
|
}
|
|
15544
|
+
const newTaskIds = new Set;
|
|
15545
|
+
for (const phase of validated.phases) {
|
|
15546
|
+
for (const task of phase.tasks)
|
|
15547
|
+
newTaskIds.add(task.id);
|
|
15548
|
+
}
|
|
15549
|
+
const missingTasks = [];
|
|
15550
|
+
for (const [id, info] of oldTaskMap.entries()) {
|
|
15551
|
+
if (!newTaskIds.has(id)) {
|
|
15552
|
+
missingTasks.push({ id, phase: info.phase, status: info.status });
|
|
15553
|
+
}
|
|
15554
|
+
}
|
|
15555
|
+
const ack = options?.acknowledged_removals;
|
|
15556
|
+
if (missingTasks.length > 0) {
|
|
15557
|
+
if (!ack) {
|
|
15558
|
+
throw new PlanTaskRemovalNotAcknowledgedError(missingTasks);
|
|
15559
|
+
}
|
|
15560
|
+
if (typeof ack.reason !== "string" || ack.reason.trim().length === 0) {
|
|
15561
|
+
throw new Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.reason must be a non-empty string.");
|
|
15562
|
+
}
|
|
15563
|
+
if (typeof ack.source !== "string" || ack.source.trim().length === 0) {
|
|
15564
|
+
throw new Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.source must be a non-empty string.");
|
|
15565
|
+
}
|
|
15566
|
+
const ackSet = new Set(ack.ids);
|
|
15567
|
+
const missingIdsSet = new Set(missingTasks.map((t) => t.id));
|
|
15568
|
+
const unacked = missingTasks.filter((t) => !ackSet.has(t.id));
|
|
15569
|
+
if (unacked.length > 0) {
|
|
15570
|
+
throw new PlanTaskRemovalNotAcknowledgedError(unacked);
|
|
15571
|
+
}
|
|
15572
|
+
for (const id of ack.ids) {
|
|
15573
|
+
if (!missingIdsSet.has(id)) {
|
|
15574
|
+
throw new Error(`PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals contains "${id}" but that task is not missing from the plan.`);
|
|
15575
|
+
}
|
|
15576
|
+
}
|
|
15577
|
+
try {
|
|
15578
|
+
for (const missing of missingTasks) {
|
|
15579
|
+
const eventInput = {
|
|
15580
|
+
plan_id: derivePlanId(validated),
|
|
15581
|
+
event_type: "task_removed",
|
|
15582
|
+
task_id: missing.id,
|
|
15583
|
+
phase_id: missing.phase,
|
|
15584
|
+
from_status: missing.status,
|
|
15585
|
+
source: ack.source,
|
|
15586
|
+
payload: { reason: ack.reason, source: ack.source }
|
|
15587
|
+
};
|
|
15588
|
+
const capturedTaskId = missing.id;
|
|
15589
|
+
await retryCasWithBackoff(directory, eventInput, {
|
|
15590
|
+
expectedHash: currentHash,
|
|
15591
|
+
planHashAfter: hashAfter,
|
|
15592
|
+
verifyValid: async () => {
|
|
15593
|
+
const onDisk = await _internals3.loadPlanJsonOnly(directory);
|
|
15594
|
+
if (!onDisk)
|
|
15595
|
+
return true;
|
|
15596
|
+
for (const p of onDisk.phases) {
|
|
15597
|
+
if (p.tasks.some((x) => x.id === capturedTaskId))
|
|
15598
|
+
return true;
|
|
15599
|
+
}
|
|
15600
|
+
return false;
|
|
15601
|
+
}
|
|
15602
|
+
});
|
|
15603
|
+
}
|
|
15604
|
+
} catch (error49) {
|
|
15605
|
+
if (error49 instanceof LedgerStaleWriterError) {
|
|
15606
|
+
throw new PlanConcurrentModificationError(`Concurrent plan modification detected after retries: ${error49.message}. Please retry the operation.`);
|
|
15607
|
+
}
|
|
15608
|
+
throw error49;
|
|
15609
|
+
}
|
|
15610
|
+
}
|
|
15493
15611
|
try {
|
|
15494
15612
|
for (const phase of validated.phases) {
|
|
15495
15613
|
for (const task of phase.tasks) {
|
|
@@ -15890,7 +16008,7 @@ function migrateLegacyPlan(planContent, swarmId) {
|
|
|
15890
16008
|
};
|
|
15891
16009
|
return plan;
|
|
15892
16010
|
}
|
|
15893
|
-
var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals3, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
|
|
16011
|
+
var PlanConcurrentModificationError, PlanTaskRemovalNotAcknowledgedError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals3, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
|
|
15894
16012
|
var init_manager = __esm(() => {
|
|
15895
16013
|
init_plan_schema();
|
|
15896
16014
|
init_utils2();
|
|
@@ -15905,6 +16023,15 @@ var init_manager = __esm(() => {
|
|
|
15905
16023
|
this.name = "PlanConcurrentModificationError";
|
|
15906
16024
|
}
|
|
15907
16025
|
};
|
|
16026
|
+
PlanTaskRemovalNotAcknowledgedError = class PlanTaskRemovalNotAcknowledgedError extends Error {
|
|
16027
|
+
missingTasks;
|
|
16028
|
+
constructor(missingTasks) {
|
|
16029
|
+
const idList = missingTasks.map((t) => `${t.id}(${t.status})`).join(", ");
|
|
16030
|
+
super(`PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: the following tasks were present in the prior plan but missing from the new save: ${idList}. Pass acknowledged_removals.ids covering all missing task IDs with a non-empty reason to proceed.`);
|
|
16031
|
+
this.name = "PlanTaskRemovalNotAcknowledgedError";
|
|
16032
|
+
this.missingTasks = missingTasks;
|
|
16033
|
+
}
|
|
16034
|
+
};
|
|
15908
16035
|
startupLedgerCheckedWorkspaces = new Set;
|
|
15909
16036
|
recoveryMutexes = new Map;
|
|
15910
16037
|
_internals3 = {
|
|
@@ -16064,6 +16191,7 @@ var init_tool_names = __esm(() => {
|
|
|
16064
16191
|
"skill_improve",
|
|
16065
16192
|
"spec_write",
|
|
16066
16193
|
"knowledge_ack",
|
|
16194
|
+
"swarm_command",
|
|
16067
16195
|
"lean_turbo_plan_lanes",
|
|
16068
16196
|
"lean_turbo_acquire_locks",
|
|
16069
16197
|
"lean_turbo_runner_status",
|
|
@@ -16316,6 +16444,7 @@ var init_constants = __esm(() => {
|
|
|
16316
16444
|
"skill_inspect",
|
|
16317
16445
|
"skill_improve",
|
|
16318
16446
|
"knowledge_ack",
|
|
16447
|
+
"swarm_command",
|
|
16319
16448
|
"lean_turbo_plan_lanes",
|
|
16320
16449
|
"lean_turbo_acquire_locks",
|
|
16321
16450
|
"lean_turbo_runner_status",
|
|
@@ -16337,7 +16466,8 @@ var init_constants = __esm(() => {
|
|
|
16337
16466
|
"todo_extract",
|
|
16338
16467
|
"doc_scan",
|
|
16339
16468
|
"knowledge_recall",
|
|
16340
|
-
"repo_map"
|
|
16469
|
+
"repo_map",
|
|
16470
|
+
"swarm_command"
|
|
16341
16471
|
],
|
|
16342
16472
|
coder: [
|
|
16343
16473
|
"diff",
|
|
@@ -16351,7 +16481,8 @@ var init_constants = __esm(() => {
|
|
|
16351
16481
|
"syntax_check",
|
|
16352
16482
|
"knowledge_add",
|
|
16353
16483
|
"knowledge_recall",
|
|
16354
|
-
"repo_map"
|
|
16484
|
+
"repo_map",
|
|
16485
|
+
"swarm_command"
|
|
16355
16486
|
],
|
|
16356
16487
|
test_engineer: [
|
|
16357
16488
|
"test_runner",
|
|
@@ -16366,7 +16497,8 @@ var init_constants = __esm(() => {
|
|
|
16366
16497
|
"pkg_audit",
|
|
16367
16498
|
"build_check",
|
|
16368
16499
|
"syntax_check",
|
|
16369
|
-
"search"
|
|
16500
|
+
"search",
|
|
16501
|
+
"swarm_command"
|
|
16370
16502
|
],
|
|
16371
16503
|
sme: [
|
|
16372
16504
|
"complexity_hotspots",
|
|
@@ -16377,7 +16509,8 @@ var init_constants = __esm(() => {
|
|
|
16377
16509
|
"schema_drift",
|
|
16378
16510
|
"search",
|
|
16379
16511
|
"symbols",
|
|
16380
|
-
"knowledge_recall"
|
|
16512
|
+
"knowledge_recall",
|
|
16513
|
+
"swarm_command"
|
|
16381
16514
|
],
|
|
16382
16515
|
reviewer: [
|
|
16383
16516
|
"diff",
|
|
@@ -16399,7 +16532,8 @@ var init_constants = __esm(() => {
|
|
|
16399
16532
|
"search",
|
|
16400
16533
|
"batch_symbols",
|
|
16401
16534
|
"suggest_patch",
|
|
16402
|
-
"repo_map"
|
|
16535
|
+
"repo_map",
|
|
16536
|
+
"swarm_command"
|
|
16403
16537
|
],
|
|
16404
16538
|
critic: [
|
|
16405
16539
|
"complexity_hotspots",
|
|
@@ -16410,7 +16544,8 @@ var init_constants = __esm(() => {
|
|
|
16410
16544
|
"knowledge_recall",
|
|
16411
16545
|
"req_coverage",
|
|
16412
16546
|
"get_approved_plan",
|
|
16413
|
-
"repo_map"
|
|
16547
|
+
"repo_map",
|
|
16548
|
+
"swarm_command"
|
|
16414
16549
|
],
|
|
16415
16550
|
critic_sounding_board: [
|
|
16416
16551
|
"complexity_hotspots",
|
|
@@ -16478,14 +16613,16 @@ var init_constants = __esm(() => {
|
|
|
16478
16613
|
"search",
|
|
16479
16614
|
"symbols",
|
|
16480
16615
|
"todo_extract",
|
|
16481
|
-
"knowledge_recall"
|
|
16616
|
+
"knowledge_recall",
|
|
16617
|
+
"swarm_command"
|
|
16482
16618
|
],
|
|
16483
16619
|
designer: [
|
|
16484
16620
|
"extract_code_blocks",
|
|
16485
16621
|
"retrieve_summary",
|
|
16486
16622
|
"search",
|
|
16487
16623
|
"symbols",
|
|
16488
|
-
"knowledge_recall"
|
|
16624
|
+
"knowledge_recall",
|
|
16625
|
+
"swarm_command"
|
|
16489
16626
|
],
|
|
16490
16627
|
curator_init: ["knowledge_recall"],
|
|
16491
16628
|
curator_phase: ["knowledge_recall"],
|
|
@@ -16501,7 +16638,8 @@ var init_constants = __esm(() => {
|
|
|
16501
16638
|
"skill_improve",
|
|
16502
16639
|
"search",
|
|
16503
16640
|
"doc_scan",
|
|
16504
|
-
"doc_extract"
|
|
16641
|
+
"doc_extract",
|
|
16642
|
+
"web_search"
|
|
16505
16643
|
],
|
|
16506
16644
|
spec_writer: [
|
|
16507
16645
|
"search",
|
|
@@ -16585,6 +16723,7 @@ var init_constants = __esm(() => {
|
|
|
16585
16723
|
skill_improve: "run the skill_improver agent to review and refine skills",
|
|
16586
16724
|
spec_write: "author or update .swarm/spec.md for the current project",
|
|
16587
16725
|
knowledge_ack: "record an explicit KNOWLEDGE_APPLIED/IGNORED/VIOLATED acknowledgment",
|
|
16726
|
+
swarm_command: "run supported /swarm commands through the canonical command registry",
|
|
16588
16727
|
lean_turbo_plan_lanes: "partition phase tasks into parallel lanes based on file-scope conflicts for Lean Turbo execution",
|
|
16589
16728
|
lean_turbo_acquire_locks: "acquire file locks for all files in a lane (all-or-nothing) before lane execution",
|
|
16590
16729
|
lean_turbo_runner_status: "read Lean Turbo run state from .swarm/turbo-state.json",
|
|
@@ -16601,67 +16740,67 @@ var init_constants = __esm(() => {
|
|
|
16601
16740
|
DEFAULT_AGENT_CONFIGS = {
|
|
16602
16741
|
coder: {
|
|
16603
16742
|
model: "opencode/minimax-m2.5-free",
|
|
16604
|
-
fallback_models: ["opencode/big-pickle"]
|
|
16743
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
16605
16744
|
},
|
|
16606
16745
|
reviewer: {
|
|
16607
16746
|
model: "opencode/big-pickle",
|
|
16608
|
-
fallback_models: ["opencode/
|
|
16747
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
16609
16748
|
},
|
|
16610
16749
|
test_engineer: {
|
|
16611
|
-
model: "opencode/
|
|
16612
|
-
fallback_models: ["opencode/
|
|
16750
|
+
model: "opencode/gpt-5-nano",
|
|
16751
|
+
fallback_models: ["opencode/big-pickle"]
|
|
16613
16752
|
},
|
|
16614
16753
|
explorer: {
|
|
16615
16754
|
model: "opencode/big-pickle",
|
|
16616
|
-
fallback_models: ["opencode/
|
|
16755
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
16617
16756
|
},
|
|
16618
16757
|
sme: {
|
|
16619
16758
|
model: "opencode/big-pickle",
|
|
16620
|
-
fallback_models: ["opencode/
|
|
16759
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
16621
16760
|
},
|
|
16622
16761
|
critic: {
|
|
16623
16762
|
model: "opencode/big-pickle",
|
|
16624
|
-
fallback_models: ["opencode/
|
|
16763
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
16625
16764
|
},
|
|
16626
16765
|
docs: {
|
|
16627
16766
|
model: "opencode/big-pickle",
|
|
16628
|
-
fallback_models: ["opencode/
|
|
16767
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
16629
16768
|
},
|
|
16630
16769
|
designer: {
|
|
16631
16770
|
model: "opencode/big-pickle",
|
|
16632
|
-
fallback_models: ["opencode/
|
|
16771
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
16633
16772
|
},
|
|
16634
16773
|
critic_sounding_board: {
|
|
16635
|
-
model: "opencode/
|
|
16636
|
-
fallback_models: ["opencode/
|
|
16774
|
+
model: "opencode/gpt-5-nano",
|
|
16775
|
+
fallback_models: ["opencode/big-pickle"]
|
|
16637
16776
|
},
|
|
16638
16777
|
critic_drift_verifier: {
|
|
16639
|
-
model: "opencode/
|
|
16640
|
-
fallback_models: ["opencode/
|
|
16778
|
+
model: "opencode/gpt-5-nano",
|
|
16779
|
+
fallback_models: ["opencode/big-pickle"]
|
|
16641
16780
|
},
|
|
16642
16781
|
critic_hallucination_verifier: {
|
|
16643
|
-
model: "opencode/
|
|
16644
|
-
fallback_models: ["opencode/
|
|
16782
|
+
model: "opencode/gpt-5-nano",
|
|
16783
|
+
fallback_models: ["opencode/big-pickle"]
|
|
16645
16784
|
},
|
|
16646
16785
|
critic_oversight: {
|
|
16647
|
-
model: "opencode/
|
|
16648
|
-
fallback_models: ["opencode/
|
|
16786
|
+
model: "opencode/gpt-5-nano",
|
|
16787
|
+
fallback_models: ["opencode/big-pickle"]
|
|
16649
16788
|
},
|
|
16650
16789
|
curator_init: {
|
|
16651
|
-
model: "opencode/
|
|
16652
|
-
fallback_models: ["opencode/
|
|
16790
|
+
model: "opencode/gpt-5-nano",
|
|
16791
|
+
fallback_models: ["opencode/big-pickle"]
|
|
16653
16792
|
},
|
|
16654
16793
|
curator_phase: {
|
|
16655
|
-
model: "opencode/
|
|
16656
|
-
fallback_models: ["opencode/
|
|
16794
|
+
model: "opencode/gpt-5-nano",
|
|
16795
|
+
fallback_models: ["opencode/big-pickle"]
|
|
16657
16796
|
},
|
|
16658
16797
|
skill_improver: {
|
|
16659
16798
|
model: "opencode/big-pickle",
|
|
16660
|
-
fallback_models: ["opencode/
|
|
16799
|
+
fallback_models: ["opencode/gpt-5-nano"]
|
|
16661
16800
|
},
|
|
16662
16801
|
spec_writer: {
|
|
16663
16802
|
model: "opencode/big-pickle",
|
|
16664
|
-
fallback_models: ["opencode/
|
|
16803
|
+
fallback_models: ["opencode/gpt-5-nano"]
|
|
16665
16804
|
}
|
|
16666
16805
|
};
|
|
16667
16806
|
});
|
|
@@ -17544,8 +17683,7 @@ function handleAgentsCommand(agents, guardrails) {
|
|
|
17544
17683
|
if (hasUnregistered) {
|
|
17545
17684
|
lines.push("", "### Unregistered Subagents");
|
|
17546
17685
|
for (const name of unregistered) {
|
|
17547
|
-
|
|
17548
|
-
lines.push(`- **${name}** (${hint})`);
|
|
17686
|
+
lines.push(`- **${name}** (requires configuration)`);
|
|
17549
17687
|
}
|
|
17550
17688
|
}
|
|
17551
17689
|
if (guardrails?.profiles && Object.keys(guardrails.profiles).length > 0) {
|
|
@@ -17574,18 +17712,9 @@ function handleAgentsCommand(agents, guardrails) {
|
|
|
17574
17712
|
return lines.join(`
|
|
17575
17713
|
`);
|
|
17576
17714
|
}
|
|
17577
|
-
var UNREGISTERED_AGENT_HINTS;
|
|
17578
17715
|
var init_agents = __esm(() => {
|
|
17579
17716
|
init_constants();
|
|
17580
17717
|
init_schema();
|
|
17581
|
-
UNREGISTERED_AGENT_HINTS = {
|
|
17582
|
-
designer: "enable ui_review.enabled",
|
|
17583
|
-
council_generalist: "enable council.general.enabled",
|
|
17584
|
-
council_skeptic: "enable council.general.enabled",
|
|
17585
|
-
council_domain_expert: "enable council.general.enabled",
|
|
17586
|
-
skill_improver: "registered by default unless agents.skill_improver.disabled is true",
|
|
17587
|
-
spec_writer: "registered by default unless agents.spec_writer.disabled is true"
|
|
17588
|
-
};
|
|
17589
17718
|
});
|
|
17590
17719
|
|
|
17591
17720
|
// src/commands/analyze.ts
|
|
@@ -20236,13 +20365,6 @@ var init_qa_gate_profile = __esm(() => {
|
|
|
20236
20365
|
final_council: false
|
|
20237
20366
|
};
|
|
20238
20367
|
});
|
|
20239
|
-
// src/parallel/runtime-config.ts
|
|
20240
|
-
var lockedProfileCache;
|
|
20241
|
-
var init_runtime_config = __esm(() => {
|
|
20242
|
-
init_plan_schema();
|
|
20243
|
-
lockedProfileCache = new Map;
|
|
20244
|
-
});
|
|
20245
|
-
|
|
20246
20368
|
// node_modules/quick-lru/index.js
|
|
20247
20369
|
var QuickLRU;
|
|
20248
20370
|
var init_quick_lru = __esm(() => {
|
|
@@ -20826,7 +20948,7 @@ var init_model_limits = __esm(() => {
|
|
|
20826
20948
|
var init_normalize_tool_name = () => {};
|
|
20827
20949
|
|
|
20828
20950
|
// src/hooks/guardrails.ts
|
|
20829
|
-
var storedInputArgs, TRANSIENT_STATUS_CODES, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_SAFE_TARGETS, DC_FS_ROOTS, pathNormalizationCache, globMatcherCache;
|
|
20951
|
+
var SPEC_DRIFT_BLOCKED_TOOLS, storedInputArgs, TRANSIENT_STATUS_CODES, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_SAFE_TARGETS, DC_FS_ROOTS, pathNormalizationCache, globMatcherCache;
|
|
20830
20952
|
var init_guardrails = __esm(() => {
|
|
20831
20953
|
init_quick_lru();
|
|
20832
20954
|
init_agents2();
|
|
@@ -20845,6 +20967,13 @@ var init_guardrails = __esm(() => {
|
|
|
20845
20967
|
init_loop_detector();
|
|
20846
20968
|
init_model_limits();
|
|
20847
20969
|
init_normalize_tool_name();
|
|
20970
|
+
SPEC_DRIFT_BLOCKED_TOOLS = new Set([
|
|
20971
|
+
"save_plan",
|
|
20972
|
+
"update_task_status",
|
|
20973
|
+
"phase_complete",
|
|
20974
|
+
"lean_turbo_run_phase",
|
|
20975
|
+
"lean_turbo_acquire_locks"
|
|
20976
|
+
]);
|
|
20848
20977
|
storedInputArgs = new Map;
|
|
20849
20978
|
TRANSIENT_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504, 529]);
|
|
20850
20979
|
toolCallsSinceLastWrite = new Map;
|
|
@@ -20888,7 +21017,6 @@ function clearPendingCoderScope() {
|
|
|
20888
21017
|
var pendingCoderScopeByTaskId;
|
|
20889
21018
|
var init_delegation_gate = __esm(() => {
|
|
20890
21019
|
init_schema();
|
|
20891
|
-
init_runtime_config();
|
|
20892
21020
|
init_state();
|
|
20893
21021
|
init_telemetry();
|
|
20894
21022
|
init_logger();
|
|
@@ -38256,31 +38384,12 @@ function parseArgs(args) {
|
|
|
38256
38384
|
}
|
|
38257
38385
|
return out;
|
|
38258
38386
|
}
|
|
38259
|
-
async function handleCouncilCommand(
|
|
38387
|
+
async function handleCouncilCommand(_directory, args) {
|
|
38260
38388
|
const parsed = parseArgs(args);
|
|
38261
38389
|
const question = sanitizeQuestion(parsed.rest.join(" "));
|
|
38262
38390
|
if (!question) {
|
|
38263
38391
|
return USAGE;
|
|
38264
38392
|
}
|
|
38265
|
-
const config3 = loadPluginConfig(directory);
|
|
38266
|
-
if (config3.council?.general?.enabled !== true) {
|
|
38267
|
-
return [
|
|
38268
|
-
"General Council is not enabled for this project.",
|
|
38269
|
-
"",
|
|
38270
|
-
"Enable it in `.opencode/opencode-swarm.json` or `~/.config/opencode/opencode-swarm.json`:",
|
|
38271
|
-
"",
|
|
38272
|
-
"```json",
|
|
38273
|
-
"{",
|
|
38274
|
-
' "council": {',
|
|
38275
|
-
' "general": { "enabled": true }',
|
|
38276
|
-
" }",
|
|
38277
|
-
"}",
|
|
38278
|
-
"```",
|
|
38279
|
-
"",
|
|
38280
|
-
"Then restart OpenCode and run `/swarm config doctor` before trying `/swarm council` again."
|
|
38281
|
-
].join(`
|
|
38282
|
-
`);
|
|
38283
|
-
}
|
|
38284
38393
|
const tokens = ["MODE: COUNCIL"];
|
|
38285
38394
|
if (parsed.preset) {
|
|
38286
38395
|
tokens.push(`preset=${parsed.preset}`);
|
|
@@ -38292,7 +38401,6 @@ async function handleCouncilCommand(directory, args) {
|
|
|
38292
38401
|
}
|
|
38293
38402
|
var MAX_QUESTION_LEN = 2000, USAGE;
|
|
38294
38403
|
var init_council = __esm(() => {
|
|
38295
|
-
init_loader();
|
|
38296
38404
|
USAGE = [
|
|
38297
38405
|
"Usage: /swarm council <question> [--preset <name>] [--spec-review]",
|
|
38298
38406
|
"",
|
|
@@ -39769,7 +39877,6 @@ __export(exports_config_doctor, {
|
|
|
39769
39877
|
restoreFromBackup: () => restoreFromBackup,
|
|
39770
39878
|
getConfigPaths: () => getConfigPaths,
|
|
39771
39879
|
createConfigBackup: () => createConfigBackup,
|
|
39772
|
-
collectConfiguredModelRefs: () => collectConfiguredModelRefs,
|
|
39773
39880
|
applySafeAutoFixes: () => applySafeAutoFixes
|
|
39774
39881
|
});
|
|
39775
39882
|
import * as crypto3 from "crypto";
|
|
@@ -40163,129 +40270,6 @@ function validateConfigKey(path24, value, _config) {
|
|
|
40163
40270
|
}
|
|
40164
40271
|
return findings;
|
|
40165
40272
|
}
|
|
40166
|
-
function addConfiguredModel(refs, model, configPath) {
|
|
40167
|
-
if (typeof model !== "string")
|
|
40168
|
-
return;
|
|
40169
|
-
const trimmed = model.trim();
|
|
40170
|
-
if (!trimmed)
|
|
40171
|
-
return;
|
|
40172
|
-
const paths = refs.get(trimmed) ?? new Set;
|
|
40173
|
-
paths.add(configPath);
|
|
40174
|
-
refs.set(trimmed, paths);
|
|
40175
|
-
}
|
|
40176
|
-
function addConfiguredAgentModels(refs, agents, prefix) {
|
|
40177
|
-
if (!agents || typeof agents !== "object" || Array.isArray(agents))
|
|
40178
|
-
return;
|
|
40179
|
-
for (const [agentName, value] of Object.entries(agents)) {
|
|
40180
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
40181
|
-
continue;
|
|
40182
|
-
const agent = value;
|
|
40183
|
-
addConfiguredModel(refs, agent.model, `${prefix}.${agentName}.model`);
|
|
40184
|
-
if (Array.isArray(agent.fallback_models)) {
|
|
40185
|
-
agent.fallback_models.forEach((model, index) => {
|
|
40186
|
-
addConfiguredModel(refs, model, `${prefix}.${agentName}.fallback_models[${index}]`);
|
|
40187
|
-
});
|
|
40188
|
-
}
|
|
40189
|
-
}
|
|
40190
|
-
}
|
|
40191
|
-
function collectConfiguredModelRefs(config3) {
|
|
40192
|
-
const refs = new Map;
|
|
40193
|
-
const rawConfig = config3;
|
|
40194
|
-
addConfiguredAgentModels(refs, rawConfig.agents, "agents");
|
|
40195
|
-
if (rawConfig.swarms && typeof rawConfig.swarms === "object" && !Array.isArray(rawConfig.swarms)) {
|
|
40196
|
-
for (const [swarmId, value] of Object.entries(rawConfig.swarms)) {
|
|
40197
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
40198
|
-
continue;
|
|
40199
|
-
addConfiguredAgentModels(refs, value.agents, `swarms.${swarmId}.agents`);
|
|
40200
|
-
}
|
|
40201
|
-
}
|
|
40202
|
-
if (rawConfig.full_auto && typeof rawConfig.full_auto === "object" && !Array.isArray(rawConfig.full_auto)) {
|
|
40203
|
-
addConfiguredModel(refs, rawConfig.full_auto.critic_model, "full_auto.critic_model");
|
|
40204
|
-
}
|
|
40205
|
-
if (rawConfig.skill_improver && typeof rawConfig.skill_improver === "object" && !Array.isArray(rawConfig.skill_improver)) {
|
|
40206
|
-
const skillImprover = rawConfig.skill_improver;
|
|
40207
|
-
addConfiguredModel(refs, skillImprover.model, "skill_improver.model");
|
|
40208
|
-
if (Array.isArray(skillImprover.fallback_models)) {
|
|
40209
|
-
skillImprover.fallback_models.forEach((model, index) => {
|
|
40210
|
-
addConfiguredModel(refs, model, `skill_improver.fallback_models[${index}]`);
|
|
40211
|
-
});
|
|
40212
|
-
}
|
|
40213
|
-
}
|
|
40214
|
-
if (rawConfig.spec_writer && typeof rawConfig.spec_writer === "object" && !Array.isArray(rawConfig.spec_writer)) {
|
|
40215
|
-
const specWriter = rawConfig.spec_writer;
|
|
40216
|
-
addConfiguredModel(refs, specWriter.model, "spec_writer.model");
|
|
40217
|
-
if (Array.isArray(specWriter.fallback_models)) {
|
|
40218
|
-
specWriter.fallback_models.forEach((model, index) => {
|
|
40219
|
-
addConfiguredModel(refs, model, `spec_writer.fallback_models[${index}]`);
|
|
40220
|
-
});
|
|
40221
|
-
}
|
|
40222
|
-
}
|
|
40223
|
-
const council = rawConfig.council;
|
|
40224
|
-
const general = council && typeof council === "object" && !Array.isArray(council) ? council.general : undefined;
|
|
40225
|
-
if (general && typeof general === "object" && !Array.isArray(general)) {
|
|
40226
|
-
addConfiguredModel(refs, general.moderatorModel, "council.general.moderatorModel");
|
|
40227
|
-
if (Array.isArray(general.members)) {
|
|
40228
|
-
general.members.forEach((member, index) => {
|
|
40229
|
-
if (!member || typeof member !== "object" || Array.isArray(member)) {
|
|
40230
|
-
return;
|
|
40231
|
-
}
|
|
40232
|
-
addConfiguredModel(refs, member.model, `council.general.members[${index}].model`);
|
|
40233
|
-
});
|
|
40234
|
-
}
|
|
40235
|
-
if (general.presets && typeof general.presets === "object" && !Array.isArray(general.presets)) {
|
|
40236
|
-
for (const [presetName, members] of Object.entries(general.presets)) {
|
|
40237
|
-
if (!Array.isArray(members))
|
|
40238
|
-
continue;
|
|
40239
|
-
members.forEach((member, index) => {
|
|
40240
|
-
if (!member || typeof member !== "object" || Array.isArray(member)) {
|
|
40241
|
-
return;
|
|
40242
|
-
}
|
|
40243
|
-
addConfiguredModel(refs, member.model, `council.general.presets.${presetName}[${index}].model`);
|
|
40244
|
-
});
|
|
40245
|
-
}
|
|
40246
|
-
}
|
|
40247
|
-
}
|
|
40248
|
-
return refs;
|
|
40249
|
-
}
|
|
40250
|
-
function validateConfiguredModels(config3, modelAvailability) {
|
|
40251
|
-
const refs = collectConfiguredModelRefs(config3);
|
|
40252
|
-
const findings = [];
|
|
40253
|
-
if (modelAvailability.error) {
|
|
40254
|
-
findings.push({
|
|
40255
|
-
id: "model-availability-unchecked",
|
|
40256
|
-
title: "Model availability check skipped",
|
|
40257
|
-
description: `Could not load OpenCode provider models from ${modelAvailability.source}: ` + modelAvailability.error,
|
|
40258
|
-
severity: "info",
|
|
40259
|
-
path: "agents",
|
|
40260
|
-
autoFixable: false
|
|
40261
|
-
});
|
|
40262
|
-
return findings;
|
|
40263
|
-
}
|
|
40264
|
-
if (refs.size === 0)
|
|
40265
|
-
return findings;
|
|
40266
|
-
for (const [modelId, paths] of refs.entries()) {
|
|
40267
|
-
if (modelAvailability.availableModelIds.has(modelId))
|
|
40268
|
-
continue;
|
|
40269
|
-
findings.push({
|
|
40270
|
-
id: "configured-model-unavailable",
|
|
40271
|
-
title: "Configured model is unavailable",
|
|
40272
|
-
description: `Configured model ${formatModelIdForDoctor(modelId)} was not found in the active OpenCode provider model registry. ` + "Run `/models` to choose a currently available model, then update opencode-swarm.json.",
|
|
40273
|
-
severity: "error",
|
|
40274
|
-
path: [...paths].sort().join(", "),
|
|
40275
|
-
currentValue: modelId,
|
|
40276
|
-
autoFixable: false
|
|
40277
|
-
});
|
|
40278
|
-
}
|
|
40279
|
-
return findings;
|
|
40280
|
-
}
|
|
40281
|
-
function formatModelIdForDoctor(modelId) {
|
|
40282
|
-
const json3 = JSON.stringify(modelId);
|
|
40283
|
-
if (!json3)
|
|
40284
|
-
return '"<invalid model id>"';
|
|
40285
|
-
if (json3.length <= 160)
|
|
40286
|
-
return json3;
|
|
40287
|
-
return `${json3.slice(0, 157)}..."`;
|
|
40288
|
-
}
|
|
40289
40273
|
function walkConfigAndValidate(obj, path24, config3, findings) {
|
|
40290
40274
|
if (obj === null || obj === undefined) {
|
|
40291
40275
|
return;
|
|
@@ -40310,12 +40294,9 @@ function walkConfigAndValidate(obj, path24, config3, findings) {
|
|
|
40310
40294
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
40311
40295
|
}
|
|
40312
40296
|
}
|
|
40313
|
-
function runConfigDoctor(config3, directory
|
|
40297
|
+
function runConfigDoctor(config3, directory) {
|
|
40314
40298
|
const findings = [];
|
|
40315
40299
|
walkConfigAndValidate(config3, "", config3, findings);
|
|
40316
|
-
if (options.modelAvailability) {
|
|
40317
|
-
findings.push(...validateConfiguredModels(config3, options.modelAvailability));
|
|
40318
|
-
}
|
|
40319
40300
|
const summary = {
|
|
40320
40301
|
info: findings.filter((f) => f.severity === "info").length,
|
|
40321
40302
|
warn: findings.filter((f) => f.severity === "warn").length,
|
|
@@ -40477,8 +40458,8 @@ function shouldRunOnStartup(automationConfig) {
|
|
|
40477
40458
|
}
|
|
40478
40459
|
return automationConfig.capabilities?.config_doctor_on_startup === true;
|
|
40479
40460
|
}
|
|
40480
|
-
async function runConfigDoctorWithFixes(directory, config3, autoFix = false
|
|
40481
|
-
const result = runConfigDoctor(config3, directory
|
|
40461
|
+
async function runConfigDoctorWithFixes(directory, config3, autoFix = false) {
|
|
40462
|
+
const result = runConfigDoctor(config3, directory);
|
|
40482
40463
|
const artifactPath = writeDoctorArtifact(directory, result);
|
|
40483
40464
|
if (!autoFix) {
|
|
40484
40465
|
return {
|
|
@@ -40498,7 +40479,7 @@ async function runConfigDoctorWithFixes(directory, config3, autoFix = false, opt
|
|
|
40498
40479
|
if (appliedFixes.length > 0) {
|
|
40499
40480
|
const freshConfig = readConfigFromFile(directory);
|
|
40500
40481
|
if (freshConfig) {
|
|
40501
|
-
const newResult = runConfigDoctor(freshConfig.config, directory
|
|
40482
|
+
const newResult = runConfigDoctor(freshConfig.config, directory);
|
|
40502
40483
|
writeDoctorArtifact(directory, newResult);
|
|
40503
40484
|
}
|
|
40504
40485
|
}
|
|
@@ -42120,23 +42101,6 @@ var init_tool_doctor = __esm(() => {
|
|
|
42120
42101
|
];
|
|
42121
42102
|
});
|
|
42122
42103
|
|
|
42123
|
-
// src/utils/timeout.ts
|
|
42124
|
-
async function withTimeout(promise3, ms, timeoutError) {
|
|
42125
|
-
let timer;
|
|
42126
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
42127
|
-
timer = setTimeout(() => reject(timeoutError), ms);
|
|
42128
|
-
if (typeof timer.unref === "function") {
|
|
42129
|
-
timer.unref();
|
|
42130
|
-
}
|
|
42131
|
-
});
|
|
42132
|
-
try {
|
|
42133
|
-
return await Promise.race([promise3, timeoutPromise]);
|
|
42134
|
-
} finally {
|
|
42135
|
-
if (timer !== undefined)
|
|
42136
|
-
clearTimeout(timer);
|
|
42137
|
-
}
|
|
42138
|
-
}
|
|
42139
|
-
|
|
42140
42104
|
// src/commands/doctor.ts
|
|
42141
42105
|
function formatToolDoctorMarkdown(result) {
|
|
42142
42106
|
const lines = [
|
|
@@ -42210,67 +42174,13 @@ function formatDoctorMarkdown(result) {
|
|
|
42210
42174
|
return lines.join(`
|
|
42211
42175
|
`);
|
|
42212
42176
|
}
|
|
42213
|
-
function
|
|
42214
|
-
const available = new Set;
|
|
42215
|
-
if (response?.providers !== undefined && !Array.isArray(response.providers)) {
|
|
42216
|
-
throw new Error("provider registry returned malformed provider list");
|
|
42217
|
-
}
|
|
42218
|
-
for (const provider of response?.providers ?? []) {
|
|
42219
|
-
if (!provider || typeof provider !== "object" || !provider.id || !provider.models || typeof provider.models !== "object" || Array.isArray(provider.models)) {
|
|
42220
|
-
continue;
|
|
42221
|
-
}
|
|
42222
|
-
for (const [modelKey, modelInfo] of Object.entries(provider.models)) {
|
|
42223
|
-
available.add(`${provider.id}/${modelKey}`);
|
|
42224
|
-
if (modelInfo && typeof modelInfo === "object" && modelInfo.id) {
|
|
42225
|
-
available.add(`${provider.id}/${modelInfo.id}`);
|
|
42226
|
-
}
|
|
42227
|
-
}
|
|
42228
|
-
}
|
|
42229
|
-
return available;
|
|
42230
|
-
}
|
|
42231
|
-
async function loadModelAvailability(directory, client, options = {}) {
|
|
42232
|
-
const providerClient = client;
|
|
42233
|
-
const providers = providerClient?.config?.providers;
|
|
42234
|
-
if (typeof providers !== "function") {
|
|
42235
|
-
return;
|
|
42236
|
-
}
|
|
42237
|
-
try {
|
|
42238
|
-
const response = await withTimeout(providers({ directory }), options.timeoutMs ?? MODEL_REGISTRY_TIMEOUT_MS, new Error(`OpenCode provider model registry lookup exceeded ${options.timeoutMs ?? MODEL_REGISTRY_TIMEOUT_MS}ms`));
|
|
42239
|
-
if (response.error) {
|
|
42240
|
-
return {
|
|
42241
|
-
availableModelIds: new Set,
|
|
42242
|
-
source: MODEL_REGISTRY_SOURCE,
|
|
42243
|
-
error: typeof response.error === "string" ? response.error : JSON.stringify(response.error)
|
|
42244
|
-
};
|
|
42245
|
-
}
|
|
42246
|
-
if (!response.data) {
|
|
42247
|
-
return {
|
|
42248
|
-
availableModelIds: new Set,
|
|
42249
|
-
source: MODEL_REGISTRY_SOURCE,
|
|
42250
|
-
error: "provider registry returned no data"
|
|
42251
|
-
};
|
|
42252
|
-
}
|
|
42253
|
-
return {
|
|
42254
|
-
availableModelIds: extractAvailableModelIds(response.data),
|
|
42255
|
-
source: MODEL_REGISTRY_SOURCE
|
|
42256
|
-
};
|
|
42257
|
-
} catch (error93) {
|
|
42258
|
-
return {
|
|
42259
|
-
availableModelIds: new Set,
|
|
42260
|
-
source: MODEL_REGISTRY_SOURCE,
|
|
42261
|
-
error: error93 instanceof Error ? error93.message : String(error93)
|
|
42262
|
-
};
|
|
42263
|
-
}
|
|
42264
|
-
}
|
|
42265
|
-
async function handleDoctorCommand(directory, args, options = {}) {
|
|
42177
|
+
async function handleDoctorCommand(directory, args) {
|
|
42266
42178
|
const enableAutoFix = args.includes("--fix") || args.includes("-f");
|
|
42267
42179
|
const config3 = loadPluginConfig(directory);
|
|
42268
|
-
const
|
|
42269
|
-
const doctorOptions = { modelAvailability };
|
|
42270
|
-
const result = runConfigDoctor(config3, directory, doctorOptions);
|
|
42180
|
+
const result = runConfigDoctor(config3, directory);
|
|
42271
42181
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
42272
42182
|
const { runConfigDoctorWithFixes: runConfigDoctorWithFixes2 } = await Promise.resolve().then(() => (init_config_doctor(), exports_config_doctor));
|
|
42273
|
-
const fixResult = await runConfigDoctorWithFixes2(directory, config3, true
|
|
42183
|
+
const fixResult = await runConfigDoctorWithFixes2(directory, config3, true);
|
|
42274
42184
|
return formatDoctorMarkdown(fixResult.result);
|
|
42275
42185
|
}
|
|
42276
42186
|
return formatDoctorMarkdown(result);
|
|
@@ -42279,7 +42189,6 @@ async function handleDoctorToolsCommand(directory, _args) {
|
|
|
42279
42189
|
const result = runToolDoctor(directory);
|
|
42280
42190
|
return formatToolDoctorMarkdown(result);
|
|
42281
42191
|
}
|
|
42282
|
-
var MODEL_REGISTRY_TIMEOUT_MS = 3000, MODEL_REGISTRY_SOURCE = "OpenCode config.providers";
|
|
42283
42192
|
var init_doctor = __esm(() => {
|
|
42284
42193
|
init_loader();
|
|
42285
42194
|
init_config_doctor();
|
|
@@ -42620,7 +42529,7 @@ function getVerdictEmoji(verdict) {
|
|
|
42620
42529
|
return getVerdictIcon(verdict);
|
|
42621
42530
|
}
|
|
42622
42531
|
async function getTaskEvidenceData(directory, taskId) {
|
|
42623
|
-
const result = await loadEvidence(directory, taskId);
|
|
42532
|
+
const result = await _internals13.loadEvidence(directory, taskId);
|
|
42624
42533
|
if (result.status !== "found") {
|
|
42625
42534
|
return {
|
|
42626
42535
|
hasEvidence: false,
|
|
@@ -42643,13 +42552,13 @@ async function getTaskEvidenceData(directory, taskId) {
|
|
|
42643
42552
|
};
|
|
42644
42553
|
}
|
|
42645
42554
|
async function getEvidenceListData(directory) {
|
|
42646
|
-
const taskIds = await listEvidenceTaskIds(directory);
|
|
42555
|
+
const taskIds = await _internals13.listEvidenceTaskIds(directory);
|
|
42647
42556
|
if (taskIds.length === 0) {
|
|
42648
42557
|
return { hasEvidence: false, tasks: [] };
|
|
42649
42558
|
}
|
|
42650
42559
|
const tasks = [];
|
|
42651
42560
|
for (const taskId of taskIds) {
|
|
42652
|
-
const result = await loadEvidence(directory, taskId);
|
|
42561
|
+
const result = await _internals13.loadEvidence(directory, taskId);
|
|
42653
42562
|
if (result.status === "found") {
|
|
42654
42563
|
tasks.push({
|
|
42655
42564
|
taskId,
|
|
@@ -42763,8 +42672,13 @@ async function handleEvidenceSummaryCommand(directory) {
|
|
|
42763
42672
|
return lines.join(`
|
|
42764
42673
|
`);
|
|
42765
42674
|
}
|
|
42675
|
+
var _internals13;
|
|
42766
42676
|
var init_evidence_service = __esm(() => {
|
|
42767
42677
|
init_manager2();
|
|
42678
|
+
_internals13 = {
|
|
42679
|
+
loadEvidence,
|
|
42680
|
+
listEvidenceTaskIds
|
|
42681
|
+
};
|
|
42768
42682
|
});
|
|
42769
42683
|
|
|
42770
42684
|
// src/commands/evidence.ts
|
|
@@ -43168,7 +43082,7 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
43168
43082
|
if (!plan) {
|
|
43169
43083
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
43170
43084
|
}
|
|
43171
|
-
if (!
|
|
43085
|
+
if (!_internals14.validatePlanPhases(plan)) {
|
|
43172
43086
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
43173
43087
|
}
|
|
43174
43088
|
let currentPhase = null;
|
|
@@ -43310,9 +43224,9 @@ function extractPhaseMetrics(content) {
|
|
|
43310
43224
|
async function getHandoffData(directory) {
|
|
43311
43225
|
const now = new Date().toISOString();
|
|
43312
43226
|
const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
|
|
43313
|
-
const sessionState =
|
|
43227
|
+
const sessionState = _internals14.parseSessionState(sessionContent);
|
|
43314
43228
|
const plan = await loadPlanJsonOnly(directory);
|
|
43315
|
-
const planInfo =
|
|
43229
|
+
const planInfo = _internals14.extractCurrentPhaseFromPlan(plan);
|
|
43316
43230
|
if (!plan) {
|
|
43317
43231
|
const planMdContent = await readSwarmFileAsync(directory, "plan.md");
|
|
43318
43232
|
if (planMdContent) {
|
|
@@ -43331,8 +43245,8 @@ async function getHandoffData(directory) {
|
|
|
43331
43245
|
}
|
|
43332
43246
|
}
|
|
43333
43247
|
const contextContent = await readSwarmFileAsync(directory, "context.md");
|
|
43334
|
-
const recentDecisions =
|
|
43335
|
-
const rawPhaseMetrics =
|
|
43248
|
+
const recentDecisions = _internals14.extractDecisions(contextContent);
|
|
43249
|
+
const rawPhaseMetrics = _internals14.extractPhaseMetrics(contextContent);
|
|
43336
43250
|
const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
|
|
43337
43251
|
let delegationState = null;
|
|
43338
43252
|
if (sessionState?.delegationState) {
|
|
@@ -43496,13 +43410,13 @@ ${lines.join(`
|
|
|
43496
43410
|
`)}
|
|
43497
43411
|
\`\`\``;
|
|
43498
43412
|
}
|
|
43499
|
-
var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20,
|
|
43413
|
+
var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals14;
|
|
43500
43414
|
var init_handoff_service = __esm(() => {
|
|
43501
43415
|
init_utils2();
|
|
43502
43416
|
init_manager();
|
|
43503
43417
|
init_utils();
|
|
43504
43418
|
RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
|
|
43505
|
-
|
|
43419
|
+
_internals14 = {
|
|
43506
43420
|
getHandoffData,
|
|
43507
43421
|
formatHandoffMarkdown,
|
|
43508
43422
|
formatContinuationPrompt,
|
|
@@ -43621,22 +43535,22 @@ async function writeSnapshot(directory, state) {
|
|
|
43621
43535
|
}
|
|
43622
43536
|
function createSnapshotWriterHook(directory) {
|
|
43623
43537
|
return (_input, _output) => {
|
|
43624
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
43538
|
+
_writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
|
|
43625
43539
|
return _writeInFlight;
|
|
43626
43540
|
};
|
|
43627
43541
|
}
|
|
43628
43542
|
async function flushPendingSnapshot(directory) {
|
|
43629
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
43543
|
+
_writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
|
|
43630
43544
|
await _writeInFlight;
|
|
43631
43545
|
}
|
|
43632
|
-
var _writeInFlight,
|
|
43546
|
+
var _writeInFlight, _internals15;
|
|
43633
43547
|
var init_snapshot_writer = __esm(() => {
|
|
43634
43548
|
init_utils2();
|
|
43635
43549
|
init_state();
|
|
43636
43550
|
init_utils();
|
|
43637
43551
|
init_bun_compat();
|
|
43638
43552
|
_writeInFlight = Promise.resolve();
|
|
43639
|
-
|
|
43553
|
+
_internals15 = {
|
|
43640
43554
|
writeSnapshot,
|
|
43641
43555
|
createSnapshotWriterHook,
|
|
43642
43556
|
flushPendingSnapshot
|
|
@@ -44101,9 +44015,9 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
44101
44015
|
skippedReason: "empty-context"
|
|
44102
44016
|
};
|
|
44103
44017
|
}
|
|
44104
|
-
const rawEntries =
|
|
44018
|
+
const rawEntries = _internals16.parseContextMd(contextContent);
|
|
44105
44019
|
if (rawEntries.length === 0) {
|
|
44106
|
-
await
|
|
44020
|
+
await _internals16.writeSentinel(sentinelPath, 0, 0);
|
|
44107
44021
|
return {
|
|
44108
44022
|
migrated: true,
|
|
44109
44023
|
entriesMigrated: 0,
|
|
@@ -44114,10 +44028,10 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
44114
44028
|
const existing = await readKnowledge(knowledgePath);
|
|
44115
44029
|
let migrated = 0;
|
|
44116
44030
|
let dropped = 0;
|
|
44117
|
-
const projectName =
|
|
44031
|
+
const projectName = _internals16.inferProjectName(directory);
|
|
44118
44032
|
for (const raw of rawEntries) {
|
|
44119
44033
|
if (config3.validation_enabled !== false) {
|
|
44120
|
-
const category = raw.categoryHint ??
|
|
44034
|
+
const category = raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text);
|
|
44121
44035
|
const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
|
|
44122
44036
|
category,
|
|
44123
44037
|
scope: "global",
|
|
@@ -44137,8 +44051,8 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
44137
44051
|
const entry = {
|
|
44138
44052
|
id: randomUUID2(),
|
|
44139
44053
|
tier: "swarm",
|
|
44140
|
-
lesson:
|
|
44141
|
-
category: raw.categoryHint ??
|
|
44054
|
+
lesson: _internals16.truncateLesson(raw.text),
|
|
44055
|
+
category: raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text),
|
|
44142
44056
|
tags: [...inferredTags, `migration:${raw.sourceSection}`],
|
|
44143
44057
|
scope: "global",
|
|
44144
44058
|
confidence: 0.3,
|
|
@@ -44161,7 +44075,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
44161
44075
|
if (migrated > 0) {
|
|
44162
44076
|
await rewriteKnowledge(knowledgePath, existing);
|
|
44163
44077
|
}
|
|
44164
|
-
await
|
|
44078
|
+
await _internals16.writeSentinel(sentinelPath, migrated, dropped);
|
|
44165
44079
|
log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
|
|
44166
44080
|
return {
|
|
44167
44081
|
migrated: true,
|
|
@@ -44171,7 +44085,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
44171
44085
|
};
|
|
44172
44086
|
}
|
|
44173
44087
|
function parseContextMd(content) {
|
|
44174
|
-
const sections =
|
|
44088
|
+
const sections = _internals16.splitIntoSections(content);
|
|
44175
44089
|
const entries = [];
|
|
44176
44090
|
const seen = new Set;
|
|
44177
44091
|
const sectionPatterns = [
|
|
@@ -44187,7 +44101,7 @@ function parseContextMd(content) {
|
|
|
44187
44101
|
const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
|
|
44188
44102
|
if (!match)
|
|
44189
44103
|
continue;
|
|
44190
|
-
const bullets =
|
|
44104
|
+
const bullets = _internals16.extractBullets(section.body);
|
|
44191
44105
|
for (const bullet of bullets) {
|
|
44192
44106
|
if (bullet.length < 15)
|
|
44193
44107
|
continue;
|
|
@@ -44196,9 +44110,9 @@ function parseContextMd(content) {
|
|
|
44196
44110
|
continue;
|
|
44197
44111
|
seen.add(normalized);
|
|
44198
44112
|
entries.push({
|
|
44199
|
-
text:
|
|
44113
|
+
text: _internals16.truncateLesson(bullet),
|
|
44200
44114
|
sourceSection: match.sourceSection,
|
|
44201
|
-
categoryHint:
|
|
44115
|
+
categoryHint: _internals16.inferCategoryFromText(bullet)
|
|
44202
44116
|
});
|
|
44203
44117
|
}
|
|
44204
44118
|
}
|
|
@@ -44291,12 +44205,12 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
44291
44205
|
await mkdir8(path28.dirname(sentinelPath), { recursive: true });
|
|
44292
44206
|
await writeFile9(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
44293
44207
|
}
|
|
44294
|
-
var
|
|
44208
|
+
var _internals16;
|
|
44295
44209
|
var init_knowledge_migrator = __esm(() => {
|
|
44296
44210
|
init_logger();
|
|
44297
44211
|
init_knowledge_store();
|
|
44298
44212
|
init_knowledge_validator();
|
|
44299
|
-
|
|
44213
|
+
_internals16 = {
|
|
44300
44214
|
migrateContextToKnowledge,
|
|
44301
44215
|
migrateKnowledgeToExternal,
|
|
44302
44216
|
parseContextMd,
|
|
@@ -44433,9 +44347,9 @@ var init_knowledge = __esm(() => {
|
|
|
44433
44347
|
|
|
44434
44348
|
// src/services/plan-service.ts
|
|
44435
44349
|
async function getPlanData(directory, phaseArg) {
|
|
44436
|
-
const plan = await loadPlanJsonOnly(directory);
|
|
44350
|
+
const plan = await _internals17.loadPlanJsonOnly(directory);
|
|
44437
44351
|
if (plan) {
|
|
44438
|
-
const fullMarkdown = derivePlanMarkdown(plan);
|
|
44352
|
+
const fullMarkdown = _internals17.derivePlanMarkdown(plan);
|
|
44439
44353
|
if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
|
|
44440
44354
|
return {
|
|
44441
44355
|
hasPlan: true,
|
|
@@ -44478,7 +44392,7 @@ async function getPlanData(directory, phaseArg) {
|
|
|
44478
44392
|
isLegacy: false
|
|
44479
44393
|
};
|
|
44480
44394
|
}
|
|
44481
|
-
const planContent = await readSwarmFileAsync(directory, "plan.md");
|
|
44395
|
+
const planContent = await _internals17.readSwarmFileAsync(directory, "plan.md");
|
|
44482
44396
|
if (!planContent) {
|
|
44483
44397
|
return {
|
|
44484
44398
|
hasPlan: false,
|
|
@@ -44574,9 +44488,15 @@ async function handlePlanCommand(directory, args) {
|
|
|
44574
44488
|
const planData = await getPlanData(directory, phaseArg);
|
|
44575
44489
|
return formatPlanMarkdown(planData);
|
|
44576
44490
|
}
|
|
44491
|
+
var _internals17;
|
|
44577
44492
|
var init_plan_service = __esm(() => {
|
|
44578
44493
|
init_utils2();
|
|
44579
44494
|
init_manager();
|
|
44495
|
+
_internals17 = {
|
|
44496
|
+
loadPlanJsonOnly,
|
|
44497
|
+
derivePlanMarkdown,
|
|
44498
|
+
readSwarmFileAsync
|
|
44499
|
+
};
|
|
44580
44500
|
});
|
|
44581
44501
|
|
|
44582
44502
|
// src/commands/plan.ts
|
|
@@ -45162,7 +45082,7 @@ async function runAdditionalLint(linter, mode, cwd) {
|
|
|
45162
45082
|
};
|
|
45163
45083
|
}
|
|
45164
45084
|
}
|
|
45165
|
-
var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint,
|
|
45085
|
+
var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals18;
|
|
45166
45086
|
var init_lint = __esm(() => {
|
|
45167
45087
|
init_zod();
|
|
45168
45088
|
init_discovery();
|
|
@@ -45194,15 +45114,15 @@ var init_lint = __esm(() => {
|
|
|
45194
45114
|
}
|
|
45195
45115
|
const { mode } = args;
|
|
45196
45116
|
const cwd = directory;
|
|
45197
|
-
const linter = await
|
|
45117
|
+
const linter = await _internals18.detectAvailableLinter(directory);
|
|
45198
45118
|
if (linter) {
|
|
45199
|
-
const result = await
|
|
45119
|
+
const result = await _internals18.runLint(linter, mode, directory);
|
|
45200
45120
|
return JSON.stringify(result, null, 2);
|
|
45201
45121
|
}
|
|
45202
|
-
const additionalLinter =
|
|
45122
|
+
const additionalLinter = _internals18.detectAdditionalLinter(cwd);
|
|
45203
45123
|
if (additionalLinter) {
|
|
45204
45124
|
warn(`[lint] Using ${additionalLinter} linter for this project`);
|
|
45205
|
-
const result = await
|
|
45125
|
+
const result = await _internals18.runAdditionalLint(additionalLinter, mode, cwd);
|
|
45206
45126
|
return JSON.stringify(result, null, 2);
|
|
45207
45127
|
}
|
|
45208
45128
|
const errorResult = {
|
|
@@ -45216,7 +45136,7 @@ For Rust: rustup component add clippy`
|
|
|
45216
45136
|
return JSON.stringify(errorResult, null, 2);
|
|
45217
45137
|
}
|
|
45218
45138
|
});
|
|
45219
|
-
|
|
45139
|
+
_internals18 = {
|
|
45220
45140
|
detectAvailableLinter,
|
|
45221
45141
|
runLint,
|
|
45222
45142
|
detectAdditionalLinter,
|
|
@@ -45530,7 +45450,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
45530
45450
|
}
|
|
45531
45451
|
async function runSecretscan(directory) {
|
|
45532
45452
|
try {
|
|
45533
|
-
const result = await
|
|
45453
|
+
const result = await _internals19.secretscan.execute({ directory }, {});
|
|
45534
45454
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
45535
45455
|
return JSON.parse(jsonStr);
|
|
45536
45456
|
} catch (e) {
|
|
@@ -45545,7 +45465,7 @@ async function runSecretscan(directory) {
|
|
|
45545
45465
|
return errorResult;
|
|
45546
45466
|
}
|
|
45547
45467
|
}
|
|
45548
|
-
var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan,
|
|
45468
|
+
var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals19;
|
|
45549
45469
|
var init_secretscan = __esm(() => {
|
|
45550
45470
|
init_zod();
|
|
45551
45471
|
init_path_security();
|
|
@@ -45917,7 +45837,7 @@ var init_secretscan = __esm(() => {
|
|
|
45917
45837
|
}
|
|
45918
45838
|
}
|
|
45919
45839
|
});
|
|
45920
|
-
|
|
45840
|
+
_internals19 = {
|
|
45921
45841
|
secretscan,
|
|
45922
45842
|
runSecretscan
|
|
45923
45843
|
};
|
|
@@ -46489,14 +46409,14 @@ function buildGoBackend() {
|
|
|
46489
46409
|
selectEntryPoints
|
|
46490
46410
|
};
|
|
46491
46411
|
}
|
|
46492
|
-
var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE,
|
|
46412
|
+
var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals20;
|
|
46493
46413
|
var init_go = __esm(() => {
|
|
46494
46414
|
init_default_backend();
|
|
46495
46415
|
init_profiles();
|
|
46496
46416
|
IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
|
|
46497
46417
|
IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
|
|
46498
46418
|
IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
|
|
46499
|
-
|
|
46419
|
+
_internals20 = { extractImports };
|
|
46500
46420
|
});
|
|
46501
46421
|
|
|
46502
46422
|
// src/lang/backends/python.ts
|
|
@@ -46608,13 +46528,13 @@ function buildPythonBackend() {
|
|
|
46608
46528
|
selectEntryPoints: selectEntryPoints2
|
|
46609
46529
|
};
|
|
46610
46530
|
}
|
|
46611
|
-
var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT,
|
|
46531
|
+
var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals21;
|
|
46612
46532
|
var init_python = __esm(() => {
|
|
46613
46533
|
init_default_backend();
|
|
46614
46534
|
init_profiles();
|
|
46615
46535
|
IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
|
|
46616
46536
|
IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
|
|
46617
|
-
|
|
46537
|
+
_internals21 = { extractImports: extractImports2 };
|
|
46618
46538
|
});
|
|
46619
46539
|
|
|
46620
46540
|
// src/test-impact/analyzer.ts
|
|
@@ -46825,7 +46745,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
|
46825
46745
|
return;
|
|
46826
46746
|
}
|
|
46827
46747
|
if (PYTHON_EXTENSIONS.has(ext)) {
|
|
46828
|
-
const modules =
|
|
46748
|
+
const modules = _internals21.extractImports(testFile, content);
|
|
46829
46749
|
for (const mod of modules) {
|
|
46830
46750
|
const resolved = resolvePythonImport(testDir, mod);
|
|
46831
46751
|
if (resolved !== null)
|
|
@@ -46834,7 +46754,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
|
46834
46754
|
return;
|
|
46835
46755
|
}
|
|
46836
46756
|
if (GO_EXTENSIONS.has(ext)) {
|
|
46837
|
-
const imports =
|
|
46757
|
+
const imports = _internals20.extractImports(testFile, content);
|
|
46838
46758
|
for (const importPath of imports) {
|
|
46839
46759
|
const sourceFiles = resolveGoImport(testDir, importPath);
|
|
46840
46760
|
for (const source of sourceFiles)
|
|
@@ -46861,8 +46781,8 @@ async function buildImpactMapInternal(cwd) {
|
|
|
46861
46781
|
return impactMap;
|
|
46862
46782
|
}
|
|
46863
46783
|
async function buildImpactMap(cwd) {
|
|
46864
|
-
const impactMap = await
|
|
46865
|
-
await
|
|
46784
|
+
const impactMap = await _internals22.buildImpactMapInternal(cwd);
|
|
46785
|
+
await _internals22.saveImpactMap(cwd, impactMap);
|
|
46866
46786
|
return impactMap;
|
|
46867
46787
|
}
|
|
46868
46788
|
async function loadImpactMap(cwd) {
|
|
@@ -46873,12 +46793,12 @@ async function loadImpactMap(cwd) {
|
|
|
46873
46793
|
const data = JSON.parse(content);
|
|
46874
46794
|
const map3 = data.map;
|
|
46875
46795
|
const generatedAt = new Date(data.generatedAt).getTime();
|
|
46876
|
-
if (!
|
|
46796
|
+
if (!_internals22.isCacheStale(map3, generatedAt)) {
|
|
46877
46797
|
return map3;
|
|
46878
46798
|
}
|
|
46879
46799
|
} catch {}
|
|
46880
46800
|
}
|
|
46881
|
-
return
|
|
46801
|
+
return _internals22.buildImpactMap(cwd);
|
|
46882
46802
|
}
|
|
46883
46803
|
async function saveImpactMap(cwd, impactMap) {
|
|
46884
46804
|
const cacheDir2 = path34.join(cwd, ".swarm", "cache");
|
|
@@ -46904,7 +46824,7 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
46904
46824
|
};
|
|
46905
46825
|
}
|
|
46906
46826
|
const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
|
|
46907
|
-
const impactMap = await
|
|
46827
|
+
const impactMap = await _internals22.loadImpactMap(cwd);
|
|
46908
46828
|
const impactedTestsSet = new Set;
|
|
46909
46829
|
const untestedFiles = [];
|
|
46910
46830
|
for (const changedFile of validFiles) {
|
|
@@ -46945,7 +46865,7 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
46945
46865
|
impactMap
|
|
46946
46866
|
};
|
|
46947
46867
|
}
|
|
46948
|
-
var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache,
|
|
46868
|
+
var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals22;
|
|
46949
46869
|
var init_analyzer = __esm(() => {
|
|
46950
46870
|
init_go();
|
|
46951
46871
|
init_python();
|
|
@@ -46957,7 +46877,7 @@ var init_analyzer = __esm(() => {
|
|
|
46957
46877
|
GO_EXTENSIONS = new Set([".go"]);
|
|
46958
46878
|
EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
46959
46879
|
goModuleCache = new Map;
|
|
46960
|
-
|
|
46880
|
+
_internals22 = {
|
|
46961
46881
|
normalizePath,
|
|
46962
46882
|
isCacheStale,
|
|
46963
46883
|
resolveRelativeImport,
|
|
@@ -47437,7 +47357,7 @@ function readPackageJsonRaw(dir) {
|
|
|
47437
47357
|
}
|
|
47438
47358
|
}
|
|
47439
47359
|
function readPackageJson(dir) {
|
|
47440
|
-
return
|
|
47360
|
+
return _internals23.readPackageJsonRaw(dir);
|
|
47441
47361
|
}
|
|
47442
47362
|
function readPackageJsonTestScript(dir) {
|
|
47443
47363
|
return readPackageJson(dir)?.scripts?.test ?? null;
|
|
@@ -47607,7 +47527,7 @@ function buildTypescriptBackend() {
|
|
|
47607
47527
|
selectEntryPoints: selectEntryPoints3
|
|
47608
47528
|
};
|
|
47609
47529
|
}
|
|
47610
|
-
var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2,
|
|
47530
|
+
var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals23;
|
|
47611
47531
|
var init_typescript = __esm(() => {
|
|
47612
47532
|
init_default_backend();
|
|
47613
47533
|
init_profiles();
|
|
@@ -47616,7 +47536,7 @@ var init_typescript = __esm(() => {
|
|
|
47616
47536
|
IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
47617
47537
|
IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
47618
47538
|
IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
47619
|
-
|
|
47539
|
+
_internals23 = {
|
|
47620
47540
|
readPackageJsonRaw,
|
|
47621
47541
|
readPackageJsonTestScript,
|
|
47622
47542
|
frameworkFromScriptsTest
|
|
@@ -47647,7 +47567,7 @@ __export(exports_dispatch, {
|
|
|
47647
47567
|
pickedProfiles: () => pickedProfiles,
|
|
47648
47568
|
pickBackend: () => pickBackend,
|
|
47649
47569
|
clearDispatchCache: () => clearDispatchCache,
|
|
47650
|
-
_internals: () =>
|
|
47570
|
+
_internals: () => _internals24
|
|
47651
47571
|
});
|
|
47652
47572
|
import * as fs21 from "fs";
|
|
47653
47573
|
import * as path38 from "path";
|
|
@@ -47702,7 +47622,7 @@ function findManifestRoot(start) {
|
|
|
47702
47622
|
return start;
|
|
47703
47623
|
}
|
|
47704
47624
|
function evictIfNeeded() {
|
|
47705
|
-
if (cache.size <=
|
|
47625
|
+
if (cache.size <= _internals24.cacheCapacity)
|
|
47706
47626
|
return;
|
|
47707
47627
|
let oldestKey;
|
|
47708
47628
|
let oldestOrder = Infinity;
|
|
@@ -47733,7 +47653,7 @@ async function pickBackend(dir) {
|
|
|
47733
47653
|
evictIfNeeded();
|
|
47734
47654
|
return null;
|
|
47735
47655
|
}
|
|
47736
|
-
const profiles = await
|
|
47656
|
+
const profiles = await _internals24.detectProjectLanguages(root);
|
|
47737
47657
|
if (profiles.length === 0) {
|
|
47738
47658
|
cache.set(cacheKey, {
|
|
47739
47659
|
hash: hash3,
|
|
@@ -47765,12 +47685,12 @@ function clearDispatchCache() {
|
|
|
47765
47685
|
manifestRootCache.clear();
|
|
47766
47686
|
insertCounter = 0;
|
|
47767
47687
|
}
|
|
47768
|
-
var
|
|
47688
|
+
var _internals24, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
|
|
47769
47689
|
var init_dispatch = __esm(() => {
|
|
47770
47690
|
init_backends();
|
|
47771
47691
|
init_detector();
|
|
47772
47692
|
init_registry_backend();
|
|
47773
|
-
|
|
47693
|
+
_internals24 = {
|
|
47774
47694
|
detectProjectLanguages,
|
|
47775
47695
|
cacheCapacity: 64
|
|
47776
47696
|
};
|
|
@@ -49307,9 +49227,9 @@ function getVersionFileVersion(dir) {
|
|
|
49307
49227
|
async function runVersionCheck(dir, _timeoutMs) {
|
|
49308
49228
|
const startTime = Date.now();
|
|
49309
49229
|
try {
|
|
49310
|
-
const packageVersion =
|
|
49311
|
-
const changelogVersion =
|
|
49312
|
-
const versionFileVersion =
|
|
49230
|
+
const packageVersion = _internals25.getPackageVersion(dir);
|
|
49231
|
+
const changelogVersion = _internals25.getChangelogVersion(dir);
|
|
49232
|
+
const versionFileVersion = _internals25.getVersionFileVersion(dir);
|
|
49313
49233
|
const versions3 = [];
|
|
49314
49234
|
if (packageVersion)
|
|
49315
49235
|
versions3.push(`package.json: ${packageVersion}`);
|
|
@@ -49659,7 +49579,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49659
49579
|
const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
49660
49580
|
let validatedDir;
|
|
49661
49581
|
try {
|
|
49662
|
-
validatedDir =
|
|
49582
|
+
validatedDir = _internals25.validateDirectoryPath(dir);
|
|
49663
49583
|
} catch (error93) {
|
|
49664
49584
|
return {
|
|
49665
49585
|
id: reportId,
|
|
@@ -49679,7 +49599,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49679
49599
|
}
|
|
49680
49600
|
let validatedTimeout;
|
|
49681
49601
|
try {
|
|
49682
|
-
validatedTimeout =
|
|
49602
|
+
validatedTimeout = _internals25.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
49683
49603
|
} catch (error93) {
|
|
49684
49604
|
return {
|
|
49685
49605
|
id: reportId,
|
|
@@ -49720,12 +49640,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49720
49640
|
});
|
|
49721
49641
|
const checks5 = [];
|
|
49722
49642
|
log("[Preflight] Running lint check...");
|
|
49723
|
-
const lintResult = await
|
|
49643
|
+
const lintResult = await _internals25.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
49724
49644
|
checks5.push(lintResult);
|
|
49725
49645
|
log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
|
|
49726
49646
|
if (!cfg.skipTests) {
|
|
49727
49647
|
log("[Preflight] Running tests check...");
|
|
49728
|
-
const testsResult = await
|
|
49648
|
+
const testsResult = await _internals25.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
49729
49649
|
checks5.push(testsResult);
|
|
49730
49650
|
log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
|
|
49731
49651
|
} else {
|
|
@@ -49737,7 +49657,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49737
49657
|
}
|
|
49738
49658
|
if (!cfg.skipSecrets) {
|
|
49739
49659
|
log("[Preflight] Running secrets check...");
|
|
49740
|
-
const secretsResult = await
|
|
49660
|
+
const secretsResult = await _internals25.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
49741
49661
|
checks5.push(secretsResult);
|
|
49742
49662
|
log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
|
|
49743
49663
|
} else {
|
|
@@ -49749,7 +49669,7 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49749
49669
|
}
|
|
49750
49670
|
if (!cfg.skipEvidence) {
|
|
49751
49671
|
log("[Preflight] Running evidence check...");
|
|
49752
|
-
const evidenceResult = await
|
|
49672
|
+
const evidenceResult = await _internals25.runEvidenceCheck(validatedDir);
|
|
49753
49673
|
checks5.push(evidenceResult);
|
|
49754
49674
|
log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
|
|
49755
49675
|
} else {
|
|
@@ -49760,12 +49680,12 @@ async function runPreflight(dir, phase, config3) {
|
|
|
49760
49680
|
});
|
|
49761
49681
|
}
|
|
49762
49682
|
log("[Preflight] Running requirement coverage check...");
|
|
49763
|
-
const reqCoverageResult = await
|
|
49683
|
+
const reqCoverageResult = await _internals25.runRequirementCoverageCheck(validatedDir, phase);
|
|
49764
49684
|
checks5.push(reqCoverageResult);
|
|
49765
49685
|
log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
|
|
49766
49686
|
if (!cfg.skipVersion) {
|
|
49767
49687
|
log("[Preflight] Running version check...");
|
|
49768
|
-
const versionResult = await
|
|
49688
|
+
const versionResult = await _internals25.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
49769
49689
|
checks5.push(versionResult);
|
|
49770
49690
|
log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
|
|
49771
49691
|
} else {
|
|
@@ -49828,10 +49748,10 @@ function formatPreflightMarkdown(report) {
|
|
|
49828
49748
|
async function handlePreflightCommand(directory, _args) {
|
|
49829
49749
|
const plan = await loadPlan(directory);
|
|
49830
49750
|
const phase = plan?.current_phase ?? 1;
|
|
49831
|
-
const report = await
|
|
49832
|
-
return
|
|
49751
|
+
const report = await _internals25.runPreflight(directory, phase);
|
|
49752
|
+
return _internals25.formatPreflightMarkdown(report);
|
|
49833
49753
|
}
|
|
49834
|
-
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG,
|
|
49754
|
+
var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals25;
|
|
49835
49755
|
var init_preflight_service = __esm(() => {
|
|
49836
49756
|
init_manager2();
|
|
49837
49757
|
init_manager();
|
|
@@ -49848,7 +49768,7 @@ var init_preflight_service = __esm(() => {
|
|
|
49848
49768
|
testScope: "convention",
|
|
49849
49769
|
linter: "biome"
|
|
49850
49770
|
};
|
|
49851
|
-
|
|
49771
|
+
_internals25 = {
|
|
49852
49772
|
runPreflight,
|
|
49853
49773
|
formatPreflightMarkdown,
|
|
49854
49774
|
handlePreflightCommand,
|
|
@@ -51372,6 +51292,25 @@ var init_context_budget_service = __esm(() => {
|
|
|
51372
51292
|
});
|
|
51373
51293
|
|
|
51374
51294
|
// src/services/status-service.ts
|
|
51295
|
+
import * as fsSync2 from "fs";
|
|
51296
|
+
import * as path46 from "path";
|
|
51297
|
+
function readSpecStalenessSnapshot(directory) {
|
|
51298
|
+
try {
|
|
51299
|
+
const p = path46.join(directory, ".swarm", "spec-staleness.json");
|
|
51300
|
+
if (!fsSync2.existsSync(p))
|
|
51301
|
+
return { stale: false };
|
|
51302
|
+
const raw = fsSync2.readFileSync(p, "utf-8");
|
|
51303
|
+
const parsed = JSON.parse(raw);
|
|
51304
|
+
return {
|
|
51305
|
+
stale: true,
|
|
51306
|
+
reason: typeof parsed?.reason === "string" ? parsed.reason : undefined,
|
|
51307
|
+
storedHash: typeof parsed?.specHash_plan === "string" ? parsed.specHash_plan : undefined,
|
|
51308
|
+
currentHash: typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null ? parsed.specHash_current : undefined
|
|
51309
|
+
};
|
|
51310
|
+
} catch {
|
|
51311
|
+
return { stale: false };
|
|
51312
|
+
}
|
|
51313
|
+
}
|
|
51375
51314
|
async function getStatusData(directory, agents) {
|
|
51376
51315
|
const plan = await loadPlan(directory);
|
|
51377
51316
|
let status;
|
|
@@ -51437,11 +51376,21 @@ async function getStatusData(directory, agents) {
|
|
|
51437
51376
|
};
|
|
51438
51377
|
}
|
|
51439
51378
|
}
|
|
51379
|
+
const drift = readSpecStalenessSnapshot(directory);
|
|
51380
|
+
if (drift.stale) {
|
|
51381
|
+
status.specStale = true;
|
|
51382
|
+
status.specStaleReason = drift.reason;
|
|
51383
|
+
status.specStaleStoredHash = drift.storedHash;
|
|
51384
|
+
status.specStaleCurrentHash = drift.currentHash;
|
|
51385
|
+
} else if (plan && plan._specStale) {
|
|
51386
|
+
status.specStale = true;
|
|
51387
|
+
status.specStaleReason = plan._specStaleReason;
|
|
51388
|
+
}
|
|
51440
51389
|
return enrichWithLeanTurbo(status, directory);
|
|
51441
51390
|
}
|
|
51442
51391
|
function enrichWithLeanTurbo(status, directory) {
|
|
51443
51392
|
const turboMode = hasActiveTurboMode();
|
|
51444
|
-
const leanActive =
|
|
51393
|
+
const leanActive = _internals26.hasActiveLeanTurbo();
|
|
51445
51394
|
let turboStrategy = "off";
|
|
51446
51395
|
if (leanActive) {
|
|
51447
51396
|
turboStrategy = "lean";
|
|
@@ -51460,7 +51409,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
51460
51409
|
}
|
|
51461
51410
|
}
|
|
51462
51411
|
if (leanSessionID) {
|
|
51463
|
-
const runState =
|
|
51412
|
+
const runState = _internals26.loadLeanTurboRunState(directory, leanSessionID);
|
|
51464
51413
|
if (runState) {
|
|
51465
51414
|
status.leanTurboPhase = runState.phase;
|
|
51466
51415
|
status.leanMaxParallelCoders = runState.maxParallelCoders;
|
|
@@ -51492,7 +51441,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
51492
51441
|
}
|
|
51493
51442
|
}
|
|
51494
51443
|
}
|
|
51495
|
-
status.fullAutoActive =
|
|
51444
|
+
status.fullAutoActive = _internals26.hasActiveFullAuto();
|
|
51496
51445
|
return status;
|
|
51497
51446
|
}
|
|
51498
51447
|
function formatStatusMarkdown(status) {
|
|
@@ -51503,6 +51452,12 @@ function formatStatusMarkdown(status) {
|
|
|
51503
51452
|
`**Tasks**: ${status.completedTasks}/${status.totalTasks} complete`,
|
|
51504
51453
|
`**Agents**: ${status.agentCount} registered`
|
|
51505
51454
|
];
|
|
51455
|
+
if (status.specStale) {
|
|
51456
|
+
const reason = status.specStaleReason ?? "spec.md changed since plan saved";
|
|
51457
|
+
const stored = status.specStaleStoredHash ?? "unknown";
|
|
51458
|
+
const current = status.specStaleCurrentHash ?? "(spec.md missing)";
|
|
51459
|
+
lines.push("", `**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`, "Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss.");
|
|
51460
|
+
}
|
|
51506
51461
|
if (status.turboStrategy && status.turboStrategy !== "off") {
|
|
51507
51462
|
lines.push("");
|
|
51508
51463
|
if (status.turboStrategy === "lean") {
|
|
@@ -51552,11 +51507,23 @@ function formatStatusMarkdown(status) {
|
|
|
51552
51507
|
async function handleStatusCommand(directory, agents) {
|
|
51553
51508
|
const statusData = await getStatusData(directory, agents);
|
|
51554
51509
|
if (!statusData.hasPlan) {
|
|
51510
|
+
if (statusData.specStale) {
|
|
51511
|
+
const reason = statusData.specStaleReason ?? "spec.md changed since plan saved";
|
|
51512
|
+
const stored = statusData.specStaleStoredHash ?? "unknown";
|
|
51513
|
+
const current = statusData.specStaleCurrentHash ?? "(spec.md missing)";
|
|
51514
|
+
return [
|
|
51515
|
+
"No active swarm plan found.",
|
|
51516
|
+
"",
|
|
51517
|
+
`**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,
|
|
51518
|
+
"Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss."
|
|
51519
|
+
].join(`
|
|
51520
|
+
`);
|
|
51521
|
+
}
|
|
51555
51522
|
return "No active swarm plan found.";
|
|
51556
51523
|
}
|
|
51557
51524
|
return formatStatusMarkdown(statusData);
|
|
51558
51525
|
}
|
|
51559
|
-
var
|
|
51526
|
+
var _internals26;
|
|
51560
51527
|
var init_status_service = __esm(() => {
|
|
51561
51528
|
init_extractors();
|
|
51562
51529
|
init_utils2();
|
|
@@ -51565,7 +51532,7 @@ var init_status_service = __esm(() => {
|
|
|
51565
51532
|
init_state3();
|
|
51566
51533
|
init_compaction_service();
|
|
51567
51534
|
init_context_budget_service();
|
|
51568
|
-
|
|
51535
|
+
_internals26 = {
|
|
51569
51536
|
loadLeanTurboRunState,
|
|
51570
51537
|
hasActiveLeanTurbo,
|
|
51571
51538
|
hasActiveFullAuto
|
|
@@ -51656,7 +51623,7 @@ async function handleTurboCommand(directory, args, sessionID) {
|
|
|
51656
51623
|
if (arg0 === "on") {
|
|
51657
51624
|
let strategy = "standard";
|
|
51658
51625
|
try {
|
|
51659
|
-
const { config: config3 } =
|
|
51626
|
+
const { config: config3 } = _internals27.loadPluginConfigWithMeta(directory);
|
|
51660
51627
|
if (config3.turbo?.strategy === "lean") {
|
|
51661
51628
|
strategy = "lean";
|
|
51662
51629
|
}
|
|
@@ -51711,7 +51678,7 @@ function enableLeanTurbo(session, directory, sessionID) {
|
|
|
51711
51678
|
let maxParallelCoders = 4;
|
|
51712
51679
|
let conflictPolicy = "serialize";
|
|
51713
51680
|
try {
|
|
51714
|
-
const { config: config3 } =
|
|
51681
|
+
const { config: config3 } = _internals27.loadPluginConfigWithMeta(directory);
|
|
51715
51682
|
const leanConfig = config3.turbo?.lean;
|
|
51716
51683
|
if (leanConfig) {
|
|
51717
51684
|
maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
|
|
@@ -51781,13 +51748,13 @@ function buildStatusMessage(session, directory, sessionID) {
|
|
|
51781
51748
|
].join(`
|
|
51782
51749
|
`);
|
|
51783
51750
|
}
|
|
51784
|
-
var
|
|
51751
|
+
var _internals27;
|
|
51785
51752
|
var init_turbo = __esm(() => {
|
|
51786
51753
|
init_config();
|
|
51787
51754
|
init_state();
|
|
51788
51755
|
init_state3();
|
|
51789
51756
|
init_logger();
|
|
51790
|
-
|
|
51757
|
+
_internals27 = {
|
|
51791
51758
|
loadPluginConfigWithMeta
|
|
51792
51759
|
};
|
|
51793
51760
|
});
|
|
@@ -51853,6 +51820,270 @@ var init_write_retro2 = __esm(() => {
|
|
|
51853
51820
|
init_write_retro();
|
|
51854
51821
|
});
|
|
51855
51822
|
|
|
51823
|
+
// src/commands/command-dispatch.ts
|
|
51824
|
+
import fs28 from "fs";
|
|
51825
|
+
import path47 from "path";
|
|
51826
|
+
function normalizeSwarmCommandInput(command, argumentText) {
|
|
51827
|
+
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
51828
|
+
return { isSwarmCommand: false, tokens: [] };
|
|
51829
|
+
}
|
|
51830
|
+
if (command === "swarm") {
|
|
51831
|
+
return {
|
|
51832
|
+
isSwarmCommand: true,
|
|
51833
|
+
tokens: argumentText.trim().split(/\s+/).filter(Boolean)
|
|
51834
|
+
};
|
|
51835
|
+
}
|
|
51836
|
+
const subcommand = command.slice("swarm-".length);
|
|
51837
|
+
const extraArgs = argumentText.trim().split(/\s+/).filter(Boolean);
|
|
51838
|
+
return {
|
|
51839
|
+
isSwarmCommand: true,
|
|
51840
|
+
tokens: [subcommand, ...extraArgs].filter(Boolean)
|
|
51841
|
+
};
|
|
51842
|
+
}
|
|
51843
|
+
function canonicalCommandKey(resolved) {
|
|
51844
|
+
return resolved.entry.aliasOf ?? resolved.key;
|
|
51845
|
+
}
|
|
51846
|
+
function formatCommandNotFound(tokens) {
|
|
51847
|
+
const attemptedCommand = tokens[0] || "";
|
|
51848
|
+
const MAX_DISPLAY = 100;
|
|
51849
|
+
const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
|
|
51850
|
+
const similar = _internals28.findSimilarCommands(attemptedCommand);
|
|
51851
|
+
const header = `Command \`/swarm ${displayCommand}\` not found.`;
|
|
51852
|
+
const suggestions = similar.length > 0 ? `Did you mean:
|
|
51853
|
+
${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
51854
|
+
`)}` : "";
|
|
51855
|
+
const footer = "Run `/swarm help` for all commands.";
|
|
51856
|
+
return [header, suggestions, footer].filter(Boolean).join(`
|
|
51857
|
+
|
|
51858
|
+
`);
|
|
51859
|
+
}
|
|
51860
|
+
function maybeMarkFirstRun(directory) {
|
|
51861
|
+
const sentinelPath = path47.join(directory, ".swarm", ".first-run-complete");
|
|
51862
|
+
try {
|
|
51863
|
+
const swarmDir = path47.join(directory, ".swarm");
|
|
51864
|
+
fs28.mkdirSync(swarmDir, { recursive: true });
|
|
51865
|
+
fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
51866
|
+
`, { flag: "wx" });
|
|
51867
|
+
return true;
|
|
51868
|
+
} catch {
|
|
51869
|
+
return false;
|
|
51870
|
+
}
|
|
51871
|
+
}
|
|
51872
|
+
function prependWelcome(text) {
|
|
51873
|
+
const welcomeMessage = `Welcome to OpenCode Swarm!
|
|
51874
|
+
` + `
|
|
51875
|
+
` + `Run \`/swarm help\` to see all available commands, or \`/swarm config\` to review your configuration.
|
|
51876
|
+
`;
|
|
51877
|
+
return welcomeMessage + text;
|
|
51878
|
+
}
|
|
51879
|
+
async function executeSwarmCommand(args) {
|
|
51880
|
+
const {
|
|
51881
|
+
directory,
|
|
51882
|
+
agents,
|
|
51883
|
+
sessionID,
|
|
51884
|
+
tokens,
|
|
51885
|
+
includeWelcome = false,
|
|
51886
|
+
buildHelpText,
|
|
51887
|
+
policy
|
|
51888
|
+
} = args;
|
|
51889
|
+
let text;
|
|
51890
|
+
const resolved = resolveCommand(tokens);
|
|
51891
|
+
if (!resolved) {
|
|
51892
|
+
text = tokens.length === 0 && buildHelpText ? buildHelpText() : formatCommandNotFound(tokens);
|
|
51893
|
+
} else {
|
|
51894
|
+
const policyResult = policy?.(resolved) ?? { allowed: true };
|
|
51895
|
+
if (!policyResult.allowed) {
|
|
51896
|
+
text = policyResult.message;
|
|
51897
|
+
} else {
|
|
51898
|
+
try {
|
|
51899
|
+
text = await resolved.entry.handler({
|
|
51900
|
+
directory,
|
|
51901
|
+
args: resolved.remainingArgs,
|
|
51902
|
+
sessionID,
|
|
51903
|
+
agents
|
|
51904
|
+
});
|
|
51905
|
+
} catch (_err) {
|
|
51906
|
+
const cmdName = tokens[0] || "unknown";
|
|
51907
|
+
const errMsg = _err instanceof Error ? _err.message : String(_err);
|
|
51908
|
+
text = `Error executing /swarm ${cmdName}: ${errMsg}`;
|
|
51909
|
+
}
|
|
51910
|
+
if (resolved.warning) {
|
|
51911
|
+
text = `${resolved.warning}
|
|
51912
|
+
|
|
51913
|
+
${text}`;
|
|
51914
|
+
}
|
|
51915
|
+
}
|
|
51916
|
+
}
|
|
51917
|
+
if (includeWelcome && maybeMarkFirstRun(directory)) {
|
|
51918
|
+
text = prependWelcome(text);
|
|
51919
|
+
}
|
|
51920
|
+
return {
|
|
51921
|
+
text,
|
|
51922
|
+
resolved: resolved ?? undefined,
|
|
51923
|
+
canonicalKey: resolved ? canonicalCommandKey(resolved) : undefined
|
|
51924
|
+
};
|
|
51925
|
+
}
|
|
51926
|
+
var init_command_dispatch = __esm(() => {
|
|
51927
|
+
init_registry();
|
|
51928
|
+
});
|
|
51929
|
+
|
|
51930
|
+
// src/commands/tool-policy.ts
|
|
51931
|
+
function classifySwarmCommandToolUse(resolved) {
|
|
51932
|
+
const canonicalKey = canonicalCommandKey(resolved);
|
|
51933
|
+
const args = resolved.remainingArgs;
|
|
51934
|
+
if (!SWARM_COMMAND_TOOL_ALLOWLIST.has(canonicalKey)) {
|
|
51935
|
+
return {
|
|
51936
|
+
allowed: false,
|
|
51937
|
+
message: `/swarm ${canonicalKey} is not available through the chat tool yet.
|
|
51938
|
+
|
|
51939
|
+
` + `Use the canonical CLI path for now: \`bunx opencode-swarm run ${canonicalKey}\`.
|
|
51940
|
+
` + `Commands with state changes, auto-heal behavior, or subprocesses need confirmation gates before chat-tool support.`
|
|
51941
|
+
};
|
|
51942
|
+
}
|
|
51943
|
+
if (canonicalKey === "config doctor" && args.some((arg) => arg === "--fix" || arg === "-f")) {
|
|
51944
|
+
return {
|
|
51945
|
+
allowed: false,
|
|
51946
|
+
message: "/swarm config doctor --fix is not available through swarm_command. Run the CLI command directly when you intend to modify config files."
|
|
51947
|
+
};
|
|
51948
|
+
}
|
|
51949
|
+
if (NO_ARGS.has(canonicalKey) && args.length > 0) {
|
|
51950
|
+
return {
|
|
51951
|
+
allowed: false,
|
|
51952
|
+
message: `/swarm ${canonicalKey} does not accept arguments through swarm_command.`
|
|
51953
|
+
};
|
|
51954
|
+
}
|
|
51955
|
+
if (canonicalKey === "knowledge") {
|
|
51956
|
+
if (args.length === 0)
|
|
51957
|
+
return { allowed: true };
|
|
51958
|
+
if (args.length === 1 && args[0] === "list")
|
|
51959
|
+
return { allowed: true };
|
|
51960
|
+
return {
|
|
51961
|
+
allowed: false,
|
|
51962
|
+
message: "Only `/swarm knowledge` and `/swarm knowledge list` are available through swarm_command. Knowledge migrate/quarantine/restore are intentionally excluded."
|
|
51963
|
+
};
|
|
51964
|
+
}
|
|
51965
|
+
if (canonicalKey === "retrieve") {
|
|
51966
|
+
if (args.length !== 1 || !SUMMARY_ID_PATTERN.test(args[0])) {
|
|
51967
|
+
return {
|
|
51968
|
+
allowed: false,
|
|
51969
|
+
message: "Usage through swarm_command: `/swarm retrieve <summary-id>` with a single summary ID such as S1."
|
|
51970
|
+
};
|
|
51971
|
+
}
|
|
51972
|
+
}
|
|
51973
|
+
if (canonicalKey === "benchmark") {
|
|
51974
|
+
const allowedFlags = new Set(["--cumulative", "--ci-gate"]);
|
|
51975
|
+
const invalid = args.filter((arg) => !allowedFlags.has(arg));
|
|
51976
|
+
if (invalid.length > 0) {
|
|
51977
|
+
return {
|
|
51978
|
+
allowed: false,
|
|
51979
|
+
message: "Only `--cumulative` and `--ci-gate` are supported for `/swarm benchmark` through swarm_command."
|
|
51980
|
+
};
|
|
51981
|
+
}
|
|
51982
|
+
}
|
|
51983
|
+
if (canonicalKey === "show-plan") {
|
|
51984
|
+
if (args.length > 1 || args[0] && !/^\d+$/.test(args[0])) {
|
|
51985
|
+
return {
|
|
51986
|
+
allowed: false,
|
|
51987
|
+
message: "Usage through swarm_command: `/swarm show-plan` or `/swarm show-plan <phase-number>`."
|
|
51988
|
+
};
|
|
51989
|
+
}
|
|
51990
|
+
}
|
|
51991
|
+
if (canonicalKey === "evidence") {
|
|
51992
|
+
if (args.length > 1 || args[0] && !TASK_ID_PATTERN.test(args[0])) {
|
|
51993
|
+
return {
|
|
51994
|
+
allowed: false,
|
|
51995
|
+
message: "Usage through swarm_command: `/swarm evidence` or `/swarm evidence <task-id>`."
|
|
51996
|
+
};
|
|
51997
|
+
}
|
|
51998
|
+
}
|
|
51999
|
+
if (canonicalKey === "help" && args.length > 2) {
|
|
52000
|
+
return {
|
|
52001
|
+
allowed: false,
|
|
52002
|
+
message: "Usage through swarm_command: `/swarm help` or `/swarm help <command>`."
|
|
52003
|
+
};
|
|
52004
|
+
}
|
|
52005
|
+
return { allowed: true };
|
|
52006
|
+
}
|
|
52007
|
+
function classifySwarmCommandChatFallbackUse(resolved) {
|
|
52008
|
+
const canonicalKey = canonicalCommandKey(resolved);
|
|
52009
|
+
const args = resolved.remainingArgs;
|
|
52010
|
+
if (canonicalKey === "config doctor" && args.some((arg) => arg === "--fix" || arg === "-f")) {
|
|
52011
|
+
return {
|
|
52012
|
+
allowed: false,
|
|
52013
|
+
message: "/swarm config doctor --fix is not available through chat fallback because it can modify configuration files. Run the CLI command directly when you intend to apply fixes."
|
|
52014
|
+
};
|
|
52015
|
+
}
|
|
52016
|
+
if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore") {
|
|
52017
|
+
return {
|
|
52018
|
+
allowed: false,
|
|
52019
|
+
message: `/swarm ${canonicalKey} is not available through chat fallback because it mutates .swarm knowledge state. ` + "Run the CLI command directly after confirming the intended state change."
|
|
52020
|
+
};
|
|
52021
|
+
}
|
|
52022
|
+
return { allowed: true };
|
|
52023
|
+
}
|
|
52024
|
+
var SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, NO_ARGS, SUMMARY_ID_PATTERN, TASK_ID_PATTERN;
|
|
52025
|
+
var init_tool_policy = __esm(() => {
|
|
52026
|
+
init_command_dispatch();
|
|
52027
|
+
SWARM_COMMAND_TOOL_COMMANDS = [
|
|
52028
|
+
"agents",
|
|
52029
|
+
"config",
|
|
52030
|
+
"config doctor",
|
|
52031
|
+
"config-doctor",
|
|
52032
|
+
"doctor",
|
|
52033
|
+
"doctor tools",
|
|
52034
|
+
"status",
|
|
52035
|
+
"show-plan",
|
|
52036
|
+
"plan",
|
|
52037
|
+
"help",
|
|
52038
|
+
"history",
|
|
52039
|
+
"evidence",
|
|
52040
|
+
"evidence summary",
|
|
52041
|
+
"evidence-summary",
|
|
52042
|
+
"retrieve",
|
|
52043
|
+
"diagnose",
|
|
52044
|
+
"preflight",
|
|
52045
|
+
"benchmark",
|
|
52046
|
+
"knowledge",
|
|
52047
|
+
"sync-plan",
|
|
52048
|
+
"export",
|
|
52049
|
+
"list-agents"
|
|
52050
|
+
];
|
|
52051
|
+
SWARM_COMMAND_TOOL_ALLOWLIST = new Set([
|
|
52052
|
+
"agents",
|
|
52053
|
+
"config",
|
|
52054
|
+
"config doctor",
|
|
52055
|
+
"doctor tools",
|
|
52056
|
+
"status",
|
|
52057
|
+
"show-plan",
|
|
52058
|
+
"help",
|
|
52059
|
+
"history",
|
|
52060
|
+
"evidence",
|
|
52061
|
+
"evidence summary",
|
|
52062
|
+
"retrieve",
|
|
52063
|
+
"diagnose",
|
|
52064
|
+
"preflight",
|
|
52065
|
+
"benchmark",
|
|
52066
|
+
"knowledge",
|
|
52067
|
+
"sync-plan",
|
|
52068
|
+
"export"
|
|
52069
|
+
]);
|
|
52070
|
+
NO_ARGS = new Set([
|
|
52071
|
+
"agents",
|
|
52072
|
+
"config",
|
|
52073
|
+
"config doctor",
|
|
52074
|
+
"doctor tools",
|
|
52075
|
+
"status",
|
|
52076
|
+
"history",
|
|
52077
|
+
"evidence summary",
|
|
52078
|
+
"diagnose",
|
|
52079
|
+
"preflight",
|
|
52080
|
+
"sync-plan",
|
|
52081
|
+
"export"
|
|
52082
|
+
]);
|
|
52083
|
+
SUMMARY_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
52084
|
+
TASK_ID_PATTERN = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
52085
|
+
});
|
|
52086
|
+
|
|
51856
52087
|
// src/commands/command-names.ts
|
|
51857
52088
|
var COMMAND_NAMES, COMMAND_NAME_SET;
|
|
51858
52089
|
var init_command_names = __esm(() => {
|
|
@@ -51865,6 +52096,7 @@ var init_command_names = __esm(() => {
|
|
|
51865
52096
|
var exports_commands = {};
|
|
51866
52097
|
__export(exports_commands, {
|
|
51867
52098
|
resolveCommand: () => resolveCommand,
|
|
52099
|
+
normalizeSwarmCommandInput: () => normalizeSwarmCommandInput,
|
|
51868
52100
|
handleWriteRetroCommand: () => handleWriteRetroCommand,
|
|
51869
52101
|
handleTurboCommand: () => handleTurboCommand,
|
|
51870
52102
|
handleSyncPlanCommand: () => handleSyncPlanCommand,
|
|
@@ -51906,18 +52138,27 @@ __export(exports_commands, {
|
|
|
51906
52138
|
handleAnalyzeCommand: () => handleAnalyzeCommand,
|
|
51907
52139
|
handleAgentsCommand: () => handleAgentsCommand,
|
|
51908
52140
|
handleAcknowledgeSpecDriftCommand: () => handleAcknowledgeSpecDriftCommand,
|
|
52141
|
+
formatCommandNotFound: () => formatCommandNotFound,
|
|
52142
|
+
executeSwarmCommand: () => executeSwarmCommand,
|
|
51909
52143
|
createSwarmCommandHandler: () => createSwarmCommandHandler,
|
|
52144
|
+
classifySwarmCommandToolUse: () => classifySwarmCommandToolUse,
|
|
52145
|
+
classifySwarmCommandChatFallbackUse: () => classifySwarmCommandChatFallbackUse,
|
|
51910
52146
|
buildHelpText: () => buildHelpText,
|
|
52147
|
+
agentHasSwarmCommandTool: () => agentHasSwarmCommandTool,
|
|
51911
52148
|
VALID_COMMANDS: () => VALID_COMMANDS,
|
|
51912
|
-
|
|
52149
|
+
SWARM_COMMAND_TOOL_COMMANDS: () => SWARM_COMMAND_TOOL_COMMANDS,
|
|
52150
|
+
SWARM_COMMAND_TOOL_ALLOWLIST: () => SWARM_COMMAND_TOOL_ALLOWLIST,
|
|
51913
52151
|
COMMAND_REGISTRY: () => COMMAND_REGISTRY,
|
|
51914
52152
|
COMMAND_NAME_SET: () => COMMAND_NAME_SET,
|
|
51915
52153
|
COMMAND_NAMES: () => COMMAND_NAMES
|
|
51916
52154
|
});
|
|
51917
|
-
import fs28 from "fs";
|
|
51918
|
-
import path46 from "path";
|
|
51919
52155
|
function buildHelpText() {
|
|
51920
|
-
const lines = [
|
|
52156
|
+
const lines = [
|
|
52157
|
+
"## Swarm Commands",
|
|
52158
|
+
"",
|
|
52159
|
+
"**Chat routing note**: supported read-only `/swarm` commands are routed through the `swarm_command` tool when the active agent has that tool. Unsupported or state-changing commands remain chat-mediated; use `bunx opencode-swarm run <subcommand>` when you need canonical output.",
|
|
52160
|
+
""
|
|
52161
|
+
];
|
|
51921
52162
|
const CATEGORIES = [
|
|
51922
52163
|
"core",
|
|
51923
52164
|
"agent",
|
|
@@ -52012,92 +52253,127 @@ function buildHelpText() {
|
|
|
52012
52253
|
return lines.join(`
|
|
52013
52254
|
`);
|
|
52014
52255
|
}
|
|
52015
|
-
function createSwarmCommandHandler(directory, agents,
|
|
52256
|
+
function createSwarmCommandHandler(directory, agents, options = {}) {
|
|
52016
52257
|
return async (input, output) => {
|
|
52017
|
-
|
|
52258
|
+
const normalized = normalizeSwarmCommandInput(input.command, input.arguments);
|
|
52259
|
+
if (!normalized.isSwarmCommand) {
|
|
52018
52260
|
return;
|
|
52019
52261
|
}
|
|
52020
|
-
let isFirstRun = false;
|
|
52021
|
-
const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
|
|
52022
|
-
try {
|
|
52023
|
-
const swarmDir = path46.join(directory, ".swarm");
|
|
52024
|
-
fs28.mkdirSync(swarmDir, { recursive: true });
|
|
52025
|
-
fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
52026
|
-
`, { flag: "wx" });
|
|
52027
|
-
isFirstRun = true;
|
|
52028
|
-
} catch (_err) {}
|
|
52029
|
-
let tokens;
|
|
52030
|
-
if (input.command === "swarm") {
|
|
52031
|
-
tokens = input.arguments.trim().split(/\s+/).filter(Boolean);
|
|
52032
|
-
} else {
|
|
52033
|
-
const subcommand = input.command.slice("swarm-".length);
|
|
52034
|
-
const extraArgs = input.arguments.trim().split(/\s+/).filter(Boolean);
|
|
52035
|
-
tokens = [subcommand, ...extraArgs];
|
|
52036
|
-
}
|
|
52037
|
-
let text;
|
|
52038
|
-
const resolved = resolveCommand(tokens);
|
|
52039
|
-
if (!resolved) {
|
|
52040
|
-
if (tokens.length === 0) {
|
|
52041
|
-
text = buildHelpText();
|
|
52042
|
-
} else {
|
|
52043
|
-
const attemptedCommand = tokens[0] || "";
|
|
52044
|
-
const MAX_DISPLAY = 100;
|
|
52045
|
-
const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
|
|
52046
|
-
const similar = _internals26.findSimilarCommands(attemptedCommand);
|
|
52047
|
-
const header = `Command \`/swarm ${displayCommand}\` not found.`;
|
|
52048
|
-
const suggestions = similar.length > 0 ? `Did you mean:
|
|
52049
|
-
${similar.map((cmd) => ` \u2022 /swarm ${cmd}`).join(`
|
|
52050
|
-
`)}` : "";
|
|
52051
|
-
const footer = "Run `/swarm help` for all commands.";
|
|
52052
|
-
text = [header, suggestions, footer].filter(Boolean).join(`
|
|
52053
|
-
|
|
52054
|
-
`);
|
|
52055
|
-
}
|
|
52056
|
-
} else {
|
|
52057
|
-
try {
|
|
52058
|
-
text = await resolved.entry.handler({
|
|
52059
|
-
directory,
|
|
52060
|
-
args: resolved.remainingArgs,
|
|
52061
|
-
sessionID: input.sessionID,
|
|
52062
|
-
agents,
|
|
52063
|
-
client
|
|
52064
|
-
});
|
|
52065
|
-
} catch (_err) {
|
|
52066
|
-
const cmdName = tokens[0] || "unknown";
|
|
52067
|
-
const errMsg = _err instanceof Error ? _err.message : String(_err);
|
|
52068
|
-
text = `Error executing /swarm ${cmdName}: ${errMsg}`;
|
|
52069
|
-
}
|
|
52070
|
-
if (resolved.warning) {
|
|
52071
|
-
text = `${resolved.warning}
|
|
52072
|
-
|
|
52073
|
-
${text}`;
|
|
52074
|
-
}
|
|
52075
|
-
}
|
|
52076
|
-
if (isFirstRun) {
|
|
52077
|
-
const welcomeMessage = `Welcome to OpenCode Swarm! \uD83D\uDC1D
|
|
52078
|
-
` + `
|
|
52079
|
-
` + `Start here: run \`/swarm diagnose\`, then \`/swarm agents\` to confirm the plugin loaded and see the exact models in use.
|
|
52080
|
-
` + `If a model is unavailable, edit \`.opencode/opencode-swarm.json\` or \`~/.config/opencode/opencode-swarm.json\` and run \`/swarm config doctor\`.
|
|
52081
|
-
` + `Useful next steps: \`/swarm brainstorm <task>\` for guided planning, \`/swarm full-auto on\` for autonomous runs after enabling it in config, and \`/swarm council <question>\` after enabling council.general.
|
|
52082
|
-
|
|
52083
|
-
`;
|
|
52084
|
-
text = welcomeMessage + text;
|
|
52085
|
-
}
|
|
52086
52262
|
output.parts.splice(0, output.parts.length, {
|
|
52087
52263
|
type: "text",
|
|
52088
|
-
text
|
|
52264
|
+
text: await buildSwarmCommandPrompt({
|
|
52265
|
+
directory,
|
|
52266
|
+
agents,
|
|
52267
|
+
sessionID: input.sessionID,
|
|
52268
|
+
tokens: normalized.tokens,
|
|
52269
|
+
activeAgentName: options.getActiveAgentName?.(input.sessionID),
|
|
52270
|
+
registeredAgents: options.registeredAgents
|
|
52271
|
+
})
|
|
52089
52272
|
});
|
|
52273
|
+
return;
|
|
52090
52274
|
};
|
|
52091
52275
|
}
|
|
52092
|
-
|
|
52276
|
+
async function buildSwarmCommandPrompt(args) {
|
|
52277
|
+
const {
|
|
52278
|
+
directory,
|
|
52279
|
+
agents,
|
|
52280
|
+
sessionID,
|
|
52281
|
+
tokens,
|
|
52282
|
+
activeAgentName,
|
|
52283
|
+
registeredAgents
|
|
52284
|
+
} = args;
|
|
52285
|
+
const resolved = _internals28.resolveCommand(tokens);
|
|
52286
|
+
if (!resolved) {
|
|
52287
|
+
if (tokens.length === 0) {
|
|
52288
|
+
return buildHelpText();
|
|
52289
|
+
}
|
|
52290
|
+
return formatCommandNotFound(tokens);
|
|
52291
|
+
}
|
|
52292
|
+
const typedResolved = resolved;
|
|
52293
|
+
const canonicalKey = canonicalCommandKey(typedResolved);
|
|
52294
|
+
const policy = classifySwarmCommandToolUse(typedResolved);
|
|
52295
|
+
const isV1ToolCommand = SWARM_COMMAND_TOOL_ALLOWLIST.has(canonicalKey);
|
|
52296
|
+
const canUseTool = agentHasSwarmCommandTool(activeAgentName, agents, registeredAgents);
|
|
52297
|
+
if (canUseTool && policy.allowed && isV1ToolCommand) {
|
|
52298
|
+
return routeToSwarmCommandTool({
|
|
52299
|
+
command: canonicalKey,
|
|
52300
|
+
args: resolved.remainingArgs,
|
|
52301
|
+
original: `/swarm ${tokens.join(" ")}`.trim()
|
|
52302
|
+
});
|
|
52303
|
+
}
|
|
52304
|
+
if (canUseTool && isV1ToolCommand && !policy.allowed) {
|
|
52305
|
+
return [
|
|
52306
|
+
`The user typed \`/swarm ${tokens.join(" ")}\`.`,
|
|
52307
|
+
policy.message,
|
|
52308
|
+
"Do not invent command output. Explain the limitation and recommend the canonical CLI path above."
|
|
52309
|
+
].join(`
|
|
52310
|
+
`);
|
|
52311
|
+
}
|
|
52312
|
+
const chatFallbackPolicy = classifySwarmCommandChatFallbackUse(typedResolved);
|
|
52313
|
+
if (!chatFallbackPolicy.allowed) {
|
|
52314
|
+
return [
|
|
52315
|
+
`The user typed \`/swarm ${tokens.join(" ")}\`.`,
|
|
52316
|
+
chatFallbackPolicy.message,
|
|
52317
|
+
"Do not execute this command through chat and do not invent command output."
|
|
52318
|
+
].join(`
|
|
52319
|
+
`);
|
|
52320
|
+
}
|
|
52321
|
+
const result = await executeSwarmCommand({
|
|
52322
|
+
directory,
|
|
52323
|
+
agents,
|
|
52324
|
+
sessionID,
|
|
52325
|
+
tokens
|
|
52326
|
+
});
|
|
52327
|
+
return formatCanonicalPromptFallback({
|
|
52328
|
+
original: `/swarm ${tokens.join(" ")}`.trim(),
|
|
52329
|
+
text: result.text
|
|
52330
|
+
});
|
|
52331
|
+
}
|
|
52332
|
+
function agentHasSwarmCommandTool(activeAgentName, agents, registeredAgents) {
|
|
52333
|
+
const name = activeAgentName ?? ORCHESTRATOR_NAME;
|
|
52334
|
+
const registeredTools = registeredAgents?.[name]?.tools;
|
|
52335
|
+
if (registeredTools) {
|
|
52336
|
+
return registeredTools.swarm_command === true;
|
|
52337
|
+
}
|
|
52338
|
+
const explicitTools = agents[name]?.config?.tools;
|
|
52339
|
+
if (explicitTools) {
|
|
52340
|
+
return explicitTools.swarm_command === true;
|
|
52341
|
+
}
|
|
52342
|
+
const baseName = stripKnownSwarmPrefix(name);
|
|
52343
|
+
return AGENT_TOOL_MAP[baseName]?.includes("swarm_command") === true;
|
|
52344
|
+
}
|
|
52345
|
+
function formatCanonicalPromptFallback(args) {
|
|
52346
|
+
return [
|
|
52347
|
+
`The user typed \`${args.original}\`.`,
|
|
52348
|
+
"Canonical opencode-swarm command output follows.",
|
|
52349
|
+
"Show this output verbatim and add no extra swarm state.",
|
|
52350
|
+
"",
|
|
52351
|
+
args.text
|
|
52352
|
+
].join(`
|
|
52353
|
+
`);
|
|
52354
|
+
}
|
|
52355
|
+
function routeToSwarmCommandTool(args) {
|
|
52356
|
+
return [
|
|
52357
|
+
`The user typed \`${args.original}\`.`,
|
|
52358
|
+
"Call the `swarm_command` tool exactly once with:",
|
|
52359
|
+
JSON.stringify({ command: args.command, args: args.args }, null, 2),
|
|
52360
|
+
"After the tool returns, show the tool output verbatim and add no extra swarm state."
|
|
52361
|
+
].join(`
|
|
52362
|
+
`);
|
|
52363
|
+
}
|
|
52093
52364
|
var init_commands = __esm(() => {
|
|
52365
|
+
init_constants();
|
|
52366
|
+
init_schema();
|
|
52367
|
+
init_command_dispatch();
|
|
52094
52368
|
init_registry();
|
|
52369
|
+
init_tool_policy();
|
|
52095
52370
|
init_acknowledge_spec_drift();
|
|
52096
52371
|
init_agents();
|
|
52097
52372
|
init_archive();
|
|
52098
52373
|
init_benchmark();
|
|
52099
52374
|
init_checkpoint2();
|
|
52100
52375
|
init_close();
|
|
52376
|
+
init_command_dispatch();
|
|
52101
52377
|
init_command_names();
|
|
52102
52378
|
init_config2();
|
|
52103
52379
|
init_council();
|
|
@@ -52125,10 +52401,9 @@ var init_commands = __esm(() => {
|
|
|
52125
52401
|
init_simulate();
|
|
52126
52402
|
init_status();
|
|
52127
52403
|
init_sync_plan();
|
|
52404
|
+
init_tool_policy();
|
|
52128
52405
|
init_turbo();
|
|
52129
52406
|
init_write_retro2();
|
|
52130
|
-
LLM_MEDIATION_WARNING = "> \u26A0\uFE0F Chat-typed `/swarm` is LLM-mediated in current OpenCode (see anomalyco/opencode#9306).\n" + `> The text below is the canonical handler output, but the model may rephrase it before display.
|
|
52131
|
-
` + "> For deterministic output, run `bunx opencode-swarm run <subcommand>` from a terminal.";
|
|
52132
52407
|
});
|
|
52133
52408
|
|
|
52134
52409
|
// src/commands/registry.ts
|
|
@@ -52158,7 +52433,7 @@ function findSimilarCommands(query) {
|
|
|
52158
52433
|
}
|
|
52159
52434
|
const scored = VALID_COMMANDS.map((cmd) => {
|
|
52160
52435
|
const cmdLower = cmd.toLowerCase();
|
|
52161
|
-
const fullScore =
|
|
52436
|
+
const fullScore = _internals28.levenshteinDistance(q, cmdLower);
|
|
52162
52437
|
let tokenScore = Infinity;
|
|
52163
52438
|
if (cmd.includes(" ") || cmd.includes("-")) {
|
|
52164
52439
|
const qTokens = q.split(/[\s-]+/);
|
|
@@ -52171,7 +52446,7 @@ function findSimilarCommands(query) {
|
|
|
52171
52446
|
for (const ct of cmdTokens) {
|
|
52172
52447
|
if (ct.length === 0)
|
|
52173
52448
|
continue;
|
|
52174
|
-
const dist =
|
|
52449
|
+
const dist = _internals28.levenshteinDistance(qt, ct);
|
|
52175
52450
|
if (dist < minDist)
|
|
52176
52451
|
minDist = dist;
|
|
52177
52452
|
}
|
|
@@ -52181,7 +52456,7 @@ function findSimilarCommands(query) {
|
|
|
52181
52456
|
}
|
|
52182
52457
|
const dashStrippedQ = q.replace(/-/g, "");
|
|
52183
52458
|
const dashStrippedCmd = cmdLower.replace(/-/g, "");
|
|
52184
|
-
const dashScore =
|
|
52459
|
+
const dashScore = _internals28.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
|
|
52185
52460
|
const score = Math.min(fullScore, tokenScore, dashScore);
|
|
52186
52461
|
return { cmd, score };
|
|
52187
52462
|
});
|
|
@@ -52213,11 +52488,11 @@ async function handleHelpCommand(ctx) {
|
|
|
52213
52488
|
return buildHelpText2();
|
|
52214
52489
|
}
|
|
52215
52490
|
const tokens = targetCommand.split(/\s+/);
|
|
52216
|
-
const resolved =
|
|
52491
|
+
const resolved = _internals28.resolveCommand(tokens);
|
|
52217
52492
|
if (resolved) {
|
|
52218
|
-
return
|
|
52493
|
+
return _internals28.buildDetailedHelp(resolved.key, resolved.entry);
|
|
52219
52494
|
}
|
|
52220
|
-
const similar =
|
|
52495
|
+
const similar = _internals28.findSimilarCommands(targetCommand);
|
|
52221
52496
|
const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
|
|
52222
52497
|
if (similar.length > 0) {
|
|
52223
52498
|
return `Command '/swarm ${targetCommand}' not found.
|
|
@@ -52253,24 +52528,24 @@ function validateAliases() {
|
|
|
52253
52528
|
}
|
|
52254
52529
|
aliasTargets.get(target).push(name);
|
|
52255
52530
|
const visited = new Set;
|
|
52256
|
-
const
|
|
52531
|
+
const path48 = [];
|
|
52257
52532
|
let current = target;
|
|
52258
52533
|
while (current) {
|
|
52259
52534
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
52260
52535
|
if (!currentEntry)
|
|
52261
52536
|
break;
|
|
52262
52537
|
if (visited.has(current)) {
|
|
52263
|
-
const cycleStart =
|
|
52538
|
+
const cycleStart = path48.indexOf(current);
|
|
52264
52539
|
const fullChain = [
|
|
52265
52540
|
name,
|
|
52266
|
-
...
|
|
52541
|
+
...path48.slice(0, cycleStart > 0 ? cycleStart : path48.length),
|
|
52267
52542
|
current
|
|
52268
52543
|
].join(" \u2192 ");
|
|
52269
52544
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
52270
52545
|
break;
|
|
52271
52546
|
}
|
|
52272
52547
|
visited.add(current);
|
|
52273
|
-
|
|
52548
|
+
path48.push(current);
|
|
52274
52549
|
current = currentEntry.aliasOf || "";
|
|
52275
52550
|
}
|
|
52276
52551
|
}
|
|
@@ -52311,7 +52586,7 @@ function resolveCommand(tokens) {
|
|
|
52311
52586
|
}
|
|
52312
52587
|
return null;
|
|
52313
52588
|
}
|
|
52314
|
-
var COMMAND_REGISTRY, VALID_COMMANDS,
|
|
52589
|
+
var COMMAND_REGISTRY, VALID_COMMANDS, _internals28, validation;
|
|
52315
52590
|
var init_registry = __esm(() => {
|
|
52316
52591
|
init_acknowledge_spec_drift();
|
|
52317
52592
|
init_agents();
|
|
@@ -52381,7 +52656,7 @@ var init_registry = __esm(() => {
|
|
|
52381
52656
|
clashesWithNativeCcCommand: "/agents"
|
|
52382
52657
|
},
|
|
52383
52658
|
help: {
|
|
52384
|
-
handler: (ctx) =>
|
|
52659
|
+
handler: (ctx) => _internals28.handleHelpCommand(ctx),
|
|
52385
52660
|
description: "Show help for swarm commands",
|
|
52386
52661
|
category: "core",
|
|
52387
52662
|
args: "[command]",
|
|
@@ -52400,13 +52675,13 @@ var init_registry = __esm(() => {
|
|
|
52400
52675
|
clashesWithNativeCcCommand: "/config"
|
|
52401
52676
|
},
|
|
52402
52677
|
"config doctor": {
|
|
52403
|
-
handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args
|
|
52678
|
+
handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args),
|
|
52404
52679
|
description: "Run config doctor checks",
|
|
52405
52680
|
subcommandOf: "config",
|
|
52406
52681
|
category: "diagnostics"
|
|
52407
52682
|
},
|
|
52408
52683
|
"config-doctor": {
|
|
52409
|
-
handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args
|
|
52684
|
+
handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args),
|
|
52410
52685
|
description: "Run config doctor checks",
|
|
52411
52686
|
subcommandOf: "config",
|
|
52412
52687
|
category: "diagnostics",
|
|
@@ -52481,7 +52756,7 @@ var init_registry = __esm(() => {
|
|
|
52481
52756
|
deprecated: true
|
|
52482
52757
|
},
|
|
52483
52758
|
doctor: {
|
|
52484
|
-
handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args
|
|
52759
|
+
handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args),
|
|
52485
52760
|
description: "Run config doctor checks",
|
|
52486
52761
|
category: "diagnostics",
|
|
52487
52762
|
aliasOf: "config doctor",
|
|
@@ -52753,7 +53028,7 @@ Subcommands:
|
|
|
52753
53028
|
}
|
|
52754
53029
|
};
|
|
52755
53030
|
VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
|
|
52756
|
-
|
|
53031
|
+
_internals28 = {
|
|
52757
53032
|
handleHelpCommand,
|
|
52758
53033
|
validateAliases,
|
|
52759
53034
|
resolveCommand,
|
|
@@ -52761,7 +53036,7 @@ Subcommands:
|
|
|
52761
53036
|
findSimilarCommands,
|
|
52762
53037
|
buildDetailedHelp
|
|
52763
53038
|
};
|
|
52764
|
-
validation =
|
|
53039
|
+
validation = _internals28.validateAliases();
|
|
52765
53040
|
if (!validation.valid) {
|
|
52766
53041
|
throw new Error(`COMMAND_REGISTRY alias validation failed:
|
|
52767
53042
|
${validation.errors.join(`
|
|
@@ -52781,53 +53056,53 @@ init_cache_paths();
|
|
|
52781
53056
|
init_constants();
|
|
52782
53057
|
import * as fs29 from "fs";
|
|
52783
53058
|
import * as os7 from "os";
|
|
52784
|
-
import * as
|
|
53059
|
+
import * as path48 from "path";
|
|
52785
53060
|
var { version: version4 } = package_default;
|
|
52786
53061
|
var CONFIG_DIR = getPluginConfigDir();
|
|
52787
|
-
var OPENCODE_CONFIG_PATH =
|
|
52788
|
-
var PLUGIN_CONFIG_PATH =
|
|
52789
|
-
var PROMPTS_DIR =
|
|
53062
|
+
var OPENCODE_CONFIG_PATH = path48.join(CONFIG_DIR, "opencode.json");
|
|
53063
|
+
var PLUGIN_CONFIG_PATH = path48.join(CONFIG_DIR, "opencode-swarm.json");
|
|
53064
|
+
var PROMPTS_DIR = path48.join(CONFIG_DIR, "opencode-swarm");
|
|
52790
53065
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
52791
53066
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
52792
53067
|
function isSafeCachePath(p) {
|
|
52793
|
-
const resolved =
|
|
52794
|
-
const home =
|
|
53068
|
+
const resolved = path48.resolve(p);
|
|
53069
|
+
const home = path48.resolve(os7.homedir());
|
|
52795
53070
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
52796
53071
|
return false;
|
|
52797
53072
|
}
|
|
52798
|
-
const segments = resolved.split(
|
|
53073
|
+
const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
|
|
52799
53074
|
if (segments.length < 4) {
|
|
52800
53075
|
return false;
|
|
52801
53076
|
}
|
|
52802
|
-
const leaf =
|
|
53077
|
+
const leaf = path48.basename(resolved);
|
|
52803
53078
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
52804
53079
|
return false;
|
|
52805
53080
|
}
|
|
52806
|
-
const parent =
|
|
53081
|
+
const parent = path48.basename(path48.dirname(resolved));
|
|
52807
53082
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
52808
53083
|
return false;
|
|
52809
53084
|
}
|
|
52810
|
-
const grandparent =
|
|
53085
|
+
const grandparent = path48.basename(path48.dirname(path48.dirname(resolved)));
|
|
52811
53086
|
if (grandparent !== "opencode") {
|
|
52812
53087
|
return false;
|
|
52813
53088
|
}
|
|
52814
53089
|
return true;
|
|
52815
53090
|
}
|
|
52816
53091
|
function isSafeLockFilePath(p) {
|
|
52817
|
-
const resolved =
|
|
52818
|
-
const home =
|
|
53092
|
+
const resolved = path48.resolve(p);
|
|
53093
|
+
const home = path48.resolve(os7.homedir());
|
|
52819
53094
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
52820
53095
|
return false;
|
|
52821
53096
|
}
|
|
52822
|
-
const segments = resolved.split(
|
|
53097
|
+
const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
|
|
52823
53098
|
if (segments.length < 4) {
|
|
52824
53099
|
return false;
|
|
52825
53100
|
}
|
|
52826
|
-
const leaf =
|
|
53101
|
+
const leaf = path48.basename(resolved);
|
|
52827
53102
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
52828
53103
|
return false;
|
|
52829
53104
|
}
|
|
52830
|
-
const parent =
|
|
53105
|
+
const parent = path48.basename(path48.dirname(resolved));
|
|
52831
53106
|
if (parent !== "opencode") {
|
|
52832
53107
|
return false;
|
|
52833
53108
|
}
|
|
@@ -52853,8 +53128,8 @@ function saveJson(filepath, data) {
|
|
|
52853
53128
|
}
|
|
52854
53129
|
function writeProjectConfigIfMissing(cwd) {
|
|
52855
53130
|
try {
|
|
52856
|
-
const opencodeDir =
|
|
52857
|
-
const projectConfigPath =
|
|
53131
|
+
const opencodeDir = path48.join(cwd, ".opencode");
|
|
53132
|
+
const projectConfigPath = path48.join(opencodeDir, "opencode-swarm.json");
|
|
52858
53133
|
if (fs29.existsSync(projectConfigPath)) {
|
|
52859
53134
|
return;
|
|
52860
53135
|
}
|
|
@@ -52871,7 +53146,7 @@ async function install() {
|
|
|
52871
53146
|
`);
|
|
52872
53147
|
ensureDir(CONFIG_DIR);
|
|
52873
53148
|
ensureDir(PROMPTS_DIR);
|
|
52874
|
-
const LEGACY_CONFIG_PATH =
|
|
53149
|
+
const LEGACY_CONFIG_PATH = path48.join(CONFIG_DIR, "config.json");
|
|
52875
53150
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
52876
53151
|
if (!opencodeConfig) {
|
|
52877
53152
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|