@ouro.bot/cli 0.1.0-alpha.2 → 0.1.0-alpha.200

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 (215) hide show
  1. package/README.md +187 -191
  2. package/SerpentGuide.ouro/agent.json +82 -0
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +6 -3
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +2 -2
  5. package/assets/ouroboros.png +0 -0
  6. package/changelog.json +1248 -0
  7. package/dist/heart/active-work.js +832 -0
  8. package/dist/heart/bridges/manager.js +358 -0
  9. package/dist/heart/bridges/state-machine.js +135 -0
  10. package/dist/heart/bridges/store.js +123 -0
  11. package/dist/heart/cares.js +179 -0
  12. package/dist/heart/commitments.js +111 -0
  13. package/dist/heart/config.js +114 -28
  14. package/dist/heart/core.js +689 -120
  15. package/dist/heart/cross-chat-delivery.js +146 -0
  16. package/dist/heart/daemon/agent-config-check.js +149 -0
  17. package/dist/heart/daemon/agent-discovery.js +81 -0
  18. package/dist/heart/daemon/agent-service.js +360 -0
  19. package/dist/heart/daemon/auth-flow.js +477 -0
  20. package/dist/heart/daemon/cadence.js +70 -0
  21. package/dist/heart/daemon/daemon-cli.js +2897 -193
  22. package/dist/heart/daemon/daemon-entry.js +194 -8
  23. package/dist/heart/daemon/daemon-health.js +136 -0
  24. package/dist/heart/daemon/daemon-runtime-sync.js +231 -0
  25. package/dist/heart/daemon/daemon-tombstone.js +123 -0
  26. package/dist/heart/daemon/daemon.js +488 -13
  27. package/dist/heart/daemon/habit-migration.js +181 -0
  28. package/dist/heart/daemon/habit-parser.js +119 -0
  29. package/dist/heart/daemon/habit-scheduler.js +369 -0
  30. package/dist/heart/daemon/hatch-animation.js +35 -0
  31. package/dist/heart/daemon/hatch-flow.js +32 -122
  32. package/dist/heart/daemon/hatch-specialist.js +7 -2
  33. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  34. package/dist/heart/daemon/hooks/bundle-meta.js +206 -0
  35. package/dist/heart/daemon/inner-status.js +89 -0
  36. package/dist/heart/daemon/launchd.js +165 -0
  37. package/dist/heart/daemon/log-tailer.js +4 -3
  38. package/dist/heart/daemon/mcp-server.js +591 -0
  39. package/dist/heart/daemon/message-router.js +17 -8
  40. package/dist/heart/daemon/os-cron-deps.js +134 -0
  41. package/dist/heart/daemon/ouro-bot-global-installer.js +128 -0
  42. package/dist/heart/daemon/ouro-bot-wrapper.js +4 -3
  43. package/dist/heart/daemon/ouro-path-installer.js +221 -0
  44. package/dist/heart/daemon/ouro-uti.js +11 -2
  45. package/dist/heart/daemon/ouro-version-manager.js +171 -0
  46. package/dist/heart/daemon/outlook-http.js +439 -0
  47. package/dist/heart/daemon/outlook-read.js +1618 -0
  48. package/dist/heart/daemon/outlook-render.js +1032 -0
  49. package/dist/heart/daemon/outlook-types.js +7 -0
  50. package/dist/heart/daemon/outlook-view.js +194 -0
  51. package/dist/heart/daemon/process-manager.js +94 -1
  52. package/dist/heart/daemon/run-hooks.js +39 -0
  53. package/dist/heart/daemon/runtime-logging.js +61 -14
  54. package/dist/heart/daemon/runtime-metadata.js +219 -0
  55. package/dist/heart/daemon/runtime-mode.js +67 -0
  56. package/dist/heart/daemon/safe-mode.js +161 -0
  57. package/dist/heart/daemon/sense-manager.js +314 -0
  58. package/dist/heart/daemon/session-id-resolver.js +131 -0
  59. package/dist/heart/daemon/skill-management-installer.js +94 -0
  60. package/dist/heart/daemon/socket-client.js +202 -0
  61. package/dist/heart/daemon/specialist-orchestrator.js +129 -0
  62. package/dist/heart/daemon/specialist-prompt.js +101 -0
  63. package/dist/heart/daemon/specialist-tools.js +283 -0
  64. package/dist/heart/daemon/staged-restart.js +138 -0
  65. package/dist/heart/daemon/task-scheduler.js +3 -25
  66. package/dist/heart/daemon/thoughts.js +507 -0
  67. package/dist/heart/daemon/update-checker.js +111 -0
  68. package/dist/heart/daemon/update-hooks.js +138 -0
  69. package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
  70. package/dist/heart/delegation.js +62 -0
  71. package/dist/heart/identity.js +220 -52
  72. package/dist/heart/intentions.js +173 -0
  73. package/dist/heart/kicks.js +2 -20
  74. package/dist/heart/migrate-config.js +127 -0
  75. package/dist/heart/model-capabilities.js +48 -0
  76. package/dist/heart/obligations.js +225 -0
  77. package/dist/heart/presence.js +185 -0
  78. package/dist/heart/progress-story.js +42 -0
  79. package/dist/heart/provider-failover.js +88 -0
  80. package/dist/heart/provider-ping.js +178 -0
  81. package/dist/heart/providers/anthropic-token.js +163 -0
  82. package/dist/heart/providers/anthropic.js +199 -36
  83. package/dist/heart/providers/azure.js +116 -10
  84. package/dist/heart/providers/github-copilot.js +157 -0
  85. package/dist/heart/providers/minimax.js +33 -3
  86. package/dist/heart/providers/openai-codex.js +51 -16
  87. package/dist/heart/sense-truth.js +61 -0
  88. package/dist/heart/session-activity.js +172 -0
  89. package/dist/heart/session-recall.js +216 -0
  90. package/dist/heart/start-of-turn-packet.js +232 -0
  91. package/dist/heart/streaming.js +120 -33
  92. package/dist/heart/sync.js +217 -0
  93. package/dist/heart/target-resolution.js +127 -0
  94. package/dist/heart/tempo.js +93 -0
  95. package/dist/heart/temporal-view.js +41 -0
  96. package/dist/heart/tool-activity-callbacks.js +36 -0
  97. package/dist/heart/tool-description.js +135 -0
  98. package/dist/heart/tool-loop.js +200 -0
  99. package/dist/heart/turn-coordinator.js +28 -0
  100. package/dist/mind/associative-recall.js +122 -32
  101. package/dist/mind/bundle-manifest.js +77 -1
  102. package/dist/mind/context.js +125 -14
  103. package/dist/mind/{memory.js → diary.js} +69 -56
  104. package/dist/mind/episodes.js +119 -0
  105. package/dist/mind/file-state.js +179 -0
  106. package/dist/mind/first-impressions.js +16 -2
  107. package/dist/mind/friends/channel.js +64 -0
  108. package/dist/mind/friends/group-context.js +144 -0
  109. package/dist/mind/friends/store-file.js +36 -0
  110. package/dist/mind/friends/trust-explanation.js +74 -0
  111. package/dist/mind/friends/types.js +9 -1
  112. package/dist/mind/journal-index.js +161 -0
  113. package/dist/mind/obligation-steering.js +221 -0
  114. package/dist/mind/obligations.js +138 -0
  115. package/dist/mind/pending.js +76 -9
  116. package/dist/mind/phrases.js +1 -0
  117. package/dist/mind/prompt.js +861 -105
  118. package/dist/mind/scrutiny.js +173 -0
  119. package/dist/mind/token-estimate.js +8 -12
  120. package/dist/nerves/cli-logging.js +15 -2
  121. package/dist/nerves/coverage/audit.js +1 -1
  122. package/dist/nerves/coverage/run-artifacts.js +1 -1
  123. package/dist/nerves/event-buffer.js +111 -0
  124. package/dist/nerves/index.js +63 -3
  125. package/dist/nerves/observation.js +20 -0
  126. package/dist/nerves/runtime.js +5 -1
  127. package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
  128. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  129. package/dist/outlook-ui/index.html +15 -0
  130. package/dist/repertoire/ado-client.js +4 -2
  131. package/dist/repertoire/ado-semantic.js +11 -5
  132. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  133. package/dist/repertoire/coding/context-pack.js +330 -0
  134. package/dist/repertoire/coding/feedback.js +301 -0
  135. package/dist/repertoire/coding/index.js +4 -1
  136. package/dist/repertoire/coding/manager.js +210 -4
  137. package/dist/repertoire/coding/spawner.js +58 -12
  138. package/dist/repertoire/coding/tools.js +209 -7
  139. package/dist/repertoire/data/ado-endpoints.json +188 -0
  140. package/dist/repertoire/guardrails.js +291 -0
  141. package/dist/repertoire/mcp-client.js +254 -0
  142. package/dist/repertoire/mcp-manager.js +251 -0
  143. package/dist/repertoire/shell-sessions.js +133 -0
  144. package/dist/repertoire/skills.js +14 -23
  145. package/dist/repertoire/tasks/board.js +43 -5
  146. package/dist/repertoire/tasks/fix.js +182 -0
  147. package/dist/repertoire/tasks/index.js +28 -10
  148. package/dist/repertoire/tasks/lifecycle.js +2 -2
  149. package/dist/repertoire/tasks/parser.js +3 -2
  150. package/dist/repertoire/tasks/scanner.js +194 -37
  151. package/dist/repertoire/tasks/transitions.js +11 -28
  152. package/dist/repertoire/tools-base.js +1360 -271
  153. package/dist/repertoire/tools-bluebubbles.js +94 -0
  154. package/dist/repertoire/tools-github.js +1 -6
  155. package/dist/repertoire/tools-teams.js +65 -59
  156. package/dist/repertoire/tools.js +318 -91
  157. package/dist/scripts/claude-code-hook.js +41 -0
  158. package/dist/scripts/claude-code-stop-hook.js +47 -0
  159. package/dist/senses/attention-queue.js +97 -0
  160. package/dist/senses/bluebubbles-client.js +532 -0
  161. package/dist/senses/bluebubbles-entry.js +13 -0
  162. package/dist/senses/bluebubbles-inbound-log.js +109 -0
  163. package/dist/senses/bluebubbles-media.js +339 -0
  164. package/dist/senses/bluebubbles-model.js +261 -0
  165. package/dist/senses/bluebubbles-mutation-log.js +116 -0
  166. package/dist/senses/bluebubbles-runtime-state.js +109 -0
  167. package/dist/senses/bluebubbles-session-cleanup.js +72 -0
  168. package/dist/senses/bluebubbles.js +1327 -0
  169. package/dist/senses/cli/adapter.js +274 -0
  170. package/dist/senses/cli/ink-app.js +156 -0
  171. package/dist/senses/cli/inline-diff.js +64 -0
  172. package/dist/senses/cli/message-list.js +51 -0
  173. package/dist/senses/cli/ouro-tui.js +349 -0
  174. package/dist/senses/cli/spinner-imperative.js +135 -0
  175. package/dist/senses/cli/spinner.js +101 -0
  176. package/dist/senses/cli/status-line.js +60 -0
  177. package/dist/senses/cli/streaming-markdown.js +526 -0
  178. package/dist/senses/cli/tool-display.js +83 -0
  179. package/dist/senses/cli/tool-render.js +85 -0
  180. package/dist/senses/cli/tui-store.js +198 -0
  181. package/dist/senses/cli/virtual-list.js +35 -0
  182. package/dist/senses/cli-entry.js +1 -1
  183. package/dist/senses/cli-layout.js +187 -0
  184. package/dist/senses/cli.js +687 -262
  185. package/dist/senses/commands.js +65 -1
  186. package/dist/senses/continuity.js +94 -0
  187. package/dist/senses/habit-turn-message.js +108 -0
  188. package/dist/senses/inner-dialog-worker.js +112 -19
  189. package/dist/senses/inner-dialog.js +592 -84
  190. package/dist/senses/pipeline.js +693 -0
  191. package/dist/senses/shared-turn.js +196 -0
  192. package/dist/senses/surface-tool.js +95 -0
  193. package/dist/senses/teams.js +817 -151
  194. package/dist/senses/trust-gate.js +112 -2
  195. package/package.json +24 -7
  196. package/skills/configure-dev-tools.md +81 -0
  197. package/subagents/README.md +4 -70
  198. package/AdoptionSpecialist.ouro/agent.json +0 -20
  199. package/dist/heart/daemon/subagent-installer.js +0 -125
  200. package/dist/inner-worker-entry.js +0 -4
  201. package/subagents/work-doer.md +0 -233
  202. package/subagents/work-merger.md +0 -624
  203. package/subagents/work-planner.md +0 -373
  204. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  205. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  206. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  207. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  208. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  209. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  210. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  211. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  212. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  213. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  214. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
  215. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
@@ -0,0 +1,134 @@
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.createRealOsCronDeps = createRealOsCronDeps;
37
+ exports.createRealCrontabDeps = createRealCrontabDeps;
38
+ exports.resolveOuroBinaryPath = resolveOuroBinaryPath;
39
+ const child_process_1 = require("child_process");
40
+ const fs = __importStar(require("fs"));
41
+ const os = __importStar(require("os"));
42
+ const path = __importStar(require("path"));
43
+ const runtime_1 = require("../../nerves/runtime");
44
+ function createRealOsCronDeps() {
45
+ (0, runtime_1.emitNervesEvent)({
46
+ component: "daemon",
47
+ event: "daemon.os_cron_deps_created",
48
+ message: "created real OS cron deps",
49
+ meta: { platform: process.platform },
50
+ });
51
+ return {
52
+ exec: (cmd) => {
53
+ try {
54
+ (0, child_process_1.execSync)(cmd, { stdio: "ignore" });
55
+ }
56
+ catch {
57
+ /* best effort */
58
+ }
59
+ },
60
+ writeFile: (p, c) => fs.writeFileSync(p, c, "utf-8"),
61
+ removeFile: (p) => {
62
+ try {
63
+ fs.unlinkSync(p);
64
+ }
65
+ catch {
66
+ /* best effort — file may already be gone */
67
+ }
68
+ },
69
+ existsFile: (p) => fs.existsSync(p),
70
+ listDir: (dir) => {
71
+ try {
72
+ return fs.readdirSync(dir);
73
+ }
74
+ catch {
75
+ return [];
76
+ }
77
+ },
78
+ mkdirp: (dir) => fs.mkdirSync(dir, { recursive: true }),
79
+ homeDir: os.homedir(),
80
+ };
81
+ }
82
+ function createRealCrontabDeps() {
83
+ (0, runtime_1.emitNervesEvent)({
84
+ component: "daemon",
85
+ event: "daemon.crontab_deps_created",
86
+ message: "created real crontab deps",
87
+ meta: {},
88
+ });
89
+ /* v8 ignore start -- crontab exec closures: calling these in tests would modify the real system crontab @preserve */
90
+ return {
91
+ execOutput: (cmd) => (0, child_process_1.execSync)(cmd, { encoding: "utf-8" }),
92
+ execWrite: (cmd, stdin) => {
93
+ (0, child_process_1.execSync)(cmd, { input: stdin, stdio: ["pipe", "ignore", "ignore"] });
94
+ },
95
+ };
96
+ /* v8 ignore stop */
97
+ }
98
+ /* v8 ignore start -- ouro path resolution: probes process.argv, filesystem layout, and PATH; branches depend on install method and runtime environment @preserve */
99
+ function resolveOuroBinaryPath() {
100
+ // Try to resolve from process.argv[1] — the script being run
101
+ const scriptPath = process.argv[1];
102
+ if (scriptPath) {
103
+ // If running via node dist/heart/daemon/daemon-entry.js, resolve the ouro wrapper
104
+ // The ouro binary is typically at the package root's bin
105
+ const distDir = path.resolve(path.dirname(scriptPath));
106
+ const packageBin = path.resolve(distDir, "..", "..", "..", "node_modules", ".bin", "ouro");
107
+ if (fs.existsSync(packageBin)) {
108
+ return packageBin;
109
+ }
110
+ // Try the repo-local scripts/ouro.sh
111
+ const repoOuro = path.resolve(distDir, "..", "..", "..", "scripts", "ouro.sh");
112
+ if (fs.existsSync(repoOuro)) {
113
+ return repoOuro;
114
+ }
115
+ }
116
+ // Try which ouro
117
+ try {
118
+ const result = (0, child_process_1.execSync)("which ouro", { encoding: "utf-8" }).trim();
119
+ if (result.length > 0)
120
+ return result;
121
+ }
122
+ catch {
123
+ /* not on PATH */
124
+ }
125
+ // Fallback: use "ouro" and rely on PATH
126
+ (0, runtime_1.emitNervesEvent)({
127
+ component: "daemon",
128
+ event: "daemon.ouro_path_fallback",
129
+ message: "could not resolve full ouro binary path, falling back to 'ouro'",
130
+ meta: {},
131
+ });
132
+ return "ouro";
133
+ }
134
+ /* v8 ignore stop */
@@ -0,0 +1,128 @@
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.syncGlobalOuroBotWrapper = syncGlobalOuroBotWrapper;
37
+ const child_process_1 = require("child_process");
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ const runtime_metadata_1 = require("./runtime-metadata");
42
+ function normalizeOutput(output) {
43
+ return (typeof output === "string" ? output : output.toString("utf-8")).trim();
44
+ }
45
+ function resolveGlobalPrefix(execFileSyncImpl) {
46
+ return normalizeOutput(execFileSyncImpl("npm", ["prefix", "-g"], { encoding: "utf-8" }));
47
+ }
48
+ function resolveGlobalRoot(execFileSyncImpl) {
49
+ return normalizeOutput(execFileSyncImpl("npm", ["root", "-g"], { encoding: "utf-8" }));
50
+ }
51
+ function readInstalledWrapperVersion(globalRoot, existsSyncImpl, readFileSyncImpl) {
52
+ const packageJsonPath = path.join(globalRoot, "ouro.bot", "package.json");
53
+ if (!existsSyncImpl(packageJsonPath))
54
+ return null;
55
+ try {
56
+ const parsed = JSON.parse(readFileSyncImpl(packageJsonPath, "utf-8"));
57
+ return typeof parsed.version === "string" && parsed.version.trim().length > 0 ? parsed.version.trim() : null;
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ function resolveExecutableOwner(globalPrefix, platform, existsSyncImpl, realpathSyncImpl) {
64
+ const binName = platform === "win32" ? "ouro.bot.cmd" : "ouro.bot";
65
+ const binPath = platform === "win32"
66
+ ? path.join(globalPrefix, binName)
67
+ : path.join(globalPrefix, "bin", binName);
68
+ if (!existsSyncImpl(binPath))
69
+ return null;
70
+ try {
71
+ const resolved = realpathSyncImpl(binPath);
72
+ if (resolved.includes(`${path.sep}node_modules${path.sep}ouro.bot${path.sep}`))
73
+ return "wrapper";
74
+ if (resolved.includes(`${path.sep}node_modules${path.sep}@ouro.bot${path.sep}cli${path.sep}`))
75
+ return "cli";
76
+ return "other";
77
+ }
78
+ catch {
79
+ return "unknown";
80
+ }
81
+ }
82
+ function syncGlobalOuroBotWrapper(deps = {}) {
83
+ /* v8 ignore start -- dependency-injection defaults are only exercised in the live runtime */
84
+ const execFileSyncImpl = deps.execFileSync ?? child_process_1.execFileSync;
85
+ const existsSyncImpl = deps.existsSync ?? fs.existsSync;
86
+ const readFileSyncImpl = deps.readFileSync ?? fs.readFileSync;
87
+ const realpathSyncImpl = deps.realpathSync ?? fs.realpathSync;
88
+ const runtimeVersion = deps.runtimeVersion ?? (0, runtime_metadata_1.getRuntimeMetadata)().version;
89
+ const platform = deps.platform ?? process.platform;
90
+ /* v8 ignore stop */
91
+ (0, runtime_1.emitNervesEvent)({
92
+ component: "daemon",
93
+ event: "daemon.ouro_bot_global_sync_start",
94
+ message: "checking global ouro.bot wrapper",
95
+ meta: { version: runtimeVersion },
96
+ });
97
+ const globalPrefix = resolveGlobalPrefix(execFileSyncImpl);
98
+ const globalRoot = resolveGlobalRoot(execFileSyncImpl);
99
+ const installedVersion = readInstalledWrapperVersion(globalRoot, existsSyncImpl, readFileSyncImpl);
100
+ const executableOwner = resolveExecutableOwner(globalPrefix, platform, existsSyncImpl, realpathSyncImpl);
101
+ if (executableOwner === "wrapper") {
102
+ (0, runtime_1.emitNervesEvent)({
103
+ component: "daemon",
104
+ event: "daemon.ouro_bot_global_sync_end",
105
+ message: "global ouro.bot wrapper already current",
106
+ meta: { version: runtimeVersion, installedVersion, executableOwner, installed: false },
107
+ });
108
+ return {
109
+ installed: false,
110
+ version: runtimeVersion,
111
+ installedVersion,
112
+ executableOwner,
113
+ };
114
+ }
115
+ execFileSyncImpl("npm", ["install", "-g", "--force", "ouro.bot@latest"], { stdio: "pipe", encoding: "utf-8" });
116
+ (0, runtime_1.emitNervesEvent)({
117
+ component: "daemon",
118
+ event: "daemon.ouro_bot_global_sync_end",
119
+ message: "global ouro.bot wrapper synced",
120
+ meta: { version: runtimeVersion, installedVersion, executableOwner, installed: true },
121
+ });
122
+ return {
123
+ installed: true,
124
+ version: runtimeVersion,
125
+ installedVersion,
126
+ executableOwner,
127
+ };
128
+ }
@@ -37,8 +37,9 @@ exports.runOuroBotWrapper = runOuroBotWrapper;
37
37
  const runtime_1 = require("../../nerves/runtime");
38
38
  const daemon_cli_1 = require("./daemon-cli");
39
39
  async function defaultLoadCanonicalRunner() {
40
- const packageName = "@ouro.bot/cli";
41
- const specifier = packageName;
40
+ // Use the subpath export so we get the daemon-cli module directly,
41
+ // NOT the root entry point which has side-effects (immediately runs the CLI).
42
+ const specifier = "@ouro.bot/cli/runOuroCli";
42
43
  const loaded = await Promise.resolve(`${specifier}`).then(s => __importStar(require(s)));
43
44
  const candidate = Object.prototype.hasOwnProperty.call(loaded, "runOuroCli")
44
45
  ? loaded["runOuroCli"]
@@ -46,7 +47,7 @@ async function defaultLoadCanonicalRunner() {
46
47
  if (typeof candidate === "function") {
47
48
  return candidate;
48
49
  }
49
- throw new Error("@ouro.bot/cli does not export runOuroCli");
50
+ throw new Error("@ouro.bot/cli/runOuroCli does not export runOuroCli");
50
51
  }
51
52
  function defaultWriteStdout(_text) {
52
53
  // Wrapper is intentionally silent by default to avoid duplicate terminal output.
@@ -0,0 +1,221 @@
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.installOuroCommand = installOuroCommand;
37
+ const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
39
+ const path = __importStar(require("path"));
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ const WRAPPER_SCRIPT = `#!/bin/sh
42
+ # Check for dev mode — if dev-config.json exists, dispatch to the dev repo
43
+ # Skip dev dispatch for "up" command (explicitly returns to production)
44
+ DEV_CONFIG="$HOME/.ouro-cli/dev-config.json"
45
+ if [ -f "$DEV_CONFIG" ] && [ "$1" != "up" ]; then
46
+ DEV_REPO=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('$DEV_CONFIG','utf-8')).repoPath)}catch{}" 2>/dev/null)
47
+ DEV_ENTRY="$DEV_REPO/dist/heart/daemon/ouro-entry.js"
48
+ if [ -n "$DEV_REPO" ] && [ -e "$DEV_ENTRY" ]; then
49
+ exec node "$DEV_ENTRY" "$@"
50
+ fi
51
+ fi
52
+ # Fall back to installed version
53
+ ENTRY="$HOME/.ouro-cli/CurrentVersion/node_modules/@ouro.bot/cli/dist/heart/daemon/ouro-entry.js"
54
+ if [ ! -e "$ENTRY" ]; then
55
+ echo "ouro not installed. Run: npx ouro.bot" >&2
56
+ exit 1
57
+ fi
58
+ exec node "$ENTRY" "$@"
59
+ `;
60
+ function writeWrapperScript(scriptPath, mkdirSync, writeFileSync, chmodSync) {
61
+ mkdirSync(path.dirname(scriptPath), { recursive: true });
62
+ writeFileSync(scriptPath, WRAPPER_SCRIPT, { mode: 0o755 });
63
+ chmodSync(scriptPath, 0o755);
64
+ }
65
+ function detectShellProfile(homeDir, shell) {
66
+ if (!shell)
67
+ return null;
68
+ const base = path.basename(shell);
69
+ if (base === "zsh")
70
+ return path.join(homeDir, ".zshrc");
71
+ if (base === "bash") {
72
+ // macOS uses .bash_profile, Linux uses .bashrc
73
+ const profilePath = path.join(homeDir, ".bash_profile");
74
+ return profilePath;
75
+ }
76
+ if (base === "fish")
77
+ return path.join(homeDir, ".config", "fish", "config.fish");
78
+ return null;
79
+ }
80
+ function isBinDirInPath(binDir, envPath) {
81
+ return envPath.split(path.delimiter).some((p) => p === binDir);
82
+ }
83
+ function buildPathExportLine(binDir, shell) {
84
+ const base = shell ? path.basename(shell) : /* v8 ignore next -- unreachable: only called when detectShellProfile returns non-null, which requires shell @preserve */ "";
85
+ if (base === "fish") {
86
+ return `\n# Added by ouro\nset -gx PATH ${binDir} $PATH\n`;
87
+ }
88
+ return `\n# Added by ouro\nexport PATH="${binDir}:$PATH"\n`;
89
+ }
90
+ function isWrapperCurrent(scriptPath, existsSync, readFileSync) {
91
+ if (!existsSync(scriptPath))
92
+ return false;
93
+ try {
94
+ return readFileSync(scriptPath, "utf-8") === WRAPPER_SCRIPT;
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ }
100
+ function installOuroCommand(deps = {}) {
101
+ /* v8 ignore start -- dep defaults: only used in real runtime, tests always inject @preserve */
102
+ const platform = deps.platform ?? process.platform;
103
+ const homeDir = deps.homeDir ?? os.homedir();
104
+ const existsSync = deps.existsSync ?? fs.existsSync;
105
+ const mkdirSync = deps.mkdirSync ?? fs.mkdirSync;
106
+ const writeFileSync = deps.writeFileSync ?? fs.writeFileSync;
107
+ const readFileSync = deps.readFileSync ?? ((p, enc) => fs.readFileSync(p, enc));
108
+ const appendFileSync = deps.appendFileSync ?? fs.appendFileSync;
109
+ const chmodSync = deps.chmodSync ?? fs.chmodSync;
110
+ const envPath = deps.envPath ?? process.env.PATH ?? "";
111
+ const shell = deps.shell ?? process.env.SHELL;
112
+ /* v8 ignore stop */
113
+ if (platform === "win32") {
114
+ (0, runtime_1.emitNervesEvent)({
115
+ component: "daemon",
116
+ event: "daemon.ouro_path_install_skip",
117
+ message: "skipped ouro PATH install on Windows",
118
+ meta: { platform },
119
+ });
120
+ return { installed: false, scriptPath: null, pathReady: false, shellProfileUpdated: null, skippedReason: "windows", repairedOldLauncher: false };
121
+ }
122
+ // Ensure ~/.ouro-cli/ directory layout exists
123
+ if (deps.ensureCliLayout) {
124
+ deps.ensureCliLayout();
125
+ }
126
+ const binDir = path.join(homeDir, ".ouro-cli", "bin");
127
+ const scriptPath = path.join(binDir, "ouro");
128
+ const oldScriptPath = path.join(homeDir, ".local", "bin", "ouro");
129
+ const modernCurrent = isWrapperCurrent(scriptPath, existsSync, readFileSync);
130
+ const oldExists = existsSync(oldScriptPath);
131
+ const oldCurrent = oldExists && isWrapperCurrent(oldScriptPath, existsSync, readFileSync);
132
+ // ── Repair old ~/.local/bin/ouro launcher ──
133
+ // If the old launcher exists with stale content it can shadow the modern
134
+ // path and cause the wrong CLI version to run. Overwrite it with the
135
+ // current wrapper so both paths resolve to ~/.ouro-cli/CurrentVersion.
136
+ let repairedOldLauncher = false;
137
+ if (oldExists && !oldCurrent) {
138
+ (0, runtime_1.emitNervesEvent)({
139
+ component: "daemon",
140
+ event: "daemon.ouro_path_repair_old",
141
+ message: "repairing stale old launcher at ~/.local/bin/ouro",
142
+ meta: { oldScriptPath },
143
+ });
144
+ try {
145
+ writeFileSync(oldScriptPath, WRAPPER_SCRIPT, { mode: 0o755 });
146
+ chmodSync(oldScriptPath, 0o755);
147
+ repairedOldLauncher = true;
148
+ }
149
+ catch {
150
+ // Best effort — old launcher repair failure must not block modern install
151
+ }
152
+ }
153
+ // ── Fast-path: modern wrapper already current ──
154
+ if (modernCurrent) {
155
+ (0, runtime_1.emitNervesEvent)({
156
+ component: "daemon",
157
+ event: "daemon.ouro_path_install_skip",
158
+ message: "ouro command already installed",
159
+ meta: { scriptPath },
160
+ });
161
+ return { installed: false, scriptPath, pathReady: isBinDirInPath(binDir, envPath), shellProfileUpdated: null, skippedReason: "already-installed", repairedOldLauncher };
162
+ }
163
+ (0, runtime_1.emitNervesEvent)({
164
+ component: "daemon",
165
+ event: "daemon.ouro_path_install_start",
166
+ message: existsSync(scriptPath) ? "repairing stale ouro wrapper script" : "installing ouro command to PATH",
167
+ meta: { scriptPath, binDir },
168
+ });
169
+ try {
170
+ if (!modernCurrent) {
171
+ writeWrapperScript(scriptPath, mkdirSync, writeFileSync, chmodSync);
172
+ }
173
+ }
174
+ catch (error) {
175
+ (0, runtime_1.emitNervesEvent)({
176
+ level: "warn",
177
+ component: "daemon",
178
+ event: "daemon.ouro_path_install_error",
179
+ message: "failed to install ouro command",
180
+ meta: { error: error instanceof Error ? error.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(error) },
181
+ });
182
+ return { installed: false, scriptPath: null, pathReady: false, shellProfileUpdated: null, skippedReason: error instanceof Error ? error.message : /* v8 ignore next -- defensive @preserve */ String(error), repairedOldLauncher };
183
+ }
184
+ // Check if ~/.ouro-cli/bin is already in PATH
185
+ const pathReady = isBinDirInPath(binDir, envPath);
186
+ let shellProfileUpdated = null;
187
+ if (!pathReady) {
188
+ const profilePath = detectShellProfile(homeDir, shell);
189
+ if (profilePath) {
190
+ try {
191
+ let existing = "";
192
+ try {
193
+ existing = readFileSync(profilePath, "utf-8");
194
+ }
195
+ catch {
196
+ // Profile doesn't exist yet — that's fine, we'll create it
197
+ }
198
+ if (!existing.includes(binDir)) {
199
+ appendFileSync(profilePath, buildPathExportLine(binDir, shell));
200
+ shellProfileUpdated = profilePath;
201
+ }
202
+ }
203
+ catch (error) {
204
+ (0, runtime_1.emitNervesEvent)({
205
+ level: "warn",
206
+ component: "daemon",
207
+ event: "daemon.ouro_path_profile_error",
208
+ message: "failed to update shell profile for PATH",
209
+ meta: { profilePath, error: error instanceof Error ? error.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(error) },
210
+ });
211
+ }
212
+ }
213
+ }
214
+ (0, runtime_1.emitNervesEvent)({
215
+ component: "daemon",
216
+ event: "daemon.ouro_path_install_end",
217
+ message: "ouro command installed",
218
+ meta: { scriptPath, pathReady, shellProfileUpdated, oldScriptPath: oldExists ? oldScriptPath : null },
219
+ });
220
+ return { installed: true, scriptPath, pathReady, shellProfileUpdated, repairedOldLauncher };
221
+ }
@@ -42,7 +42,13 @@ const identity_1 = require("../identity");
42
42
  const runtime_1 = require("../../nerves/runtime");
43
43
  const LSREGISTER_PATH = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";
44
44
  const ICON_SIZES = [16, 32, 128, 256, 512];
45
- function resolveIconSourcePath(repoRoot) {
45
+ function resolveIconSourcePath(repoRoot, existsSync) {
46
+ // Prefer bundled asset (shipped with npm package)
47
+ const bundledPath = path.resolve(repoRoot, "assets", "ouroboros.png");
48
+ if (existsSync(bundledPath)) {
49
+ return bundledPath;
50
+ }
51
+ // Fall back to adjacent repo path (dev environment)
46
52
  return path.resolve(repoRoot, "..", "ouroboros-website", "public", "images", "ouroboros.png");
47
53
  }
48
54
  function buildIconAsset(iconSourcePath, icnsPath, iconsetDir, deps) {
@@ -91,6 +97,7 @@ function buildInfoPlist(iconInstalled) {
91
97
  " <key>UTTypeConformsTo</key>",
92
98
  " <array>",
93
99
  " <string>public.folder</string>",
100
+ " <string>com.apple.package</string>",
94
101
  " </array>",
95
102
  " <key>UTTypeTagSpecification</key>",
96
103
  " <dict>",
@@ -112,6 +119,8 @@ function buildInfoPlist(iconInstalled) {
112
119
  " </array>",
113
120
  " <key>CFBundleTypeRole</key>",
114
121
  " <string>Editor</string>",
122
+ " <key>LSTypeIsPackage</key>",
123
+ " <true/>",
115
124
  ` ${iconTag.trim()}`,
116
125
  " </dict>",
117
126
  " </array>",
@@ -152,7 +161,7 @@ function registerOuroBundleUti(deps = {}) {
152
161
  const plistPath = path.join(contentsDir, "Info.plist");
153
162
  const icnsPath = path.join(resourcesDir, "ouro.icns");
154
163
  const iconsetDir = path.join(supportRoot, "ouro.iconset");
155
- const iconSourcePath = resolveIconSourcePath(repoRoot);
164
+ const iconSourcePath = resolveIconSourcePath(repoRoot, existsSync);
156
165
  (0, runtime_1.emitNervesEvent)({
157
166
  component: "daemon",
158
167
  event: "daemon.ouro_uti_register_start",