cortex-agents 4.1.2 → 5.0.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/README.md +85 -16
- package/dist/cli.js +165 -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/mcp-server.d.ts +2 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +555 -0
- package/dist/tools/branch.d.ts +2 -2
- 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/tools/plan.d.ts +4 -4
- package/dist/tools/worktree.d.ts +2 -2
- 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 +6 -3
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Cortex Engine — Seed / Import module
|
|
3
|
+
// Reads .opencode/ agent and skill markdown files and imports them into SQLite.
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { AgentStore } from "./agents.js";
|
|
8
|
+
import { SkillStore } from "./skills.js";
|
|
9
|
+
import { ModelStore } from "./models.js";
|
|
10
|
+
import { TargetStore } from "./targets.js";
|
|
11
|
+
import { MODEL_REGISTRY } from "../registry.js";
|
|
12
|
+
/**
|
|
13
|
+
* Populate the database from .opencode/ markdown files and static registries.
|
|
14
|
+
* All operations are idempotent (INSERT OR REPLACE) and wrapped in a single
|
|
15
|
+
* transaction for atomicity.
|
|
16
|
+
*/
|
|
17
|
+
export function seedDatabase(db, opencodeDir) {
|
|
18
|
+
const agents = new AgentStore(db);
|
|
19
|
+
const skills = new SkillStore(db);
|
|
20
|
+
const models = new ModelStore(db);
|
|
21
|
+
const targets = new TargetStore(db);
|
|
22
|
+
const result = { agents: 0, skills: 0, models: 0, targets: 0 };
|
|
23
|
+
const run = db.transaction(() => {
|
|
24
|
+
result.agents = seedAgents(agents, opencodeDir);
|
|
25
|
+
result.skills = seedSkills(skills, opencodeDir);
|
|
26
|
+
result.models = seedModels(models);
|
|
27
|
+
result.targets = seedTargets(targets);
|
|
28
|
+
seedAgentTargetConfigs(agents, targets, opencodeDir);
|
|
29
|
+
});
|
|
30
|
+
run();
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
// ---- Agent seeding ---------------------------------------------------------
|
|
34
|
+
/** Claude Code native tool name mapping from opencode short names. */
|
|
35
|
+
const CLAUDE_NATIVE_TOOLS = {
|
|
36
|
+
read: "Read",
|
|
37
|
+
write: "Write",
|
|
38
|
+
edit: "Edit",
|
|
39
|
+
bash: "Bash",
|
|
40
|
+
glob: "Glob",
|
|
41
|
+
grep: "Grep",
|
|
42
|
+
};
|
|
43
|
+
/** Gemini CLI native tool name mapping from opencode short names. */
|
|
44
|
+
const GEMINI_NATIVE_TOOLS = {
|
|
45
|
+
read: "read_file",
|
|
46
|
+
write: "write_file",
|
|
47
|
+
edit: "edit_file",
|
|
48
|
+
bash: "run_shell_command",
|
|
49
|
+
glob: "glob_tool",
|
|
50
|
+
grep: "grep_search",
|
|
51
|
+
};
|
|
52
|
+
/** MCP tool prefix for cortex-agents tools exposed via MCP (Claude uses __). */
|
|
53
|
+
const MCP_PREFIX = "mcp__cortex-agents__";
|
|
54
|
+
/** MCP tool prefix for cortex-agents tools exposed via MCP (Gemini uses _). */
|
|
55
|
+
const MCP_PREFIX_GEMINI = "mcp_cortex-agents_";
|
|
56
|
+
function seedAgents(store, opencodeDir) {
|
|
57
|
+
const agentsDir = path.join(opencodeDir, "agents");
|
|
58
|
+
if (!fs.existsSync(agentsDir))
|
|
59
|
+
return 0;
|
|
60
|
+
const files = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md"));
|
|
61
|
+
let count = 0;
|
|
62
|
+
for (const file of files) {
|
|
63
|
+
const id = file.replace(/\.md$/, "");
|
|
64
|
+
const raw = fs.readFileSync(path.join(agentsDir, file), "utf-8");
|
|
65
|
+
const parsed = parseFrontmatter(raw);
|
|
66
|
+
if (!parsed)
|
|
67
|
+
continue;
|
|
68
|
+
const { frontmatter, body } = parsed;
|
|
69
|
+
store.upsert({
|
|
70
|
+
id,
|
|
71
|
+
description: frontmatter.description ?? "",
|
|
72
|
+
mode: frontmatter.mode ?? "subagent",
|
|
73
|
+
temperature: parseFloat(String(frontmatter.temperature ?? "0")),
|
|
74
|
+
system_prompt: body.trim(),
|
|
75
|
+
});
|
|
76
|
+
// -- Tools --
|
|
77
|
+
const tools = frontmatter.tools;
|
|
78
|
+
if (tools && typeof tools === "object") {
|
|
79
|
+
const toolMap = {};
|
|
80
|
+
for (const [k, v] of Object.entries(tools)) {
|
|
81
|
+
toolMap[k] = v === true || v === "true";
|
|
82
|
+
}
|
|
83
|
+
store.setTools(id, toolMap);
|
|
84
|
+
}
|
|
85
|
+
// -- Bash permissions --
|
|
86
|
+
const permission = frontmatter.permission;
|
|
87
|
+
if (permission && typeof permission === "object") {
|
|
88
|
+
const bashPerms = {};
|
|
89
|
+
// edit permission → stored as a bash permission with pattern "__edit__"
|
|
90
|
+
if (permission.edit !== undefined) {
|
|
91
|
+
bashPerms["__edit__"] = String(permission.edit);
|
|
92
|
+
}
|
|
93
|
+
const bash = permission.bash;
|
|
94
|
+
if (typeof bash === "string") {
|
|
95
|
+
// Simple string value: all patterns get this permission (e.g. "deny", "ask")
|
|
96
|
+
bashPerms["*"] = bash;
|
|
97
|
+
}
|
|
98
|
+
else if (bash && typeof bash === "object") {
|
|
99
|
+
// Record<pattern, permission>
|
|
100
|
+
for (const [pattern, perm] of Object.entries(bash)) {
|
|
101
|
+
bashPerms[pattern] = String(perm);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (Object.keys(bashPerms).length > 0) {
|
|
105
|
+
store.setBashPermissions(id, bashPerms);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
count++;
|
|
109
|
+
}
|
|
110
|
+
return count;
|
|
111
|
+
}
|
|
112
|
+
// ---- Skill seeding ---------------------------------------------------------
|
|
113
|
+
function seedSkills(store, opencodeDir) {
|
|
114
|
+
const skillsDir = path.join(opencodeDir, "skills");
|
|
115
|
+
if (!fs.existsSync(skillsDir))
|
|
116
|
+
return 0;
|
|
117
|
+
const dirs = fs
|
|
118
|
+
.readdirSync(skillsDir, { withFileTypes: true })
|
|
119
|
+
.filter((d) => d.isDirectory());
|
|
120
|
+
let count = 0;
|
|
121
|
+
for (const dir of dirs) {
|
|
122
|
+
const skillFile = path.join(skillsDir, dir.name, "SKILL.md");
|
|
123
|
+
if (!fs.existsSync(skillFile))
|
|
124
|
+
continue;
|
|
125
|
+
const raw = fs.readFileSync(skillFile, "utf-8");
|
|
126
|
+
const parsed = parseFrontmatter(raw);
|
|
127
|
+
// Skills are served as-is, so content is the full file
|
|
128
|
+
store.upsert({
|
|
129
|
+
id: dir.name,
|
|
130
|
+
name: parsed?.frontmatter.name
|
|
131
|
+
? String(parsed.frontmatter.name)
|
|
132
|
+
: dir.name,
|
|
133
|
+
description: parsed?.frontmatter.description
|
|
134
|
+
? String(parsed.frontmatter.description)
|
|
135
|
+
: null,
|
|
136
|
+
content: raw,
|
|
137
|
+
});
|
|
138
|
+
count++;
|
|
139
|
+
}
|
|
140
|
+
return count;
|
|
141
|
+
}
|
|
142
|
+
// ---- Model seeding ---------------------------------------------------------
|
|
143
|
+
function seedModels(store) {
|
|
144
|
+
for (const entry of MODEL_REGISTRY) {
|
|
145
|
+
store.upsert({
|
|
146
|
+
id: entry.id,
|
|
147
|
+
name: entry.name,
|
|
148
|
+
provider: entry.provider,
|
|
149
|
+
tier: entry.tier,
|
|
150
|
+
description: entry.description,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return MODEL_REGISTRY.length;
|
|
154
|
+
}
|
|
155
|
+
// ---- Target seeding --------------------------------------------------------
|
|
156
|
+
const BUILTIN_TARGETS = [
|
|
157
|
+
{
|
|
158
|
+
id: "claude",
|
|
159
|
+
display_name: "Claude Code",
|
|
160
|
+
config_dir: "~/.claude",
|
|
161
|
+
agent_file_format: "claude_md",
|
|
162
|
+
instructions_file: "CLAUDE.md",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
id: "opencode",
|
|
166
|
+
display_name: "OpenCode",
|
|
167
|
+
config_dir: "~/.config/opencode",
|
|
168
|
+
agent_file_format: "opencode_md",
|
|
169
|
+
instructions_file: null,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: "codex",
|
|
173
|
+
display_name: "Codex CLI",
|
|
174
|
+
config_dir: "~/.codex",
|
|
175
|
+
agent_file_format: "codex_md",
|
|
176
|
+
instructions_file: "agents/AGENTS.md",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: "gemini",
|
|
180
|
+
display_name: "Gemini CLI",
|
|
181
|
+
config_dir: "~/.gemini",
|
|
182
|
+
agent_file_format: "gemini_md",
|
|
183
|
+
instructions_file: "GEMINI.md",
|
|
184
|
+
},
|
|
185
|
+
];
|
|
186
|
+
function seedTargets(store) {
|
|
187
|
+
for (const target of BUILTIN_TARGETS) {
|
|
188
|
+
store.upsertTarget({
|
|
189
|
+
id: target.id,
|
|
190
|
+
display_name: target.display_name,
|
|
191
|
+
config_dir: target.config_dir,
|
|
192
|
+
agent_file_format: target.agent_file_format,
|
|
193
|
+
instructions_file: target.instructions_file,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return BUILTIN_TARGETS.length;
|
|
197
|
+
}
|
|
198
|
+
// ---- Agent-target config seeding (Claude + Gemini) -------------------------
|
|
199
|
+
function seedAgentTargetConfigs(agentStore, targetStore, opencodeDir) {
|
|
200
|
+
const agentsDir = path.join(opencodeDir, "agents");
|
|
201
|
+
if (!fs.existsSync(agentsDir))
|
|
202
|
+
return;
|
|
203
|
+
const files = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md"));
|
|
204
|
+
for (const file of files) {
|
|
205
|
+
const agentId = file.replace(/\.md$/, "");
|
|
206
|
+
const raw = fs.readFileSync(path.join(agentsDir, file), "utf-8");
|
|
207
|
+
const parsed = parseFrontmatter(raw);
|
|
208
|
+
if (!parsed)
|
|
209
|
+
continue;
|
|
210
|
+
const tools = parsed.frontmatter.tools ?? {};
|
|
211
|
+
// ---- Claude target config ----
|
|
212
|
+
{
|
|
213
|
+
const toolsOverride = [];
|
|
214
|
+
const disallowedTools = [];
|
|
215
|
+
for (const [toolName, allowed] of Object.entries(tools)) {
|
|
216
|
+
const isAllowed = allowed === true || allowed === "true";
|
|
217
|
+
const claudeName = CLAUDE_NATIVE_TOOLS[toolName];
|
|
218
|
+
if (claudeName) {
|
|
219
|
+
if (isAllowed) {
|
|
220
|
+
toolsOverride.push(claudeName);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
disallowedTools.push(claudeName);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
if (isAllowed) {
|
|
228
|
+
toolsOverride.push(`${MCP_PREFIX}${toolName}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
targetStore.upsertAgentTargetConfig({
|
|
233
|
+
agent_id: agentId,
|
|
234
|
+
target_id: "claude",
|
|
235
|
+
native_name: null,
|
|
236
|
+
tools_override: toolsOverride.length > 0 ? toolsOverride : null,
|
|
237
|
+
disallowed_tools: disallowedTools.length > 0 ? disallowedTools : null,
|
|
238
|
+
model_override: "inherit",
|
|
239
|
+
extra_frontmatter: { mcpServers: "cortex-agents" },
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
// ---- Gemini target config ----
|
|
243
|
+
{
|
|
244
|
+
const toolsOverride = [];
|
|
245
|
+
for (const [toolName, allowed] of Object.entries(tools)) {
|
|
246
|
+
const isAllowed = allowed === true || allowed === "true";
|
|
247
|
+
if (!isAllowed)
|
|
248
|
+
continue;
|
|
249
|
+
const geminiName = GEMINI_NATIVE_TOOLS[toolName];
|
|
250
|
+
if (geminiName) {
|
|
251
|
+
toolsOverride.push(geminiName);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
toolsOverride.push(`${MCP_PREFIX_GEMINI}${toolName}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
targetStore.upsertAgentTargetConfig({
|
|
258
|
+
agent_id: agentId,
|
|
259
|
+
target_id: "gemini",
|
|
260
|
+
native_name: null,
|
|
261
|
+
tools_override: toolsOverride.length > 0 ? toolsOverride : null,
|
|
262
|
+
disallowed_tools: null,
|
|
263
|
+
model_override: null,
|
|
264
|
+
extra_frontmatter: null,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Parse YAML-like frontmatter delimited by `---`.
|
|
271
|
+
* Handles:
|
|
272
|
+
* - Top-level key: value pairs
|
|
273
|
+
* - Nested objects via indentation (one level deep)
|
|
274
|
+
* - Boolean (true/false), number, and string values
|
|
275
|
+
* - Comments (lines starting with #)
|
|
276
|
+
*
|
|
277
|
+
* This is intentionally minimal to avoid a YAML library dependency.
|
|
278
|
+
*/
|
|
279
|
+
function parseFrontmatter(content) {
|
|
280
|
+
const trimmed = content.trimStart();
|
|
281
|
+
if (!trimmed.startsWith("---"))
|
|
282
|
+
return null;
|
|
283
|
+
// Find the closing --- delimiter
|
|
284
|
+
const afterFirst = trimmed.indexOf("\n");
|
|
285
|
+
if (afterFirst === -1)
|
|
286
|
+
return null;
|
|
287
|
+
const rest = trimmed.slice(afterFirst + 1);
|
|
288
|
+
const closingIdx = rest.indexOf("\n---");
|
|
289
|
+
if (closingIdx === -1)
|
|
290
|
+
return null;
|
|
291
|
+
const frontmatterStr = rest.slice(0, closingIdx);
|
|
292
|
+
const body = rest.slice(closingIdx + 4); // skip past "\n---"
|
|
293
|
+
const result = {};
|
|
294
|
+
const lines = frontmatterStr.split("\n");
|
|
295
|
+
// Track up to 3 levels: top (indent 0), level1 (indent 2), level2 (indent 4+)
|
|
296
|
+
let l0Key = null;
|
|
297
|
+
let l0Obj = null;
|
|
298
|
+
let l1Key = null;
|
|
299
|
+
let l1Obj = null;
|
|
300
|
+
for (const line of lines) {
|
|
301
|
+
// Skip empty lines and comments
|
|
302
|
+
if (line.trim() === "" || line.trim().startsWith("#"))
|
|
303
|
+
continue;
|
|
304
|
+
const indent = line.length - line.trimStart().length;
|
|
305
|
+
const kv = line.trim().match(/^([^:]+):\s*(.*)$/);
|
|
306
|
+
if (!kv)
|
|
307
|
+
continue;
|
|
308
|
+
const rawKey = kv[1].trim();
|
|
309
|
+
// Strip surrounding quotes from key (e.g., "git status*" → git status*)
|
|
310
|
+
const key = (rawKey.startsWith('"') && rawKey.endsWith('"'))
|
|
311
|
+
|| (rawKey.startsWith("'") && rawKey.endsWith("'"))
|
|
312
|
+
? rawKey.slice(1, -1)
|
|
313
|
+
: rawKey;
|
|
314
|
+
const val = kv[2].trim();
|
|
315
|
+
if (indent === 0) {
|
|
316
|
+
// Top-level key
|
|
317
|
+
l1Key = null;
|
|
318
|
+
l1Obj = null;
|
|
319
|
+
if (val === "") {
|
|
320
|
+
l0Key = key;
|
|
321
|
+
l0Obj = null; // will be created on first nested line
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
l0Key = key;
|
|
325
|
+
l0Obj = null;
|
|
326
|
+
result[key] = parseScalar(val);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
else if (indent >= 2 && indent < 4 && l0Key !== null) {
|
|
330
|
+
// Level 1 nested (2 spaces) — belongs to l0Key
|
|
331
|
+
l1Key = null;
|
|
332
|
+
l1Obj = null;
|
|
333
|
+
if (l0Obj === null) {
|
|
334
|
+
l0Obj = {};
|
|
335
|
+
result[l0Key] = l0Obj;
|
|
336
|
+
}
|
|
337
|
+
if (val === "") {
|
|
338
|
+
l1Key = key;
|
|
339
|
+
l1Obj = null;
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
l1Key = key;
|
|
343
|
+
l1Obj = null;
|
|
344
|
+
l0Obj[key] = parseScalar(val);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else if (indent >= 4 && l0Key !== null && l1Key !== null) {
|
|
348
|
+
// Level 2 nested (4+ spaces) — belongs to l1Key within l0Key
|
|
349
|
+
if (l0Obj === null) {
|
|
350
|
+
l0Obj = {};
|
|
351
|
+
result[l0Key] = l0Obj;
|
|
352
|
+
}
|
|
353
|
+
if (l1Obj === null) {
|
|
354
|
+
l1Obj = {};
|
|
355
|
+
l0Obj[l1Key] = l1Obj;
|
|
356
|
+
}
|
|
357
|
+
l1Obj[key] = parseScalar(val);
|
|
358
|
+
}
|
|
359
|
+
else if (indent >= 2 && l0Key !== null) {
|
|
360
|
+
// Fallback for deeper nesting without l1Key
|
|
361
|
+
if (l0Obj === null) {
|
|
362
|
+
l0Obj = {};
|
|
363
|
+
result[l0Key] = l0Obj;
|
|
364
|
+
}
|
|
365
|
+
l0Obj[key] = parseScalar(val);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return { frontmatter: result, body };
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Parse a scalar value from a YAML-like string.
|
|
372
|
+
* Returns boolean, number, or string.
|
|
373
|
+
*/
|
|
374
|
+
function parseScalar(val) {
|
|
375
|
+
// Remove surrounding quotes if present
|
|
376
|
+
if ((val.startsWith('"') && val.endsWith('"')) ||
|
|
377
|
+
(val.startsWith("'") && val.endsWith("'"))) {
|
|
378
|
+
return val.slice(1, -1);
|
|
379
|
+
}
|
|
380
|
+
// Booleans
|
|
381
|
+
if (val === "true")
|
|
382
|
+
return true;
|
|
383
|
+
if (val === "false")
|
|
384
|
+
return false;
|
|
385
|
+
// Null
|
|
386
|
+
if (val === "null" || val === "~")
|
|
387
|
+
return "";
|
|
388
|
+
// Numbers
|
|
389
|
+
const num = Number(val);
|
|
390
|
+
if (!Number.isNaN(num) && val !== "")
|
|
391
|
+
return num;
|
|
392
|
+
// Strip inline comments: "value # comment" -> "value"
|
|
393
|
+
const commentIdx = val.indexOf(" #");
|
|
394
|
+
if (commentIdx !== -1) {
|
|
395
|
+
return parseScalar(val.slice(0, commentIdx).trim());
|
|
396
|
+
}
|
|
397
|
+
return val;
|
|
398
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type BetterSqlite3 from "better-sqlite3";
|
|
2
|
+
import type { Skill, SkillInput } from "./types.js";
|
|
3
|
+
export declare class SkillStore {
|
|
4
|
+
private db;
|
|
5
|
+
constructor(db: BetterSqlite3.Database);
|
|
6
|
+
get(id: string): Skill | null;
|
|
7
|
+
list(): Skill[];
|
|
8
|
+
getContent(id: string): string | null;
|
|
9
|
+
upsert(skill: SkillInput): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/engine/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,qBAAa,UAAU;IACT,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa,CAAC,QAAQ;IAE9C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAK7B,IAAI,IAAI,KAAK,EAAE;IAKf,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAMrC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;CAOhC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class SkillStore {
|
|
2
|
+
db;
|
|
3
|
+
constructor(db) {
|
|
4
|
+
this.db = db;
|
|
5
|
+
}
|
|
6
|
+
get(id) {
|
|
7
|
+
const stmt = this.db.prepare("SELECT * FROM skills WHERE id = ?");
|
|
8
|
+
return stmt.get(id) ?? null;
|
|
9
|
+
}
|
|
10
|
+
list() {
|
|
11
|
+
const stmt = this.db.prepare("SELECT * FROM skills ORDER BY id");
|
|
12
|
+
return stmt.all();
|
|
13
|
+
}
|
|
14
|
+
getContent(id) {
|
|
15
|
+
const stmt = this.db.prepare("SELECT content FROM skills WHERE id = ?");
|
|
16
|
+
const row = stmt.get(id);
|
|
17
|
+
return row?.content ?? null;
|
|
18
|
+
}
|
|
19
|
+
upsert(skill) {
|
|
20
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO skills (id, name, description, content, updated_at)
|
|
21
|
+
VALUES (?, ?, ?, ?, datetime('now'))`);
|
|
22
|
+
stmt.run(skill.id, skill.name, skill.description ?? null, skill.content);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type BetterSqlite3 from "better-sqlite3";
|
|
2
|
+
import type { CliTarget, AgentTargetConfig, Installation } from "./types.js";
|
|
3
|
+
export declare class TargetStore {
|
|
4
|
+
private db;
|
|
5
|
+
constructor(db: BetterSqlite3.Database);
|
|
6
|
+
getTarget(id: string): CliTarget | null;
|
|
7
|
+
listTargets(): CliTarget[];
|
|
8
|
+
upsertTarget(target: CliTarget): void;
|
|
9
|
+
getAgentTargetConfig(agentId: string, targetId: string): AgentTargetConfig | null;
|
|
10
|
+
upsertAgentTargetConfig(config: AgentTargetConfig): void;
|
|
11
|
+
listAgentTargetConfigs(targetId: string): AgentTargetConfig[];
|
|
12
|
+
getConfig(key: string): string | null;
|
|
13
|
+
setConfig(key: string, value: string): void;
|
|
14
|
+
recordInstallation(targetId: string, scope: string, path: string, version: string): void;
|
|
15
|
+
getInstallations(): Installation[];
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=targets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../../src/engine/targets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,YAAY,EACb,MAAM,YAAY,CAAC;AA+BpB,qBAAa,WAAW;IACV,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa,CAAC,QAAQ;IAI9C,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAKvC,WAAW,IAAI,SAAS,EAAE;IAK1B,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAgBrC,oBAAoB,CAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,iBAAiB,GAAG,IAAI;IAU3B,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAqBxD,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAU7D,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQrC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAU3C,kBAAkB,CAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,IAAI;IAQP,gBAAgB,IAAI,YAAY,EAAE;CAMnC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
function parseAgentTargetConfig(row) {
|
|
2
|
+
return {
|
|
3
|
+
agent_id: row.agent_id,
|
|
4
|
+
target_id: row.target_id,
|
|
5
|
+
native_name: row.native_name,
|
|
6
|
+
tools_override: row.tools_override
|
|
7
|
+
? JSON.parse(row.tools_override)
|
|
8
|
+
: null,
|
|
9
|
+
disallowed_tools: row.disallowed_tools
|
|
10
|
+
? JSON.parse(row.disallowed_tools)
|
|
11
|
+
: null,
|
|
12
|
+
model_override: row.model_override,
|
|
13
|
+
extra_frontmatter: row.extra_frontmatter
|
|
14
|
+
? JSON.parse(row.extra_frontmatter)
|
|
15
|
+
: null,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export class TargetStore {
|
|
19
|
+
db;
|
|
20
|
+
constructor(db) {
|
|
21
|
+
this.db = db;
|
|
22
|
+
}
|
|
23
|
+
// ---- CLI targets ----------------------------------------------------------
|
|
24
|
+
getTarget(id) {
|
|
25
|
+
const stmt = this.db.prepare("SELECT * FROM cli_targets WHERE id = ?");
|
|
26
|
+
return stmt.get(id) ?? null;
|
|
27
|
+
}
|
|
28
|
+
listTargets() {
|
|
29
|
+
const stmt = this.db.prepare("SELECT * FROM cli_targets ORDER BY id");
|
|
30
|
+
return stmt.all();
|
|
31
|
+
}
|
|
32
|
+
upsertTarget(target) {
|
|
33
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO cli_targets (id, display_name, config_dir, agent_file_format, instructions_file)
|
|
34
|
+
VALUES (?, ?, ?, ?, ?)`);
|
|
35
|
+
stmt.run(target.id, target.display_name, target.config_dir, target.agent_file_format, target.instructions_file ?? null);
|
|
36
|
+
}
|
|
37
|
+
// ---- Agent target configs -------------------------------------------------
|
|
38
|
+
getAgentTargetConfig(agentId, targetId) {
|
|
39
|
+
const stmt = this.db.prepare("SELECT * FROM agent_target_config WHERE agent_id = ? AND target_id = ?");
|
|
40
|
+
const row = stmt.get(agentId, targetId);
|
|
41
|
+
return row ? parseAgentTargetConfig(row) : null;
|
|
42
|
+
}
|
|
43
|
+
upsertAgentTargetConfig(config) {
|
|
44
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO agent_target_config
|
|
45
|
+
(agent_id, target_id, native_name, tools_override, disallowed_tools, model_override, extra_frontmatter)
|
|
46
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`);
|
|
47
|
+
stmt.run(config.agent_id, config.target_id, config.native_name ?? null, config.tools_override ? JSON.stringify(config.tools_override) : null, config.disallowed_tools
|
|
48
|
+
? JSON.stringify(config.disallowed_tools)
|
|
49
|
+
: null, config.model_override ?? null, config.extra_frontmatter
|
|
50
|
+
? JSON.stringify(config.extra_frontmatter)
|
|
51
|
+
: null);
|
|
52
|
+
}
|
|
53
|
+
listAgentTargetConfigs(targetId) {
|
|
54
|
+
const stmt = this.db.prepare("SELECT * FROM agent_target_config WHERE target_id = ?");
|
|
55
|
+
const rows = stmt.all(targetId);
|
|
56
|
+
return rows.map(parseAgentTargetConfig);
|
|
57
|
+
}
|
|
58
|
+
// ---- User config ----------------------------------------------------------
|
|
59
|
+
getConfig(key) {
|
|
60
|
+
const stmt = this.db.prepare("SELECT value FROM user_config WHERE key = ?");
|
|
61
|
+
const row = stmt.get(key);
|
|
62
|
+
return row?.value ?? null;
|
|
63
|
+
}
|
|
64
|
+
setConfig(key, value) {
|
|
65
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO user_config (key, value)
|
|
66
|
+
VALUES (?, ?)`);
|
|
67
|
+
stmt.run(key, value);
|
|
68
|
+
}
|
|
69
|
+
// ---- Installation tracking ------------------------------------------------
|
|
70
|
+
recordInstallation(targetId, scope, path, version) {
|
|
71
|
+
const stmt = this.db.prepare(`INSERT OR REPLACE INTO installations (target_id, scope, path, installed_at, version)
|
|
72
|
+
VALUES (?, ?, ?, datetime('now'), ?)`);
|
|
73
|
+
stmt.run(targetId, scope, path, version);
|
|
74
|
+
}
|
|
75
|
+
getInstallations() {
|
|
76
|
+
const stmt = this.db.prepare("SELECT * FROM installations ORDER BY installed_at DESC");
|
|
77
|
+
return stmt.all();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export type AgentMode = 'primary' | 'subagent';
|
|
2
|
+
export type PermissionLevel = 'allow' | 'ask' | 'deny';
|
|
3
|
+
export type ModelTier = 'premium' | 'standard' | 'fast';
|
|
4
|
+
export type BindingType = 'auto' | 'recommended';
|
|
5
|
+
export type InstallScope = 'global' | 'project';
|
|
6
|
+
/** Row from the `agents` table. */
|
|
7
|
+
export interface Agent {
|
|
8
|
+
id: string;
|
|
9
|
+
description: string;
|
|
10
|
+
mode: AgentMode;
|
|
11
|
+
temperature: number;
|
|
12
|
+
system_prompt: string;
|
|
13
|
+
created_at: string;
|
|
14
|
+
updated_at: string;
|
|
15
|
+
}
|
|
16
|
+
/** Payload for creating or updating an agent. */
|
|
17
|
+
export interface AgentInput {
|
|
18
|
+
id: string;
|
|
19
|
+
description: string;
|
|
20
|
+
mode: AgentMode;
|
|
21
|
+
temperature?: number;
|
|
22
|
+
system_prompt: string;
|
|
23
|
+
}
|
|
24
|
+
/** Row from the `agent_tools` table. */
|
|
25
|
+
export interface AgentTool {
|
|
26
|
+
agent_id: string;
|
|
27
|
+
tool_name: string;
|
|
28
|
+
allowed: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** Row from the `agent_bash_permissions` table. */
|
|
31
|
+
export interface BashPermission {
|
|
32
|
+
agent_id: string;
|
|
33
|
+
pattern: string;
|
|
34
|
+
permission: PermissionLevel;
|
|
35
|
+
}
|
|
36
|
+
/** Row from the `skills` table. */
|
|
37
|
+
export interface Skill {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
description: string | null;
|
|
41
|
+
content: string;
|
|
42
|
+
created_at: string | null;
|
|
43
|
+
updated_at: string | null;
|
|
44
|
+
}
|
|
45
|
+
/** Payload for creating or updating a skill. */
|
|
46
|
+
export interface SkillInput {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
description?: string | null;
|
|
50
|
+
content: string;
|
|
51
|
+
}
|
|
52
|
+
/** Row from the `agent_skills` table. */
|
|
53
|
+
export interface AgentSkill {
|
|
54
|
+
agent_id: string;
|
|
55
|
+
skill_id: string;
|
|
56
|
+
binding: BindingType;
|
|
57
|
+
}
|
|
58
|
+
/** Row from the `cli_targets` table. */
|
|
59
|
+
export interface CliTarget {
|
|
60
|
+
id: string;
|
|
61
|
+
display_name: string;
|
|
62
|
+
config_dir: string;
|
|
63
|
+
agent_file_format: string;
|
|
64
|
+
instructions_file: string | null;
|
|
65
|
+
}
|
|
66
|
+
/** Row from the `agent_target_config` table. JSON columns are parsed at read time. */
|
|
67
|
+
export interface AgentTargetConfig {
|
|
68
|
+
agent_id: string;
|
|
69
|
+
target_id: string;
|
|
70
|
+
native_name: string | null;
|
|
71
|
+
tools_override: string[] | null;
|
|
72
|
+
disallowed_tools: string[] | null;
|
|
73
|
+
model_override: string | null;
|
|
74
|
+
extra_frontmatter: Record<string, unknown> | null;
|
|
75
|
+
}
|
|
76
|
+
/** Row from the `models` table. */
|
|
77
|
+
export interface Model {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string;
|
|
80
|
+
provider: string;
|
|
81
|
+
tier: ModelTier;
|
|
82
|
+
description: string;
|
|
83
|
+
}
|
|
84
|
+
/** Row from the `installations` table. */
|
|
85
|
+
export interface Installation {
|
|
86
|
+
target_id: string;
|
|
87
|
+
scope: InstallScope;
|
|
88
|
+
path: string;
|
|
89
|
+
installed_at: string | null;
|
|
90
|
+
version: string;
|
|
91
|
+
}
|
|
92
|
+
/** Outcome of a sync operation against a single CLI target. */
|
|
93
|
+
export interface SyncResult {
|
|
94
|
+
target: string;
|
|
95
|
+
agentsWritten: string[];
|
|
96
|
+
skillsWritten: string[];
|
|
97
|
+
instructionsWritten: boolean;
|
|
98
|
+
errors: string[];
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Cortex Engine — Core type definitions
|
|
3
|
+
// Maps 1:1 to the SQLite schema with typed JSON fields and union literals.
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
export {};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAiMlD,eAAO,MAAM,YAAY,EAAE,MA8N1B,CAAC;AAGF,eAAe,YAAY,CAAC"}
|