@ouro.bot/cli 0.1.0-alpha.2 → 0.1.0-alpha.200
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 +187 -191
- 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/assets/ouroboros.png +0 -0
- package/changelog.json +1248 -0
- package/dist/heart/active-work.js +832 -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/cares.js +179 -0
- package/dist/heart/commitments.js +111 -0
- package/dist/heart/config.js +114 -28
- package/dist/heart/core.js +689 -120
- package/dist/heart/cross-chat-delivery.js +146 -0
- package/dist/heart/daemon/agent-config-check.js +149 -0
- package/dist/heart/daemon/agent-discovery.js +81 -0
- package/dist/heart/daemon/agent-service.js +360 -0
- package/dist/heart/daemon/auth-flow.js +477 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/daemon-cli.js +2897 -193
- package/dist/heart/daemon/daemon-entry.js +194 -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 +123 -0
- package/dist/heart/daemon/daemon.js +488 -13
- package/dist/heart/daemon/habit-migration.js +181 -0
- package/dist/heart/daemon/habit-parser.js +119 -0
- package/dist/heart/daemon/habit-scheduler.js +369 -0
- package/dist/heart/daemon/hatch-animation.js +35 -0
- package/dist/heart/daemon/hatch-flow.js +32 -122
- package/dist/heart/daemon/hatch-specialist.js +7 -2
- 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 +165 -0
- package/dist/heart/daemon/log-tailer.js +4 -3
- package/dist/heart/daemon/mcp-server.js +591 -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-global-installer.js +128 -0
- package/dist/heart/daemon/ouro-bot-wrapper.js +4 -3
- package/dist/heart/daemon/ouro-path-installer.js +221 -0
- package/dist/heart/daemon/ouro-uti.js +11 -2
- package/dist/heart/daemon/ouro-version-manager.js +171 -0
- package/dist/heart/daemon/outlook-http.js +439 -0
- package/dist/heart/daemon/outlook-read.js +1618 -0
- package/dist/heart/daemon/outlook-render.js +1032 -0
- package/dist/heart/daemon/outlook-types.js +7 -0
- package/dist/heart/daemon/outlook-view.js +194 -0
- package/dist/heart/daemon/process-manager.js +94 -1
- package/dist/heart/daemon/run-hooks.js +39 -0
- package/dist/heart/daemon/runtime-logging.js +61 -14
- 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 +314 -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 +202 -0
- package/dist/heart/daemon/specialist-orchestrator.js +129 -0
- package/dist/heart/daemon/specialist-prompt.js +101 -0
- package/dist/heart/daemon/specialist-tools.js +283 -0
- package/dist/heart/daemon/staged-restart.js +138 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/thoughts.js +507 -0
- package/dist/heart/daemon/update-checker.js +111 -0
- package/dist/heart/daemon/update-hooks.js +138 -0
- package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/identity.js +220 -52
- package/dist/heart/intentions.js +173 -0
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/migrate-config.js +127 -0
- package/dist/heart/model-capabilities.js +48 -0
- package/dist/heart/obligations.js +225 -0
- package/dist/heart/presence.js +185 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +88 -0
- package/dist/heart/provider-ping.js +178 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +199 -36
- package/dist/heart/providers/azure.js +116 -10
- package/dist/heart/providers/github-copilot.js +157 -0
- package/dist/heart/providers/minimax.js +33 -3
- package/dist/heart/providers/openai-codex.js +51 -16
- 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 +232 -0
- package/dist/heart/streaming.js +120 -33
- package/dist/heart/sync.js +217 -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-loop.js +200 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/mind/associative-recall.js +122 -32
- package/dist/mind/bundle-manifest.js +77 -1
- package/dist/mind/context.js +125 -14
- package/dist/mind/{memory.js → diary.js} +69 -56
- package/dist/mind/episodes.js +119 -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/store-file.js +36 -0
- 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/obligations.js +138 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +861 -105
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +15 -2
- package/dist/nerves/coverage/audit.js +1 -1
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +63 -3
- package/dist/nerves/observation.js +20 -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 +4 -2
- package/dist/repertoire/ado-semantic.js +11 -5
- 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 +210 -4
- package/dist/repertoire/coding/spawner.js +58 -12
- package/dist/repertoire/coding/tools.js +209 -7
- package/dist/repertoire/data/ado-endpoints.json +188 -0
- package/dist/repertoire/guardrails.js +291 -0
- package/dist/repertoire/mcp-client.js +254 -0
- package/dist/repertoire/mcp-manager.js +251 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +14 -23
- 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/tools-base.js +1360 -271
- package/dist/repertoire/tools-bluebubbles.js +94 -0
- package/dist/repertoire/tools-github.js +1 -6
- package/dist/repertoire/tools-teams.js +65 -59
- package/dist/repertoire/tools.js +318 -91
- 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 +97 -0
- package/dist/senses/bluebubbles-client.js +532 -0
- package/dist/senses/bluebubbles-entry.js +13 -0
- package/dist/senses/bluebubbles-inbound-log.js +109 -0
- package/dist/senses/bluebubbles-media.js +339 -0
- package/dist/senses/bluebubbles-model.js +261 -0
- package/dist/senses/bluebubbles-mutation-log.js +116 -0
- package/dist/senses/bluebubbles-runtime-state.js +109 -0
- package/dist/senses/bluebubbles-session-cleanup.js +72 -0
- package/dist/senses/bluebubbles.js +1327 -0
- package/dist/senses/cli/adapter.js +274 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +349 -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 +198 -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 +687 -262
- 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 +592 -84
- package/dist/senses/pipeline.js +693 -0
- package/dist/senses/shared-turn.js +196 -0
- package/dist/senses/surface-tool.js +95 -0
- package/dist/senses/teams.js +817 -151
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +24 -7
- package/skills/configure-dev-tools.md +81 -0
- package/subagents/README.md +4 -70
- package/AdoptionSpecialist.ouro/agent.json +0 -20
- package/dist/heart/daemon/subagent-installer.js +0 -125
- package/dist/inner-worker-entry.js +0 -4
- package/subagents/work-doer.md +0 -233
- package/subagents/work-merger.md +0 -624
- package/subagents/work-planner.md +0 -373
- /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/python.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,179 @@
|
|
|
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.createCare = createCare;
|
|
37
|
+
exports.readCares = readCares;
|
|
38
|
+
exports.readActiveCares = readActiveCares;
|
|
39
|
+
exports.updateCare = updateCare;
|
|
40
|
+
exports.resolveCare = resolveCare;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const runtime_1 = require("../nerves/runtime");
|
|
44
|
+
const sync_1 = require("./sync");
|
|
45
|
+
function caresDir(agentRoot) {
|
|
46
|
+
return path.join(agentRoot, "arc", "cares");
|
|
47
|
+
}
|
|
48
|
+
function careFilePath(agentRoot, id) {
|
|
49
|
+
return path.join(caresDir(agentRoot), `${id}.json`);
|
|
50
|
+
}
|
|
51
|
+
function generateId() {
|
|
52
|
+
const timestamp = Date.now();
|
|
53
|
+
const random = Math.random().toString(36).slice(2, 10);
|
|
54
|
+
return `care-${timestamp}-${random}`;
|
|
55
|
+
}
|
|
56
|
+
function createCare(agentRoot, input) {
|
|
57
|
+
const now = new Date().toISOString();
|
|
58
|
+
const id = generateId();
|
|
59
|
+
const care = {
|
|
60
|
+
id,
|
|
61
|
+
label: input.label,
|
|
62
|
+
why: input.why,
|
|
63
|
+
kind: input.kind,
|
|
64
|
+
status: input.status,
|
|
65
|
+
salience: input.salience,
|
|
66
|
+
steward: input.steward,
|
|
67
|
+
relatedFriendIds: input.relatedFriendIds,
|
|
68
|
+
relatedAgentIds: input.relatedAgentIds,
|
|
69
|
+
relatedObligationIds: input.relatedObligationIds,
|
|
70
|
+
relatedEpisodeIds: input.relatedEpisodeIds,
|
|
71
|
+
currentRisk: input.currentRisk,
|
|
72
|
+
nextCheckAt: input.nextCheckAt,
|
|
73
|
+
createdAt: now,
|
|
74
|
+
updatedAt: now,
|
|
75
|
+
};
|
|
76
|
+
const dir = caresDir(agentRoot);
|
|
77
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
78
|
+
const filePath = careFilePath(agentRoot, id);
|
|
79
|
+
fs.writeFileSync(filePath, JSON.stringify(care, null, 2), "utf-8");
|
|
80
|
+
(0, sync_1.trackSyncWrite)(filePath);
|
|
81
|
+
(0, runtime_1.emitNervesEvent)({
|
|
82
|
+
component: "heart",
|
|
83
|
+
event: "heart.care_created",
|
|
84
|
+
message: `care created: ${input.label}`,
|
|
85
|
+
meta: { careId: id, status: input.status, salience: input.salience },
|
|
86
|
+
});
|
|
87
|
+
return care;
|
|
88
|
+
}
|
|
89
|
+
function readCares(agentRoot) {
|
|
90
|
+
const dir = caresDir(agentRoot);
|
|
91
|
+
if (!fs.existsSync(dir)) {
|
|
92
|
+
(0, runtime_1.emitNervesEvent)({
|
|
93
|
+
component: "heart",
|
|
94
|
+
event: "heart.cares_read",
|
|
95
|
+
message: "read cares: directory missing, returning empty",
|
|
96
|
+
meta: { count: 0 },
|
|
97
|
+
});
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
const files = fs.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
101
|
+
const cares = [];
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
try {
|
|
104
|
+
const content = fs.readFileSync(path.join(dir, file), "utf-8");
|
|
105
|
+
const care = JSON.parse(content);
|
|
106
|
+
cares.push(care);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Skip malformed JSON files gracefully
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
(0, runtime_1.emitNervesEvent)({
|
|
113
|
+
component: "heart",
|
|
114
|
+
event: "heart.cares_read",
|
|
115
|
+
message: `read ${cares.length} cares`,
|
|
116
|
+
meta: { count: cares.length },
|
|
117
|
+
});
|
|
118
|
+
return cares;
|
|
119
|
+
}
|
|
120
|
+
function readActiveCares(agentRoot) {
|
|
121
|
+
const all = readCares(agentRoot);
|
|
122
|
+
const active = all.filter((c) => c.status === "active" || c.status === "watching");
|
|
123
|
+
(0, runtime_1.emitNervesEvent)({
|
|
124
|
+
component: "heart",
|
|
125
|
+
event: "heart.active_cares_read",
|
|
126
|
+
message: `read ${active.length} active cares`,
|
|
127
|
+
meta: { count: active.length, total: all.length },
|
|
128
|
+
});
|
|
129
|
+
return active;
|
|
130
|
+
}
|
|
131
|
+
function readCareFile(agentRoot, id) {
|
|
132
|
+
const filePath = careFilePath(agentRoot, id);
|
|
133
|
+
if (!fs.existsSync(filePath)) {
|
|
134
|
+
throw new Error(`Care not found: ${id}`);
|
|
135
|
+
}
|
|
136
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
137
|
+
}
|
|
138
|
+
function writeCareFile(agentRoot, care) {
|
|
139
|
+
const filePath = careFilePath(agentRoot, care.id);
|
|
140
|
+
fs.writeFileSync(filePath, JSON.stringify(care, null, 2), "utf-8");
|
|
141
|
+
(0, sync_1.trackSyncWrite)(filePath);
|
|
142
|
+
}
|
|
143
|
+
function updateCare(agentRoot, id, updates) {
|
|
144
|
+
const care = readCareFile(agentRoot, id);
|
|
145
|
+
const now = new Date().toISOString();
|
|
146
|
+
const updated = {
|
|
147
|
+
...care,
|
|
148
|
+
...updates,
|
|
149
|
+
id: care.id, // protect ID from overwrite
|
|
150
|
+
createdAt: care.createdAt, // protect createdAt
|
|
151
|
+
updatedAt: now,
|
|
152
|
+
};
|
|
153
|
+
writeCareFile(agentRoot, updated);
|
|
154
|
+
(0, runtime_1.emitNervesEvent)({
|
|
155
|
+
component: "heart",
|
|
156
|
+
event: "heart.care_updated",
|
|
157
|
+
message: `care updated: ${updated.label}`,
|
|
158
|
+
meta: { careId: id, updates: Object.keys(updates) },
|
|
159
|
+
});
|
|
160
|
+
return updated;
|
|
161
|
+
}
|
|
162
|
+
function resolveCare(agentRoot, id) {
|
|
163
|
+
const care = readCareFile(agentRoot, id);
|
|
164
|
+
const now = new Date().toISOString();
|
|
165
|
+
const resolved = {
|
|
166
|
+
...care,
|
|
167
|
+
status: "resolved",
|
|
168
|
+
resolvedAt: now,
|
|
169
|
+
updatedAt: now,
|
|
170
|
+
};
|
|
171
|
+
writeCareFile(agentRoot, resolved);
|
|
172
|
+
(0, runtime_1.emitNervesEvent)({
|
|
173
|
+
component: "heart",
|
|
174
|
+
event: "heart.care_resolved",
|
|
175
|
+
message: `care resolved: ${resolved.label}`,
|
|
176
|
+
meta: { careId: id },
|
|
177
|
+
});
|
|
178
|
+
return resolved;
|
|
179
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveCommitments = deriveCommitments;
|
|
4
|
+
exports.formatCommitments = formatCommitments;
|
|
5
|
+
const obligations_1 = require("./obligations");
|
|
6
|
+
const runtime_1 = require("../nerves/runtime");
|
|
7
|
+
function describeActiveObligation(obligation) {
|
|
8
|
+
if (obligation.status === "pending") {
|
|
9
|
+
return `i owe ${obligation.origin.friendId}: ${obligation.content}`;
|
|
10
|
+
}
|
|
11
|
+
const surface = obligation.currentSurface?.label;
|
|
12
|
+
const statusText = obligation.status.replaceAll("_", " ");
|
|
13
|
+
if (surface) {
|
|
14
|
+
return `i owe ${obligation.origin.friendId}: ${obligation.content} (${statusText} in ${surface})`;
|
|
15
|
+
}
|
|
16
|
+
return `i owe ${obligation.origin.friendId}: ${obligation.content} (${statusText})`;
|
|
17
|
+
}
|
|
18
|
+
function deriveCommitments(activeWorkFrame, innerJob, pendingObligations) {
|
|
19
|
+
const committedTo = [];
|
|
20
|
+
const completionCriteria = [];
|
|
21
|
+
const safeToIgnore = [];
|
|
22
|
+
// Persistent obligations from the obligation store
|
|
23
|
+
// Sort by status priority: investigating/waiting/updating before pending
|
|
24
|
+
if (pendingObligations && pendingObligations.length > 0) {
|
|
25
|
+
const sorted = [...pendingObligations].sort((a, b) => {
|
|
26
|
+
const advancedA = a.status !== "pending" && a.status !== "fulfilled" ? 0 : 1;
|
|
27
|
+
const advancedB = b.status !== "pending" && b.status !== "fulfilled" ? 0 : 1;
|
|
28
|
+
return advancedA - advancedB;
|
|
29
|
+
});
|
|
30
|
+
let hasAdvancedObligation = false;
|
|
31
|
+
for (const ob of sorted) {
|
|
32
|
+
if (!(0, obligations_1.isOpenObligationStatus)(ob.status))
|
|
33
|
+
continue;
|
|
34
|
+
committedTo.push(describeActiveObligation(ob));
|
|
35
|
+
if (ob.status !== "pending")
|
|
36
|
+
hasAdvancedObligation = true;
|
|
37
|
+
}
|
|
38
|
+
completionCriteria.push("fulfill my outstanding obligations");
|
|
39
|
+
if (hasAdvancedObligation) {
|
|
40
|
+
completionCriteria.push("close my active obligation loops");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Inner job
|
|
44
|
+
if (innerJob.status === "queued" || innerJob.status === "running") {
|
|
45
|
+
const contentSuffix = innerJob.content ? ` -- ${innerJob.content.slice(0, 60)}` : "";
|
|
46
|
+
committedTo.push(`i'm thinking through something privately${contentSuffix}`);
|
|
47
|
+
}
|
|
48
|
+
else if (innerJob.status === "surfaced") {
|
|
49
|
+
committedTo.push("i finished thinking about something and need to bring it back");
|
|
50
|
+
}
|
|
51
|
+
// mustResolveBeforeHandoff
|
|
52
|
+
if (activeWorkFrame.mustResolveBeforeHandoff) {
|
|
53
|
+
committedTo.push("i need to finish what i started before moving on");
|
|
54
|
+
completionCriteria.push("resolve the current thread before moving on");
|
|
55
|
+
}
|
|
56
|
+
// Bridges
|
|
57
|
+
for (const bridge of activeWorkFrame.bridges) {
|
|
58
|
+
committedTo.push(`i have shared work: ${bridge.summary || bridge.objective}`);
|
|
59
|
+
}
|
|
60
|
+
if (activeWorkFrame.bridges.length > 0) {
|
|
61
|
+
completionCriteria.push("keep shared work aligned across sessions");
|
|
62
|
+
}
|
|
63
|
+
// Tasks
|
|
64
|
+
for (const taskName of activeWorkFrame.taskPressure?.liveTaskNames ?? []) {
|
|
65
|
+
committedTo.push(`i'm tracking: ${taskName}`);
|
|
66
|
+
}
|
|
67
|
+
// Obligation completion criteria
|
|
68
|
+
if (innerJob.obligationStatus === "pending") {
|
|
69
|
+
const name = innerJob.origin?.friendName ?? innerJob.origin?.friendId ?? "them";
|
|
70
|
+
completionCriteria.push(`bring my answer back to ${name}`);
|
|
71
|
+
}
|
|
72
|
+
// Default completion criteria
|
|
73
|
+
if (completionCriteria.length === 0) {
|
|
74
|
+
completionCriteria.push("just be present in this conversation");
|
|
75
|
+
}
|
|
76
|
+
// Safe to ignore
|
|
77
|
+
if (innerJob.status === "idle" && !(activeWorkFrame.inner?.hasPending)) {
|
|
78
|
+
safeToIgnore.push("no private thinking in progress");
|
|
79
|
+
}
|
|
80
|
+
if (activeWorkFrame.bridges.length === 0) {
|
|
81
|
+
safeToIgnore.push("no shared work to coordinate");
|
|
82
|
+
}
|
|
83
|
+
if ((activeWorkFrame.taskPressure?.liveTaskNames ?? []).length === 0) {
|
|
84
|
+
safeToIgnore.push("no active tasks to track");
|
|
85
|
+
}
|
|
86
|
+
(0, runtime_1.emitNervesEvent)({
|
|
87
|
+
component: "engine",
|
|
88
|
+
event: "engine.commitments_derive",
|
|
89
|
+
message: "derived commitments frame",
|
|
90
|
+
meta: { committedCount: committedTo.length, criteriaCount: completionCriteria.length },
|
|
91
|
+
});
|
|
92
|
+
return { committedTo, completionCriteria, safeToIgnore };
|
|
93
|
+
}
|
|
94
|
+
function formatCommitments(commitments) {
|
|
95
|
+
const sections = [];
|
|
96
|
+
if (commitments.committedTo.length === 0) {
|
|
97
|
+
sections.push("i'm not holding anything specific right now. i'm free to be present.");
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
sections.push("## what i'm holding right now");
|
|
101
|
+
sections.push("");
|
|
102
|
+
sections.push(commitments.committedTo.map((c) => `- ${c}`).join("\n"));
|
|
103
|
+
}
|
|
104
|
+
sections.push("");
|
|
105
|
+
sections.push("## what \"done\" looks like");
|
|
106
|
+
sections.push(commitments.completionCriteria.map((c) => `- ${c}`).join("\n"));
|
|
107
|
+
sections.push("");
|
|
108
|
+
sections.push("## what i can let go of");
|
|
109
|
+
sections.push(commitments.safeToIgnore.map((c) => `- ${c}`).join("\n"));
|
|
110
|
+
return sections.join("\n");
|
|
111
|
+
}
|
package/dist/heart/config.js
CHANGED
|
@@ -35,63 +35,87 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.loadConfig = loadConfig;
|
|
37
37
|
exports.resetConfigCache = resetConfigCache;
|
|
38
|
-
exports.
|
|
38
|
+
exports.patchRuntimeConfig = patchRuntimeConfig;
|
|
39
39
|
exports.getAzureConfig = getAzureConfig;
|
|
40
40
|
exports.getMinimaxConfig = getMinimaxConfig;
|
|
41
41
|
exports.getAnthropicConfig = getAnthropicConfig;
|
|
42
42
|
exports.getOpenAICodexConfig = getOpenAICodexConfig;
|
|
43
|
+
exports.getGithubCopilotConfig = getGithubCopilotConfig;
|
|
43
44
|
exports.getTeamsConfig = getTeamsConfig;
|
|
45
|
+
exports.getTeamsSecondaryConfig = getTeamsSecondaryConfig;
|
|
44
46
|
exports.getContextConfig = getContextConfig;
|
|
45
47
|
exports.getOAuthConfig = getOAuthConfig;
|
|
48
|
+
exports.resolveOAuthForTenant = resolveOAuthForTenant;
|
|
46
49
|
exports.getTeamsChannelConfig = getTeamsChannelConfig;
|
|
50
|
+
exports.getBlueBubblesConfig = getBlueBubblesConfig;
|
|
51
|
+
exports.getBlueBubblesChannelConfig = getBlueBubblesChannelConfig;
|
|
47
52
|
exports.getIntegrationsConfig = getIntegrationsConfig;
|
|
53
|
+
exports.getSyncConfig = getSyncConfig;
|
|
48
54
|
exports.getOpenAIEmbeddingsApiKey = getOpenAIEmbeddingsApiKey;
|
|
49
55
|
exports.getLogsDir = getLogsDir;
|
|
56
|
+
exports.sanitizeKey = sanitizeKey;
|
|
57
|
+
exports.slugify = slugify;
|
|
58
|
+
exports.resolveSessionPath = resolveSessionPath;
|
|
50
59
|
exports.sessionPath = sessionPath;
|
|
51
60
|
exports.logPath = logPath;
|
|
52
61
|
const fs = __importStar(require("fs"));
|
|
53
62
|
const path = __importStar(require("path"));
|
|
54
|
-
const os = __importStar(require("os"));
|
|
55
63
|
const identity_1 = require("./identity");
|
|
56
64
|
const runtime_1 = require("../nerves/runtime");
|
|
57
65
|
const DEFAULT_SECRETS_TEMPLATE = {
|
|
58
66
|
providers: {
|
|
59
|
-
// Keep provider field ordering consistent: model first, then auth credentials,
|
|
60
|
-
// then provider-specific transport fields.
|
|
61
67
|
azure: {
|
|
62
|
-
modelName: "",
|
|
63
68
|
apiKey: "",
|
|
64
69
|
endpoint: "",
|
|
65
70
|
deployment: "",
|
|
66
71
|
apiVersion: "2025-04-01-preview",
|
|
72
|
+
managedIdentityClientId: "",
|
|
67
73
|
},
|
|
68
74
|
minimax: {
|
|
69
|
-
model: "",
|
|
70
75
|
apiKey: "",
|
|
71
76
|
},
|
|
72
77
|
anthropic: {
|
|
73
|
-
model: "claude-opus-4-6",
|
|
74
78
|
setupToken: "",
|
|
75
79
|
},
|
|
76
80
|
"openai-codex": {
|
|
77
|
-
model: "gpt-5.2",
|
|
78
81
|
oauthAccessToken: "",
|
|
79
82
|
},
|
|
83
|
+
"github-copilot": {
|
|
84
|
+
githubToken: "",
|
|
85
|
+
baseUrl: "",
|
|
86
|
+
},
|
|
80
87
|
},
|
|
81
88
|
teams: {
|
|
82
89
|
clientId: "",
|
|
83
90
|
clientSecret: "",
|
|
84
91
|
tenantId: "",
|
|
92
|
+
managedIdentityClientId: "",
|
|
85
93
|
},
|
|
86
94
|
oauth: {
|
|
87
95
|
graphConnectionName: "graph",
|
|
88
96
|
adoConnectionName: "ado",
|
|
89
97
|
githubConnectionName: "",
|
|
90
98
|
},
|
|
99
|
+
teamsSecondary: {
|
|
100
|
+
clientId: "",
|
|
101
|
+
clientSecret: "",
|
|
102
|
+
tenantId: "",
|
|
103
|
+
managedIdentityClientId: "",
|
|
104
|
+
},
|
|
91
105
|
teamsChannel: {
|
|
92
106
|
skipConfirmation: true,
|
|
93
107
|
port: 3978,
|
|
94
108
|
},
|
|
109
|
+
bluebubbles: {
|
|
110
|
+
serverUrl: "",
|
|
111
|
+
password: "",
|
|
112
|
+
accountId: "default",
|
|
113
|
+
},
|
|
114
|
+
bluebubblesChannel: {
|
|
115
|
+
port: 18790,
|
|
116
|
+
webhookPath: "/bluebubbles-webhook",
|
|
117
|
+
requestTimeoutMs: 30000,
|
|
118
|
+
},
|
|
95
119
|
integrations: {
|
|
96
120
|
perplexityApiKey: "",
|
|
97
121
|
openaiEmbeddingsApiKey: "",
|
|
@@ -104,15 +128,19 @@ function defaultRuntimeConfig() {
|
|
|
104
128
|
minimax: { ...DEFAULT_SECRETS_TEMPLATE.providers.minimax },
|
|
105
129
|
anthropic: { ...DEFAULT_SECRETS_TEMPLATE.providers.anthropic },
|
|
106
130
|
"openai-codex": { ...DEFAULT_SECRETS_TEMPLATE.providers["openai-codex"] },
|
|
131
|
+
"github-copilot": { ...DEFAULT_SECRETS_TEMPLATE.providers["github-copilot"] },
|
|
107
132
|
},
|
|
108
133
|
teams: { ...DEFAULT_SECRETS_TEMPLATE.teams },
|
|
134
|
+
teamsSecondary: { ...DEFAULT_SECRETS_TEMPLATE.teamsSecondary },
|
|
109
135
|
oauth: { ...DEFAULT_SECRETS_TEMPLATE.oauth },
|
|
110
136
|
context: { ...identity_1.DEFAULT_AGENT_CONTEXT },
|
|
111
137
|
teamsChannel: { ...DEFAULT_SECRETS_TEMPLATE.teamsChannel },
|
|
138
|
+
bluebubbles: { ...DEFAULT_SECRETS_TEMPLATE.bluebubbles },
|
|
139
|
+
bluebubblesChannel: { ...DEFAULT_SECRETS_TEMPLATE.bluebubblesChannel },
|
|
112
140
|
integrations: { ...DEFAULT_SECRETS_TEMPLATE.integrations },
|
|
113
141
|
};
|
|
114
142
|
}
|
|
115
|
-
let
|
|
143
|
+
let _runtimeConfigOverride = null;
|
|
116
144
|
let _testContextOverride = null;
|
|
117
145
|
function resolveConfigPath() {
|
|
118
146
|
return (0, identity_1.getAgentSecretsPath)();
|
|
@@ -134,15 +162,6 @@ function deepMerge(defaults, partial) {
|
|
|
134
162
|
return result;
|
|
135
163
|
}
|
|
136
164
|
function loadConfig() {
|
|
137
|
-
if (_cachedConfig) {
|
|
138
|
-
(0, runtime_1.emitNervesEvent)({
|
|
139
|
-
event: "config.load",
|
|
140
|
-
component: "config/identity",
|
|
141
|
-
message: "config loaded from cache",
|
|
142
|
-
meta: { source: "cache" },
|
|
143
|
-
});
|
|
144
|
-
return _cachedConfig;
|
|
145
|
-
}
|
|
146
165
|
const configPath = resolveConfigPath();
|
|
147
166
|
// Auto-create config directory if it doesn't exist
|
|
148
167
|
const configDir = path.dirname(configPath);
|
|
@@ -203,7 +222,10 @@ function loadConfig() {
|
|
|
203
222
|
},
|
|
204
223
|
});
|
|
205
224
|
}
|
|
206
|
-
|
|
225
|
+
const mergedConfig = deepMerge(defaultRuntimeConfig(), sanitizedFileData);
|
|
226
|
+
const config = _runtimeConfigOverride
|
|
227
|
+
? deepMerge(mergedConfig, _runtimeConfigOverride)
|
|
228
|
+
: mergedConfig;
|
|
207
229
|
(0, runtime_1.emitNervesEvent)({
|
|
208
230
|
event: "config.load",
|
|
209
231
|
component: "config/identity",
|
|
@@ -211,22 +233,22 @@ function loadConfig() {
|
|
|
211
233
|
meta: {
|
|
212
234
|
source: "disk",
|
|
213
235
|
used_defaults_only: Object.keys(fileData).length === 0,
|
|
236
|
+
override_applied: _runtimeConfigOverride !== null,
|
|
214
237
|
},
|
|
215
238
|
});
|
|
216
|
-
return
|
|
239
|
+
return config;
|
|
217
240
|
}
|
|
218
241
|
function resetConfigCache() {
|
|
219
|
-
|
|
242
|
+
_runtimeConfigOverride = null;
|
|
220
243
|
_testContextOverride = null;
|
|
221
244
|
}
|
|
222
|
-
function
|
|
223
|
-
loadConfig(); // ensure _cachedConfig exists
|
|
245
|
+
function patchRuntimeConfig(partial) {
|
|
224
246
|
const contextPatch = partial.context;
|
|
225
247
|
if (contextPatch) {
|
|
226
248
|
const base = _testContextOverride ?? identity_1.DEFAULT_AGENT_CONTEXT;
|
|
227
249
|
_testContextOverride = deepMerge(base, contextPatch);
|
|
228
250
|
}
|
|
229
|
-
|
|
251
|
+
_runtimeConfigOverride = deepMerge((_runtimeConfigOverride ?? {}), partial);
|
|
230
252
|
}
|
|
231
253
|
function getAzureConfig() {
|
|
232
254
|
const config = loadConfig();
|
|
@@ -244,10 +266,18 @@ function getOpenAICodexConfig() {
|
|
|
244
266
|
const config = loadConfig();
|
|
245
267
|
return { ...config.providers["openai-codex"] };
|
|
246
268
|
}
|
|
269
|
+
function getGithubCopilotConfig() {
|
|
270
|
+
const config = loadConfig();
|
|
271
|
+
return { ...config.providers["github-copilot"] };
|
|
272
|
+
}
|
|
247
273
|
function getTeamsConfig() {
|
|
248
274
|
const config = loadConfig();
|
|
249
275
|
return { ...config.teams };
|
|
250
276
|
}
|
|
277
|
+
function getTeamsSecondaryConfig() {
|
|
278
|
+
const config = loadConfig();
|
|
279
|
+
return { ...config.teamsSecondary };
|
|
280
|
+
}
|
|
251
281
|
function getContextConfig() {
|
|
252
282
|
if (_testContextOverride) {
|
|
253
283
|
return { ..._testContextOverride };
|
|
@@ -268,29 +298,85 @@ function getOAuthConfig() {
|
|
|
268
298
|
const config = loadConfig();
|
|
269
299
|
return { ...config.oauth };
|
|
270
300
|
}
|
|
301
|
+
/** Resolve OAuth connection names for a specific tenant, falling back to defaults. */
|
|
302
|
+
function resolveOAuthForTenant(tenantId) {
|
|
303
|
+
const base = getOAuthConfig();
|
|
304
|
+
const overrides = tenantId ? base.tenantOverrides?.[tenantId] : undefined;
|
|
305
|
+
return {
|
|
306
|
+
graphConnectionName: overrides?.graphConnectionName ?? base.graphConnectionName,
|
|
307
|
+
adoConnectionName: overrides?.adoConnectionName ?? base.adoConnectionName,
|
|
308
|
+
githubConnectionName: overrides?.githubConnectionName ?? base.githubConnectionName,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
271
311
|
function getTeamsChannelConfig() {
|
|
272
312
|
const config = loadConfig();
|
|
273
313
|
const { skipConfirmation, flushIntervalMs, port } = config.teamsChannel;
|
|
274
314
|
return { skipConfirmation, flushIntervalMs, port };
|
|
275
315
|
}
|
|
316
|
+
function getBlueBubblesConfig() {
|
|
317
|
+
const config = loadConfig();
|
|
318
|
+
const { serverUrl, password, accountId } = config.bluebubbles;
|
|
319
|
+
if (!serverUrl.trim()) {
|
|
320
|
+
throw new Error("bluebubbles.serverUrl is required in secrets.json to run the BlueBubbles sense.");
|
|
321
|
+
}
|
|
322
|
+
if (!password.trim()) {
|
|
323
|
+
throw new Error("bluebubbles.password is required in secrets.json to run the BlueBubbles sense.");
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
serverUrl: serverUrl.trim(),
|
|
327
|
+
password: password.trim(),
|
|
328
|
+
accountId: accountId.trim() || "default",
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function getBlueBubblesChannelConfig() {
|
|
332
|
+
const config = loadConfig();
|
|
333
|
+
const { port, webhookPath, requestTimeoutMs } = config.bluebubblesChannel;
|
|
334
|
+
return { port, webhookPath, requestTimeoutMs };
|
|
335
|
+
}
|
|
276
336
|
function getIntegrationsConfig() {
|
|
277
337
|
const config = loadConfig();
|
|
278
338
|
return { ...config.integrations };
|
|
279
339
|
}
|
|
340
|
+
function getSyncConfig() {
|
|
341
|
+
try {
|
|
342
|
+
const agentConfig = (0, identity_1.loadAgentConfig)();
|
|
343
|
+
return {
|
|
344
|
+
enabled: agentConfig.sync?.enabled ?? false,
|
|
345
|
+
remote: agentConfig.sync?.remote ?? "origin",
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
/* v8 ignore next -- defensive: loadAgentConfig failure in test/bootstrap @preserve */
|
|
350
|
+
return { enabled: false, remote: "origin" };
|
|
351
|
+
}
|
|
352
|
+
}
|
|
280
353
|
function getOpenAIEmbeddingsApiKey() {
|
|
281
354
|
return getIntegrationsConfig().openaiEmbeddingsApiKey;
|
|
282
355
|
}
|
|
283
356
|
function getLogsDir() {
|
|
284
|
-
return path.join(
|
|
357
|
+
return path.join((0, identity_1.getAgentRoot)(), "state", "logs");
|
|
285
358
|
}
|
|
286
359
|
function sanitizeKey(key) {
|
|
287
360
|
return key.replace(/[/:]/g, "_");
|
|
288
361
|
}
|
|
289
|
-
function
|
|
290
|
-
|
|
291
|
-
|
|
362
|
+
function slugify(value) {
|
|
363
|
+
return value
|
|
364
|
+
.trim()
|
|
365
|
+
.toLowerCase()
|
|
366
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
367
|
+
.replace(/^-+/, "")
|
|
368
|
+
.replace(/-+$/, "");
|
|
369
|
+
}
|
|
370
|
+
function resolveSessionPath(friendId, channel, key, options) {
|
|
371
|
+
const dir = path.join((0, identity_1.getAgentRoot)(), "state", "sessions", friendId, channel);
|
|
372
|
+
if (options?.ensureDir) {
|
|
373
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
374
|
+
}
|
|
292
375
|
return path.join(dir, sanitizeKey(key) + ".json");
|
|
293
376
|
}
|
|
377
|
+
function sessionPath(friendId, channel, key) {
|
|
378
|
+
return resolveSessionPath(friendId, channel, key, { ensureDir: true });
|
|
379
|
+
}
|
|
294
380
|
function logPath(channel, key) {
|
|
295
381
|
return path.join(getLogsDir(), channel, sanitizeKey(key) + ".ndjson");
|
|
296
382
|
}
|