@ouro.bot/cli 0.1.0-alpha.24 → 0.1.0-alpha.241

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 (258) hide show
  1. package/README.md +187 -191
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
  4. package/changelog.json +1459 -0
  5. package/dist/arc/attention-types.js +8 -0
  6. package/dist/arc/cares.js +140 -0
  7. package/dist/arc/episodes.js +119 -0
  8. package/dist/arc/intentions.js +133 -0
  9. package/dist/arc/json-store.js +120 -0
  10. package/dist/arc/obligations.js +237 -0
  11. package/dist/arc/presence.js +185 -0
  12. package/dist/heart/active-work.js +832 -0
  13. package/dist/heart/agent-entry.js +37 -2
  14. package/dist/heart/auth/auth-flow.js +447 -0
  15. package/dist/heart/bridges/manager.js +358 -0
  16. package/dist/heart/bridges/state-machine.js +135 -0
  17. package/dist/heart/bridges/store.js +123 -0
  18. package/dist/heart/commitments.js +111 -0
  19. package/dist/heart/config-registry.js +304 -0
  20. package/dist/heart/config.js +63 -30
  21. package/dist/heart/core.js +620 -159
  22. package/dist/heart/cross-chat-delivery.js +131 -0
  23. package/dist/heart/daemon/agent-config-check.js +149 -0
  24. package/dist/heart/daemon/agent-discovery.js +81 -0
  25. package/dist/heart/daemon/agent-service.js +360 -0
  26. package/dist/heart/daemon/cadence.js +70 -0
  27. package/dist/heart/daemon/cli-defaults.js +557 -0
  28. package/dist/heart/daemon/cli-exec.js +1847 -0
  29. package/dist/heart/daemon/cli-parse.js +759 -0
  30. package/dist/heart/daemon/cli-render.js +399 -0
  31. package/dist/heart/daemon/cli-types.js +8 -0
  32. package/dist/heart/daemon/daemon-cli.js +29 -1177
  33. package/dist/heart/daemon/daemon-entry.js +202 -4
  34. package/dist/heart/daemon/daemon-health.js +136 -0
  35. package/dist/heart/daemon/daemon-runtime-sync.js +153 -12
  36. package/dist/heart/daemon/daemon-tombstone.js +123 -0
  37. package/dist/heart/daemon/daemon.js +492 -20
  38. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  39. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  40. package/dist/heart/daemon/inner-status.js +89 -0
  41. package/dist/heart/daemon/launchd.js +39 -8
  42. package/dist/heart/daemon/log-tailer.js +4 -3
  43. package/dist/heart/daemon/message-router.js +17 -8
  44. package/dist/heart/daemon/os-cron-deps.js +134 -0
  45. package/dist/heart/daemon/ouro-bot-entry.js +1 -1
  46. package/dist/heart/daemon/process-manager.js +123 -0
  47. package/dist/heart/daemon/run-hooks.js +2 -0
  48. package/dist/heart/daemon/runtime-logging.js +58 -15
  49. package/dist/heart/daemon/runtime-metadata.js +101 -0
  50. package/dist/heart/daemon/runtime-mode.js +67 -0
  51. package/dist/heart/daemon/safe-mode.js +161 -0
  52. package/dist/heart/daemon/sense-manager.js +72 -3
  53. package/dist/heart/daemon/session-id-resolver.js +131 -0
  54. package/dist/heart/daemon/skill-management-installer.js +94 -0
  55. package/dist/heart/daemon/socket-client.js +202 -0
  56. package/dist/heart/daemon/task-scheduler.js +3 -25
  57. package/dist/heart/daemon/thoughts.js +507 -0
  58. package/dist/heart/delegation.js +62 -0
  59. package/dist/heart/habits/habit-migration.js +181 -0
  60. package/dist/heart/habits/habit-parser.js +119 -0
  61. package/dist/heart/habits/habit-scheduler.js +369 -0
  62. package/dist/heart/{daemon → hatch}/hatch-flow.js +30 -120
  63. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  64. package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
  65. package/dist/heart/{daemon → hatch}/specialist-tools.js +49 -3
  66. package/dist/heart/identity.js +157 -55
  67. package/dist/heart/kicks.js +2 -20
  68. package/dist/heart/mcp/mcp-server.js +651 -0
  69. package/dist/heart/migrate-config.js +127 -0
  70. package/dist/heart/model-capabilities.js +48 -0
  71. package/dist/heart/outlook/outlook-http.js +439 -0
  72. package/dist/heart/outlook/outlook-read.js +1618 -0
  73. package/dist/heart/outlook/outlook-render.js +1032 -0
  74. package/dist/heart/outlook/outlook-types.js +7 -0
  75. package/dist/heart/outlook/outlook-view.js +194 -0
  76. package/dist/heart/progress-story.js +42 -0
  77. package/dist/heart/provider-failover.js +88 -0
  78. package/dist/heart/provider-ping.js +162 -0
  79. package/dist/heart/providers/anthropic-token.js +163 -0
  80. package/dist/heart/providers/anthropic.js +187 -41
  81. package/dist/heart/providers/azure.js +116 -10
  82. package/dist/heart/providers/github-copilot.js +157 -0
  83. package/dist/heart/providers/minimax.js +33 -3
  84. package/dist/heart/providers/openai-codex.js +51 -16
  85. package/dist/heart/session-activity.js +172 -0
  86. package/dist/heart/session-recall.js +216 -0
  87. package/dist/heart/start-of-turn-packet.js +330 -0
  88. package/dist/heart/streaming.js +36 -27
  89. package/dist/heart/sync.js +217 -0
  90. package/dist/heart/target-resolution.js +127 -0
  91. package/dist/heart/tempo.js +93 -0
  92. package/dist/heart/temporal-view.js +41 -0
  93. package/dist/heart/tool-activity-callbacks.js +36 -0
  94. package/dist/heart/tool-description.js +135 -0
  95. package/dist/heart/tool-loop.js +200 -0
  96. package/dist/heart/turn-context.js +358 -0
  97. package/dist/heart/turn-coordinator.js +28 -0
  98. package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
  99. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  100. package/dist/heart/{daemon → versioning}/ouro-path-installer.js +78 -35
  101. package/dist/heart/versioning/ouro-version-manager.js +171 -0
  102. package/dist/heart/{daemon → versioning}/staged-restart.js +30 -6
  103. package/dist/heart/{daemon → versioning}/update-checker.js +9 -1
  104. package/dist/heart/{daemon → versioning}/update-hooks.js +11 -0
  105. package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +41 -3
  106. package/dist/mind/associative-recall.js +126 -66
  107. package/dist/mind/bundle-manifest.js +8 -1
  108. package/dist/mind/context.js +125 -14
  109. package/dist/mind/{memory.js → diary.js} +73 -96
  110. package/dist/mind/embedding-provider.js +60 -0
  111. package/dist/mind/file-state.js +179 -0
  112. package/dist/mind/first-impressions.js +16 -2
  113. package/dist/mind/friends/channel.js +56 -0
  114. package/dist/mind/friends/group-context.js +144 -0
  115. package/dist/mind/friends/resolver.js +37 -0
  116. package/dist/mind/friends/store-file.js +58 -3
  117. package/dist/mind/friends/trust-explanation.js +74 -0
  118. package/dist/mind/friends/types.js +8 -0
  119. package/dist/mind/journal-index.js +161 -0
  120. package/dist/mind/obligation-steering.js +221 -0
  121. package/dist/mind/pending.js +76 -9
  122. package/dist/mind/phrases.js +1 -0
  123. package/dist/mind/prompt.js +762 -109
  124. package/dist/mind/scrutiny.js +173 -0
  125. package/dist/mind/token-estimate.js +8 -12
  126. package/dist/nerves/coverage/audit.js +1 -1
  127. package/dist/nerves/coverage/file-completeness.js +50 -5
  128. package/dist/nerves/coverage/run-artifacts.js +1 -1
  129. package/dist/nerves/event-buffer.js +111 -0
  130. package/dist/nerves/index.js +64 -4
  131. package/dist/nerves/observation.js +20 -0
  132. package/dist/nerves/runtime.js +5 -1
  133. package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
  134. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  135. package/dist/outlook-ui/index.html +15 -0
  136. package/dist/repertoire/ado-client.js +15 -56
  137. package/dist/repertoire/ado-semantic.js +11 -10
  138. package/dist/repertoire/api-client.js +97 -0
  139. package/dist/repertoire/bitwarden-store.js +319 -0
  140. package/dist/repertoire/bw-installer.js +79 -0
  141. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  142. package/dist/repertoire/coding/context-pack.js +330 -0
  143. package/dist/repertoire/coding/feedback.js +197 -30
  144. package/dist/repertoire/coding/manager.js +149 -2
  145. package/dist/repertoire/coding/spawner.js +55 -9
  146. package/dist/repertoire/coding/tools.js +170 -7
  147. package/dist/repertoire/commerce-errors.js +109 -0
  148. package/dist/repertoire/commerce-self-test.js +156 -0
  149. package/dist/repertoire/credential-access.js +515 -0
  150. package/dist/repertoire/duffel-client.js +185 -0
  151. package/dist/repertoire/github-client.js +14 -55
  152. package/dist/repertoire/graph-client.js +11 -52
  153. package/dist/repertoire/guardrails.js +369 -0
  154. package/dist/repertoire/mcp-client.js +255 -0
  155. package/dist/repertoire/mcp-manager.js +303 -0
  156. package/dist/repertoire/mcp-tools.js +63 -0
  157. package/dist/repertoire/shell-sessions.js +133 -0
  158. package/dist/repertoire/skills.js +14 -23
  159. package/dist/repertoire/stripe-client.js +131 -0
  160. package/dist/repertoire/tasks/board.js +43 -5
  161. package/dist/repertoire/tasks/fix.js +182 -0
  162. package/dist/repertoire/tasks/index.js +28 -10
  163. package/dist/repertoire/tasks/lifecycle.js +2 -2
  164. package/dist/repertoire/tasks/parser.js +3 -2
  165. package/dist/repertoire/tasks/scanner.js +194 -37
  166. package/dist/repertoire/tasks/transitions.js +11 -28
  167. package/dist/repertoire/tools-base.js +43 -771
  168. package/dist/repertoire/tools-bluebubbles.js +94 -0
  169. package/dist/repertoire/tools-bridge.js +141 -0
  170. package/dist/repertoire/tools-config.js +185 -0
  171. package/dist/repertoire/tools-continuity.js +248 -0
  172. package/dist/repertoire/tools-credential.js +182 -0
  173. package/dist/repertoire/tools-files.js +342 -0
  174. package/dist/repertoire/tools-flight.js +224 -0
  175. package/dist/repertoire/tools-flow.js +62 -0
  176. package/dist/repertoire/tools-github.js +1 -7
  177. package/dist/repertoire/tools-memory.js +347 -0
  178. package/dist/repertoire/tools-session.js +739 -0
  179. package/dist/repertoire/tools-shell.js +120 -0
  180. package/dist/repertoire/tools-stripe.js +180 -0
  181. package/dist/repertoire/tools-surface.js +243 -0
  182. package/dist/repertoire/tools-teams.js +12 -62
  183. package/dist/repertoire/tools-travel.js +125 -0
  184. package/dist/repertoire/tools-user-profile.js +144 -0
  185. package/dist/repertoire/tools-vault.js +110 -0
  186. package/dist/repertoire/tools.js +147 -130
  187. package/dist/repertoire/travel-api-client.js +360 -0
  188. package/dist/repertoire/user-profile.js +118 -0
  189. package/dist/repertoire/vault-setup.js +241 -0
  190. package/dist/scripts/claude-code-hook.js +41 -0
  191. package/dist/scripts/claude-code-stop-hook.js +47 -0
  192. package/dist/senses/attention-queue.js +97 -0
  193. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +109 -10
  194. package/dist/senses/bluebubbles/entry.js +13 -0
  195. package/dist/senses/bluebubbles/inbound-log.js +109 -0
  196. package/dist/senses/bluebubbles/index.js +1374 -0
  197. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +119 -24
  198. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +13 -5
  199. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  200. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  201. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  202. package/dist/senses/cli/adapter.js +274 -0
  203. package/dist/senses/cli/ink-app.js +156 -0
  204. package/dist/senses/cli/inline-diff.js +64 -0
  205. package/dist/senses/cli/message-list.js +51 -0
  206. package/dist/senses/cli/ouro-tui.js +358 -0
  207. package/dist/senses/cli/spinner-imperative.js +135 -0
  208. package/dist/senses/cli/spinner.js +101 -0
  209. package/dist/senses/cli/status-line.js +60 -0
  210. package/dist/senses/cli/streaming-markdown.js +526 -0
  211. package/dist/senses/cli/tool-display.js +83 -0
  212. package/dist/senses/cli/tool-render.js +85 -0
  213. package/dist/senses/cli/tui-store.js +198 -0
  214. package/dist/senses/cli/virtual-list.js +35 -0
  215. package/dist/senses/cli-entry.js +1 -1
  216. package/dist/senses/cli-layout.js +187 -0
  217. package/dist/senses/cli.js +510 -246
  218. package/dist/senses/commands.js +65 -1
  219. package/dist/senses/continuity.js +94 -0
  220. package/dist/senses/habit-turn-message.js +108 -0
  221. package/dist/senses/inner-dialog-worker.js +112 -19
  222. package/dist/senses/inner-dialog.js +593 -85
  223. package/dist/senses/pipeline.js +559 -0
  224. package/dist/senses/shared-turn.js +199 -0
  225. package/dist/senses/surface-tool.js +68 -0
  226. package/dist/senses/teams.js +664 -165
  227. package/dist/senses/trust-gate.js +112 -2
  228. package/package.json +14 -7
  229. package/skills/agent-commerce.md +106 -0
  230. package/skills/browser-navigation.md +110 -0
  231. package/skills/commerce-setup-guide.md +116 -0
  232. package/skills/commerce-setup.md +84 -0
  233. package/skills/configure-dev-tools.md +81 -0
  234. package/skills/travel-planning.md +138 -0
  235. package/dist/heart/daemon/subagent-installer.js +0 -134
  236. package/dist/senses/bluebubbles-entry.js +0 -11
  237. package/dist/senses/bluebubbles.js +0 -421
  238. package/dist/senses/debug-activity.js +0 -107
  239. package/subagents/README.md +0 -73
  240. package/subagents/work-doer.md +0 -235
  241. package/subagents/work-merger.md +0 -618
  242. package/subagents/work-planner.md +0 -382
  243. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  244. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  245. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  246. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  247. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  248. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  249. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  250. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  251. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  252. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  253. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  254. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
  255. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  256. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  257. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  258. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
@@ -0,0 +1,557 @@
1
+ "use strict";
2
+ /**
3
+ * CLI default dependency wiring.
4
+ *
5
+ * Creates the production OuroCliDeps with real filesystem, socket, and
6
+ * process bindings. Tests inject mocks for all of these.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.defaultStartDaemonProcess = defaultStartDaemonProcess;
43
+ exports.readFirstBundleMetaVersion = readFirstBundleMetaVersion;
44
+ exports.defaultListDiscoveredAgents = defaultListDiscoveredAgents;
45
+ exports.discoverExistingCredentials = discoverExistingCredentials;
46
+ exports.defaultRunSerpentGuide = defaultRunSerpentGuide;
47
+ exports.createDefaultOuroCliDeps = createDefaultOuroCliDeps;
48
+ const child_process_1 = require("child_process");
49
+ const fs = __importStar(require("fs"));
50
+ const os = __importStar(require("os"));
51
+ const path = __importStar(require("path"));
52
+ const identity_1 = require("../identity");
53
+ const runtime_1 = require("../../nerves/runtime");
54
+ const ouro_path_installer_1 = require("../versioning/ouro-path-installer");
55
+ const ouro_uti_1 = require("../versioning/ouro-uti");
56
+ const ouro_version_manager_1 = require("../versioning/ouro-version-manager");
57
+ const skill_management_installer_1 = require("./skill-management-installer");
58
+ const hatch_flow_1 = require("../hatch/hatch-flow");
59
+ const specialist_orchestrator_1 = require("../hatch/specialist-orchestrator");
60
+ const specialist_prompt_1 = require("../hatch/specialist-prompt");
61
+ const specialist_tools_1 = require("../hatch/specialist-tools");
62
+ const runtime_mode_1 = require("./runtime-mode");
63
+ const agent_discovery_1 = require("./agent-discovery");
64
+ const bundle_manifest_1 = require("../../mind/bundle-manifest");
65
+ const ouro_bot_global_installer_1 = require("../versioning/ouro-bot-global-installer");
66
+ const launchd_1 = require("./launchd");
67
+ const socket_client_1 = require("./socket-client");
68
+ const session_activity_1 = require("../session-activity");
69
+ const auth_flow_1 = require("../auth/auth-flow");
70
+ const cli_parse_1 = require("./cli-parse");
71
+ // ── Default implementations ──
72
+ function defaultStartDaemonProcess(socketPath) {
73
+ const entry = path.join((0, identity_1.getRepoRoot)(), "dist", "heart", "daemon", "daemon-entry.js");
74
+ // Redirect stdio to /dev/null via file descriptors — using 'ignore' causes EPIPE
75
+ // when the daemon's logging system writes to stderr after the parent exits.
76
+ const outFd = fs.openSync(os.devNull, "w");
77
+ const errFd = fs.openSync(os.devNull, "w");
78
+ const child = (0, child_process_1.spawn)("node", [entry, "--socket", socketPath], {
79
+ detached: true,
80
+ stdio: ["ignore", outFd, errFd],
81
+ });
82
+ child.unref();
83
+ // Don't close fds — the child process needs them. They'll be cleaned up when the parent exits.
84
+ return Promise.resolve({ pid: child.pid ?? null });
85
+ }
86
+ function defaultWriteStdout(text) {
87
+ // eslint-disable-next-line no-console -- terminal UX: CLI command output
88
+ console.log(text);
89
+ }
90
+ /**
91
+ * Read the runtimeVersion from the first .ouro bundle's bundle-meta.json.
92
+ * Returns undefined if none found or unreadable.
93
+ */
94
+ function readFirstBundleMetaVersion(bundlesRoot) {
95
+ try {
96
+ if (!fs.existsSync(bundlesRoot))
97
+ return undefined;
98
+ const entries = fs.readdirSync(bundlesRoot, { withFileTypes: true });
99
+ for (const entry of entries) {
100
+ /* v8 ignore next -- skip non-.ouro dirs: tested via version-detect tests @preserve */
101
+ if (!entry.isDirectory() || !entry.name.endsWith(".ouro"))
102
+ continue;
103
+ const metaPath = path.join(bundlesRoot, entry.name, "bundle-meta.json");
104
+ if (!fs.existsSync(metaPath))
105
+ continue;
106
+ const raw = fs.readFileSync(metaPath, "utf-8");
107
+ const meta = JSON.parse(raw);
108
+ if (meta.runtimeVersion)
109
+ return meta.runtimeVersion;
110
+ }
111
+ }
112
+ catch {
113
+ // Best effort — return undefined on any error
114
+ }
115
+ return undefined;
116
+ }
117
+ function defaultCleanupStaleSocket(socketPath) {
118
+ if (fs.existsSync(socketPath)) {
119
+ fs.unlinkSync(socketPath);
120
+ }
121
+ }
122
+ function defaultFallbackPendingMessage(command) {
123
+ const inboxDir = path.join((0, identity_1.getAgentBundlesRoot)(), `${command.to}.ouro`, "inbox");
124
+ const pendingPath = path.join(inboxDir, "pending.jsonl");
125
+ const queuedAt = new Date().toISOString();
126
+ const payload = {
127
+ from: command.from,
128
+ to: command.to,
129
+ content: command.content,
130
+ priority: command.priority ?? "normal",
131
+ sessionId: command.sessionId,
132
+ taskRef: command.taskRef,
133
+ queuedAt,
134
+ };
135
+ fs.mkdirSync(inboxDir, { recursive: true });
136
+ fs.appendFileSync(pendingPath, `${JSON.stringify(payload)}\n`, "utf-8");
137
+ (0, runtime_1.emitNervesEvent)({
138
+ level: "warn",
139
+ component: "daemon",
140
+ event: "daemon.message_fallback_queued",
141
+ message: "queued message to pending fallback file",
142
+ meta: {
143
+ to: command.to,
144
+ path: pendingPath,
145
+ sessionId: command.sessionId ?? null,
146
+ taskRef: command.taskRef ?? null,
147
+ },
148
+ });
149
+ return pendingPath;
150
+ }
151
+ function defaultEnsureDaemonBootPersistence(socketPath) {
152
+ if (process.platform !== "darwin") {
153
+ return;
154
+ }
155
+ const homeDir = os.homedir();
156
+ const writeDeps = {
157
+ writeFile: (filePath, content) => fs.writeFileSync(filePath, content, "utf-8"),
158
+ mkdirp: (dir) => fs.mkdirSync(dir, { recursive: true }),
159
+ homeDir,
160
+ };
161
+ const entryPath = path.join((0, identity_1.getRepoRoot)(), "dist", "heart", "daemon", "daemon-entry.js");
162
+ /* v8 ignore next -- covered via mock in daemon-cli-defaults.test.ts; v8 on CI attributes the real fs.existsSync branch to the non-mock load @preserve */
163
+ if (!fs.existsSync(entryPath)) {
164
+ (0, runtime_1.emitNervesEvent)({
165
+ level: "warn",
166
+ component: "daemon",
167
+ event: "daemon.entry_path_missing",
168
+ message: "entryPath does not exist on disk — plist may point to a stale location. Run 'ouro daemon install' from the correct location.",
169
+ meta: { entryPath },
170
+ });
171
+ }
172
+ const logDir = (0, identity_1.getAgentDaemonLogsDir)();
173
+ // Write plist only — do NOT launchctl bootstrap.
174
+ // The daemon is already running (started by ouro up). Bootstrapping would
175
+ // start a SECOND daemon via launchd's RunAtLoad, causing a race where
176
+ // killOrphanProcesses kills the first daemon and both end up dead.
177
+ // The plist on disk is sufficient: launchd picks it up on login.
178
+ (0, launchd_1.writeLaunchAgentPlist)(writeDeps, {
179
+ nodePath: process.execPath,
180
+ entryPath,
181
+ socketPath,
182
+ logDir,
183
+ envPath: process.env.PATH,
184
+ });
185
+ }
186
+ async function defaultPromptInput(question) {
187
+ const readline = await Promise.resolve().then(() => __importStar(require("readline/promises")));
188
+ const rl = readline.createInterface({
189
+ input: process.stdin,
190
+ output: process.stdout,
191
+ });
192
+ try {
193
+ const response = await rl.question(question);
194
+ return response.trim();
195
+ }
196
+ finally {
197
+ rl.close();
198
+ }
199
+ }
200
+ function defaultListDiscoveredAgents() {
201
+ return (0, agent_discovery_1.listEnabledBundleAgents)({
202
+ bundlesRoot: (0, identity_1.getAgentBundlesRoot)(),
203
+ readdirSync: fs.readdirSync,
204
+ readFileSync: fs.readFileSync,
205
+ });
206
+ }
207
+ // ── Credential discovery ──
208
+ function discoverExistingCredentials(secretsRoot) {
209
+ const found = [];
210
+ let entries;
211
+ try {
212
+ entries = fs.readdirSync(secretsRoot, { withFileTypes: true });
213
+ }
214
+ catch {
215
+ return found;
216
+ }
217
+ for (const entry of entries) {
218
+ if (!entry.isDirectory())
219
+ continue;
220
+ const secretsPath = path.join(secretsRoot, entry.name, "secrets.json");
221
+ let raw;
222
+ try {
223
+ raw = fs.readFileSync(secretsPath, "utf-8");
224
+ }
225
+ catch {
226
+ continue;
227
+ }
228
+ let parsed;
229
+ try {
230
+ parsed = JSON.parse(raw);
231
+ }
232
+ catch {
233
+ continue;
234
+ }
235
+ if (!parsed.providers)
236
+ continue;
237
+ for (const [provName, provConfig] of Object.entries(parsed.providers)) {
238
+ const desc = identity_1.PROVIDER_CREDENTIALS[provName];
239
+ /* v8 ignore next -- guard: unknown provider names in stored secrets @preserve */
240
+ if (!desc)
241
+ continue;
242
+ const hasRequired = desc.required.every((key) => !!provConfig[key]);
243
+ if (hasRequired) {
244
+ const credentials = {};
245
+ for (const key of Object.keys(provConfig))
246
+ credentials[key] = provConfig[key];
247
+ found.push({ agentName: entry.name, provider: provName, credentials, providerConfig: { ...provConfig } });
248
+ }
249
+ }
250
+ }
251
+ // Deduplicate by provider+credential value (keep first seen)
252
+ const seen = new Set();
253
+ return found.filter((cred) => {
254
+ const key = `${cred.provider}:${JSON.stringify(cred.credentials)}`;
255
+ if (seen.has(key))
256
+ return false;
257
+ seen.add(key);
258
+ return true;
259
+ });
260
+ }
261
+ // ── Serpent guide (interactive hatch) ──
262
+ /* v8 ignore start -- integration: interactive terminal specialist session @preserve */
263
+ async function defaultRunSerpentGuide() {
264
+ const { runCliSession } = await Promise.resolve().then(() => __importStar(require("../../senses/cli")));
265
+ const { patchRuntimeConfig } = await Promise.resolve().then(() => __importStar(require("../config")));
266
+ const { setAgentName, setAgentConfigOverride } = await Promise.resolve().then(() => __importStar(require("../identity")));
267
+ const readlinePromises = await Promise.resolve().then(() => __importStar(require("readline/promises")));
268
+ const crypto = await Promise.resolve().then(() => __importStar(require("crypto")));
269
+ // Phase 1: cold CLI — collect provider/credentials with a simple readline
270
+ const coldRl = readlinePromises.createInterface({ input: process.stdin, output: process.stdout });
271
+ const coldPrompt = async (q) => {
272
+ const answer = await coldRl.question(q);
273
+ return answer.trim();
274
+ };
275
+ let providerRaw;
276
+ let credentials = {};
277
+ let providerConfig = {};
278
+ const tempDir = path.join(os.tmpdir(), `ouro-hatch-${crypto.randomUUID()}`);
279
+ try {
280
+ const secretsRoot = path.join(os.homedir(), ".agentsecrets");
281
+ const discovered = discoverExistingCredentials(secretsRoot);
282
+ const existingBundleCount = (0, specialist_orchestrator_1.listExistingBundles)((0, identity_1.getAgentBundlesRoot)()).length;
283
+ const hatchVerb = existingBundleCount > 0 ? "let's hatch a new agent." : "let's hatch your first agent.";
284
+ // Default models per provider (used when entering new credentials)
285
+ const defaultModels = {
286
+ anthropic: "claude-opus-4-6",
287
+ minimax: "MiniMax-M2.7",
288
+ "openai-codex": "gpt-5.4",
289
+ "github-copilot": "claude-sonnet-4.6",
290
+ azure: "",
291
+ };
292
+ // Scan environment variables for API keys using the canonical descriptor
293
+ const envDiscovered = [];
294
+ for (const [provider, desc] of Object.entries(identity_1.PROVIDER_CREDENTIALS)) {
295
+ const envCred = {};
296
+ let firstEnvVar;
297
+ for (const [envVar, credKey] of Object.entries(desc.envVars)) {
298
+ const value = process.env[envVar];
299
+ if (value) {
300
+ ;
301
+ envCred[credKey] = value;
302
+ if (!firstEnvVar)
303
+ firstEnvVar = envVar;
304
+ }
305
+ }
306
+ // Only register if at least one required field was found
307
+ const hasRequired = desc.required.some((key) => !!envCred[key]);
308
+ if (hasRequired && firstEnvVar) {
309
+ const provCfg = { model: defaultModels[provider] };
310
+ if (provider === "azure" && envCred.deployment)
311
+ provCfg.deployment = envCred.deployment;
312
+ envDiscovered.push({ provider, agentName: "env", credentials: envCred, providerConfig: provCfg, envVar: firstEnvVar });
313
+ discovered.push({ provider, agentName: "env", credentials: envCred, providerConfig: provCfg });
314
+ }
315
+ }
316
+ if (discovered.length > 0) {
317
+ process.stdout.write(`\n\ud83d\udc0d welcome to ouroboros! ${hatchVerb}\n`);
318
+ process.stdout.write("i found existing API credentials:\n\n");
319
+ const unique = [...new Map(discovered.map((d) => [`${d.provider}`, d])).values()];
320
+ for (let i = 0; i < unique.length; i++) {
321
+ const model = unique[i].providerConfig.model || unique[i].providerConfig.deployment || "";
322
+ const modelLabel = model ? `, ${model}` : "";
323
+ const envMatch = envDiscovered.find((e) => e.provider === unique[i].provider && unique[i].agentName === "env");
324
+ const sourceLabel = envMatch ? `from env: $${envMatch.envVar}` : `from ${unique[i].agentName}`;
325
+ process.stdout.write(` ${i + 1}. ${unique[i].provider}${modelLabel} (${sourceLabel})\n`);
326
+ }
327
+ process.stdout.write("\n");
328
+ const choice = await coldPrompt("use one of these? enter number, or 'new' for a different key: ");
329
+ const idx = parseInt(choice, 10) - 1;
330
+ if (idx >= 0 && idx < unique.length) {
331
+ providerRaw = unique[idx].provider;
332
+ credentials = unique[idx].credentials;
333
+ providerConfig = unique[idx].providerConfig;
334
+ }
335
+ else {
336
+ const pRaw = await coldPrompt("provider (anthropic/azure/minimax/openai-codex/github-copilot): ");
337
+ if (!(0, cli_parse_1.isAgentProvider)(pRaw)) {
338
+ process.stdout.write("unknown provider. run `ouro hatch` to try again.\n");
339
+ coldRl.close();
340
+ return null;
341
+ }
342
+ providerRaw = pRaw;
343
+ providerConfig = { model: defaultModels[providerRaw] };
344
+ credentials = await (0, auth_flow_1.collectRuntimeAuthCredentials)({ agentName: "SerpentGuide", provider: providerRaw, promptInput: coldPrompt }, {});
345
+ }
346
+ }
347
+ else {
348
+ process.stdout.write(`\n\ud83d\udc0d welcome to ouroboros! ${hatchVerb}\n`);
349
+ process.stdout.write("i need an API key to power our conversation.\n\n");
350
+ const pRaw = await coldPrompt("provider (anthropic/azure/minimax/openai-codex/github-copilot): ");
351
+ if (!(0, cli_parse_1.isAgentProvider)(pRaw)) {
352
+ process.stdout.write("unknown provider. run `ouro hatch` to try again.\n");
353
+ coldRl.close();
354
+ return null;
355
+ }
356
+ providerRaw = pRaw;
357
+ providerConfig = { model: defaultModels[providerRaw] };
358
+ credentials = await (0, auth_flow_1.collectRuntimeAuthCredentials)({ agentName: "SerpentGuide", provider: providerRaw, promptInput: coldPrompt }, {});
359
+ }
360
+ coldRl.close();
361
+ process.stdout.write("\n");
362
+ // Phase 2: configure runtime for serpent guide
363
+ const bundleSourceDir = path.resolve(__dirname, "..", "..", "..", "SerpentGuide.ouro");
364
+ const bundlesRoot = (0, identity_1.getAgentBundlesRoot)();
365
+ const secretsRoot2 = path.join(os.homedir(), ".agentsecrets");
366
+ // Suppress non-critical log noise during hatch (no secrets.json, etc.)
367
+ const { setRuntimeLogger } = await Promise.resolve().then(() => __importStar(require("../../nerves/runtime")));
368
+ const { createLogger } = await Promise.resolve().then(() => __importStar(require("../../nerves")));
369
+ setRuntimeLogger(createLogger({ level: "error" }));
370
+ // Configure runtime: set agent identity + config override so runAgent
371
+ // doesn't try to read from ~/AgentBundles/SerpentGuide.ouro/
372
+ setAgentName("SerpentGuide");
373
+ // Build specialist system prompt
374
+ const soulText = (0, specialist_orchestrator_1.loadSoulText)(bundleSourceDir);
375
+ const identitiesDir = path.join(bundleSourceDir, "psyche", "identities");
376
+ const identity = (0, specialist_orchestrator_1.pickRandomIdentity)(identitiesDir);
377
+ // Load identity-specific spinner phrases (falls back to DEFAULT_AGENT_PHRASES)
378
+ const { loadIdentityPhrases } = await Promise.resolve().then(() => __importStar(require("../hatch/specialist-orchestrator")));
379
+ const phrases = loadIdentityPhrases(bundleSourceDir, identity.fileName);
380
+ const resolvedModel = providerConfig.model || providerConfig.deployment || "";
381
+ setAgentConfigOverride({
382
+ version: 2,
383
+ enabled: true,
384
+ provider: providerRaw,
385
+ humanFacing: { provider: providerRaw, model: resolvedModel },
386
+ agentFacing: { provider: providerRaw, model: resolvedModel },
387
+ phrases,
388
+ });
389
+ patchRuntimeConfig({
390
+ providers: {
391
+ [providerRaw]: { ...providerConfig, ...credentials },
392
+ },
393
+ });
394
+ // Ping-verify credentials before entering the serpent guide session
395
+ const { pingProvider } = await Promise.resolve().then(() => __importStar(require("../provider-ping")));
396
+ const pingResult = await pingProvider(providerRaw, { ...providerConfig, ...credentials });
397
+ if (!pingResult.ok) {
398
+ process.stdout.write(`credentials didn't work (${pingResult.message}). run 'ouro hatch' to try again.\n`);
399
+ return null;
400
+ }
401
+ const existingBundles = (0, specialist_orchestrator_1.listExistingBundles)(bundlesRoot);
402
+ const systemPrompt = (0, specialist_prompt_1.buildSpecialistSystemPrompt)(soulText, identity.content, existingBundles, {
403
+ tempDir,
404
+ provider: providerRaw,
405
+ model: providerConfig.model ?? "",
406
+ });
407
+ // Build specialist tools
408
+ const specialistTools = (0, specialist_tools_1.getSpecialistTools)();
409
+ const specialistExecTool = (0, specialist_tools_1.createSpecialistExecTool)({
410
+ tempDir,
411
+ credentials,
412
+ provider: providerRaw,
413
+ bundlesRoot,
414
+ secretsRoot: secretsRoot2,
415
+ animationWriter: (text) => process.stdout.write(text),
416
+ });
417
+ // Run the serpent guide session via runCliSession
418
+ const result = await runCliSession({
419
+ agentName: "SerpentGuide",
420
+ tools: specialistTools,
421
+ execTool: specialistExecTool,
422
+ exitOnToolCall: "complete_adoption",
423
+ autoFirstTurn: true,
424
+ banner: false,
425
+ disableCommands: true,
426
+ skipSystemPromptRefresh: true,
427
+ messages: [
428
+ { role: "system", content: systemPrompt },
429
+ { role: "user", content: "hi" },
430
+ ],
431
+ });
432
+ if (result.exitReason === "tool_exit" && result.toolResult) {
433
+ const parsed = typeof result.toolResult === "string" ? JSON.parse(result.toolResult) : result.toolResult;
434
+ if (parsed.success && parsed.agentName) {
435
+ return parsed.agentName;
436
+ }
437
+ }
438
+ return null;
439
+ }
440
+ catch (err) {
441
+ process.stderr.write(`\nouro hatch error: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
442
+ coldRl.close();
443
+ return null;
444
+ }
445
+ finally {
446
+ // Clear specialist config/identity so the hatched agent gets its own
447
+ setAgentConfigOverride(null);
448
+ const { resetProviderRuntime } = await Promise.resolve().then(() => __importStar(require("../core")));
449
+ resetProviderRuntime();
450
+ const { resetConfigCache } = await Promise.resolve().then(() => __importStar(require("../config")));
451
+ resetConfigCache();
452
+ // Restore default logging
453
+ const { setRuntimeLogger: restoreLogger } = await Promise.resolve().then(() => __importStar(require("../../nerves/runtime")));
454
+ restoreLogger(null);
455
+ // Clean up temp dir if it still exists
456
+ try {
457
+ if (fs.existsSync(tempDir)) {
458
+ fs.rmSync(tempDir, { recursive: true, force: true });
459
+ }
460
+ }
461
+ catch {
462
+ // Best effort cleanup
463
+ }
464
+ }
465
+ }
466
+ /* v8 ignore stop */
467
+ // ── Factory ──
468
+ function createDefaultOuroCliDeps(socketPath = socket_client_1.DEFAULT_DAEMON_SOCKET_PATH) {
469
+ return {
470
+ socketPath,
471
+ sendCommand: socket_client_1.sendDaemonCommand,
472
+ startDaemonProcess: defaultStartDaemonProcess,
473
+ writeStdout: defaultWriteStdout,
474
+ checkSocketAlive: socket_client_1.checkDaemonSocketAlive,
475
+ cleanupStaleSocket: defaultCleanupStaleSocket,
476
+ fallbackPendingMessage: defaultFallbackPendingMessage,
477
+ listDiscoveredAgents: defaultListDiscoveredAgents,
478
+ runHatchFlow: hatch_flow_1.runHatchFlow,
479
+ promptInput: defaultPromptInput,
480
+ runSerpentGuide: defaultRunSerpentGuide,
481
+ runAuthFlow: auth_flow_1.runRuntimeAuthFlow,
482
+ registerOuroBundleType: ouro_uti_1.registerOuroBundleUti,
483
+ installOuroCommand: ouro_path_installer_1.installOuroCommand,
484
+ /* v8 ignore start -- self-healing: ensures active symlink matches running runtime version @preserve */
485
+ ensureCurrentVersionInstalled: () => {
486
+ const linkedVersion = (0, ouro_version_manager_1.getCurrentVersion)({});
487
+ const version = (0, bundle_manifest_1.getPackageVersion)();
488
+ if (linkedVersion === version)
489
+ return;
490
+ (0, ouro_version_manager_1.ensureLayout)({});
491
+ const cliHome = (0, ouro_version_manager_1.getOuroCliHome)();
492
+ const versionEntry = path.join(cliHome, "versions", version, "node_modules", "@ouro.bot", "cli", "dist", "heart", "daemon", "ouro-entry.js");
493
+ if (!fs.existsSync(versionEntry)) {
494
+ (0, ouro_version_manager_1.installVersion)(version, {});
495
+ }
496
+ (0, ouro_version_manager_1.activateVersion)(version, {});
497
+ },
498
+ /* v8 ignore stop */
499
+ /* v8 ignore start -- CLI version management defaults: integration code @preserve */
500
+ checkForCliUpdate: async () => {
501
+ const { checkForUpdate } = await Promise.resolve().then(() => __importStar(require("../versioning/update-checker")));
502
+ return checkForUpdate((0, bundle_manifest_1.getPackageVersion)(), {
503
+ fetchRegistryJson: async () => {
504
+ const res = await fetch("https://registry.npmjs.org/@ouro.bot/cli");
505
+ return res.json();
506
+ },
507
+ distTag: "alpha",
508
+ });
509
+ },
510
+ installCliVersion: async (version) => { (0, ouro_version_manager_1.installVersion)(version, {}); },
511
+ activateCliVersion: (version) => { (0, ouro_version_manager_1.activateVersion)(version, {}); },
512
+ getCurrentCliVersion: () => (0, ouro_version_manager_1.getCurrentVersion)({}),
513
+ getPreviousCliVersion: () => (0, ouro_version_manager_1.getPreviousVersion)({}),
514
+ listCliVersions: () => (0, ouro_version_manager_1.listInstalledVersions)({}),
515
+ reExecFromNewVersion: (reArgs) => {
516
+ const entry = path.join((0, ouro_version_manager_1.getOuroCliHome)(), "CurrentVersion", "node_modules", "@ouro.bot", "cli", "dist", "heart", "daemon", "ouro-entry.js");
517
+ require("child_process").execFileSync("node", [entry, ...reArgs], { stdio: "inherit" });
518
+ process.exit(0);
519
+ },
520
+ /* v8 ignore stop */
521
+ syncGlobalOuroBotWrapper: ouro_bot_global_installer_1.syncGlobalOuroBotWrapper,
522
+ ensureSkillManagement: skill_management_installer_1.ensureSkillManagement,
523
+ ensureDaemonBootPersistence: defaultEnsureDaemonBootPersistence,
524
+ /* v8 ignore start -- dev-mode defaults: tests inject mocks for mode detection and binary resolution @preserve */
525
+ detectMode: () => (0, runtime_mode_1.detectRuntimeMode)((0, identity_1.getRepoRoot)()),
526
+ getInstalledBinaryPath: () => {
527
+ const cliHome = (0, ouro_version_manager_1.getOuroCliHome)();
528
+ const binaryPath = path.join(cliHome, "bin", "ouro");
529
+ return fs.existsSync(binaryPath) ? binaryPath : null;
530
+ },
531
+ execInstalledBinary: (binaryPath, binArgs) => {
532
+ const { execFileSync } = require("child_process");
533
+ execFileSync(binaryPath, binArgs, { stdio: "inherit" });
534
+ process.exit(0);
535
+ },
536
+ /* v8 ignore stop */
537
+ /* v8 ignore next 3 -- integration: launches interactive CLI session @preserve */
538
+ startChat: async (agentName) => {
539
+ const { main } = await Promise.resolve().then(() => __importStar(require("../../senses/cli")));
540
+ await main(agentName);
541
+ },
542
+ scanSessions: async () => {
543
+ const agentName = (0, identity_1.getAgentName)();
544
+ const agentRoot = (0, identity_1.getAgentRoot)(agentName);
545
+ return (0, session_activity_1.listSessionActivity)({
546
+ sessionsDir: path.join(agentRoot, "state", "sessions"),
547
+ friendsDir: path.join(agentRoot, "friends"),
548
+ agentName,
549
+ }).map((entry) => ({
550
+ friendId: entry.friendId,
551
+ friendName: entry.friendName,
552
+ channel: entry.channel,
553
+ lastActivity: entry.lastActivityAt,
554
+ }));
555
+ },
556
+ };
557
+ }