@ouro.bot/cli 0.1.0-alpha.13 → 0.1.0-alpha.130
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/psyche/SOUL.md +2 -2
- package/AdoptionSpecialist.ouro/psyche/identities/monty.md +2 -2
- package/README.md +147 -205
- package/changelog.json +808 -0
- package/dist/heart/active-work.js +622 -0
- package/dist/heart/bridges/manager.js +358 -0
- package/dist/heart/bridges/state-machine.js +135 -0
- package/dist/heart/bridges/store.js +123 -0
- package/dist/heart/commitments.js +105 -0
- package/dist/heart/config.js +66 -21
- package/dist/heart/core.js +518 -100
- 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 +432 -0
- package/dist/heart/daemon/daemon-cli.js +1516 -195
- package/dist/heart/daemon/daemon-entry.js +43 -2
- package/dist/heart/daemon/daemon-runtime-sync.js +212 -0
- package/dist/heart/daemon/daemon.js +261 -1
- package/dist/heart/daemon/hatch-animation.js +10 -3
- package/dist/heart/daemon/hatch-flow.js +7 -72
- 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-global-installer.js +128 -0
- package/dist/heart/daemon/ouro-path-installer.js +57 -29
- package/dist/heart/daemon/ouro-version-manager.js +171 -0
- package/dist/heart/daemon/process-manager.js +13 -0
- 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 +50 -2
- 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 +2 -2
- package/dist/heart/daemon/specialist-prompt.js +7 -4
- package/dist/heart/daemon/specialist-tools.js +52 -3
- package/dist/heart/daemon/staged-restart.js +114 -0
- package/dist/heart/daemon/thoughts.js +507 -0
- package/dist/heart/daemon/update-checker.js +111 -0
- package/dist/heart/daemon/update-hooks.js +138 -0
- package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/identity.js +64 -21
- package/dist/heart/kicks.js +1 -19
- package/dist/heart/model-capabilities.js +48 -0
- package/dist/heart/obligations.js +197 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +88 -0
- package/dist/heart/provider-ping.js +159 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +195 -34
- package/dist/heart/providers/azure.js +115 -9
- package/dist/heart/providers/github-copilot.js +157 -0
- package/dist/heart/providers/minimax.js +33 -3
- package/dist/heart/providers/openai-codex.js +49 -14
- package/dist/heart/safe-workspace.js +381 -0
- package/dist/heart/session-activity.js +173 -0
- package/dist/heart/session-recall.js +216 -0
- package/dist/heart/streaming.js +108 -24
- package/dist/heart/target-resolution.js +123 -0
- package/dist/heart/tool-loop.js +194 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/mind/associative-recall.js +14 -2
- package/dist/mind/bundle-manifest.js +12 -0
- package/dist/mind/context.js +60 -14
- package/dist/mind/first-impressions.js +16 -2
- package/dist/mind/friends/channel.js +35 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/store-file.js +19 -0
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +8 -0
- package/dist/mind/memory.js +27 -26
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt.js +456 -77
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +15 -2
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/index.js +12 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/repertoire/ado-client.js +4 -2
- package/dist/repertoire/coding/context-pack.js +254 -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 +39 -9
- package/dist/repertoire/coding/tools.js +171 -4
- package/dist/repertoire/data/ado-endpoints.json +188 -0
- package/dist/repertoire/guardrails.js +290 -0
- package/dist/repertoire/mcp-client.js +254 -0
- package/dist/repertoire/mcp-manager.js +198 -0
- package/dist/repertoire/skills.js +3 -26
- package/dist/repertoire/tasks/board.js +12 -0
- package/dist/repertoire/tasks/index.js +23 -9
- package/dist/repertoire/tasks/transitions.js +1 -2
- package/dist/repertoire/tools-base.js +925 -250
- package/dist/repertoire/tools-bluebubbles.js +93 -0
- package/dist/repertoire/tools-teams.js +58 -25
- package/dist/repertoire/tools.js +106 -53
- package/dist/senses/bluebubbles-client.js +210 -5
- package/dist/senses/bluebubbles-entry.js +2 -0
- package/dist/senses/bluebubbles-inbound-log.js +109 -0
- package/dist/senses/bluebubbles-media.js +339 -0
- package/dist/senses/bluebubbles-model.js +12 -4
- package/dist/senses/bluebubbles-mutation-log.js +45 -5
- package/dist/senses/bluebubbles-runtime-state.js +109 -0
- package/dist/senses/bluebubbles-session-cleanup.js +72 -0
- package/dist/senses/bluebubbles.js +915 -45
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +374 -131
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/debug-activity.js +154 -0
- package/dist/senses/inner-dialog-worker.js +47 -18
- package/dist/senses/inner-dialog.js +388 -83
- package/dist/senses/pipeline.js +444 -0
- package/dist/senses/teams.js +607 -129
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +9 -3
- package/subagents/README.md +4 -70
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/subagents/work-doer.md +0 -233
- package/subagents/work-merger.md +0 -624
- package/subagents/work-planner.md +0 -373
|
@@ -99,10 +99,10 @@ function pickRandomIdentity(identitiesDir, random = Math.random) {
|
|
|
99
99
|
files = fs.readdirSync(identitiesDir).filter((f) => f.endsWith(".md"));
|
|
100
100
|
}
|
|
101
101
|
catch {
|
|
102
|
-
return { fileName: "default", content: "I am
|
|
102
|
+
return { fileName: "default", content: "I am a serpent guide who helps humans hatch their first agent." };
|
|
103
103
|
}
|
|
104
104
|
if (files.length === 0) {
|
|
105
|
-
return { fileName: "default", content: "I am
|
|
105
|
+
return { fileName: "default", content: "I am a serpent guide who helps humans hatch their first agent." };
|
|
106
106
|
}
|
|
107
107
|
const idx = Math.floor(random() * files.length);
|
|
108
108
|
const fileName = files[idx];
|
|
@@ -28,9 +28,10 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
|
|
|
28
28
|
}
|
|
29
29
|
sections.push([
|
|
30
30
|
"## Who I am",
|
|
31
|
-
"I am one of thirteen
|
|
32
|
-
"Most humans only go through
|
|
31
|
+
"I am one of thirteen serpent guides who help humans hatch their first agent. The system randomly selected me for this session.",
|
|
32
|
+
"Most humans only go through this process once, so this is likely the only time they'll meet me.",
|
|
33
33
|
"I make this encounter count — warm, memorable, and uniquely mine.",
|
|
34
|
+
"IMPORTANT: I NEVER refer to myself as an 'adoption specialist' or use the words 'adoption specialist' — those are internal implementation labels, not something the human should ever see. I introduce myself by my own name from my identity.",
|
|
34
35
|
"",
|
|
35
36
|
"## Voice rules",
|
|
36
37
|
"IMPORTANT: I keep every response to 1-3 short sentences. I sound like a friend texting, not a manual.",
|
|
@@ -69,12 +70,13 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
|
|
|
69
70
|
].join("\n"));
|
|
70
71
|
sections.push([
|
|
71
72
|
"## Conversation flow",
|
|
72
|
-
"The human just connected. I speak first — I greet them warmly and introduce myself in my own voice.",
|
|
73
|
-
"I briefly mention that I'm one of several
|
|
73
|
+
"The human just connected. I speak first — I greet them warmly and introduce myself by name in my own voice.",
|
|
74
|
+
"I briefly mention that I'm one of several serpent guides and they got me today.",
|
|
74
75
|
"I ask their name.",
|
|
75
76
|
"Then I ask what they'd like their agent to help with — one question at a time.",
|
|
76
77
|
"I'm proactive: I suggest ideas and guide them. If they seem unsure, I offer a concrete suggestion.",
|
|
77
78
|
"I don't wait for the human to figure things out — I explain simply what an agent is if needed.",
|
|
79
|
+
"Before finalizing, I offer to collect their phone number and/or Teams email so the new agent can recognize them across channels.",
|
|
78
80
|
"When I have enough context about the agent's personality and purpose:",
|
|
79
81
|
"1. I write all 5 psyche files to the temp directory using write_file",
|
|
80
82
|
"2. I write agent.json to the temp directory using write_file",
|
|
@@ -87,6 +89,7 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
|
|
|
87
89
|
"- `write_file`: Write a file to disk. Use this to write psyche files and agent.json to the temp directory.",
|
|
88
90
|
"- `read_file`: Read a file from disk. Useful for reviewing existing agent bundles or migration sources.",
|
|
89
91
|
"- `list_directory`: List directory contents. Useful for exploring existing agent bundles.",
|
|
92
|
+
"- I also have the normal local harness tools when useful here, including `shell`, `ouro task create`, `ouro reminder create`, memory tools, coding tools, and repo helpers.",
|
|
90
93
|
"- `complete_adoption`: Finalize the bundle. Validates, scaffolds structural dirs, moves to ~/AgentBundles/, writes secrets, plays hatch animation. I call this with `name` (PascalCase) and `handoff_message` (warm message for the human).",
|
|
91
94
|
"- `final_answer`: End the conversation with a final message. I call this after complete_adoption succeeds.",
|
|
92
95
|
"",
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.getSpecialistTools = getSpecialistTools;
|
|
37
37
|
exports.createSpecialistExecTool = createSpecialistExecTool;
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const path = __importStar(require("path"));
|
|
40
41
|
const tools_base_1 = require("../../repertoire/tools-base");
|
|
@@ -58,6 +59,14 @@ const completeAdoptionTool = {
|
|
|
58
59
|
type: "string",
|
|
59
60
|
description: "a warm handoff message to display to the human after the agent is hatched",
|
|
60
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
|
+
},
|
|
61
70
|
},
|
|
62
71
|
required: ["name", "handoff_message"],
|
|
63
72
|
},
|
|
@@ -65,12 +74,23 @@ const completeAdoptionTool = {
|
|
|
65
74
|
};
|
|
66
75
|
const readFileTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "read_file");
|
|
67
76
|
const writeFileTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "write_file");
|
|
68
|
-
const
|
|
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
|
+
};
|
|
69
89
|
/**
|
|
70
90
|
* Returns the specialist's tool schema array.
|
|
71
91
|
*/
|
|
72
92
|
function getSpecialistTools() {
|
|
73
|
-
return [completeAdoptionTool, tools_base_1.finalAnswerTool, readFileTool.tool, writeFileTool.tool,
|
|
93
|
+
return [completeAdoptionTool, tools_base_1.finalAnswerTool, readFileTool.tool, writeFileTool.tool, listDirToolSchema];
|
|
74
94
|
}
|
|
75
95
|
const PSYCHE_FILES = ["SOUL.md", "IDENTITY.md", "LORE.md", "TACIT.md", "ASPIRATIONS.md"];
|
|
76
96
|
function isPascalCase(name) {
|
|
@@ -164,6 +184,32 @@ async function execCompleteAdoption(args, deps) {
|
|
|
164
184
|
}
|
|
165
185
|
return `error: failed to write secrets: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
|
|
166
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
|
+
}
|
|
167
213
|
// Play hatch animation
|
|
168
214
|
await (0, hatch_animation_1.playHatchAnimation)(name, deps.animationWriter);
|
|
169
215
|
// Display handoff message
|
|
@@ -211,7 +257,10 @@ function createSpecialistExecTool(deps) {
|
|
|
211
257
|
try {
|
|
212
258
|
const dir = path.dirname(args.path);
|
|
213
259
|
fs.mkdirSync(dir, { recursive: true });
|
|
214
|
-
|
|
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");
|
|
215
264
|
return `wrote ${args.path}`;
|
|
216
265
|
}
|
|
217
266
|
catch (e) {
|
|
@@ -0,0 +1,114 @@
|
|
|
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.performStagedRestart = performStagedRestart;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
39
|
+
async function performStagedRestart(version, deps) {
|
|
40
|
+
(0, runtime_1.emitNervesEvent)({
|
|
41
|
+
component: "daemon",
|
|
42
|
+
event: "daemon.staged_restart_start",
|
|
43
|
+
message: "starting staged restart",
|
|
44
|
+
meta: { version },
|
|
45
|
+
});
|
|
46
|
+
// Step 1: Install new version
|
|
47
|
+
try {
|
|
48
|
+
deps.execSync(`npm install -g @ouro.bot/cli@${version}`);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
const errorMessage = err instanceof Error ? err.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(err);
|
|
52
|
+
(0, runtime_1.emitNervesEvent)({
|
|
53
|
+
component: "daemon",
|
|
54
|
+
event: "daemon.staged_restart_install_failed",
|
|
55
|
+
message: "npm install failed",
|
|
56
|
+
meta: { version, error: errorMessage },
|
|
57
|
+
});
|
|
58
|
+
return { ok: false, error: errorMessage };
|
|
59
|
+
}
|
|
60
|
+
// Step 2: Resolve new code path
|
|
61
|
+
const newCodePath = deps.resolveNewCodePath(version);
|
|
62
|
+
if (!newCodePath) {
|
|
63
|
+
(0, runtime_1.emitNervesEvent)({
|
|
64
|
+
component: "daemon",
|
|
65
|
+
event: "daemon.staged_restart_path_failed",
|
|
66
|
+
message: "could not resolve new code path",
|
|
67
|
+
meta: { version },
|
|
68
|
+
});
|
|
69
|
+
return { ok: false, error: "could not resolve new code path after install" };
|
|
70
|
+
}
|
|
71
|
+
// Step 3: Spawn hook runner on NEW code
|
|
72
|
+
const hookRunnerPath = path.join(newCodePath, "dist", "heart", "daemon", "run-hooks.js");
|
|
73
|
+
const spawnResult = deps.spawnSync(deps.nodePath, [hookRunnerPath, "--bundles-root", deps.bundlesRoot], { stdio: "inherit" });
|
|
74
|
+
if (spawnResult.error) {
|
|
75
|
+
const errorMessage = spawnResult.error.message;
|
|
76
|
+
(0, runtime_1.emitNervesEvent)({
|
|
77
|
+
component: "daemon",
|
|
78
|
+
event: "daemon.staged_restart_spawn_failed",
|
|
79
|
+
message: "hook runner spawn failed",
|
|
80
|
+
meta: { version, error: errorMessage },
|
|
81
|
+
});
|
|
82
|
+
return { ok: false, error: errorMessage };
|
|
83
|
+
}
|
|
84
|
+
if (spawnResult.status !== 0) {
|
|
85
|
+
(0, runtime_1.emitNervesEvent)({
|
|
86
|
+
component: "daemon",
|
|
87
|
+
event: "daemon.staged_restart_hooks_failed",
|
|
88
|
+
message: "hook runner exited with non-zero status",
|
|
89
|
+
meta: { version, exitCode: spawnResult.status },
|
|
90
|
+
});
|
|
91
|
+
return { ok: false, error: `hook runner exited with code ${spawnResult.status}` };
|
|
92
|
+
}
|
|
93
|
+
// Step 4: Graceful shutdown (launchd will restart with new code)
|
|
94
|
+
(0, runtime_1.emitNervesEvent)({
|
|
95
|
+
component: "daemon",
|
|
96
|
+
event: "daemon.staged_restart_hooks_passed",
|
|
97
|
+
message: "hooks passed, shutting down for restart",
|
|
98
|
+
meta: { version },
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
await deps.gracefulShutdown();
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const shutdownError = err instanceof Error ? err.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(err);
|
|
105
|
+
(0, runtime_1.emitNervesEvent)({
|
|
106
|
+
component: "daemon",
|
|
107
|
+
event: "daemon.staged_restart_shutdown_error",
|
|
108
|
+
message: "graceful shutdown encountered error",
|
|
109
|
+
meta: { version, error: shutdownError },
|
|
110
|
+
});
|
|
111
|
+
return { ok: true, shutdownError };
|
|
112
|
+
}
|
|
113
|
+
return { ok: true };
|
|
114
|
+
}
|