@ouro.bot/cli 0.1.0-alpha.376 → 0.1.0-alpha.378
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/README.md +7 -4
- package/SerpentGuide.ouro/psyche/SOUL.md +1 -1
- package/changelog.json +18 -0
- package/dist/heart/agent-entry.js +22 -2
- package/dist/heart/config.js +19 -82
- package/dist/heart/daemon/agent-config-check.js +1 -7
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +1 -1
- package/dist/heart/daemon/cli-exec.js +112 -6
- package/dist/heart/daemon/cli-help.js +7 -0
- package/dist/heart/daemon/cli-parse.js +37 -0
- package/dist/heart/daemon/doctor.js +18 -32
- package/dist/heart/daemon/runtime-metadata.js +2 -30
- package/dist/heart/daemon/sense-manager.js +37 -27
- package/dist/heart/identity.js +0 -7
- package/dist/heart/runtime-credentials.js +181 -0
- package/dist/heart/turn-context.js +1 -12
- package/dist/mind/prompt.js +6 -15
- package/dist/repertoire/tools-notes.js +1 -1
- package/dist/repertoire/vault-unlock.js +2 -1
- package/dist/senses/bluebubbles/entry.js +60 -3
- package/dist/senses/cli-entry.js +60 -8
- package/dist/senses/teams-entry.js +60 -8
- package/package.json +1 -1
- package/skills/travel-planning.md +2 -6
|
@@ -36,7 +36,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.getRuntimeMetadata = getRuntimeMetadata;
|
|
37
37
|
const crypto_1 = require("crypto");
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
|
-
const os = __importStar(require("os"));
|
|
40
39
|
const path = __importStar(require("path"));
|
|
41
40
|
const childProcess = __importStar(require("child_process"));
|
|
42
41
|
const identity_1 = require("../identity");
|
|
@@ -87,19 +86,7 @@ function readLastUpdated(repoRoot, packageJsonPath, statSyncImpl, execFileSyncIm
|
|
|
87
86
|
return { value: UNKNOWN_METADATA, source: "unknown" };
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
|
-
function
|
|
91
|
-
const homedirImpl = optionalFunction(os, "homedir");
|
|
92
|
-
if (!homedirImpl) {
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
try {
|
|
96
|
-
return homedirImpl.call(os);
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
function listConfigTargets(bundlesRoot, secretsRoot, daemonLoggingPath, readdirSyncImpl) {
|
|
89
|
+
function listConfigTargets(bundlesRoot, daemonLoggingPath, readdirSyncImpl) {
|
|
103
90
|
if (!readdirSyncImpl)
|
|
104
91
|
return [];
|
|
105
92
|
const targets = new Set();
|
|
@@ -117,19 +104,6 @@ function listConfigTargets(bundlesRoot, secretsRoot, daemonLoggingPath, readdirS
|
|
|
117
104
|
catch {
|
|
118
105
|
// ignore unreadable bundle roots
|
|
119
106
|
}
|
|
120
|
-
if (secretsRoot) {
|
|
121
|
-
try {
|
|
122
|
-
const secretEntries = readdirSyncImpl(secretsRoot, { withFileTypes: true });
|
|
123
|
-
for (const entry of secretEntries) {
|
|
124
|
-
if (!entry.isDirectory())
|
|
125
|
-
continue;
|
|
126
|
-
targets.add(path.join(secretsRoot, entry.name, "secrets.json"));
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
// ignore unreadable secrets roots
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
107
|
return [...targets].sort();
|
|
134
108
|
}
|
|
135
109
|
function readConfigFingerprint(targets, readFileSyncImpl, existsSyncImpl) {
|
|
@@ -172,8 +146,6 @@ function readConfigFingerprint(targets, readFileSyncImpl, existsSyncImpl) {
|
|
|
172
146
|
function getRuntimeMetadata(deps = {}) {
|
|
173
147
|
const repoRoot = deps.repoRoot ?? (0, identity_1.getRepoRoot)();
|
|
174
148
|
const bundlesRoot = deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)();
|
|
175
|
-
const homeDir = readHomeDir();
|
|
176
|
-
const secretsRoot = deps.secretsRoot ?? (homeDir ? path.join(homeDir, ".agentsecrets") : null);
|
|
177
149
|
const daemonLoggingPath = deps.daemonLoggingPath ?? (0, identity_1.getAgentDaemonLoggingConfigPath)();
|
|
178
150
|
const readFileSyncImpl = deps.readFileSync ?? optionalFunction(fs, "readFileSync")?.bind(fs) ?? null;
|
|
179
151
|
const statSyncImpl = deps.statSync ?? optionalFunction(fs, "statSync")?.bind(fs) ?? null;
|
|
@@ -191,7 +163,7 @@ function getRuntimeMetadata(deps = {}) {
|
|
|
191
163
|
throw new Error("git unavailable");
|
|
192
164
|
}))
|
|
193
165
|
: { value: UNKNOWN_METADATA, source: "unknown" };
|
|
194
|
-
const configTargets = listConfigTargets(bundlesRoot,
|
|
166
|
+
const configTargets = listConfigTargets(bundlesRoot, daemonLoggingPath, readdirSyncImpl);
|
|
195
167
|
const configFingerprint = readConfigFingerprint(configTargets, readFileSyncImpl, existsSyncImpl);
|
|
196
168
|
(0, runtime_1.emitNervesEvent)({
|
|
197
169
|
component: "daemon",
|
|
@@ -39,6 +39,7 @@ const os = __importStar(require("os"));
|
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
40
|
const runtime_1 = require("../../nerves/runtime");
|
|
41
41
|
const identity_1 = require("../identity");
|
|
42
|
+
const runtime_credentials_1 = require("../runtime-credentials");
|
|
42
43
|
const sense_truth_1 = require("../sense-truth");
|
|
43
44
|
const process_manager_1 = require("./process-manager");
|
|
44
45
|
const DEFAULT_TEAMS_PORT = 3978;
|
|
@@ -87,22 +88,6 @@ function readAgentSenses(agentJsonPath) {
|
|
|
87
88
|
}
|
|
88
89
|
return defaults;
|
|
89
90
|
}
|
|
90
|
-
function readSecretsPayload(secretsPath) {
|
|
91
|
-
try {
|
|
92
|
-
const raw = fs.readFileSync(secretsPath, "utf-8");
|
|
93
|
-
const parsed = JSON.parse(raw);
|
|
94
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
95
|
-
return { payload: {}, error: "invalid secrets.json object" };
|
|
96
|
-
}
|
|
97
|
-
return { payload: parsed, error: null };
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
return {
|
|
101
|
-
payload: {},
|
|
102
|
-
error: error instanceof Error ? error.message : String(error),
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
91
|
function textField(record, key) {
|
|
107
92
|
const value = record?.[key];
|
|
108
93
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -111,13 +96,18 @@ function numberField(record, key, fallback) {
|
|
|
111
96
|
const value = record?.[key];
|
|
112
97
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
113
98
|
}
|
|
114
|
-
function
|
|
99
|
+
function senseFactsFromRuntimeConfig(agent, senses, runtimeConfig) {
|
|
115
100
|
const base = {
|
|
116
101
|
cli: { configured: true, detail: "local interactive terminal" },
|
|
117
102
|
teams: { configured: false, detail: "not enabled in agent.json" },
|
|
118
103
|
bluebubbles: { configured: false, detail: "not enabled in agent.json" },
|
|
119
104
|
};
|
|
120
|
-
const
|
|
105
|
+
const payload = runtimeConfig.ok ? runtimeConfig.config : {};
|
|
106
|
+
const unavailableDetail = runtimeConfig.ok
|
|
107
|
+
? ""
|
|
108
|
+
: runtimeConfig.reason === "missing"
|
|
109
|
+
? `missing vault runtime/config (${agent})`
|
|
110
|
+
: `vault runtime/config unavailable (${runtimeConfig.error})`;
|
|
121
111
|
const teams = payload.teams;
|
|
122
112
|
const teamsChannel = payload.teamsChannel;
|
|
123
113
|
const bluebubbles = payload.bluebubbles;
|
|
@@ -137,9 +127,7 @@ function senseFactsFromSecrets(agent, senses, secretsPath) {
|
|
|
137
127
|
}
|
|
138
128
|
: {
|
|
139
129
|
configured: false,
|
|
140
|
-
detail:
|
|
141
|
-
? `missing secrets.json (${agent})`
|
|
142
|
-
: `missing ${missing.join("/")}`,
|
|
130
|
+
detail: runtimeConfig.ok ? `missing ${missing.join("/")}` : unavailableDetail,
|
|
143
131
|
};
|
|
144
132
|
}
|
|
145
133
|
if (senses.bluebubbles.enabled) {
|
|
@@ -155,13 +143,17 @@ function senseFactsFromSecrets(agent, senses, secretsPath) {
|
|
|
155
143
|
}
|
|
156
144
|
: {
|
|
157
145
|
configured: false,
|
|
158
|
-
detail:
|
|
159
|
-
? `missing secrets.json (${agent})`
|
|
160
|
-
: `missing ${missing.join("/")}`,
|
|
146
|
+
detail: runtimeConfig.ok ? `missing ${missing.join("/")}` : unavailableDetail,
|
|
161
147
|
};
|
|
162
148
|
}
|
|
163
149
|
return base;
|
|
164
150
|
}
|
|
151
|
+
function senseRepairHint(agent, sense) {
|
|
152
|
+
if (sense === "teams") {
|
|
153
|
+
return `Run 'ouro vault config set --agent ${agent} --key teams.clientId', teams.clientSecret, and teams.tenantId; then run 'ouro up' again.`;
|
|
154
|
+
}
|
|
155
|
+
return `Run 'ouro vault config set --agent ${agent} --key bluebubbles.serverUrl' and bluebubbles.password; then run 'ouro up' again.`;
|
|
156
|
+
}
|
|
165
157
|
function parseSenseSnapshotName(name) {
|
|
166
158
|
const parts = name.split(":");
|
|
167
159
|
if (parts.length !== 2)
|
|
@@ -235,16 +227,15 @@ class DaemonSenseManager {
|
|
|
235
227
|
bundlesRoot;
|
|
236
228
|
constructor(options) {
|
|
237
229
|
const bundlesRoot = options.bundlesRoot ?? path.join(os.homedir(), "AgentBundles");
|
|
238
|
-
const secretsRoot = options.secretsRoot ?? path.join(os.homedir(), ".agentsecrets");
|
|
239
230
|
this.bundlesRoot = bundlesRoot;
|
|
240
231
|
this.contexts = new Map(options.agents.map((agent) => {
|
|
241
232
|
const senses = readAgentSenses(path.join(bundlesRoot, `${agent}.ouro`, "agent.json"));
|
|
242
|
-
const facts =
|
|
233
|
+
const facts = senseFactsFromRuntimeConfig(agent, senses, (0, runtime_credentials_1.readRuntimeCredentialConfig)(agent));
|
|
243
234
|
return [agent, { senses, facts }];
|
|
244
235
|
}));
|
|
245
236
|
const managedSenseAgents = [...this.contexts.entries()].flatMap(([agent, context]) => {
|
|
246
237
|
return ["teams", "bluebubbles"]
|
|
247
|
-
.filter((sense) => context.senses[sense].enabled
|
|
238
|
+
.filter((sense) => context.senses[sense].enabled)
|
|
248
239
|
.map((sense) => ({
|
|
249
240
|
name: `${agent}:${sense}`,
|
|
250
241
|
agentArg: agent,
|
|
@@ -255,6 +246,24 @@ class DaemonSenseManager {
|
|
|
255
246
|
});
|
|
256
247
|
this.processManager = options.processManager ?? new process_manager_1.DaemonProcessManager({
|
|
257
248
|
agents: managedSenseAgents,
|
|
249
|
+
configCheck: async (name) => {
|
|
250
|
+
const parsed = parseSenseSnapshotName(name);
|
|
251
|
+
if (!parsed)
|
|
252
|
+
return { ok: true };
|
|
253
|
+
const context = this.contexts.get(parsed.agent);
|
|
254
|
+
if (!context)
|
|
255
|
+
return { ok: true };
|
|
256
|
+
const refreshed = await (0, runtime_credentials_1.refreshRuntimeCredentialConfig)(parsed.agent, { preserveCachedOnFailure: true });
|
|
257
|
+
context.facts = senseFactsFromRuntimeConfig(parsed.agent, context.senses, refreshed);
|
|
258
|
+
const fact = context.facts[parsed.sense];
|
|
259
|
+
if (fact.configured)
|
|
260
|
+
return { ok: true };
|
|
261
|
+
return {
|
|
262
|
+
ok: false,
|
|
263
|
+
error: `${parsed.sense} is enabled for ${parsed.agent} but runtime credentials are not ready: ${fact.detail}`,
|
|
264
|
+
fix: senseRepairHint(parsed.agent, parsed.sense),
|
|
265
|
+
};
|
|
266
|
+
},
|
|
258
267
|
});
|
|
259
268
|
(0, runtime_1.emitNervesEvent)({
|
|
260
269
|
component: "channels",
|
|
@@ -290,6 +299,7 @@ class DaemonSenseManager {
|
|
|
290
299
|
runtime.set(parsed.agent, current);
|
|
291
300
|
}
|
|
292
301
|
const rows = [...this.contexts.entries()].flatMap(([agent, context]) => {
|
|
302
|
+
context.facts = senseFactsFromRuntimeConfig(agent, context.senses, (0, runtime_credentials_1.readRuntimeCredentialConfig)(agent));
|
|
293
303
|
const blueBubblesRuntimeFacts = readBlueBubblesRuntimeFacts(agent, this.bundlesRoot, runtime.get(agent)?.bluebubbles);
|
|
294
304
|
const runtimeInfo = {
|
|
295
305
|
cli: { configured: true },
|
package/dist/heart/identity.js
CHANGED
|
@@ -48,7 +48,6 @@ exports.getAgentDaemonLogsDir = getAgentDaemonLogsDir;
|
|
|
48
48
|
exports.getAgentDaemonLoggingConfigPath = getAgentDaemonLoggingConfigPath;
|
|
49
49
|
exports.getAgentMessagesRoot = getAgentMessagesRoot;
|
|
50
50
|
exports.getAgentToolsRoot = getAgentToolsRoot;
|
|
51
|
-
exports.getAgentSecretsPath = getAgentSecretsPath;
|
|
52
51
|
exports.loadAgentConfig = loadAgentConfig;
|
|
53
52
|
exports.setAgentName = setAgentName;
|
|
54
53
|
exports.setAgentConfigOverride = setAgentConfigOverride;
|
|
@@ -248,12 +247,6 @@ function getAgentMessagesRoot(agentName) {
|
|
|
248
247
|
function getAgentToolsRoot(agentName) {
|
|
249
248
|
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "tools");
|
|
250
249
|
}
|
|
251
|
-
/**
|
|
252
|
-
* Returns the conventional secrets path: `~/.agentsecrets/<agentName>/secrets.json`
|
|
253
|
-
*/
|
|
254
|
-
function getAgentSecretsPath(agentName = getAgentName()) {
|
|
255
|
-
return path.join(os.homedir(), ".agentsecrets", agentName, "secrets.json");
|
|
256
|
-
}
|
|
257
250
|
const VALID_PROVIDERS = ["azure", "minimax", "anthropic", "openai-codex", "github-copilot"];
|
|
258
251
|
function isValidProvider(value) {
|
|
259
252
|
return typeof value === "string" && VALID_PROVIDERS.includes(value);
|
|
@@ -0,0 +1,181 @@
|
|
|
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.RUNTIME_CONFIG_ITEM_NAME = void 0;
|
|
37
|
+
exports.readRuntimeCredentialConfig = readRuntimeCredentialConfig;
|
|
38
|
+
exports.cacheRuntimeCredentialConfig = cacheRuntimeCredentialConfig;
|
|
39
|
+
exports.refreshRuntimeCredentialConfig = refreshRuntimeCredentialConfig;
|
|
40
|
+
exports.upsertRuntimeCredentialConfig = upsertRuntimeCredentialConfig;
|
|
41
|
+
exports.resetRuntimeCredentialConfigCache = resetRuntimeCredentialConfigCache;
|
|
42
|
+
const crypto = __importStar(require("node:crypto"));
|
|
43
|
+
const runtime_1 = require("../nerves/runtime");
|
|
44
|
+
const credential_access_1 = require("../repertoire/credential-access");
|
|
45
|
+
const identity_1 = require("./identity");
|
|
46
|
+
exports.RUNTIME_CONFIG_ITEM_NAME = "runtime/config";
|
|
47
|
+
let cachedRuntimeConfigs = new Map();
|
|
48
|
+
function isRecord(value) {
|
|
49
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
function stableJson(value) {
|
|
52
|
+
if (Array.isArray(value))
|
|
53
|
+
return `[${value.map(stableJson).join(",")}]`;
|
|
54
|
+
if (isRecord(value)) {
|
|
55
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`).join(",")}}`;
|
|
56
|
+
}
|
|
57
|
+
return JSON.stringify(value);
|
|
58
|
+
}
|
|
59
|
+
function runtimeConfigVaultPath(agentName) {
|
|
60
|
+
return `vault:${agentName}:${exports.RUNTIME_CONFIG_ITEM_NAME}`;
|
|
61
|
+
}
|
|
62
|
+
function runtimeConfigRevision(payload) {
|
|
63
|
+
return `runtime_${crypto
|
|
64
|
+
.createHash("sha256")
|
|
65
|
+
.update(stableJson(payload))
|
|
66
|
+
.digest("hex")
|
|
67
|
+
.slice(0, 16)}`;
|
|
68
|
+
}
|
|
69
|
+
function validateRuntimeCredentialPayload(value) {
|
|
70
|
+
if (!isRecord(value))
|
|
71
|
+
throw new Error("runtime credential payload must be an object");
|
|
72
|
+
if (value.schemaVersion !== 1)
|
|
73
|
+
throw new Error("runtime credential payload schemaVersion must be 1");
|
|
74
|
+
if (value.kind !== "runtime-config")
|
|
75
|
+
throw new Error("runtime credential payload kind must be runtime-config");
|
|
76
|
+
if (typeof value.updatedAt !== "string" || value.updatedAt.trim().length === 0) {
|
|
77
|
+
throw new Error("runtime credential payload updatedAt must be non-empty");
|
|
78
|
+
}
|
|
79
|
+
if (!isRecord(value.config))
|
|
80
|
+
throw new Error("runtime credential payload config must be an object");
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
function resultFromPayload(agentName, payload) {
|
|
84
|
+
return {
|
|
85
|
+
ok: true,
|
|
86
|
+
itemPath: runtimeConfigVaultPath(agentName),
|
|
87
|
+
config: { ...payload.config },
|
|
88
|
+
revision: runtimeConfigRevision(payload),
|
|
89
|
+
updatedAt: payload.updatedAt,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function missingRuntimeConfig(agentName) {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
reason: "missing",
|
|
96
|
+
itemPath: runtimeConfigVaultPath(agentName),
|
|
97
|
+
error: `no runtime credentials stored at ${runtimeConfigVaultPath(agentName)}`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function cacheResult(agentName, result) {
|
|
101
|
+
cachedRuntimeConfigs.set(agentName, result);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
function readRuntimeCredentialConfig(agentName = (0, identity_1.getAgentName)()) {
|
|
105
|
+
return cachedRuntimeConfigs.get(agentName) ?? missingRuntimeConfig(agentName);
|
|
106
|
+
}
|
|
107
|
+
function cacheRuntimeCredentialConfig(agentName, config, now = new Date()) {
|
|
108
|
+
const payload = {
|
|
109
|
+
schemaVersion: 1,
|
|
110
|
+
kind: "runtime-config",
|
|
111
|
+
updatedAt: now.toISOString(),
|
|
112
|
+
config: { ...config },
|
|
113
|
+
};
|
|
114
|
+
return cacheResult(agentName, resultFromPayload(agentName, payload));
|
|
115
|
+
}
|
|
116
|
+
async function refreshRuntimeCredentialConfig(agentName, options = {}) {
|
|
117
|
+
try {
|
|
118
|
+
const store = (0, credential_access_1.getCredentialStore)(agentName);
|
|
119
|
+
const raw = await store.getRawSecret(exports.RUNTIME_CONFIG_ITEM_NAME, "password");
|
|
120
|
+
const payload = validateRuntimeCredentialPayload(JSON.parse(raw));
|
|
121
|
+
const result = resultFromPayload(agentName, payload);
|
|
122
|
+
(0, runtime_1.emitNervesEvent)({
|
|
123
|
+
component: "config/identity",
|
|
124
|
+
event: "config.runtime_credentials_loaded",
|
|
125
|
+
message: "loaded runtime credentials from vault",
|
|
126
|
+
meta: { agentName, itemPath: result.itemPath, revision: result.revision },
|
|
127
|
+
});
|
|
128
|
+
return cacheResult(agentName, result);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
132
|
+
const cached = cachedRuntimeConfigs.get(agentName);
|
|
133
|
+
const reason = message.includes(`no credential found for domain "${exports.RUNTIME_CONFIG_ITEM_NAME}"`)
|
|
134
|
+
? "missing"
|
|
135
|
+
: message.includes("runtime credential payload")
|
|
136
|
+
? "invalid"
|
|
137
|
+
: "unavailable";
|
|
138
|
+
const result = {
|
|
139
|
+
ok: false,
|
|
140
|
+
reason,
|
|
141
|
+
itemPath: runtimeConfigVaultPath(agentName),
|
|
142
|
+
error: reason === "missing" ? `no runtime credentials stored at ${runtimeConfigVaultPath(agentName)}` : message,
|
|
143
|
+
};
|
|
144
|
+
(0, runtime_1.emitNervesEvent)({
|
|
145
|
+
level: reason === "missing" ? "warn" : "error",
|
|
146
|
+
component: "config/identity",
|
|
147
|
+
event: "config.runtime_credentials_unavailable",
|
|
148
|
+
message: "runtime credentials unavailable",
|
|
149
|
+
meta: { agentName, reason, itemPath: result.itemPath },
|
|
150
|
+
});
|
|
151
|
+
if (options.preserveCachedOnFailure && cached?.ok)
|
|
152
|
+
return cached;
|
|
153
|
+
return cacheResult(agentName, result);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function upsertRuntimeCredentialConfig(agentName, config, now = new Date()) {
|
|
157
|
+
const payload = {
|
|
158
|
+
schemaVersion: 1,
|
|
159
|
+
kind: "runtime-config",
|
|
160
|
+
updatedAt: now.toISOString(),
|
|
161
|
+
config: { ...config },
|
|
162
|
+
};
|
|
163
|
+
const store = (0, credential_access_1.getCredentialStore)(agentName);
|
|
164
|
+
await store.store(exports.RUNTIME_CONFIG_ITEM_NAME, {
|
|
165
|
+
username: "runtime/config",
|
|
166
|
+
password: JSON.stringify(payload),
|
|
167
|
+
notes: "Ouro runtime credentials for senses and integrations. Provider credentials live in providers/* items.",
|
|
168
|
+
});
|
|
169
|
+
const result = resultFromPayload(agentName, payload);
|
|
170
|
+
(0, runtime_1.emitNervesEvent)({
|
|
171
|
+
component: "config/identity",
|
|
172
|
+
event: "config.runtime_credentials_upserted",
|
|
173
|
+
message: "upserted runtime credential config in vault",
|
|
174
|
+
meta: { agentName, itemPath: result.itemPath, revision: result.revision },
|
|
175
|
+
});
|
|
176
|
+
cacheResult(agentName, result);
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
function resetRuntimeCredentialConfigCache() {
|
|
180
|
+
cachedRuntimeConfigs = new Map();
|
|
181
|
+
}
|
|
@@ -146,18 +146,7 @@ function readSenseStatusLines() {
|
|
|
146
146
|
teams: { enabled: false },
|
|
147
147
|
bluebubbles: { enabled: false },
|
|
148
148
|
};
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
const raw = fs.readFileSync((0, identity_1.getAgentSecretsPath)(), "utf-8");
|
|
152
|
-
const parsed = JSON.parse(raw);
|
|
153
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
154
|
-
payload = parsed;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
catch { /* v8 ignore start -- defensive: fallback on read failure @preserve */
|
|
158
|
-
payload = {};
|
|
159
|
-
/* v8 ignore stop */
|
|
160
|
-
}
|
|
149
|
+
const payload = (0, config_1.loadConfig)();
|
|
161
150
|
const teams = payload.teams;
|
|
162
151
|
const bluebubbles = payload.bluebubbles;
|
|
163
152
|
const configured = {
|
package/dist/mind/prompt.js
CHANGED
|
@@ -64,6 +64,7 @@ const ouro_version_manager_1 = require("../heart/versioning/ouro-version-manager
|
|
|
64
64
|
const tools_1 = require("../repertoire/tools");
|
|
65
65
|
const skills_1 = require("../repertoire/skills");
|
|
66
66
|
const identity_1 = require("../heart/identity");
|
|
67
|
+
const config_1 = require("../heart/config");
|
|
67
68
|
const runtime_mode_1 = require("../heart/daemon/runtime-mode");
|
|
68
69
|
const types_1 = require("./friends/types");
|
|
69
70
|
const trust_explanation_1 = require("./friends/trust-explanation");
|
|
@@ -416,17 +417,7 @@ function localSenseStatusLines() {
|
|
|
416
417
|
teams: { enabled: false },
|
|
417
418
|
bluebubbles: { enabled: false },
|
|
418
419
|
};
|
|
419
|
-
|
|
420
|
-
try {
|
|
421
|
-
const raw = fs.readFileSync((0, identity_1.getAgentSecretsPath)(), "utf-8");
|
|
422
|
-
const parsed = JSON.parse(raw);
|
|
423
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
424
|
-
payload = parsed;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
catch {
|
|
428
|
-
payload = {};
|
|
429
|
-
}
|
|
420
|
+
const payload = (0, config_1.loadConfig)();
|
|
430
421
|
const teams = payload.teams;
|
|
431
422
|
const bluebubbles = payload.bluebubbles;
|
|
432
423
|
const configured = {
|
|
@@ -454,13 +445,13 @@ function senseRuntimeGuidance(channel, preReadStatusLines) {
|
|
|
454
445
|
lines.push("sense states:");
|
|
455
446
|
lines.push("- interactive = available when opened by the user instead of kept running by the daemon");
|
|
456
447
|
lines.push("- disabled = turned off in agent.json");
|
|
457
|
-
lines.push("- needs_config = enabled but missing required
|
|
448
|
+
lines.push("- needs_config = enabled but missing required vault runtime/config values");
|
|
458
449
|
lines.push("- ready = enabled and configured; `ouro up` should bring it online");
|
|
459
450
|
lines.push("- running = enabled and currently active");
|
|
460
451
|
lines.push("- error = enabled but unhealthy");
|
|
461
|
-
lines.push("If asked how to enable another sense, I explain the relevant agent.json senses entry and required
|
|
462
|
-
lines.push("teams setup truth: enable `senses.teams.enabled`, then
|
|
463
|
-
lines.push("bluebubbles setup truth: enable `senses.bluebubbles.enabled`, then
|
|
452
|
+
lines.push("If asked how to enable another sense, I explain the relevant agent.json senses entry and required agent-vault runtime/config fields instead of guessing.");
|
|
453
|
+
lines.push("teams setup truth: enable `senses.teams.enabled`, then store `teams.clientId`, `teams.clientSecret`, and `teams.tenantId` in the agent vault runtime/config item.");
|
|
454
|
+
lines.push("bluebubbles setup truth: enable `senses.bluebubbles.enabled`, then store `bluebubbles.serverUrl` and `bluebubbles.password` in the agent vault runtime/config item.");
|
|
464
455
|
if (channel === "cli") {
|
|
465
456
|
lines.push("cli is interactive: it is available when the user opens it, not something `ouro up` daemonizes.");
|
|
466
457
|
}
|
|
@@ -127,7 +127,7 @@ exports.notesToolDefinitions = [
|
|
|
127
127
|
try {
|
|
128
128
|
const key = (0, config_1.getIntegrationsConfig)().perplexityApiKey;
|
|
129
129
|
if (!key)
|
|
130
|
-
return "error: perplexityApiKey not configured in
|
|
130
|
+
return "error: perplexityApiKey not configured in the agent vault runtime/config item";
|
|
131
131
|
const res = await fetch("https://api.perplexity.ai/search", {
|
|
132
132
|
method: "POST",
|
|
133
133
|
headers: {
|
|
@@ -110,7 +110,8 @@ function lockedMessage(config, store) {
|
|
|
110
110
|
"This computer does not currently have usable local unlock material for that vault.",
|
|
111
111
|
"This can happen on a new computer, after a local profile or hostname migration, or if the local unlock entry was removed.",
|
|
112
112
|
"",
|
|
113
|
-
`Run \`${command}\` and enter the vault unlock secret from the operator
|
|
113
|
+
`Run \`${command}\` and enter the saved agent vault unlock secret from the human/operator who controls that vault.`,
|
|
114
|
+
"If nobody saved that unlock secret, Ouro cannot recover it; create or rotate the agent vault and re-enter credentials.",
|
|
114
115
|
].join("\n");
|
|
115
116
|
}
|
|
116
117
|
function validateStoreKind(store) {
|
|
@@ -1,13 +1,70 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// Thin entrypoint for `npm run bluebubbles` / `node dist/senses/bluebubbles/entry.js --agent <name>`.
|
|
3
3
|
// Separated from index.ts so the BlueBubbles adapter stays testable.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
4
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
|
|
38
|
+
const agentArgIndex = process.argv.indexOf("--agent");
|
|
39
|
+
const agentName = agentArgIndex >= 0 ? process.argv[agentArgIndex + 1] : undefined;
|
|
40
|
+
if (!agentName) {
|
|
6
41
|
// eslint-disable-next-line no-console -- pre-boot guard: --agent check before imports
|
|
7
42
|
console.error("Missing required --agent <name> argument.\nUsage: node dist/senses/bluebubbles/entry.js --agent ouroboros");
|
|
8
43
|
process.exit(1);
|
|
9
44
|
}
|
|
10
|
-
const index_1 = require("./index");
|
|
11
45
|
const runtime_logging_1 = require("../../heart/daemon/runtime-logging");
|
|
46
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
12
47
|
(0, runtime_logging_1.configureDaemonRuntimeLogger)("bluebubbles");
|
|
13
|
-
(0,
|
|
48
|
+
(0, runtime_1.emitNervesEvent)({
|
|
49
|
+
component: "senses",
|
|
50
|
+
event: "senses.entry_boot",
|
|
51
|
+
message: "booting BlueBubbles entrypoint",
|
|
52
|
+
meta: { entry: "bluebubbles", agentName },
|
|
53
|
+
});
|
|
54
|
+
Promise.resolve().then(() => __importStar(require("../../heart/runtime-credentials"))).then(async ({ refreshRuntimeCredentialConfig }) => {
|
|
55
|
+
await refreshRuntimeCredentialConfig(agentName, { preserveCachedOnFailure: true }).catch(() => undefined);
|
|
56
|
+
const { startBlueBubblesApp } = await Promise.resolve().then(() => __importStar(require("./index")));
|
|
57
|
+
await startBlueBubblesApp();
|
|
58
|
+
})
|
|
59
|
+
.catch((error) => {
|
|
60
|
+
(0, runtime_1.emitNervesEvent)({
|
|
61
|
+
level: "error",
|
|
62
|
+
component: "senses",
|
|
63
|
+
event: "senses.entry_error",
|
|
64
|
+
message: "BlueBubbles entrypoint failed",
|
|
65
|
+
meta: { entry: "bluebubbles", agentName, error: error instanceof Error ? error.message : String(error) },
|
|
66
|
+
});
|
|
67
|
+
// eslint-disable-next-line no-console -- fatal startup guard for sense process
|
|
68
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
package/dist/senses/cli-entry.js
CHANGED
|
@@ -1,15 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
+
})();
|
|
7
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const runtime_1 = require("../nerves/runtime");
|
|
8
37
|
// Fail fast if --agent is missing (before any src/ code tries getAgentName())
|
|
9
|
-
|
|
38
|
+
const agentArgIndex = process.argv.indexOf("--agent");
|
|
39
|
+
const agentName = agentArgIndex >= 0 ? process.argv[agentArgIndex + 1] : undefined;
|
|
40
|
+
if (!agentName) {
|
|
10
41
|
// eslint-disable-next-line no-console -- pre-boot guard: --agent check before imports
|
|
11
42
|
console.error("Missing required --agent <name> argument.\nUsage: node dist/senses/cli-entry.js --agent ouroboros");
|
|
12
43
|
process.exit(1);
|
|
13
44
|
}
|
|
14
|
-
|
|
15
|
-
|
|
45
|
+
(0, runtime_1.emitNervesEvent)({
|
|
46
|
+
component: "senses",
|
|
47
|
+
event: "senses.entry_boot",
|
|
48
|
+
message: "booting CLI entrypoint",
|
|
49
|
+
meta: { entry: "cli", agentName },
|
|
50
|
+
});
|
|
51
|
+
Promise.resolve().then(() => __importStar(require("../heart/runtime-credentials"))).then(async ({ refreshRuntimeCredentialConfig }) => {
|
|
52
|
+
await refreshRuntimeCredentialConfig(agentName, { preserveCachedOnFailure: true }).catch(() => undefined);
|
|
53
|
+
const { main } = await Promise.resolve().then(() => __importStar(require("./cli")));
|
|
54
|
+
main();
|
|
55
|
+
})
|
|
56
|
+
.catch((error) => {
|
|
57
|
+
(0, runtime_1.emitNervesEvent)({
|
|
58
|
+
level: "error",
|
|
59
|
+
component: "senses",
|
|
60
|
+
event: "senses.entry_error",
|
|
61
|
+
message: "CLI entrypoint failed",
|
|
62
|
+
meta: { entry: "cli", agentName, error: error instanceof Error ? error.message : String(error) },
|
|
63
|
+
});
|
|
64
|
+
// eslint-disable-next-line no-console -- fatal startup guard for sense process
|
|
65
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|