@ouro.bot/cli 0.0.1-alpha.0 → 0.1.0-alpha.10

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 (129) hide show
  1. package/AdoptionSpecialist.ouro/agent.json +20 -0
  2. package/AdoptionSpecialist.ouro/psyche/SOUL.md +24 -0
  3. package/AdoptionSpecialist.ouro/psyche/identities/basilisk.md +31 -0
  4. package/AdoptionSpecialist.ouro/psyche/identities/jafar.md +31 -0
  5. package/AdoptionSpecialist.ouro/psyche/identities/jormungandr.md +31 -0
  6. package/AdoptionSpecialist.ouro/psyche/identities/kaa.md +31 -0
  7. package/AdoptionSpecialist.ouro/psyche/identities/medusa.md +31 -0
  8. package/AdoptionSpecialist.ouro/psyche/identities/monty.md +31 -0
  9. package/AdoptionSpecialist.ouro/psyche/identities/nagini.md +31 -0
  10. package/AdoptionSpecialist.ouro/psyche/identities/ouroboros.md +31 -0
  11. package/AdoptionSpecialist.ouro/psyche/identities/python.md +31 -0
  12. package/AdoptionSpecialist.ouro/psyche/identities/quetzalcoatl.md +31 -0
  13. package/AdoptionSpecialist.ouro/psyche/identities/sir-hiss.md +31 -0
  14. package/AdoptionSpecialist.ouro/psyche/identities/the-serpent.md +31 -0
  15. package/AdoptionSpecialist.ouro/psyche/identities/the-snake.md +31 -0
  16. package/README.md +224 -6
  17. package/dist/heart/agent-entry.js +17 -0
  18. package/dist/heart/api-error.js +34 -0
  19. package/dist/heart/config.js +330 -0
  20. package/dist/heart/core.js +524 -0
  21. package/dist/heart/daemon/daemon-cli.js +884 -0
  22. package/dist/heart/daemon/daemon-entry.js +74 -0
  23. package/dist/heart/daemon/daemon.js +313 -0
  24. package/dist/heart/daemon/hatch-animation.js +28 -0
  25. package/dist/heart/daemon/hatch-flow.js +286 -0
  26. package/dist/heart/daemon/hatch-specialist.js +112 -0
  27. package/dist/heart/daemon/health-monitor.js +79 -0
  28. package/dist/heart/daemon/log-tailer.js +146 -0
  29. package/dist/heart/daemon/message-router.js +98 -0
  30. package/dist/heart/daemon/os-cron.js +260 -0
  31. package/dist/heart/daemon/ouro-bot-entry.js +23 -0
  32. package/dist/heart/daemon/ouro-bot-wrapper.js +91 -0
  33. package/dist/heart/daemon/ouro-entry.js +23 -0
  34. package/dist/heart/daemon/ouro-uti.js +212 -0
  35. package/dist/heart/daemon/process-manager.js +237 -0
  36. package/dist/heart/daemon/runtime-logging.js +102 -0
  37. package/dist/heart/daemon/specialist-orchestrator.js +161 -0
  38. package/dist/heart/daemon/specialist-prompt.js +56 -0
  39. package/dist/heart/daemon/specialist-session.js +150 -0
  40. package/dist/heart/daemon/specialist-tools.js +132 -0
  41. package/dist/heart/daemon/subagent-installer.js +125 -0
  42. package/dist/heart/daemon/task-scheduler.js +240 -0
  43. package/dist/heart/harness.js +26 -0
  44. package/dist/heart/identity.js +295 -0
  45. package/dist/heart/kicks.js +144 -0
  46. package/dist/heart/primitives.js +4 -0
  47. package/dist/heart/providers/anthropic.js +332 -0
  48. package/dist/heart/providers/azure.js +66 -0
  49. package/dist/heart/providers/minimax.js +53 -0
  50. package/dist/heart/providers/openai-codex.js +162 -0
  51. package/dist/heart/streaming.js +415 -0
  52. package/dist/heart/turn-coordinator.js +62 -0
  53. package/dist/inner-worker-entry.js +4 -0
  54. package/dist/mind/associative-recall.js +197 -0
  55. package/dist/mind/bundle-manifest.js +118 -0
  56. package/dist/mind/context.js +302 -0
  57. package/dist/mind/first-impressions.js +43 -0
  58. package/dist/mind/format.js +56 -0
  59. package/dist/mind/friends/channel.js +49 -0
  60. package/dist/mind/friends/resolver.js +84 -0
  61. package/dist/mind/friends/store-file.js +171 -0
  62. package/dist/mind/friends/store.js +4 -0
  63. package/dist/mind/friends/tokens.js +26 -0
  64. package/dist/mind/friends/types.js +21 -0
  65. package/dist/mind/memory.js +388 -0
  66. package/dist/mind/pending.js +93 -0
  67. package/dist/mind/phrases.js +43 -0
  68. package/dist/mind/prompt-refresh.js +20 -0
  69. package/dist/mind/prompt.js +355 -0
  70. package/dist/mind/token-estimate.js +119 -0
  71. package/dist/nerves/cli-logging.js +31 -0
  72. package/dist/nerves/coverage/audit-rules.js +81 -0
  73. package/dist/nerves/coverage/audit.js +200 -0
  74. package/dist/nerves/coverage/cli-main.js +5 -0
  75. package/dist/nerves/coverage/cli.js +51 -0
  76. package/dist/nerves/coverage/contract.js +23 -0
  77. package/dist/nerves/coverage/file-completeness.js +56 -0
  78. package/dist/nerves/coverage/run-artifacts.js +77 -0
  79. package/dist/nerves/coverage/source-scanner.js +34 -0
  80. package/dist/nerves/index.js +152 -0
  81. package/dist/nerves/runtime.js +38 -0
  82. package/dist/repertoire/ado-client.js +211 -0
  83. package/dist/repertoire/ado-context.js +73 -0
  84. package/dist/repertoire/ado-semantic.js +841 -0
  85. package/dist/repertoire/ado-templates.js +146 -0
  86. package/dist/repertoire/coding/index.js +36 -0
  87. package/dist/repertoire/coding/manager.js +489 -0
  88. package/dist/repertoire/coding/monitor.js +60 -0
  89. package/dist/repertoire/coding/reporter.js +45 -0
  90. package/dist/repertoire/coding/spawner.js +102 -0
  91. package/dist/repertoire/coding/tools.js +167 -0
  92. package/dist/repertoire/coding/types.js +2 -0
  93. package/dist/repertoire/data/ado-endpoints.json +122 -0
  94. package/dist/repertoire/data/graph-endpoints.json +212 -0
  95. package/dist/repertoire/github-client.js +64 -0
  96. package/dist/repertoire/graph-client.js +118 -0
  97. package/dist/repertoire/skills.js +156 -0
  98. package/dist/repertoire/tasks/board.js +122 -0
  99. package/dist/repertoire/tasks/index.js +210 -0
  100. package/dist/repertoire/tasks/lifecycle.js +80 -0
  101. package/dist/repertoire/tasks/middleware.js +65 -0
  102. package/dist/repertoire/tasks/parser.js +173 -0
  103. package/dist/repertoire/tasks/scanner.js +132 -0
  104. package/dist/repertoire/tasks/transitions.js +145 -0
  105. package/dist/repertoire/tasks/types.js +2 -0
  106. package/dist/repertoire/tools-base.js +714 -0
  107. package/dist/repertoire/tools-github.js +53 -0
  108. package/dist/repertoire/tools-teams.js +308 -0
  109. package/dist/repertoire/tools.js +199 -0
  110. package/dist/senses/bluebubbles-client.js +279 -0
  111. package/dist/senses/bluebubbles-entry.js +11 -0
  112. package/dist/senses/bluebubbles-model.js +253 -0
  113. package/dist/senses/bluebubbles-mutation-log.js +76 -0
  114. package/dist/senses/bluebubbles.js +332 -0
  115. package/dist/senses/cli-entry.js +15 -0
  116. package/dist/senses/cli.js +604 -0
  117. package/dist/senses/commands.js +98 -0
  118. package/dist/senses/inner-dialog-worker.js +61 -0
  119. package/dist/senses/inner-dialog.js +231 -0
  120. package/dist/senses/session-lock.js +119 -0
  121. package/dist/senses/teams-entry.js +15 -0
  122. package/dist/senses/teams.js +696 -0
  123. package/dist/senses/trust-gate.js +150 -0
  124. package/package.json +35 -11
  125. package/subagents/README.md +73 -0
  126. package/subagents/work-doer.md +233 -0
  127. package/subagents/work-merger.md +624 -0
  128. package/subagents/work-planner.md +373 -0
  129. package/bin/ouro.js +0 -6
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runAdoptionSpecialist = runAdoptionSpecialist;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const runtime_1 = require("../../nerves/runtime");
40
+ const identity_1 = require("../identity");
41
+ const config_1 = require("../config");
42
+ const core_1 = require("../core");
43
+ const hatch_flow_1 = require("./hatch-flow");
44
+ const specialist_prompt_1 = require("./specialist-prompt");
45
+ const specialist_tools_1 = require("./specialist-tools");
46
+ const specialist_session_1 = require("./specialist-session");
47
+ function listExistingBundles(bundlesRoot) {
48
+ let entries;
49
+ try {
50
+ entries = fs.readdirSync(bundlesRoot, { withFileTypes: true });
51
+ }
52
+ catch {
53
+ return [];
54
+ }
55
+ const discovered = [];
56
+ for (const entry of entries) {
57
+ if (!entry.isDirectory() || !entry.name.endsWith(".ouro"))
58
+ continue;
59
+ const agentName = entry.name.slice(0, -5);
60
+ discovered.push(agentName);
61
+ }
62
+ return discovered.sort((a, b) => a.localeCompare(b));
63
+ }
64
+ function pickRandomIdentity(identitiesDir, random) {
65
+ const files = fs.readdirSync(identitiesDir).filter((f) => f.endsWith(".md"));
66
+ if (files.length === 0) {
67
+ return { fileName: "default", content: "I am the adoption specialist." };
68
+ }
69
+ const idx = Math.floor(random() * files.length);
70
+ const fileName = files[idx];
71
+ const content = fs.readFileSync(path.join(identitiesDir, fileName), "utf-8");
72
+ return { fileName, content };
73
+ }
74
+ /**
75
+ * Run the full adoption specialist flow:
76
+ * 1. Pick a random identity from the bundled AdoptionSpecialist.ouro
77
+ * 2. Read SOUL.md
78
+ * 3. List existing bundles
79
+ * 4. Build system prompt
80
+ * 5. Set up provider (setAgentName, setAgentConfigOverride, writeSecretsFile, reset caches)
81
+ * 6. Run the specialist session
82
+ * 7. Clean up identity/config overrides
83
+ * 8. Return hatchling name
84
+ */
85
+ async function runAdoptionSpecialist(deps) {
86
+ const { bundleSourceDir, bundlesRoot, secretsRoot, provider, credentials, humanName, callbacks, signal } = deps;
87
+ const random = deps.random ?? Math.random;
88
+ (0, runtime_1.emitNervesEvent)({
89
+ component: "daemon",
90
+ event: "daemon.specialist_orchestrator_start",
91
+ message: "starting adoption specialist orchestrator",
92
+ meta: { provider, bundleSourceDir },
93
+ });
94
+ // 1. Read SOUL.md
95
+ const soulPath = path.join(bundleSourceDir, "psyche", "SOUL.md");
96
+ let soulText = "";
97
+ try {
98
+ soulText = fs.readFileSync(soulPath, "utf-8");
99
+ }
100
+ catch {
101
+ // No SOUL.md -- proceed without it
102
+ }
103
+ // 2. Pick random identity
104
+ const identitiesDir = path.join(bundleSourceDir, "psyche", "identities");
105
+ const identity = pickRandomIdentity(identitiesDir, random);
106
+ (0, runtime_1.emitNervesEvent)({
107
+ component: "daemon",
108
+ event: "daemon.specialist_identity_picked",
109
+ message: "picked specialist identity",
110
+ meta: { identity: identity.fileName },
111
+ });
112
+ // 3. List existing bundles
113
+ const existingBundles = listExistingBundles(bundlesRoot);
114
+ // 4. Build system prompt
115
+ const systemPrompt = (0, specialist_prompt_1.buildSpecialistSystemPrompt)(soulText, identity.content, existingBundles);
116
+ // 5. Set up provider
117
+ (0, identity_1.setAgentName)("AdoptionSpecialist");
118
+ (0, identity_1.setAgentConfigOverride)({
119
+ version: 1,
120
+ enabled: true,
121
+ provider,
122
+ phrases: { thinking: ["thinking"], tool: ["checking"], followup: ["processing"] },
123
+ });
124
+ (0, hatch_flow_1.writeSecretsFile)("AdoptionSpecialist", provider, credentials, secretsRoot);
125
+ (0, config_1.resetConfigCache)();
126
+ (0, core_1.resetProviderRuntime)();
127
+ try {
128
+ // Create provider runtime
129
+ const providerRuntime = (0, core_1.createProviderRegistry)().resolve();
130
+ if (!providerRuntime) {
131
+ throw new Error("Failed to create provider runtime for adoption specialist");
132
+ }
133
+ // 6. Run session
134
+ const tools = (0, specialist_tools_1.getSpecialistTools)();
135
+ const readline = deps.createReadline();
136
+ const result = await (0, specialist_session_1.runSpecialistSession)({
137
+ providerRuntime,
138
+ systemPrompt,
139
+ tools,
140
+ execTool: (name, args) => (0, specialist_tools_1.execSpecialistTool)(name, args, {
141
+ humanName,
142
+ provider,
143
+ credentials,
144
+ bundlesRoot,
145
+ secretsRoot,
146
+ specialistIdentitiesDir: identitiesDir,
147
+ }),
148
+ readline,
149
+ callbacks,
150
+ signal,
151
+ kickoffMessage: "hi, i just ran ouro for the first time",
152
+ });
153
+ return result.hatchedAgentName;
154
+ }
155
+ finally {
156
+ // 7. Cleanup: restore identity/config state
157
+ (0, identity_1.setAgentConfigOverride)(null);
158
+ (0, config_1.resetConfigCache)();
159
+ (0, core_1.resetProviderRuntime)();
160
+ }
161
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildSpecialistSystemPrompt = buildSpecialistSystemPrompt;
4
+ const runtime_1 = require("../../nerves/runtime");
5
+ /**
6
+ * Build the adoption specialist's system prompt from its components.
7
+ * The prompt is written in first person (the specialist's own voice).
8
+ */
9
+ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles) {
10
+ (0, runtime_1.emitNervesEvent)({
11
+ component: "daemon",
12
+ event: "daemon.specialist_prompt_build",
13
+ message: "building specialist system prompt",
14
+ meta: { bundleCount: existingBundles.length },
15
+ });
16
+ const sections = [];
17
+ if (soulText) {
18
+ sections.push(soulText);
19
+ }
20
+ if (identityText) {
21
+ sections.push(identityText);
22
+ }
23
+ if (existingBundles.length > 0) {
24
+ sections.push(`## Existing agents\nThe human already has these agents: ${existingBundles.join(", ")}.`);
25
+ }
26
+ else {
27
+ sections.push("## Existing agents\nThe human has no agents yet. This will be their first hatchling.");
28
+ }
29
+ sections.push([
30
+ "## Who I am",
31
+ "I am one of thirteen adoption specialists. The system randomly selected me for this session.",
32
+ "Most humans only go through adoption once, so this is likely the only time they'll meet me.",
33
+ "I make this encounter count — warm, memorable, and uniquely mine.",
34
+ "",
35
+ "## Conversation flow",
36
+ "The human just connected. I speak first — I greet them warmly and introduce myself in my own voice.",
37
+ "I briefly mention that I'm one of several adoption specialists and they got me today.",
38
+ "I ask their name and what they'd like their agent to help with.",
39
+ "I'm proactive: I suggest ideas, ask focused questions, and guide them through the process.",
40
+ "I don't wait for the human to figure things out — I explain what an agent is, what it can do, and what we're building together.",
41
+ "If they seem unsure, I offer concrete examples and suggestions. I never leave them hanging.",
42
+ "I keep the conversation natural, warm, and concise. I don't overwhelm with too many questions at once.",
43
+ "When I have enough context, I suggest a name for the hatchling and confirm with the human.",
44
+ "Then I call `hatch_agent` with the agent name and the human's name.",
45
+ "",
46
+ "## Tools",
47
+ "I have these tools available:",
48
+ "- `hatch_agent`: Create a new agent bundle. I call this with `name` (the agent name, PascalCase) and `humanName` (what the human told me their name is).",
49
+ "- `final_answer`: End the conversation with a final message to the human. I call this when the adoption process is complete.",
50
+ "- `read_file`: Read a file from disk. Useful for reviewing existing agent bundles or migration sources.",
51
+ "- `list_directory`: List directory contents. Useful for exploring existing agent bundles.",
52
+ "",
53
+ "I must call `final_answer` when I am done to end the session cleanly.",
54
+ ].join("\n"));
55
+ return sections.join("\n\n");
56
+ }
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSpecialistSession = runSpecialistSession;
4
+ const runtime_1 = require("../../nerves/runtime");
5
+ /**
6
+ * Run the specialist conversation session loop.
7
+ *
8
+ * The loop:
9
+ * 1. Initialize messages with system prompt
10
+ * 2. Prompt user -> add to messages -> call streamTurn -> process result
11
+ * 3. If result has no tool calls: push assistant message, re-prompt
12
+ * 4. If result has final_answer sole call: extract answer, emit via callbacks, done
13
+ * 5. If result has other tool calls: execute each, push tool results, continue loop
14
+ * 6. On abort signal: clean exit
15
+ * 7. Return { hatchedAgentName } -- name from hatch_agent if called
16
+ */
17
+ async function runSpecialistSession(deps) {
18
+ const { providerRuntime, systemPrompt, tools, execTool, readline, callbacks, signal, kickoffMessage } = deps;
19
+ (0, runtime_1.emitNervesEvent)({
20
+ component: "daemon",
21
+ event: "daemon.specialist_session_start",
22
+ message: "starting specialist session loop",
23
+ meta: {},
24
+ });
25
+ const messages = [
26
+ { role: "system", content: systemPrompt },
27
+ ];
28
+ let hatchedAgentName = null;
29
+ let done = false;
30
+ let isFirstTurn = true;
31
+ try {
32
+ while (!done) {
33
+ if (signal?.aborted)
34
+ break;
35
+ // On the first turn with a kickoff message, inject it so the specialist speaks first
36
+ if (isFirstTurn && kickoffMessage) {
37
+ isFirstTurn = false;
38
+ messages.push({ role: "user", content: kickoffMessage });
39
+ }
40
+ else {
41
+ // Get user input
42
+ const userInput = await readline.question("> ");
43
+ if (!userInput.trim())
44
+ continue;
45
+ messages.push({ role: "user", content: userInput });
46
+ }
47
+ providerRuntime.resetTurnState(messages);
48
+ // Inner loop: process tool calls until we get a final_answer or plain text
49
+ let turnDone = false;
50
+ while (!turnDone) {
51
+ if (signal?.aborted) {
52
+ done = true;
53
+ break;
54
+ }
55
+ callbacks.onModelStart();
56
+ const result = await providerRuntime.streamTurn({
57
+ messages,
58
+ activeTools: tools,
59
+ callbacks,
60
+ signal,
61
+ });
62
+ // Build assistant message
63
+ const assistantMsg = {
64
+ role: "assistant",
65
+ };
66
+ if (result.content)
67
+ assistantMsg.content = result.content;
68
+ if (result.toolCalls.length) {
69
+ assistantMsg.tool_calls = result.toolCalls.map((tc) => ({
70
+ id: tc.id,
71
+ type: "function",
72
+ function: { name: tc.name, arguments: tc.arguments },
73
+ }));
74
+ }
75
+ if (!result.toolCalls.length) {
76
+ // Plain text response -- push and re-prompt
77
+ messages.push(assistantMsg);
78
+ turnDone = true;
79
+ continue;
80
+ }
81
+ // Check for final_answer
82
+ const isSoleFinalAnswer = result.toolCalls.length === 1 && result.toolCalls[0].name === "final_answer";
83
+ if (isSoleFinalAnswer) {
84
+ let answer;
85
+ try {
86
+ const parsed = JSON.parse(result.toolCalls[0].arguments);
87
+ if (typeof parsed === "string") {
88
+ answer = parsed;
89
+ }
90
+ else if (parsed.answer != null) {
91
+ answer = parsed.answer;
92
+ }
93
+ }
94
+ catch {
95
+ // malformed
96
+ }
97
+ if (answer != null) {
98
+ callbacks.onTextChunk(answer);
99
+ messages.push(assistantMsg);
100
+ done = true;
101
+ turnDone = true;
102
+ continue;
103
+ }
104
+ // Malformed final_answer -- ask model to retry
105
+ messages.push(assistantMsg);
106
+ messages.push({
107
+ role: "tool",
108
+ tool_call_id: result.toolCalls[0].id,
109
+ content: "your final_answer was incomplete or malformed. call final_answer again with your complete response.",
110
+ });
111
+ providerRuntime.appendToolOutput(result.toolCalls[0].id, "retry");
112
+ continue;
113
+ }
114
+ // Execute tool calls
115
+ messages.push(assistantMsg);
116
+ for (const tc of result.toolCalls) {
117
+ if (signal?.aborted)
118
+ break;
119
+ let args = {};
120
+ try {
121
+ args = JSON.parse(tc.arguments);
122
+ }
123
+ catch {
124
+ // ignore parse error
125
+ }
126
+ callbacks.onToolStart(tc.name, args);
127
+ let toolResult;
128
+ try {
129
+ toolResult = await execTool(tc.name, args);
130
+ }
131
+ catch (e) {
132
+ toolResult = `error: ${e}`;
133
+ }
134
+ callbacks.onToolEnd(tc.name, tc.name, true);
135
+ // Track hatchling name
136
+ if (tc.name === "hatch_agent" && args.name) {
137
+ hatchedAgentName = args.name;
138
+ }
139
+ messages.push({ role: "tool", tool_call_id: tc.id, content: toolResult });
140
+ providerRuntime.appendToolOutput(tc.id, toolResult);
141
+ }
142
+ // After processing tool calls, continue inner loop for tool result processing
143
+ }
144
+ }
145
+ }
146
+ finally {
147
+ readline.close();
148
+ }
149
+ return { hatchedAgentName };
150
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getSpecialistTools = getSpecialistTools;
37
+ exports.execSpecialistTool = execSpecialistTool;
38
+ const fs = __importStar(require("fs"));
39
+ const tools_base_1 = require("../../repertoire/tools-base");
40
+ const hatch_flow_1 = require("./hatch-flow");
41
+ const hatch_animation_1 = require("./hatch-animation");
42
+ const runtime_1 = require("../../nerves/runtime");
43
+ const hatchAgentTool = {
44
+ type: "function",
45
+ function: {
46
+ name: "hatch_agent",
47
+ description: "create a new agent bundle with the given name. call this when you have gathered enough information from the human to hatch their agent.",
48
+ parameters: {
49
+ type: "object",
50
+ properties: {
51
+ name: {
52
+ type: "string",
53
+ description: "the name for the new agent (PascalCase, e.g. 'Slugger')",
54
+ },
55
+ humanName: {
56
+ type: "string",
57
+ description: "the human's preferred name, as they told you during conversation",
58
+ },
59
+ },
60
+ required: ["name", "humanName"],
61
+ },
62
+ },
63
+ };
64
+ const readFileTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "read_file");
65
+ const listDirTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "list_directory");
66
+ /**
67
+ * Returns the specialist's tool schema array.
68
+ */
69
+ function getSpecialistTools() {
70
+ return [hatchAgentTool, tools_base_1.finalAnswerTool, readFileTool.tool, listDirTool.tool];
71
+ }
72
+ /**
73
+ * Execute a specialist tool call.
74
+ * Returns the tool result string.
75
+ */
76
+ async function execSpecialistTool(name, args, deps) {
77
+ (0, runtime_1.emitNervesEvent)({
78
+ component: "daemon",
79
+ event: "daemon.specialist_tool_exec",
80
+ message: "executing specialist tool",
81
+ meta: { tool: name },
82
+ });
83
+ if (name === "hatch_agent") {
84
+ const agentName = args.name;
85
+ if (!agentName) {
86
+ return "error: missing required 'name' parameter for hatch_agent";
87
+ }
88
+ const input = {
89
+ agentName,
90
+ humanName: args.humanName || deps.humanName,
91
+ provider: deps.provider,
92
+ credentials: deps.credentials,
93
+ };
94
+ // Pass identity dirs to prevent hatch flow from syncing to ~/AgentBundles/AdoptionSpecialist.ouro/
95
+ // or cwd/AdoptionSpecialist.ouro/. The specialist already picked its identity; the hatch flow
96
+ // just needs a valid source dir to pick from for the hatchling's LORE.md seed.
97
+ const identitiesDir = deps.specialistIdentitiesDir;
98
+ const result = await (0, hatch_flow_1.runHatchFlow)(input, {
99
+ bundlesRoot: deps.bundlesRoot,
100
+ secretsRoot: deps.secretsRoot,
101
+ ...(identitiesDir ? { specialistIdentitySourceDir: identitiesDir, specialistIdentityTargetDir: identitiesDir } : {}),
102
+ });
103
+ await (0, hatch_animation_1.playHatchAnimation)(agentName, deps.animationWriter);
104
+ return [
105
+ `hatched ${agentName} successfully.`,
106
+ `bundle path: ${result.bundleRoot}`,
107
+ `identity seed: ${result.selectedIdentity}`,
108
+ `specialist secrets: ${result.specialistSecretsPath}`,
109
+ `hatchling secrets: ${result.hatchlingSecretsPath}`,
110
+ ].join("\n");
111
+ }
112
+ if (name === "read_file") {
113
+ try {
114
+ return fs.readFileSync(args.path, "utf-8");
115
+ }
116
+ catch (e) {
117
+ return `error: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
118
+ }
119
+ }
120
+ if (name === "list_directory") {
121
+ try {
122
+ return fs
123
+ .readdirSync(args.path, { withFileTypes: true })
124
+ .map((e) => `${e.isDirectory() ? "d" : "-"} ${e.name}`)
125
+ .join("\n");
126
+ }
127
+ catch (e) {
128
+ return `error: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
129
+ }
130
+ }
131
+ return `error: unknown tool '${name}'`;
132
+ }
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.installSubagentsForAvailableCli = installSubagentsForAvailableCli;
37
+ const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
39
+ const path = __importStar(require("path"));
40
+ const child_process_1 = require("child_process");
41
+ const runtime_1 = require("../../nerves/runtime");
42
+ function detectCliBinary(binary) {
43
+ const result = (0, child_process_1.spawnSync)("which", [binary], { encoding: "utf-8" });
44
+ if (result.status !== 0)
45
+ return null;
46
+ const resolved = result.stdout.trim();
47
+ return resolved.length > 0 ? resolved : null;
48
+ }
49
+ function listSubagentSources(subagentsDir) {
50
+ if (!fs.existsSync(subagentsDir))
51
+ return [];
52
+ return fs.readdirSync(subagentsDir)
53
+ .filter((name) => name.endsWith(".md"))
54
+ .filter((name) => name !== "README.md")
55
+ .map((name) => path.join(subagentsDir, name))
56
+ .sort((a, b) => a.localeCompare(b));
57
+ }
58
+ function ensureSymlink(source, target) {
59
+ fs.mkdirSync(path.dirname(target), { recursive: true });
60
+ if (fs.existsSync(target)) {
61
+ const stats = fs.lstatSync(target);
62
+ if (stats.isSymbolicLink()) {
63
+ const linkedPath = fs.readlinkSync(target);
64
+ if (linkedPath === source)
65
+ return false;
66
+ }
67
+ fs.unlinkSync(target);
68
+ }
69
+ fs.symlinkSync(source, target);
70
+ return true;
71
+ }
72
+ async function installSubagentsForAvailableCli(options = {}) {
73
+ const repoRoot = options.repoRoot ?? path.resolve(__dirname, "..", "..", "..");
74
+ const homeDir = options.homeDir ?? os.homedir();
75
+ const which = options.which ?? detectCliBinary;
76
+ const subagentsDir = path.join(repoRoot, "subagents");
77
+ const sources = listSubagentSources(subagentsDir);
78
+ const notes = [];
79
+ (0, runtime_1.emitNervesEvent)({
80
+ component: "daemon",
81
+ event: "daemon.subagent_install_start",
82
+ message: "starting subagent auto-install",
83
+ meta: { sources: sources.length },
84
+ });
85
+ if (sources.length === 0) {
86
+ notes.push(`no subagent files found at ${subagentsDir}`);
87
+ return { claudeInstalled: 0, codexInstalled: 0, notes };
88
+ }
89
+ let claudeInstalled = 0;
90
+ let codexInstalled = 0;
91
+ const claudePath = which("claude");
92
+ if (!claudePath) {
93
+ notes.push("claude CLI not found; skipping subagent install");
94
+ }
95
+ else {
96
+ const claudeAgentsDir = path.join(homeDir, ".claude", "agents");
97
+ for (const source of sources) {
98
+ const target = path.join(claudeAgentsDir, path.basename(source));
99
+ if (ensureSymlink(source, target)) {
100
+ claudeInstalled += 1;
101
+ }
102
+ }
103
+ }
104
+ const codexPath = which("codex");
105
+ if (!codexPath) {
106
+ notes.push("codex CLI not found; skipping subagent install");
107
+ }
108
+ else {
109
+ const codexSkillsDir = path.join(homeDir, ".codex", "skills");
110
+ for (const source of sources) {
111
+ const skillName = path.basename(source, ".md");
112
+ const target = path.join(codexSkillsDir, skillName, "SKILL.md");
113
+ if (ensureSymlink(source, target)) {
114
+ codexInstalled += 1;
115
+ }
116
+ }
117
+ }
118
+ (0, runtime_1.emitNervesEvent)({
119
+ component: "daemon",
120
+ event: "daemon.subagent_install_end",
121
+ message: "completed subagent auto-install",
122
+ meta: { claudeInstalled, codexInstalled, notes: notes.length },
123
+ });
124
+ return { claudeInstalled, codexInstalled, notes };
125
+ }