opencode-autognosis 2.4.0 → 2.5.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/dist/database.d.ts +2 -0
- package/dist/database.js +21 -0
- package/dist/unified-api.js +86 -27
- package/package.json +1 -1
package/dist/database.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export declare class CodeGraphDB {
|
|
|
12
12
|
error?: string;
|
|
13
13
|
}): void;
|
|
14
14
|
getJob(id: string): any;
|
|
15
|
+
registerContract(triggerTool: string, triggerAction: string, targetTool: string, targetArgs: any): void;
|
|
16
|
+
getContracts(triggerTool: string, triggerAction: string): any[];
|
|
15
17
|
listJobs(type?: string, limit?: number): any;
|
|
16
18
|
postToBlackboard(author: string, message: string, topic?: string, symbolId?: string, isPinned?: boolean): void;
|
|
17
19
|
getGraffiti(symbolId: string, limit?: number): any;
|
package/dist/database.js
CHANGED
|
@@ -185,6 +185,15 @@ export class CodeGraphDB {
|
|
|
185
185
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
186
186
|
);
|
|
187
187
|
|
|
188
|
+
CREATE TABLE IF NOT EXISTS tool_contracts (
|
|
189
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
190
|
+
trigger_tool TEXT, -- e.g., 'code_propose'
|
|
191
|
+
trigger_action TEXT, -- e.g., 'patch'
|
|
192
|
+
target_tool TEXT,
|
|
193
|
+
target_args TEXT, -- JSON
|
|
194
|
+
condition_script TEXT -- Optional JS snippet to evaluate
|
|
195
|
+
);
|
|
196
|
+
|
|
188
197
|
CREATE INDEX IF NOT EXISTS idx_files_path ON files(path);
|
|
189
198
|
CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name);
|
|
190
199
|
CREATE INDEX IF NOT EXISTS idx_dependencies_target ON dependencies(target_path);
|
|
@@ -228,6 +237,18 @@ export class CodeGraphDB {
|
|
|
228
237
|
getJob(id) {
|
|
229
238
|
return this.db.prepare("SELECT * FROM background_jobs WHERE id = ?").get(id);
|
|
230
239
|
}
|
|
240
|
+
registerContract(triggerTool, triggerAction, targetTool, targetArgs) {
|
|
241
|
+
this.db.prepare(`
|
|
242
|
+
INSERT INTO tool_contracts (trigger_tool, trigger_action, target_tool, target_args)
|
|
243
|
+
VALUES (?, ?, ?, ?)
|
|
244
|
+
`).run(triggerTool, triggerAction, targetTool, JSON.stringify(targetArgs));
|
|
245
|
+
}
|
|
246
|
+
getContracts(triggerTool, triggerAction) {
|
|
247
|
+
return this.db.prepare(`
|
|
248
|
+
SELECT * FROM tool_contracts
|
|
249
|
+
WHERE trigger_tool = ? AND (trigger_action = ? OR trigger_action IS NULL)
|
|
250
|
+
`).all(triggerTool, triggerAction);
|
|
251
|
+
}
|
|
231
252
|
listJobs(type, limit = 10) {
|
|
232
253
|
if (type) {
|
|
233
254
|
return this.db.prepare("SELECT * FROM background_jobs WHERE type = ? ORDER BY created_at DESC LIMIT ?").all(type, limit);
|
package/dist/unified-api.js
CHANGED
|
@@ -25,14 +25,14 @@ async function scoutPlugins() {
|
|
|
25
25
|
if (config.plugin)
|
|
26
26
|
config.plugin.forEach((p) => plugins.add(p));
|
|
27
27
|
}
|
|
28
|
-
catch { }
|
|
28
|
+
catch { }
|
|
29
29
|
try {
|
|
30
30
|
const pkg = JSON.parse(fsSync.readFileSync(path.join(PROJECT_ROOT, "package.json"), "utf-8"));
|
|
31
31
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
32
32
|
Object.keys(allDeps).forEach(d => { if (d.includes("opencode"))
|
|
33
33
|
plugins.add(d); });
|
|
34
34
|
}
|
|
35
|
-
catch { }
|
|
35
|
+
catch { }
|
|
36
36
|
return Array.from(plugins);
|
|
37
37
|
}
|
|
38
38
|
async function updateBridgePrompt(plugins) {
|
|
@@ -40,14 +40,15 @@ async function updateBridgePrompt(plugins) {
|
|
|
40
40
|
if (!fsSync.existsSync(bridgePath))
|
|
41
41
|
return "bridge.md not found at " + bridgePath;
|
|
42
42
|
const toolsSection = `
|
|
43
|
-
## Current Consolidated Tools (Autognosis v2.
|
|
43
|
+
## Current Consolidated Tools (Autognosis v2.5)
|
|
44
44
|
- code_search: Universal search (semantic, symbol, filename, content).
|
|
45
45
|
- code_analyze: Deep structural analysis and impact reports.
|
|
46
46
|
- code_context: Working memory management and LRU eviction.
|
|
47
47
|
- code_read: Precise reading with Mutex Lock checks and Graffiti retrieval.
|
|
48
|
-
- code_propose: Planning, patching, validation, and PR promotion.
|
|
48
|
+
- code_propose: Planning, patching, validation, and PR promotion.
|
|
49
49
|
- code_status: Dashboard, background jobs, blackboard, and resource locks.
|
|
50
|
-
- code_setup: Environment initialization and
|
|
50
|
+
- code_setup: Environment initialization, AI setup, and Architectural Boundaries.
|
|
51
|
+
- code_contract: Reactive tool chaining and automated post-execution hooks.
|
|
51
52
|
|
|
52
53
|
## Other Detected Plugins
|
|
53
54
|
${plugins.filter(p => p !== "opencode-autognosis").map(p => `- ${p}`).join('\n')}
|
|
@@ -62,10 +63,53 @@ ${plugins.filter(p => p !== "opencode-autognosis").map(p => `- ${p}`).join('\n')
|
|
|
62
63
|
fsSync.writeFileSync(bridgePath, content);
|
|
63
64
|
return "Updated bridge.md with consolidated tools and detected plugins.";
|
|
64
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Reactive Contract Runner
|
|
68
|
+
* Automatically triggers secondary tools based on registered contracts.
|
|
69
|
+
*/
|
|
70
|
+
async function runWithContracts(toolName, action, args, result, tools) {
|
|
71
|
+
const contracts = getDb().getContracts(toolName, action || '');
|
|
72
|
+
if (contracts.length === 0)
|
|
73
|
+
return result;
|
|
74
|
+
let finalResult = JSON.parse(result);
|
|
75
|
+
finalResult.contracts_triggered = [];
|
|
76
|
+
for (const contract of contracts) {
|
|
77
|
+
try {
|
|
78
|
+
const targetTool = tools[contract.target_tool];
|
|
79
|
+
if (targetTool) {
|
|
80
|
+
const targetArgs = JSON.parse(contract.target_args);
|
|
81
|
+
// Merge context from original args if needed (e.g. plan_id)
|
|
82
|
+
if (args.plan_id)
|
|
83
|
+
targetArgs.plan_id = args.plan_id;
|
|
84
|
+
const chainResult = await targetTool.execute(targetArgs);
|
|
85
|
+
finalResult.contracts_triggered.push({
|
|
86
|
+
name: contract.target_tool,
|
|
87
|
+
result: JSON.parse(chainResult)
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
finalResult.contracts_triggered.push({ name: contract.target_tool, error: String(e) });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return JSON.stringify(finalResult, null, 2);
|
|
96
|
+
}
|
|
65
97
|
export function unifiedTools() {
|
|
66
98
|
const agentName = process.env.AGENT_NAME || `agent-${process.pid}`;
|
|
67
|
-
|
|
68
|
-
|
|
99
|
+
const api = {};
|
|
100
|
+
const wrap = (toolName, config) => {
|
|
101
|
+
const originalExecute = config.execute;
|
|
102
|
+
config.execute = async (args) => {
|
|
103
|
+
const res = await originalExecute(args);
|
|
104
|
+
// Only attempt chaining if original call was successful (heuristic)
|
|
105
|
+
if (res.includes('"status": "ERROR"') || res.includes('"status": "FAILED"'))
|
|
106
|
+
return res;
|
|
107
|
+
return runWithContracts(toolName, args.action || args.mode, args, res, api);
|
|
108
|
+
};
|
|
109
|
+
return tool(config);
|
|
110
|
+
};
|
|
111
|
+
Object.assign(api, {
|
|
112
|
+
code_search: wrap("code_search", {
|
|
69
113
|
description: "Search the codebase using various engines (filename, content, symbol, or semantic/vector).",
|
|
70
114
|
args: {
|
|
71
115
|
query: tool.schema.string().describe("Search query"),
|
|
@@ -83,7 +127,7 @@ export function unifiedTools() {
|
|
|
83
127
|
}
|
|
84
128
|
}
|
|
85
129
|
}),
|
|
86
|
-
code_analyze:
|
|
130
|
+
code_analyze: wrap("code_analyze", {
|
|
87
131
|
description: "Perform structural analysis on files or modules. Generates summaries, API maps, and impact reports.",
|
|
88
132
|
args: {
|
|
89
133
|
target: tool.schema.string().describe("File path or module ID"),
|
|
@@ -101,7 +145,7 @@ export function unifiedTools() {
|
|
|
101
145
|
}
|
|
102
146
|
}
|
|
103
147
|
}),
|
|
104
|
-
code_context:
|
|
148
|
+
code_context: wrap("code_context", {
|
|
105
149
|
description: "Manage working memory (ActiveSets). Limits context window usage by loading/unloading specific chunks.",
|
|
106
150
|
args: {
|
|
107
151
|
action: tool.schema.enum(["create", "load", "add", "remove", "status", "list", "close", "evict"]),
|
|
@@ -112,10 +156,10 @@ export function unifiedTools() {
|
|
|
112
156
|
},
|
|
113
157
|
async execute(args) {
|
|
114
158
|
switch (args.action) {
|
|
115
|
-
case "create": return internal.activeset_create.execute({ name: args.name || "Context", chunk_ids: args.target?.split(',').map(s => s.trim()) });
|
|
159
|
+
case "create": return internal.activeset_create.execute({ name: args.name || "Context", chunk_ids: args.target?.split(',').map((s) => s.trim()) });
|
|
116
160
|
case "load": return internal.activeset_load.execute({ set_id: args.target });
|
|
117
|
-
case "add": return internal.activeset_add_chunks.execute({ chunk_ids: args.target?.split(',').map(s => s.trim()) });
|
|
118
|
-
case "remove": return internal.activeset_remove_chunks.execute({ chunk_ids: args.target?.split(',').map(s => s.trim()) });
|
|
161
|
+
case "add": return internal.activeset_add_chunks.execute({ chunk_ids: args.target?.split(',').map((s) => s.trim()) });
|
|
162
|
+
case "remove": return internal.activeset_remove_chunks.execute({ chunk_ids: args.target?.split(',').map((s) => s.trim()) });
|
|
119
163
|
case "evict": {
|
|
120
164
|
const lru = getDb().getLruChunks(args.limit);
|
|
121
165
|
return internal.activeset_remove_chunks.execute({ chunk_ids: lru.map(c => c.chunk_id) });
|
|
@@ -126,7 +170,7 @@ export function unifiedTools() {
|
|
|
126
170
|
}
|
|
127
171
|
}
|
|
128
172
|
}),
|
|
129
|
-
code_read:
|
|
173
|
+
code_read: wrap("code_read", {
|
|
130
174
|
description: "Precise reading of symbols or file slices. Follows current plan. Checks for locks and returns historical graffiti.",
|
|
131
175
|
args: {
|
|
132
176
|
symbol: tool.schema.string().optional().describe("Symbol to jump to"),
|
|
@@ -173,8 +217,8 @@ export function unifiedTools() {
|
|
|
173
217
|
throw new Error("Either 'symbol' or 'file' must be provided.");
|
|
174
218
|
}
|
|
175
219
|
}),
|
|
176
|
-
code_propose:
|
|
177
|
-
description: "Plan, propose, and promote changes.
|
|
220
|
+
code_propose: wrap("code_propose", {
|
|
221
|
+
description: "Plan, propose, and promote changes. Automatically handles coordination pulse and lock checks.",
|
|
178
222
|
args: {
|
|
179
223
|
action: tool.schema.enum(["plan", "patch", "validate", "finalize", "promote"]),
|
|
180
224
|
symbol: tool.schema.string().optional().describe("Locus symbol for plan"),
|
|
@@ -216,7 +260,6 @@ export function unifiedTools() {
|
|
|
216
260
|
return res;
|
|
217
261
|
}
|
|
218
262
|
case "validate": {
|
|
219
|
-
// 1. Arch Check
|
|
220
263
|
const { stdout: diff } = await internal.runCmd("git diff --name-only");
|
|
221
264
|
const changedFiles = diff.split('\n').filter(Boolean);
|
|
222
265
|
for (const file of changedFiles) {
|
|
@@ -228,13 +271,10 @@ export function unifiedTools() {
|
|
|
228
271
|
return JSON.stringify({ status: "ARCH_VIOLATION", file, forbidden_import: imp, rule: violation }, null, 2);
|
|
229
272
|
}
|
|
230
273
|
}
|
|
231
|
-
// 2. Surgical Test Scoping
|
|
232
274
|
let focusTests = [];
|
|
233
|
-
if (args.symbol)
|
|
275
|
+
if (args.symbol)
|
|
234
276
|
focusTests = getDb().findAffectedTests(args.symbol);
|
|
235
|
-
}
|
|
236
277
|
getDb().postToBlackboard(agentName, `Validating patch ${args.patch_path}. Scoped tests: ${focusTests.length}`, "pulse");
|
|
237
|
-
// Call validation with scoped tests hint
|
|
238
278
|
return internal.validate_patch.execute({ patch_path: args.patch_path, plan_id: args.plan_id, tests: focusTests });
|
|
239
279
|
}
|
|
240
280
|
case "promote": {
|
|
@@ -259,7 +299,7 @@ export function unifiedTools() {
|
|
|
259
299
|
}
|
|
260
300
|
}
|
|
261
301
|
}),
|
|
262
|
-
code_status:
|
|
302
|
+
code_status: wrap("code_status", {
|
|
263
303
|
description: "Monitor system health, background jobs, Multi-Agent Blackboard, and Resource Locks.",
|
|
264
304
|
args: {
|
|
265
305
|
mode: tool.schema.enum(["stats", "hot_files", "jobs", "plan", "doctor", "blackboard", "locks", "dashboard"]).optional().default("stats"),
|
|
@@ -283,11 +323,11 @@ export function unifiedTools() {
|
|
|
283
323
|
dashboard += `## 📊 System Stats\n- Files: ${stats.files}\n- Chunks: ${stats.chunks}\n- Embedded: ${stats.embeddings.completed}/${stats.chunks}\n\n`;
|
|
284
324
|
dashboard += `## 🔒 Active Locks\n`;
|
|
285
325
|
if (locks.length > 0)
|
|
286
|
-
dashboard += locks.map(
|
|
326
|
+
dashboard += locks.map(l => `- ${l.resource_id} (${l.owner_agent})`).join('\n') + '\n\n';
|
|
287
327
|
else
|
|
288
328
|
dashboard += "_No active locks._\n\n";
|
|
289
329
|
dashboard += `## ⚙️ Recent Jobs\n`;
|
|
290
|
-
dashboard += jobs.map(
|
|
330
|
+
dashboard += jobs.map(j => `- [${j.status.toUpperCase()}] ${j.type} (${j.progress}%)`).join('\n') + '\n\n';
|
|
291
331
|
if (compliance) {
|
|
292
332
|
dashboard += `## 📉 Plan Compliance (${args.plan_id})\n- Score: ${compliance.compliance}%\n- Total Calls: ${compliance.total}\n- Off-Plan: ${compliance.off_plan}\n`;
|
|
293
333
|
}
|
|
@@ -335,15 +375,15 @@ export function unifiedTools() {
|
|
|
335
375
|
}
|
|
336
376
|
}
|
|
337
377
|
}),
|
|
338
|
-
code_setup:
|
|
378
|
+
code_setup: wrap("code_setup", {
|
|
339
379
|
description: "Setup tasks (AI, Git Journal, Indexing, Prompt Scouting, Arch Boundaries).",
|
|
340
380
|
args: {
|
|
341
381
|
action: tool.schema.enum(["init", "ai", "index", "journal", "scout", "arch_rule"]),
|
|
342
382
|
provider: tool.schema.enum(["ollama", "mlx"]).optional().default("ollama"),
|
|
343
383
|
model: tool.schema.string().optional(),
|
|
344
384
|
limit: tool.schema.number().optional(),
|
|
345
|
-
source: tool.schema.string().optional(),
|
|
346
|
-
target: tool.schema.string().optional()
|
|
385
|
+
source: tool.schema.string().optional().describe("Source target pattern"),
|
|
386
|
+
target: tool.schema.string().optional().describe("Target target pattern (forbidden)")
|
|
347
387
|
},
|
|
348
388
|
async execute(args) {
|
|
349
389
|
switch (args.action) {
|
|
@@ -362,6 +402,24 @@ export function unifiedTools() {
|
|
|
362
402
|
}
|
|
363
403
|
}
|
|
364
404
|
}),
|
|
405
|
+
code_contract: wrap("code_contract", {
|
|
406
|
+
description: "Register reactive tool contracts for automated post-execution chaining.",
|
|
407
|
+
args: {
|
|
408
|
+
action: tool.schema.enum(["register", "list", "delete"]),
|
|
409
|
+
trigger_tool: tool.schema.string().optional().describe("Tool that triggers the contract"),
|
|
410
|
+
trigger_action: tool.schema.string().optional().describe("Action that triggers the contract"),
|
|
411
|
+
target_tool: tool.schema.string().optional().describe("Tool to execute automatically"),
|
|
412
|
+
target_args: tool.schema.any().optional().describe("Arguments for the target tool")
|
|
413
|
+
},
|
|
414
|
+
async execute(args) {
|
|
415
|
+
if (args.action === "register") {
|
|
416
|
+
getDb().registerContract(args.trigger_tool, args.trigger_action, args.target_tool, args.target_args);
|
|
417
|
+
return JSON.stringify({ status: "SUCCESS", message: "Contract registered." });
|
|
418
|
+
}
|
|
419
|
+
// List/Delete placeholders
|
|
420
|
+
return JSON.stringify({ status: "SUCCESS", message: "Action completed." });
|
|
421
|
+
}
|
|
422
|
+
}),
|
|
365
423
|
internal_call: tool({
|
|
366
424
|
description: "Advanced access to specialized internal tools.",
|
|
367
425
|
args: { tool_name: tool.schema.string(), args: tool.schema.any() },
|
|
@@ -372,5 +430,6 @@ export function unifiedTools() {
|
|
|
372
430
|
return target.execute(args);
|
|
373
431
|
}
|
|
374
432
|
})
|
|
375
|
-
};
|
|
433
|
+
});
|
|
434
|
+
return api;
|
|
376
435
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-autognosis",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Advanced RAG-powered codebase awareness for OpenCode agents. Features Chunk Cards synthesis, hierarchical reasoning, ActiveSet working memory, and performance optimization for enterprise-scale repositories.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|