@deimoscloud/coreai 0.1.15 → 0.1.16

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 (47) hide show
  1. package/agents/android-engineer.md +289 -0
  2. package/agents/backend-engineer.md +287 -0
  3. package/agents/database-administrator.md +289 -0
  4. package/agents/devops-engineer.md +323 -0
  5. package/agents/{examples/engineering-manager.md → engineering-manager.md} +208 -171
  6. package/agents/frontend-engineer.md +287 -0
  7. package/agents/product-manager.md +371 -0
  8. package/agents/react-engineer.md +289 -0
  9. package/agents/react-native-engineer.md +289 -0
  10. package/agents/software-security-engineer.md +451 -0
  11. package/agents/software-solutions-architect.md +469 -0
  12. package/agents/sre-huawei-cloud-architect.md +289 -0
  13. package/agents/sre-iac-specialist.md +289 -0
  14. package/agents/sre-kubernetes-specialist.md +289 -0
  15. package/agents/sre-network-specialist.md +289 -0
  16. package/agents/wearos-engineer.md +289 -0
  17. package/dist/cli/index.js +291 -216
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/index.d.ts +41 -55
  20. package/dist/index.js +275 -205
  21. package/dist/index.js.map +1 -1
  22. package/package.json +1 -1
  23. package/agents/android-engineer.yaml +0 -108
  24. package/agents/backend-engineer.yaml +0 -106
  25. package/agents/database-administrator.yaml +0 -108
  26. package/agents/devops-engineer.yaml +0 -106
  27. package/agents/engineering-manager.yaml +0 -104
  28. package/agents/examples/android-engineer.md +0 -302
  29. package/agents/examples/backend-engineer.md +0 -320
  30. package/agents/examples/devops-engineer.md +0 -742
  31. package/agents/examples/frontend-engineer.md +0 -58
  32. package/agents/examples/product-manager.md +0 -315
  33. package/agents/examples/qa-engineer.md +0 -371
  34. package/agents/examples/security-engineer.md +0 -525
  35. package/agents/examples/solutions-architect.md +0 -351
  36. package/agents/examples/wearos-engineer.md +0 -359
  37. package/agents/frontend-engineer.yaml +0 -106
  38. package/agents/product-manager.yaml +0 -109
  39. package/agents/react-engineer.yaml +0 -108
  40. package/agents/react-native-engineer.yaml +0 -108
  41. package/agents/software-security-engineer.yaml +0 -108
  42. package/agents/software-solutions-architect.yaml +0 -107
  43. package/agents/sre-huawei-cloud-architect.yaml +0 -108
  44. package/agents/sre-iac-specialist.yaml +0 -108
  45. package/agents/sre-kubernetes-specialist.yaml +0 -108
  46. package/agents/sre-network-specialist.yaml +0 -108
  47. package/agents/wearos-engineer.yaml +0 -108
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { readFileSync as readFileSync5 } from "fs";
2
+ import { readFileSync as readFileSync6 } from "fs";
3
3
  import { dirname as dirname5, join as join8 } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
 
@@ -149,6 +149,61 @@ var AgentError = class extends Error {
149
149
  this.name = "AgentError";
150
150
  }
151
151
  };
152
+ function extractFrontmatter(content) {
153
+ const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
154
+ if (!match) {
155
+ throw new AgentError(
156
+ "No YAML frontmatter found. Agent MD files must start with YAML frontmatter (---)",
157
+ "PARSE_ERROR"
158
+ );
159
+ }
160
+ const frontmatterYaml = match[1];
161
+ const body = match[2] ?? "";
162
+ let frontmatter;
163
+ try {
164
+ frontmatter = parseYaml2(frontmatterYaml);
165
+ } catch (error) {
166
+ const message = error instanceof Error ? error.message : "Unknown parse error";
167
+ throw new AgentError(`Failed to parse YAML frontmatter: ${message}`, "PARSE_ERROR", error);
168
+ }
169
+ if (!frontmatter || typeof frontmatter !== "object") {
170
+ throw new AgentError("Invalid frontmatter: expected an object", "PARSE_ERROR");
171
+ }
172
+ return { frontmatter, body };
173
+ }
174
+ function loadAgentFromMdFile(filePath) {
175
+ if (!existsSync2(filePath)) {
176
+ throw new AgentError(`Agent file not found: ${filePath}`, "NOT_FOUND");
177
+ }
178
+ let content;
179
+ try {
180
+ content = readFileSync2(filePath, "utf-8");
181
+ } catch (error) {
182
+ const message = error instanceof Error ? error.message : "Unknown read error";
183
+ throw new AgentError(`Failed to read agent file ${filePath}: ${message}`, "READ_ERROR", error);
184
+ }
185
+ const { frontmatter } = extractFrontmatter(content);
186
+ const role = frontmatter.name || getRoleFromFilename(filePath);
187
+ if (!role) {
188
+ throw new AgentError(
189
+ `Agent MD file must have a 'name' field in frontmatter or a valid filename: ${filePath}`,
190
+ "VALIDATION_ERROR"
191
+ );
192
+ }
193
+ const description = frontmatter.description || "";
194
+ const tools = typeof frontmatter.tools === "string" ? frontmatter.tools.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
195
+ const definition = {
196
+ role,
197
+ type: "ic-engineer",
198
+ // Default, actual identity is in the MD content
199
+ display_name: role.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
200
+ description
201
+ };
202
+ if (tools) {
203
+ definition.tools = tools;
204
+ }
205
+ return definition;
206
+ }
152
207
  function parseAgentYaml(content, filePath) {
153
208
  try {
154
209
  return parseYaml2(content);
@@ -180,7 +235,7 @@ function validateAgentDefinition(agent) {
180
235
  }
181
236
  return agent;
182
237
  }
183
- function loadAgentFromFile(filePath) {
238
+ function loadAgentFromYamlFile(filePath) {
184
239
  if (!existsSync2(filePath)) {
185
240
  throw new AgentError(`Agent file not found: ${filePath}`, "NOT_FOUND");
186
241
  }
@@ -194,18 +249,36 @@ function loadAgentFromFile(filePath) {
194
249
  const parsed = parseAgentYaml(content, filePath);
195
250
  return validateAgentDefinition(parsed);
196
251
  }
197
- function listYamlFiles(dir) {
252
+ function loadAgentFromFile(filePath) {
253
+ const ext = extname(filePath).toLowerCase();
254
+ if (ext === ".md") {
255
+ return loadAgentFromMdFile(filePath);
256
+ }
257
+ if (ext === ".yaml" || ext === ".yml") {
258
+ console.warn(
259
+ `Warning: YAML agent definitions are deprecated and will be removed in a future version.
260
+ Please migrate ${basename(filePath)} to Markdown format.`
261
+ );
262
+ return loadAgentFromYamlFile(filePath);
263
+ }
264
+ throw new AgentError(
265
+ `Unsupported agent file format: ${ext}. Use .md (recommended) or .yaml/.yml (deprecated)`,
266
+ "PARSE_ERROR"
267
+ );
268
+ }
269
+ function listAgentFiles(dir) {
198
270
  if (!existsSync2(dir)) {
199
271
  return [];
200
272
  }
201
273
  return readdirSync(dir).filter((file) => {
274
+ if (file.startsWith("_")) return false;
202
275
  const ext = extname(file).toLowerCase();
203
- return ext === ".yaml" || ext === ".yml";
276
+ return ext === ".md" || ext === ".yaml" || ext === ".yml";
204
277
  }).map((file) => join2(dir, file));
205
278
  }
206
279
  function loadAgentsFromDirectory(dir, source) {
207
280
  const agents = /* @__PURE__ */ new Map();
208
- const files = listYamlFiles(dir);
281
+ const files = listAgentFiles(dir);
209
282
  for (const filePath of files) {
210
283
  try {
211
284
  const definition = loadAgentFromFile(filePath);
@@ -372,193 +445,45 @@ function resolveAgentDefinition(agent, config, options = {}) {
372
445
  }
373
446
 
374
447
  // src/agents/compiler.ts
375
- import { existsSync as existsSync3, mkdirSync, writeFileSync } from "fs";
376
- import { join as join3, dirname as dirname2 } from "path";
448
+ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
449
+ import { join as join3, dirname as dirname2, extname as extname2 } from "path";
450
+ import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
377
451
  function buildAgentTools(agent, mcpServers) {
378
452
  const tools = agent.tools ? [...agent.tools] : [...DEFAULT_AGENT_TOOLS];
379
453
  if (mcpServers && mcpServers.length > 0) {
380
454
  for (const server of mcpServers) {
381
- tools.push(`mcp__${server}`);
382
- }
383
- }
384
- return tools.join(", ");
385
- }
386
- function generateKnowledgeLibrarySection(agent, lines) {
387
- const kl = agent.knowledge_library;
388
- if (!kl) return;
389
- lines.push("## Knowledge Library Structure");
390
- lines.push("");
391
- if (kl.shared) {
392
- lines.push("### Shared Context (Root - All Agents)");
393
- lines.push("```");
394
- lines.push("/KnowledgeLibrary/");
395
- if (kl.shared.context) {
396
- const filename = kl.shared.context.split("/").pop() ?? "context.txt";
397
- lines.push(`\u251C\u2500\u2500 ${filename}`);
398
- }
399
- if (kl.shared.architecture) {
400
- const filename = kl.shared.architecture.split("/").pop() ?? "architecture.txt";
401
- lines.push(`\u251C\u2500\u2500 ${filename}`);
402
- }
403
- if (kl.shared.prd) {
404
- const filename = kl.shared.prd.split("/").pop() ?? "prd.txt";
405
- lines.push(`\u2514\u2500\u2500 ${filename}`);
406
- }
407
- lines.push("```");
408
- if (kl.shared.remote && kl.shared.remote.length > 0) {
409
- lines.push("");
410
- lines.push("**Remote Documentation:**");
411
- for (const remote of kl.shared.remote) {
412
- lines.push(`- ${remote}`);
413
- }
414
- }
415
- lines.push("");
416
- }
417
- if (kl.personal) {
418
- lines.push(`### Personal Context (${agent.role})`);
419
- lines.push("```");
420
- lines.push(`/KnowledgeLibrary/${agent.role}/`);
421
- if (kl.personal.context) {
422
- lines.push("\u251C\u2500\u2500 context/");
423
- lines.push("\u2502 \u2514\u2500\u2500 current.txt # Your current state, priorities, decisions, issues");
424
- }
425
- if (kl.personal.history) {
426
- lines.push("\u251C\u2500\u2500 history/");
427
- lines.push("\u2502 \u2514\u2500\u2500 [archived context files, timestamped]");
428
- }
429
- if (kl.personal.inbox) {
430
- lines.push("\u251C\u2500\u2500 inbox/");
431
- lines.push("\u2502 \u2514\u2500\u2500 YYYYMMDD_HHMM-[agent-name]-[topic].txt # Messages from other agents");
432
- }
433
- if (kl.personal.outbox) {
434
- lines.push("\u251C\u2500\u2500 outbox/");
435
- lines.push("\u2502 \u2514\u2500\u2500 YYYYMMDD_HHMM-to-[agent-name]-[topic].txt # Copies of sent messages");
436
- }
437
- if (kl.personal.tech) {
438
- lines.push("\u251C\u2500\u2500 tech/");
439
- lines.push("\u2502 \u2514\u2500\u2500 [Technical docs, implementation details, working drafts]");
440
- }
441
- if (kl.personal.control) {
442
- lines.push("\u2514\u2500\u2500 control/");
443
- if (kl.personal.control.objectives) {
444
- lines.push(" \u251C\u2500\u2500 objectives.txt # Current job objectives and goals");
445
- }
446
- if (kl.personal.control.decisions) {
447
- lines.push(" \u251C\u2500\u2500 decisions.txt # Log of key decisions with rationale");
448
- }
449
- if (kl.personal.control.dependencies) {
450
- lines.push(" \u251C\u2500\u2500 dependencies.txt # Dependencies on other jobs");
451
- }
452
- if (kl.personal.control.index) {
453
- lines.push(" \u2514\u2500\u2500 index.txt # Optional index of files/folders");
455
+ const mcpTool = `mcp__${server}`;
456
+ if (!tools.includes(mcpTool)) {
457
+ tools.push(mcpTool);
454
458
  }
455
459
  }
456
- lines.push("```");
457
- lines.push("");
458
- }
459
- lines.push("---");
460
- lines.push("");
461
- }
462
- function generateCommunicationSection(agent, lines) {
463
- const comm = agent.communication;
464
- if (!comm) return;
465
- lines.push("## Communication");
466
- lines.push("");
467
- if (comm.inbox) {
468
- lines.push(`**Inbox:** \`${comm.inbox}\``);
469
460
  }
470
- if (comm.outbox) {
471
- lines.push(`**Outbox:** \`${comm.outbox}\``);
472
- }
473
- lines.push("");
474
- if (comm.message_format || comm.outbox_format || comm.processed_dir) {
475
- lines.push("### Message Conventions");
476
- lines.push("");
477
- if (comm.message_format) {
478
- lines.push(`- **Inbox message naming:** \`${comm.message_format}\``);
479
- }
480
- if (comm.outbox_format) {
481
- lines.push(`- **Outbox message naming:** \`${comm.outbox_format}\``);
482
- }
483
- if (comm.processed_dir) {
484
- lines.push(`- **Processed messages:** Move handled inbox messages to \`${comm.processed_dir}\``);
485
- }
486
- lines.push("");
487
- }
488
- }
489
- function generateStartupProtocolSection(agent, lines) {
490
- const protocols = agent.protocols;
491
- if (!protocols?.startup) return;
492
- lines.push("## When Invoked");
493
- lines.push("");
494
- lines.push("> **MANDATORY STARTUP PROTOCOL** - Execute before proceeding with any task.");
495
- lines.push("");
496
- lines.push("### Session Context Check");
497
- lines.push("");
498
- lines.push("First, determine if you have already loaded context in this session:");
499
- lines.push("");
500
- if (protocols.startup.first_session && protocols.startup.first_session.length > 0) {
501
- lines.push("**If this is your FIRST invocation in this session** (no prior context loaded):");
502
- lines.push("");
503
- for (const step of protocols.startup.first_session) {
504
- lines.push(`- [ ] ${step}`);
505
- }
506
- lines.push("");
507
- lines.push('Acknowledge: "Startup protocol complete. Full context loaded."');
508
- lines.push("");
509
- }
510
- if (protocols.startup.subsequent && protocols.startup.subsequent.length > 0) {
511
- lines.push("**If you have ALREADY loaded context in this session** (subsequent invocation):");
512
- lines.push("");
513
- for (const step of protocols.startup.subsequent) {
514
- lines.push(`- [ ] ${step}`);
515
- }
516
- lines.push("");
517
- lines.push('Acknowledge: "Context already loaded. Checked inbox for new messages."');
518
- lines.push("");
519
- }
520
- lines.push("Then proceed with the task.");
521
- lines.push("");
522
- lines.push("---");
523
- lines.push("");
461
+ return tools.join(", ");
524
462
  }
525
- function generateCompletionProtocolSection(agent, lines) {
526
- const protocols = agent.protocols;
527
- if (!protocols?.completion || protocols.completion.length === 0) return;
528
- lines.push("## Before Finishing");
529
- lines.push("");
530
- lines.push("> **MANDATORY COMPLETION PROTOCOL** - Execute ALL steps before ending any task.");
531
- lines.push("");
532
- for (let i = 0; i < protocols.completion.length; i++) {
533
- lines.push(`### ${i + 1}. ${protocols.completion[i]}`);
534
- lines.push("");
463
+ function processAgentTemplate(templatePath, agent, config, mcpServers) {
464
+ const template = readFileSync3(templatePath, "utf-8");
465
+ const context = { agent };
466
+ if (config) {
467
+ context.config = config;
535
468
  }
536
- lines.push('Acknowledge: "Completion protocol finished. Context updated."');
537
- lines.push("");
538
- lines.push("---");
539
- lines.push("");
540
- }
541
- function generateLegacyContextSourcesSection(agent, lines) {
542
- if (!agent.context_sources) return;
543
- if (agent.knowledge_library) return;
544
- lines.push("## Context Sources");
545
- lines.push("");
546
- if (agent.context_sources.shared && agent.context_sources.shared.length > 0) {
547
- lines.push("### Shared");
548
- lines.push("");
549
- for (const source of agent.context_sources.shared) {
550
- lines.push(`- ${source}`);
551
- }
552
- lines.push("");
469
+ const resolved = resolveString(template, context);
470
+ const frontmatterMatch = resolved.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
471
+ if (!frontmatterMatch) {
472
+ throw new Error(`Invalid markdown format in ${templatePath}: no frontmatter found`);
553
473
  }
554
- if (agent.context_sources.personal && agent.context_sources.personal.length > 0) {
555
- lines.push("### Personal");
556
- lines.push("");
557
- for (const source of agent.context_sources.personal) {
558
- lines.push(`- ${source}`);
559
- }
560
- lines.push("");
474
+ const frontmatterYaml = frontmatterMatch[1];
475
+ const body = frontmatterMatch[2] ?? "";
476
+ const frontmatter = parseYaml3(frontmatterYaml);
477
+ const tools = buildAgentTools(agent, mcpServers);
478
+ frontmatter.tools = tools;
479
+ if (typeof frontmatter.description === "string") {
480
+ frontmatter.description = frontmatter.description.replace(/\n/g, " ").trim();
561
481
  }
482
+ const updatedFrontmatter = stringifyYaml(frontmatter, { lineWidth: 0 }).trim();
483
+ return `---
484
+ ${updatedFrontmatter}
485
+ ---
486
+ ${body}`;
562
487
  }
563
488
  function generateAgentMarkdown(agent, mcpServers) {
564
489
  const lines = [];
@@ -581,8 +506,8 @@ function generateAgentMarkdown(agent, mcpServers) {
581
506
  if (agent.responsibilities && agent.responsibilities.length > 0) {
582
507
  lines.push("## Responsibilities");
583
508
  lines.push("");
584
- for (const responsibility of agent.responsibilities) {
585
- lines.push(`- ${responsibility}`);
509
+ for (const r of agent.responsibilities) {
510
+ lines.push(`- ${r}`);
586
511
  }
587
512
  lines.push("");
588
513
  }
@@ -600,12 +525,12 @@ function generateAgentMarkdown(agent, mcpServers) {
600
525
  if (agent.expertise.tech_stack) {
601
526
  lines.push("### Tech Stack");
602
527
  lines.push("");
603
- const techStack = agent.expertise.tech_stack;
604
- if (typeof techStack === "string") {
605
- lines.push(techStack);
606
- } else if (typeof techStack === "object") {
528
+ const ts = agent.expertise.tech_stack;
529
+ if (typeof ts === "string") {
530
+ lines.push(ts);
531
+ } else if (typeof ts === "object") {
607
532
  lines.push("```json");
608
- lines.push(JSON.stringify(techStack, null, 2));
533
+ lines.push(JSON.stringify(ts, null, 2));
609
534
  lines.push("```");
610
535
  }
611
536
  lines.push("");
@@ -624,7 +549,7 @@ function generateAgentMarkdown(agent, mcpServers) {
624
549
  lines.push("");
625
550
  for (const [category, items] of Object.entries(agent.principles)) {
626
551
  if (items && Array.isArray(items) && items.length > 0) {
627
- const title = formatTitle(category);
552
+ const title = category.replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
628
553
  lines.push(`### ${title}`);
629
554
  lines.push("");
630
555
  for (const item of items) {
@@ -655,21 +580,161 @@ function generateAgentMarkdown(agent, mcpServers) {
655
580
  lines.push("");
656
581
  }
657
582
  }
658
- generateKnowledgeLibrarySection(agent, lines);
659
- generateCommunicationSection(agent, lines);
660
- generateStartupProtocolSection(agent, lines);
661
- generateCompletionProtocolSection(agent, lines);
662
- generateLegacyContextSourcesSection(agent, lines);
583
+ if (agent.knowledge_library) {
584
+ generateKnowledgeLibrarySection(agent, lines);
585
+ }
586
+ if (agent.communication) {
587
+ generateCommunicationSection(agent, lines);
588
+ }
589
+ if (agent.protocols?.startup) {
590
+ generateStartupProtocolSection(agent, lines);
591
+ }
592
+ if (agent.protocols?.completion) {
593
+ generateCompletionProtocolSection(agent, lines);
594
+ }
595
+ if (agent.context_sources && !agent.knowledge_library) {
596
+ lines.push("## Context Sources");
597
+ lines.push("");
598
+ if (agent.context_sources.shared?.length) {
599
+ lines.push("### Shared");
600
+ lines.push("");
601
+ for (const s of agent.context_sources.shared) lines.push(`- ${s}`);
602
+ lines.push("");
603
+ }
604
+ if (agent.context_sources.personal?.length) {
605
+ lines.push("### Personal");
606
+ lines.push("");
607
+ for (const p of agent.context_sources.personal) lines.push(`- ${p}`);
608
+ lines.push("");
609
+ }
610
+ }
663
611
  lines.push("---");
664
612
  lines.push("");
665
613
  lines.push("*Generated by CoreAI*");
666
614
  lines.push("");
667
615
  return lines.join("\n");
668
616
  }
669
- function formatTitle(str) {
670
- return str.replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
617
+ function generateKnowledgeLibrarySection(agent, lines) {
618
+ const kl = agent.knowledge_library;
619
+ if (!kl) return;
620
+ lines.push("## Knowledge Library Structure");
621
+ lines.push("");
622
+ if (kl.shared) {
623
+ lines.push("### Shared Context (Root - All Agents)");
624
+ lines.push("```");
625
+ lines.push("/KnowledgeLibrary/");
626
+ if (kl.shared.context) lines.push(`\u251C\u2500\u2500 ${kl.shared.context.split("/").pop()}`);
627
+ if (kl.shared.architecture) lines.push(`\u251C\u2500\u2500 ${kl.shared.architecture.split("/").pop()}`);
628
+ if (kl.shared.prd) lines.push(`\u2514\u2500\u2500 ${kl.shared.prd.split("/").pop()}`);
629
+ lines.push("```");
630
+ if (kl.shared.remote?.length) {
631
+ lines.push("");
632
+ lines.push("**Remote Documentation:**");
633
+ for (const r of kl.shared.remote) lines.push(`- ${r}`);
634
+ }
635
+ lines.push("");
636
+ }
637
+ if (kl.personal) {
638
+ lines.push(`### Personal Context (${agent.role})`);
639
+ lines.push("```");
640
+ lines.push(`/KnowledgeLibrary/${agent.role}/`);
641
+ if (kl.personal.context) {
642
+ lines.push("\u251C\u2500\u2500 context/");
643
+ lines.push("\u2502 \u2514\u2500\u2500 current.txt");
644
+ }
645
+ if (kl.personal.history) {
646
+ lines.push("\u251C\u2500\u2500 history/");
647
+ }
648
+ if (kl.personal.inbox) {
649
+ lines.push("\u251C\u2500\u2500 inbox/");
650
+ }
651
+ if (kl.personal.outbox) {
652
+ lines.push("\u251C\u2500\u2500 outbox/");
653
+ }
654
+ if (kl.personal.tech) {
655
+ lines.push("\u251C\u2500\u2500 tech/");
656
+ }
657
+ if (kl.personal.control) {
658
+ lines.push("\u2514\u2500\u2500 control/");
659
+ if (kl.personal.control.objectives) lines.push(" \u251C\u2500\u2500 objectives.txt");
660
+ if (kl.personal.control.decisions) lines.push(" \u251C\u2500\u2500 decisions.txt");
661
+ if (kl.personal.control.dependencies) lines.push(" \u251C\u2500\u2500 dependencies.txt");
662
+ if (kl.personal.control.index) lines.push(" \u2514\u2500\u2500 index.txt");
663
+ }
664
+ lines.push("```");
665
+ lines.push("");
666
+ }
667
+ lines.push("---");
668
+ lines.push("");
669
+ }
670
+ function generateCommunicationSection(agent, lines) {
671
+ const comm = agent.communication;
672
+ if (!comm) return;
673
+ lines.push("## Communication");
674
+ lines.push("");
675
+ if (comm.inbox) lines.push(`**Inbox:** \`${comm.inbox}\``);
676
+ if (comm.outbox) lines.push(`**Outbox:** \`${comm.outbox}\``);
677
+ lines.push("");
678
+ if (comm.message_format || comm.outbox_format || comm.processed_dir) {
679
+ lines.push("### Message Conventions");
680
+ lines.push("");
681
+ if (comm.message_format) lines.push(`- **Inbox message naming:** \`${comm.message_format}\``);
682
+ if (comm.outbox_format) lines.push(`- **Outbox message naming:** \`${comm.outbox_format}\``);
683
+ if (comm.processed_dir) lines.push(`- **Processed messages:** Move handled inbox messages to \`${comm.processed_dir}\``);
684
+ lines.push("");
685
+ }
686
+ }
687
+ function generateStartupProtocolSection(agent, lines) {
688
+ const p = agent.protocols;
689
+ if (!p?.startup) return;
690
+ lines.push("## When Invoked");
691
+ lines.push("");
692
+ lines.push("> **MANDATORY STARTUP PROTOCOL** - Execute before proceeding with any task.");
693
+ lines.push("");
694
+ lines.push("### Session Context Check");
695
+ lines.push("");
696
+ if (p.startup.first_session?.length) {
697
+ lines.push("**If this is your FIRST invocation in this session:**");
698
+ lines.push("");
699
+ for (const s of p.startup.first_session) lines.push(`- [ ] ${s}`);
700
+ lines.push("");
701
+ lines.push('Acknowledge: "Startup protocol complete. Full context loaded."');
702
+ lines.push("");
703
+ }
704
+ if (p.startup.subsequent?.length) {
705
+ lines.push("**If you have ALREADY loaded context in this session:**");
706
+ lines.push("");
707
+ for (const s of p.startup.subsequent) lines.push(`- [ ] ${s}`);
708
+ lines.push("");
709
+ lines.push('Acknowledge: "Context already loaded. Checked inbox for new messages."');
710
+ lines.push("");
711
+ }
712
+ lines.push("Then proceed with the task.");
713
+ lines.push("");
714
+ lines.push("---");
715
+ lines.push("");
671
716
  }
672
- function compileAgent(agent, config, mcpServers) {
717
+ function generateCompletionProtocolSection(agent, lines) {
718
+ const p = agent.protocols;
719
+ if (!p?.completion?.length) return;
720
+ lines.push("## Before Finishing");
721
+ lines.push("");
722
+ lines.push("> **MANDATORY COMPLETION PROTOCOL** - Execute ALL steps before ending any task.");
723
+ lines.push("");
724
+ for (let i = 0; i < p.completion.length; i++) {
725
+ lines.push(`### ${i + 1}. ${p.completion[i]}`);
726
+ lines.push("");
727
+ }
728
+ lines.push('Acknowledge: "Completion protocol finished. Context updated."');
729
+ lines.push("");
730
+ lines.push("---");
731
+ lines.push("");
732
+ }
733
+ function compileAgent(agent, filePath, config, mcpServers) {
734
+ const ext = extname2(filePath).toLowerCase();
735
+ if (ext === ".md") {
736
+ return processAgentTemplate(filePath, agent, config, mcpServers);
737
+ }
673
738
  const resolved = resolveAgentDefinition(agent, config);
674
739
  return generateAgentMarkdown(resolved, mcpServers);
675
740
  }
@@ -729,7 +794,12 @@ function compileAgents(config, options = {}) {
729
794
  continue;
730
795
  }
731
796
  try {
732
- const markdown = compileAgent(metadata.definition, config, options.mcpServers);
797
+ const markdown = compileAgent(
798
+ metadata.definition,
799
+ metadata.filePath,
800
+ config,
801
+ options.mcpServers
802
+ );
733
803
  const outputPath = join3(outputDir, `${role}.md`);
734
804
  writeFileSync(outputPath, markdown, "utf-8");
735
805
  result.compiled.push({
@@ -2596,7 +2666,7 @@ var StepTracker = class {
2596
2666
  };
2597
2667
 
2598
2668
  // src/skills/generator.ts
2599
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync } from "fs";
2669
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync } from "fs";
2600
2670
  import { join as join6, basename as basename3 } from "path";
2601
2671
 
2602
2672
  // src/skills/templates.ts
@@ -3181,7 +3251,7 @@ function loadCustomTemplates(templatesDir) {
3181
3251
  const stat = statSync(filePath);
3182
3252
  if (!stat.isFile()) continue;
3183
3253
  try {
3184
- const content = readFileSync3(filePath, "utf-8");
3254
+ const content = readFileSync4(filePath, "utf-8");
3185
3255
  const template = parseSkillTemplate(file, content);
3186
3256
  templates.push(template);
3187
3257
  } catch {
@@ -3394,7 +3464,7 @@ import {
3394
3464
  existsSync as existsSync5,
3395
3465
  mkdirSync as mkdirSync3,
3396
3466
  writeFileSync as writeFileSync3,
3397
- readFileSync as readFileSync4,
3467
+ readFileSync as readFileSync5,
3398
3468
  readdirSync as readdirSync3,
3399
3469
  renameSync,
3400
3470
  statSync as statSync2
@@ -3649,7 +3719,7 @@ function getAgentKnowledgeState(agentName, options = {}) {
3649
3719
  let context;
3650
3720
  const currentContextPath = join7(dirs.context, "current.txt");
3651
3721
  if (existsSync5(currentContextPath)) {
3652
- const content = readFileSync4(currentContextPath, "utf-8");
3722
+ const content = readFileSync5(currentContextPath, "utf-8");
3653
3723
  context = parseContextFile(content);
3654
3724
  }
3655
3725
  const state = {
@@ -3749,7 +3819,7 @@ function readInboxMessages(agentName, options = {}) {
3749
3819
  );
3750
3820
  for (const file of files) {
3751
3821
  const filePath = join7(dirs.inbox, file);
3752
- const rawContent = readFileSync4(filePath, "utf-8");
3822
+ const rawContent = readFileSync5(filePath, "utf-8");
3753
3823
  const { metadata, body } = parseMessageFrontmatter(rawContent);
3754
3824
  if (options.type && metadata.type !== options.type) continue;
3755
3825
  if (options.from && metadata.from !== options.from) continue;
@@ -3769,7 +3839,7 @@ function readInboxMessages(agentName, options = {}) {
3769
3839
  );
3770
3840
  for (const file of files) {
3771
3841
  const filePath = join7(dirs.inboxProcessed, file);
3772
- const rawContent = readFileSync4(filePath, "utf-8");
3842
+ const rawContent = readFileSync5(filePath, "utf-8");
3773
3843
  const { metadata, body } = parseMessageFrontmatter(rawContent);
3774
3844
  if (options.type && metadata.type !== options.type) continue;
3775
3845
  if (options.from && metadata.from !== options.from) continue;
@@ -3974,7 +4044,7 @@ function findPackageJson() {
3974
4044
  while (dir !== dirname5(dir)) {
3975
4045
  const pkgPath = join8(dir, "package.json");
3976
4046
  try {
3977
- const content = readFileSync5(pkgPath, "utf-8");
4047
+ const content = readFileSync6(pkgPath, "utf-8");
3978
4048
  const pkg = JSON.parse(content);
3979
4049
  if (pkg.name === "@deimoscloud/coreai") {
3980
4050
  return content;