@ouro.bot/cli 0.1.0-alpha.6 → 0.1.0-alpha.60

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 (117) hide show
  1. package/AdoptionSpecialist.ouro/agent.json +70 -9
  2. package/AdoptionSpecialist.ouro/psyche/SOUL.md +5 -2
  3. package/AdoptionSpecialist.ouro/psyche/identities/monty.md +2 -2
  4. package/README.md +147 -205
  5. package/assets/ouroboros.png +0 -0
  6. package/changelog.json +325 -0
  7. package/dist/heart/active-work.js +178 -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/config.js +57 -23
  12. package/dist/heart/core.js +236 -90
  13. package/dist/heart/cross-chat-delivery.js +146 -0
  14. package/dist/heart/daemon/agent-discovery.js +81 -0
  15. package/dist/heart/daemon/auth-flow.js +351 -0
  16. package/dist/heart/daemon/daemon-cli.js +1173 -227
  17. package/dist/heart/daemon/daemon-entry.js +55 -6
  18. package/dist/heart/daemon/daemon-runtime-sync.js +212 -0
  19. package/dist/heart/daemon/daemon.js +189 -10
  20. package/dist/heart/daemon/hatch-animation.js +10 -3
  21. package/dist/heart/daemon/hatch-flow.js +4 -82
  22. package/dist/heart/daemon/hooks/bundle-meta.js +92 -0
  23. package/dist/heart/daemon/launchd.js +159 -0
  24. package/dist/heart/daemon/log-tailer.js +4 -3
  25. package/dist/heart/daemon/message-router.js +17 -8
  26. package/dist/heart/daemon/ouro-bot-entry.js +0 -0
  27. package/dist/heart/daemon/ouro-bot-global-installer.js +128 -0
  28. package/dist/heart/daemon/ouro-entry.js +0 -0
  29. package/dist/heart/daemon/ouro-path-installer.js +178 -0
  30. package/dist/heart/daemon/ouro-uti.js +11 -2
  31. package/dist/heart/daemon/process-manager.js +14 -1
  32. package/dist/heart/daemon/run-hooks.js +37 -0
  33. package/dist/heart/daemon/runtime-logging.js +58 -15
  34. package/dist/heart/daemon/runtime-metadata.js +219 -0
  35. package/dist/heart/daemon/runtime-mode.js +67 -0
  36. package/dist/heart/daemon/sense-manager.js +307 -0
  37. package/dist/heart/daemon/socket-client.js +202 -0
  38. package/dist/heart/daemon/specialist-orchestrator.js +53 -84
  39. package/dist/heart/daemon/specialist-prompt.js +64 -5
  40. package/dist/heart/daemon/specialist-tools.js +213 -58
  41. package/dist/heart/daemon/staged-restart.js +114 -0
  42. package/dist/heart/daemon/subagent-installer.js +48 -7
  43. package/dist/heart/daemon/thoughts.js +379 -0
  44. package/dist/heart/daemon/update-checker.js +111 -0
  45. package/dist/heart/daemon/update-hooks.js +138 -0
  46. package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
  47. package/dist/heart/delegation.js +62 -0
  48. package/dist/heart/identity.js +122 -19
  49. package/dist/heart/kicks.js +1 -19
  50. package/dist/heart/model-capabilities.js +40 -0
  51. package/dist/heart/progress-story.js +42 -0
  52. package/dist/heart/providers/anthropic.js +74 -9
  53. package/dist/heart/providers/azure.js +86 -7
  54. package/dist/heart/providers/minimax.js +4 -0
  55. package/dist/heart/providers/openai-codex.js +12 -3
  56. package/dist/heart/safe-workspace.js +228 -0
  57. package/dist/heart/sense-truth.js +61 -0
  58. package/dist/heart/session-activity.js +169 -0
  59. package/dist/heart/session-recall.js +116 -0
  60. package/dist/heart/streaming.js +100 -22
  61. package/dist/heart/target-resolution.js +123 -0
  62. package/dist/heart/turn-coordinator.js +28 -0
  63. package/dist/mind/associative-recall.js +14 -2
  64. package/dist/mind/bundle-manifest.js +70 -0
  65. package/dist/mind/context.js +27 -11
  66. package/dist/mind/first-impressions.js +16 -2
  67. package/dist/mind/friends/channel.js +35 -0
  68. package/dist/mind/friends/group-context.js +144 -0
  69. package/dist/mind/friends/store-file.js +19 -0
  70. package/dist/mind/friends/trust-explanation.js +74 -0
  71. package/dist/mind/friends/types.js +8 -0
  72. package/dist/mind/memory.js +27 -26
  73. package/dist/mind/pending.js +72 -9
  74. package/dist/mind/phrases.js +1 -0
  75. package/dist/mind/prompt.js +299 -77
  76. package/dist/mind/token-estimate.js +8 -12
  77. package/dist/nerves/cli-logging.js +15 -2
  78. package/dist/nerves/coverage/run-artifacts.js +1 -1
  79. package/dist/repertoire/ado-client.js +4 -2
  80. package/dist/repertoire/coding/feedback.js +134 -0
  81. package/dist/repertoire/coding/index.js +4 -1
  82. package/dist/repertoire/coding/manager.js +62 -4
  83. package/dist/repertoire/coding/spawner.js +3 -3
  84. package/dist/repertoire/coding/tools.js +41 -2
  85. package/dist/repertoire/data/ado-endpoints.json +188 -0
  86. package/dist/repertoire/tasks/board.js +12 -0
  87. package/dist/repertoire/tasks/index.js +23 -9
  88. package/dist/repertoire/tasks/transitions.js +1 -2
  89. package/dist/repertoire/tools-base.js +629 -251
  90. package/dist/repertoire/tools-bluebubbles.js +93 -0
  91. package/dist/repertoire/tools-teams.js +58 -25
  92. package/dist/repertoire/tools.js +92 -48
  93. package/dist/senses/bluebubbles-client.js +210 -5
  94. package/dist/senses/bluebubbles-entry.js +2 -0
  95. package/dist/senses/bluebubbles-inbound-log.js +109 -0
  96. package/dist/senses/bluebubbles-media.js +339 -0
  97. package/dist/senses/bluebubbles-model.js +12 -4
  98. package/dist/senses/bluebubbles-mutation-log.js +45 -5
  99. package/dist/senses/bluebubbles-runtime-state.js +109 -0
  100. package/dist/senses/bluebubbles-session-cleanup.js +72 -0
  101. package/dist/senses/bluebubbles.js +890 -45
  102. package/dist/senses/cli-layout.js +87 -0
  103. package/dist/senses/cli.js +345 -144
  104. package/dist/senses/continuity.js +94 -0
  105. package/dist/senses/debug-activity.js +148 -0
  106. package/dist/senses/inner-dialog-worker.js +47 -18
  107. package/dist/senses/inner-dialog.js +330 -84
  108. package/dist/senses/pipeline.js +278 -0
  109. package/dist/senses/teams.js +570 -129
  110. package/dist/senses/trust-gate.js +112 -2
  111. package/package.json +14 -3
  112. package/subagents/README.md +46 -33
  113. package/subagents/work-doer.md +28 -24
  114. package/subagents/work-merger.md +24 -30
  115. package/subagents/work-planner.md +44 -27
  116. package/dist/heart/daemon/specialist-session.js +0 -142
  117. package/dist/inner-worker-entry.js +0 -4
@@ -39,7 +39,9 @@ const fs = __importStar(require("fs"));
39
39
  const os = __importStar(require("os"));
40
40
  const path = __importStar(require("path"));
41
41
  const identity_1 = require("../identity");
42
+ const config_1 = require("../config");
42
43
  const runtime_1 = require("../../nerves/runtime");
44
+ const auth_flow_1 = require("./auth-flow");
43
45
  const hatch_specialist_1 = require("./hatch-specialist");
44
46
  function requiredCredentialKeys(provider) {
45
47
  if (provider === "anthropic")
@@ -66,70 +68,8 @@ function validateCredentials(provider, credentials) {
66
68
  throw new Error(`Missing required credentials for ${provider}: ${missing.join(", ")}`);
67
69
  }
68
70
  }
69
- function buildSecretsTemplate() {
70
- return {
71
- providers: {
72
- azure: {
73
- modelName: "gpt-4o-mini",
74
- apiKey: "",
75
- endpoint: "",
76
- deployment: "",
77
- apiVersion: "2025-04-01-preview",
78
- },
79
- minimax: {
80
- model: "minimax-text-01",
81
- apiKey: "",
82
- },
83
- anthropic: {
84
- model: "claude-opus-4-6",
85
- setupToken: "",
86
- },
87
- "openai-codex": {
88
- model: "gpt-5.2",
89
- oauthAccessToken: "",
90
- },
91
- },
92
- teams: {
93
- clientId: "",
94
- clientSecret: "",
95
- tenantId: "",
96
- },
97
- oauth: {
98
- graphConnectionName: "graph",
99
- adoConnectionName: "ado",
100
- githubConnectionName: "",
101
- },
102
- teamsChannel: {
103
- skipConfirmation: true,
104
- port: 3978,
105
- },
106
- integrations: {
107
- perplexityApiKey: "",
108
- openaiEmbeddingsApiKey: "",
109
- },
110
- };
111
- }
112
71
  function writeSecretsFile(agentName, provider, credentials, secretsRoot) {
113
- const secrets = buildSecretsTemplate();
114
- if (provider === "anthropic") {
115
- secrets.providers.anthropic.setupToken = credentials.setupToken.trim();
116
- }
117
- else if (provider === "openai-codex") {
118
- secrets.providers["openai-codex"].oauthAccessToken = credentials.oauthAccessToken.trim();
119
- }
120
- else if (provider === "minimax") {
121
- secrets.providers.minimax.apiKey = credentials.apiKey.trim();
122
- }
123
- else {
124
- secrets.providers.azure.apiKey = credentials.apiKey.trim();
125
- secrets.providers.azure.endpoint = credentials.endpoint.trim();
126
- secrets.providers.azure.deployment = credentials.deployment.trim();
127
- }
128
- const secretsDir = path.join(secretsRoot, agentName);
129
- fs.mkdirSync(secretsDir, { recursive: true });
130
- const secretsPath = path.join(secretsDir, "secrets.json");
131
- fs.writeFileSync(secretsPath, `${JSON.stringify(secrets, null, 2)}\n`, "utf-8");
132
- return secretsPath;
72
+ return (0, auth_flow_1.writeProviderCredentials)(agentName, provider, credentials, { secretsRoot }).secretsPath;
133
73
  }
134
74
  function writeReadme(dir, purpose) {
135
75
  fs.mkdirSync(dir, { recursive: true });
@@ -138,14 +78,6 @@ function writeReadme(dir, purpose) {
138
78
  fs.writeFileSync(readmePath, `# ${path.basename(dir)}\n\n${purpose}\n`, "utf-8");
139
79
  }
140
80
  }
141
- function slugify(value) {
142
- const trimmed = value.trim().toLowerCase();
143
- const slug = trimmed
144
- .replace(/[^a-z0-9]+/g, "-")
145
- .replace(/^-+/, "")
146
- .replace(/-+$/, "");
147
- return slug || "friend";
148
- }
149
81
  function pad(value) {
150
82
  return String(value).padStart(2, "0");
151
83
  }
@@ -182,7 +114,7 @@ function writeFriendImprint(bundleRoot, humanName, now) {
182
114
  const friendsDir = path.join(bundleRoot, "friends");
183
115
  fs.mkdirSync(friendsDir, { recursive: true });
184
116
  const nowIso = now.toISOString();
185
- const id = `friend-${slugify(humanName)}`;
117
+ const id = `friend-${(0, config_1.slugify)(humanName) || "friend"}`;
186
118
  const localExternalId = `${os.userInfo().username}@${os.hostname()}`;
187
119
  const record = {
188
120
  id,
@@ -207,15 +139,6 @@ function writeFriendImprint(bundleRoot, humanName, now) {
207
139
  };
208
140
  fs.writeFileSync(path.join(friendsDir, `${id}.json`), `${JSON.stringify(record, null, 2)}\n`, "utf-8");
209
141
  }
210
- function writeHatchlingPsyche(bundleRoot, input, identityFileName) {
211
- const psycheDir = path.join(bundleRoot, "psyche");
212
- fs.mkdirSync(psycheDir, { recursive: true });
213
- fs.writeFileSync(path.join(psycheDir, "SOUL.md"), "# SOUL\n\nI am a practical, collaborative agent. I keep commitments and communicate clearly.\n", "utf-8");
214
- fs.writeFileSync(path.join(psycheDir, "IDENTITY.md"), `# IDENTITY\n\nI'm ${input.agentName}, newly hatched and ready to help ${input.humanName}.`, "utf-8");
215
- fs.writeFileSync(path.join(psycheDir, "LORE.md"), `# LORE\n\nHatched with specialist identity seed: ${identityFileName}.`, "utf-8");
216
- fs.writeFileSync(path.join(psycheDir, "TACIT.md"), "# TACIT\n\n- Save what I learn.\n- Keep tasks current.\n", "utf-8");
217
- fs.writeFileSync(path.join(psycheDir, "ASPIRATIONS.md"), "# ASPIRATIONS\n\n- Become a reliable partner for my primary friend.\n", "utf-8");
218
- }
219
142
  function writeMemoryScaffold(bundleRoot) {
220
143
  const memoryRoot = path.join(bundleRoot, "psyche", "memory");
221
144
  fs.mkdirSync(path.join(memoryRoot, "daily"), { recursive: true });
@@ -267,7 +190,6 @@ async function runHatchFlow(input, deps = {}) {
267
190
  writeReadme(path.join(bundleRoot, "senses"), "Sense-specific config.");
268
191
  writeReadme(path.join(bundleRoot, "senses", "teams"), "Teams sense config.");
269
192
  writeHatchlingAgentConfig(bundleRoot, input);
270
- writeHatchlingPsyche(bundleRoot, input, selected.fileName);
271
193
  writeMemoryScaffold(bundleRoot);
272
194
  writeFriendImprint(bundleRoot, input.humanName, now);
273
195
  writeHeartbeatTask(bundleRoot, now);
@@ -0,0 +1,92 @@
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.bundleMetaHook = bundleMetaHook;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const runtime_1 = require("../../../nerves/runtime");
40
+ async function bundleMetaHook(ctx) {
41
+ (0, runtime_1.emitNervesEvent)({
42
+ component: "daemon",
43
+ event: "daemon.bundle_meta_hook_start",
44
+ message: "running bundle-meta update hook",
45
+ meta: { agentRoot: ctx.agentRoot, currentVersion: ctx.currentVersion },
46
+ });
47
+ const metaPath = path.join(ctx.agentRoot, "bundle-meta.json");
48
+ let existing;
49
+ try {
50
+ if (fs.existsSync(metaPath)) {
51
+ const raw = fs.readFileSync(metaPath, "utf-8");
52
+ existing = JSON.parse(raw);
53
+ }
54
+ }
55
+ catch {
56
+ // Malformed JSON -- treat as missing, will overwrite with fresh
57
+ existing = undefined;
58
+ }
59
+ const updated = {
60
+ runtimeVersion: ctx.currentVersion,
61
+ bundleSchemaVersion: existing?.bundleSchemaVersion ?? 1,
62
+ lastUpdated: new Date().toISOString(),
63
+ };
64
+ // Save old runtimeVersion as previousRuntimeVersion (if there was one)
65
+ if (existing?.runtimeVersion) {
66
+ updated.previousRuntimeVersion = existing.runtimeVersion;
67
+ }
68
+ try {
69
+ fs.writeFileSync(metaPath, JSON.stringify(updated, null, 2) + "\n", "utf-8");
70
+ }
71
+ catch (err) {
72
+ const errorMessage = err instanceof Error ? err.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(err);
73
+ (0, runtime_1.emitNervesEvent)({
74
+ component: "daemon",
75
+ event: "daemon.bundle_meta_hook_error",
76
+ message: "bundle-meta hook write failed",
77
+ meta: { agentRoot: ctx.agentRoot, error: errorMessage },
78
+ });
79
+ return { ok: false, error: errorMessage };
80
+ }
81
+ (0, runtime_1.emitNervesEvent)({
82
+ component: "daemon",
83
+ event: "daemon.bundle_meta_hook_end",
84
+ message: "bundle-meta updated",
85
+ meta: {
86
+ agentRoot: ctx.agentRoot,
87
+ runtimeVersion: updated.runtimeVersion,
88
+ previousRuntimeVersion: updated.previousRuntimeVersion,
89
+ },
90
+ });
91
+ return { ok: true };
92
+ }
@@ -0,0 +1,159 @@
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.DAEMON_PLIST_LABEL = void 0;
37
+ exports.generateDaemonPlist = generateDaemonPlist;
38
+ exports.writeLaunchAgentPlist = writeLaunchAgentPlist;
39
+ exports.installLaunchAgent = installLaunchAgent;
40
+ exports.uninstallLaunchAgent = uninstallLaunchAgent;
41
+ exports.isDaemonInstalled = isDaemonInstalled;
42
+ const path = __importStar(require("path"));
43
+ const runtime_1 = require("../../nerves/runtime");
44
+ exports.DAEMON_PLIST_LABEL = "bot.ouro.daemon";
45
+ function plistFilePath(homeDir) {
46
+ return path.join(homeDir, "Library", "LaunchAgents", `${exports.DAEMON_PLIST_LABEL}.plist`);
47
+ }
48
+ function userLaunchDomain(userUid) {
49
+ return `gui/${userUid}`;
50
+ }
51
+ function generateDaemonPlist(options) {
52
+ (0, runtime_1.emitNervesEvent)({
53
+ component: "daemon",
54
+ event: "daemon.launchd_generate_plist",
55
+ message: "generating daemon plist",
56
+ meta: { entryPath: options.entryPath, socketPath: options.socketPath },
57
+ });
58
+ const lines = [
59
+ `<?xml version="1.0" encoding="UTF-8"?>`,
60
+ `<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,
61
+ `<plist version="1.0">`,
62
+ `<dict>`,
63
+ ` <key>Label</key>`,
64
+ ` <string>${exports.DAEMON_PLIST_LABEL}</string>`,
65
+ ` <key>ProgramArguments</key>`,
66
+ ` <array>`,
67
+ ` <string>${options.nodePath}</string>`,
68
+ ` <string>${options.entryPath}</string>`,
69
+ ` <string>--socket</string>`,
70
+ ` <string>${options.socketPath}</string>`,
71
+ ` </array>`,
72
+ ` <key>RunAtLoad</key>`,
73
+ ` <true/>`,
74
+ ` <key>KeepAlive</key>`,
75
+ ` <true/>`,
76
+ ];
77
+ if (options.envPath) {
78
+ lines.push(` <key>EnvironmentVariables</key>`, ` <dict>`, ` <key>PATH</key>`, ` <string>${options.envPath}</string>`, ` </dict>`);
79
+ }
80
+ if (options.logDir) {
81
+ lines.push(` <key>StandardOutPath</key>`, ` <string>${path.join(options.logDir, "ouro-daemon-stdout.log")}</string>`, ` <key>StandardErrorPath</key>`, ` <string>${path.join(options.logDir, "ouro-daemon-stderr.log")}</string>`);
82
+ }
83
+ lines.push(`</dict>`, `</plist>`, ``);
84
+ return lines.join("\n");
85
+ }
86
+ function writeLaunchAgentPlist(deps, options) {
87
+ const launchAgentsDir = path.join(deps.homeDir, "Library", "LaunchAgents");
88
+ deps.mkdirp(launchAgentsDir);
89
+ if (options.logDir) {
90
+ deps.mkdirp(options.logDir);
91
+ }
92
+ const fullPath = plistFilePath(deps.homeDir);
93
+ const xml = generateDaemonPlist(options);
94
+ deps.writeFile(fullPath, xml);
95
+ (0, runtime_1.emitNervesEvent)({
96
+ component: "daemon",
97
+ event: "daemon.launchd_plist_written",
98
+ message: "daemon launch agent plist written",
99
+ meta: { plistPath: fullPath, entryPath: options.entryPath, socketPath: options.socketPath },
100
+ });
101
+ return fullPath;
102
+ }
103
+ function installLaunchAgent(deps, options) {
104
+ (0, runtime_1.emitNervesEvent)({
105
+ component: "daemon",
106
+ event: "daemon.launchd_install",
107
+ message: "installing launch agent",
108
+ meta: { entryPath: options.entryPath, socketPath: options.socketPath },
109
+ });
110
+ const fullPath = plistFilePath(deps.homeDir);
111
+ const domain = userLaunchDomain(deps.userUid);
112
+ // Unload existing (best effort) for idempotent re-install
113
+ if (deps.existsFile(fullPath)) {
114
+ try {
115
+ deps.exec(`launchctl bootout ${domain} "${fullPath}"`);
116
+ }
117
+ catch { /* best effort */ }
118
+ }
119
+ writeLaunchAgentPlist(deps, options);
120
+ deps.exec(`launchctl bootstrap ${domain} "${fullPath}"`);
121
+ (0, runtime_1.emitNervesEvent)({
122
+ component: "daemon",
123
+ event: "daemon.launchd_installed",
124
+ message: "launch agent installed",
125
+ meta: { plistPath: fullPath },
126
+ });
127
+ }
128
+ function uninstallLaunchAgent(deps) {
129
+ (0, runtime_1.emitNervesEvent)({
130
+ component: "daemon",
131
+ event: "daemon.launchd_uninstall",
132
+ message: "uninstalling launch agent",
133
+ meta: {},
134
+ });
135
+ const fullPath = plistFilePath(deps.homeDir);
136
+ const domain = userLaunchDomain(deps.userUid);
137
+ if (deps.existsFile(fullPath)) {
138
+ try {
139
+ deps.exec(`launchctl bootout ${domain} "${fullPath}"`);
140
+ }
141
+ catch { /* best effort */ }
142
+ deps.removeFile(fullPath);
143
+ }
144
+ (0, runtime_1.emitNervesEvent)({
145
+ component: "daemon",
146
+ event: "daemon.launchd_uninstalled",
147
+ message: "launch agent uninstalled",
148
+ meta: { plistPath: fullPath },
149
+ });
150
+ }
151
+ function isDaemonInstalled(deps) {
152
+ (0, runtime_1.emitNervesEvent)({
153
+ component: "daemon",
154
+ event: "daemon.launchd_check_installed",
155
+ message: "checking if daemon is installed",
156
+ meta: {},
157
+ });
158
+ return deps.existsFile(plistFilePath(deps.homeDir));
159
+ }
@@ -37,10 +37,10 @@ exports.discoverLogFiles = discoverLogFiles;
37
37
  exports.readLastLines = readLastLines;
38
38
  exports.formatLogLine = formatLogLine;
39
39
  exports.tailLogs = tailLogs;
40
- const os = __importStar(require("os"));
41
40
  const path = __importStar(require("path"));
42
41
  const nerves_1 = require("../../nerves");
43
42
  const runtime_1 = require("../../nerves/runtime");
43
+ const identity_1 = require("../identity");
44
44
  const LEVEL_COLORS = {
45
45
  debug: "\x1b[2m",
46
46
  info: "\x1b[36m",
@@ -49,11 +49,12 @@ const LEVEL_COLORS = {
49
49
  };
50
50
  function discoverLogFiles(options) {
51
51
  /* v8 ignore start -- integration: default DI stubs for real OS @preserve */
52
- const homeDir = options.homeDir ?? os.homedir();
53
52
  const existsSync = options.existsSync ?? (() => false);
54
53
  const readdirSync = options.readdirSync ?? (() => []);
55
54
  /* v8 ignore stop */
56
- const logDir = path.join(homeDir, ".agentstate", "daemon", "logs");
55
+ const logDir = options.homeDir
56
+ ? path.join(options.homeDir, "AgentBundles", `${options.agentName ?? "slugger"}.ouro`, "state", "daemon", "logs")
57
+ : (0, identity_1.getAgentDaemonLogsDir)(options.agentName);
57
58
  const files = [];
58
59
  if (existsSync(logDir)) {
59
60
  for (const name of readdirSync(logDir)) {
@@ -35,9 +35,9 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.FileMessageRouter = void 0;
37
37
  const fs = __importStar(require("fs"));
38
- const os = __importStar(require("os"));
39
38
  const path = __importStar(require("path"));
40
39
  const runtime_1 = require("../../nerves/runtime");
40
+ const identity_1 = require("../identity");
41
41
  function messageId(nowIso) {
42
42
  return `msg-${nowIso.replace(/[^0-9]/g, "")}`;
43
43
  }
@@ -45,7 +45,7 @@ class FileMessageRouter {
45
45
  baseDir;
46
46
  now;
47
47
  constructor(options = {}) {
48
- this.baseDir = options.baseDir ?? path.join(os.homedir(), ".agentstate", "messages");
48
+ this.baseDir = options.baseDir ?? (0, identity_1.getAgentMessagesRoot)();
49
49
  this.now = options.now ?? (() => new Date().toISOString());
50
50
  fs.mkdirSync(this.baseDir, { recursive: true });
51
51
  }
@@ -77,12 +77,21 @@ class FileMessageRouter {
77
77
  if (!fs.existsSync(inboxPath))
78
78
  return [];
79
79
  const raw = fs.readFileSync(inboxPath, "utf-8");
80
- fs.writeFileSync(inboxPath, "", "utf-8");
81
- const messages = raw
82
- .split("\n")
83
- .map((line) => line.trim())
84
- .filter((line) => line.length > 0)
85
- .map((line) => JSON.parse(line));
80
+ const messages = [];
81
+ const unparsed = [];
82
+ for (const line of raw.split("\n")) {
83
+ const trimmed = line.trim();
84
+ if (!trimmed)
85
+ continue;
86
+ try {
87
+ messages.push(JSON.parse(trimmed));
88
+ }
89
+ catch {
90
+ unparsed.push(trimmed);
91
+ }
92
+ }
93
+ // Only clear inbox after parsing; preserve lines that failed to parse.
94
+ fs.writeFileSync(inboxPath, unparsed.length > 0 ? unparsed.map((l) => `${l}\n`).join("") : "", "utf-8");
86
95
  (0, runtime_1.emitNervesEvent)({
87
96
  component: "daemon",
88
97
  event: "daemon.message_polled",
File without changes
@@ -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
+ }
File without changes