opencode-swarm 6.45.0 → 6.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/explorer.d.ts +1 -1
- package/dist/index.js +63 -18
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentDefinition } from './architect';
|
|
2
2
|
export declare const CURATOR_INIT_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_INIT\nPRIOR_SUMMARY: [JSON or \"none\"]\nKNOWLEDGE_ENTRIES: [JSON array of high-confidence entries]\nPROJECT_CONTEXT: [context.md excerpt]\n\nACTIONS:\n- Read the prior summary to understand session history\n- Cross-reference knowledge entries against project context\n- Identify contradictions (knowledge says X, project state shows Y)\n- Produce a concise briefing for the architect\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Flag contradictions explicitly with CONTRADICTION: prefix\n- If no prior summary exists, state \"First session \u2014 no prior context\"\n\nOUTPUT FORMAT:\nBRIEFING:\n[concise summary of prior session state, key decisions, active blockers]\n\nCONTRADICTIONS:\n- [entry_id]: [description] (or \"None detected\")\n\nKNOWLEDGE_STATS:\n- Entries reviewed: [N]\n- Prior phases covered: [N]\n";
|
|
3
|
-
export declare const CURATOR_PHASE_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_PHASE [phase_number]\nPRIOR_DIGEST: [running summary or \"none\"]\nPHASE_EVENTS: [JSON array from events.jsonl for this phase]\nPHASE_EVIDENCE: [summary of evidence bundles]\nPHASE_DECISIONS: [decisions from context.md]\nAGENTS_DISPATCHED: [list]\nAGENTS_EXPECTED: [list from config]\n\nACTIONS:\n- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)\n- Identify workflow deviations: missing reviewer, missing retro, skipped test_engineer\n- Recommend knowledge updates: entries to promote, archive, or flag as contradicted\n- Summarize key decisions and blockers resolved\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Compliance observations are READ-ONLY \u2014 report, do not enforce\n- Extend the digest, never replace it\n\nOUTPUT FORMAT:\nPHASE_DIGEST:\nphase: [N]\nsummary: [what was accomplished]\nagents_used: [list]\ntasks_completed: [N]/[total]\nkey_decisions: [list]\nblockers_resolved: [list]\n\nCOMPLIANCE:\n- [type]: [description] (or \"No deviations observed\")\n\nKNOWLEDGE_UPDATES:\n- [action]
|
|
3
|
+
export declare const CURATOR_PHASE_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_PHASE [phase_number]\nPRIOR_DIGEST: [running summary or \"none\"]\nPHASE_EVENTS: [JSON array from events.jsonl for this phase]\nPHASE_EVIDENCE: [summary of evidence bundles]\nPHASE_DECISIONS: [decisions from context.md]\nAGENTS_DISPATCHED: [list]\nAGENTS_EXPECTED: [list from config]\n\nACTIONS:\n- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)\n- Identify workflow deviations: missing reviewer, missing retro, skipped test_engineer\n- Recommend knowledge updates: entries to promote, archive, or flag as contradicted\n- Summarize key decisions and blockers resolved\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Compliance observations are READ-ONLY \u2014 report, do not enforce\n- Extend the digest, never replace it\n\nOUTPUT FORMAT:\nPHASE_DIGEST:\nphase: [N]\nsummary: [what was accomplished]\nagents_used: [list]\ntasks_completed: [N]/[total]\nkey_decisions: [list]\nblockers_resolved: [list]\n\nCOMPLIANCE:\n- [type]: [description] (or \"No deviations observed\")\n\nKNOWLEDGE_UPDATES:\n- [action] new: [reason] (or \"No recommendations\")\nNOTE: Always use \"new\" as the token \u2014 existing entry IDs (UUID v4) are not available in this context. Any non-UUID token is treated as \"new\" by the parser. Only \"promote new:\" creates a new entry; \"archive new:\" and \"flag_contradiction new:\" are silently skipped because those actions require an existing entry to operate on.\n\nEXTENDED_DIGEST:\n[the full running digest with this phase appended]\n";
|
|
4
4
|
export declare function createExplorerAgent(model: string, customPrompt?: string, customAppendPrompt?: string): AgentDefinition;
|
|
5
5
|
export declare function createExplorerCuratorAgent(model: string, mode: 'CURATOR_INIT' | 'CURATOR_PHASE', customAppendPrompt?: string): AgentDefinition;
|
package/dist/index.js
CHANGED
|
@@ -32519,7 +32519,7 @@ __export(exports_co_change_analyzer, {
|
|
|
32519
32519
|
buildCoChangeMatrix: () => buildCoChangeMatrix
|
|
32520
32520
|
});
|
|
32521
32521
|
import * as child_process2 from "child_process";
|
|
32522
|
-
import { randomUUID } from "crypto";
|
|
32522
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
32523
32523
|
import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
|
|
32524
32524
|
import * as path19 from "path";
|
|
32525
32525
|
import { promisify } from "util";
|
|
@@ -32779,7 +32779,7 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
32779
32779
|
}
|
|
32780
32780
|
const confidence = Math.min(0.3 + 0.2 * Math.min(pair.coChangeCount / 10, 1), 0.5);
|
|
32781
32781
|
entries.push({
|
|
32782
|
-
id:
|
|
32782
|
+
id: randomUUID2(),
|
|
32783
32783
|
tier: "swarm",
|
|
32784
32784
|
lesson,
|
|
32785
32785
|
category: "architecture",
|
|
@@ -36214,17 +36214,17 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
36214
36214
|
const testFiles = [];
|
|
36215
36215
|
for (const file3 of sourceFiles) {
|
|
36216
36216
|
const normalizedPath = file3.replace(/\\/g, "/");
|
|
36217
|
-
const
|
|
36217
|
+
const basename5 = path28.basename(file3);
|
|
36218
36218
|
const dirname12 = path28.dirname(file3);
|
|
36219
|
-
if (hasCompoundTestExtension(
|
|
36219
|
+
if (hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
|
|
36220
36220
|
if (!testFiles.includes(file3)) {
|
|
36221
36221
|
testFiles.push(file3);
|
|
36222
36222
|
}
|
|
36223
36223
|
continue;
|
|
36224
36224
|
}
|
|
36225
36225
|
for (const _pattern of TEST_PATTERNS) {
|
|
36226
|
-
const nameWithoutExt =
|
|
36227
|
-
const ext = path28.extname(
|
|
36226
|
+
const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
|
|
36227
|
+
const ext = path28.extname(basename5);
|
|
36228
36228
|
const possibleTestFiles = [
|
|
36229
36229
|
path28.join(dirname12, `${nameWithoutExt}.spec${ext}`),
|
|
36230
36230
|
path28.join(dirname12, `${nameWithoutExt}.test${ext}`),
|
|
@@ -38054,17 +38054,17 @@ function normalizeSeparators(filePath) {
|
|
|
38054
38054
|
}
|
|
38055
38055
|
function matchesDocPattern(filePath, patterns) {
|
|
38056
38056
|
const normalizedPath = normalizeSeparators(filePath);
|
|
38057
|
-
const
|
|
38057
|
+
const basename6 = path42.basename(filePath);
|
|
38058
38058
|
for (const pattern of patterns) {
|
|
38059
38059
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
38060
|
-
if (
|
|
38060
|
+
if (basename6 === pattern) {
|
|
38061
38061
|
return true;
|
|
38062
38062
|
}
|
|
38063
38063
|
continue;
|
|
38064
38064
|
}
|
|
38065
38065
|
if (pattern.startsWith("**/")) {
|
|
38066
38066
|
const filenamePattern = pattern.slice(3);
|
|
38067
|
-
if (
|
|
38067
|
+
if (basename6 === filenamePattern) {
|
|
38068
38068
|
return true;
|
|
38069
38069
|
}
|
|
38070
38070
|
continue;
|
|
@@ -44118,7 +44118,8 @@ COMPLIANCE:
|
|
|
44118
44118
|
- [type]: [description] (or "No deviations observed")
|
|
44119
44119
|
|
|
44120
44120
|
KNOWLEDGE_UPDATES:
|
|
44121
|
-
- [action]
|
|
44121
|
+
- [action] new: [reason] (or "No recommendations")
|
|
44122
|
+
NOTE: Always use "new" as the token \u2014 existing entry IDs (UUID v4) are not available in this context. Any non-UUID token is treated as "new" by the parser. Only "promote new:" creates a new entry; "archive new:" and "flag_contradiction new:" are silently skipped because those actions require an existing entry to operate on.
|
|
44122
44123
|
|
|
44123
44124
|
EXTENDED_DIGEST:
|
|
44124
44125
|
[the full running digest with this phase appended]
|
|
@@ -48202,6 +48203,7 @@ async function handleConfigCommand(directory, _args) {
|
|
|
48202
48203
|
init_schema();
|
|
48203
48204
|
|
|
48204
48205
|
// src/hooks/curator.ts
|
|
48206
|
+
import { randomUUID } from "crypto";
|
|
48205
48207
|
import * as fs12 from "fs";
|
|
48206
48208
|
import * as path18 from "path";
|
|
48207
48209
|
init_event_bus();
|
|
@@ -48223,7 +48225,8 @@ function parseKnowledgeRecommendations(llmOutput) {
|
|
|
48223
48225
|
const match = trimmed.match(/^-\s+(promote|archive|flag_contradiction)\s+(\S+):\s+(.+)$/i);
|
|
48224
48226
|
if (match) {
|
|
48225
48227
|
const action = match[1].toLowerCase();
|
|
48226
|
-
const
|
|
48228
|
+
const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
48229
|
+
const entryId = match[2] === "new" || !UUID_V4.test(match[2]) ? undefined : match[2];
|
|
48227
48230
|
const reason = match[3].trim();
|
|
48228
48231
|
recommendations.push({
|
|
48229
48232
|
action,
|
|
@@ -48737,6 +48740,43 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, _knowled
|
|
|
48737
48740
|
if (modified) {
|
|
48738
48741
|
await rewriteKnowledge(knowledgePath, updatedEntries);
|
|
48739
48742
|
}
|
|
48743
|
+
for (const rec of recommendations) {
|
|
48744
|
+
if (rec.entry_id !== undefined)
|
|
48745
|
+
continue;
|
|
48746
|
+
if (rec.action !== "promote") {
|
|
48747
|
+
skipped++;
|
|
48748
|
+
continue;
|
|
48749
|
+
}
|
|
48750
|
+
const lesson = rec.lesson?.trim() ?? "";
|
|
48751
|
+
if (lesson.length < 15) {
|
|
48752
|
+
skipped++;
|
|
48753
|
+
continue;
|
|
48754
|
+
}
|
|
48755
|
+
const now = new Date().toISOString();
|
|
48756
|
+
const newEntry = {
|
|
48757
|
+
id: randomUUID(),
|
|
48758
|
+
tier: "swarm",
|
|
48759
|
+
lesson: lesson.slice(0, 280),
|
|
48760
|
+
category: "other",
|
|
48761
|
+
tags: [],
|
|
48762
|
+
scope: "global",
|
|
48763
|
+
confidence: 0.5,
|
|
48764
|
+
status: "candidate",
|
|
48765
|
+
confirmed_by: [],
|
|
48766
|
+
retrieval_outcomes: {
|
|
48767
|
+
applied_count: 0,
|
|
48768
|
+
succeeded_after_count: 0,
|
|
48769
|
+
failed_after_count: 0
|
|
48770
|
+
},
|
|
48771
|
+
schema_version: 1,
|
|
48772
|
+
created_at: now,
|
|
48773
|
+
updated_at: now,
|
|
48774
|
+
auto_generated: true,
|
|
48775
|
+
project_name: path18.basename(directory)
|
|
48776
|
+
};
|
|
48777
|
+
await appendKnowledge(knowledgePath, newEntry);
|
|
48778
|
+
applied++;
|
|
48779
|
+
}
|
|
48740
48780
|
return { applied, skipped };
|
|
48741
48781
|
}
|
|
48742
48782
|
|
|
@@ -50416,7 +50456,7 @@ init_schema();
|
|
|
50416
50456
|
|
|
50417
50457
|
// src/hooks/knowledge-migrator.ts
|
|
50418
50458
|
init_knowledge_store();
|
|
50419
|
-
import { randomUUID as
|
|
50459
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
50420
50460
|
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
50421
50461
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
50422
50462
|
import * as path23 from "path";
|
|
@@ -50486,7 +50526,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
50486
50526
|
}
|
|
50487
50527
|
const inferredTags = inferTags(raw.text);
|
|
50488
50528
|
const entry = {
|
|
50489
|
-
id:
|
|
50529
|
+
id: randomUUID3(),
|
|
50490
50530
|
tier: "swarm",
|
|
50491
50531
|
lesson: truncateLesson(raw.text),
|
|
50492
50532
|
category: raw.categoryHint ?? inferCategoryFromText(raw.text),
|
|
@@ -59858,7 +59898,7 @@ function countCodeLines(content) {
|
|
|
59858
59898
|
return lines.length;
|
|
59859
59899
|
}
|
|
59860
59900
|
function isTestFile(filePath) {
|
|
59861
|
-
const
|
|
59901
|
+
const basename8 = path52.basename(filePath);
|
|
59862
59902
|
const _ext = path52.extname(filePath).toLowerCase();
|
|
59863
59903
|
const testPatterns = [
|
|
59864
59904
|
".test.",
|
|
@@ -59874,7 +59914,7 @@ function isTestFile(filePath) {
|
|
|
59874
59914
|
".spec.jsx"
|
|
59875
59915
|
];
|
|
59876
59916
|
for (const pattern of testPatterns) {
|
|
59877
|
-
if (
|
|
59917
|
+
if (basename8.includes(pattern)) {
|
|
59878
59918
|
return true;
|
|
59879
59919
|
}
|
|
59880
59920
|
}
|
|
@@ -60540,7 +60580,12 @@ var curator_analyze = createSwarmTool({
|
|
|
60540
60580
|
let applied = 0;
|
|
60541
60581
|
let skipped = 0;
|
|
60542
60582
|
if (typedArgs.recommendations && typedArgs.recommendations.length > 0) {
|
|
60543
|
-
const
|
|
60583
|
+
const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
60584
|
+
const sanitizedRecs = typedArgs.recommendations.map((rec) => ({
|
|
60585
|
+
...rec,
|
|
60586
|
+
entry_id: rec.entry_id === undefined || UUID_V4.test(rec.entry_id) ? rec.entry_id : undefined
|
|
60587
|
+
}));
|
|
60588
|
+
const result = await applyCuratorKnowledgeUpdates(directory, sanitizedRecs, knowledgeConfig);
|
|
60544
60589
|
applied = result.applied;
|
|
60545
60590
|
skipped = result.skipped;
|
|
60546
60591
|
}
|
|
@@ -62218,7 +62263,7 @@ var imports = createSwarmTool({
|
|
|
62218
62263
|
init_dist();
|
|
62219
62264
|
init_config();
|
|
62220
62265
|
init_knowledge_store();
|
|
62221
|
-
import { randomUUID as
|
|
62266
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
62222
62267
|
init_manager2();
|
|
62223
62268
|
init_create_tool();
|
|
62224
62269
|
var VALID_CATEGORIES2 = [
|
|
@@ -62293,7 +62338,7 @@ var knowledgeAdd = createSwarmTool({
|
|
|
62293
62338
|
project_name = plan?.title ?? "";
|
|
62294
62339
|
} catch {}
|
|
62295
62340
|
const entry = {
|
|
62296
|
-
id:
|
|
62341
|
+
id: randomUUID6(),
|
|
62297
62342
|
tier: "swarm",
|
|
62298
62343
|
lesson,
|
|
62299
62344
|
category,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.45.
|
|
3
|
+
"version": "6.45.1",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|