@ouro.bot/cli 0.1.0-alpha.36 → 0.1.0-alpha.360

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 (326) hide show
  1. package/README.md +194 -184
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  5. package/changelog.json +2149 -0
  6. package/dist/arc/attention-types.js +8 -0
  7. package/dist/arc/cares.js +140 -0
  8. package/dist/arc/episodes.js +117 -0
  9. package/dist/arc/intentions.js +133 -0
  10. package/dist/arc/json-store.js +117 -0
  11. package/dist/arc/obligations.js +237 -0
  12. package/dist/arc/packets.js +193 -0
  13. package/dist/arc/presence.js +185 -0
  14. package/dist/arc/task-lifecycle.js +65 -0
  15. package/dist/heart/active-work.js +832 -0
  16. package/dist/heart/agent-entry.js +37 -2
  17. package/dist/heart/attachments/image-normalize.js +194 -0
  18. package/dist/heart/attachments/materialize.js +97 -0
  19. package/dist/heart/attachments/originals.js +88 -0
  20. package/dist/heart/attachments/render.js +29 -0
  21. package/dist/heart/attachments/sources/adapter.js +2 -0
  22. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  23. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  24. package/dist/heart/attachments/sources/index.js +16 -0
  25. package/dist/heart/attachments/store.js +103 -0
  26. package/dist/heart/attachments/types.js +93 -0
  27. package/dist/heart/auth/auth-flow.js +463 -0
  28. package/dist/heart/bridges/manager.js +358 -0
  29. package/dist/heart/bridges/state-machine.js +135 -0
  30. package/dist/heart/bridges/store.js +123 -0
  31. package/dist/heart/bundle-state.js +168 -0
  32. package/dist/heart/commitments.js +111 -0
  33. package/dist/heart/config-registry.js +304 -0
  34. package/dist/heart/config.js +53 -21
  35. package/dist/heart/core.js +743 -252
  36. package/dist/heart/cross-chat-delivery.js +131 -0
  37. package/dist/heart/daemon/agent-config-check.js +561 -0
  38. package/dist/heart/daemon/agent-discovery.js +79 -3
  39. package/dist/heart/daemon/agent-service.js +360 -0
  40. package/dist/heart/daemon/agentic-repair.js +185 -0
  41. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  42. package/dist/heart/daemon/cadence.js +70 -0
  43. package/dist/heart/daemon/cli-defaults.js +591 -0
  44. package/dist/heart/daemon/cli-exec.js +2649 -0
  45. package/dist/heart/daemon/cli-help.js +306 -0
  46. package/dist/heart/daemon/cli-parse.js +913 -0
  47. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  48. package/dist/heart/daemon/cli-render.js +560 -0
  49. package/dist/heart/daemon/cli-types.js +8 -0
  50. package/dist/heart/daemon/daemon-cli.js +30 -1171
  51. package/dist/heart/daemon/daemon-entry.js +358 -3
  52. package/dist/heart/daemon/daemon-health.js +141 -0
  53. package/dist/heart/daemon/daemon-runtime-sync.js +157 -12
  54. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  55. package/dist/heart/daemon/daemon.js +757 -58
  56. package/dist/heart/daemon/doctor-types.js +8 -0
  57. package/dist/heart/daemon/doctor.js +465 -0
  58. package/dist/heart/daemon/health-monitor.js +79 -1
  59. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  60. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  61. package/dist/heart/daemon/http-health-probe.js +80 -0
  62. package/dist/heart/daemon/inner-status.js +89 -0
  63. package/dist/heart/daemon/interactive-repair.js +91 -0
  64. package/dist/heart/daemon/launchd.js +46 -9
  65. package/dist/heart/daemon/log-tailer.js +82 -12
  66. package/dist/heart/daemon/logs-prune.js +105 -0
  67. package/dist/heart/daemon/message-router.js +17 -8
  68. package/dist/heart/daemon/os-cron-deps.js +134 -0
  69. package/dist/heart/daemon/ouro-bot-entry.js +1 -1
  70. package/dist/heart/daemon/process-manager.js +201 -0
  71. package/dist/heart/daemon/provider-discovery.js +140 -0
  72. package/dist/heart/daemon/pulse.js +475 -0
  73. package/dist/heart/daemon/run-hooks.js +2 -0
  74. package/dist/heart/daemon/runtime-logging.js +67 -16
  75. package/dist/heart/daemon/runtime-metadata.js +101 -0
  76. package/dist/heart/daemon/runtime-mode.js +67 -0
  77. package/dist/heart/daemon/safe-mode.js +161 -0
  78. package/dist/heart/daemon/sense-manager.js +72 -3
  79. package/dist/heart/daemon/session-id-resolver.js +131 -0
  80. package/dist/heart/daemon/skill-management-installer.js +94 -0
  81. package/dist/heart/daemon/socket-client.js +307 -0
  82. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  83. package/dist/heart/daemon/startup-tui.js +237 -0
  84. package/dist/heart/daemon/task-scheduler.js +3 -25
  85. package/dist/heart/daemon/thoughts.js +510 -0
  86. package/dist/heart/daemon/up-progress.js +135 -0
  87. package/dist/heart/delegation.js +62 -0
  88. package/dist/heart/habits/habit-migration.js +181 -0
  89. package/dist/heart/habits/habit-parser.js +140 -0
  90. package/dist/heart/habits/habit-scheduler.js +371 -0
  91. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -120
  92. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  93. package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
  94. package/dist/heart/{daemon → hatch}/specialist-tools.js +56 -10
  95. package/dist/heart/identity.js +154 -59
  96. package/dist/heart/kept-notes.js +357 -0
  97. package/dist/heart/kicks.js +2 -20
  98. package/dist/heart/machine-identity.js +161 -0
  99. package/dist/heart/mcp/mcp-server.js +653 -0
  100. package/dist/heart/migrate-config.js +127 -0
  101. package/dist/heart/model-capabilities.js +59 -0
  102. package/dist/heart/outlook/outlook-http-hooks.js +64 -0
  103. package/dist/heart/outlook/outlook-http-response.js +7 -0
  104. package/dist/heart/outlook/outlook-http-routes.js +232 -0
  105. package/dist/heart/outlook/outlook-http-static.js +99 -0
  106. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  107. package/dist/heart/outlook/outlook-http.js +99 -0
  108. package/dist/heart/outlook/outlook-read.js +28 -0
  109. package/dist/heart/outlook/outlook-types.js +27 -0
  110. package/dist/heart/outlook/outlook-view.js +195 -0
  111. package/dist/heart/outlook/readers/agent-machine.js +359 -0
  112. package/dist/heart/outlook/readers/continuity-readers.js +332 -0
  113. package/dist/heart/outlook/readers/runtime-readers.js +660 -0
  114. package/dist/heart/outlook/readers/sessions.js +232 -0
  115. package/dist/heart/outlook/readers/shared.js +111 -0
  116. package/dist/heart/progress-story.js +42 -0
  117. package/dist/heart/provider-attempt.js +133 -0
  118. package/dist/heart/provider-binding-resolver.js +240 -0
  119. package/dist/heart/provider-credential-pool.js +395 -0
  120. package/dist/heart/provider-failover.js +274 -0
  121. package/dist/heart/provider-models.js +81 -0
  122. package/dist/heart/provider-ping.js +227 -0
  123. package/dist/heart/provider-state.js +208 -0
  124. package/dist/heart/provider-visibility.js +183 -0
  125. package/dist/heart/providers/anthropic-token.js +163 -0
  126. package/dist/heart/providers/anthropic.js +177 -50
  127. package/dist/heart/providers/azure.js +102 -11
  128. package/dist/heart/providers/error-classification.js +63 -0
  129. package/dist/heart/providers/github-copilot.js +145 -0
  130. package/dist/heart/providers/minimax-vlm.js +189 -0
  131. package/dist/heart/providers/minimax.js +28 -6
  132. package/dist/heart/providers/openai-codex.js +38 -23
  133. package/dist/heart/session-activity.js +190 -0
  134. package/dist/heart/session-events.js +855 -0
  135. package/dist/heart/session-transcript.js +167 -0
  136. package/dist/heart/start-of-turn-packet.js +345 -0
  137. package/dist/heart/streaming.js +36 -27
  138. package/dist/heart/sync.js +332 -0
  139. package/dist/heart/target-resolution.js +127 -0
  140. package/dist/heart/tempo.js +93 -0
  141. package/dist/heart/temporal-view.js +41 -0
  142. package/dist/heart/tool-activity-callbacks.js +36 -0
  143. package/dist/heart/tool-description.js +135 -0
  144. package/dist/heart/tool-friction.js +55 -0
  145. package/dist/heart/tool-loop.js +200 -0
  146. package/dist/heart/turn-context.js +362 -0
  147. package/dist/heart/turn-coordinator.js +28 -0
  148. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  149. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  150. package/dist/heart/versioning/ouro-path-installer.js +296 -0
  151. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  152. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  153. package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
  154. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  155. package/dist/mind/bundle-manifest.js +7 -1
  156. package/dist/mind/context.js +141 -94
  157. package/dist/mind/diary-integrity.js +60 -0
  158. package/dist/mind/{memory.js → diary.js} +84 -96
  159. package/dist/mind/embedding-provider.js +60 -0
  160. package/dist/mind/file-state.js +179 -0
  161. package/dist/mind/first-impressions.js +14 -1
  162. package/dist/mind/friends/channel.js +56 -0
  163. package/dist/mind/friends/group-context.js +144 -0
  164. package/dist/mind/friends/resolver.js +38 -1
  165. package/dist/mind/friends/store-file.js +58 -3
  166. package/dist/mind/friends/trust-explanation.js +74 -0
  167. package/dist/mind/friends/types.js +9 -1
  168. package/dist/mind/journal-index.js +161 -0
  169. package/dist/mind/note-search.js +268 -0
  170. package/dist/mind/obligation-steering.js +221 -0
  171. package/dist/mind/pending.js +74 -7
  172. package/dist/mind/prompt.js +1013 -112
  173. package/dist/mind/provenance-trust.js +26 -0
  174. package/dist/mind/scrutiny.js +173 -0
  175. package/dist/mind/token-estimate.js +8 -12
  176. package/dist/nerves/cli-logging.js +7 -1
  177. package/dist/nerves/coverage/audit-rules.js +15 -6
  178. package/dist/nerves/coverage/audit.js +28 -2
  179. package/dist/nerves/coverage/cli.js +1 -1
  180. package/dist/nerves/coverage/file-completeness.js +83 -5
  181. package/dist/nerves/coverage/run-artifacts.js +1 -1
  182. package/dist/nerves/event-buffer.js +111 -0
  183. package/dist/nerves/index.js +224 -4
  184. package/dist/nerves/observation.js +20 -0
  185. package/dist/nerves/redact.js +79 -0
  186. package/dist/nerves/runtime.js +5 -1
  187. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  188. package/dist/outlook-ui/assets/index-xTdv64BV.js +61 -0
  189. package/dist/outlook-ui/index.html +15 -0
  190. package/dist/repertoire/ado-client.js +15 -56
  191. package/dist/repertoire/ado-semantic.js +11 -10
  192. package/dist/repertoire/api-client.js +97 -0
  193. package/dist/repertoire/bitwarden-store.js +319 -0
  194. package/dist/repertoire/bundle-templates.js +72 -0
  195. package/dist/repertoire/bw-installer.js +79 -0
  196. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  197. package/dist/repertoire/coding/context-pack.js +330 -0
  198. package/dist/repertoire/coding/feedback.js +197 -30
  199. package/dist/repertoire/coding/manager.js +158 -9
  200. package/dist/repertoire/coding/spawner.js +55 -9
  201. package/dist/repertoire/coding/tools.js +170 -7
  202. package/dist/repertoire/commerce-errors.js +109 -0
  203. package/dist/repertoire/commerce-self-test.js +156 -0
  204. package/dist/repertoire/credential-access.js +527 -0
  205. package/dist/repertoire/duffel-client.js +185 -0
  206. package/dist/repertoire/github-client.js +14 -55
  207. package/dist/repertoire/graph-client.js +11 -52
  208. package/dist/repertoire/guardrails.js +375 -0
  209. package/dist/repertoire/mcp-client.js +255 -0
  210. package/dist/repertoire/mcp-manager.js +305 -0
  211. package/dist/repertoire/mcp-tools.js +63 -0
  212. package/dist/repertoire/shell-sessions.js +133 -0
  213. package/dist/repertoire/skills.js +15 -24
  214. package/dist/repertoire/stripe-client.js +131 -0
  215. package/dist/repertoire/tasks/board.js +43 -5
  216. package/dist/repertoire/tasks/fix.js +182 -0
  217. package/dist/repertoire/tasks/index.js +28 -10
  218. package/dist/repertoire/tasks/lifecycle.js +2 -2
  219. package/dist/repertoire/tasks/parser.js +3 -2
  220. package/dist/repertoire/tasks/scanner.js +194 -37
  221. package/dist/repertoire/tasks/transitions.js +16 -79
  222. package/dist/repertoire/tool-results.js +29 -0
  223. package/dist/repertoire/tools-attachments.js +316 -0
  224. package/dist/repertoire/tools-base.js +45 -771
  225. package/dist/repertoire/tools-bluebubbles.js +1 -0
  226. package/dist/repertoire/tools-bridge.js +141 -0
  227. package/dist/repertoire/tools-bundle.js +984 -0
  228. package/dist/repertoire/tools-config.js +185 -0
  229. package/dist/repertoire/tools-continuity.js +248 -0
  230. package/dist/repertoire/tools-credential.js +182 -0
  231. package/dist/repertoire/tools-files.js +342 -0
  232. package/dist/repertoire/tools-flight.js +224 -0
  233. package/dist/repertoire/tools-flow.js +105 -0
  234. package/dist/repertoire/tools-github.js +1 -7
  235. package/dist/repertoire/tools-notes.js +376 -0
  236. package/dist/repertoire/tools-session.js +739 -0
  237. package/dist/repertoire/tools-shell.js +120 -0
  238. package/dist/repertoire/tools-stripe.js +180 -0
  239. package/dist/repertoire/tools-surface.js +243 -0
  240. package/dist/repertoire/tools-teams.js +12 -62
  241. package/dist/repertoire/tools-travel.js +125 -0
  242. package/dist/repertoire/tools-user-profile.js +144 -0
  243. package/dist/repertoire/tools-vault.js +110 -0
  244. package/dist/repertoire/tools.js +144 -138
  245. package/dist/repertoire/travel-api-client.js +360 -0
  246. package/dist/repertoire/user-profile.js +118 -0
  247. package/dist/repertoire/vault-setup.js +241 -0
  248. package/dist/scripts/claude-code-hook.js +41 -0
  249. package/dist/scripts/claude-code-stop-hook.js +47 -0
  250. package/dist/senses/attention-queue.js +116 -0
  251. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  252. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  253. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +225 -9
  254. package/dist/senses/bluebubbles/entry.js +13 -0
  255. package/dist/senses/bluebubbles/inbound-log.js +113 -0
  256. package/dist/senses/bluebubbles/index.js +1616 -0
  257. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  258. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +43 -12
  259. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  260. package/dist/senses/bluebubbles/replay.js +129 -0
  261. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  262. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  263. package/dist/senses/cli/bracketed-paste.js +82 -0
  264. package/dist/senses/cli/image-paste.js +287 -0
  265. package/dist/senses/cli/image-ref-navigation.js +75 -0
  266. package/dist/senses/cli/ink-app.js +156 -0
  267. package/dist/senses/cli/inline-diff.js +64 -0
  268. package/dist/senses/cli/input-keys.js +174 -0
  269. package/dist/senses/cli/kill-ring.js +86 -0
  270. package/dist/senses/cli/message-list.js +51 -0
  271. package/dist/senses/cli/ouro-tui.js +605 -0
  272. package/dist/senses/cli/spinner-imperative.js +135 -0
  273. package/dist/senses/cli/spinner.js +101 -0
  274. package/dist/senses/cli/status-line.js +60 -0
  275. package/dist/senses/cli/streaming-markdown.js +526 -0
  276. package/dist/senses/cli/tool-display.js +83 -0
  277. package/dist/senses/cli/tool-render.js +85 -0
  278. package/dist/senses/cli/tui-store.js +240 -0
  279. package/dist/senses/cli/virtual-list.js +35 -0
  280. package/dist/senses/cli-entry.js +1 -1
  281. package/dist/senses/cli-layout.js +187 -0
  282. package/dist/senses/cli.js +587 -249
  283. package/dist/senses/commands.js +66 -3
  284. package/dist/senses/continuity.js +94 -0
  285. package/dist/senses/habit-turn-message.js +108 -0
  286. package/dist/senses/inner-dialog-worker.js +112 -19
  287. package/dist/senses/inner-dialog.js +633 -86
  288. package/dist/senses/pipeline.js +603 -0
  289. package/dist/senses/proactive-content-guard.js +51 -0
  290. package/dist/senses/shared-turn.js +199 -0
  291. package/dist/senses/surface-tool.js +68 -0
  292. package/dist/senses/teams.js +690 -160
  293. package/dist/senses/trust-gate.js +112 -2
  294. package/package.json +29 -7
  295. package/skills/agent-commerce.md +106 -0
  296. package/skills/browser-navigation.md +110 -0
  297. package/skills/commerce-setup-guide.md +116 -0
  298. package/skills/commerce-setup.md +84 -0
  299. package/skills/configure-dev-tools.md +81 -0
  300. package/skills/travel-planning.md +138 -0
  301. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  302. package/dist/heart/daemon/subagent-installer.js +0 -134
  303. package/dist/mind/associative-recall.js +0 -197
  304. package/dist/senses/bluebubbles-entry.js +0 -11
  305. package/dist/senses/bluebubbles.js +0 -558
  306. package/dist/senses/debug-activity.js +0 -127
  307. package/subagents/README.md +0 -73
  308. package/subagents/work-doer.md +0 -235
  309. package/subagents/work-merger.md +0 -618
  310. package/subagents/work-planner.md +0 -382
  311. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  312. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  313. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  314. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  315. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  316. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  317. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  318. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  319. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  320. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  321. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  322. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  323. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  324. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  325. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  326. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,913 @@
1
+ "use strict";
2
+ /**
3
+ * CLI argument parsing — converts argv into OuroCliCommand objects.
4
+ *
5
+ * Pure functions: no side effects, no daemon communication.
6
+ * Each command group has its own parser; parseOuroCommand dispatches.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.extractAgentFlag = extractAgentFlag;
10
+ exports.extractFacingFlag = extractFacingFlag;
11
+ exports.facingToProviderLane = facingToProviderLane;
12
+ exports.isAgentProvider = isAgentProvider;
13
+ exports.usage = usage;
14
+ exports.parseMcpServeCommand = parseMcpServeCommand;
15
+ exports.parseOuroCommand = parseOuroCommand;
16
+ const types_1 = require("../../mind/friends/types");
17
+ const cli_help_1 = require("./cli-help");
18
+ // ── Shared helpers ──
19
+ function extractAgentFlag(args) {
20
+ const idx = args.indexOf("--agent");
21
+ if (idx === -1 || idx + 1 >= args.length)
22
+ return { rest: args };
23
+ const agent = args[idx + 1];
24
+ const rest = [...args.slice(0, idx), ...args.slice(idx + 2)];
25
+ return { agent, rest };
26
+ }
27
+ function extractFacingFlag(args) {
28
+ const idx = args.indexOf("--facing");
29
+ if (idx === -1 || idx + 1 >= args.length)
30
+ return { rest: args };
31
+ const value = args[idx + 1];
32
+ if (value !== "human" && value !== "agent") {
33
+ throw new Error(`--facing must be 'human' or 'agent'`);
34
+ }
35
+ const rest = [...args.slice(0, idx), ...args.slice(idx + 2)];
36
+ return { facing: value, rest };
37
+ }
38
+ function facingToProviderLane(facing) {
39
+ return facing === "human" ? "outward" : "inner";
40
+ }
41
+ function isProviderLane(value) {
42
+ return value === "outward" || value === "inner";
43
+ }
44
+ function extractLaneFlag(args) {
45
+ const idx = args.indexOf("--lane");
46
+ if (idx === -1 || idx + 1 >= args.length)
47
+ return { rest: args };
48
+ const value = args[idx + 1];
49
+ if (!isProviderLane(value)) {
50
+ throw new Error("--lane must be 'outward' or 'inner'");
51
+ }
52
+ const rest = [...args.slice(0, idx), ...args.slice(idx + 2)];
53
+ return { lane: value, rest };
54
+ }
55
+ function isAgentProvider(value) {
56
+ return value === "azure" || value === "anthropic" || value === "minimax" || value === "openai-codex" || value === "github-copilot";
57
+ }
58
+ function usage() {
59
+ return [
60
+ "Usage:",
61
+ " ouro [up] [--no-repair]",
62
+ " ouro dev [--repo-path <path>] [--clone [--clone-path <path>]]",
63
+ " ouro stop|down|status|logs|hatch",
64
+ " ouro status --agent <name>",
65
+ " ouro use --agent <name> --lane outward|inner --provider <provider> --model <model> [--force]",
66
+ " ouro check --agent <name> --lane outward|inner",
67
+ " ouro outlook [--json]",
68
+ " ouro -v|--version",
69
+ " ouro config model --agent <name> <model-name>",
70
+ " ouro config models --agent <name>",
71
+ " ouro auth --agent <name> [--provider <provider>]",
72
+ " ouro auth verify --agent <name> [--provider <provider>]",
73
+ " ouro auth switch --agent <name> --provider <provider>",
74
+ " ouro chat <agent>",
75
+ " ouro msg --to <agent> [--session <id>] [--task <ref>] <message>",
76
+ " ouro poke <agent> --task <task-id>",
77
+ " ouro poke <agent> --habit <name>",
78
+ " ouro habit list [--agent <name>]",
79
+ " ouro habit create [--agent <name>] <name> [--cadence <interval>]",
80
+ " ouro link <agent> --friend <id> --provider <provider> --external-id <external-id>",
81
+ " ouro bluebubbles replay --agent <name> --message-guid <guid> [--event-type new-message|updated-message] [--json]",
82
+ " ouro task board [<status>] [--agent <name>]",
83
+ " ouro task create <title> [--type <type>] [--agent <name>]",
84
+ " ouro task update <id> <status> [--agent <name>]",
85
+ " ouro task show <id> [--agent <name>]",
86
+ " ouro task fix [--safe|--all] [<id> [--option <N>]] [--agent <name>]",
87
+ " ouro task actionable|deps|sessions [--agent <name>]",
88
+ " ouro reminder create <title> --body <body> [--at <iso>] [--cadence <interval>] [--category <category>] [--agent <name>]",
89
+ " ouro friend list [--agent <name>]",
90
+ " ouro friend show <id> [--agent <name>]",
91
+ " ouro friend create --name <name> [--trust <level>] [--agent <name>]",
92
+ " ouro friend update <id> --trust <level> [--agent <name>]",
93
+ " ouro thoughts [--last <n>] [--json] [--follow] [--agent <name>]",
94
+ " ouro inner [--agent <name>]",
95
+ " ouro friend link <agent> --friend <id> --provider <p> --external-id <eid>",
96
+ " ouro friend unlink <agent> --friend <id> --provider <p> --external-id <eid>",
97
+ " ouro whoami [--agent <name>]",
98
+ " ouro session list [--agent <name>]",
99
+ " ouro mcp list",
100
+ " ouro mcp call <server> <tool> [--args '{...}']",
101
+ " ouro rollback [<version>]",
102
+ " ouro versions",
103
+ " ouro doctor",
104
+ ].join("\n");
105
+ }
106
+ // ── Per-group parsers ──
107
+ function parseMessageCommand(args) {
108
+ let to;
109
+ let sessionId;
110
+ let taskRef;
111
+ const messageParts = [];
112
+ for (let i = 0; i < args.length; i += 1) {
113
+ const token = args[i];
114
+ if (token === "--to") {
115
+ to = args[i + 1];
116
+ i += 1;
117
+ continue;
118
+ }
119
+ if (token === "--session") {
120
+ sessionId = args[i + 1];
121
+ i += 1;
122
+ continue;
123
+ }
124
+ if (token === "--task") {
125
+ taskRef = args[i + 1];
126
+ i += 1;
127
+ continue;
128
+ }
129
+ messageParts.push(token);
130
+ }
131
+ const content = messageParts.join(" ").trim();
132
+ if (!to || !content)
133
+ throw new Error(`Usage\n${usage()}`);
134
+ return {
135
+ kind: "message.send",
136
+ from: "ouro-cli",
137
+ to,
138
+ content,
139
+ sessionId,
140
+ taskRef,
141
+ };
142
+ }
143
+ function parsePokeCommand(args) {
144
+ const agent = args[0];
145
+ if (!agent)
146
+ throw new Error(`Usage\n${usage()}`);
147
+ let taskId;
148
+ let habitName;
149
+ for (let i = 1; i < args.length; i += 1) {
150
+ if (args[i] === "--task") {
151
+ taskId = args[i + 1];
152
+ i += 1;
153
+ }
154
+ if (args[i] === "--habit") {
155
+ habitName = args[i + 1];
156
+ i += 1;
157
+ }
158
+ }
159
+ // --habit takes priority over --task
160
+ if (habitName)
161
+ return { kind: "habit.poke", agent, habitName };
162
+ if (!taskId)
163
+ throw new Error(`Usage\n${usage()}`);
164
+ return { kind: "task.poke", agent, taskId };
165
+ }
166
+ function parseHabitCommand(args) {
167
+ const { agent, rest } = extractAgentFlag(args);
168
+ const sub = rest[0];
169
+ if (sub === "list") {
170
+ return { kind: "habit.list", ...(agent ? { agent } : {}) };
171
+ }
172
+ if (sub === "create") {
173
+ const nameArgs = rest.slice(1);
174
+ let name;
175
+ let cadence;
176
+ const positional = [];
177
+ for (let i = 0; i < nameArgs.length; i++) {
178
+ if (nameArgs[i] === "--cadence" && nameArgs[i + 1]) {
179
+ cadence = nameArgs[++i];
180
+ continue;
181
+ }
182
+ /* v8 ignore start -- defensive: --agent already extracted by extractAgentFlag; guard prevents regression if parsing flow changes @preserve */
183
+ if (nameArgs[i] === "--agent" && nameArgs[i + 1]) {
184
+ i++; // skip --agent value (already extracted)
185
+ continue;
186
+ }
187
+ /* v8 ignore stop */
188
+ positional.push(nameArgs[i]);
189
+ }
190
+ name = positional[0];
191
+ if (!name)
192
+ throw new Error(`Usage\n${usage()}`);
193
+ return { kind: "habit.create", name, ...(agent ? { agent } : {}), ...(cadence ? { cadence } : {}) };
194
+ }
195
+ throw new Error(`Usage\n${usage()}`);
196
+ }
197
+ function parseLinkCommand(args, kind = "friend.link") {
198
+ const agent = args[0];
199
+ if (!agent)
200
+ throw new Error(`Usage\n${usage()}`);
201
+ let friendId;
202
+ let providerRaw;
203
+ let externalId;
204
+ for (let i = 1; i < args.length; i += 1) {
205
+ const token = args[i];
206
+ if (token === "--friend") {
207
+ friendId = args[i + 1];
208
+ i += 1;
209
+ continue;
210
+ }
211
+ if (token === "--provider") {
212
+ providerRaw = args[i + 1];
213
+ i += 1;
214
+ continue;
215
+ }
216
+ if (token === "--external-id") {
217
+ externalId = args[i + 1];
218
+ i += 1;
219
+ continue;
220
+ }
221
+ }
222
+ if (!friendId || !providerRaw || !externalId) {
223
+ throw new Error(`Usage\n${usage()}`);
224
+ }
225
+ if (!(0, types_1.isIdentityProvider)(providerRaw)) {
226
+ throw new Error(`Unknown identity provider '${providerRaw}'. Use aad|local|teams-conversation.`);
227
+ }
228
+ return {
229
+ kind,
230
+ agent,
231
+ friendId,
232
+ provider: providerRaw,
233
+ externalId,
234
+ };
235
+ }
236
+ function parseHatchCommand(args) {
237
+ let agentName;
238
+ let humanName;
239
+ let providerRaw;
240
+ let migrationPath;
241
+ const credentials = {};
242
+ for (let i = 0; i < args.length; i += 1) {
243
+ const token = args[i];
244
+ if (token === "--agent") {
245
+ agentName = args[i + 1];
246
+ i += 1;
247
+ continue;
248
+ }
249
+ if (token === "--human") {
250
+ humanName = args[i + 1];
251
+ i += 1;
252
+ continue;
253
+ }
254
+ if (token === "--provider") {
255
+ providerRaw = args[i + 1];
256
+ i += 1;
257
+ continue;
258
+ }
259
+ if (token === "--setup-token") {
260
+ credentials.setupToken = args[i + 1];
261
+ i += 1;
262
+ continue;
263
+ }
264
+ if (token === "--oauth-token") {
265
+ credentials.oauthAccessToken = args[i + 1];
266
+ i += 1;
267
+ continue;
268
+ }
269
+ if (token === "--api-key") {
270
+ credentials.apiKey = args[i + 1];
271
+ i += 1;
272
+ continue;
273
+ }
274
+ if (token === "--endpoint") {
275
+ credentials.endpoint = args[i + 1];
276
+ i += 1;
277
+ continue;
278
+ }
279
+ if (token === "--deployment") {
280
+ credentials.deployment = args[i + 1];
281
+ i += 1;
282
+ continue;
283
+ }
284
+ if (token === "--migration-path") {
285
+ migrationPath = args[i + 1];
286
+ i += 1;
287
+ continue;
288
+ }
289
+ }
290
+ if (providerRaw && !isAgentProvider(providerRaw)) {
291
+ throw new Error("Unknown provider. Use azure|anthropic|minimax|openai-codex|github-copilot.");
292
+ }
293
+ const provider = providerRaw && isAgentProvider(providerRaw) ? providerRaw : undefined;
294
+ return {
295
+ kind: "hatch.start",
296
+ agentName,
297
+ humanName,
298
+ provider,
299
+ credentials: Object.keys(credentials).length > 0 ? credentials : undefined,
300
+ migrationPath,
301
+ };
302
+ }
303
+ function parseTaskCommand(args) {
304
+ const { agent, rest: cleaned } = extractAgentFlag(args);
305
+ const [sub, ...rest] = cleaned;
306
+ if (!sub)
307
+ throw new Error(`Usage\n${usage()}`);
308
+ if (sub === "board") {
309
+ const status = rest[0];
310
+ return status
311
+ ? { kind: "task.board", status, ...(agent ? { agent } : {}) }
312
+ : { kind: "task.board", ...(agent ? { agent } : {}) };
313
+ }
314
+ if (sub === "create") {
315
+ const title = rest[0];
316
+ if (!title)
317
+ throw new Error(`Usage\n${usage()}`);
318
+ let type;
319
+ for (let i = 1; i < rest.length; i++) {
320
+ if (rest[i] === "--type" && rest[i + 1]) {
321
+ type = rest[i + 1];
322
+ i += 1;
323
+ }
324
+ }
325
+ return type
326
+ ? { kind: "task.create", title, type, ...(agent ? { agent } : {}) }
327
+ : { kind: "task.create", title, ...(agent ? { agent } : {}) };
328
+ }
329
+ if (sub === "update") {
330
+ const id = rest[0];
331
+ const status = rest[1];
332
+ if (!id || !status)
333
+ throw new Error(`Usage\n${usage()}`);
334
+ return { kind: "task.update", id, status, ...(agent ? { agent } : {}) };
335
+ }
336
+ if (sub === "show") {
337
+ const id = rest[0];
338
+ if (!id)
339
+ throw new Error(`Usage\n${usage()}`);
340
+ return { kind: "task.show", id, ...(agent ? { agent } : {}) };
341
+ }
342
+ if (sub === "actionable")
343
+ return { kind: "task.actionable", ...(agent ? { agent } : {}) };
344
+ if (sub === "deps")
345
+ return { kind: "task.deps", ...(agent ? { agent } : {}) };
346
+ if (sub === "sessions")
347
+ return { kind: "task.sessions", ...(agent ? { agent } : {}) };
348
+ if (sub === "fix") {
349
+ // fix --safe | fix --all | fix <id> [--option N] | fix (dry-run)
350
+ if (rest.length === 0)
351
+ return { kind: "task.fix", mode: "dry-run", ...(agent ? { agent } : {}) };
352
+ const first = rest[0];
353
+ if (first === "--safe" || first === "--all") {
354
+ return { kind: "task.fix", mode: "safe", ...(agent ? { agent } : {}) };
355
+ }
356
+ // first arg is an issue ID (contains a colon, e.g. schema-missing-kind:one-shots/foo.md)
357
+ const issueId = first;
358
+ let option;
359
+ for (let i = 1; i < rest.length; i++) {
360
+ if (rest[i] === "--option" && rest[i + 1]) {
361
+ option = parseInt(rest[i + 1], 10);
362
+ i += 1;
363
+ }
364
+ }
365
+ return {
366
+ kind: "task.fix",
367
+ mode: "single",
368
+ issueId,
369
+ ...(option !== undefined ? { option } : {}),
370
+ ...(agent ? { agent } : {}),
371
+ };
372
+ }
373
+ throw new Error(`Usage\n${usage()}`);
374
+ }
375
+ function parseAuthCommand(args) {
376
+ const first = args[0];
377
+ // Support both positional (`auth switch`) and flag (`auth --switch`) forms
378
+ if (first === "verify" || first === "switch" || first === "--verify" || first === "--switch") {
379
+ const subcommand = first.replace(/^--/, "");
380
+ const { agent, rest: afterAgent } = extractAgentFlag(args.slice(1));
381
+ const { facing, rest } = extractFacingFlag(afterAgent);
382
+ let provider;
383
+ /* v8 ignore start -- provider flag parsing: branches tested via CLI parsing tests @preserve */
384
+ for (let i = 0; i < rest.length; i += 1) {
385
+ if (rest[i] === "--provider") {
386
+ const value = rest[i + 1];
387
+ if (!isAgentProvider(value))
388
+ throw new Error(`Usage\n${usage()}`);
389
+ provider = value;
390
+ i += 1;
391
+ continue;
392
+ }
393
+ }
394
+ /* v8 ignore stop */
395
+ /* v8 ignore next -- defensive: agent always provided in tests @preserve */
396
+ if (!agent)
397
+ throw new Error(`Usage\n${usage()}`);
398
+ if (subcommand === "switch") {
399
+ if (!provider)
400
+ throw new Error(`auth switch requires --provider.\n${usage()}`);
401
+ return facing ? { kind: "auth.switch", agent, provider, facing } : { kind: "auth.switch", agent, provider };
402
+ }
403
+ return provider ? { kind: "auth.verify", agent, provider } : { kind: "auth.verify", agent };
404
+ }
405
+ const { agent, rest } = extractAgentFlag(args);
406
+ let provider;
407
+ for (let i = 0; i < rest.length; i += 1) {
408
+ if (rest[i] === "--provider") {
409
+ const value = rest[i + 1];
410
+ if (!isAgentProvider(value))
411
+ throw new Error(`Usage\n${usage()}`);
412
+ provider = value;
413
+ i += 1;
414
+ continue;
415
+ }
416
+ }
417
+ if (!agent) {
418
+ throw new Error([
419
+ "Usage:",
420
+ " ouro auth --agent <name> [--provider <provider>] Set up credentials",
421
+ " ouro auth verify --agent <name> [--provider <p>] Verify credentials work",
422
+ " ouro auth switch --agent <name> --provider <p> Switch active provider",
423
+ ].join("\n"));
424
+ }
425
+ return provider ? { kind: "auth.run", agent, provider } : { kind: "auth.run", agent };
426
+ }
427
+ function parseProviderUseCommand(args) {
428
+ const { agent, rest: afterAgent } = extractAgentFlag(args);
429
+ const { facing, rest: afterFacing } = extractFacingFlag(afterAgent);
430
+ const { lane, rest } = extractLaneFlag(afterFacing);
431
+ let provider;
432
+ let model;
433
+ let force = false;
434
+ for (let i = 0; i < rest.length; i += 1) {
435
+ const token = rest[i];
436
+ if (token === "--provider") {
437
+ const value = rest[i + 1];
438
+ if (!isAgentProvider(value))
439
+ throw new Error(`Usage: ouro use --agent <name> --lane outward|inner --provider <provider> --model <model>`);
440
+ provider = value;
441
+ i += 1;
442
+ continue;
443
+ }
444
+ if (token === "--model") {
445
+ model = rest[i + 1];
446
+ i += 1;
447
+ continue;
448
+ }
449
+ if (token === "--force") {
450
+ force = true;
451
+ continue;
452
+ }
453
+ throw new Error("Usage: ouro use --agent <name> --lane outward|inner --provider <provider> --model <model> [--force]");
454
+ }
455
+ const resolvedLane = lane ?? (facing ? facingToProviderLane(facing) : undefined);
456
+ if (!agent || !resolvedLane || !provider || !model) {
457
+ throw new Error("Usage: ouro use --agent <name> --lane outward|inner --provider <provider> --model <model> [--force]");
458
+ }
459
+ return {
460
+ kind: "provider.use",
461
+ agent,
462
+ lane: resolvedLane,
463
+ provider,
464
+ model,
465
+ ...(force ? { force: true } : {}),
466
+ ...(facing ? { legacyFacing: facing } : {}),
467
+ };
468
+ }
469
+ function parseProviderCheckCommand(args) {
470
+ const { agent, rest: afterAgent } = extractAgentFlag(args);
471
+ const { facing, rest: afterFacing } = extractFacingFlag(afterAgent);
472
+ const { lane, rest } = extractLaneFlag(afterFacing);
473
+ const resolvedLane = lane ?? (facing ? facingToProviderLane(facing) : undefined);
474
+ if (!agent || !resolvedLane || rest.length > 0) {
475
+ throw new Error("Usage: ouro check --agent <name> --lane outward|inner");
476
+ }
477
+ return {
478
+ kind: "provider.check",
479
+ agent,
480
+ lane: resolvedLane,
481
+ ...(facing ? { legacyFacing: facing } : {}),
482
+ };
483
+ }
484
+ function parseReminderCommand(args) {
485
+ const { agent, rest: cleaned } = extractAgentFlag(args);
486
+ const [sub, ...rest] = cleaned;
487
+ if (!sub)
488
+ throw new Error(`Usage\n${usage()}`);
489
+ if (sub === "create") {
490
+ const title = rest[0];
491
+ if (!title)
492
+ throw new Error(`Usage\n${usage()}`);
493
+ let body;
494
+ let scheduledAt;
495
+ let cadence;
496
+ let category;
497
+ let requester;
498
+ for (let i = 1; i < rest.length; i++) {
499
+ if (rest[i] === "--body" && rest[i + 1]) {
500
+ body = rest[i + 1];
501
+ i += 1;
502
+ }
503
+ else if (rest[i] === "--at" && rest[i + 1]) {
504
+ scheduledAt = rest[i + 1];
505
+ i += 1;
506
+ }
507
+ else if (rest[i] === "--cadence" && rest[i + 1]) {
508
+ cadence = rest[i + 1];
509
+ i += 1;
510
+ }
511
+ else if (rest[i] === "--category" && rest[i + 1]) {
512
+ category = rest[i + 1];
513
+ i += 1;
514
+ }
515
+ else if (rest[i] === "--requester" && rest[i + 1]) {
516
+ requester = rest[i + 1];
517
+ i += 1;
518
+ }
519
+ }
520
+ if (!body)
521
+ throw new Error(`Usage\n${usage()}`);
522
+ if (!scheduledAt && !cadence)
523
+ throw new Error(`Usage\n${usage()}`);
524
+ return {
525
+ kind: "reminder.create",
526
+ title,
527
+ body,
528
+ ...(scheduledAt ? { scheduledAt } : {}),
529
+ ...(cadence ? { cadence } : {}),
530
+ ...(category ? { category } : {}),
531
+ ...(requester ? { requester } : {}),
532
+ ...(agent ? { agent } : {}),
533
+ };
534
+ }
535
+ throw new Error(`Usage\n${usage()}`);
536
+ }
537
+ function parseSessionCommand(args) {
538
+ const { agent, rest: cleaned } = extractAgentFlag(args);
539
+ const [sub] = cleaned;
540
+ if (!sub)
541
+ throw new Error(`Usage\n${usage()}`);
542
+ if (sub === "list")
543
+ return { kind: "session.list", ...(agent ? { agent } : {}) };
544
+ throw new Error(`Usage\n${usage()}`);
545
+ }
546
+ function parseAttentionCommand(args) {
547
+ const { agent, rest: cleaned } = extractAgentFlag(args);
548
+ const sub = cleaned[0];
549
+ if (sub === "show" && cleaned[1]) {
550
+ return { kind: "attention.show", id: cleaned[1], ...(agent ? { agent } : {}) };
551
+ }
552
+ if (sub === "history") {
553
+ return { kind: "attention.history", ...(agent ? { agent } : {}) };
554
+ }
555
+ return { kind: "attention.list", ...(agent ? { agent } : {}) };
556
+ }
557
+ function parseThoughtsCommand(args) {
558
+ const { agent, rest: cleaned } = extractAgentFlag(args);
559
+ let last;
560
+ let json = false;
561
+ let follow = false;
562
+ for (let i = 0; i < cleaned.length; i++) {
563
+ if (cleaned[i] === "--last" && i + 1 < cleaned.length) {
564
+ last = Number.parseInt(cleaned[i + 1], 10);
565
+ i++;
566
+ }
567
+ if (cleaned[i] === "--json")
568
+ json = true;
569
+ if (cleaned[i] === "--follow" || cleaned[i] === "-f")
570
+ follow = true;
571
+ }
572
+ return { kind: "thoughts", ...(agent ? { agent } : {}), ...(last ? { last } : {}), ...(json ? { json } : {}), ...(follow ? { follow } : {}) };
573
+ }
574
+ function parseFriendCommand(args) {
575
+ const { agent, rest: cleaned } = extractAgentFlag(args);
576
+ const [sub, ...rest] = cleaned;
577
+ if (!sub)
578
+ throw new Error(`Usage\n${usage()}`);
579
+ if (sub === "list")
580
+ return { kind: "friend.list", ...(agent ? { agent } : {}) };
581
+ if (sub === "show") {
582
+ const friendId = rest[0];
583
+ if (!friendId)
584
+ throw new Error(`Usage\n${usage()}`);
585
+ return { kind: "friend.show", friendId, ...(agent ? { agent } : {}) };
586
+ }
587
+ if (sub === "create") {
588
+ let name;
589
+ let trustLevel;
590
+ for (let i = 0; i < rest.length; i++) {
591
+ if (rest[i] === "--name" && rest[i + 1]) {
592
+ name = rest[i + 1];
593
+ i += 1;
594
+ }
595
+ else if (rest[i] === "--trust" && rest[i + 1]) {
596
+ trustLevel = rest[i + 1];
597
+ i += 1;
598
+ }
599
+ }
600
+ if (!name)
601
+ throw new Error(`Usage\n${usage()}`);
602
+ return {
603
+ kind: "friend.create",
604
+ name,
605
+ ...(trustLevel ? { trustLevel } : {}),
606
+ ...(agent ? { agent } : {}),
607
+ };
608
+ }
609
+ if (sub === "update") {
610
+ const friendId = rest[0];
611
+ if (!friendId)
612
+ throw new Error(`Usage: ouro friend update <id> --trust <level>`);
613
+ let trustLevel;
614
+ /* v8 ignore start -- flag parsing loop: tested via CLI parsing tests @preserve */
615
+ for (let i = 1; i < rest.length; i++) {
616
+ if (rest[i] === "--trust" && rest[i + 1]) {
617
+ trustLevel = rest[i + 1];
618
+ i += 1;
619
+ }
620
+ }
621
+ /* v8 ignore stop */
622
+ const VALID_TRUST_LEVELS = new Set(["stranger", "acquaintance", "friend", "family"]);
623
+ if (!trustLevel || !VALID_TRUST_LEVELS.has(trustLevel)) {
624
+ throw new Error(`Usage: ouro friend update <id> --trust <stranger|acquaintance|friend|family>`);
625
+ }
626
+ return {
627
+ kind: "friend.update",
628
+ friendId,
629
+ trustLevel: trustLevel,
630
+ ...(agent ? { agent } : {}),
631
+ };
632
+ }
633
+ if (sub === "link")
634
+ return parseLinkCommand(rest, "friend.link");
635
+ if (sub === "unlink")
636
+ return parseLinkCommand(rest, "friend.unlink");
637
+ throw new Error(`Usage\n${usage()}`);
638
+ }
639
+ function parseConfigCommand(args) {
640
+ const { agent, rest: afterAgent } = extractAgentFlag(args);
641
+ const { facing, rest: cleaned } = extractFacingFlag(afterAgent);
642
+ const [sub, ...rest] = cleaned;
643
+ if (!sub)
644
+ throw new Error(`Usage\n${usage()}`);
645
+ if (sub === "model") {
646
+ if (!agent)
647
+ throw new Error("--agent is required for config model");
648
+ const modelName = rest[0];
649
+ if (!modelName)
650
+ throw new Error(`Usage: ouro config model --agent <name> <model-name>`);
651
+ return facing ? { kind: "config.model", agent, modelName, facing } : { kind: "config.model", agent, modelName };
652
+ }
653
+ if (sub === "models") {
654
+ if (!agent)
655
+ throw new Error("--agent is required for config models");
656
+ return { kind: "config.models", agent };
657
+ }
658
+ throw new Error(`Usage\n${usage()}`);
659
+ }
660
+ function parseMcpCommand(args) {
661
+ const [sub, ...rest] = args;
662
+ if (!sub)
663
+ throw new Error(`Usage\n${usage()}`);
664
+ if (sub === "list")
665
+ return { kind: "mcp.list" };
666
+ if (sub === "call") {
667
+ const server = rest[0];
668
+ const tool = rest[1];
669
+ if (!server || !tool)
670
+ throw new Error(`Usage\n${usage()}`);
671
+ const argsIdx = rest.indexOf("--args");
672
+ const mcpArgs = argsIdx !== -1 && rest[argsIdx + 1] ? rest[argsIdx + 1] : undefined;
673
+ return { kind: "mcp.call", server, tool, ...(mcpArgs ? { args: mcpArgs } : {}) };
674
+ }
675
+ throw new Error(`Usage\n${usage()}`);
676
+ }
677
+ function parseMcpServeCommand(args) {
678
+ let agent;
679
+ let friendId;
680
+ let socketOverride;
681
+ for (let i = 0; i < args.length; i++) {
682
+ if (args[i] === "--agent" && args[i + 1]) {
683
+ agent = args[++i];
684
+ continue;
685
+ }
686
+ if (args[i] === "--friend" && args[i + 1]) {
687
+ friendId = args[++i];
688
+ continue;
689
+ }
690
+ if (args[i] === "--socket" && args[i + 1]) {
691
+ socketOverride = args[++i];
692
+ continue;
693
+ }
694
+ }
695
+ if (!agent)
696
+ throw new Error("mcp-serve requires --agent <name>");
697
+ return { kind: "mcp-serve", agent, ...(friendId ? { friendId } : {}), ...(socketOverride ? { socketOverride } : {}) };
698
+ }
699
+ function parseSetupCommand(args) {
700
+ let tool;
701
+ let agent;
702
+ for (let i = 0; i < args.length; i++) {
703
+ if (args[i] === "--tool" && args[i + 1]) {
704
+ tool = args[++i];
705
+ continue;
706
+ }
707
+ if (args[i] === "--agent" && args[i + 1]) {
708
+ agent = args[++i];
709
+ continue;
710
+ }
711
+ }
712
+ if (!tool)
713
+ throw new Error("setup requires --tool (claude-code | codex)");
714
+ if (tool !== "claude-code" && tool !== "codex")
715
+ throw new Error(`Unknown tool: ${tool}. Supported: claude-code, codex`);
716
+ if (!agent)
717
+ throw new Error("setup requires --agent <name>");
718
+ return { kind: "setup", tool, agent };
719
+ }
720
+ function parseBlueBubblesCommand(args) {
721
+ const subcommand = args[0];
722
+ if (subcommand !== "replay") {
723
+ throw new Error(`Usage\n${usage()}`);
724
+ }
725
+ let agent;
726
+ let messageGuid;
727
+ let eventType = "new-message";
728
+ let json = false;
729
+ for (let i = 1; i < args.length; i += 1) {
730
+ if (args[i] === "--agent" && args[i + 1]) {
731
+ agent = args[++i];
732
+ continue;
733
+ }
734
+ if (args[i] === "--message-guid" && args[i + 1]) {
735
+ messageGuid = args[++i];
736
+ continue;
737
+ }
738
+ if (args[i] === "--event-type" && args[i + 1]) {
739
+ const candidate = args[++i];
740
+ if (candidate !== "new-message" && candidate !== "updated-message") {
741
+ throw new Error("bluebubbles replay --event-type must be new-message or updated-message");
742
+ }
743
+ eventType = candidate;
744
+ continue;
745
+ }
746
+ if (args[i] === "--json") {
747
+ json = true;
748
+ continue;
749
+ }
750
+ }
751
+ if (!agent)
752
+ throw new Error("bluebubbles replay requires --agent <name>");
753
+ if (!messageGuid)
754
+ throw new Error("bluebubbles replay requires --message-guid <guid>");
755
+ return {
756
+ kind: "bluebubbles.replay",
757
+ agent,
758
+ messageGuid,
759
+ eventType,
760
+ ...(json ? { json: true } : {}),
761
+ };
762
+ }
763
+ // ── Main dispatch ──
764
+ function parseOuroCommand(args) {
765
+ const [head, second] = args;
766
+ if (!head)
767
+ return { kind: "daemon.up" };
768
+ // ── help command ──
769
+ if (head === "help") {
770
+ return second ? { kind: "help", command: second } : { kind: "help" };
771
+ }
772
+ // ── per-command --help ──
773
+ if (args.includes("--help")) {
774
+ return { kind: "help", command: head };
775
+ }
776
+ if (head === "--agent" && second) {
777
+ return parseOuroCommand(args.slice(2));
778
+ }
779
+ if (head === "hook") {
780
+ const hookArgs = args.slice(1);
781
+ let event;
782
+ let hookAgent;
783
+ for (let i = 0; i < hookArgs.length; i++) {
784
+ if (hookArgs[i] === "--agent" && hookArgs[i + 1]) {
785
+ hookAgent = hookArgs[++i];
786
+ continue;
787
+ }
788
+ /* v8 ignore start -- false branch: extra positional args after event are ignored */
789
+ if (!event) {
790
+ event = hookArgs[i];
791
+ }
792
+ /* v8 ignore stop */
793
+ }
794
+ if (!event)
795
+ throw new Error("hook requires an event name (session-start, stop, post-tool-use)");
796
+ if (!hookAgent)
797
+ throw new Error("hook requires --agent <name>");
798
+ return { kind: "hook", event, agent: hookAgent };
799
+ }
800
+ if (head === "up") {
801
+ const noRepair = args.includes("--no-repair");
802
+ return noRepair ? { kind: "daemon.up", noRepair: true } : { kind: "daemon.up" };
803
+ }
804
+ if (head === "dev") {
805
+ const devArgs = args.slice(1);
806
+ let repoPath;
807
+ let clone = false;
808
+ let clonePath;
809
+ for (let i = 0; i < devArgs.length; i++) {
810
+ if (devArgs[i] === "--repo-path" && devArgs[i + 1]) {
811
+ repoPath = devArgs[++i];
812
+ continue;
813
+ }
814
+ if (devArgs[i] === "--clone") {
815
+ clone = true;
816
+ continue;
817
+ }
818
+ if (devArgs[i] === "--clone-path" && devArgs[i + 1]) {
819
+ clonePath = devArgs[++i];
820
+ continue;
821
+ }
822
+ }
823
+ return { kind: "daemon.dev", repoPath, clone, clonePath };
824
+ }
825
+ if (head === "rollback")
826
+ return { kind: "rollback", ...(second ? { version: second } : {}) };
827
+ if (head === "versions")
828
+ return { kind: "versions" };
829
+ if (head === "stop" || head === "down")
830
+ return { kind: "daemon.stop" };
831
+ if (head === "status") {
832
+ const { agent, rest } = extractAgentFlag(args.slice(1));
833
+ if (agent) {
834
+ if (rest.length > 0)
835
+ throw new Error("Usage: ouro status --agent <name>");
836
+ return { kind: "provider.status", agent };
837
+ }
838
+ return { kind: "daemon.status" };
839
+ }
840
+ if (head === "use")
841
+ return parseProviderUseCommand(args.slice(1));
842
+ if (head === "check")
843
+ return parseProviderCheckCommand(args.slice(1));
844
+ if (head === "logs") {
845
+ if (second === "prune")
846
+ return { kind: "daemon.logs.prune" };
847
+ return { kind: "daemon.logs" };
848
+ }
849
+ if (head === "outlook")
850
+ return { kind: "outlook", ...(args.includes("--json") ? { json: true } : {}) };
851
+ if (head === "hatch")
852
+ return parseHatchCommand(args.slice(1));
853
+ if (head === "auth")
854
+ return parseAuthCommand(args.slice(1));
855
+ if (head === "task")
856
+ return parseTaskCommand(args.slice(1));
857
+ if (head === "reminder")
858
+ return parseReminderCommand(args.slice(1));
859
+ if (head === "habit")
860
+ return parseHabitCommand(args.slice(1));
861
+ if (head === "friend")
862
+ return parseFriendCommand(args.slice(1));
863
+ if (head === "config")
864
+ return parseConfigCommand(args.slice(1));
865
+ if (head === "mcp")
866
+ return parseMcpCommand(args.slice(1));
867
+ if (head === "whoami") {
868
+ const { agent } = extractAgentFlag(args.slice(1));
869
+ return { kind: "whoami", ...(agent ? { agent } : {}) };
870
+ }
871
+ if (head === "session")
872
+ return parseSessionCommand(args.slice(1));
873
+ if (head === "changelog") {
874
+ const sliced = args.slice(1);
875
+ const { agent, rest: remaining } = extractAgentFlag(sliced);
876
+ let from;
877
+ const fromIdx = remaining.indexOf("--from");
878
+ if (fromIdx !== -1 && remaining[fromIdx + 1]) {
879
+ from = remaining[fromIdx + 1];
880
+ }
881
+ return { kind: "changelog", ...(from ? { from } : {}), ...(agent ? { agent } : {}) };
882
+ }
883
+ if (head === "thoughts")
884
+ return parseThoughtsCommand(args.slice(1));
885
+ if (head === "attention")
886
+ return parseAttentionCommand(args.slice(1));
887
+ if (head === "inner") {
888
+ const { agent } = extractAgentFlag(args.slice(1));
889
+ return { kind: "inner.status", ...(agent ? { agent } : {}) };
890
+ }
891
+ if (head === "chat") {
892
+ if (!second)
893
+ return { kind: "chat.connect", agent: "" };
894
+ return { kind: "chat.connect", agent: second };
895
+ }
896
+ if (head === "msg")
897
+ return parseMessageCommand(args.slice(1));
898
+ if (head === "poke")
899
+ return parsePokeCommand(args.slice(1));
900
+ if (head === "link")
901
+ return parseLinkCommand(args.slice(1));
902
+ if (head === "mcp-serve")
903
+ return parseMcpServeCommand(args.slice(1));
904
+ if (head === "setup")
905
+ return parseSetupCommand(args.slice(1));
906
+ if (head === "doctor")
907
+ return { kind: "doctor" };
908
+ if (head === "bluebubbles")
909
+ return parseBlueBubblesCommand(args.slice(1));
910
+ const suggestion = (0, cli_help_1.suggestCommand)(head);
911
+ const hint = suggestion ? ` Did you mean '${suggestion}'?` : "";
912
+ throw new Error(`Unknown command '${args.join(" ")}'.${hint}\n${usage()}`);
913
+ }