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.
Files changed (53) hide show
  1. package/README.md +85 -16
  2. package/dist/cli.js +146 -13
  3. package/dist/engine/agents.d.ts +19 -0
  4. package/dist/engine/agents.d.ts.map +1 -0
  5. package/dist/engine/agents.js +69 -0
  6. package/dist/engine/db.d.ts +13 -0
  7. package/dist/engine/db.d.ts.map +1 -0
  8. package/dist/engine/db.js +28 -0
  9. package/dist/engine/index.d.ts +50 -0
  10. package/dist/engine/index.d.ts.map +1 -0
  11. package/dist/engine/index.js +135 -0
  12. package/dist/engine/models.d.ts +12 -0
  13. package/dist/engine/models.d.ts.map +1 -0
  14. package/dist/engine/models.js +23 -0
  15. package/dist/engine/renderers/claude.d.ts +18 -0
  16. package/dist/engine/renderers/claude.d.ts.map +1 -0
  17. package/dist/engine/renderers/claude.js +226 -0
  18. package/dist/engine/renderers/codex.d.ts +22 -0
  19. package/dist/engine/renderers/codex.d.ts.map +1 -0
  20. package/dist/engine/renderers/codex.js +115 -0
  21. package/dist/engine/renderers/gemini.d.ts +18 -0
  22. package/dist/engine/renderers/gemini.d.ts.map +1 -0
  23. package/dist/engine/renderers/gemini.js +203 -0
  24. package/dist/engine/renderers/index.d.ts +21 -0
  25. package/dist/engine/renderers/index.d.ts.map +1 -0
  26. package/dist/engine/renderers/index.js +13 -0
  27. package/dist/engine/renderers/opencode.d.ts +18 -0
  28. package/dist/engine/renderers/opencode.d.ts.map +1 -0
  29. package/dist/engine/renderers/opencode.js +119 -0
  30. package/dist/engine/schema.d.ts +13 -0
  31. package/dist/engine/schema.d.ts.map +1 -0
  32. package/dist/engine/schema.js +125 -0
  33. package/dist/engine/seed.d.ts +14 -0
  34. package/dist/engine/seed.d.ts.map +1 -0
  35. package/dist/engine/seed.js +398 -0
  36. package/dist/engine/skills.d.ts +11 -0
  37. package/dist/engine/skills.d.ts.map +1 -0
  38. package/dist/engine/skills.js +24 -0
  39. package/dist/engine/targets.d.ts +17 -0
  40. package/dist/engine/targets.d.ts.map +1 -0
  41. package/dist/engine/targets.js +79 -0
  42. package/dist/engine/types.d.ts +100 -0
  43. package/dist/engine/types.d.ts.map +1 -0
  44. package/dist/engine/types.js +5 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +53 -0
  47. package/dist/tools/engine.d.ts +22 -0
  48. package/dist/tools/engine.d.ts.map +1 -0
  49. package/dist/tools/engine.js +56 -0
  50. package/dist/utils/cortex-code-bridge.d.ts +21 -0
  51. package/dist/utils/cortex-code-bridge.d.ts.map +1 -0
  52. package/dist/utils/cortex-code-bridge.js +104 -0
  53. package/package.json +4 -2
@@ -0,0 +1,135 @@
1
+ // ---------------------------------------------------------------------------
2
+ // CortexEngine — Facade class
3
+ // Single entry point for all engine operations: DB lifecycle, CRUD, rendering.
4
+ // ---------------------------------------------------------------------------
5
+ import * as path from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { createDatabase, getDefaultDbPath } from "./db.js";
8
+ import { initializeSchema } from "./schema.js";
9
+ import { seedDatabase } from "./seed.js";
10
+ import { AgentStore } from "./agents.js";
11
+ import { SkillStore } from "./skills.js";
12
+ import { ModelStore } from "./models.js";
13
+ import { TargetStore } from "./targets.js";
14
+ import { getRenderer } from "./renderers/index.js";
15
+ // Side-effect imports: register renderers
16
+ import "./renderers/claude.js";
17
+ import "./renderers/opencode.js";
18
+ import "./renderers/codex.js";
19
+ import "./renderers/gemini.js";
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
22
+ /** Path to the .opencode/ directory shipped with the package. */
23
+ const PACKAGE_OPENCODE_DIR = path.resolve(__dirname, "..", "..", ".opencode");
24
+ export class CortexEngine {
25
+ db;
26
+ _agents;
27
+ _skills;
28
+ _models;
29
+ _targets;
30
+ constructor(dbPath) {
31
+ this.db = createDatabase(dbPath ?? getDefaultDbPath());
32
+ this._agents = new AgentStore(this.db);
33
+ this._skills = new SkillStore(this.db);
34
+ this._models = new ModelStore(this.db);
35
+ this._targets = new TargetStore(this.db);
36
+ }
37
+ // ---- Lifecycle -----------------------------------------------------------
38
+ /** Create tables, run migrations, seed if empty. */
39
+ initialize() {
40
+ initializeSchema(this.db);
41
+ // Seed only if agents table is empty (first run)
42
+ const count = this._agents.list().length;
43
+ if (count === 0) {
44
+ return this.seed();
45
+ }
46
+ return null;
47
+ }
48
+ /** Re-seed the database from .opencode/ files. */
49
+ seed(opencodeDir) {
50
+ return seedDatabase(this.db, opencodeDir ?? PACKAGE_OPENCODE_DIR);
51
+ }
52
+ /** Close the database connection. */
53
+ close() {
54
+ this.db.close();
55
+ }
56
+ // ---- Agents --------------------------------------------------------------
57
+ getAgent(id) {
58
+ return this._agents.get(id);
59
+ }
60
+ listAgents(filter) {
61
+ return this._agents.list(filter);
62
+ }
63
+ upsertAgent(agent) {
64
+ this._agents.upsert(agent);
65
+ }
66
+ getAgentTools(agentId) {
67
+ return this._agents.getTools(agentId);
68
+ }
69
+ getAgentBashPermissions(agentId) {
70
+ return this._agents.getBashPermissions(agentId);
71
+ }
72
+ // ---- Skills --------------------------------------------------------------
73
+ getSkill(id) {
74
+ return this._skills.get(id);
75
+ }
76
+ listSkills() {
77
+ return this._skills.list();
78
+ }
79
+ getSkillContent(id) {
80
+ return this._skills.getContent(id);
81
+ }
82
+ upsertSkill(skill) {
83
+ this._skills.upsert(skill);
84
+ }
85
+ getAgentSkills(agentId) {
86
+ return this._agents.getSkills(agentId);
87
+ }
88
+ // ---- Targets -------------------------------------------------------------
89
+ getTarget(id) {
90
+ return this._targets.getTarget(id);
91
+ }
92
+ listTargets() {
93
+ return this._targets.listTargets();
94
+ }
95
+ getAgentTargetConfig(agentId, targetId) {
96
+ return this._targets.getAgentTargetConfig(agentId, targetId);
97
+ }
98
+ // ---- Rendering & Sync ----------------------------------------------------
99
+ renderAgent(agentId, targetId) {
100
+ const renderer = getRenderer(targetId, this.db);
101
+ if (!renderer)
102
+ throw new Error(`No renderer for target: ${targetId}`);
103
+ return renderer.renderAgent(agentId);
104
+ }
105
+ renderInstructions(targetId) {
106
+ const renderer = getRenderer(targetId, this.db);
107
+ if (!renderer)
108
+ throw new Error(`No renderer for target: ${targetId}`);
109
+ return renderer.renderInstructions();
110
+ }
111
+ syncTarget(targetId, opts) {
112
+ const renderer = getRenderer(targetId, this.db);
113
+ if (!renderer)
114
+ throw new Error(`No renderer for target: ${targetId}`);
115
+ return renderer.sync(opts);
116
+ }
117
+ // ---- Models --------------------------------------------------------------
118
+ listModels(filter) {
119
+ return this._models.list(filter);
120
+ }
121
+ // ---- Config --------------------------------------------------------------
122
+ getConfig(key) {
123
+ return this._targets.getConfig(key);
124
+ }
125
+ setConfig(key, value) {
126
+ this._targets.setConfig(key, value);
127
+ }
128
+ // ---- Installation tracking -----------------------------------------------
129
+ recordInstallation(targetId, scope, path, version) {
130
+ this._targets.recordInstallation(targetId, scope, path, version);
131
+ }
132
+ getInstallations() {
133
+ return this._targets.getInstallations();
134
+ }
135
+ }
@@ -0,0 +1,12 @@
1
+ import type BetterSqlite3 from "better-sqlite3";
2
+ import type { Model } from "./types.js";
3
+ export declare class ModelStore {
4
+ private db;
5
+ constructor(db: BetterSqlite3.Database);
6
+ get(id: string): Model | null;
7
+ list(filter?: {
8
+ tier?: string;
9
+ }): Model[];
10
+ upsert(model: Model): void;
11
+ }
12
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/engine/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,qBAAa,UAAU;IACT,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa,CAAC,QAAQ;IAE9C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAK7B,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,EAAE;IAazC,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAO3B"}
@@ -0,0 +1,23 @@
1
+ export class ModelStore {
2
+ db;
3
+ constructor(db) {
4
+ this.db = db;
5
+ }
6
+ get(id) {
7
+ const stmt = this.db.prepare("SELECT * FROM models WHERE id = ?");
8
+ return stmt.get(id) ?? null;
9
+ }
10
+ list(filter) {
11
+ if (filter?.tier) {
12
+ const stmt = this.db.prepare("SELECT * FROM models WHERE tier = ? ORDER BY provider, name");
13
+ return stmt.all(filter.tier);
14
+ }
15
+ const stmt = this.db.prepare("SELECT * FROM models ORDER BY provider, name");
16
+ return stmt.all();
17
+ }
18
+ upsert(model) {
19
+ const stmt = this.db.prepare(`INSERT OR REPLACE INTO models (id, name, provider, tier, description)
20
+ VALUES (?, ?, ?, ?, ?)`);
21
+ stmt.run(model.id, model.name, model.provider, model.tier, model.description);
22
+ }
23
+ }
@@ -0,0 +1,18 @@
1
+ import type BetterSqlite3 from "better-sqlite3";
2
+ import type { Renderer } from "./index.js";
3
+ import type { SyncResult } from "../types.js";
4
+ declare class ClaudeRenderer implements Renderer {
5
+ private db;
6
+ private agents;
7
+ private skills;
8
+ private targets;
9
+ constructor(db: BetterSqlite3.Database);
10
+ renderAgent(agentId: string): string;
11
+ renderInstructions(): string;
12
+ sync(opts?: {
13
+ scope?: string;
14
+ projectPath?: string;
15
+ }): SyncResult;
16
+ }
17
+ export { ClaudeRenderer };
18
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/engine/renderers/claude.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA2E9C,cAAM,cAAe,YAAW,QAAQ;IAK1B,OAAO,CAAC,EAAE;IAJtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAAc;gBAET,EAAE,EAAE,aAAa,CAAC,QAAQ;IAQ9C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IA4EpC,kBAAkB,IAAI,MAAM;IA0C5B,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;CA4ClE;AAKD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,226 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Cortex Engine — Claude Code renderer
3
+ // Produces ~/.claude/agents/*.md files (YAML frontmatter + system prompt)
4
+ // and a CLAUDE.md instructions file.
5
+ // ---------------------------------------------------------------------------
6
+ import * as fs from "fs";
7
+ import * as path from "path";
8
+ import * as os from "os";
9
+ import { AgentStore } from "../agents.js";
10
+ import { SkillStore } from "../skills.js";
11
+ import { TargetStore } from "../targets.js";
12
+ import { registerRenderer } from "./index.js";
13
+ // ---------------------------------------------------------------------------
14
+ // Tool-name mapping: OpenCode name -> Claude PascalCase name
15
+ // ---------------------------------------------------------------------------
16
+ const NATIVE_TOOL_MAP = {
17
+ read: "Read",
18
+ write: "Write",
19
+ edit: "Edit",
20
+ bash: "Bash",
21
+ glob: "Glob",
22
+ grep: "Grep",
23
+ skill: "Skill",
24
+ task: "Agent",
25
+ };
26
+ const NATIVE_TOOL_NAMES = new Set(Object.keys(NATIVE_TOOL_MAP));
27
+ /**
28
+ * Map an OpenCode tool name to its Claude representation.
29
+ *
30
+ * - Native tools (read, write, ...) become PascalCase (Read, Write, ...).
31
+ * - The special `task` tool maps to `Agent`.
32
+ * - Everything else is a Cortex MCP tool: `mcp__cortex-agents__{name}`.
33
+ */
34
+ function mapToolName(toolName) {
35
+ if (NATIVE_TOOL_NAMES.has(toolName)) {
36
+ return NATIVE_TOOL_MAP[toolName];
37
+ }
38
+ return `mcp__cortex-agents__${toolName}`;
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // YAML helpers — lightweight, no external dep
42
+ // ---------------------------------------------------------------------------
43
+ /** Escape a YAML string value. Wraps in quotes when necessary. */
44
+ function yamlValue(v) {
45
+ // If it contains characters that could confuse a YAML parser, quote it.
46
+ if (v === "" ||
47
+ v.includes(":") ||
48
+ v.includes("#") ||
49
+ v.includes("{") ||
50
+ v.includes("}") ||
51
+ v.includes("[") ||
52
+ v.includes("]") ||
53
+ v.includes(",") ||
54
+ v.includes("&") ||
55
+ v.includes("*") ||
56
+ v.includes("!") ||
57
+ v.includes("|") ||
58
+ v.includes(">") ||
59
+ v.includes("'") ||
60
+ v.includes('"') ||
61
+ v.includes("%") ||
62
+ v.includes("@") ||
63
+ v.includes("`") ||
64
+ v.startsWith(" ") ||
65
+ v.endsWith(" ")) {
66
+ return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
67
+ }
68
+ return v;
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // ClaudeRenderer
72
+ // ---------------------------------------------------------------------------
73
+ class ClaudeRenderer {
74
+ db;
75
+ agents;
76
+ skills;
77
+ targets;
78
+ constructor(db) {
79
+ this.db = db;
80
+ this.agents = new AgentStore(db);
81
+ this.skills = new SkillStore(db);
82
+ this.targets = new TargetStore(db);
83
+ }
84
+ // ---- renderAgent ----------------------------------------------------------
85
+ renderAgent(agentId) {
86
+ const agent = this.agents.get(agentId);
87
+ if (!agent)
88
+ throw new Error(`Agent not found: ${agentId}`);
89
+ const targetConfig = this.targets.getAgentTargetConfig(agentId, "claude");
90
+ const agentTools = this.agents.getTools(agentId);
91
+ // ----- Determine tools and disallowedTools lists -----
92
+ let toolsList;
93
+ let disallowedList;
94
+ if (targetConfig?.tools_override) {
95
+ // Explicit override from the agent_target_config table — use as-is.
96
+ toolsList = targetConfig.tools_override;
97
+ }
98
+ else {
99
+ // Derive from agent_tools: every tool where allowed = true.
100
+ toolsList = agentTools
101
+ .filter((t) => t.allowed)
102
+ .map((t) => mapToolName(t.tool_name));
103
+ }
104
+ if (targetConfig?.disallowed_tools) {
105
+ disallowedList = targetConfig.disallowed_tools;
106
+ }
107
+ else {
108
+ // Derive from agent_tools: every tool where allowed = false,
109
+ // but only native tools make sense in disallowedTools.
110
+ disallowedList = agentTools
111
+ .filter((t) => !t.allowed && NATIVE_TOOL_NAMES.has(t.tool_name))
112
+ .map((t) => NATIVE_TOOL_MAP[t.tool_name]);
113
+ }
114
+ // ----- Model -----
115
+ const model = targetConfig?.model_override ?? "inherit";
116
+ // ----- Description -----
117
+ const description = targetConfig?.native_name ?? agent.description;
118
+ // ----- Build frontmatter -----
119
+ const lines = ["---"];
120
+ lines.push(`name: ${yamlValue(agentId)}`);
121
+ lines.push(`description: ${yamlValue(description)}`);
122
+ if (toolsList.length > 0) {
123
+ lines.push(`tools: ${toolsList.map(yamlValue).join(", ")}`);
124
+ }
125
+ if (disallowedList.length > 0) {
126
+ lines.push(`disallowedTools: ${disallowedList.map(yamlValue).join(", ")}`);
127
+ }
128
+ lines.push(`model: ${yamlValue(model)}`);
129
+ // Extra frontmatter from target config (arbitrary keys).
130
+ // Seed stores mcpServers here; fall back to default if absent.
131
+ const extra = targetConfig?.extra_frontmatter ?? {};
132
+ if (!("mcpServers" in extra)) {
133
+ lines.push("mcpServers: cortex-agents");
134
+ }
135
+ for (const [key, value] of Object.entries(extra)) {
136
+ lines.push(`${key}: ${yamlValue(String(value))}`);
137
+ }
138
+ lines.push("---");
139
+ // ----- System prompt body -----
140
+ return lines.join("\n") + "\n" + agent.system_prompt;
141
+ }
142
+ // ---- renderInstructions ---------------------------------------------------
143
+ renderInstructions() {
144
+ const skills = this.skills.list();
145
+ const agents = this.agents.list();
146
+ const subagents = agents.filter((a) => a.mode === "subagent");
147
+ return `# Cortex Agents — Global Configuration
148
+
149
+ > Auto-generated by \`npx cortex-agents install --target claude --global\`. Do not edit manually.
150
+
151
+ ## Overview
152
+
153
+ Cortex Agents provides structured development workflows: plan \u2192 build \u2192 quality gate \u2192 ship.
154
+ All 33 tools are available via MCP server (\`npx cortex-agents mcp\`).
155
+
156
+ ## Default Workflow
157
+
158
+ When starting a new task or session, always default to the \`/architect\` workflow first to plan the work before implementing. Only skip planning for trivial changes (typo fixes, single-line edits).
159
+
160
+ 1. **Plan** \u2014 Use \`/architect\` to analyze requirements and create an implementation plan
161
+ 2. **Implement** \u2014 Use \`/implement\` to execute the plan with iterative build+test verification
162
+ 3. **Fix** \u2014 Use \`/fix\` for quick bug fixes with minimal changes
163
+
164
+ ## Available Skills
165
+
166
+ ${skills.map((s) => ` - ${s.id}`).join("\n")}
167
+
168
+ ## Custom Agents (available in /agents)
169
+
170
+ ${subagents.map((a) => a.id).join(", ")}
171
+
172
+ ## Quality Gate
173
+
174
+ After implementation, assess change scope and launch parallel Agent tool calls:
175
+ - **Trivial** (docs only): Skip quality gate
176
+ - **Low** (tests/config): Testing agent only
177
+ - **Standard** (normal code): Testing + Security + Audit + Docs agents
178
+ - **High** (auth/payments/infra): All agents including Perf and DevOps
179
+ `;
180
+ }
181
+ // ---- sync -----------------------------------------------------------------
182
+ sync(opts) {
183
+ const target = this.targets.getTarget("claude");
184
+ if (!target)
185
+ throw new Error("Claude target not configured");
186
+ const configDir = target.config_dir.replace("~", os.homedir());
187
+ const agentsDir = path.join(configDir, "agents");
188
+ fs.mkdirSync(agentsDir, { recursive: true });
189
+ const result = {
190
+ target: "claude",
191
+ agentsWritten: [],
192
+ skillsWritten: [],
193
+ instructionsWritten: false,
194
+ errors: [],
195
+ };
196
+ // Render each agent
197
+ const agents = this.agents.list();
198
+ for (const agent of agents) {
199
+ try {
200
+ const content = this.renderAgent(agent.id);
201
+ const filePath = path.join(agentsDir, `${agent.id}.md`);
202
+ fs.writeFileSync(filePath, content);
203
+ result.agentsWritten.push(agent.id);
204
+ }
205
+ catch (err) {
206
+ result.errors.push(`Agent ${agent.id}: ${err.message}`);
207
+ }
208
+ }
209
+ // Render instructions file
210
+ if (target.instructions_file) {
211
+ try {
212
+ const content = this.renderInstructions();
213
+ const filePath = path.join(configDir, target.instructions_file);
214
+ fs.writeFileSync(filePath, content);
215
+ result.instructionsWritten = true;
216
+ }
217
+ catch (err) {
218
+ result.errors.push(`Instructions: ${err.message}`);
219
+ }
220
+ }
221
+ return result;
222
+ }
223
+ }
224
+ // Self-register on import.
225
+ registerRenderer("claude", (db) => new ClaudeRenderer(db));
226
+ export { ClaudeRenderer };
@@ -0,0 +1,22 @@
1
+ import type BetterSqlite3 from "better-sqlite3";
2
+ import type { Renderer } from "./index.js";
3
+ import type { SyncResult } from "../types.js";
4
+ declare class CodexRenderer implements Renderer {
5
+ private db;
6
+ private agents;
7
+ private skills;
8
+ private targets;
9
+ constructor(db: BetterSqlite3.Database);
10
+ /**
11
+ * Codex doesn't use per-agent .md files (agents are configured in TOML).
12
+ * Returns the agent's system prompt as plain text for API consumers.
13
+ */
14
+ renderAgent(agentId: string): string;
15
+ renderInstructions(): string;
16
+ sync(opts?: {
17
+ scope?: string;
18
+ projectPath?: string;
19
+ }): SyncResult;
20
+ }
21
+ export { CodexRenderer };
22
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/engine/renderers/codex.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU9C,cAAM,aAAc,YAAW,QAAQ;IAKzB,OAAO,CAAC,EAAE;IAJtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAAc;gBAET,EAAE,EAAE,aAAa,CAAC,QAAQ;IAQ9C;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAQpC,kBAAkB,IAAI,MAAM;IA+C5B,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;CAgClE;AAKD,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,115 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Cortex Engine — Codex CLI renderer
3
+ // Produces ~/.codex/agents/AGENTS.md instructions file.
4
+ // Codex agents are configured via TOML (user-specific), so we only render
5
+ // the instructions markdown file here.
6
+ // ---------------------------------------------------------------------------
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import * as os from "os";
10
+ import { AgentStore } from "../agents.js";
11
+ import { SkillStore } from "../skills.js";
12
+ import { TargetStore } from "../targets.js";
13
+ import { registerRenderer } from "./index.js";
14
+ // ---------------------------------------------------------------------------
15
+ // CodexRenderer
16
+ // ---------------------------------------------------------------------------
17
+ class CodexRenderer {
18
+ db;
19
+ agents;
20
+ skills;
21
+ targets;
22
+ constructor(db) {
23
+ this.db = db;
24
+ this.agents = new AgentStore(db);
25
+ this.skills = new SkillStore(db);
26
+ this.targets = new TargetStore(db);
27
+ }
28
+ // ---- renderAgent ----------------------------------------------------------
29
+ /**
30
+ * Codex doesn't use per-agent .md files (agents are configured in TOML).
31
+ * Returns the agent's system prompt as plain text for API consumers.
32
+ */
33
+ renderAgent(agentId) {
34
+ const agent = this.agents.get(agentId);
35
+ if (!agent)
36
+ throw new Error(`Agent not found: ${agentId}`);
37
+ return agent.system_prompt;
38
+ }
39
+ // ---- renderInstructions ---------------------------------------------------
40
+ renderInstructions() {
41
+ const skills = this.skills.list();
42
+ const agents = this.agents.list();
43
+ const subagents = agents.filter((a) => a.mode === "subagent");
44
+ const agentList = agents
45
+ .map((a) => `- **${a.id}**: ${a.description}`)
46
+ .join("\n");
47
+ return `# Cortex Agents — Project Instructions
48
+
49
+ > Auto-generated by \`npx cortex-agents install --target codex\`. Do not edit manually.
50
+
51
+ ## Overview
52
+
53
+ Cortex Agents provides structured development workflows: plan \u2192 build \u2192 quality gate \u2192 ship.
54
+
55
+ ## Default Workflow
56
+
57
+ 1. **Plan** \u2014 Analyze requirements and create an implementation plan
58
+ 2. **Implement** \u2014 Execute the plan with iterative build+test verification
59
+ 3. **Fix** \u2014 Quick bug fixes with minimal changes
60
+
61
+ ## Available Agents
62
+
63
+ ${agentList}
64
+
65
+ ## Available Skills
66
+
67
+ ${skills.map((s) => ` - ${s.id}`).join("\n")}
68
+
69
+ ## Custom Agents
70
+
71
+ ${subagents.map((a) => a.id).join(", ")}
72
+
73
+ ## Quality Gate
74
+
75
+ After implementation, assess change scope and launch parallel tool calls:
76
+ - **Trivial** (docs only): Skip quality gate
77
+ - **Low** (tests/config): Testing agent only
78
+ - **Standard** (normal code): Testing + Security + Audit + Docs agents
79
+ - **High** (auth/payments/infra): All agents including Perf and DevOps
80
+ `;
81
+ }
82
+ // ---- sync -----------------------------------------------------------------
83
+ sync(opts) {
84
+ const target = this.targets.getTarget("codex");
85
+ if (!target)
86
+ throw new Error("Codex target not configured");
87
+ const configDir = target.config_dir.replace("~", os.homedir());
88
+ const agentsDir = path.join(configDir, "agents");
89
+ fs.mkdirSync(agentsDir, { recursive: true });
90
+ const result = {
91
+ target: "codex",
92
+ agentsWritten: [],
93
+ skillsWritten: [],
94
+ instructionsWritten: false,
95
+ errors: [],
96
+ };
97
+ // Render instructions file (agents/AGENTS.md)
98
+ if (target.instructions_file) {
99
+ try {
100
+ const content = this.renderInstructions();
101
+ const filePath = path.join(configDir, target.instructions_file);
102
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
103
+ fs.writeFileSync(filePath, content);
104
+ result.instructionsWritten = true;
105
+ }
106
+ catch (err) {
107
+ result.errors.push(`Instructions: ${err.message}`);
108
+ }
109
+ }
110
+ return result;
111
+ }
112
+ }
113
+ // Self-register on import.
114
+ registerRenderer("codex", (db) => new CodexRenderer(db));
115
+ export { CodexRenderer };
@@ -0,0 +1,18 @@
1
+ import type BetterSqlite3 from "better-sqlite3";
2
+ import type { Renderer } from "./index.js";
3
+ import type { SyncResult } from "../types.js";
4
+ declare class GeminiRenderer implements Renderer {
5
+ private db;
6
+ private agents;
7
+ private skills;
8
+ private targets;
9
+ constructor(db: BetterSqlite3.Database);
10
+ renderAgent(agentId: string): string;
11
+ renderInstructions(): string;
12
+ sync(opts?: {
13
+ scope?: string;
14
+ projectPath?: string;
15
+ }): SyncResult;
16
+ }
17
+ export { GeminiRenderer };
18
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/engine/renderers/gemini.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAuE9C,cAAM,cAAe,YAAW,QAAQ;IAK1B,OAAO,CAAC,EAAE;IAJtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAAc;gBAET,EAAE,EAAE,aAAa,CAAC,QAAQ;IAQ9C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAoDpC,kBAAkB,IAAI,MAAM;IA0C5B,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;CA4ClE;AAKD,OAAO,EAAE,cAAc,EAAE,CAAC"}