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

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 (119) hide show
  1. package/AdoptionSpecialist.ouro/agent.json +20 -0
  2. package/AdoptionSpecialist.ouro/psyche/SOUL.md +22 -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 +296 -0
  20. package/dist/heart/core.js +515 -0
  21. package/dist/heart/daemon/daemon-cli.js +675 -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-flow.js +285 -0
  25. package/dist/heart/daemon/hatch-specialist.js +107 -0
  26. package/dist/heart/daemon/health-monitor.js +79 -0
  27. package/dist/heart/daemon/log-tailer.js +146 -0
  28. package/dist/heart/daemon/message-router.js +98 -0
  29. package/dist/heart/daemon/os-cron.js +260 -0
  30. package/dist/heart/daemon/ouro-bot-entry.js +23 -0
  31. package/dist/heart/daemon/ouro-bot-wrapper.js +90 -0
  32. package/dist/heart/daemon/ouro-entry.js +23 -0
  33. package/dist/heart/daemon/ouro-uti.js +212 -0
  34. package/dist/heart/daemon/process-manager.js +237 -0
  35. package/dist/heart/daemon/runtime-logging.js +98 -0
  36. package/dist/heart/daemon/subagent-installer.js +125 -0
  37. package/dist/heart/daemon/task-scheduler.js +240 -0
  38. package/dist/heart/harness.js +26 -0
  39. package/dist/heart/identity.js +281 -0
  40. package/dist/heart/kicks.js +144 -0
  41. package/dist/heart/primitives.js +4 -0
  42. package/dist/heart/providers/anthropic.js +329 -0
  43. package/dist/heart/providers/azure.js +66 -0
  44. package/dist/heart/providers/minimax.js +53 -0
  45. package/dist/heart/providers/openai-codex.js +162 -0
  46. package/dist/heart/streaming.js +412 -0
  47. package/dist/heart/turn-coordinator.js +62 -0
  48. package/dist/inner-worker-entry.js +4 -0
  49. package/dist/mind/associative-recall.js +197 -0
  50. package/dist/mind/bundle-manifest.js +118 -0
  51. package/dist/mind/context.js +302 -0
  52. package/dist/mind/first-impressions.js +43 -0
  53. package/dist/mind/format.js +56 -0
  54. package/dist/mind/friends/channel.js +41 -0
  55. package/dist/mind/friends/resolver.js +84 -0
  56. package/dist/mind/friends/store-file.js +171 -0
  57. package/dist/mind/friends/store.js +4 -0
  58. package/dist/mind/friends/tokens.js +26 -0
  59. package/dist/mind/friends/types.js +21 -0
  60. package/dist/mind/memory.js +388 -0
  61. package/dist/mind/pending.js +93 -0
  62. package/dist/mind/phrases.js +43 -0
  63. package/dist/mind/prompt-refresh.js +20 -0
  64. package/dist/mind/prompt.js +352 -0
  65. package/dist/mind/token-estimate.js +119 -0
  66. package/dist/nerves/cli-logging.js +31 -0
  67. package/dist/nerves/coverage/audit-rules.js +81 -0
  68. package/dist/nerves/coverage/audit.js +200 -0
  69. package/dist/nerves/coverage/cli-main.js +5 -0
  70. package/dist/nerves/coverage/cli.js +51 -0
  71. package/dist/nerves/coverage/contract.js +23 -0
  72. package/dist/nerves/coverage/file-completeness.js +56 -0
  73. package/dist/nerves/coverage/run-artifacts.js +77 -0
  74. package/dist/nerves/coverage/source-scanner.js +34 -0
  75. package/dist/nerves/index.js +152 -0
  76. package/dist/nerves/runtime.js +38 -0
  77. package/dist/repertoire/ado-client.js +211 -0
  78. package/dist/repertoire/ado-context.js +73 -0
  79. package/dist/repertoire/ado-semantic.js +841 -0
  80. package/dist/repertoire/ado-templates.js +146 -0
  81. package/dist/repertoire/coding/index.js +36 -0
  82. package/dist/repertoire/coding/manager.js +489 -0
  83. package/dist/repertoire/coding/monitor.js +60 -0
  84. package/dist/repertoire/coding/reporter.js +45 -0
  85. package/dist/repertoire/coding/spawner.js +102 -0
  86. package/dist/repertoire/coding/tools.js +167 -0
  87. package/dist/repertoire/coding/types.js +2 -0
  88. package/dist/repertoire/data/ado-endpoints.json +122 -0
  89. package/dist/repertoire/data/graph-endpoints.json +212 -0
  90. package/dist/repertoire/github-client.js +64 -0
  91. package/dist/repertoire/graph-client.js +118 -0
  92. package/dist/repertoire/skills.js +156 -0
  93. package/dist/repertoire/tasks/board.js +122 -0
  94. package/dist/repertoire/tasks/index.js +210 -0
  95. package/dist/repertoire/tasks/lifecycle.js +80 -0
  96. package/dist/repertoire/tasks/middleware.js +65 -0
  97. package/dist/repertoire/tasks/parser.js +173 -0
  98. package/dist/repertoire/tasks/scanner.js +132 -0
  99. package/dist/repertoire/tasks/transitions.js +145 -0
  100. package/dist/repertoire/tasks/types.js +2 -0
  101. package/dist/repertoire/tools-base.js +714 -0
  102. package/dist/repertoire/tools-github.js +53 -0
  103. package/dist/repertoire/tools-teams.js +308 -0
  104. package/dist/repertoire/tools.js +199 -0
  105. package/dist/senses/cli-entry.js +15 -0
  106. package/dist/senses/cli.js +604 -0
  107. package/dist/senses/commands.js +98 -0
  108. package/dist/senses/inner-dialog-worker.js +61 -0
  109. package/dist/senses/inner-dialog.js +231 -0
  110. package/dist/senses/session-lock.js +119 -0
  111. package/dist/senses/teams-entry.js +15 -0
  112. package/dist/senses/teams.js +696 -0
  113. package/dist/senses/trust-gate.js +150 -0
  114. package/package.json +34 -11
  115. package/subagents/README.md +73 -0
  116. package/subagents/work-doer.md +233 -0
  117. package/subagents/work-merger.md +624 -0
  118. package/subagents/work-planner.md +373 -0
  119. package/bin/ouro.js +0 -6
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const process_manager_1 = require("./process-manager");
5
+ const daemon_1 = require("./daemon");
6
+ const runtime_1 = require("../../nerves/runtime");
7
+ const message_router_1 = require("./message-router");
8
+ const health_monitor_1 = require("./health-monitor");
9
+ const task_scheduler_1 = require("./task-scheduler");
10
+ const runtime_logging_1 = require("./runtime-logging");
11
+ function parseSocketPath(argv) {
12
+ const socketIndex = argv.indexOf("--socket");
13
+ if (socketIndex >= 0) {
14
+ const value = argv[socketIndex + 1];
15
+ if (value && value.trim().length > 0)
16
+ return value;
17
+ }
18
+ return "/tmp/ouroboros-daemon.sock";
19
+ }
20
+ const socketPath = parseSocketPath(process.argv);
21
+ (0, runtime_logging_1.configureDaemonRuntimeLogger)("daemon");
22
+ (0, runtime_1.emitNervesEvent)({
23
+ component: "daemon",
24
+ event: "daemon.entry_start",
25
+ message: "starting daemon entrypoint",
26
+ meta: { socketPath },
27
+ });
28
+ const processManager = new process_manager_1.DaemonProcessManager({
29
+ agents: [
30
+ { name: "ouroboros", entry: "heart/agent-entry.js", channel: "cli", autoStart: true },
31
+ { name: "slugger", entry: "heart/agent-entry.js", channel: "cli", autoStart: true },
32
+ ],
33
+ });
34
+ const scheduler = new task_scheduler_1.TaskDrivenScheduler({
35
+ agents: ["ouroboros", "slugger"],
36
+ });
37
+ const router = new message_router_1.FileMessageRouter();
38
+ const healthMonitor = new health_monitor_1.HealthMonitor({
39
+ processManager,
40
+ scheduler,
41
+ alertSink: (message) => {
42
+ (0, runtime_1.emitNervesEvent)({
43
+ level: "error",
44
+ component: "daemon",
45
+ event: "daemon.health_alert",
46
+ message: "health monitor produced critical alert",
47
+ meta: { message },
48
+ });
49
+ },
50
+ });
51
+ const daemon = new daemon_1.OuroDaemon({
52
+ socketPath,
53
+ processManager,
54
+ scheduler,
55
+ healthMonitor,
56
+ router,
57
+ });
58
+ void daemon.start().catch(async () => {
59
+ (0, runtime_1.emitNervesEvent)({
60
+ level: "error",
61
+ component: "daemon",
62
+ event: "daemon.entry_error",
63
+ message: "daemon entrypoint failed",
64
+ meta: {},
65
+ });
66
+ await daemon.stop();
67
+ process.exit(1);
68
+ });
69
+ process.on("SIGINT", () => {
70
+ void daemon.stop().then(() => process.exit(0));
71
+ });
72
+ process.on("SIGTERM", () => {
73
+ void daemon.stop().then(() => process.exit(0));
74
+ });
@@ -0,0 +1,313 @@
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.OuroDaemon = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const net = __importStar(require("net"));
39
+ const path = __importStar(require("path"));
40
+ const identity_1 = require("../identity");
41
+ const runtime_1 = require("../../nerves/runtime");
42
+ function formatStatusSummary(snapshots) {
43
+ if (snapshots.length === 0)
44
+ return "no managed agents";
45
+ return snapshots
46
+ .map((snapshot) => {
47
+ return `${snapshot.name}\t${snapshot.channel}\t${snapshot.status}\tpid=${snapshot.pid ?? "none"}\trestarts=${snapshot.restartCount}`;
48
+ })
49
+ .join("\n");
50
+ }
51
+ function parseIncomingCommand(raw) {
52
+ let parsed;
53
+ try {
54
+ parsed = JSON.parse(raw);
55
+ }
56
+ catch {
57
+ throw new Error("Invalid daemon command payload: expected JSON object.");
58
+ }
59
+ if (!parsed || typeof parsed !== "object" || !("kind" in parsed)) {
60
+ throw new Error("Invalid daemon command payload: missing kind.");
61
+ }
62
+ const kind = parsed.kind;
63
+ if (typeof kind !== "string") {
64
+ throw new Error("Invalid daemon command payload: kind must be a string.");
65
+ }
66
+ return parsed;
67
+ }
68
+ class OuroDaemon {
69
+ socketPath;
70
+ processManager;
71
+ scheduler;
72
+ healthMonitor;
73
+ router;
74
+ bundlesRoot;
75
+ server = null;
76
+ constructor(options) {
77
+ this.socketPath = options.socketPath;
78
+ this.processManager = options.processManager;
79
+ this.scheduler = options.scheduler;
80
+ this.healthMonitor = options.healthMonitor;
81
+ this.router = options.router;
82
+ this.bundlesRoot = options.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)();
83
+ }
84
+ async start() {
85
+ if (this.server)
86
+ return;
87
+ (0, runtime_1.emitNervesEvent)({
88
+ component: "daemon",
89
+ event: "daemon.server_start",
90
+ message: "starting daemon server",
91
+ meta: { socketPath: this.socketPath },
92
+ });
93
+ await this.processManager.startAutoStartAgents();
94
+ this.scheduler.start?.();
95
+ await this.scheduler.reconcile?.();
96
+ await this.drainPendingBundleMessages();
97
+ if (fs.existsSync(this.socketPath)) {
98
+ fs.unlinkSync(this.socketPath);
99
+ }
100
+ this.server = net.createServer((connection) => {
101
+ let raw = "";
102
+ let responded = false;
103
+ const flushResponse = async () => {
104
+ if (responded)
105
+ return;
106
+ responded = true;
107
+ const response = await this.handleRawPayload(raw);
108
+ connection.end(response);
109
+ };
110
+ connection.on("data", (chunk) => {
111
+ raw += chunk.toString("utf-8");
112
+ void flushResponse();
113
+ });
114
+ connection.on("end", () => {
115
+ void flushResponse();
116
+ });
117
+ });
118
+ const server = this.server;
119
+ await new Promise((resolve, reject) => {
120
+ server.once("error", reject);
121
+ server.listen(this.socketPath, () => resolve());
122
+ });
123
+ }
124
+ async drainPendingBundleMessages() {
125
+ if (!fs.existsSync(this.bundlesRoot))
126
+ return;
127
+ let bundleDirs;
128
+ try {
129
+ bundleDirs = fs.readdirSync(this.bundlesRoot, { withFileTypes: true });
130
+ }
131
+ catch {
132
+ return;
133
+ }
134
+ for (const bundleDir of bundleDirs) {
135
+ if (!bundleDir.isDirectory() || !bundleDir.name.endsWith(".ouro"))
136
+ continue;
137
+ const pendingPath = path.join(this.bundlesRoot, bundleDir.name, "inbox", "pending.jsonl");
138
+ if (!fs.existsSync(pendingPath))
139
+ continue;
140
+ const raw = fs.readFileSync(pendingPath, "utf-8");
141
+ const lines = raw
142
+ .split("\n")
143
+ .map((line) => line.trim())
144
+ .filter((line) => line.length > 0);
145
+ const retained = [];
146
+ for (const line of lines) {
147
+ try {
148
+ const parsed = JSON.parse(line);
149
+ if (typeof parsed.from !== "string" ||
150
+ typeof parsed.to !== "string" ||
151
+ typeof parsed.content !== "string") {
152
+ retained.push(line);
153
+ continue;
154
+ }
155
+ await this.router.send({
156
+ from: parsed.from,
157
+ to: parsed.to,
158
+ content: parsed.content,
159
+ priority: typeof parsed.priority === "string" ? parsed.priority : undefined,
160
+ sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : undefined,
161
+ taskRef: typeof parsed.taskRef === "string" ? parsed.taskRef : undefined,
162
+ });
163
+ }
164
+ catch {
165
+ retained.push(line);
166
+ }
167
+ }
168
+ const next = retained.length > 0 ? `${retained.join("\n")}\n` : "";
169
+ fs.writeFileSync(pendingPath, next, "utf-8");
170
+ }
171
+ }
172
+ async stop() {
173
+ (0, runtime_1.emitNervesEvent)({
174
+ component: "daemon",
175
+ event: "daemon.server_stop",
176
+ message: "stopping daemon server",
177
+ meta: { socketPath: this.socketPath },
178
+ });
179
+ this.scheduler.stop?.();
180
+ await this.processManager.stopAll();
181
+ if (this.server) {
182
+ await new Promise((resolve) => {
183
+ this.server?.close(() => resolve());
184
+ });
185
+ this.server = null;
186
+ }
187
+ if (fs.existsSync(this.socketPath)) {
188
+ fs.unlinkSync(this.socketPath);
189
+ }
190
+ }
191
+ async handleRawPayload(raw) {
192
+ try {
193
+ const command = parseIncomingCommand(raw);
194
+ const response = await this.handleCommand(command);
195
+ return JSON.stringify(response);
196
+ }
197
+ catch (error) {
198
+ return JSON.stringify({
199
+ ok: false,
200
+ error: error instanceof Error ? error.message : String(error),
201
+ });
202
+ }
203
+ }
204
+ async handleCommand(command) {
205
+ (0, runtime_1.emitNervesEvent)({
206
+ component: "daemon",
207
+ event: "daemon.command_received",
208
+ message: "handling daemon command",
209
+ meta: { kind: command.kind },
210
+ });
211
+ switch (command.kind) {
212
+ case "daemon.start":
213
+ await this.start();
214
+ return { ok: true, message: "daemon started" };
215
+ case "daemon.stop":
216
+ await this.stop();
217
+ return { ok: true, message: "daemon stopped" };
218
+ case "daemon.status": {
219
+ const snapshots = this.processManager.listAgentSnapshots();
220
+ return {
221
+ ok: true,
222
+ summary: formatStatusSummary(snapshots),
223
+ data: snapshots,
224
+ };
225
+ }
226
+ case "daemon.health": {
227
+ const checks = await this.healthMonitor.runChecks();
228
+ const summary = checks.map((check) => `${check.name}:${check.status}:${check.message}`).join("\n");
229
+ return { ok: true, summary, data: checks };
230
+ }
231
+ case "daemon.logs":
232
+ return {
233
+ ok: true,
234
+ summary: "logs: use `ouro logs` to tail daemon and agent output",
235
+ message: "log streaming available via ouro logs",
236
+ data: { logDir: "~/.agentstate/daemon/logs" },
237
+ };
238
+ case "agent.start":
239
+ await this.processManager.startAgent(command.agent);
240
+ return { ok: true, message: `started ${command.agent}` };
241
+ case "agent.stop":
242
+ await this.processManager.stopAgent?.(command.agent);
243
+ return { ok: true, message: `stopped ${command.agent}` };
244
+ case "agent.restart":
245
+ await this.processManager.restartAgent?.(command.agent);
246
+ return { ok: true, message: `restarted ${command.agent}` };
247
+ case "cron.list": {
248
+ const jobs = this.scheduler.listJobs();
249
+ const summary = jobs.length === 0
250
+ ? "no cron jobs"
251
+ : jobs.map((job) => `${job.id}\t${job.schedule}\tlast=${job.lastRun ?? "never"}`).join("\n");
252
+ return { ok: true, summary, data: jobs };
253
+ }
254
+ case "cron.trigger": {
255
+ const result = await this.scheduler.triggerJob(command.jobId);
256
+ return { ok: result.ok, message: result.message };
257
+ }
258
+ case "message.send": {
259
+ const receipt = await this.router.send({
260
+ from: command.from,
261
+ to: command.to,
262
+ content: command.content,
263
+ priority: command.priority,
264
+ sessionId: command.sessionId,
265
+ taskRef: command.taskRef,
266
+ });
267
+ this.processManager.sendToAgent?.(command.to, { type: "message" });
268
+ return { ok: true, message: `queued message ${receipt.id}`, data: receipt };
269
+ }
270
+ case "message.poll": {
271
+ const messages = this.router.pollInbox(command.agent);
272
+ return {
273
+ ok: true,
274
+ summary: `${messages.length} messages`,
275
+ data: messages,
276
+ };
277
+ }
278
+ case "chat.connect":
279
+ await this.processManager.startAgent(command.agent);
280
+ return {
281
+ ok: true,
282
+ message: `connected to ${command.agent}`,
283
+ };
284
+ case "task.poke": {
285
+ const receipt = await this.router.send({
286
+ from: "ouro-poke",
287
+ to: command.agent,
288
+ content: `poke ${command.taskId}`,
289
+ priority: "high",
290
+ taskRef: command.taskId,
291
+ });
292
+ await this.scheduler.recordTaskRun?.(command.agent, command.taskId);
293
+ this.processManager.sendToAgent?.(command.agent, { type: "poke", taskId: command.taskId });
294
+ return {
295
+ ok: true,
296
+ message: `queued poke ${receipt.id}`,
297
+ data: receipt,
298
+ };
299
+ }
300
+ case "hatch.start":
301
+ return {
302
+ ok: true,
303
+ message: "hatch flow is stubbed in Gate 3 and completed in Gate 6",
304
+ };
305
+ default:
306
+ return {
307
+ ok: false,
308
+ error: `Unknown daemon command kind '${command.kind}'.`,
309
+ };
310
+ }
311
+ }
312
+ }
313
+ exports.OuroDaemon = OuroDaemon;
@@ -0,0 +1,285 @@
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.runHatchFlow = runHatchFlow;
37
+ const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
39
+ const path = __importStar(require("path"));
40
+ const identity_1 = require("../identity");
41
+ const runtime_1 = require("../../nerves/runtime");
42
+ const hatch_specialist_1 = require("./hatch-specialist");
43
+ function requiredCredentialKeys(provider) {
44
+ if (provider === "anthropic")
45
+ return ["setupToken"];
46
+ if (provider === "openai-codex")
47
+ return ["oauthAccessToken"];
48
+ if (provider === "minimax")
49
+ return ["apiKey"];
50
+ return ["apiKey", "endpoint", "deployment"];
51
+ }
52
+ function validateCredentials(provider, credentials) {
53
+ const missing = requiredCredentialKeys(provider).filter((key) => {
54
+ const value = credentials[key];
55
+ return typeof value !== "string" || value.trim().length === 0;
56
+ });
57
+ if (missing.length > 0) {
58
+ (0, runtime_1.emitNervesEvent)({
59
+ level: "error",
60
+ component: "daemon",
61
+ event: "daemon.hatch_credentials_error",
62
+ message: "hatch flow credentials validation failed",
63
+ meta: { provider, missing },
64
+ });
65
+ throw new Error(`Missing required credentials for ${provider}: ${missing.join(", ")}`);
66
+ }
67
+ }
68
+ function buildSecretsTemplate() {
69
+ return {
70
+ providers: {
71
+ azure: {
72
+ modelName: "gpt-4o-mini",
73
+ apiKey: "",
74
+ endpoint: "",
75
+ deployment: "",
76
+ apiVersion: "2025-04-01-preview",
77
+ },
78
+ minimax: {
79
+ model: "minimax-text-01",
80
+ apiKey: "",
81
+ },
82
+ anthropic: {
83
+ model: "claude-opus-4-6",
84
+ setupToken: "",
85
+ },
86
+ "openai-codex": {
87
+ model: "gpt-5.2",
88
+ oauthAccessToken: "",
89
+ },
90
+ },
91
+ teams: {
92
+ clientId: "",
93
+ clientSecret: "",
94
+ tenantId: "",
95
+ },
96
+ oauth: {
97
+ graphConnectionName: "graph",
98
+ adoConnectionName: "ado",
99
+ githubConnectionName: "",
100
+ },
101
+ teamsChannel: {
102
+ skipConfirmation: true,
103
+ port: 3978,
104
+ },
105
+ integrations: {
106
+ perplexityApiKey: "",
107
+ openaiEmbeddingsApiKey: "",
108
+ },
109
+ };
110
+ }
111
+ function writeSecretsFile(agentName, provider, credentials, secretsRoot) {
112
+ const secrets = buildSecretsTemplate();
113
+ if (provider === "anthropic") {
114
+ secrets.providers.anthropic.setupToken = credentials.setupToken.trim();
115
+ }
116
+ else if (provider === "openai-codex") {
117
+ secrets.providers["openai-codex"].oauthAccessToken = credentials.oauthAccessToken.trim();
118
+ }
119
+ else if (provider === "minimax") {
120
+ secrets.providers.minimax.apiKey = credentials.apiKey.trim();
121
+ }
122
+ else {
123
+ secrets.providers.azure.apiKey = credentials.apiKey.trim();
124
+ secrets.providers.azure.endpoint = credentials.endpoint.trim();
125
+ secrets.providers.azure.deployment = credentials.deployment.trim();
126
+ }
127
+ const secretsDir = path.join(secretsRoot, agentName);
128
+ fs.mkdirSync(secretsDir, { recursive: true });
129
+ const secretsPath = path.join(secretsDir, "secrets.json");
130
+ fs.writeFileSync(secretsPath, `${JSON.stringify(secrets, null, 2)}\n`, "utf-8");
131
+ return secretsPath;
132
+ }
133
+ function writeReadme(dir, purpose) {
134
+ fs.mkdirSync(dir, { recursive: true });
135
+ const readmePath = path.join(dir, "README.md");
136
+ if (!fs.existsSync(readmePath)) {
137
+ fs.writeFileSync(readmePath, `# ${path.basename(dir)}\n\n${purpose}\n`, "utf-8");
138
+ }
139
+ }
140
+ function slugify(value) {
141
+ const trimmed = value.trim().toLowerCase();
142
+ const slug = trimmed
143
+ .replace(/[^a-z0-9]+/g, "-")
144
+ .replace(/^-+/, "")
145
+ .replace(/-+$/, "");
146
+ return slug || "friend";
147
+ }
148
+ function pad(value) {
149
+ return String(value).padStart(2, "0");
150
+ }
151
+ function formatTaskStem(now) {
152
+ return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}`;
153
+ }
154
+ function writeHeartbeatTask(bundleRoot, now) {
155
+ const habitsDir = path.join(bundleRoot, "tasks", "habits");
156
+ fs.mkdirSync(habitsDir, { recursive: true });
157
+ const stem = formatTaskStem(now);
158
+ const filePath = path.join(habitsDir, `${stem}-heartbeat.md`);
159
+ const iso = now.toISOString();
160
+ const content = [
161
+ "---",
162
+ "type: habit",
163
+ "category: runtime",
164
+ "title: Heartbeat check-in",
165
+ "status: processing",
166
+ `created: ${iso}`,
167
+ `updated: ${iso}`,
168
+ "requester: system",
169
+ "validator: null",
170
+ "cadence: \"30m\"",
171
+ "scheduledAt: null",
172
+ "lastRun: null",
173
+ "---",
174
+ "",
175
+ "Run a lightweight heartbeat cycle. Review task board and inbox.",
176
+ "",
177
+ ].join("\n");
178
+ fs.writeFileSync(filePath, content, "utf-8");
179
+ }
180
+ function writeFriendImprint(bundleRoot, humanName, now) {
181
+ const friendsDir = path.join(bundleRoot, "friends");
182
+ fs.mkdirSync(friendsDir, { recursive: true });
183
+ const nowIso = now.toISOString();
184
+ const id = `friend-${slugify(humanName)}`;
185
+ const localExternalId = `${os.userInfo().username}@${os.hostname()}`;
186
+ const record = {
187
+ id,
188
+ name: humanName,
189
+ role: "primary",
190
+ trustLevel: "family",
191
+ connections: [],
192
+ externalIds: [
193
+ {
194
+ provider: "local",
195
+ externalId: localExternalId,
196
+ linkedAt: nowIso,
197
+ },
198
+ ],
199
+ tenantMemberships: [],
200
+ toolPreferences: {},
201
+ notes: {},
202
+ totalTokens: 0,
203
+ createdAt: nowIso,
204
+ updatedAt: nowIso,
205
+ schemaVersion: 1,
206
+ };
207
+ fs.writeFileSync(path.join(friendsDir, `${id}.json`), `${JSON.stringify(record, null, 2)}\n`, "utf-8");
208
+ }
209
+ function writeHatchlingPsyche(bundleRoot, input, identityFileName) {
210
+ const psycheDir = path.join(bundleRoot, "psyche");
211
+ fs.mkdirSync(psycheDir, { recursive: true });
212
+ fs.writeFileSync(path.join(psycheDir, "SOUL.md"), "# SOUL\n\nI am a practical, collaborative agent. I keep commitments and communicate clearly.\n", "utf-8");
213
+ fs.writeFileSync(path.join(psycheDir, "IDENTITY.md"), `# IDENTITY\n\nI'm ${input.agentName}, newly hatched and ready to help ${input.humanName}.`, "utf-8");
214
+ fs.writeFileSync(path.join(psycheDir, "LORE.md"), `# LORE\n\nHatched with specialist identity seed: ${identityFileName}.`, "utf-8");
215
+ fs.writeFileSync(path.join(psycheDir, "TACIT.md"), "# TACIT\n\n- Save what I learn.\n- Keep tasks current.\n", "utf-8");
216
+ fs.writeFileSync(path.join(psycheDir, "ASPIRATIONS.md"), "# ASPIRATIONS\n\n- Become a reliable partner for my primary friend.\n", "utf-8");
217
+ }
218
+ function writeMemoryScaffold(bundleRoot) {
219
+ const memoryRoot = path.join(bundleRoot, "psyche", "memory");
220
+ fs.mkdirSync(path.join(memoryRoot, "daily"), { recursive: true });
221
+ fs.mkdirSync(path.join(memoryRoot, "archive"), { recursive: true });
222
+ fs.writeFileSync(path.join(memoryRoot, "facts.jsonl"), "", "utf-8");
223
+ fs.writeFileSync(path.join(memoryRoot, "entities.json"), "{}\n", "utf-8");
224
+ }
225
+ function writeHatchlingAgentConfig(bundleRoot, input) {
226
+ const template = (0, identity_1.buildDefaultAgentTemplate)(input.agentName);
227
+ template.provider = input.provider;
228
+ template.enabled = true;
229
+ fs.writeFileSync(path.join(bundleRoot, "agent.json"), `${JSON.stringify(template, null, 2)}\n`, "utf-8");
230
+ }
231
+ async function runHatchFlow(input, deps = {}) {
232
+ (0, runtime_1.emitNervesEvent)({
233
+ component: "daemon",
234
+ event: "daemon.hatch_flow_start",
235
+ message: "starting hatch flow",
236
+ meta: { agentName: input.agentName, provider: input.provider },
237
+ });
238
+ validateCredentials(input.provider, input.credentials);
239
+ const bundlesRoot = deps.bundlesRoot ?? path.join(os.homedir(), "AgentBundles");
240
+ const secretsRoot = deps.secretsRoot ?? path.join(os.homedir(), ".agentsecrets");
241
+ const sourceIdentities = deps.specialistIdentitySourceDir ?? (0, hatch_specialist_1.getSpecialistIdentitySourceDir)();
242
+ const targetIdentities = deps.specialistIdentityTargetDir ?? (0, hatch_specialist_1.getRepoSpecialistIdentitiesDir)();
243
+ const now = deps.now ? deps.now() : new Date();
244
+ const random = deps.random ?? Math.random;
245
+ (0, hatch_specialist_1.syncSpecialistIdentities)({
246
+ sourceDir: sourceIdentities,
247
+ targetDir: targetIdentities,
248
+ });
249
+ const selected = (0, hatch_specialist_1.pickRandomSpecialistIdentity)({
250
+ identitiesDir: targetIdentities,
251
+ random,
252
+ });
253
+ const specialistSecretsPath = writeSecretsFile("AdoptionSpecialist", input.provider, input.credentials, secretsRoot);
254
+ const hatchlingSecretsPath = writeSecretsFile(input.agentName, input.provider, input.credentials, secretsRoot);
255
+ const bundleRoot = path.join(bundlesRoot, `${input.agentName}.ouro`);
256
+ fs.mkdirSync(bundleRoot, { recursive: true });
257
+ writeReadme(bundleRoot, "Root of this agent bundle.");
258
+ writeReadme(path.join(bundleRoot, "psyche"), "Identity and behavior files.");
259
+ writeReadme(path.join(bundleRoot, "psyche", "memory"), "Persistent memory store.");
260
+ writeReadme(path.join(bundleRoot, "friends"), "Known friend records.");
261
+ writeReadme(path.join(bundleRoot, "tasks"), "Task files.");
262
+ writeReadme(path.join(bundleRoot, "tasks", "habits"), "Recurring tasks.");
263
+ writeReadme(path.join(bundleRoot, "tasks", "one-shots"), "One-shot tasks.");
264
+ writeReadme(path.join(bundleRoot, "tasks", "ongoing"), "Ongoing tasks.");
265
+ writeReadme(path.join(bundleRoot, "skills"), "Local skill files.");
266
+ writeReadme(path.join(bundleRoot, "senses"), "Sense-specific config.");
267
+ writeReadme(path.join(bundleRoot, "senses", "teams"), "Teams sense config.");
268
+ writeHatchlingAgentConfig(bundleRoot, input);
269
+ writeHatchlingPsyche(bundleRoot, input, selected.fileName);
270
+ writeMemoryScaffold(bundleRoot);
271
+ writeFriendImprint(bundleRoot, input.humanName, now);
272
+ writeHeartbeatTask(bundleRoot, now);
273
+ (0, runtime_1.emitNervesEvent)({
274
+ component: "daemon",
275
+ event: "daemon.hatch_flow_end",
276
+ message: "completed hatch flow",
277
+ meta: { bundleRoot, identity: selected.fileName },
278
+ });
279
+ return {
280
+ bundleRoot,
281
+ selectedIdentity: selected.fileName,
282
+ specialistSecretsPath,
283
+ hatchlingSecretsPath,
284
+ };
285
+ }