cortex-agents 4.1.2 → 5.0.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 +85 -16
- package/dist/cli.js +146 -13
- package/dist/engine/agents.d.ts +19 -0
- package/dist/engine/agents.d.ts.map +1 -0
- package/dist/engine/agents.js +69 -0
- package/dist/engine/db.d.ts +13 -0
- package/dist/engine/db.d.ts.map +1 -0
- package/dist/engine/db.js +28 -0
- package/dist/engine/index.d.ts +50 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +135 -0
- package/dist/engine/models.d.ts +12 -0
- package/dist/engine/models.d.ts.map +1 -0
- package/dist/engine/models.js +23 -0
- package/dist/engine/renderers/claude.d.ts +18 -0
- package/dist/engine/renderers/claude.d.ts.map +1 -0
- package/dist/engine/renderers/claude.js +226 -0
- package/dist/engine/renderers/codex.d.ts +22 -0
- package/dist/engine/renderers/codex.d.ts.map +1 -0
- package/dist/engine/renderers/codex.js +115 -0
- package/dist/engine/renderers/gemini.d.ts +18 -0
- package/dist/engine/renderers/gemini.d.ts.map +1 -0
- package/dist/engine/renderers/gemini.js +203 -0
- package/dist/engine/renderers/index.d.ts +21 -0
- package/dist/engine/renderers/index.d.ts.map +1 -0
- package/dist/engine/renderers/index.js +13 -0
- package/dist/engine/renderers/opencode.d.ts +18 -0
- package/dist/engine/renderers/opencode.d.ts.map +1 -0
- package/dist/engine/renderers/opencode.js +119 -0
- package/dist/engine/schema.d.ts +13 -0
- package/dist/engine/schema.d.ts.map +1 -0
- package/dist/engine/schema.js +125 -0
- package/dist/engine/seed.d.ts +14 -0
- package/dist/engine/seed.d.ts.map +1 -0
- package/dist/engine/seed.js +398 -0
- package/dist/engine/skills.d.ts +11 -0
- package/dist/engine/skills.d.ts.map +1 -0
- package/dist/engine/skills.js +24 -0
- package/dist/engine/targets.d.ts +17 -0
- package/dist/engine/targets.d.ts.map +1 -0
- package/dist/engine/targets.js +79 -0
- package/dist/engine/types.d.ts +100 -0
- package/dist/engine/types.d.ts.map +1 -0
- package/dist/engine/types.js +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -0
- package/dist/tools/engine.d.ts +22 -0
- package/dist/tools/engine.d.ts.map +1 -0
- package/dist/tools/engine.js +56 -0
- package/dist/utils/cortex-code-bridge.d.ts +21 -0
- package/dist/utils/cortex-code-bridge.d.ts.map +1 -0
- package/dist/utils/cortex-code-bridge.js +104 -0
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CortexCodeBridge } from "./utils/cortex-code-bridge.js";
|
|
1
2
|
// Import all tool modules
|
|
2
3
|
import * as cortex from "./tools/cortex";
|
|
3
4
|
import * as worktree from "./tools/worktree";
|
|
@@ -9,6 +10,7 @@ import * as task from "./tools/task";
|
|
|
9
10
|
import * as github from "./tools/github";
|
|
10
11
|
import * as repl from "./tools/repl";
|
|
11
12
|
import * as qualityGate from "./tools/quality-gate";
|
|
13
|
+
import * as engineTools from "./tools/engine";
|
|
12
14
|
// ─── Agent Descriptions (for handover toasts) ───────────────────────────────
|
|
13
15
|
const AGENT_DESCRIPTIONS = {
|
|
14
16
|
implement: "Development mode — ready to implement",
|
|
@@ -149,6 +151,7 @@ function extractErrorMessage(error) {
|
|
|
149
151
|
}
|
|
150
152
|
// ─── Plugin Entry ────────────────────────────────────────────────────────────
|
|
151
153
|
export const CortexPlugin = async (ctx) => {
|
|
154
|
+
const bridge = new CortexCodeBridge();
|
|
152
155
|
return {
|
|
153
156
|
tool: {
|
|
154
157
|
// Cortex tools - .cortex directory management
|
|
@@ -193,6 +196,9 @@ export const CortexPlugin = async (ctx) => {
|
|
|
193
196
|
repl_summary: repl.summary,
|
|
194
197
|
// Quality gate aggregation tool
|
|
195
198
|
quality_gate_summary: qualityGate.qualityGateSummary,
|
|
199
|
+
// Engine-backed tools
|
|
200
|
+
cortex_get_skill: engineTools.getSkill,
|
|
201
|
+
cortex_list_agents: engineTools.listAgents,
|
|
196
202
|
},
|
|
197
203
|
// ── Post-execution toast notifications ────────────────────────────────
|
|
198
204
|
//
|
|
@@ -235,6 +241,53 @@ export const CortexPlugin = async (ctx) => {
|
|
|
235
241
|
},
|
|
236
242
|
// ── Event-driven notifications ───────────────────────────────────────
|
|
237
243
|
async event({ event }) {
|
|
244
|
+
// ── Cortex Code bridge (fire-and-forget, no-op outside Cortex Code) ──
|
|
245
|
+
if (bridge.isActive) {
|
|
246
|
+
// session.status busy → agent started working
|
|
247
|
+
if (event.type === "session.status" &&
|
|
248
|
+
event.properties.status.type === "busy") {
|
|
249
|
+
bridge.taskStarted();
|
|
250
|
+
}
|
|
251
|
+
// session.status idle → agent waiting for user input
|
|
252
|
+
if (event.type === "session.status" &&
|
|
253
|
+
event.properties.status.type === "idle") {
|
|
254
|
+
bridge.interactionNeeded("input");
|
|
255
|
+
}
|
|
256
|
+
// session.idle → all processing complete
|
|
257
|
+
if (event.type === "session.idle") {
|
|
258
|
+
bridge.taskFinished();
|
|
259
|
+
}
|
|
260
|
+
// session.error → forward error
|
|
261
|
+
if (event.type === "session.error") {
|
|
262
|
+
const rawError = event.properties.error;
|
|
263
|
+
const error = rawError &&
|
|
264
|
+
typeof rawError === "object" &&
|
|
265
|
+
"name" in rawError &&
|
|
266
|
+
typeof rawError.name === "string"
|
|
267
|
+
? rawError
|
|
268
|
+
: undefined;
|
|
269
|
+
bridge.error(extractErrorMessage(error));
|
|
270
|
+
}
|
|
271
|
+
// message.part.updated — text content
|
|
272
|
+
if (event.type === "message.part.updated" &&
|
|
273
|
+
event.properties.part.type === "text") {
|
|
274
|
+
bridge.text(event.properties.part.text);
|
|
275
|
+
}
|
|
276
|
+
// message.part.updated — tool call
|
|
277
|
+
if (event.type === "message.part.updated" &&
|
|
278
|
+
event.properties.part.type === "tool") {
|
|
279
|
+
const part = event.properties.part;
|
|
280
|
+
bridge.toolCall(part.callID, part.tool, part.metadata);
|
|
281
|
+
}
|
|
282
|
+
// message.updated — token/cost tracking (assistant messages with usage)
|
|
283
|
+
if (event.type === "message.updated" &&
|
|
284
|
+
event.properties.info.role === "assistant") {
|
|
285
|
+
const msg = event.properties.info;
|
|
286
|
+
if ("tokens" in msg && msg.tokens) {
|
|
287
|
+
bridge.usage(msg.tokens.input ?? 0, msg.tokens.output ?? 0, msg.cost ?? 0, "modelID" in msg ? msg.modelID : undefined);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
238
291
|
try {
|
|
239
292
|
// Agent handover notifications
|
|
240
293
|
if (event.type === "message.part.updated" &&
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const getSkill: {
|
|
2
|
+
description: string;
|
|
3
|
+
args: {
|
|
4
|
+
skillId: import("zod").ZodString;
|
|
5
|
+
};
|
|
6
|
+
execute(args: {
|
|
7
|
+
skillId: string;
|
|
8
|
+
}, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
9
|
+
};
|
|
10
|
+
export declare const listAgents: {
|
|
11
|
+
description: string;
|
|
12
|
+
args: {
|
|
13
|
+
mode: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
14
|
+
primary: "primary";
|
|
15
|
+
subagent: "subagent";
|
|
16
|
+
}>>;
|
|
17
|
+
};
|
|
18
|
+
execute(args: {
|
|
19
|
+
mode?: "primary" | "subagent" | undefined;
|
|
20
|
+
}, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/tools/engine.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,QAAQ;;;;;;;;CAoBnB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;CA4BrB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Engine-backed MCP tools: cortex_get_skill, cortex_list_agents
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { tool } from "@opencode-ai/plugin";
|
|
5
|
+
import { CortexEngine } from "../engine/index.js";
|
|
6
|
+
let _engine = null;
|
|
7
|
+
function getEngine() {
|
|
8
|
+
if (!_engine) {
|
|
9
|
+
_engine = new CortexEngine();
|
|
10
|
+
_engine.initialize();
|
|
11
|
+
}
|
|
12
|
+
return _engine;
|
|
13
|
+
}
|
|
14
|
+
export const getSkill = tool({
|
|
15
|
+
description: "Retrieve the full content of a domain skill by ID. Returns the skill markdown including guidelines, patterns, and best practices.",
|
|
16
|
+
args: {
|
|
17
|
+
skillId: tool.schema
|
|
18
|
+
.string()
|
|
19
|
+
.describe('The skill identifier, e.g. "security-hardening", "api-design"'),
|
|
20
|
+
},
|
|
21
|
+
async execute(args) {
|
|
22
|
+
const engine = getEngine();
|
|
23
|
+
const content = engine.getSkillContent(args.skillId);
|
|
24
|
+
if (!content) {
|
|
25
|
+
const skills = engine.listSkills();
|
|
26
|
+
const available = skills.map((s) => s.id).join(", ");
|
|
27
|
+
return `✗ Skill not found: ${args.skillId}\n\nAvailable skills: ${available}`;
|
|
28
|
+
}
|
|
29
|
+
return content;
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
export const listAgents = tool({
|
|
33
|
+
description: "List all registered agents with their mode (primary/subagent), description, and available tools.",
|
|
34
|
+
args: {
|
|
35
|
+
mode: tool.schema
|
|
36
|
+
.enum(["primary", "subagent"])
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("Filter by agent mode"),
|
|
39
|
+
},
|
|
40
|
+
async execute(args) {
|
|
41
|
+
const engine = getEngine();
|
|
42
|
+
const filter = args.mode ? { mode: args.mode } : undefined;
|
|
43
|
+
const agents = engine.listAgents(filter);
|
|
44
|
+
if (agents.length === 0) {
|
|
45
|
+
return "✗ No agents found in the database. Run 'npx cortex-agents install' first.";
|
|
46
|
+
}
|
|
47
|
+
const lines = agents.map((a) => {
|
|
48
|
+
const tools = engine.getAgentTools(a.id);
|
|
49
|
+
const enabledTools = tools
|
|
50
|
+
.filter((t) => t.allowed)
|
|
51
|
+
.map((t) => t.tool_name);
|
|
52
|
+
return `- **${a.id}** (${a.mode}) — ${a.description}\n Tools: ${enabledTools.join(", ") || "none"}`;
|
|
53
|
+
});
|
|
54
|
+
return `✓ ${agents.length} agents:\n\n${lines.join("\n\n")}`;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class CortexCodeBridge {
|
|
2
|
+
private readonly eventUrl;
|
|
3
|
+
private readonly taskId;
|
|
4
|
+
private readonly active;
|
|
5
|
+
private tokensIn;
|
|
6
|
+
private tokensOut;
|
|
7
|
+
private costUsd;
|
|
8
|
+
private sessionStartTime;
|
|
9
|
+
private started;
|
|
10
|
+
constructor();
|
|
11
|
+
get isActive(): boolean;
|
|
12
|
+
taskStarted(): void;
|
|
13
|
+
taskFinished(): void;
|
|
14
|
+
usage(tokensIn: number, tokensOut: number, costUsd: number, model?: string): void;
|
|
15
|
+
interactionNeeded(reason: string, prompt?: string): void;
|
|
16
|
+
text(content: string): void;
|
|
17
|
+
toolCall(id: string, name: string, input?: unknown): void;
|
|
18
|
+
error(message: string, code?: string, recoverable?: boolean): void;
|
|
19
|
+
private send;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=cortex-code-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cortex-code-bridge.d.ts","sourceRoot":"","sources":["../../src/utils/cortex-code-bridge.ts"],"names":[],"mappings":"AAgBA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAGjC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAAK;IAEpB,OAAO,CAAC,gBAAgB,CAAc;IACtC,OAAO,CAAC,OAAO,CAAS;;IAUxB,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAID,WAAW,IAAI,IAAI;IAOnB,YAAY,IAAI,IAAI;IAUpB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAYjF,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAOxD,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAQzD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI;IAUlE,OAAO,CAAC,IAAI;CAkBb"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// ─── Cortex Code Event Bridge ─────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// When running inside Cortex Code's embedded terminal, the environment provides:
|
|
4
|
+
// CORTEX_EVENT_URL — HTTP endpoint for structured events
|
|
5
|
+
// CORTEX_TASK_ID — ID of the parent task in Cortex Code
|
|
6
|
+
// CORTEX_CODE — "1" when running inside Cortex Code
|
|
7
|
+
//
|
|
8
|
+
// This bridge POSTs structured events so Cortex Code can precisely track agent
|
|
9
|
+
// state (working, waiting, finished) instead of relying on ANSI heuristics.
|
|
10
|
+
//
|
|
11
|
+
// Payload format (Cortex Event Protocol):
|
|
12
|
+
// { cortex: "event", taskId, type, timestamp, ...fields }
|
|
13
|
+
//
|
|
14
|
+
// All HTTP calls are fire-and-forget with a 5s timeout — they never block the
|
|
15
|
+
// agent or throw errors.
|
|
16
|
+
export class CortexCodeBridge {
|
|
17
|
+
eventUrl;
|
|
18
|
+
taskId;
|
|
19
|
+
active;
|
|
20
|
+
// Accumulated usage for task_finished summary
|
|
21
|
+
tokensIn = 0;
|
|
22
|
+
tokensOut = 0;
|
|
23
|
+
costUsd = 0;
|
|
24
|
+
sessionStartTime = Date.now();
|
|
25
|
+
started = false;
|
|
26
|
+
constructor() {
|
|
27
|
+
this.eventUrl = process.env.CORTEX_EVENT_URL;
|
|
28
|
+
this.taskId = process.env.CORTEX_TASK_ID;
|
|
29
|
+
const cortexCode = process.env.CORTEX_CODE;
|
|
30
|
+
this.active = !!(this.eventUrl && this.taskId && cortexCode);
|
|
31
|
+
}
|
|
32
|
+
get isActive() {
|
|
33
|
+
return this.active;
|
|
34
|
+
}
|
|
35
|
+
// ── Event Senders ─────────────────────────────────────────────────────────
|
|
36
|
+
taskStarted() {
|
|
37
|
+
if (this.started)
|
|
38
|
+
return;
|
|
39
|
+
this.started = true;
|
|
40
|
+
this.sessionStartTime = Date.now();
|
|
41
|
+
this.send("task_started", {});
|
|
42
|
+
}
|
|
43
|
+
taskFinished() {
|
|
44
|
+
const duration = Date.now() - this.sessionStartTime;
|
|
45
|
+
this.send("task_finished", {
|
|
46
|
+
tokensIn: this.tokensIn,
|
|
47
|
+
tokensOut: this.tokensOut,
|
|
48
|
+
costUsd: this.costUsd,
|
|
49
|
+
duration,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
usage(tokensIn, tokensOut, costUsd, model) {
|
|
53
|
+
this.tokensIn += tokensIn;
|
|
54
|
+
this.tokensOut += tokensOut;
|
|
55
|
+
this.costUsd += costUsd;
|
|
56
|
+
this.send("usage", {
|
|
57
|
+
tokensIn,
|
|
58
|
+
tokensOut,
|
|
59
|
+
costUsd,
|
|
60
|
+
...(model ? { model } : {}),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
interactionNeeded(reason, prompt) {
|
|
64
|
+
this.send("interaction_needed", {
|
|
65
|
+
reason,
|
|
66
|
+
...(prompt ? { prompt } : {}),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
text(content) {
|
|
70
|
+
this.send("text", { content });
|
|
71
|
+
}
|
|
72
|
+
toolCall(id, name, input) {
|
|
73
|
+
this.send("tool_call", {
|
|
74
|
+
id,
|
|
75
|
+
name,
|
|
76
|
+
...(input !== undefined ? { input } : {}),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
error(message, code, recoverable) {
|
|
80
|
+
this.send("error", {
|
|
81
|
+
message,
|
|
82
|
+
...(code ? { code } : {}),
|
|
83
|
+
...(recoverable !== undefined ? { recoverable } : {}),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// ── Internal ──────────────────────────────────────────────────────────────
|
|
87
|
+
send(type, fields) {
|
|
88
|
+
if (!this.active)
|
|
89
|
+
return;
|
|
90
|
+
const payload = {
|
|
91
|
+
cortex: "event",
|
|
92
|
+
taskId: this.taskId,
|
|
93
|
+
type,
|
|
94
|
+
timestamp: Date.now(),
|
|
95
|
+
...fields,
|
|
96
|
+
};
|
|
97
|
+
fetch(this.eventUrl, {
|
|
98
|
+
method: "POST",
|
|
99
|
+
headers: { "Content-Type": "application/json" },
|
|
100
|
+
body: JSON.stringify(payload),
|
|
101
|
+
signal: AbortSignal.timeout(5000),
|
|
102
|
+
}).catch(() => { });
|
|
103
|
+
}
|
|
104
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortex-agents",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"description": "Structured AI development workflows for OpenCode and Claude Code — plan, build, ship with discipline",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -55,12 +55,14 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@opencode-ai/plugin": "^1.0.0",
|
|
58
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
58
59
|
"@types/node": "^20.0.0",
|
|
59
60
|
"@types/prompts": "^2.4.9",
|
|
60
61
|
"typescript": "^5.0.0",
|
|
61
62
|
"vitest": "^3.0.0"
|
|
62
63
|
},
|
|
63
64
|
"dependencies": {
|
|
65
|
+
"better-sqlite3": "^12.6.2",
|
|
64
66
|
"prompts": "^2.4.2"
|
|
65
67
|
}
|
|
66
68
|
}
|