@ouro.bot/cli 0.1.0-alpha.9 → 0.1.0-alpha.91
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.
- package/AdoptionSpecialist.ouro/agent.json +70 -9
- package/AdoptionSpecialist.ouro/psyche/SOUL.md +5 -2
- package/AdoptionSpecialist.ouro/psyche/identities/monty.md +2 -2
- package/README.md +147 -205
- package/assets/ouroboros.png +0 -0
- package/changelog.json +536 -0
- package/dist/heart/active-work.js +251 -0
- package/dist/heart/bridges/manager.js +358 -0
- package/dist/heart/bridges/state-machine.js +135 -0
- package/dist/heart/bridges/store.js +123 -0
- package/dist/heart/commitments.js +109 -0
- package/dist/heart/config.js +68 -23
- package/dist/heart/core.js +452 -93
- package/dist/heart/cross-chat-delivery.js +146 -0
- package/dist/heart/daemon/agent-discovery.js +81 -0
- package/dist/heart/daemon/auth-flow.js +430 -0
- package/dist/heart/daemon/daemon-cli.js +1738 -269
- package/dist/heart/daemon/daemon-entry.js +55 -6
- package/dist/heart/daemon/daemon-runtime-sync.js +212 -0
- package/dist/heart/daemon/daemon.js +216 -10
- package/dist/heart/daemon/hatch-animation.js +10 -3
- package/dist/heart/daemon/hatch-flow.js +7 -82
- package/dist/heart/daemon/hooks/bundle-meta.js +92 -0
- package/dist/heart/daemon/launchd.js +159 -0
- package/dist/heart/daemon/log-tailer.js +4 -3
- package/dist/heart/daemon/message-router.js +17 -8
- package/dist/heart/daemon/ouro-bot-entry.js +0 -0
- package/dist/heart/daemon/ouro-bot-global-installer.js +128 -0
- package/dist/heart/daemon/ouro-entry.js +0 -0
- package/dist/heart/daemon/ouro-path-installer.js +260 -0
- package/dist/heart/daemon/ouro-uti.js +11 -2
- package/dist/heart/daemon/ouro-version-manager.js +171 -0
- package/dist/heart/daemon/process-manager.js +14 -1
- package/dist/heart/daemon/run-hooks.js +37 -0
- package/dist/heart/daemon/runtime-logging.js +58 -15
- package/dist/heart/daemon/runtime-metadata.js +219 -0
- package/dist/heart/daemon/runtime-mode.js +67 -0
- package/dist/heart/daemon/sense-manager.js +307 -0
- package/dist/heart/daemon/skill-management-installer.js +94 -0
- package/dist/heart/daemon/socket-client.js +202 -0
- package/dist/heart/daemon/specialist-orchestrator.js +53 -84
- package/dist/heart/daemon/specialist-prompt.js +63 -11
- package/dist/heart/daemon/specialist-tools.js +211 -60
- package/dist/heart/daemon/staged-restart.js +114 -0
- package/dist/heart/daemon/thoughts.js +507 -0
- package/dist/heart/daemon/update-checker.js +111 -0
- package/dist/heart/daemon/update-hooks.js +138 -0
- package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/identity.js +126 -21
- package/dist/heart/kicks.js +1 -19
- package/dist/heart/model-capabilities.js +48 -0
- package/dist/heart/obligations.js +191 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/providers/anthropic.js +74 -9
- package/dist/heart/providers/azure.js +86 -7
- package/dist/heart/providers/github-copilot.js +149 -0
- package/dist/heart/providers/minimax.js +4 -0
- package/dist/heart/providers/openai-codex.js +12 -3
- package/dist/heart/safe-workspace.js +362 -0
- package/dist/heart/sense-truth.js +61 -0
- package/dist/heart/session-activity.js +169 -0
- package/dist/heart/session-recall.js +116 -0
- package/dist/heart/streaming.js +100 -22
- package/dist/heart/target-resolution.js +123 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/mind/associative-recall.js +14 -2
- package/dist/mind/bundle-manifest.js +70 -0
- package/dist/mind/context.js +57 -11
- package/dist/mind/first-impressions.js +16 -2
- package/dist/mind/friends/channel.js +35 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/store-file.js +19 -0
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +8 -0
- package/dist/mind/memory.js +27 -26
- package/dist/mind/obligation-steering.js +31 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +467 -77
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +15 -2
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/index.js +12 -0
- package/dist/repertoire/ado-client.js +4 -2
- package/dist/repertoire/coding/feedback.js +180 -0
- package/dist/repertoire/coding/index.js +4 -1
- package/dist/repertoire/coding/manager.js +69 -4
- package/dist/repertoire/coding/spawner.js +21 -3
- package/dist/repertoire/coding/tools.js +105 -2
- package/dist/repertoire/data/ado-endpoints.json +188 -0
- package/dist/repertoire/guardrails.js +290 -0
- package/dist/repertoire/mcp-client.js +254 -0
- package/dist/repertoire/mcp-manager.js +195 -0
- package/dist/repertoire/skills.js +3 -26
- package/dist/repertoire/tasks/board.js +12 -0
- package/dist/repertoire/tasks/index.js +23 -9
- package/dist/repertoire/tasks/transitions.js +1 -2
- package/dist/repertoire/tools-base.js +714 -249
- package/dist/repertoire/tools-bluebubbles.js +93 -0
- package/dist/repertoire/tools-teams.js +58 -25
- package/dist/repertoire/tools.js +106 -53
- package/dist/senses/bluebubbles-client.js +210 -5
- package/dist/senses/bluebubbles-entry.js +2 -0
- package/dist/senses/bluebubbles-inbound-log.js +109 -0
- package/dist/senses/bluebubbles-media.js +339 -0
- package/dist/senses/bluebubbles-model.js +12 -4
- package/dist/senses/bluebubbles-mutation-log.js +45 -5
- package/dist/senses/bluebubbles-runtime-state.js +109 -0
- package/dist/senses/bluebubbles-session-cleanup.js +72 -0
- package/dist/senses/bluebubbles.js +894 -45
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +400 -164
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/debug-activity.js +154 -0
- package/dist/senses/inner-dialog-worker.js +47 -18
- package/dist/senses/inner-dialog.js +377 -83
- package/dist/senses/pipeline.js +307 -0
- package/dist/senses/teams.js +573 -129
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +14 -3
- package/subagents/README.md +4 -70
- package/dist/heart/daemon/specialist-session.js +0 -142
- package/dist/heart/daemon/subagent-installer.js +0 -125
- package/dist/inner-worker-entry.js +0 -4
- package/subagents/work-doer.md +0 -233
- package/subagents/work-merger.md +0 -624
- package/subagents/work-planner.md +0 -373
|
@@ -39,13 +39,18 @@ 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")
|
|
46
48
|
return ["setupToken"];
|
|
47
49
|
if (provider === "openai-codex")
|
|
48
50
|
return ["oauthAccessToken"];
|
|
51
|
+
/* v8 ignore next -- branch tested via requiredCredentialKeys unit test @preserve */
|
|
52
|
+
if (provider === "github-copilot")
|
|
53
|
+
return ["githubToken"];
|
|
49
54
|
if (provider === "minimax")
|
|
50
55
|
return ["apiKey"];
|
|
51
56
|
return ["apiKey", "endpoint", "deployment"];
|
|
@@ -66,70 +71,8 @@ function validateCredentials(provider, credentials) {
|
|
|
66
71
|
throw new Error(`Missing required credentials for ${provider}: ${missing.join(", ")}`);
|
|
67
72
|
}
|
|
68
73
|
}
|
|
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
74
|
function writeSecretsFile(agentName, provider, credentials, secretsRoot) {
|
|
113
|
-
|
|
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;
|
|
75
|
+
return (0, auth_flow_1.writeProviderCredentials)(agentName, provider, credentials, { secretsRoot }).secretsPath;
|
|
133
76
|
}
|
|
134
77
|
function writeReadme(dir, purpose) {
|
|
135
78
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -138,14 +81,6 @@ function writeReadme(dir, purpose) {
|
|
|
138
81
|
fs.writeFileSync(readmePath, `# ${path.basename(dir)}\n\n${purpose}\n`, "utf-8");
|
|
139
82
|
}
|
|
140
83
|
}
|
|
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
84
|
function pad(value) {
|
|
150
85
|
return String(value).padStart(2, "0");
|
|
151
86
|
}
|
|
@@ -182,7 +117,7 @@ function writeFriendImprint(bundleRoot, humanName, now) {
|
|
|
182
117
|
const friendsDir = path.join(bundleRoot, "friends");
|
|
183
118
|
fs.mkdirSync(friendsDir, { recursive: true });
|
|
184
119
|
const nowIso = now.toISOString();
|
|
185
|
-
const id = `friend-${slugify(humanName)}`;
|
|
120
|
+
const id = `friend-${(0, config_1.slugify)(humanName) || "friend"}`;
|
|
186
121
|
const localExternalId = `${os.userInfo().username}@${os.hostname()}`;
|
|
187
122
|
const record = {
|
|
188
123
|
id,
|
|
@@ -207,15 +142,6 @@ function writeFriendImprint(bundleRoot, humanName, now) {
|
|
|
207
142
|
};
|
|
208
143
|
fs.writeFileSync(path.join(friendsDir, `${id}.json`), `${JSON.stringify(record, null, 2)}\n`, "utf-8");
|
|
209
144
|
}
|
|
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
145
|
function writeMemoryScaffold(bundleRoot) {
|
|
220
146
|
const memoryRoot = path.join(bundleRoot, "psyche", "memory");
|
|
221
147
|
fs.mkdirSync(path.join(memoryRoot, "daily"), { recursive: true });
|
|
@@ -267,7 +193,6 @@ async function runHatchFlow(input, deps = {}) {
|
|
|
267
193
|
writeReadme(path.join(bundleRoot, "senses"), "Sense-specific config.");
|
|
268
194
|
writeReadme(path.join(bundleRoot, "senses", "teams"), "Teams sense config.");
|
|
269
195
|
writeHatchlingAgentConfig(bundleRoot, input);
|
|
270
|
-
writeHatchlingPsyche(bundleRoot, input, selected.fileName);
|
|
271
196
|
writeMemoryScaffold(bundleRoot);
|
|
272
197
|
writeFriendImprint(bundleRoot, input.humanName, now);
|
|
273
198
|
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 =
|
|
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 ??
|
|
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
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|