opencode-swarm 7.83.0 → 7.84.0
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 +3 -1
- package/dist/cli/capability-probe-jevmgwmf.js +18 -0
- package/dist/cli/config-doctor-4tcdd9vt.js +35 -0
- package/dist/cli/dispatch-k86d928w.js +477 -0
- package/dist/cli/evidence-summary-service-g2znnd33.js +320 -0
- package/dist/cli/explorer-gz70sm9b.js +16 -0
- package/dist/cli/gate-evidence-y8zn7fe2.js +29 -0
- package/dist/cli/guardrail-explain-tcamcdfy.js +30 -0
- package/dist/cli/guardrail-log-fd14n96q.js +15 -0
- package/dist/cli/index-293f68mj.js +13538 -0
- package/dist/cli/index-8ra2qpk8.js +29027 -0
- package/dist/cli/index-a76rekgs.js +67 -0
- package/dist/cli/index-a82d6d87.js +1241 -0
- package/dist/cli/index-b9v501fr.js +371 -0
- package/dist/cli/index-bcp79s17.js +1673 -0
- package/dist/cli/index-ckntc5gf.js +91 -0
- package/dist/cli/index-d9fbxaqd.js +2314 -0
- package/dist/cli/index-e7h9bb6v.js +233 -0
- package/dist/cli/index-e8pk68cc.js +540 -0
- package/dist/cli/index-eb85wtx9.js +242 -0
- package/dist/cli/index-f8r50m3h.js +14505 -0
- package/dist/cli/index-fjwwrwr5.js +37 -0
- package/dist/cli/index-hz59hg4h.js +452 -0
- package/dist/cli/index-j710h2ge.js +412 -0
- package/dist/cli/index-jfgr5gye.js +110 -0
- package/dist/cli/index-jtqkh8jf.js +119 -0
- package/dist/cli/index-p0arc26j.js +28 -0
- package/dist/cli/index-p0ye10nd.js +222 -0
- package/dist/cli/index-pv2xmc9k.js +2391 -0
- package/dist/cli/index-red8fm8p.js +2914 -0
- package/dist/cli/index-wg3r6acj.js +2042 -0
- package/dist/cli/index-xw0bcy0v.js +583 -0
- package/dist/cli/index-yhsmmv2z.js +339 -0
- package/dist/cli/index-yx44zd0p.js +40 -0
- package/dist/cli/index-zfsbaaqh.js +29 -0
- package/dist/cli/index.js +73 -69708
- package/dist/cli/knowledge-store-n4x6zyk7.js +73 -0
- package/dist/cli/pending-delegations-pz61mrsz.js +255 -0
- package/dist/cli/pr-subscriptions-y1nn36e5.js +33 -0
- package/dist/cli/schema-c2dbzhm8.js +168 -0
- package/dist/cli/skill-generator-a5ehggyg.js +55 -0
- package/dist/cli/task-envelope-qn0qtnh0.js +90 -0
- package/dist/cli/telemetry-9bbyxrvn.js +20 -0
- package/dist/cli/workspace-snapshot-w58jr2ga.js +90 -0
- package/dist/commands/guardrail-explain.d.ts +1 -0
- package/dist/commands/guardrail-log.d.ts +1 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/hooks/guardrails/audit-log.d.ts +114 -0
- package/dist/index.js +3569 -2366
- package/dist/services/diagnose-service.d.ts +5 -0
- package/dist/services/guardrail-explain-service.d.ts +42 -0
- package/dist/services/guardrail-log-service.d.ts +10 -0
- package/package.json +2 -2
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
handleGuardrailExplain
|
|
4
|
+
} from "./index-xw0bcy0v.js";
|
|
5
|
+
import {
|
|
6
|
+
handleGuardrailLog
|
|
7
|
+
} from "./index-jfgr5gye.js";
|
|
8
|
+
import {
|
|
9
|
+
COMMAND_REGISTRY,
|
|
10
|
+
SWARM_COMMAND_TOOL_ALLOWLIST,
|
|
11
|
+
SWARM_COMMAND_TOOL_COMMANDS,
|
|
12
|
+
VALID_COMMANDS,
|
|
13
|
+
_internals,
|
|
14
|
+
canonicalCommandKey,
|
|
15
|
+
classifySwarmCommandChatFallbackUse,
|
|
16
|
+
classifySwarmCommandToolUse,
|
|
17
|
+
executeSwarmCommand,
|
|
18
|
+
formatCommandNotFound,
|
|
19
|
+
handleAcknowledgeSpecDriftCommand,
|
|
20
|
+
handleAgentsCommand,
|
|
21
|
+
handleAnalyzeCommand,
|
|
22
|
+
handleArchiveCommand,
|
|
23
|
+
handleAutoProceedCommand,
|
|
24
|
+
handleBenchmarkCommand,
|
|
25
|
+
handleBrainstormCommand,
|
|
26
|
+
handleCheckpointCommand,
|
|
27
|
+
handleClarifyCommand,
|
|
28
|
+
handleCloseCommand,
|
|
29
|
+
handleCodebaseReviewCommand,
|
|
30
|
+
handleConcurrencyCommand,
|
|
31
|
+
handleConfigCommand,
|
|
32
|
+
handleConsolidateCommand,
|
|
33
|
+
handleCouncilCommand,
|
|
34
|
+
handleCurateCommand,
|
|
35
|
+
handleDarkMatterCommand,
|
|
36
|
+
handleDeepDiveCommand,
|
|
37
|
+
handleDeepResearchCommand,
|
|
38
|
+
handleDiagnoseCommand,
|
|
39
|
+
handleDoctorCommand,
|
|
40
|
+
handleEvidenceCommand,
|
|
41
|
+
handleEvidenceSummaryCommand,
|
|
42
|
+
handleExportCommand,
|
|
43
|
+
handleFullAutoCommand,
|
|
44
|
+
handleHandoffCommand,
|
|
45
|
+
handleHelpCommand,
|
|
46
|
+
handleHistoryCommand,
|
|
47
|
+
handleKnowledgeListCommand,
|
|
48
|
+
handleKnowledgeMigrateCommand,
|
|
49
|
+
handleKnowledgeQuarantineCommand,
|
|
50
|
+
handleKnowledgeRestoreCommand,
|
|
51
|
+
handleKnowledgeRetryHardeningCommand,
|
|
52
|
+
handleKnowledgeUnactionableCommand,
|
|
53
|
+
handleLearningCommand,
|
|
54
|
+
handleMemoryCommand,
|
|
55
|
+
handleMemoryExportCommand,
|
|
56
|
+
handleMemoryImportCommand,
|
|
57
|
+
handleMemoryMigrateCommand,
|
|
58
|
+
handleMemoryStatusCommand,
|
|
59
|
+
handlePlanCommand,
|
|
60
|
+
handlePreflightCommand,
|
|
61
|
+
handlePromoteCommand,
|
|
62
|
+
handleQaGatesCommand,
|
|
63
|
+
handleResetCommand,
|
|
64
|
+
handleResetSessionCommand,
|
|
65
|
+
handleRetrieveCommand,
|
|
66
|
+
handleRollbackCommand,
|
|
67
|
+
handleSddCommand,
|
|
68
|
+
handleSddProjectCommand,
|
|
69
|
+
handleSddStatusCommand,
|
|
70
|
+
handleSddValidateCommand,
|
|
71
|
+
handleSimulateCommand,
|
|
72
|
+
handleSpecifyCommand,
|
|
73
|
+
handleStatusCommand,
|
|
74
|
+
handleSyncPlanCommand,
|
|
75
|
+
handleTurboCommand,
|
|
76
|
+
handleWriteRetroCommand,
|
|
77
|
+
normalizeSwarmCommandInput,
|
|
78
|
+
resolveCommand
|
|
79
|
+
} from "./index-8ra2qpk8.js";
|
|
80
|
+
import"./index-pv2xmc9k.js";
|
|
81
|
+
import"./index-yhsmmv2z.js";
|
|
82
|
+
import"./index-d9fbxaqd.js";
|
|
83
|
+
import"./index-e8pk68cc.js";
|
|
84
|
+
import"./index-a82d6d87.js";
|
|
85
|
+
import {
|
|
86
|
+
AGENT_TOOL_MAP,
|
|
87
|
+
ORCHESTRATOR_NAME,
|
|
88
|
+
stripKnownSwarmPrefix
|
|
89
|
+
} from "./index-wg3r6acj.js";
|
|
90
|
+
import"./index-red8fm8p.js";
|
|
91
|
+
import"./index-f8r50m3h.js";
|
|
92
|
+
import"./index-hz59hg4h.js";
|
|
93
|
+
import"./index-e7h9bb6v.js";
|
|
94
|
+
import"./index-fjwwrwr5.js";
|
|
95
|
+
import"./index-eb85wtx9.js";
|
|
96
|
+
import"./index-ckntc5gf.js";
|
|
97
|
+
import"./index-jtqkh8jf.js";
|
|
98
|
+
import"./index-zfsbaaqh.js";
|
|
99
|
+
import"./index-p0arc26j.js";
|
|
100
|
+
import"./index-yx44zd0p.js";
|
|
101
|
+
import"./index-bcp79s17.js";
|
|
102
|
+
import"./index-293f68mj.js";
|
|
103
|
+
import"./index-b9v501fr.js";
|
|
104
|
+
import"./index-p0ye10nd.js";
|
|
105
|
+
import"./index-a76rekgs.js";
|
|
106
|
+
// src/commands/command-names.ts
|
|
107
|
+
var COMMAND_NAMES = Object.freeze(Object.keys(COMMAND_REGISTRY));
|
|
108
|
+
var COMMAND_NAME_SET = new Set(COMMAND_NAMES);
|
|
109
|
+
|
|
110
|
+
// src/commands/index.ts
|
|
111
|
+
function buildHelpText() {
|
|
112
|
+
const lines = [
|
|
113
|
+
"## Swarm Commands",
|
|
114
|
+
"",
|
|
115
|
+
"**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.",
|
|
116
|
+
""
|
|
117
|
+
];
|
|
118
|
+
const CATEGORIES = [
|
|
119
|
+
"core",
|
|
120
|
+
"agent",
|
|
121
|
+
"config",
|
|
122
|
+
"diagnostics",
|
|
123
|
+
"utility"
|
|
124
|
+
];
|
|
125
|
+
const byCategory = new Map;
|
|
126
|
+
for (const cat of CATEGORIES) {
|
|
127
|
+
byCategory.set(cat, []);
|
|
128
|
+
}
|
|
129
|
+
const deprecatedAliases = [];
|
|
130
|
+
for (const cmd of VALID_COMMANDS) {
|
|
131
|
+
const entry = COMMAND_REGISTRY[cmd];
|
|
132
|
+
if (entry.aliasOf) {
|
|
133
|
+
deprecatedAliases.push({ name: cmd, aliasOf: entry.aliasOf });
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (entry.subcommandOf) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (cmd.includes(" ")) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const category = entry.category || "utility";
|
|
143
|
+
const catLines = byCategory.get(category) || [];
|
|
144
|
+
catLines.push(cmd);
|
|
145
|
+
byCategory.set(category, catLines);
|
|
146
|
+
}
|
|
147
|
+
const shownAsSubcommand = new Set;
|
|
148
|
+
for (const cat of CATEGORIES) {
|
|
149
|
+
const catLines = byCategory.get(cat);
|
|
150
|
+
if (!catLines || catLines.length === 0)
|
|
151
|
+
continue;
|
|
152
|
+
const catTitle = cat.charAt(0).toUpperCase() + cat.slice(1);
|
|
153
|
+
lines.push(`### ${catTitle}`, "");
|
|
154
|
+
for (const cmd of catLines) {
|
|
155
|
+
const entry = COMMAND_REGISTRY[cmd];
|
|
156
|
+
lines.push(`- \`/swarm ${cmd}\` \u2014 ${entry.description}`);
|
|
157
|
+
if (entry.clashesWithNativeCcCommand) {
|
|
158
|
+
lines.push(` \u26A0\uFE0F Name conflicts with CC built-in \`${entry.clashesWithNativeCcCommand}\` \u2014 always use \`/swarm ${cmd}\``);
|
|
159
|
+
}
|
|
160
|
+
if (entry.args) {
|
|
161
|
+
lines.push(` Args: \`${entry.args}\``);
|
|
162
|
+
}
|
|
163
|
+
if (entry.details) {
|
|
164
|
+
lines.push(` ${entry.details}`);
|
|
165
|
+
}
|
|
166
|
+
const subcommands = VALID_COMMANDS.filter((sub) => sub.startsWith(`${cmd} `) && sub !== cmd);
|
|
167
|
+
for (const sub of subcommands) {
|
|
168
|
+
shownAsSubcommand.add(sub);
|
|
169
|
+
const subEntry = COMMAND_REGISTRY[sub];
|
|
170
|
+
const subName = sub.slice(cmd.length + 1);
|
|
171
|
+
lines.push(` - \`${subName}\` \u2014 ${subEntry.description}`);
|
|
172
|
+
if (subEntry.args) {
|
|
173
|
+
lines.push(` Args: \`${subEntry.args}\``);
|
|
174
|
+
}
|
|
175
|
+
if (subEntry.details) {
|
|
176
|
+
lines.push(` ${subEntry.details}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
lines.push("");
|
|
181
|
+
}
|
|
182
|
+
for (const cmd of VALID_COMMANDS) {
|
|
183
|
+
if (!cmd.includes(" ") || shownAsSubcommand.has(cmd))
|
|
184
|
+
continue;
|
|
185
|
+
const entry = COMMAND_REGISTRY[cmd];
|
|
186
|
+
if (entry.aliasOf || entry.subcommandOf)
|
|
187
|
+
continue;
|
|
188
|
+
lines.push(`- \`/swarm ${cmd}\` \u2014 ${entry.description}`);
|
|
189
|
+
if (entry.clashesWithNativeCcCommand) {
|
|
190
|
+
lines.push(` \u26A0\uFE0F Name conflicts with CC built-in \`${entry.clashesWithNativeCcCommand}\` \u2014 always use \`/swarm ${cmd}\``);
|
|
191
|
+
}
|
|
192
|
+
if (entry.args) {
|
|
193
|
+
lines.push(` Args: \`${entry.args}\``);
|
|
194
|
+
}
|
|
195
|
+
if (entry.details) {
|
|
196
|
+
lines.push(` ${entry.details}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (deprecatedAliases.length > 0) {
|
|
200
|
+
lines.push("### Deprecated Commands", "");
|
|
201
|
+
for (const { name, aliasOf } of deprecatedAliases) {
|
|
202
|
+
lines.push(`- \`/swarm ${name}\` \u2192 Use \`/swarm ${aliasOf}\``);
|
|
203
|
+
const aliasEntry = COMMAND_REGISTRY[name];
|
|
204
|
+
if (aliasEntry?.clashesWithNativeCcCommand) {
|
|
205
|
+
lines.push(` \u26A0\uFE0F Name conflicts with CC built-in \`${aliasEntry.clashesWithNativeCcCommand}\` \u2014 always use \`/swarm ${aliasOf}\``);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return lines.join(`
|
|
210
|
+
`);
|
|
211
|
+
}
|
|
212
|
+
function createSwarmCommandHandler(directory, agents, options = {}) {
|
|
213
|
+
return async (input, output) => {
|
|
214
|
+
const normalized = normalizeSwarmCommandInput(input.command, input.arguments);
|
|
215
|
+
if (!normalized.isSwarmCommand) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
output.parts.splice(0, output.parts.length, {
|
|
219
|
+
type: "text",
|
|
220
|
+
text: await buildSwarmCommandPrompt({
|
|
221
|
+
directory,
|
|
222
|
+
agents,
|
|
223
|
+
sessionID: input.sessionID,
|
|
224
|
+
tokens: normalized.tokens,
|
|
225
|
+
activeAgentName: options.getActiveAgentName?.(input.sessionID),
|
|
226
|
+
packageRoot: options.packageRoot,
|
|
227
|
+
registeredAgents: options.registeredAgents
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
return;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
async function buildSwarmCommandPrompt(args) {
|
|
234
|
+
const {
|
|
235
|
+
directory,
|
|
236
|
+
agents,
|
|
237
|
+
sessionID,
|
|
238
|
+
tokens,
|
|
239
|
+
activeAgentName,
|
|
240
|
+
packageRoot,
|
|
241
|
+
registeredAgents
|
|
242
|
+
} = args;
|
|
243
|
+
const resolved = _internals.resolveCommand(tokens);
|
|
244
|
+
if (!resolved) {
|
|
245
|
+
if (tokens.length === 0) {
|
|
246
|
+
return buildHelpText();
|
|
247
|
+
}
|
|
248
|
+
return formatCommandNotFound(tokens);
|
|
249
|
+
}
|
|
250
|
+
const typedResolved = resolved;
|
|
251
|
+
const canonicalKey = canonicalCommandKey(typedResolved);
|
|
252
|
+
const policy = classifySwarmCommandToolUse(typedResolved);
|
|
253
|
+
const isV1ToolCommand = SWARM_COMMAND_TOOL_ALLOWLIST.has(canonicalKey);
|
|
254
|
+
const canUseTool = agentHasSwarmCommandTool(activeAgentName, agents, registeredAgents);
|
|
255
|
+
if (canUseTool && policy.allowed && isV1ToolCommand) {
|
|
256
|
+
return routeToSwarmCommandTool({
|
|
257
|
+
command: canonicalKey,
|
|
258
|
+
args: resolved.remainingArgs,
|
|
259
|
+
original: `/swarm ${tokens.join(" ")}`.trim()
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
if (canUseTool && isV1ToolCommand && !policy.allowed) {
|
|
263
|
+
return [
|
|
264
|
+
`The user typed \`/swarm ${tokens.join(" ")}\`.`,
|
|
265
|
+
policy.message,
|
|
266
|
+
"Do not invent command output. Explain the limitation and recommend the canonical CLI path above."
|
|
267
|
+
].join(`
|
|
268
|
+
`);
|
|
269
|
+
}
|
|
270
|
+
const chatFallbackPolicy = classifySwarmCommandChatFallbackUse(typedResolved);
|
|
271
|
+
if (!chatFallbackPolicy.allowed) {
|
|
272
|
+
return [
|
|
273
|
+
`The user typed \`/swarm ${tokens.join(" ")}\`.`,
|
|
274
|
+
chatFallbackPolicy.message,
|
|
275
|
+
"Do not execute this command through chat and do not invent command output."
|
|
276
|
+
].join(`
|
|
277
|
+
`);
|
|
278
|
+
}
|
|
279
|
+
const result = await executeSwarmCommand({
|
|
280
|
+
directory,
|
|
281
|
+
agents,
|
|
282
|
+
sessionID,
|
|
283
|
+
tokens,
|
|
284
|
+
packageRoot
|
|
285
|
+
});
|
|
286
|
+
return formatCanonicalPromptFallback({
|
|
287
|
+
original: `/swarm ${tokens.join(" ")}`.trim(),
|
|
288
|
+
text: result.text
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
function agentHasSwarmCommandTool(activeAgentName, agents, registeredAgents) {
|
|
292
|
+
const name = activeAgentName ?? ORCHESTRATOR_NAME;
|
|
293
|
+
const registeredTools = registeredAgents?.[name]?.tools;
|
|
294
|
+
if (registeredTools) {
|
|
295
|
+
return registeredTools.swarm_command === true;
|
|
296
|
+
}
|
|
297
|
+
const explicitTools = agents[name]?.config?.tools;
|
|
298
|
+
if (explicitTools) {
|
|
299
|
+
return explicitTools.swarm_command === true;
|
|
300
|
+
}
|
|
301
|
+
const baseName = stripKnownSwarmPrefix(name);
|
|
302
|
+
return AGENT_TOOL_MAP[baseName]?.includes("swarm_command") === true;
|
|
303
|
+
}
|
|
304
|
+
function formatCanonicalPromptFallback(args) {
|
|
305
|
+
if (/^\s*\[MODE:/.test(args.text)) {
|
|
306
|
+
return [
|
|
307
|
+
`The user typed \`${args.original}\`.`,
|
|
308
|
+
"The line below is a swarm MODE-activation signal, NOT output to display.",
|
|
309
|
+
"Enter the mode named in its `[MODE: X ...]` header now: follow your",
|
|
310
|
+
'prompt\u2019s "### MODE: X" section, load the SKILL.md it references, and',
|
|
311
|
+
"follow that protocol exactly. Treat any text after the closing bracket as",
|
|
312
|
+
"additional instructions. Do NOT echo this signal verbatim.",
|
|
313
|
+
"",
|
|
314
|
+
args.text
|
|
315
|
+
].join(`
|
|
316
|
+
`);
|
|
317
|
+
}
|
|
318
|
+
return [
|
|
319
|
+
`The user typed \`${args.original}\`.`,
|
|
320
|
+
"Canonical opencode-swarm command output follows.",
|
|
321
|
+
"Show this output verbatim and add no extra swarm state.",
|
|
322
|
+
"",
|
|
323
|
+
args.text
|
|
324
|
+
].join(`
|
|
325
|
+
`);
|
|
326
|
+
}
|
|
327
|
+
function routeToSwarmCommandTool(args) {
|
|
328
|
+
return [
|
|
329
|
+
`The user typed \`${args.original}\`.`,
|
|
330
|
+
"Call the `swarm_command` tool exactly once with:",
|
|
331
|
+
JSON.stringify({ command: args.command, args: args.args }, null, 2),
|
|
332
|
+
"After the tool returns, show the tool output verbatim and add no extra swarm state."
|
|
333
|
+
].join(`
|
|
334
|
+
`);
|
|
335
|
+
}
|
|
336
|
+
export {
|
|
337
|
+
resolveCommand,
|
|
338
|
+
normalizeSwarmCommandInput,
|
|
339
|
+
handleWriteRetroCommand,
|
|
340
|
+
handleTurboCommand,
|
|
341
|
+
handleSyncPlanCommand,
|
|
342
|
+
handleStatusCommand,
|
|
343
|
+
handleSpecifyCommand,
|
|
344
|
+
handleSimulateCommand,
|
|
345
|
+
handleSddValidateCommand,
|
|
346
|
+
handleSddStatusCommand,
|
|
347
|
+
handleSddProjectCommand,
|
|
348
|
+
handleSddCommand,
|
|
349
|
+
handleRollbackCommand,
|
|
350
|
+
handleRetrieveCommand,
|
|
351
|
+
handleResetSessionCommand,
|
|
352
|
+
handleResetCommand,
|
|
353
|
+
handleQaGatesCommand,
|
|
354
|
+
handlePromoteCommand,
|
|
355
|
+
handlePreflightCommand,
|
|
356
|
+
handlePlanCommand,
|
|
357
|
+
handleMemoryStatusCommand,
|
|
358
|
+
handleMemoryMigrateCommand,
|
|
359
|
+
handleMemoryImportCommand,
|
|
360
|
+
handleMemoryExportCommand,
|
|
361
|
+
handleMemoryCommand,
|
|
362
|
+
handleLearningCommand,
|
|
363
|
+
handleKnowledgeUnactionableCommand,
|
|
364
|
+
handleKnowledgeRetryHardeningCommand,
|
|
365
|
+
handleKnowledgeRestoreCommand,
|
|
366
|
+
handleKnowledgeQuarantineCommand,
|
|
367
|
+
handleKnowledgeMigrateCommand,
|
|
368
|
+
handleKnowledgeListCommand,
|
|
369
|
+
handleHistoryCommand,
|
|
370
|
+
handleHelpCommand,
|
|
371
|
+
handleHandoffCommand,
|
|
372
|
+
handleGuardrailLog,
|
|
373
|
+
handleGuardrailExplain,
|
|
374
|
+
handleFullAutoCommand,
|
|
375
|
+
handleExportCommand,
|
|
376
|
+
handleEvidenceSummaryCommand,
|
|
377
|
+
handleEvidenceCommand,
|
|
378
|
+
handleDoctorCommand,
|
|
379
|
+
handleDiagnoseCommand,
|
|
380
|
+
handleDeepResearchCommand,
|
|
381
|
+
handleDeepDiveCommand,
|
|
382
|
+
handleDarkMatterCommand,
|
|
383
|
+
handleCurateCommand,
|
|
384
|
+
handleCouncilCommand,
|
|
385
|
+
handleConsolidateCommand,
|
|
386
|
+
handleConfigCommand,
|
|
387
|
+
handleConcurrencyCommand,
|
|
388
|
+
handleCodebaseReviewCommand,
|
|
389
|
+
handleCloseCommand,
|
|
390
|
+
handleClarifyCommand,
|
|
391
|
+
handleCheckpointCommand,
|
|
392
|
+
handleBrainstormCommand,
|
|
393
|
+
handleBenchmarkCommand,
|
|
394
|
+
handleAutoProceedCommand,
|
|
395
|
+
handleArchiveCommand,
|
|
396
|
+
handleAnalyzeCommand,
|
|
397
|
+
handleAgentsCommand,
|
|
398
|
+
handleAcknowledgeSpecDriftCommand,
|
|
399
|
+
formatCommandNotFound,
|
|
400
|
+
executeSwarmCommand,
|
|
401
|
+
createSwarmCommandHandler,
|
|
402
|
+
classifySwarmCommandToolUse,
|
|
403
|
+
classifySwarmCommandChatFallbackUse,
|
|
404
|
+
buildHelpText,
|
|
405
|
+
agentHasSwarmCommandTool,
|
|
406
|
+
VALID_COMMANDS,
|
|
407
|
+
SWARM_COMMAND_TOOL_COMMANDS,
|
|
408
|
+
SWARM_COMMAND_TOOL_ALLOWLIST,
|
|
409
|
+
COMMAND_REGISTRY,
|
|
410
|
+
COMMAND_NAME_SET,
|
|
411
|
+
COMMAND_NAMES
|
|
412
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
redactPath,
|
|
4
|
+
redactShellCommand
|
|
5
|
+
} from "./index-pv2xmc9k.js";
|
|
6
|
+
|
|
7
|
+
// src/services/guardrail-log-service.ts
|
|
8
|
+
import * as fs from "fs/promises";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
var BLOCK_TYPES = new Set([
|
|
11
|
+
"file_write",
|
|
12
|
+
"scope_violation",
|
|
13
|
+
"destructive_block"
|
|
14
|
+
]);
|
|
15
|
+
function isBlockEntry(entry) {
|
|
16
|
+
if (entry.type === null || entry.type === undefined)
|
|
17
|
+
return false;
|
|
18
|
+
return BLOCK_TYPES.has(entry.type);
|
|
19
|
+
}
|
|
20
|
+
function redactSummary(entry) {
|
|
21
|
+
if (entry.type === "file_write" || entry.type === "scope_violation") {
|
|
22
|
+
const raw = entry.path ?? "";
|
|
23
|
+
return redactPath(raw);
|
|
24
|
+
}
|
|
25
|
+
if (entry.type === "destructive_block" || entry.type === "sandbox_wrap" || entry.type === "sandbox_skip" || entry.type === "shell" || entry.type === null || entry.type === undefined) {
|
|
26
|
+
const raw = entry.command ?? "";
|
|
27
|
+
return redactShellCommand(raw);
|
|
28
|
+
}
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
function formatEntry(entry) {
|
|
32
|
+
const decisionType = entry.type ?? "shell";
|
|
33
|
+
const summary = redactSummary(entry);
|
|
34
|
+
return `- [${entry.ts}] ${decisionType} | agent: ${entry.agent} | ${summary}`;
|
|
35
|
+
}
|
|
36
|
+
async function handleGuardrailLog(directory, args) {
|
|
37
|
+
const auditPath = path.join(directory, ".swarm", "session", "shell-audit.jsonl");
|
|
38
|
+
let raw;
|
|
39
|
+
try {
|
|
40
|
+
raw = await fs.readFile(auditPath, "utf-8");
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
43
|
+
return "No guardrail decisions recorded yet.";
|
|
44
|
+
}
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
const lines = raw.split(/\r?\n/);
|
|
48
|
+
const entries = [];
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
if (line.trim().length === 0)
|
|
51
|
+
continue;
|
|
52
|
+
let parsed;
|
|
53
|
+
try {
|
|
54
|
+
parsed = JSON.parse(line);
|
|
55
|
+
} catch {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!isPlainObject(parsed))
|
|
59
|
+
continue;
|
|
60
|
+
if (typeof parsed.ts !== "string")
|
|
61
|
+
continue;
|
|
62
|
+
if (typeof parsed.sessionID !== "string")
|
|
63
|
+
continue;
|
|
64
|
+
if (typeof parsed.agent !== "string")
|
|
65
|
+
continue;
|
|
66
|
+
if (typeof parsed.tool !== "string")
|
|
67
|
+
continue;
|
|
68
|
+
const entry = {
|
|
69
|
+
ts: parsed.ts,
|
|
70
|
+
sessionID: parsed.sessionID,
|
|
71
|
+
agent: parsed.agent,
|
|
72
|
+
tool: parsed.tool
|
|
73
|
+
};
|
|
74
|
+
if (typeof parsed.type === "string") {
|
|
75
|
+
entry.type = parsed.type;
|
|
76
|
+
}
|
|
77
|
+
if (typeof parsed.command === "string") {
|
|
78
|
+
entry.command = parsed.command;
|
|
79
|
+
}
|
|
80
|
+
if (typeof parsed.path === "string") {
|
|
81
|
+
entry.path = parsed.path;
|
|
82
|
+
}
|
|
83
|
+
entries.push(entry);
|
|
84
|
+
}
|
|
85
|
+
if (entries.length === 0) {
|
|
86
|
+
return "No guardrail decisions recorded yet.";
|
|
87
|
+
}
|
|
88
|
+
const blocksOnly = args.includes("--blocks-only");
|
|
89
|
+
const filtered = blocksOnly ? entries.filter(isBlockEntry) : entries;
|
|
90
|
+
if (filtered.length === 0) {
|
|
91
|
+
if (blocksOnly) {
|
|
92
|
+
return "No guardrail block decisions recorded yet.";
|
|
93
|
+
}
|
|
94
|
+
return "No guardrail decisions recorded yet.";
|
|
95
|
+
}
|
|
96
|
+
filtered.sort((a, b) => {
|
|
97
|
+
const diff = b.ts.localeCompare(a.ts);
|
|
98
|
+
return diff === 0 ? 0 : diff;
|
|
99
|
+
});
|
|
100
|
+
const header = blocksOnly ? "# Guardrail Block Log (most-recent-first)" : "# Guardrail Decision Log (most-recent-first)";
|
|
101
|
+
const body = filtered.map(formatEntry).join(`
|
|
102
|
+
`);
|
|
103
|
+
return `${header}
|
|
104
|
+
|
|
105
|
+
${body}`;
|
|
106
|
+
}
|
|
107
|
+
function isPlainObject(value) {
|
|
108
|
+
return typeof value === "object" && value !== null && (value.constructor === Object || Object.getPrototypeOf(value) === null);
|
|
109
|
+
}
|
|
110
|
+
export { handleGuardrailLog };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/utils/swarm-artifact-cache.ts
|
|
3
|
+
import * as fs from "fs/promises";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
var MAX_CACHE_ENTRIES = 128;
|
|
6
|
+
var textCache = new Map;
|
|
7
|
+
var parsedCache = new Map;
|
|
8
|
+
var stats = {
|
|
9
|
+
textReadCount: 0,
|
|
10
|
+
textCacheHitCount: 0,
|
|
11
|
+
textCacheMissCount: 0,
|
|
12
|
+
parsedReadCount: 0,
|
|
13
|
+
parseCount: 0,
|
|
14
|
+
parsedCacheHitCount: 0,
|
|
15
|
+
parsedCacheMissCount: 0,
|
|
16
|
+
statFailureCount: 0,
|
|
17
|
+
evictionCount: 0,
|
|
18
|
+
textEvictionCount: 0,
|
|
19
|
+
parsedEvictionCount: 0,
|
|
20
|
+
cloneFallbackCount: 0,
|
|
21
|
+
textEntryCount: 0,
|
|
22
|
+
parsedEntryCount: 0
|
|
23
|
+
};
|
|
24
|
+
function sameStamp(a, b) {
|
|
25
|
+
return a.mtimeMs === b.mtimeMs && a.ctimeMs === b.ctimeMs && a.size === b.size;
|
|
26
|
+
}
|
|
27
|
+
async function getStamp(filePath) {
|
|
28
|
+
try {
|
|
29
|
+
const stat2 = await fs.stat(filePath);
|
|
30
|
+
if (!stat2.isFile())
|
|
31
|
+
return null;
|
|
32
|
+
return { mtimeMs: stat2.mtimeMs, ctimeMs: stat2.ctimeMs, size: stat2.size };
|
|
33
|
+
} catch {
|
|
34
|
+
stats.statFailureCount++;
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function canStoreRead(before, after) {
|
|
39
|
+
return after !== null && sameStamp(before, after);
|
|
40
|
+
}
|
|
41
|
+
function setBounded(cache, key, value, cacheKind) {
|
|
42
|
+
cache.set(key, value);
|
|
43
|
+
while (cache.size > MAX_CACHE_ENTRIES) {
|
|
44
|
+
const oldest = cache.keys().next().value;
|
|
45
|
+
if (oldest === undefined)
|
|
46
|
+
break;
|
|
47
|
+
cache.delete(oldest);
|
|
48
|
+
stats.evictionCount++;
|
|
49
|
+
if (cacheKind === "text") {
|
|
50
|
+
stats.textEvictionCount++;
|
|
51
|
+
} else {
|
|
52
|
+
stats.parsedEvictionCount++;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
stats.textEntryCount = textCache.size;
|
|
56
|
+
stats.parsedEntryCount = parsedCache.size;
|
|
57
|
+
}
|
|
58
|
+
function cloneCachedValue(value) {
|
|
59
|
+
if (value === null || typeof value !== "object")
|
|
60
|
+
return value;
|
|
61
|
+
if (typeof structuredClone === "function") {
|
|
62
|
+
return structuredClone(value);
|
|
63
|
+
}
|
|
64
|
+
stats.cloneFallbackCount++;
|
|
65
|
+
return JSON.parse(JSON.stringify(value));
|
|
66
|
+
}
|
|
67
|
+
async function readCachedTextFile(filePath, directRead) {
|
|
68
|
+
const cacheKey = path.resolve(filePath);
|
|
69
|
+
const stamp = await getStamp(cacheKey);
|
|
70
|
+
if (!stamp) {
|
|
71
|
+
stats.textReadCount++;
|
|
72
|
+
return directRead();
|
|
73
|
+
}
|
|
74
|
+
const cached = textCache.get(cacheKey);
|
|
75
|
+
if (cached && sameStamp(cached, stamp)) {
|
|
76
|
+
stats.textCacheHitCount++;
|
|
77
|
+
return cached.value;
|
|
78
|
+
}
|
|
79
|
+
stats.textCacheMissCount++;
|
|
80
|
+
stats.textReadCount++;
|
|
81
|
+
const value = await directRead();
|
|
82
|
+
const afterReadStamp = await getStamp(cacheKey);
|
|
83
|
+
if (value !== null && canStoreRead(stamp, afterReadStamp)) {
|
|
84
|
+
setBounded(textCache, cacheKey, { ...afterReadStamp, value }, "text");
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
async function readCachedParsedFile(filePath, namespace, readText, parse) {
|
|
89
|
+
const resolvedPath = path.resolve(filePath);
|
|
90
|
+
const cacheKey = `${resolvedPath}\x00${namespace}`;
|
|
91
|
+
const stamp = await getStamp(resolvedPath);
|
|
92
|
+
if (!stamp) {
|
|
93
|
+
stats.parsedReadCount++;
|
|
94
|
+
const content2 = await readText();
|
|
95
|
+
if (content2 === null)
|
|
96
|
+
return null;
|
|
97
|
+
stats.parseCount++;
|
|
98
|
+
return parse(content2);
|
|
99
|
+
}
|
|
100
|
+
const cached = parsedCache.get(cacheKey);
|
|
101
|
+
if (cached && sameStamp(cached, stamp)) {
|
|
102
|
+
stats.parsedCacheHitCount++;
|
|
103
|
+
return cloneCachedValue(cached.value);
|
|
104
|
+
}
|
|
105
|
+
stats.parsedCacheMissCount++;
|
|
106
|
+
stats.parsedReadCount++;
|
|
107
|
+
const content = await readText();
|
|
108
|
+
if (content === null)
|
|
109
|
+
return null;
|
|
110
|
+
stats.parseCount++;
|
|
111
|
+
const value = parse(content);
|
|
112
|
+
const afterReadStamp = await getStamp(resolvedPath);
|
|
113
|
+
if (canStoreRead(stamp, afterReadStamp)) {
|
|
114
|
+
setBounded(parsedCache, cacheKey, { ...afterReadStamp, value }, "parsed");
|
|
115
|
+
}
|
|
116
|
+
return cloneCachedValue(value);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { readCachedTextFile, readCachedParsedFile };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/utils/merge.ts
|
|
3
|
+
var MAX_MERGE_DEPTH = 10;
|
|
4
|
+
function deepMergeInternal(base, override, depth) {
|
|
5
|
+
if (depth >= MAX_MERGE_DEPTH) {
|
|
6
|
+
throw new Error(`deepMerge exceeded maximum depth of ${MAX_MERGE_DEPTH}`);
|
|
7
|
+
}
|
|
8
|
+
const result = { ...base };
|
|
9
|
+
for (const key of Object.keys(override)) {
|
|
10
|
+
const baseVal = base[key];
|
|
11
|
+
const overrideVal = override[key];
|
|
12
|
+
if (typeof baseVal === "object" && baseVal !== null && typeof overrideVal === "object" && overrideVal !== null && !Array.isArray(baseVal) && !Array.isArray(overrideVal)) {
|
|
13
|
+
result[key] = deepMergeInternal(baseVal, overrideVal, depth + 1);
|
|
14
|
+
} else {
|
|
15
|
+
result[key] = overrideVal;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
function deepMerge(base, override) {
|
|
21
|
+
if (!base)
|
|
22
|
+
return override;
|
|
23
|
+
if (!override)
|
|
24
|
+
return base;
|
|
25
|
+
return deepMergeInternal(base, override, 0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { deepMerge };
|