@ouro.bot/cli 0.1.0-alpha.3 → 0.1.0-alpha.300
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 +188 -190
- package/SerpentGuide.ouro/agent.json +82 -0
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +6 -3
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +2 -2
- package/SerpentGuide.ouro/psyche/identities/python.md +31 -0
- package/assets/ouroboros.png +0 -0
- package/changelog.json +1888 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +140 -0
- package/dist/arc/episodes.js +117 -0
- package/dist/arc/intentions.js +133 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +237 -0
- package/dist/arc/packets.js +203 -0
- package/dist/arc/presence.js +185 -0
- package/dist/heart/active-work.js +832 -0
- package/dist/heart/agent-entry.js +37 -2
- package/dist/heart/attachments/image-normalize.js +194 -0
- package/dist/heart/attachments/materialize.js +230 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/store.js +103 -0
- package/dist/heart/attachments/types.js +138 -0
- package/dist/heart/auth/auth-flow.js +456 -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/bundle-state.js +168 -0
- package/dist/heart/commitments.js +111 -0
- package/dist/heart/config-registry.js +304 -0
- package/dist/heart/config.js +123 -28
- package/dist/heart/core.js +738 -191
- package/dist/heart/cross-chat-delivery.js +131 -0
- package/dist/heart/daemon/agent-config-check.js +149 -0
- package/dist/heart/daemon/agent-discovery.js +157 -0
- package/dist/heart/daemon/agent-service.js +360 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/cli-defaults.js +574 -0
- package/dist/heart/daemon/cli-exec.js +1945 -0
- package/dist/heart/daemon/cli-parse.js +808 -0
- package/dist/heart/daemon/cli-render.js +503 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/daemon-cli.js +29 -673
- package/dist/heart/daemon/daemon-entry.js +259 -8
- package/dist/heart/daemon/daemon-health.js +136 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +231 -0
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +745 -18
- package/dist/heart/daemon/health-monitor.js +38 -0
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +206 -0
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/launchd.js +171 -0
- package/dist/heart/daemon/log-tailer.js +82 -12
- package/dist/heart/daemon/logs-prune.js +105 -0
- package/dist/heart/daemon/message-router.js +17 -8
- package/dist/heart/daemon/os-cron-deps.js +134 -0
- package/dist/heart/daemon/ouro-bot-entry.js +1 -1
- package/dist/heart/daemon/process-manager.js +181 -1
- package/dist/heart/daemon/pulse.js +463 -0
- package/dist/heart/daemon/run-hooks.js +39 -0
- package/dist/heart/daemon/runtime-logging.js +70 -15
- package/dist/heart/daemon/runtime-metadata.js +219 -0
- package/dist/heart/daemon/runtime-mode.js +67 -0
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +335 -0
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +94 -0
- package/dist/heart/daemon/socket-client.js +307 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/thoughts.js +510 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/habits/habit-migration.js +181 -0
- package/dist/heart/habits/habit-parser.js +140 -0
- package/dist/heart/habits/habit-scheduler.js +371 -0
- package/dist/heart/hatch/hatch-animation.js +35 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +31 -130
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +7 -2
- package/dist/heart/hatch/specialist-orchestrator.js +129 -0
- package/dist/heart/hatch/specialist-prompt.js +101 -0
- package/dist/heart/hatch/specialist-tools.js +283 -0
- package/dist/heart/identity.js +241 -54
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/mcp/mcp-server.js +653 -0
- package/dist/heart/migrate-config.js +127 -0
- package/dist/heart/model-capabilities.js +59 -0
- package/dist/heart/outlook/outlook-http.js +439 -0
- package/dist/heart/outlook/outlook-read.js +1618 -0
- package/dist/heart/outlook/outlook-render.js +1032 -0
- package/dist/heart/outlook/outlook-types.js +7 -0
- package/dist/heart/outlook/outlook-view.js +194 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +88 -0
- package/dist/heart/provider-ping.js +162 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +181 -41
- package/dist/heart/providers/azure.js +98 -11
- package/dist/heart/providers/error-classification.js +63 -0
- package/dist/heart/providers/github-copilot.js +136 -0
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +23 -5
- package/dist/heart/providers/openai-codex.js +33 -22
- package/dist/heart/sense-truth.js +61 -0
- package/dist/heart/session-activity.js +172 -0
- package/dist/heart/session-recall.js +216 -0
- package/dist/heart/start-of-turn-packet.js +339 -0
- package/dist/heart/streaming.js +120 -33
- package/dist/heart/sync.js +332 -0
- package/dist/heart/target-resolution.js +127 -0
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/tool-activity-callbacks.js +36 -0
- package/dist/heart/tool-description.js +135 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +358 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +5 -4
- package/dist/heart/versioning/ouro-path-installer.js +221 -0
- package/dist/heart/{daemon → versioning}/ouro-uti.js +11 -2
- package/dist/heart/versioning/ouro-version-manager.js +295 -0
- package/dist/heart/versioning/staged-restart.js +146 -0
- package/dist/heart/versioning/update-checker.js +113 -0
- package/dist/heart/versioning/update-hooks.js +142 -0
- package/dist/heart/versioning/wrapper-publish-guard.js +86 -0
- package/dist/mind/associative-recall.js +135 -66
- package/dist/mind/bundle-manifest.js +77 -1
- package/dist/mind/context.js +125 -14
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +84 -96
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/first-impressions.js +16 -2
- package/dist/mind/friends/channel.js +64 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/resolver.js +37 -0
- package/dist/mind/friends/store-file.js +58 -3
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +9 -1
- package/dist/mind/journal-index.js +161 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +1011 -107
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +22 -3
- package/dist/nerves/coverage/audit.js +1 -1
- package/dist/nerves/coverage/file-completeness.js +59 -5
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +224 -4
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
- package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
- package/dist/outlook-ui/index.html +15 -0
- package/dist/repertoire/ado-client.js +17 -56
- package/dist/repertoire/ado-semantic.js +11 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +319 -0
- package/dist/repertoire/bundle-templates.js +72 -0
- package/dist/repertoire/bw-installer.js +79 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +330 -0
- package/dist/repertoire/coding/feedback.js +301 -0
- package/dist/repertoire/coding/index.js +4 -1
- package/dist/repertoire/coding/manager.js +220 -13
- package/dist/repertoire/coding/spawner.js +58 -12
- package/dist/repertoire/coding/tools.js +209 -7
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +527 -0
- package/dist/repertoire/data/ado-endpoints.json +188 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +375 -0
- package/dist/repertoire/mcp-client.js +255 -0
- package/dist/repertoire/mcp-manager.js +305 -0
- package/dist/repertoire/mcp-tools.js +63 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +14 -23
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tasks/board.js +43 -5
- package/dist/repertoire/tasks/fix.js +182 -0
- package/dist/repertoire/tasks/index.js +28 -10
- package/dist/repertoire/tasks/lifecycle.js +2 -2
- package/dist/repertoire/tasks/parser.js +3 -2
- package/dist/repertoire/tasks/scanner.js +194 -37
- package/dist/repertoire/tasks/transitions.js +11 -28
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +316 -0
- package/dist/repertoire/tools-base.js +45 -707
- package/dist/repertoire/tools-bluebubbles.js +94 -0
- package/dist/repertoire/tools-bridge.js +141 -0
- package/dist/repertoire/tools-bundle.js +984 -0
- package/dist/repertoire/tools-config.js +185 -0
- package/dist/repertoire/tools-continuity.js +248 -0
- package/dist/repertoire/tools-credential.js +182 -0
- package/dist/repertoire/tools-files.js +342 -0
- package/dist/repertoire/tools-flight.js +224 -0
- package/dist/repertoire/tools-flow.js +105 -0
- package/dist/repertoire/tools-github.js +1 -7
- package/dist/repertoire/tools-memory.js +374 -0
- package/dist/repertoire/tools-session.js +739 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-stripe.js +180 -0
- package/dist/repertoire/tools-surface.js +243 -0
- package/dist/repertoire/tools-teams.js +64 -61
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-user-profile.js +144 -0
- package/dist/repertoire/tools-vault.js +110 -0
- package/dist/repertoire/tools.js +149 -98
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/user-profile.js +118 -0
- package/dist/repertoire/vault-setup.js +241 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/attention-queue.js +116 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/bluebubbles/client.js +568 -0
- package/dist/senses/bluebubbles/entry.js +13 -0
- package/dist/senses/bluebubbles/inbound-log.js +113 -0
- package/dist/senses/bluebubbles/index.js +1427 -0
- package/dist/senses/bluebubbles/media.js +390 -0
- package/dist/senses/bluebubbles/model.js +282 -0
- package/dist/senses/bluebubbles/mutation-log.js +116 -0
- package/dist/senses/bluebubbles/replay.js +129 -0
- package/dist/senses/bluebubbles/runtime-state.js +109 -0
- package/dist/senses/bluebubbles/session-cleanup.js +72 -0
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +595 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +83 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +240 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +1 -1
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +772 -264
- package/dist/senses/commands.js +65 -1
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +112 -19
- package/dist/senses/inner-dialog.js +633 -86
- package/dist/senses/pipeline.js +560 -0
- package/dist/senses/shared-turn.js +195 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams.js +814 -196
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +25 -9
- package/skills/agent-commerce.md +106 -0
- package/skills/browser-navigation.md +110 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +81 -0
- package/skills/travel-planning.md +138 -0
- package/AdoptionSpecialist.ouro/agent.json +0 -20
- package/AdoptionSpecialist.ouro/psyche/identities/python.md +0 -1
- package/dist/heart/daemon/subagent-installer.js +0 -125
- package/dist/inner-worker-entry.js +0 -4
- package/subagents/README.md +0 -73
- package/subagents/work-doer.md +0 -233
- package/subagents/work-merger.md +0 -624
- package/subagents/work-planner.md +0 -373
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
|
@@ -0,0 +1,283 @@
|
|
|
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.getSpecialistTools = getSpecialistTools;
|
|
37
|
+
exports.createSpecialistExecTool = createSpecialistExecTool;
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const tools_base_1 = require("../../repertoire/tools-base");
|
|
42
|
+
const hatch_flow_1 = require("./hatch-flow");
|
|
43
|
+
const hatch_animation_1 = require("./hatch-animation");
|
|
44
|
+
const bundle_manifest_1 = require("../../mind/bundle-manifest");
|
|
45
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
46
|
+
const completeAdoptionTool = {
|
|
47
|
+
type: "function",
|
|
48
|
+
function: {
|
|
49
|
+
name: "complete_adoption",
|
|
50
|
+
description: "finalize the agent bundle and hatch the new agent. call this only when you have written all 5 psyche files and agent.json to the temp directory, and the human has approved the bundle.",
|
|
51
|
+
parameters: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: {
|
|
54
|
+
name: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "the PascalCase name for the new agent (e.g. 'Slugger')",
|
|
57
|
+
},
|
|
58
|
+
handoff_message: {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: "a warm handoff message to display to the human after the agent is hatched",
|
|
61
|
+
},
|
|
62
|
+
phone: {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "the human's phone number (optional, for iMessage contact recognition)",
|
|
65
|
+
},
|
|
66
|
+
teams_handle: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: "the human's Teams email/handle (optional, for Teams contact recognition)",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
required: ["name", "handoff_message"],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
const readFileTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "read_file");
|
|
76
|
+
const writeFileTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "write_file");
|
|
77
|
+
const listDirToolSchema = {
|
|
78
|
+
type: "function",
|
|
79
|
+
function: {
|
|
80
|
+
name: "list_directory",
|
|
81
|
+
description: "list directory contents",
|
|
82
|
+
parameters: {
|
|
83
|
+
type: "object",
|
|
84
|
+
properties: { path: { type: "string" } },
|
|
85
|
+
required: ["path"],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Returns the specialist's tool schema array.
|
|
91
|
+
*/
|
|
92
|
+
function getSpecialistTools() {
|
|
93
|
+
return [completeAdoptionTool, tools_base_1.settleTool, readFileTool.tool, writeFileTool.tool, listDirToolSchema];
|
|
94
|
+
}
|
|
95
|
+
const PSYCHE_FILES = ["SOUL.md", "IDENTITY.md", "LORE.md", "TACIT.md", "ASPIRATIONS.md"];
|
|
96
|
+
function isPascalCase(name) {
|
|
97
|
+
return /^[A-Z][a-zA-Z0-9]*$/.test(name);
|
|
98
|
+
}
|
|
99
|
+
function writeReadme(dir, purpose) {
|
|
100
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
101
|
+
const readmePath = path.join(dir, "README.md");
|
|
102
|
+
/* v8 ignore next -- defensive: guard against re-scaffold on existing bundle @preserve */
|
|
103
|
+
if (!fs.existsSync(readmePath)) {
|
|
104
|
+
fs.writeFileSync(readmePath, `# ${path.basename(dir)}\n\n${purpose}\n`, "utf-8");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function scaffoldBundle(bundleRoot) {
|
|
108
|
+
writeReadme(path.join(bundleRoot, "memory"), "Persistent memory store.");
|
|
109
|
+
writeReadme(path.join(bundleRoot, "memory", "daily"), "Daily memory entries.");
|
|
110
|
+
writeReadme(path.join(bundleRoot, "memory", "archive"), "Archived memory.");
|
|
111
|
+
writeReadme(path.join(bundleRoot, "friends"), "Known friend records.");
|
|
112
|
+
writeReadme(path.join(bundleRoot, "tasks"), "Task files.");
|
|
113
|
+
writeReadme(path.join(bundleRoot, "tasks", "one-shots"), "One-shot tasks.");
|
|
114
|
+
writeReadme(path.join(bundleRoot, "habits"), "Recurring habits and autonomous rhythms.");
|
|
115
|
+
writeReadme(path.join(bundleRoot, "tasks", "ongoing"), "Ongoing tasks.");
|
|
116
|
+
writeReadme(path.join(bundleRoot, "skills"), "Local skill files.");
|
|
117
|
+
writeReadme(path.join(bundleRoot, "senses"), "Sense-specific config.");
|
|
118
|
+
writeReadme(path.join(bundleRoot, "senses", "teams"), "Teams sense config.");
|
|
119
|
+
// Memory scaffold files
|
|
120
|
+
const memoryRoot = path.join(bundleRoot, "memory");
|
|
121
|
+
const factsPath = path.join(memoryRoot, "facts.jsonl");
|
|
122
|
+
const entitiesPath = path.join(memoryRoot, "entities.json");
|
|
123
|
+
/* v8 ignore next -- defensive: guard against re-scaffold on existing bundle @preserve */
|
|
124
|
+
if (!fs.existsSync(factsPath))
|
|
125
|
+
fs.writeFileSync(factsPath, "", "utf-8");
|
|
126
|
+
/* v8 ignore next -- defensive: guard against re-scaffold on existing bundle @preserve */
|
|
127
|
+
if (!fs.existsSync(entitiesPath))
|
|
128
|
+
fs.writeFileSync(entitiesPath, "{}\n", "utf-8");
|
|
129
|
+
// bundle-meta.json
|
|
130
|
+
const meta = (0, bundle_manifest_1.createBundleMeta)();
|
|
131
|
+
fs.writeFileSync(path.join(bundleRoot, "bundle-meta.json"), JSON.stringify(meta, null, 2) + "\n", "utf-8");
|
|
132
|
+
}
|
|
133
|
+
function moveDir(src, dest) {
|
|
134
|
+
try {
|
|
135
|
+
fs.renameSync(src, dest);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
/* v8 ignore start -- cross-device fallback: only triggers on EXDEV (e.g. /tmp → different mount), untestable in CI @preserve */
|
|
139
|
+
fs.cpSync(src, dest, { recursive: true });
|
|
140
|
+
fs.rmSync(src, { recursive: true, force: true });
|
|
141
|
+
/* v8 ignore stop */
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function execCompleteAdoption(args, deps) {
|
|
145
|
+
const name = args.name;
|
|
146
|
+
const handoffMessage = args.handoff_message;
|
|
147
|
+
if (!name) {
|
|
148
|
+
return "error: missing required 'name' parameter";
|
|
149
|
+
}
|
|
150
|
+
if (!isPascalCase(name)) {
|
|
151
|
+
return `error: name '${name}' must be PascalCase (e.g. 'Slugger', 'MyAgent')`;
|
|
152
|
+
}
|
|
153
|
+
// Validate psyche files exist
|
|
154
|
+
const psycheDir = path.join(deps.tempDir, "psyche");
|
|
155
|
+
const missingPsyche = PSYCHE_FILES.filter((f) => !fs.existsSync(path.join(psycheDir, f)));
|
|
156
|
+
if (missingPsyche.length > 0) {
|
|
157
|
+
return `error: missing psyche files in temp directory: ${missingPsyche.join(", ")}. write them first using write_file.`;
|
|
158
|
+
}
|
|
159
|
+
// Validate agent.json exists
|
|
160
|
+
const agentJsonPath = path.join(deps.tempDir, "agent.json");
|
|
161
|
+
if (!fs.existsSync(agentJsonPath)) {
|
|
162
|
+
return "error: agent.json not found in temp directory. write it first using write_file.";
|
|
163
|
+
}
|
|
164
|
+
// Validate target doesn't exist
|
|
165
|
+
const targetBundle = path.join(deps.bundlesRoot, `${name}.ouro`);
|
|
166
|
+
if (fs.existsSync(targetBundle)) {
|
|
167
|
+
return `error: bundle '${name}.ouro' already exists at ${deps.bundlesRoot}. choose a different name.`;
|
|
168
|
+
}
|
|
169
|
+
// Scaffold structural dirs into tempDir
|
|
170
|
+
scaffoldBundle(deps.tempDir);
|
|
171
|
+
// Move tempDir -> final bundle location
|
|
172
|
+
moveDir(deps.tempDir, targetBundle);
|
|
173
|
+
// Write secrets
|
|
174
|
+
try {
|
|
175
|
+
(0, hatch_flow_1.writeSecretsFile)(name, deps.provider, deps.credentials, deps.secretsRoot);
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
// Rollback: remove the moved bundle
|
|
179
|
+
try {
|
|
180
|
+
fs.rmSync(targetBundle, { recursive: true, force: true });
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Best effort cleanup
|
|
184
|
+
}
|
|
185
|
+
return `error: failed to write secrets: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
|
|
186
|
+
}
|
|
187
|
+
// Create initial friend record if contact info provided
|
|
188
|
+
const phone = args.phone;
|
|
189
|
+
const teamsHandle = args.teams_handle;
|
|
190
|
+
if (phone || teamsHandle) {
|
|
191
|
+
const friendId = crypto.randomUUID();
|
|
192
|
+
const now = new Date().toISOString();
|
|
193
|
+
const externalIds = [];
|
|
194
|
+
if (phone)
|
|
195
|
+
externalIds.push({ provider: "imessage-handle", externalId: phone, linkedAt: now });
|
|
196
|
+
if (teamsHandle)
|
|
197
|
+
externalIds.push({ provider: "aad", externalId: teamsHandle, linkedAt: now });
|
|
198
|
+
const friendRecord = {
|
|
199
|
+
id: friendId,
|
|
200
|
+
name: deps.humanName ?? "primary",
|
|
201
|
+
trustLevel: "family",
|
|
202
|
+
externalIds,
|
|
203
|
+
tenantMemberships: [],
|
|
204
|
+
toolPreferences: {},
|
|
205
|
+
notes: {},
|
|
206
|
+
createdAt: now,
|
|
207
|
+
updatedAt: now,
|
|
208
|
+
schemaVersion: 1,
|
|
209
|
+
};
|
|
210
|
+
const friendPath = path.join(targetBundle, "friends", `${friendId}.json`);
|
|
211
|
+
fs.writeFileSync(friendPath, JSON.stringify(friendRecord, null, 2), "utf-8");
|
|
212
|
+
}
|
|
213
|
+
// Play hatch animation
|
|
214
|
+
await (0, hatch_animation_1.playHatchAnimation)(name, deps.animationWriter);
|
|
215
|
+
// Display handoff message
|
|
216
|
+
/* v8 ignore next -- UI-only: handoff message display, covered by integration @preserve */
|
|
217
|
+
if (handoffMessage && deps.animationWriter) {
|
|
218
|
+
deps.animationWriter(`\n${handoffMessage}\n`);
|
|
219
|
+
}
|
|
220
|
+
(0, runtime_1.emitNervesEvent)({
|
|
221
|
+
component: "daemon",
|
|
222
|
+
event: "daemon.adoption_complete",
|
|
223
|
+
message: "adoption completed successfully",
|
|
224
|
+
meta: { agentName: name, bundlePath: targetBundle },
|
|
225
|
+
});
|
|
226
|
+
return JSON.stringify({ success: true, agentName: name, bundlePath: targetBundle });
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Create a specialist tool executor with the given dependencies captured in closure.
|
|
230
|
+
*/
|
|
231
|
+
function createSpecialistExecTool(deps) {
|
|
232
|
+
(0, runtime_1.emitNervesEvent)({
|
|
233
|
+
component: "daemon",
|
|
234
|
+
event: "daemon.specialist_exec_tool_created",
|
|
235
|
+
message: "specialist exec tool created",
|
|
236
|
+
meta: { tempDir: deps.tempDir },
|
|
237
|
+
});
|
|
238
|
+
return async (name, args) => {
|
|
239
|
+
(0, runtime_1.emitNervesEvent)({
|
|
240
|
+
component: "daemon",
|
|
241
|
+
event: "daemon.specialist_tool_exec",
|
|
242
|
+
message: "executing specialist tool",
|
|
243
|
+
meta: { tool: name },
|
|
244
|
+
});
|
|
245
|
+
if (name === "complete_adoption") {
|
|
246
|
+
return execCompleteAdoption(args, deps);
|
|
247
|
+
}
|
|
248
|
+
if (name === "read_file") {
|
|
249
|
+
try {
|
|
250
|
+
return fs.readFileSync(args.path, "utf-8");
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
return `error: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive @preserve */ String(e)}`;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (name === "write_file") {
|
|
257
|
+
try {
|
|
258
|
+
const dir = path.dirname(args.path);
|
|
259
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
260
|
+
const content = typeof args.content === "string"
|
|
261
|
+
? args.content
|
|
262
|
+
: JSON.stringify(args.content, null, 2);
|
|
263
|
+
fs.writeFileSync(args.path, content, "utf-8");
|
|
264
|
+
return `wrote ${args.path}`;
|
|
265
|
+
}
|
|
266
|
+
catch (e) {
|
|
267
|
+
return `error: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive @preserve */ String(e)}`;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (name === "list_directory") {
|
|
271
|
+
try {
|
|
272
|
+
return fs
|
|
273
|
+
.readdirSync(args.path, { withFileTypes: true })
|
|
274
|
+
.map((e) => `${e.isDirectory() ? "d" : "-"} ${e.name}`)
|
|
275
|
+
.join("\n");
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
278
|
+
return `error: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive @preserve */ String(e)}`;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return `error: unknown tool '${name}'`;
|
|
282
|
+
};
|
|
283
|
+
}
|
package/dist/heart/identity.js
CHANGED
|
@@ -33,20 +33,40 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.DEFAULT_AGENT_PHRASES = exports.DEFAULT_AGENT_CONTEXT = void 0;
|
|
36
|
+
exports.HARNESS_CANONICAL_REPO_URL = exports.DEFAULT_AGENT_SENSES = exports.DEFAULT_VAULT_SERVER_URL = exports.DEFAULT_AGENT_PHRASES = exports.DEFAULT_AGENT_CONTEXT = exports.PROVIDER_CREDENTIALS = void 0;
|
|
37
|
+
exports.resolveVaultConfig = resolveVaultConfig;
|
|
38
|
+
exports.normalizeSenses = normalizeSenses;
|
|
37
39
|
exports.buildDefaultAgentTemplate = buildDefaultAgentTemplate;
|
|
38
40
|
exports.getAgentName = getAgentName;
|
|
39
41
|
exports.getRepoRoot = getRepoRoot;
|
|
40
42
|
exports.getAgentBundlesRoot = getAgentBundlesRoot;
|
|
41
43
|
exports.getAgentRoot = getAgentRoot;
|
|
44
|
+
exports.getAgentStateRoot = getAgentStateRoot;
|
|
45
|
+
exports.getAgentRepoWorkspacesRoot = getAgentRepoWorkspacesRoot;
|
|
46
|
+
exports.getAgentDaemonStateRoot = getAgentDaemonStateRoot;
|
|
47
|
+
exports.getAgentDaemonLogsDir = getAgentDaemonLogsDir;
|
|
48
|
+
exports.getAgentDaemonLoggingConfigPath = getAgentDaemonLoggingConfigPath;
|
|
49
|
+
exports.getAgentMessagesRoot = getAgentMessagesRoot;
|
|
50
|
+
exports.getAgentToolsRoot = getAgentToolsRoot;
|
|
42
51
|
exports.getAgentSecretsPath = getAgentSecretsPath;
|
|
43
52
|
exports.loadAgentConfig = loadAgentConfig;
|
|
44
53
|
exports.setAgentName = setAgentName;
|
|
54
|
+
exports.setAgentConfigOverride = setAgentConfigOverride;
|
|
55
|
+
exports.resetAgentConfigCache = resetAgentConfigCache;
|
|
45
56
|
exports.resetIdentity = resetIdentity;
|
|
46
57
|
const fs = __importStar(require("fs"));
|
|
47
58
|
const os = __importStar(require("os"));
|
|
48
59
|
const path = __importStar(require("path"));
|
|
49
60
|
const runtime_1 = require("../nerves/runtime");
|
|
61
|
+
const migrate_config_1 = require("./migrate-config");
|
|
62
|
+
/** Single source of truth for per-provider credential field names, env var mappings, and prompt labels. */
|
|
63
|
+
exports.PROVIDER_CREDENTIALS = {
|
|
64
|
+
anthropic: { required: ["setupToken"], envVars: { ANTHROPIC_API_KEY: "setupToken" }, promptLabels: { setupToken: "Anthropic setup-token" } },
|
|
65
|
+
"openai-codex": { required: ["oauthAccessToken"], envVars: { OPENAI_API_KEY: "oauthAccessToken" }, promptLabels: { oauthAccessToken: "OpenAI Codex OAuth token" } },
|
|
66
|
+
azure: { required: ["apiKey", "endpoint", "deployment"], envVars: { AZURE_OPENAI_API_KEY: "apiKey", AZURE_OPENAI_KEY: "apiKey", AZURE_OPENAI_ENDPOINT: "endpoint", AZURE_OPENAI_DEPLOYMENT: "deployment" }, promptLabels: { apiKey: "Azure API key", endpoint: "Azure endpoint", deployment: "Azure deployment" } },
|
|
67
|
+
minimax: { required: ["apiKey"], envVars: { MINIMAX_API_KEY: "apiKey" }, promptLabels: { apiKey: "MiniMax API key" } },
|
|
68
|
+
"github-copilot": { required: ["githubToken", "baseUrl"], envVars: { GH_TOKEN: "githubToken", GITHUB_TOKEN: "githubToken" }, promptLabels: { githubToken: "GitHub token" } },
|
|
69
|
+
};
|
|
50
70
|
exports.DEFAULT_AGENT_CONTEXT = {
|
|
51
71
|
maxTokens: 80000,
|
|
52
72
|
contextMargin: 20,
|
|
@@ -56,12 +76,85 @@ exports.DEFAULT_AGENT_PHRASES = {
|
|
|
56
76
|
tool: ["running tool"],
|
|
57
77
|
followup: ["processing"],
|
|
58
78
|
};
|
|
79
|
+
exports.DEFAULT_VAULT_SERVER_URL = "https://vault.ouro.bot";
|
|
80
|
+
/**
|
|
81
|
+
* Resolve the vault config for an agent, applying defaults.
|
|
82
|
+
* If vault is not configured in agent.json, returns default values.
|
|
83
|
+
*/
|
|
84
|
+
function resolveVaultConfig(agentName, config) {
|
|
85
|
+
return {
|
|
86
|
+
email: config?.email ?? `${agentName}@ouro.bot`,
|
|
87
|
+
serverUrl: config?.serverUrl ?? exports.DEFAULT_VAULT_SERVER_URL,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
exports.DEFAULT_AGENT_SENSES = {
|
|
91
|
+
cli: { enabled: true },
|
|
92
|
+
teams: { enabled: false },
|
|
93
|
+
bluebubbles: { enabled: false },
|
|
94
|
+
};
|
|
95
|
+
function normalizeSenses(value, configFile) {
|
|
96
|
+
const defaults = {
|
|
97
|
+
cli: { ...exports.DEFAULT_AGENT_SENSES.cli },
|
|
98
|
+
teams: { ...exports.DEFAULT_AGENT_SENSES.teams },
|
|
99
|
+
bluebubbles: { ...exports.DEFAULT_AGENT_SENSES.bluebubbles },
|
|
100
|
+
};
|
|
101
|
+
if (value === undefined) {
|
|
102
|
+
return defaults;
|
|
103
|
+
}
|
|
104
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
105
|
+
(0, runtime_1.emitNervesEvent)({
|
|
106
|
+
level: "error",
|
|
107
|
+
event: "config_identity.error",
|
|
108
|
+
component: "config/identity",
|
|
109
|
+
message: "agent config has invalid senses block",
|
|
110
|
+
meta: { path: configFile },
|
|
111
|
+
});
|
|
112
|
+
throw new Error(`agent.json at ${configFile} must include senses as an object when present.`);
|
|
113
|
+
}
|
|
114
|
+
const raw = value;
|
|
115
|
+
const senseNames = ["cli", "teams", "bluebubbles"];
|
|
116
|
+
for (const senseName of senseNames) {
|
|
117
|
+
const rawSense = raw[senseName];
|
|
118
|
+
if (rawSense === undefined) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (!rawSense || typeof rawSense !== "object" || Array.isArray(rawSense)) {
|
|
122
|
+
(0, runtime_1.emitNervesEvent)({
|
|
123
|
+
level: "error",
|
|
124
|
+
event: "config_identity.error",
|
|
125
|
+
component: "config/identity",
|
|
126
|
+
message: "agent config has invalid sense config",
|
|
127
|
+
meta: { path: configFile, sense: senseName },
|
|
128
|
+
});
|
|
129
|
+
throw new Error(`agent.json at ${configFile} has invalid senses.${senseName} config.`);
|
|
130
|
+
}
|
|
131
|
+
const enabled = rawSense.enabled;
|
|
132
|
+
if (typeof enabled !== "boolean") {
|
|
133
|
+
(0, runtime_1.emitNervesEvent)({
|
|
134
|
+
level: "error",
|
|
135
|
+
event: "config_identity.error",
|
|
136
|
+
component: "config/identity",
|
|
137
|
+
message: "agent config has invalid sense enabled flag",
|
|
138
|
+
meta: { path: configFile, sense: senseName, enabled: enabled ?? null },
|
|
139
|
+
});
|
|
140
|
+
throw new Error(`agent.json at ${configFile} must include senses.${senseName}.enabled as boolean.`);
|
|
141
|
+
}
|
|
142
|
+
defaults[senseName] = { enabled };
|
|
143
|
+
}
|
|
144
|
+
return defaults;
|
|
145
|
+
}
|
|
59
146
|
function buildDefaultAgentTemplate(_agentName) {
|
|
60
147
|
return {
|
|
61
|
-
version:
|
|
148
|
+
version: 2,
|
|
62
149
|
enabled: true,
|
|
63
|
-
provider: "anthropic",
|
|
150
|
+
humanFacing: { provider: "anthropic", model: "claude-opus-4-6" },
|
|
151
|
+
agentFacing: { provider: "anthropic", model: "claude-opus-4-6" },
|
|
64
152
|
context: { ...exports.DEFAULT_AGENT_CONTEXT },
|
|
153
|
+
senses: {
|
|
154
|
+
cli: { ...exports.DEFAULT_AGENT_SENSES.cli },
|
|
155
|
+
teams: { ...exports.DEFAULT_AGENT_SENSES.teams },
|
|
156
|
+
bluebubbles: { ...exports.DEFAULT_AGENT_SENSES.bluebubbles },
|
|
157
|
+
},
|
|
65
158
|
phrases: {
|
|
66
159
|
thinking: [...exports.DEFAULT_AGENT_PHRASES.thinking],
|
|
67
160
|
tool: [...exports.DEFAULT_AGENT_PHRASES.tool],
|
|
@@ -70,7 +163,7 @@ function buildDefaultAgentTemplate(_agentName) {
|
|
|
70
163
|
};
|
|
71
164
|
}
|
|
72
165
|
let _cachedAgentName = null;
|
|
73
|
-
let
|
|
166
|
+
let _agentConfigOverride = null;
|
|
74
167
|
/**
|
|
75
168
|
* Parse `--agent <name>` from process.argv.
|
|
76
169
|
* Caches the result after first parse.
|
|
@@ -111,13 +204,49 @@ function getRepoRoot() {
|
|
|
111
204
|
* Returns the shared bundle root directory: `~/AgentBundles/`
|
|
112
205
|
*/
|
|
113
206
|
function getAgentBundlesRoot() {
|
|
114
|
-
|
|
207
|
+
const homeBase = process.env.WEBSITE_SITE_NAME ? "/home" : os.homedir();
|
|
208
|
+
return path.join(homeBase, "AgentBundles");
|
|
115
209
|
}
|
|
116
210
|
/**
|
|
117
211
|
* Returns the agent-specific bundle directory: `~/AgentBundles/<agentName>.ouro/`
|
|
118
212
|
*/
|
|
119
|
-
function getAgentRoot() {
|
|
120
|
-
return path.join(getAgentBundlesRoot(), `${
|
|
213
|
+
function getAgentRoot(agentName = getAgentName()) {
|
|
214
|
+
return path.join(getAgentBundlesRoot(), `${agentName}.ouro`);
|
|
215
|
+
}
|
|
216
|
+
function resolveOptionalAgentName(agentName) {
|
|
217
|
+
if (agentName && agentName.trim().length > 0)
|
|
218
|
+
return agentName.trim();
|
|
219
|
+
try {
|
|
220
|
+
return getAgentName();
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return "slugger";
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Returns the bundle-local runtime state directory: `~/AgentBundles/<agentName>.ouro/state/`
|
|
228
|
+
*/
|
|
229
|
+
function getAgentStateRoot(agentName) {
|
|
230
|
+
return path.join(getAgentRoot(resolveOptionalAgentName(agentName)), "state");
|
|
231
|
+
}
|
|
232
|
+
exports.HARNESS_CANONICAL_REPO_URL = "https://github.com/ouroborosbot/ouroboros.git";
|
|
233
|
+
function getAgentRepoWorkspacesRoot(agentName) {
|
|
234
|
+
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "workspaces");
|
|
235
|
+
}
|
|
236
|
+
function getAgentDaemonStateRoot(agentName) {
|
|
237
|
+
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "daemon");
|
|
238
|
+
}
|
|
239
|
+
function getAgentDaemonLogsDir(agentName) {
|
|
240
|
+
return path.join(getAgentDaemonStateRoot(resolveOptionalAgentName(agentName)), "logs");
|
|
241
|
+
}
|
|
242
|
+
function getAgentDaemonLoggingConfigPath(agentName) {
|
|
243
|
+
return path.join(getAgentDaemonStateRoot(resolveOptionalAgentName(agentName)), "logging.json");
|
|
244
|
+
}
|
|
245
|
+
function getAgentMessagesRoot(agentName) {
|
|
246
|
+
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "messages");
|
|
247
|
+
}
|
|
248
|
+
function getAgentToolsRoot(agentName) {
|
|
249
|
+
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "tools");
|
|
121
250
|
}
|
|
122
251
|
/**
|
|
123
252
|
* Returns the conventional secrets path: `~/.agentsecrets/<agentName>/secrets.json`
|
|
@@ -125,23 +254,11 @@ function getAgentRoot() {
|
|
|
125
254
|
function getAgentSecretsPath(agentName = getAgentName()) {
|
|
126
255
|
return path.join(os.homedir(), ".agentsecrets", agentName, "secrets.json");
|
|
127
256
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
function loadAgentConfig() {
|
|
134
|
-
if (_cachedAgentConfig) {
|
|
135
|
-
(0, runtime_1.emitNervesEvent)({
|
|
136
|
-
event: "identity.resolve",
|
|
137
|
-
component: "config/identity",
|
|
138
|
-
message: "loaded agent config from cache",
|
|
139
|
-
meta: { source: "cache" },
|
|
140
|
-
});
|
|
141
|
-
return _cachedAgentConfig;
|
|
142
|
-
}
|
|
143
|
-
const agentRoot = getAgentRoot();
|
|
144
|
-
const configFile = path.join(agentRoot, "agent.json");
|
|
257
|
+
const VALID_PROVIDERS = ["azure", "minimax", "anthropic", "openai-codex", "github-copilot"];
|
|
258
|
+
function isValidProvider(value) {
|
|
259
|
+
return typeof value === "string" && VALID_PROVIDERS.includes(value);
|
|
260
|
+
}
|
|
261
|
+
function readAndParseAgentJson(configFile) {
|
|
145
262
|
let raw;
|
|
146
263
|
try {
|
|
147
264
|
raw = fs.readFileSync(configFile, "utf-8");
|
|
@@ -159,9 +276,8 @@ function loadAgentConfig() {
|
|
|
159
276
|
});
|
|
160
277
|
throw new Error(`Cannot read agent.json at ${configFile}. Does the agent directory exist?`);
|
|
161
278
|
}
|
|
162
|
-
let parsed;
|
|
163
279
|
try {
|
|
164
|
-
|
|
280
|
+
return JSON.parse(raw);
|
|
165
281
|
}
|
|
166
282
|
catch (error) {
|
|
167
283
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -176,6 +292,62 @@ function loadAgentConfig() {
|
|
|
176
292
|
});
|
|
177
293
|
throw new Error(`Invalid JSON in agent.json at ${configFile}. Check syntax.`);
|
|
178
294
|
}
|
|
295
|
+
}
|
|
296
|
+
function validateFacingConfig(parsed, facingName, configFile) {
|
|
297
|
+
const raw = parsed[facingName];
|
|
298
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
299
|
+
(0, runtime_1.emitNervesEvent)({
|
|
300
|
+
level: "error",
|
|
301
|
+
event: "config_identity.error",
|
|
302
|
+
component: "config/identity",
|
|
303
|
+
message: `agent config missing or invalid ${facingName}`,
|
|
304
|
+
meta: { path: configFile, [facingName]: raw ?? null },
|
|
305
|
+
});
|
|
306
|
+
throw new Error(`agent.json at ${configFile} must include ${facingName} as { provider, model }.`);
|
|
307
|
+
}
|
|
308
|
+
const facing = raw;
|
|
309
|
+
if (!isValidProvider(facing.provider)) {
|
|
310
|
+
(0, runtime_1.emitNervesEvent)({
|
|
311
|
+
level: "error",
|
|
312
|
+
event: "config_identity.error",
|
|
313
|
+
component: "config/identity",
|
|
314
|
+
message: `agent config has invalid provider in ${facingName}`,
|
|
315
|
+
meta: { path: configFile, provider: facing.provider ?? null },
|
|
316
|
+
});
|
|
317
|
+
throw new Error(`agent.json at ${configFile} ${facingName}.provider must be one of: ${VALID_PROVIDERS.join(", ")}.`);
|
|
318
|
+
}
|
|
319
|
+
if (typeof facing.model !== "string") {
|
|
320
|
+
(0, runtime_1.emitNervesEvent)({
|
|
321
|
+
level: "error",
|
|
322
|
+
event: "config_identity.error",
|
|
323
|
+
component: "config/identity",
|
|
324
|
+
message: `agent config has invalid model in ${facingName}`,
|
|
325
|
+
meta: { path: configFile, model: facing.model ?? null },
|
|
326
|
+
});
|
|
327
|
+
throw new Error(`agent.json at ${configFile} ${facingName}.model must be a string.`);
|
|
328
|
+
}
|
|
329
|
+
return { provider: facing.provider, model: facing.model };
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Load and parse `<agentRoot>/agent.json`.
|
|
333
|
+
* Reads the file fresh on each call unless an override is set.
|
|
334
|
+
* If the config is v1, auto-migrates to v2 via migrateAgentConfigV1ToV2 and re-reads.
|
|
335
|
+
* Throws descriptive error if file is missing or contains invalid JSON.
|
|
336
|
+
*/
|
|
337
|
+
function loadAgentConfig() {
|
|
338
|
+
if (_agentConfigOverride) {
|
|
339
|
+
return _agentConfigOverride;
|
|
340
|
+
}
|
|
341
|
+
const agentRoot = getAgentRoot();
|
|
342
|
+
const configFile = path.join(agentRoot, "agent.json");
|
|
343
|
+
let parsed = readAndParseAgentJson(configFile);
|
|
344
|
+
// Inline migration: v1 -> v2
|
|
345
|
+
const rawVersion = parsed.version;
|
|
346
|
+
const initialVersion = typeof rawVersion === "number" ? rawVersion : 1;
|
|
347
|
+
if (initialVersion < 2) {
|
|
348
|
+
(0, migrate_config_1.migrateAgentConfigV1ToV2)(agentRoot);
|
|
349
|
+
parsed = readAndParseAgentJson(configFile);
|
|
350
|
+
}
|
|
179
351
|
const existingPhrases = parsed.phrases;
|
|
180
352
|
const needsFill = !existingPhrases ||
|
|
181
353
|
!existingPhrases.thinking ||
|
|
@@ -197,27 +369,11 @@ function loadAgentConfig() {
|
|
|
197
369
|
});
|
|
198
370
|
fs.writeFileSync(configFile, JSON.stringify(parsed, null, 2) + "\n", "utf-8");
|
|
199
371
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
(0, runtime_1.emitNervesEvent)({
|
|
206
|
-
level: "error",
|
|
207
|
-
event: "config_identity.error",
|
|
208
|
-
component: "config/identity",
|
|
209
|
-
message: "agent config missing or invalid provider",
|
|
210
|
-
meta: {
|
|
211
|
-
path: configFile,
|
|
212
|
-
provider: rawProvider,
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
throw new Error(`agent.json at ${configFile} must include provider: "azure", "minimax", "anthropic", or "openai-codex".`);
|
|
216
|
-
}
|
|
217
|
-
const rawVersion = parsed.version;
|
|
218
|
-
const version = rawVersion === undefined ? 1 : rawVersion;
|
|
219
|
-
if (typeof version !== "number" ||
|
|
220
|
-
!Number.isInteger(version) ||
|
|
372
|
+
// Validate v2 facing configs
|
|
373
|
+
const humanFacing = validateFacingConfig(parsed, "humanFacing", configFile);
|
|
374
|
+
const agentFacing = validateFacingConfig(parsed, "agentFacing", configFile);
|
|
375
|
+
const version = typeof parsed.version === "number" ? parsed.version : 1;
|
|
376
|
+
if (!Number.isInteger(version) ||
|
|
221
377
|
version < 1) {
|
|
222
378
|
(0, runtime_1.emitNervesEvent)({
|
|
223
379
|
level: "error",
|
|
@@ -226,7 +382,7 @@ function loadAgentConfig() {
|
|
|
226
382
|
message: "agent config missing or invalid version",
|
|
227
383
|
meta: {
|
|
228
384
|
path: configFile,
|
|
229
|
-
version:
|
|
385
|
+
version: parsed.version,
|
|
230
386
|
},
|
|
231
387
|
});
|
|
232
388
|
throw new Error(`agent.json at ${configFile} must include version as integer >= 1.`);
|
|
@@ -246,21 +402,37 @@ function loadAgentConfig() {
|
|
|
246
402
|
});
|
|
247
403
|
throw new Error(`agent.json at ${configFile} must include enabled as boolean.`);
|
|
248
404
|
}
|
|
249
|
-
|
|
405
|
+
// Tolerate deprecated provider field for backward compatibility
|
|
406
|
+
const rawProvider = parsed.provider;
|
|
407
|
+
const provider = isValidProvider(rawProvider) ? rawProvider : undefined;
|
|
408
|
+
// Spread parsed first so any field present in AgentConfig is carried
|
|
409
|
+
// through by default, then explicitly override the fields that need
|
|
410
|
+
// validation or normalization. This eliminates the field-drop bug class
|
|
411
|
+
// that caused the `sync` block (and previously `shell`) to be silently
|
|
412
|
+
// omitted from the returned config. Regression-guarded by the
|
|
413
|
+
// Required<AgentConfig> contract test in identity-contract.test.ts.
|
|
414
|
+
const config = {
|
|
415
|
+
...parsed,
|
|
250
416
|
version,
|
|
251
417
|
enabled,
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
418
|
+
humanFacing,
|
|
419
|
+
agentFacing,
|
|
420
|
+
senses: normalizeSenses(parsed.senses, configFile),
|
|
255
421
|
phrases: parsed.phrases,
|
|
256
422
|
};
|
|
423
|
+
if (provider !== undefined) {
|
|
424
|
+
config.provider = provider;
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
delete config.provider;
|
|
428
|
+
}
|
|
257
429
|
(0, runtime_1.emitNervesEvent)({
|
|
258
430
|
event: "identity.resolve",
|
|
259
431
|
component: "config/identity",
|
|
260
432
|
message: "loaded agent config from disk",
|
|
261
433
|
meta: { source: "disk" },
|
|
262
434
|
});
|
|
263
|
-
return
|
|
435
|
+
return config;
|
|
264
436
|
}
|
|
265
437
|
/**
|
|
266
438
|
* Prime the agent name cache explicitly.
|
|
@@ -271,11 +443,26 @@ function loadAgentConfig() {
|
|
|
271
443
|
function setAgentName(name) {
|
|
272
444
|
_cachedAgentName = name;
|
|
273
445
|
}
|
|
446
|
+
/**
|
|
447
|
+
* Override the agent config returned by loadAgentConfig().
|
|
448
|
+
* When set to a non-null AgentConfig, loadAgentConfig() returns the override
|
|
449
|
+
* instead of reading from disk. When set to null, normal disk-based loading resumes.
|
|
450
|
+
*/
|
|
451
|
+
function setAgentConfigOverride(config) {
|
|
452
|
+
_agentConfigOverride = config;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Preserve the compatibility hook for callers that previously cleared cached
|
|
456
|
+
* disk-backed agent config. Agent config is now read fresh on every call.
|
|
457
|
+
*/
|
|
458
|
+
function resetAgentConfigCache() {
|
|
459
|
+
// No-op: disk-backed agent config is no longer memoized in-process.
|
|
460
|
+
}
|
|
274
461
|
/**
|
|
275
462
|
* Clear all cached identity state.
|
|
276
463
|
* Used in tests and when switching agent context.
|
|
277
464
|
*/
|
|
278
465
|
function resetIdentity() {
|
|
279
466
|
_cachedAgentName = null;
|
|
280
|
-
|
|
467
|
+
_agentConfigOverride = null;
|
|
281
468
|
}
|