@ouro.bot/cli 0.1.0-alpha.26 → 0.1.0-alpha.261
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/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
- package/changelog.json +1582 -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/presence.js +185 -0
- package/dist/heart/active-work.js +832 -0
- package/dist/heart/agent-entry.js +37 -2
- package/dist/heart/auth/auth-flow.js +447 -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 +111 -0
- package/dist/heart/config-registry.js +304 -0
- package/dist/heart/config.js +63 -30
- package/dist/heart/core.js +644 -196
- 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 +145 -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 +557 -0
- package/dist/heart/daemon/cli-exec.js +1877 -0
- package/dist/heart/daemon/cli-parse.js +759 -0
- package/dist/heart/daemon/cli-render.js +464 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/daemon-cli.js +29 -1179
- package/dist/heart/daemon/daemon-entry.js +216 -4
- package/dist/heart/daemon/daemon-health.js +136 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +153 -12
- package/dist/heart/daemon/daemon-tombstone.js +123 -0
- package/dist/heart/daemon/daemon.js +590 -54
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/launchd.js +39 -8
- package/dist/heart/daemon/log-tailer.js +4 -3
- 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 +123 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +58 -15
- package/dist/heart/daemon/runtime-metadata.js +101 -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 +72 -3
- 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 +276 -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 +119 -0
- package/dist/heart/habits/habit-scheduler.js +371 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +30 -120
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
- package/dist/heart/{daemon → hatch}/specialist-tools.js +49 -3
- package/dist/heart/identity.js +157 -55
- 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 +169 -46
- 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/session-activity.js +172 -0
- package/dist/heart/session-recall.js +216 -0
- package/dist/heart/start-of-turn-packet.js +330 -0
- package/dist/heart/streaming.js +36 -27
- package/dist/heart/sync.js +277 -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-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 +1 -1
- package/dist/heart/{daemon → versioning}/ouro-path-installer.js +78 -35
- package/dist/heart/versioning/ouro-version-manager.js +171 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +30 -6
- package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
- package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +41 -3
- package/dist/mind/associative-recall.js +126 -66
- package/dist/mind/bundle-manifest.js +8 -1
- package/dist/mind/context.js +125 -14
- package/dist/mind/{memory.js → diary.js} +68 -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 +56 -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 +8 -0
- 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 +765 -109
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/coverage/audit.js +1 -1
- package/dist/nerves/coverage/file-completeness.js +50 -5
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +64 -4
- 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 +15 -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/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 +197 -30
- package/dist/repertoire/coding/manager.js +149 -2
- package/dist/repertoire/coding/spawner.js +55 -9
- package/dist/repertoire/coding/tools.js +170 -7
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +515 -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 +369 -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/tools-base.js +43 -771
- package/dist/repertoire/tools-bluebubbles.js +201 -0
- package/dist/repertoire/tools-bridge.js +141 -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 +62 -0
- package/dist/repertoire/tools-github.js +1 -7
- package/dist/repertoire/tools-memory.js +347 -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 +12 -62
- 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 +155 -130
- 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 +97 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +145 -10
- package/dist/senses/bluebubbles/entry.js +13 -0
- package/dist/senses/bluebubbles/inbound-log.js +110 -0
- package/dist/senses/bluebubbles/index.js +1374 -0
- package/dist/senses/bluebubbles/media.js +455 -0
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +20 -5
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
- 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 +211 -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 +168 -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 +581 -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 +569 -246
- 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 +593 -85
- package/dist/senses/pipeline.js +552 -0
- package/dist/senses/shared-turn.js +199 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams.js +664 -165
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +14 -7
- 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/dist/heart/daemon/subagent-installer.js +0 -134
- package/dist/senses/bluebubbles-entry.js +0 -11
- package/dist/senses/bluebubbles-media.js +0 -244
- package/dist/senses/bluebubbles.js +0 -421
- package/dist/senses/debug-activity.js +0 -107
- package/subagents/README.md +0 -73
- package/subagents/work-doer.md +0 -235
- package/subagents/work-merger.md +0 -618
- package/subagents/work-planner.md +0 -382
- /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/monty.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
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/update-hooks.js +0 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bluebubblesToolDefinitions = void 0;
|
|
4
|
+
const runtime_1 = require("../nerves/runtime");
|
|
5
|
+
const config_1 = require("../heart/config");
|
|
6
|
+
const minimax_1 = require("../heart/providers/minimax");
|
|
7
|
+
const minimax_vlm_1 = require("../heart/providers/minimax-vlm");
|
|
8
|
+
const attachment_cache_1 = require("../senses/bluebubbles/attachment-cache");
|
|
9
|
+
const media_1 = require("../senses/bluebubbles/media");
|
|
10
|
+
// AX-1: the tool description is the only instruction manual a future agent
|
|
11
|
+
// gets. It must teach WHEN to reach for the tool and HOW to write a good
|
|
12
|
+
// prompt. A type-signature-style "Describes an image." is a violation.
|
|
13
|
+
const DESCRIBE_IMAGE_DESCRIPTION = "Use this tool to look at an attachment the user sent, or to re-interrogate an image with a targeted question. " +
|
|
14
|
+
"The current chat model can't see images natively; this tool runs the image through a vision-language model (VLM) " +
|
|
15
|
+
"and returns a text description. " +
|
|
16
|
+
"Prefer targeted prompts (\"what's the flight number in the bottom-right?\") over generic ones (\"describe this image\") — " +
|
|
17
|
+
"you'll get better answers. " +
|
|
18
|
+
"Call this when the user sent a screenshot and you need to read text from it, verify a detail, or double-check something " +
|
|
19
|
+
"the ingestion-time auto-describe summary might have missed. " +
|
|
20
|
+
"The attachment_guid comes from the attachment marker in the user's most recent message.";
|
|
21
|
+
exports.bluebubblesToolDefinitions = [
|
|
22
|
+
{
|
|
23
|
+
tool: {
|
|
24
|
+
type: "function",
|
|
25
|
+
function: {
|
|
26
|
+
name: "bluebubbles_set_reply_target",
|
|
27
|
+
description: "choose where the current iMessage turn should land. use this when you want to widen back to top-level or route your update into a specific active thread in the same chat.",
|
|
28
|
+
parameters: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
target: {
|
|
32
|
+
type: "string",
|
|
33
|
+
enum: ["current_lane", "top_level", "thread"],
|
|
34
|
+
description: "current_lane mirrors the current inbound lane, top_level answers in the main chat, and thread targets a specific active thread.",
|
|
35
|
+
},
|
|
36
|
+
threadOriginatorGuid: {
|
|
37
|
+
type: "string",
|
|
38
|
+
description: "required when target=thread; use one of the thread ids surfaced in the inbound iMessage context.",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
required: ["target"],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
handler: (args, ctx) => {
|
|
46
|
+
const target = typeof args.target === "string" ? args.target.trim() : "";
|
|
47
|
+
const controller = ctx?.bluebubblesReplyTarget;
|
|
48
|
+
if (!controller) {
|
|
49
|
+
(0, runtime_1.emitNervesEvent)({
|
|
50
|
+
level: "warn",
|
|
51
|
+
component: "tools",
|
|
52
|
+
event: "tool.error",
|
|
53
|
+
message: "bluebubbles reply target missing controller",
|
|
54
|
+
meta: { target },
|
|
55
|
+
});
|
|
56
|
+
return "bluebubbles reply targeting is not available in this context.";
|
|
57
|
+
}
|
|
58
|
+
if (target === "current_lane") {
|
|
59
|
+
const result = controller.setSelection({ target: "current_lane" });
|
|
60
|
+
(0, runtime_1.emitNervesEvent)({
|
|
61
|
+
component: "tools",
|
|
62
|
+
event: "tool.end",
|
|
63
|
+
message: "bluebubbles reply target updated",
|
|
64
|
+
meta: { target: "current_lane", success: true },
|
|
65
|
+
});
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
if (target === "top_level") {
|
|
69
|
+
const result = controller.setSelection({ target: "top_level" });
|
|
70
|
+
(0, runtime_1.emitNervesEvent)({
|
|
71
|
+
component: "tools",
|
|
72
|
+
event: "tool.end",
|
|
73
|
+
message: "bluebubbles reply target updated",
|
|
74
|
+
meta: { target: "top_level", success: true },
|
|
75
|
+
});
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
if (target === "thread") {
|
|
79
|
+
const threadOriginatorGuid = typeof args.threadOriginatorGuid === "string" ? args.threadOriginatorGuid.trim() : "";
|
|
80
|
+
if (!threadOriginatorGuid) {
|
|
81
|
+
(0, runtime_1.emitNervesEvent)({
|
|
82
|
+
level: "warn",
|
|
83
|
+
component: "tools",
|
|
84
|
+
event: "tool.error",
|
|
85
|
+
message: "bluebubbles reply target missing thread id",
|
|
86
|
+
meta: { target: "thread" },
|
|
87
|
+
});
|
|
88
|
+
return "threadOriginatorGuid is required when target=thread.";
|
|
89
|
+
}
|
|
90
|
+
const result = controller.setSelection({ target: "thread", threadOriginatorGuid });
|
|
91
|
+
(0, runtime_1.emitNervesEvent)({
|
|
92
|
+
component: "tools",
|
|
93
|
+
event: "tool.end",
|
|
94
|
+
message: "bluebubbles reply target updated",
|
|
95
|
+
meta: { target: "thread", success: true },
|
|
96
|
+
});
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
(0, runtime_1.emitNervesEvent)({
|
|
100
|
+
level: "warn",
|
|
101
|
+
component: "tools",
|
|
102
|
+
event: "tool.error",
|
|
103
|
+
message: "bluebubbles reply target invalid target",
|
|
104
|
+
meta: { target },
|
|
105
|
+
});
|
|
106
|
+
return "target must be one of: current_lane, top_level, thread.";
|
|
107
|
+
},
|
|
108
|
+
summaryKeys: ["target", "threadOriginatorGuid"],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
tool: {
|
|
112
|
+
type: "function",
|
|
113
|
+
function: {
|
|
114
|
+
name: "describe_image",
|
|
115
|
+
description: DESCRIBE_IMAGE_DESCRIPTION,
|
|
116
|
+
parameters: {
|
|
117
|
+
type: "object",
|
|
118
|
+
properties: {
|
|
119
|
+
attachment_guid: {
|
|
120
|
+
type: "string",
|
|
121
|
+
description: "The guid of the attachment to describe. Usually pulled from the attachment marker in the user's most recent message.",
|
|
122
|
+
},
|
|
123
|
+
prompt: {
|
|
124
|
+
type: "string",
|
|
125
|
+
description: "A targeted question about the image. Prefer specific prompts over generic ones — e.g. 'what's the flight number in the bottom-right?' gives better answers than 'describe this image'.",
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
required: ["attachment_guid", "prompt"],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
handler: async (args) => {
|
|
133
|
+
const attachmentGuid = typeof args.attachment_guid === "string" ? args.attachment_guid.trim() : "";
|
|
134
|
+
const prompt = typeof args.prompt === "string" ? args.prompt.trim() : "";
|
|
135
|
+
if (!attachmentGuid) {
|
|
136
|
+
(0, runtime_1.emitNervesEvent)({
|
|
137
|
+
level: "warn",
|
|
138
|
+
component: "tools",
|
|
139
|
+
event: "tool.error",
|
|
140
|
+
message: "describe_image missing attachment_guid",
|
|
141
|
+
meta: {},
|
|
142
|
+
});
|
|
143
|
+
return "describe_image: attachment_guid is required — pass the guid from the inbound attachment marker and retry";
|
|
144
|
+
}
|
|
145
|
+
if (!prompt) {
|
|
146
|
+
(0, runtime_1.emitNervesEvent)({
|
|
147
|
+
level: "warn",
|
|
148
|
+
component: "tools",
|
|
149
|
+
event: "tool.error",
|
|
150
|
+
message: "describe_image missing prompt",
|
|
151
|
+
meta: {},
|
|
152
|
+
});
|
|
153
|
+
return "describe_image: prompt is required — supply a targeted question (e.g. 'what's the flight number in the bottom-right?') and retry";
|
|
154
|
+
}
|
|
155
|
+
const summary = (0, attachment_cache_1.lookupBlueBubblesAttachment)(attachmentGuid);
|
|
156
|
+
if (!summary) {
|
|
157
|
+
(0, runtime_1.emitNervesEvent)({
|
|
158
|
+
level: "warn",
|
|
159
|
+
component: "tools",
|
|
160
|
+
event: "tool.error",
|
|
161
|
+
message: "describe_image attachment not found in cache",
|
|
162
|
+
meta: { attachmentGuid },
|
|
163
|
+
});
|
|
164
|
+
return `describe_image: no attachment with guid ${attachmentGuid} found in recent messages — ask the user to resend the image or verify the guid`;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const config = (0, config_1.getBlueBubblesConfig)();
|
|
168
|
+
const channelConfig = (0, config_1.getBlueBubblesChannelConfig)();
|
|
169
|
+
const downloaded = await (0, media_1.downloadBlueBubblesAttachment)(summary, config, channelConfig);
|
|
170
|
+
const mimeType = downloaded.contentType ?? summary.mimeType ?? "image/png";
|
|
171
|
+
const base64 = downloaded.buffer.toString("base64");
|
|
172
|
+
const dataUrl = `data:${mimeType};base64,${base64}`;
|
|
173
|
+
const { apiKey } = (0, config_1.getMinimaxConfig)();
|
|
174
|
+
if (!apiKey) {
|
|
175
|
+
throw new Error("minimax API key not found in secrets.json — re-run credential setup or add a minimax key");
|
|
176
|
+
}
|
|
177
|
+
const description = await (0, minimax_vlm_1.minimaxVlmDescribe)({
|
|
178
|
+
apiKey,
|
|
179
|
+
prompt,
|
|
180
|
+
imageDataUrl: dataUrl,
|
|
181
|
+
baseURL: minimax_1.MINIMAX_PROVIDER_BASE_URL,
|
|
182
|
+
attachmentGuid,
|
|
183
|
+
mimeType,
|
|
184
|
+
});
|
|
185
|
+
return description;
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
189
|
+
(0, runtime_1.emitNervesEvent)({
|
|
190
|
+
level: "warn",
|
|
191
|
+
component: "tools",
|
|
192
|
+
event: "tool.error",
|
|
193
|
+
message: "describe_image failed",
|
|
194
|
+
meta: { attachmentGuid, reason },
|
|
195
|
+
});
|
|
196
|
+
return `describe_image failed: ${reason}`;
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
summaryKeys: ["attachment_guid", "prompt"],
|
|
200
|
+
},
|
|
201
|
+
];
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bridgeToolDefinitions = void 0;
|
|
4
|
+
const config_1 = require("../heart/config");
|
|
5
|
+
const manager_1 = require("../heart/bridges/manager");
|
|
6
|
+
const runtime_1 = require("../nerves/runtime");
|
|
7
|
+
const session_recall_1 = require("../heart/session-recall");
|
|
8
|
+
const NO_SESSION_FOUND_MESSAGE = "no session found for that friend/channel/key combination.";
|
|
9
|
+
const EMPTY_SESSION_MESSAGE = "session exists but has no non-system messages.";
|
|
10
|
+
async function recallSessionSafely(options) {
|
|
11
|
+
try {
|
|
12
|
+
return await (0, session_recall_1.recallSession)(options);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (options.summarize) {
|
|
16
|
+
(0, runtime_1.emitNervesEvent)({
|
|
17
|
+
component: "daemon",
|
|
18
|
+
event: "daemon.session_recall_summary_fallback",
|
|
19
|
+
message: "session recall summarization failed; using raw transcript",
|
|
20
|
+
meta: {
|
|
21
|
+
friendId: options.friendId,
|
|
22
|
+
channel: options.channel,
|
|
23
|
+
key: options.key,
|
|
24
|
+
/* v8 ignore next -- branch: String(error) fallback only for non-Error throws @preserve */
|
|
25
|
+
error: error instanceof Error ? error.message : String(error),
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
try {
|
|
29
|
+
return await (0, session_recall_1.recallSession)({
|
|
30
|
+
...options,
|
|
31
|
+
summarize: undefined,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return { kind: "missing" };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { kind: "missing" };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.bridgeToolDefinitions = [
|
|
42
|
+
// -- cross-session awareness --
|
|
43
|
+
{
|
|
44
|
+
tool: {
|
|
45
|
+
type: "function",
|
|
46
|
+
function: {
|
|
47
|
+
name: "bridge_manage",
|
|
48
|
+
description: "create and manage shared live-work bridges across already-active sessions.",
|
|
49
|
+
parameters: {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: {
|
|
52
|
+
action: {
|
|
53
|
+
type: "string",
|
|
54
|
+
enum: ["begin", "attach", "status", "promote_task", "complete", "cancel"],
|
|
55
|
+
},
|
|
56
|
+
bridgeId: { type: "string", description: "bridge id for all actions except begin" },
|
|
57
|
+
objective: { type: "string", description: "objective for begin" },
|
|
58
|
+
summary: { type: "string", description: "optional concise shared-work summary" },
|
|
59
|
+
friendId: { type: "string", description: "target friend id for attach" },
|
|
60
|
+
channel: { type: "string", description: "target channel for attach" },
|
|
61
|
+
key: { type: "string", description: "target session key for attach (defaults to 'session')" },
|
|
62
|
+
title: { type: "string", description: "task title override for promote_task" },
|
|
63
|
+
category: { type: "string", description: "task category override for promote_task" },
|
|
64
|
+
body: { type: "string", description: "task body override for promote_task" },
|
|
65
|
+
},
|
|
66
|
+
required: ["action"],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
handler: async (args, ctx) => {
|
|
71
|
+
const manager = (0, manager_1.createBridgeManager)();
|
|
72
|
+
const action = (args.action || "").trim();
|
|
73
|
+
if (action === "begin") {
|
|
74
|
+
if (!ctx?.currentSession) {
|
|
75
|
+
return "bridge_manage begin requires an active session context.";
|
|
76
|
+
}
|
|
77
|
+
const objective = (args.objective || "").trim();
|
|
78
|
+
if (!objective)
|
|
79
|
+
return "objective is required for bridge begin.";
|
|
80
|
+
return (0, manager_1.formatBridgeStatus)(manager.beginBridge({
|
|
81
|
+
objective,
|
|
82
|
+
summary: (args.summary || objective).trim(),
|
|
83
|
+
session: ctx.currentSession,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
const bridgeId = (args.bridgeId || "").trim();
|
|
87
|
+
if (!bridgeId) {
|
|
88
|
+
return "bridgeId is required for this bridge action.";
|
|
89
|
+
}
|
|
90
|
+
if (action === "attach") {
|
|
91
|
+
const friendId = (args.friendId || "").trim();
|
|
92
|
+
const channel = (args.channel || "").trim();
|
|
93
|
+
const key = (args.key || "session").trim();
|
|
94
|
+
if (!friendId || !channel) {
|
|
95
|
+
return "friendId and channel are required for bridge attach.";
|
|
96
|
+
}
|
|
97
|
+
const sessionPath = (0, config_1.resolveSessionPath)(friendId, channel, key);
|
|
98
|
+
const recall = await recallSessionSafely({
|
|
99
|
+
sessionPath,
|
|
100
|
+
friendId,
|
|
101
|
+
channel,
|
|
102
|
+
key,
|
|
103
|
+
messageCount: 20,
|
|
104
|
+
trustLevel: ctx?.context?.friend?.trustLevel,
|
|
105
|
+
summarize: ctx?.summarize,
|
|
106
|
+
});
|
|
107
|
+
if (recall.kind === "missing") {
|
|
108
|
+
return NO_SESSION_FOUND_MESSAGE;
|
|
109
|
+
}
|
|
110
|
+
return (0, manager_1.formatBridgeStatus)(manager.attachSession(bridgeId, {
|
|
111
|
+
friendId,
|
|
112
|
+
channel,
|
|
113
|
+
key,
|
|
114
|
+
sessionPath,
|
|
115
|
+
snapshot: recall.kind === "ok" ? recall.snapshot : EMPTY_SESSION_MESSAGE,
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
if (action === "status") {
|
|
119
|
+
const bridge = manager.getBridge(bridgeId);
|
|
120
|
+
if (!bridge)
|
|
121
|
+
return `bridge not found: ${bridgeId}`;
|
|
122
|
+
return (0, manager_1.formatBridgeStatus)(bridge);
|
|
123
|
+
}
|
|
124
|
+
if (action === "promote_task") {
|
|
125
|
+
return (0, manager_1.formatBridgeStatus)(manager.promoteBridgeToTask(bridgeId, {
|
|
126
|
+
title: args.title,
|
|
127
|
+
category: args.category,
|
|
128
|
+
body: args.body,
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
if (action === "complete") {
|
|
132
|
+
return (0, manager_1.formatBridgeStatus)(manager.completeBridge(bridgeId));
|
|
133
|
+
}
|
|
134
|
+
if (action === "cancel") {
|
|
135
|
+
return (0, manager_1.formatBridgeStatus)(manager.cancelBridge(bridgeId));
|
|
136
|
+
}
|
|
137
|
+
return `unknown bridge action: ${action}`;
|
|
138
|
+
},
|
|
139
|
+
summaryKeys: ["action", "bridgeId", "objective", "friendId", "channel", "key"],
|
|
140
|
+
},
|
|
141
|
+
];
|
|
@@ -0,0 +1,185 @@
|
|
|
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.configToolDefinitions = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const runtime_1 = require("../nerves/runtime");
|
|
40
|
+
const identity_1 = require("../heart/identity");
|
|
41
|
+
const config_registry_1 = require("../heart/config-registry");
|
|
42
|
+
exports.configToolDefinitions = [
|
|
43
|
+
{
|
|
44
|
+
tool: {
|
|
45
|
+
type: "function",
|
|
46
|
+
function: {
|
|
47
|
+
name: "read_config",
|
|
48
|
+
description: "Read current agent configuration with tier annotations, descriptions, defaults, and effects. Optionally filter by topic to see only related settings.",
|
|
49
|
+
parameters: {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: {
|
|
52
|
+
related_to: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Optional topic to filter results (e.g., 'model', 'logging', 'senses'). Case-insensitive partial match.",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
handler: (a) => {
|
|
61
|
+
const entries = a.related_to
|
|
62
|
+
? (0, config_registry_1.getRegistryEntriesByTopic)(a.related_to)
|
|
63
|
+
: (0, config_registry_1.getRegistryEntries)();
|
|
64
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
65
|
+
const configPath = path.join(agentRoot, "agent.json");
|
|
66
|
+
let rawConfig = {};
|
|
67
|
+
try {
|
|
68
|
+
rawConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
/* v8 ignore next -- defensive: agent.json read failure in read_config @preserve */
|
|
72
|
+
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.read_config_error", message: "failed to read agent.json", meta: { path: configPath } });
|
|
73
|
+
}
|
|
74
|
+
const result = entries.map((entry) => {
|
|
75
|
+
const parts = entry.path.split(".");
|
|
76
|
+
let current = rawConfig;
|
|
77
|
+
for (const part of parts) {
|
|
78
|
+
if (current && typeof current === "object" && !Array.isArray(current)) {
|
|
79
|
+
current = current[part];
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
current = undefined;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const isExplicit = current !== undefined;
|
|
87
|
+
let source;
|
|
88
|
+
let currentValue;
|
|
89
|
+
if (isExplicit) {
|
|
90
|
+
source = "explicit";
|
|
91
|
+
currentValue = current;
|
|
92
|
+
}
|
|
93
|
+
else if (entry.default !== undefined) {
|
|
94
|
+
source = "default";
|
|
95
|
+
currentValue = entry.default;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
source = "unset";
|
|
99
|
+
currentValue = null;
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
path: entry.path,
|
|
103
|
+
currentValue,
|
|
104
|
+
source,
|
|
105
|
+
tier: entry.tier,
|
|
106
|
+
description: entry.description,
|
|
107
|
+
default: entry.default !== undefined ? entry.default : null,
|
|
108
|
+
effects: entry.effects,
|
|
109
|
+
topics: entry.topics,
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.read_config", message: `read_config returned ${result.length} entries`, meta: { count: result.length, topic: a.related_to ?? null } });
|
|
113
|
+
return JSON.stringify({ entries: result }, null, 2);
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
tool: {
|
|
118
|
+
type: "function",
|
|
119
|
+
function: {
|
|
120
|
+
name: "update_config",
|
|
121
|
+
description: "Update an agent configuration value. Managed keys (version, enabled) cannot be modified.",
|
|
122
|
+
parameters: {
|
|
123
|
+
type: "object",
|
|
124
|
+
properties: {
|
|
125
|
+
path: { type: "string", description: "Config key in dot-notation (e.g., 'context.contextMargin', 'logging.level')" },
|
|
126
|
+
value: { type: "string", description: "New value as JSON (e.g., '25', '\"debug\"', '[\"terminal\", \"ndjson\"]')" },
|
|
127
|
+
},
|
|
128
|
+
required: ["path", "value"],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
handler: (a) => {
|
|
133
|
+
const entry = (0, config_registry_1.getRegistryEntry)(a.path);
|
|
134
|
+
if (!entry) {
|
|
135
|
+
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.update_config_error", message: `unknown config path: ${a.path}`, meta: { path: a.path } });
|
|
136
|
+
return `Error: unknown config path "${a.path}". Use read_config to see available paths.`;
|
|
137
|
+
}
|
|
138
|
+
let parsedValue;
|
|
139
|
+
try {
|
|
140
|
+
parsedValue = JSON.parse(a.value);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.update_config_error", message: `invalid JSON value for ${a.path}`, meta: { path: a.path, value: a.value } });
|
|
144
|
+
return `Error: invalid JSON value. Provide value as valid JSON (e.g., 25, "debug", ["terminal"]).`;
|
|
145
|
+
}
|
|
146
|
+
// Validate value against registry entry's validator
|
|
147
|
+
/* v8 ignore next -- all current entries have validators; guard kept for future entries without one @preserve */
|
|
148
|
+
if (entry.validate) {
|
|
149
|
+
const validationError = entry.validate(parsedValue);
|
|
150
|
+
if (validationError) {
|
|
151
|
+
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.update_config_error", message: `validation failed for ${a.path}: ${validationError}`, meta: { path: a.path, value: a.value, validationError } });
|
|
152
|
+
return `Error: validation failed for "${a.path}": ${validationError}`;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Managed: refuse
|
|
156
|
+
if (entry.tier === "managed") {
|
|
157
|
+
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.update_config_refused", message: `refused managed change to ${a.path}`, meta: { path: a.path, tier: "managed" } });
|
|
158
|
+
return `This key is managed by the harness and cannot be modified directly.`;
|
|
159
|
+
}
|
|
160
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
161
|
+
const configPath = path.join(agentRoot, "agent.json");
|
|
162
|
+
let rawConfig;
|
|
163
|
+
try {
|
|
164
|
+
rawConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
/* v8 ignore next -- defensive: agent.json read failure in update_config @preserve */
|
|
168
|
+
return `Error: failed to read agent.json at ${configPath}`;
|
|
169
|
+
}
|
|
170
|
+
// Apply change immediately
|
|
171
|
+
const parts = entry.path.split(".");
|
|
172
|
+
let target = rawConfig;
|
|
173
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
174
|
+
if (!(parts[i] in target) || typeof target[parts[i]] !== "object" || target[parts[i]] === null) {
|
|
175
|
+
target[parts[i]] = {};
|
|
176
|
+
}
|
|
177
|
+
target = target[parts[i]];
|
|
178
|
+
}
|
|
179
|
+
target[parts[parts.length - 1]] = parsedValue;
|
|
180
|
+
fs.writeFileSync(configPath, JSON.stringify(rawConfig, null, 2) + "\n", "utf-8");
|
|
181
|
+
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.update_config_applied", message: `applied config change to ${a.path}`, meta: { path: a.path, tier: entry.tier, value: parsedValue } });
|
|
182
|
+
return `Success: "${a.path}" updated to ${JSON.stringify(parsedValue)}. Change applied immediately.`;
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
];
|