@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.
- 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 +325 -0
- package/dist/heart/active-work.js +178 -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/config.js +57 -23
- package/dist/heart/core.js +236 -90
- 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 +351 -0
- package/dist/heart/daemon/daemon-cli.js +1173 -227
- 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 +189 -10
- package/dist/heart/daemon/hatch-animation.js +10 -3
- package/dist/heart/daemon/hatch-flow.js +4 -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 +178 -0
- package/dist/heart/daemon/ouro-uti.js +11 -2
- 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/socket-client.js +202 -0
- package/dist/heart/daemon/specialist-orchestrator.js +53 -84
- package/dist/heart/daemon/specialist-prompt.js +64 -5
- package/dist/heart/daemon/specialist-tools.js +213 -58
- package/dist/heart/daemon/staged-restart.js +114 -0
- package/dist/heart/daemon/subagent-installer.js +48 -7
- package/dist/heart/daemon/thoughts.js +379 -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 +122 -19
- package/dist/heart/kicks.js +1 -19
- package/dist/heart/model-capabilities.js +40 -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/minimax.js +4 -0
- package/dist/heart/providers/openai-codex.js +12 -3
- package/dist/heart/safe-workspace.js +228 -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 +27 -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/pending.js +72 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +299 -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/repertoire/ado-client.js +4 -2
- package/dist/repertoire/coding/feedback.js +134 -0
- package/dist/repertoire/coding/index.js +4 -1
- package/dist/repertoire/coding/manager.js +62 -4
- package/dist/repertoire/coding/spawner.js +3 -3
- package/dist/repertoire/coding/tools.js +41 -2
- package/dist/repertoire/data/ado-endpoints.json +188 -0
- 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 +629 -251
- package/dist/repertoire/tools-bluebubbles.js +93 -0
- package/dist/repertoire/tools-teams.js +58 -25
- package/dist/repertoire/tools.js +92 -48
- 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 +890 -45
- package/dist/senses/cli-layout.js +87 -0
- package/dist/senses/cli.js +345 -144
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/debug-activity.js +148 -0
- package/dist/senses/inner-dialog-worker.js +47 -18
- package/dist/senses/inner-dialog.js +330 -84
- package/dist/senses/pipeline.js +278 -0
- package/dist/senses/teams.js +570 -129
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +14 -3
- package/subagents/README.md +46 -33
- package/subagents/work-doer.md +28 -24
- package/subagents/work-merger.md +24 -30
- package/subagents/work-planner.md +44 -27
- package/dist/heart/daemon/specialist-session.js +0 -142
- package/dist/inner-worker-entry.js +0 -4
|
@@ -3,11 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.toAnthropicMessages = toAnthropicMessages;
|
|
6
7
|
exports.createAnthropicProviderRuntime = createAnthropicProviderRuntime;
|
|
7
8
|
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
8
9
|
const config_1 = require("../config");
|
|
9
10
|
const identity_1 = require("../identity");
|
|
10
11
|
const runtime_1 = require("../../nerves/runtime");
|
|
12
|
+
const streaming_1 = require("../streaming");
|
|
13
|
+
const model_capabilities_1 = require("../model-capabilities");
|
|
11
14
|
const ANTHROPIC_SETUP_TOKEN_PREFIX = "sk-ant-oat01-";
|
|
12
15
|
const ANTHROPIC_SETUP_TOKEN_MIN_LENGTH = 80;
|
|
13
16
|
const ANTHROPIC_OAUTH_BETA_HEADER = "claude-code-20250219,oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14,interleaved-thinking-2025-05-14";
|
|
@@ -21,10 +24,10 @@ function getAnthropicSetupTokenInstructions() {
|
|
|
21
24
|
const agentName = getAnthropicAgentNameForGuidance();
|
|
22
25
|
return [
|
|
23
26
|
"Fix:",
|
|
24
|
-
` 1. Run \`
|
|
25
|
-
" (or run `claude setup-token` and paste the token manually)",
|
|
27
|
+
` 1. Run \`ouro auth --agent ${agentName}\``,
|
|
26
28
|
` 2. Open ${getAnthropicSecretsPathForGuidance()}`,
|
|
27
29
|
" 3. Confirm providers.anthropic.setupToken is set",
|
|
30
|
+
" 4. After reauth, retry the failed ouro command or reconnect this session.",
|
|
28
31
|
].join("\n");
|
|
29
32
|
}
|
|
30
33
|
function getAnthropicReauthGuidance(reason) {
|
|
@@ -92,6 +95,18 @@ function toAnthropicMessages(messages) {
|
|
|
92
95
|
if (msg.role === "assistant") {
|
|
93
96
|
const assistant = msg;
|
|
94
97
|
const blocks = [];
|
|
98
|
+
// Restore thinking blocks before text/tool_use blocks
|
|
99
|
+
const thinkingBlocks = assistant._thinking_blocks;
|
|
100
|
+
if (thinkingBlocks) {
|
|
101
|
+
for (const tb of thinkingBlocks) {
|
|
102
|
+
if (tb.type === "thinking") {
|
|
103
|
+
blocks.push({ type: "thinking", thinking: tb.thinking, signature: tb.signature });
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
blocks.push({ type: "redacted_thinking", data: tb.data });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
95
110
|
const text = toAnthropicTextContent(assistant.content);
|
|
96
111
|
if (text) {
|
|
97
112
|
blocks.push({ type: "text", text });
|
|
@@ -194,11 +209,14 @@ function withAnthropicAuthGuidance(error) {
|
|
|
194
209
|
async function streamAnthropicMessages(client, model, request) {
|
|
195
210
|
const { system, messages } = toAnthropicMessages(request.messages);
|
|
196
211
|
const anthropicTools = toAnthropicTools(request.activeTools);
|
|
212
|
+
const modelCaps = (0, model_capabilities_1.getModelCapabilities)(model);
|
|
213
|
+
const maxTokens = modelCaps.maxOutputTokens ?? 16384;
|
|
197
214
|
const params = {
|
|
198
215
|
model,
|
|
199
|
-
max_tokens:
|
|
216
|
+
max_tokens: maxTokens,
|
|
200
217
|
messages,
|
|
201
218
|
stream: true,
|
|
219
|
+
thinking: { type: "adaptive", effort: request.reasoningEffort ?? "medium" },
|
|
202
220
|
};
|
|
203
221
|
if (system)
|
|
204
222
|
params.system = system;
|
|
@@ -218,6 +236,9 @@ async function streamAnthropicMessages(client, model, request) {
|
|
|
218
236
|
let streamStarted = false;
|
|
219
237
|
let usage;
|
|
220
238
|
const toolCalls = new Map();
|
|
239
|
+
const thinkingBlocks = new Map();
|
|
240
|
+
const redactedBlocks = new Map();
|
|
241
|
+
const answerStreamer = new streaming_1.FinalAnswerStreamer(request.callbacks);
|
|
221
242
|
try {
|
|
222
243
|
for await (const event of response) {
|
|
223
244
|
if (request.signal?.aborted)
|
|
@@ -225,17 +246,29 @@ async function streamAnthropicMessages(client, model, request) {
|
|
|
225
246
|
const eventType = String(event.type ?? "");
|
|
226
247
|
if (eventType === "content_block_start") {
|
|
227
248
|
const block = event.content_block;
|
|
228
|
-
|
|
229
|
-
|
|
249
|
+
const index = Number(event.index);
|
|
250
|
+
if (block?.type === "thinking") {
|
|
251
|
+
thinkingBlocks.set(index, { type: "thinking", thinking: "", signature: "" });
|
|
252
|
+
}
|
|
253
|
+
else if (block?.type === "redacted_thinking") {
|
|
254
|
+
redactedBlocks.set(index, { type: "redacted_thinking", data: String(block.data ?? "") });
|
|
255
|
+
}
|
|
256
|
+
else if (block?.type === "tool_use") {
|
|
230
257
|
const rawInput = block.input;
|
|
231
258
|
const input = rawInput && typeof rawInput === "object"
|
|
232
259
|
? JSON.stringify(rawInput)
|
|
233
260
|
: "";
|
|
261
|
+
const name = String(block.name ?? "");
|
|
234
262
|
toolCalls.set(index, {
|
|
235
263
|
id: String(block.id ?? ""),
|
|
236
|
-
name
|
|
264
|
+
name,
|
|
237
265
|
arguments: input,
|
|
238
266
|
});
|
|
267
|
+
// Activate eager streaming for sole final_answer tool call
|
|
268
|
+
/* v8 ignore next -- final_answer streaming activation, tested via FinalAnswerStreamer unit tests @preserve */
|
|
269
|
+
if (name === "final_answer" && toolCalls.size === 1) {
|
|
270
|
+
answerStreamer.activate();
|
|
271
|
+
}
|
|
239
272
|
}
|
|
240
273
|
continue;
|
|
241
274
|
}
|
|
@@ -257,14 +290,31 @@ async function streamAnthropicMessages(client, model, request) {
|
|
|
257
290
|
request.callbacks.onModelStreamStart();
|
|
258
291
|
streamStarted = true;
|
|
259
292
|
}
|
|
260
|
-
|
|
293
|
+
const thinkingText = String(delta?.thinking ?? "");
|
|
294
|
+
request.callbacks.onReasoningChunk(thinkingText);
|
|
295
|
+
const thinkingIndex = Number(event.index);
|
|
296
|
+
const thinkingBlock = thinkingBlocks.get(thinkingIndex);
|
|
297
|
+
if (thinkingBlock)
|
|
298
|
+
thinkingBlock.thinking += thinkingText;
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
if (deltaType === "signature_delta") {
|
|
302
|
+
const sigIndex = Number(event.index);
|
|
303
|
+
const sigBlock = thinkingBlocks.get(sigIndex);
|
|
304
|
+
if (sigBlock)
|
|
305
|
+
sigBlock.signature += String(delta?.signature ?? "");
|
|
261
306
|
continue;
|
|
262
307
|
}
|
|
263
308
|
if (deltaType === "input_json_delta") {
|
|
264
309
|
const index = Number(event.index);
|
|
265
310
|
const existing = toolCalls.get(index);
|
|
266
311
|
if (existing) {
|
|
267
|
-
|
|
312
|
+
const partialJson = String(delta?.partial_json ?? "");
|
|
313
|
+
existing.arguments = mergeAnthropicToolArguments(existing.arguments, partialJson);
|
|
314
|
+
/* v8 ignore next -- final_answer delta streaming, tested via FinalAnswerStreamer unit tests @preserve */
|
|
315
|
+
if (existing.name === "final_answer" && toolCalls.size === 1) {
|
|
316
|
+
answerStreamer.processDelta(partialJson);
|
|
317
|
+
}
|
|
268
318
|
}
|
|
269
319
|
continue;
|
|
270
320
|
}
|
|
@@ -288,11 +338,20 @@ async function streamAnthropicMessages(client, model, request) {
|
|
|
288
338
|
catch (error) {
|
|
289
339
|
throw withAnthropicAuthGuidance(error);
|
|
290
340
|
}
|
|
341
|
+
// Collect all thinking blocks (regular + redacted) sorted by index to preserve ordering
|
|
342
|
+
const allThinkingIndices = [...thinkingBlocks.keys(), ...redactedBlocks.keys()].sort((a, b) => a - b);
|
|
343
|
+
const outputItems = allThinkingIndices.map((idx) => {
|
|
344
|
+
const tb = thinkingBlocks.get(idx);
|
|
345
|
+
if (tb)
|
|
346
|
+
return tb;
|
|
347
|
+
return redactedBlocks.get(idx);
|
|
348
|
+
});
|
|
291
349
|
return {
|
|
292
350
|
content,
|
|
293
351
|
toolCalls: [...toolCalls.values()],
|
|
294
|
-
outputItems
|
|
352
|
+
outputItems,
|
|
295
353
|
usage,
|
|
354
|
+
finalAnswerStreamed: answerStreamer.streamed,
|
|
296
355
|
};
|
|
297
356
|
}
|
|
298
357
|
function createAnthropicProviderRuntime() {
|
|
@@ -306,6 +365,10 @@ function createAnthropicProviderRuntime() {
|
|
|
306
365
|
if (!(anthropicConfig.model && anthropicConfig.setupToken)) {
|
|
307
366
|
throw new Error(getAnthropicReauthGuidance("provider 'anthropic' is selected in agent.json but providers.anthropic.model/setupToken is incomplete in secrets.json."));
|
|
308
367
|
}
|
|
368
|
+
const modelCaps = (0, model_capabilities_1.getModelCapabilities)(anthropicConfig.model);
|
|
369
|
+
const capabilities = new Set();
|
|
370
|
+
if (modelCaps.reasoningEffort)
|
|
371
|
+
capabilities.add("reasoning-effort");
|
|
309
372
|
const credential = resolveAnthropicSetupTokenCredential();
|
|
310
373
|
const client = new sdk_1.default({
|
|
311
374
|
authToken: credential.token,
|
|
@@ -319,6 +382,8 @@ function createAnthropicProviderRuntime() {
|
|
|
319
382
|
id: "anthropic",
|
|
320
383
|
model: anthropicConfig.model,
|
|
321
384
|
client,
|
|
385
|
+
capabilities,
|
|
386
|
+
supportedReasoningEfforts: modelCaps.reasoningEffort,
|
|
322
387
|
resetTurnState(_messages) {
|
|
323
388
|
// Anthropic request payload is derived from canonical messages each turn.
|
|
324
389
|
},
|
|
@@ -1,35 +1,114 @@
|
|
|
1
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
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createAzureTokenProvider = createAzureTokenProvider;
|
|
3
37
|
exports.createAzureProviderRuntime = createAzureProviderRuntime;
|
|
4
38
|
const openai_1 = require("openai");
|
|
5
39
|
const config_1 = require("../config");
|
|
6
40
|
const runtime_1 = require("../../nerves/runtime");
|
|
7
41
|
const streaming_1 = require("../streaming");
|
|
42
|
+
const model_capabilities_1 = require("../model-capabilities");
|
|
43
|
+
const COGNITIVE_SERVICES_SCOPE = "https://cognitiveservices.azure.com/.default";
|
|
44
|
+
// @azure/identity is imported dynamically (below) rather than at the top level
|
|
45
|
+
// because it's a heavy package (~30+ transitive deps) and we only need it when
|
|
46
|
+
// using the managed-identity auth path. API-key users and other providers
|
|
47
|
+
// shouldn't pay the cold-start cost.
|
|
48
|
+
function createAzureTokenProvider(managedIdentityClientId) {
|
|
49
|
+
let credential = null;
|
|
50
|
+
return async () => {
|
|
51
|
+
try {
|
|
52
|
+
if (!credential) {
|
|
53
|
+
const { DefaultAzureCredential } = await Promise.resolve().then(() => __importStar(require("@azure/identity")));
|
|
54
|
+
const credentialOptions = managedIdentityClientId
|
|
55
|
+
? { managedIdentityClientId }
|
|
56
|
+
: undefined;
|
|
57
|
+
credential = new DefaultAzureCredential(credentialOptions);
|
|
58
|
+
}
|
|
59
|
+
const tokenResponse = await credential.getToken(COGNITIVE_SERVICES_SCOPE);
|
|
60
|
+
return tokenResponse.token;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
64
|
+
throw new Error(`Azure OpenAI authentication failed: ${detail}\n` +
|
|
65
|
+
"To fix this, either:\n" +
|
|
66
|
+
" 1. Set providers.azure.apiKey in secrets.json, or\n" +
|
|
67
|
+
" 2. Run 'az login' to authenticate with your Azure account (for local dev), or\n" +
|
|
68
|
+
" 3. Attach a managed identity to your App Service and set providers.azure.managedIdentityClientId in secrets.json (for deployed environments)");
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
8
72
|
function createAzureProviderRuntime() {
|
|
73
|
+
const azureConfig = (0, config_1.getAzureConfig)();
|
|
74
|
+
const useApiKey = !!azureConfig.apiKey;
|
|
75
|
+
const authMethod = useApiKey ? "key" : "managed-identity";
|
|
9
76
|
(0, runtime_1.emitNervesEvent)({
|
|
10
77
|
component: "engine",
|
|
11
78
|
event: "engine.provider_init",
|
|
12
79
|
message: "azure provider init",
|
|
13
|
-
meta: { provider: "azure" },
|
|
80
|
+
meta: { provider: "azure", authMethod },
|
|
14
81
|
});
|
|
15
|
-
|
|
16
|
-
if (!(azureConfig.apiKey && azureConfig.endpoint && azureConfig.deployment && azureConfig.modelName)) {
|
|
82
|
+
if (!(azureConfig.endpoint && azureConfig.deployment && azureConfig.modelName)) {
|
|
17
83
|
throw new Error("provider 'azure' is selected in agent.json but providers.azure is incomplete in secrets.json.");
|
|
18
84
|
}
|
|
19
|
-
const
|
|
20
|
-
|
|
85
|
+
const modelCaps = (0, model_capabilities_1.getModelCapabilities)(azureConfig.modelName);
|
|
86
|
+
const capabilities = new Set();
|
|
87
|
+
if (modelCaps.reasoningEffort)
|
|
88
|
+
capabilities.add("reasoning-effort");
|
|
89
|
+
const clientOptions = {
|
|
21
90
|
endpoint: azureConfig.endpoint.replace(/\/openai.*$/, ""),
|
|
22
91
|
deployment: azureConfig.deployment,
|
|
23
92
|
apiVersion: azureConfig.apiVersion,
|
|
24
93
|
timeout: 30000,
|
|
25
94
|
maxRetries: 0,
|
|
26
|
-
}
|
|
95
|
+
};
|
|
96
|
+
if (useApiKey) {
|
|
97
|
+
clientOptions.apiKey = azureConfig.apiKey;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const managedIdentityClientId = azureConfig.managedIdentityClientId || undefined;
|
|
101
|
+
clientOptions.azureADTokenProvider = createAzureTokenProvider(managedIdentityClientId);
|
|
102
|
+
}
|
|
103
|
+
const client = new openai_1.AzureOpenAI(clientOptions);
|
|
27
104
|
let nativeInput = null;
|
|
28
105
|
let nativeInstructions = "";
|
|
29
106
|
return {
|
|
30
107
|
id: "azure",
|
|
31
108
|
model: azureConfig.modelName,
|
|
32
109
|
client,
|
|
110
|
+
capabilities,
|
|
111
|
+
supportedReasoningEfforts: modelCaps.reasoningEffort,
|
|
33
112
|
resetTurnState(messages) {
|
|
34
113
|
const { instructions, input } = (0, streaming_1.toResponsesInput)(messages);
|
|
35
114
|
nativeInput = input;
|
|
@@ -48,7 +127,7 @@ function createAzureProviderRuntime() {
|
|
|
48
127
|
input: nativeInput,
|
|
49
128
|
instructions: nativeInstructions,
|
|
50
129
|
tools: (0, streaming_1.toResponsesTools)(request.activeTools),
|
|
51
|
-
reasoning: { effort: "medium", summary: "detailed" },
|
|
130
|
+
reasoning: { effort: request.reasoningEffort ?? "medium", summary: "detailed" },
|
|
52
131
|
stream: true,
|
|
53
132
|
store: false,
|
|
54
133
|
include: ["reasoning.encrypted_content"],
|
|
@@ -8,6 +8,7 @@ const openai_1 = __importDefault(require("openai"));
|
|
|
8
8
|
const config_1 = require("../config");
|
|
9
9
|
const runtime_1 = require("../../nerves/runtime");
|
|
10
10
|
const streaming_1 = require("../streaming");
|
|
11
|
+
const model_capabilities_1 = require("../model-capabilities");
|
|
11
12
|
function createMinimaxProviderRuntime() {
|
|
12
13
|
(0, runtime_1.emitNervesEvent)({
|
|
13
14
|
component: "engine",
|
|
@@ -19,6 +20,8 @@ function createMinimaxProviderRuntime() {
|
|
|
19
20
|
if (!minimaxConfig.apiKey) {
|
|
20
21
|
throw new Error("provider 'minimax' is selected in agent.json but providers.minimax.apiKey is missing in secrets.json.");
|
|
21
22
|
}
|
|
23
|
+
// Registry consulted; MiniMax models return empty defaults (no capabilities to derive)
|
|
24
|
+
(0, model_capabilities_1.getModelCapabilities)(minimaxConfig.model);
|
|
22
25
|
const client = new openai_1.default({
|
|
23
26
|
apiKey: minimaxConfig.apiKey,
|
|
24
27
|
baseURL: "https://api.minimaxi.chat/v1",
|
|
@@ -29,6 +32,7 @@ function createMinimaxProviderRuntime() {
|
|
|
29
32
|
id: "minimax",
|
|
30
33
|
model: minimaxConfig.model,
|
|
31
34
|
client,
|
|
35
|
+
capabilities: new Set(),
|
|
32
36
|
resetTurnState(_messages) {
|
|
33
37
|
// No provider-owned turn state for chat-completions providers.
|
|
34
38
|
},
|
|
@@ -9,6 +9,7 @@ const config_1 = require("../config");
|
|
|
9
9
|
const identity_1 = require("../identity");
|
|
10
10
|
const runtime_1 = require("../../nerves/runtime");
|
|
11
11
|
const streaming_1 = require("../streaming");
|
|
12
|
+
const model_capabilities_1 = require("../model-capabilities");
|
|
12
13
|
const OPENAI_CODEX_AUTH_FAILURE_MARKERS = [
|
|
13
14
|
"authentication failed",
|
|
14
15
|
"unauthorized",
|
|
@@ -27,11 +28,11 @@ function getOpenAICodexOAuthInstructions() {
|
|
|
27
28
|
const agentName = getOpenAICodexAgentNameForGuidance();
|
|
28
29
|
return [
|
|
29
30
|
"Fix:",
|
|
30
|
-
` 1. Run \`
|
|
31
|
-
" (or run `codex login` and set the OAuth token manually)",
|
|
31
|
+
` 1. Run \`ouro auth --agent ${agentName}\``,
|
|
32
32
|
` 2. Open ${getOpenAICodexSecretsPathForGuidance()}`,
|
|
33
33
|
" 3. Confirm providers.openai-codex.oauthAccessToken is set",
|
|
34
34
|
" 4. This provider uses chatgpt.com/backend-api/codex/responses (not api.openai.com/responses).",
|
|
35
|
+
" 5. After reauth, retry the failed ouro command or reconnect this session.",
|
|
35
36
|
].join("\n");
|
|
36
37
|
}
|
|
37
38
|
function getOpenAICodexReauthGuidance(reason) {
|
|
@@ -106,6 +107,12 @@ function createOpenAICodexProviderRuntime() {
|
|
|
106
107
|
if (!chatgptAccountId) {
|
|
107
108
|
throw new Error(getOpenAICodexReauthGuidance("OpenAI Codex OAuth access token is missing a chatgpt_account_id claim required for chatgpt.com/backend-api/codex."));
|
|
108
109
|
}
|
|
110
|
+
const modelCaps = (0, model_capabilities_1.getModelCapabilities)(codexConfig.model);
|
|
111
|
+
const capabilities = new Set();
|
|
112
|
+
if (modelCaps.reasoningEffort)
|
|
113
|
+
capabilities.add("reasoning-effort");
|
|
114
|
+
if (modelCaps.phase)
|
|
115
|
+
capabilities.add("phase-annotation");
|
|
109
116
|
const client = new openai_1.default({
|
|
110
117
|
apiKey: token,
|
|
111
118
|
baseURL: OPENAI_CODEX_BACKEND_BASE_URL,
|
|
@@ -123,6 +130,8 @@ function createOpenAICodexProviderRuntime() {
|
|
|
123
130
|
id: "openai-codex",
|
|
124
131
|
model: codexConfig.model,
|
|
125
132
|
client,
|
|
133
|
+
capabilities,
|
|
134
|
+
supportedReasoningEfforts: modelCaps.reasoningEffort,
|
|
126
135
|
resetTurnState(messages) {
|
|
127
136
|
const { instructions, input } = (0, streaming_1.toResponsesInput)(messages);
|
|
128
137
|
nativeInput = input;
|
|
@@ -141,7 +150,7 @@ function createOpenAICodexProviderRuntime() {
|
|
|
141
150
|
input: nativeInput,
|
|
142
151
|
instructions: nativeInstructions,
|
|
143
152
|
tools: (0, streaming_1.toResponsesTools)(request.activeTools),
|
|
144
|
-
reasoning: { effort: "medium", summary: "detailed" },
|
|
153
|
+
reasoning: { effort: request.reasoningEffort ?? "medium", summary: "detailed" },
|
|
145
154
|
stream: true,
|
|
146
155
|
store: false,
|
|
147
156
|
include: ["reasoning.encrypted_content"],
|
|
@@ -0,0 +1,228 @@
|
|
|
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.resetSafeWorkspaceSelection = resetSafeWorkspaceSelection;
|
|
37
|
+
exports.getActiveSafeWorkspaceSelection = getActiveSafeWorkspaceSelection;
|
|
38
|
+
exports.ensureSafeRepoWorkspace = ensureSafeRepoWorkspace;
|
|
39
|
+
exports.resolveSafeRepoPath = resolveSafeRepoPath;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
const identity_1 = require("./identity");
|
|
44
|
+
const runtime_1 = require("../nerves/runtime");
|
|
45
|
+
let activeSelection = null;
|
|
46
|
+
let cleanupHookRegistered = false;
|
|
47
|
+
function defaultNow() {
|
|
48
|
+
return Date.now();
|
|
49
|
+
}
|
|
50
|
+
function resolveAgentName(explicit) {
|
|
51
|
+
if (explicit && explicit.trim().length > 0)
|
|
52
|
+
return explicit.trim();
|
|
53
|
+
try {
|
|
54
|
+
return (0, identity_1.getAgentName)();
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return "slugger";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function runGit(cwd, args, spawnSync) {
|
|
61
|
+
return spawnSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
62
|
+
}
|
|
63
|
+
function readStdout(result) {
|
|
64
|
+
return (result.stdout ?? Buffer.from("")).toString("utf-8").trim();
|
|
65
|
+
}
|
|
66
|
+
function readStderr(result) {
|
|
67
|
+
return (result.stderr ?? Buffer.from("")).toString("utf-8").trim();
|
|
68
|
+
}
|
|
69
|
+
function assertGitOk(result, action) {
|
|
70
|
+
if (result.error) {
|
|
71
|
+
throw result.error;
|
|
72
|
+
}
|
|
73
|
+
if (result.status !== 0) {
|
|
74
|
+
const detail = readStderr(result) || readStdout(result) || `exit ${result.status ?? "unknown"}`;
|
|
75
|
+
throw new Error(`${action} failed: ${detail}`);
|
|
76
|
+
}
|
|
77
|
+
return readStdout(result);
|
|
78
|
+
}
|
|
79
|
+
function isGitClone(repoRoot, spawnSync) {
|
|
80
|
+
const result = runGit(repoRoot, ["rev-parse", "--is-inside-work-tree"], spawnSync);
|
|
81
|
+
return result.status === 0 && readStdout(result) === "true";
|
|
82
|
+
}
|
|
83
|
+
function readCurrentBranch(repoRoot, spawnSync) {
|
|
84
|
+
return assertGitOk(runGit(repoRoot, ["rev-parse", "--abbrev-ref", "HEAD"], spawnSync), "git branch read");
|
|
85
|
+
}
|
|
86
|
+
function ensureFetchedOrigin(repoRoot, spawnSync) {
|
|
87
|
+
assertGitOk(runGit(repoRoot, ["fetch", "origin"], spawnSync), "git fetch origin");
|
|
88
|
+
}
|
|
89
|
+
function ensureMainFastForward(repoRoot, spawnSync) {
|
|
90
|
+
assertGitOk(runGit(repoRoot, ["pull", "--ff-only", "origin", "main"], spawnSync), "git pull --ff-only origin main");
|
|
91
|
+
}
|
|
92
|
+
function createDedicatedWorktree(repoRoot, workspaceRoot, branchSuffix, existsSync, mkdirSync, rmSync, spawnSync) {
|
|
93
|
+
mkdirSync(path.dirname(workspaceRoot), { recursive: true });
|
|
94
|
+
const branchName = `slugger/${branchSuffix}`;
|
|
95
|
+
if (existsSync(workspaceRoot)) {
|
|
96
|
+
rmSync(workspaceRoot, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
assertGitOk(runGit(repoRoot, ["worktree", "add", "-B", branchName, workspaceRoot, "origin/main"], spawnSync), "git worktree add");
|
|
99
|
+
return { workspaceRoot, created: true };
|
|
100
|
+
}
|
|
101
|
+
function createScratchClone(workspaceRoot, cloneUrl, existsSync, mkdirSync, rmSync, spawnSync) {
|
|
102
|
+
mkdirSync(path.dirname(workspaceRoot), { recursive: true });
|
|
103
|
+
if (existsSync(workspaceRoot)) {
|
|
104
|
+
rmSync(workspaceRoot, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
const result = spawnSync("git", ["clone", "--depth", "1", "--branch", "main", cloneUrl, workspaceRoot], {
|
|
107
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
108
|
+
});
|
|
109
|
+
assertGitOk(result, "git clone");
|
|
110
|
+
return { workspaceRoot, created: true };
|
|
111
|
+
}
|
|
112
|
+
function registerCleanupHook(options) {
|
|
113
|
+
if (cleanupHookRegistered)
|
|
114
|
+
return;
|
|
115
|
+
cleanupHookRegistered = true;
|
|
116
|
+
process.on("exit", () => {
|
|
117
|
+
if (!activeSelection?.cleanupAfterMerge)
|
|
118
|
+
return;
|
|
119
|
+
try {
|
|
120
|
+
options.rmSync(activeSelection.workspaceRoot, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// best effort
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function resetSafeWorkspaceSelection(options = {}) {
|
|
128
|
+
activeSelection = null;
|
|
129
|
+
if (!options.keepCleanupHookRegistered) {
|
|
130
|
+
cleanupHookRegistered = false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function getActiveSafeWorkspaceSelection() {
|
|
134
|
+
return activeSelection;
|
|
135
|
+
}
|
|
136
|
+
function ensureSafeRepoWorkspace(options = {}) {
|
|
137
|
+
if (activeSelection) {
|
|
138
|
+
return activeSelection;
|
|
139
|
+
}
|
|
140
|
+
const repoRoot = options.repoRoot ?? (0, identity_1.getRepoRoot)();
|
|
141
|
+
const agentName = resolveAgentName(options.agentName);
|
|
142
|
+
const canonicalRepoUrl = options.canonicalRepoUrl ?? identity_1.HARNESS_CANONICAL_REPO_URL;
|
|
143
|
+
const workspaceBase = options.workspaceRoot ?? (0, identity_1.getAgentRepoWorkspacesRoot)(agentName);
|
|
144
|
+
const spawnSync = options.spawnSync ?? child_process_1.spawnSync;
|
|
145
|
+
const existsSync = options.existsSync ?? fs.existsSync;
|
|
146
|
+
const mkdirSync = options.mkdirSync ?? fs.mkdirSync;
|
|
147
|
+
const rmSync = options.rmSync ?? fs.rmSync;
|
|
148
|
+
const now = options.now ?? defaultNow;
|
|
149
|
+
const stamp = String(now());
|
|
150
|
+
registerCleanupHook({ rmSync });
|
|
151
|
+
let selection;
|
|
152
|
+
if (isGitClone(repoRoot, spawnSync)) {
|
|
153
|
+
const branch = readCurrentBranch(repoRoot, spawnSync);
|
|
154
|
+
ensureFetchedOrigin(repoRoot, spawnSync);
|
|
155
|
+
if (branch === "main") {
|
|
156
|
+
ensureMainFastForward(repoRoot, spawnSync);
|
|
157
|
+
const worktreeRoot = path.join(workspaceBase, `ouroboros-main-${stamp}`);
|
|
158
|
+
const created = createDedicatedWorktree(repoRoot, worktreeRoot, `safe-workspace-${stamp}`, existsSync, mkdirSync, rmSync, spawnSync);
|
|
159
|
+
selection = {
|
|
160
|
+
runtimeKind: "clone-main",
|
|
161
|
+
repoRoot,
|
|
162
|
+
workspaceRoot: created.workspaceRoot,
|
|
163
|
+
sourceBranch: branch,
|
|
164
|
+
sourceCloneUrl: canonicalRepoUrl,
|
|
165
|
+
cleanupAfterMerge: false,
|
|
166
|
+
created: created.created,
|
|
167
|
+
note: `running from clone on main; fast-forwarded and created dedicated worktree ${created.workspaceRoot}`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const worktreeRoot = path.join(workspaceBase, `ouroboros-origin-main-${stamp}`);
|
|
172
|
+
const created = createDedicatedWorktree(repoRoot, worktreeRoot, `safe-workspace-${stamp}`, existsSync, mkdirSync, rmSync, spawnSync);
|
|
173
|
+
selection = {
|
|
174
|
+
runtimeKind: "clone-non-main",
|
|
175
|
+
repoRoot,
|
|
176
|
+
workspaceRoot: created.workspaceRoot,
|
|
177
|
+
sourceBranch: branch,
|
|
178
|
+
sourceCloneUrl: canonicalRepoUrl,
|
|
179
|
+
cleanupAfterMerge: false,
|
|
180
|
+
created: created.created,
|
|
181
|
+
note: `running from branch ${branch}; defaulted new work from origin/main in dedicated worktree ${created.workspaceRoot}`,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
const scratchRoot = path.join(workspaceBase, `ouroboros-scratch-${stamp}`);
|
|
187
|
+
const created = createScratchClone(scratchRoot, canonicalRepoUrl, existsSync, mkdirSync, rmSync, spawnSync);
|
|
188
|
+
selection = {
|
|
189
|
+
runtimeKind: "installed-runtime",
|
|
190
|
+
repoRoot,
|
|
191
|
+
workspaceRoot: created.workspaceRoot,
|
|
192
|
+
sourceBranch: null,
|
|
193
|
+
sourceCloneUrl: canonicalRepoUrl,
|
|
194
|
+
cleanupAfterMerge: true,
|
|
195
|
+
created: created.created,
|
|
196
|
+
note: `running from installed runtime/wrapper; created scratch clone ${created.workspaceRoot} from ${canonicalRepoUrl}`,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
activeSelection = selection;
|
|
200
|
+
(0, runtime_1.emitNervesEvent)({
|
|
201
|
+
component: "workspace",
|
|
202
|
+
event: "workspace.safe_repo_acquired",
|
|
203
|
+
message: "acquired safe repo workspace before local edits",
|
|
204
|
+
meta: {
|
|
205
|
+
runtimeKind: selection.runtimeKind,
|
|
206
|
+
repoRoot: selection.repoRoot,
|
|
207
|
+
workspaceRoot: selection.workspaceRoot,
|
|
208
|
+
sourceBranch: selection.sourceBranch,
|
|
209
|
+
sourceCloneUrl: selection.sourceCloneUrl,
|
|
210
|
+
cleanupAfterMerge: selection.cleanupAfterMerge,
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
return selection;
|
|
214
|
+
}
|
|
215
|
+
function resolveSafeRepoPath(options) {
|
|
216
|
+
const requestedPath = path.resolve(options.requestedPath);
|
|
217
|
+
const repoRoot = path.resolve(options.repoRoot ?? (0, identity_1.getRepoRoot)());
|
|
218
|
+
if (activeSelection && requestedPath.startsWith(activeSelection.workspaceRoot + path.sep)) {
|
|
219
|
+
return { selection: activeSelection, resolvedPath: requestedPath };
|
|
220
|
+
}
|
|
221
|
+
if (requestedPath !== repoRoot && !requestedPath.startsWith(repoRoot + path.sep)) {
|
|
222
|
+
return { selection: activeSelection, resolvedPath: requestedPath };
|
|
223
|
+
}
|
|
224
|
+
const selection = ensureSafeRepoWorkspace(options);
|
|
225
|
+
const relativePath = requestedPath === repoRoot ? "" : path.relative(repoRoot, requestedPath);
|
|
226
|
+
const resolvedPath = relativePath ? path.join(selection.workspaceRoot, relativePath) : selection.workspaceRoot;
|
|
227
|
+
return { selection, resolvedPath };
|
|
228
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSenseInventory = getSenseInventory;
|
|
4
|
+
const runtime_1 = require("../nerves/runtime");
|
|
5
|
+
const identity_1 = require("./identity");
|
|
6
|
+
const SENSES = [
|
|
7
|
+
{ sense: "cli", label: "CLI", daemonManaged: false },
|
|
8
|
+
{ sense: "teams", label: "Teams", daemonManaged: true },
|
|
9
|
+
{ sense: "bluebubbles", label: "BlueBubbles", daemonManaged: true },
|
|
10
|
+
];
|
|
11
|
+
function configuredSenses(senses) {
|
|
12
|
+
return senses ?? {
|
|
13
|
+
cli: { ...identity_1.DEFAULT_AGENT_SENSES.cli },
|
|
14
|
+
teams: { ...identity_1.DEFAULT_AGENT_SENSES.teams },
|
|
15
|
+
bluebubbles: { ...identity_1.DEFAULT_AGENT_SENSES.bluebubbles },
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function resolveStatus(enabled, daemonManaged, runtimeInfo) {
|
|
19
|
+
if (!enabled) {
|
|
20
|
+
return "disabled";
|
|
21
|
+
}
|
|
22
|
+
if (!daemonManaged) {
|
|
23
|
+
return "interactive";
|
|
24
|
+
}
|
|
25
|
+
if (runtimeInfo?.runtime === "error") {
|
|
26
|
+
return "error";
|
|
27
|
+
}
|
|
28
|
+
if (runtimeInfo?.runtime === "running") {
|
|
29
|
+
return "running";
|
|
30
|
+
}
|
|
31
|
+
if (runtimeInfo?.configured === false) {
|
|
32
|
+
return "needs_config";
|
|
33
|
+
}
|
|
34
|
+
return "ready";
|
|
35
|
+
}
|
|
36
|
+
function getSenseInventory(agent, runtime = {}) {
|
|
37
|
+
const senses = configuredSenses(agent.senses);
|
|
38
|
+
const inventory = SENSES.map(({ sense, label, daemonManaged }) => {
|
|
39
|
+
const enabled = senses[sense].enabled;
|
|
40
|
+
return {
|
|
41
|
+
sense,
|
|
42
|
+
label,
|
|
43
|
+
enabled,
|
|
44
|
+
daemonManaged,
|
|
45
|
+
status: resolveStatus(enabled, daemonManaged, runtime[sense]),
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
(0, runtime_1.emitNervesEvent)({
|
|
49
|
+
component: "channels",
|
|
50
|
+
event: "channel.sense_inventory_built",
|
|
51
|
+
message: "built sense inventory",
|
|
52
|
+
meta: {
|
|
53
|
+
senses: inventory.map((entry) => ({
|
|
54
|
+
sense: entry.sense,
|
|
55
|
+
enabled: entry.enabled,
|
|
56
|
+
status: entry.status,
|
|
57
|
+
})),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
return inventory;
|
|
61
|
+
}
|