@ouro.bot/cli 0.1.0-alpha.22 → 0.1.0-alpha.220
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 +1354 -2
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +140 -0
- package/dist/arc/episodes.js +119 -0
- package/dist/arc/intentions.js +133 -0
- package/dist/arc/json-store.js +120 -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 +444 -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 +305 -0
- package/dist/heart/config.js +59 -30
- package/dist/heart/core.js +601 -145
- 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 +81 -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 +1847 -0
- package/dist/heart/daemon/cli-parse.js +759 -0
- package/dist/heart/daemon/cli-render.js +316 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/daemon-cli.js +29 -1163
- package/dist/heart/daemon/daemon-entry.js +202 -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 +487 -20
- 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 +202 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/thoughts.js +507 -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 +369 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +29 -119
- 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 +144 -55
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/mcp/mcp-server.js +608 -0
- package/dist/heart/migrate-config.js +127 -0
- package/dist/heart/model-capabilities.js +48 -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 +187 -41
- 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/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 +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-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 +9 -1
- package/dist/heart/{daemon → versioning}/update-hooks.js +20 -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} +73 -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/store-file.js +36 -0
- 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 +779 -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 +47 -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 -5
- package/dist/repertoire/api-client.js +100 -0
- package/dist/repertoire/bitwarden-client.js +290 -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/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +342 -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 +35 -771
- package/dist/repertoire/tools-bluebubbles.js +94 -0
- package/dist/repertoire/tools-bridge.js +141 -0
- package/dist/repertoire/tools-config.js +266 -0
- package/dist/repertoire/tools-continuity.js +248 -0
- package/dist/repertoire/tools-files.js +342 -0
- package/dist/repertoire/tools-flow.js +62 -0
- package/dist/repertoire/tools-github.js +1 -6
- package/dist/repertoire/tools-memory.js +347 -0
- package/dist/repertoire/tools-session.js +721 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-surface.js +242 -0
- package/dist/repertoire/tools-teams.js +12 -59
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-vault.js +185 -0
- package/dist/repertoire/tools.js +132 -124
- package/dist/repertoire/travel-api-client.js +224 -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-client.js → bluebubbles/client.js} +109 -10
- package/dist/senses/bluebubbles/entry.js +13 -0
- package/dist/senses/bluebubbles/inbound-log.js +109 -0
- package/dist/senses/bluebubbles/index.js +1327 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +119 -24
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +13 -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/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 +358 -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 +503 -244
- 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 +591 -84
- package/dist/senses/pipeline.js +559 -0
- package/dist/senses/shared-turn.js +196 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams.js +667 -120
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +12 -6
- package/skills/browser-navigation.md +110 -0
- package/skills/configure-dev-tools.md +81 -0
- package/skills/travel-planning.md +143 -0
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/dist/senses/bluebubbles-entry.js +0 -11
- 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
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shellToolDefinitions = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const shell_sessions_1 = require("./shell-sessions");
|
|
6
|
+
const identity_1 = require("../heart/identity");
|
|
7
|
+
const runtime_1 = require("../nerves/runtime");
|
|
8
|
+
exports.shellToolDefinitions = [
|
|
9
|
+
{
|
|
10
|
+
tool: {
|
|
11
|
+
type: "function",
|
|
12
|
+
function: {
|
|
13
|
+
name: "shell",
|
|
14
|
+
description: "Run a shell command and return stdout/stderr. Working directory persists between calls. Use dedicated tools instead of shell when available: read_file instead of cat, edit_file instead of sed, glob instead of find, grep instead of grep/rg. Reserve shell for operations that genuinely need the shell: installing packages, running builds/tests, git operations, process management. Be careful with destructive commands -- consider reversibility before running. If a command fails, read the error output before retrying with a different approach.",
|
|
15
|
+
parameters: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
command: { type: "string" },
|
|
19
|
+
timeout_ms: {
|
|
20
|
+
type: "number",
|
|
21
|
+
description: "Timeout in milliseconds. Default: 30000. Max: 600000.",
|
|
22
|
+
},
|
|
23
|
+
background: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
description: "Run in background. Returns immediately with a process ID. Use shell_status/shell_tail to monitor.",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
required: ["command"],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
handler: (a) => {
|
|
33
|
+
// Destructive pattern detection (friction, not a block)
|
|
34
|
+
const destructivePatterns = (0, shell_sessions_1.detectDestructivePatterns)(a.command);
|
|
35
|
+
if (destructivePatterns.length > 0) {
|
|
36
|
+
(0, runtime_1.emitNervesEvent)({
|
|
37
|
+
level: "warn",
|
|
38
|
+
event: "tool.shell.destructive_detected",
|
|
39
|
+
component: "tools",
|
|
40
|
+
message: `destructive pattern detected: ${destructivePatterns.join(", ")}`,
|
|
41
|
+
meta: { command: a.command, patterns: destructivePatterns },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// Background mode: spawn and return immediately
|
|
45
|
+
if (a.background === "true") {
|
|
46
|
+
const session = (0, shell_sessions_1.spawnBackgroundShell)(a.command);
|
|
47
|
+
return JSON.stringify({ id: session.id, command: session.command, status: session.status });
|
|
48
|
+
}
|
|
49
|
+
const MAX_TIMEOUT = 600000;
|
|
50
|
+
const requestedTimeout = Number(a.timeout_ms) || 0;
|
|
51
|
+
let configDefault = 30000;
|
|
52
|
+
try {
|
|
53
|
+
configDefault = (0, identity_1.loadAgentConfig)().shell?.defaultTimeout ?? 30000;
|
|
54
|
+
}
|
|
55
|
+
catch { /* test env: no --agent flag */ }
|
|
56
|
+
const baseTimeout = requestedTimeout > 0 ? requestedTimeout : configDefault;
|
|
57
|
+
const timeout = Math.min(baseTimeout, MAX_TIMEOUT);
|
|
58
|
+
const output = (0, child_process_1.execSync)(a.command, {
|
|
59
|
+
encoding: "utf-8",
|
|
60
|
+
timeout,
|
|
61
|
+
});
|
|
62
|
+
if (destructivePatterns.length > 0) {
|
|
63
|
+
return `${output}\n\n--- destructive pattern detected: ${destructivePatterns.join(", ")} ---`;
|
|
64
|
+
}
|
|
65
|
+
return output;
|
|
66
|
+
},
|
|
67
|
+
summaryKeys: ["command"],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
tool: {
|
|
71
|
+
type: "function",
|
|
72
|
+
function: {
|
|
73
|
+
name: "shell_status",
|
|
74
|
+
description: "Check status of background shell processes. Omit id to list all.",
|
|
75
|
+
parameters: {
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: {
|
|
78
|
+
id: { type: "string", description: "Background shell process ID" },
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
handler: (a) => {
|
|
84
|
+
if (!a.id) {
|
|
85
|
+
return JSON.stringify((0, shell_sessions_1.listShellSessions)());
|
|
86
|
+
}
|
|
87
|
+
const session = (0, shell_sessions_1.getShellSession)(a.id);
|
|
88
|
+
if (!session)
|
|
89
|
+
return `process not found: ${a.id}`;
|
|
90
|
+
return JSON.stringify(session);
|
|
91
|
+
},
|
|
92
|
+
summaryKeys: ["id"],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
tool: {
|
|
96
|
+
type: "function",
|
|
97
|
+
function: {
|
|
98
|
+
name: "shell_tail",
|
|
99
|
+
description: "Show recent output from a background shell process.",
|
|
100
|
+
parameters: {
|
|
101
|
+
type: "object",
|
|
102
|
+
properties: {
|
|
103
|
+
id: { type: "string", description: "Background shell process ID" },
|
|
104
|
+
},
|
|
105
|
+
required: ["id"],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
handler: (a) => {
|
|
110
|
+
/* v8 ignore next -- schema requires id, defensive guard @preserve */
|
|
111
|
+
if (!a.id)
|
|
112
|
+
return "id is required";
|
|
113
|
+
const output = (0, shell_sessions_1.tailShellSession)(a.id);
|
|
114
|
+
if (output === undefined)
|
|
115
|
+
return `process not found: ${a.id}`;
|
|
116
|
+
return output || "(no output yet)";
|
|
117
|
+
},
|
|
118
|
+
summaryKeys: ["id"],
|
|
119
|
+
},
|
|
120
|
+
];
|
|
@@ -0,0 +1,242 @@
|
|
|
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.surfaceToolDefinition = exports.surfaceToolDef = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const identity_1 = require("../heart/identity");
|
|
39
|
+
const surface_tool_1 = require("../senses/surface-tool");
|
|
40
|
+
const obligations_1 = require("../arc/obligations");
|
|
41
|
+
const session_activity_1 = require("../heart/session-activity");
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
// Surface tool schema — canonical home. Handler lives in senses/surface-tool.ts.
|
|
44
|
+
exports.surfaceToolDef = {
|
|
45
|
+
type: "function",
|
|
46
|
+
function: {
|
|
47
|
+
name: "surface",
|
|
48
|
+
description: "share a thought outward — deliver an answer, ask a follow-up, or surface progress to whoever needs to hear it. pass delegationId to address a held thought (see your attention queue above), or friendId for spontaneous outreach. does not end your turn.",
|
|
49
|
+
parameters: {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: {
|
|
52
|
+
content: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "the message to deliver",
|
|
55
|
+
},
|
|
56
|
+
delegationId: {
|
|
57
|
+
type: "string",
|
|
58
|
+
description: "ID from your attention queue — addresses a specific held thought",
|
|
59
|
+
},
|
|
60
|
+
friendId: {
|
|
61
|
+
type: "string",
|
|
62
|
+
description: "friend to reach out to spontaneously (when not addressing a held thought)",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
required: ["content"],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
// Surface tool handler: routes content to friend's freshest session
|
|
70
|
+
/* v8 ignore start -- surface handler wiring: core logic tested via surface-tool.test.ts; this wires identity/routing deps @preserve */
|
|
71
|
+
exports.surfaceToolDefinition = {
|
|
72
|
+
tool: exports.surfaceToolDef,
|
|
73
|
+
handler: async (args, ctx) => {
|
|
74
|
+
const queue = ctx?.delegatedOrigins ?? [];
|
|
75
|
+
const agentName = (() => { try {
|
|
76
|
+
return (0, identity_1.getAgentName)();
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return "unknown";
|
|
80
|
+
} })();
|
|
81
|
+
const routeToFriend = async (friendId, content, queueItem) => {
|
|
82
|
+
/* v8 ignore start -- routing: integration path tested via inner-dialog routing tests @preserve */
|
|
83
|
+
try {
|
|
84
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
85
|
+
const sessionsDir = path.join(agentRoot, "state", "sessions");
|
|
86
|
+
const friendsDir = path.join(agentRoot, "friends");
|
|
87
|
+
// Resolve friend name → UUID if needed (agents may pass name instead of UUID)
|
|
88
|
+
let resolvedFriendId = friendId;
|
|
89
|
+
if (!fs.existsSync(path.join(sessionsDir, friendId))) {
|
|
90
|
+
try {
|
|
91
|
+
const friendFiles = fs.readdirSync(friendsDir).filter((f) => f.endsWith(".json"));
|
|
92
|
+
for (const file of friendFiles) {
|
|
93
|
+
const raw = fs.readFileSync(path.join(friendsDir, file), "utf-8");
|
|
94
|
+
const record = JSON.parse(raw);
|
|
95
|
+
if (record.name?.toLowerCase() === friendId.toLowerCase() && record.id) {
|
|
96
|
+
resolvedFriendId = record.id;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch { /* friends dir unreadable — continue with original friendId */ }
|
|
102
|
+
}
|
|
103
|
+
friendId = resolvedFriendId;
|
|
104
|
+
// Priority 1: Bridge-preferred session (if queue item has a bridgeId)
|
|
105
|
+
if (queueItem?.bridgeId) {
|
|
106
|
+
const { createBridgeManager } = await Promise.resolve().then(() => __importStar(require("../heart/bridges/manager")));
|
|
107
|
+
const bridge = createBridgeManager().getBridge(queueItem.bridgeId);
|
|
108
|
+
if (bridge && bridge.lifecycle !== "completed" && bridge.lifecycle !== "cancelled") {
|
|
109
|
+
const allSessions = (0, session_activity_1.listSessionActivity)({ sessionsDir, friendsDir, agentName, activeThresholdMs: Number.MAX_SAFE_INTEGER });
|
|
110
|
+
const bridgeTarget = allSessions.find((activity) => activity.friendId === friendId
|
|
111
|
+
&& activity.channel !== "inner"
|
|
112
|
+
&& bridge.attachedSessions.some((s) => s.friendId === activity.friendId && s.channel === activity.channel && s.key === activity.key));
|
|
113
|
+
if (bridgeTarget) {
|
|
114
|
+
// Attempt proactive BB delivery for bridge target
|
|
115
|
+
if (bridgeTarget.channel === "bluebubbles") {
|
|
116
|
+
const { sendProactiveBlueBubblesMessageToSession } = await Promise.resolve().then(() => __importStar(require("../senses/bluebubbles")));
|
|
117
|
+
const proactiveResult = await sendProactiveBlueBubblesMessageToSession({
|
|
118
|
+
friendId: bridgeTarget.friendId,
|
|
119
|
+
sessionKey: bridgeTarget.key,
|
|
120
|
+
text: content,
|
|
121
|
+
});
|
|
122
|
+
if (proactiveResult.delivered) {
|
|
123
|
+
// Inject surfaced content into the target session so it knows what was delivered
|
|
124
|
+
const { appendSyntheticAssistantMessage } = await Promise.resolve().then(() => __importStar(require("../mind/context")));
|
|
125
|
+
const sessionFilePath = path.join(sessionsDir, bridgeTarget.friendId, bridgeTarget.channel, `${bridgeTarget.key}.json`);
|
|
126
|
+
appendSyntheticAssistantMessage(sessionFilePath, `[surfaced from inner dialog] ${content}`);
|
|
127
|
+
return { status: "delivered", detail: "via iMessage" };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Fall back to pending queue for bridge target
|
|
131
|
+
const { queuePendingMessage, getPendingDir } = await Promise.resolve().then(() => __importStar(require("../mind/pending")));
|
|
132
|
+
const pendingDir = getPendingDir(agentName, bridgeTarget.friendId, bridgeTarget.channel, bridgeTarget.key);
|
|
133
|
+
queuePendingMessage(pendingDir, {
|
|
134
|
+
from: agentName,
|
|
135
|
+
friendId: bridgeTarget.friendId,
|
|
136
|
+
channel: bridgeTarget.channel,
|
|
137
|
+
key: bridgeTarget.key,
|
|
138
|
+
content,
|
|
139
|
+
timestamp: Date.now(),
|
|
140
|
+
});
|
|
141
|
+
return { status: "queued", detail: `for next interaction via ${bridgeTarget.channel}` };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Priority 2: Try proactive delivery first, then queue to freshest session
|
|
146
|
+
const allFriendSessions = (0, session_activity_1.listSessionActivity)({ sessionsDir, friendsDir, agentName, activeThresholdMs: Number.MAX_SAFE_INTEGER })
|
|
147
|
+
.filter((s) => s.friendId === friendId && s.channel !== "inner");
|
|
148
|
+
// 2a: Attempt proactive BB delivery on any BB session (prefer freshest)
|
|
149
|
+
const bbSession = allFriendSessions.find((s) => s.channel === "bluebubbles");
|
|
150
|
+
if (bbSession) {
|
|
151
|
+
const { sendProactiveBlueBubblesMessageToSession } = await Promise.resolve().then(() => __importStar(require("../senses/bluebubbles")));
|
|
152
|
+
const proactiveResult = await sendProactiveBlueBubblesMessageToSession({
|
|
153
|
+
friendId: bbSession.friendId,
|
|
154
|
+
sessionKey: bbSession.key,
|
|
155
|
+
text: content,
|
|
156
|
+
});
|
|
157
|
+
if (proactiveResult.delivered) {
|
|
158
|
+
const { appendSyntheticAssistantMessage } = await Promise.resolve().then(() => __importStar(require("../mind/context")));
|
|
159
|
+
const sessionFilePath = path.join(sessionsDir, bbSession.friendId, bbSession.channel, `${bbSession.key}.json`);
|
|
160
|
+
appendSyntheticAssistantMessage(sessionFilePath, `[surfaced from inner dialog] ${content}`);
|
|
161
|
+
return { status: "delivered", detail: "via iMessage" };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// 2b: No proactive delivery — queue to freshest non-inner session
|
|
165
|
+
const freshest = allFriendSessions[0];
|
|
166
|
+
if (freshest) {
|
|
167
|
+
const { queuePendingMessage, getPendingDir } = await Promise.resolve().then(() => __importStar(require("../mind/pending")));
|
|
168
|
+
const pendingDir = getPendingDir(agentName, freshest.friendId, freshest.channel, freshest.key);
|
|
169
|
+
queuePendingMessage(pendingDir, {
|
|
170
|
+
from: agentName,
|
|
171
|
+
friendId: freshest.friendId,
|
|
172
|
+
channel: freshest.channel,
|
|
173
|
+
key: freshest.key,
|
|
174
|
+
content,
|
|
175
|
+
timestamp: Date.now(),
|
|
176
|
+
});
|
|
177
|
+
return { status: "queued", detail: `for next interaction via ${freshest.channel}` };
|
|
178
|
+
}
|
|
179
|
+
// Priority 3: Deferred — no active session found
|
|
180
|
+
const { getDeferredReturnDir } = await Promise.resolve().then(() => __importStar(require("../mind/pending")));
|
|
181
|
+
const { queuePendingMessage: queueDeferred } = await Promise.resolve().then(() => __importStar(require("../mind/pending")));
|
|
182
|
+
const deferredDir = getDeferredReturnDir(agentName, friendId);
|
|
183
|
+
queueDeferred(deferredDir, {
|
|
184
|
+
from: agentName,
|
|
185
|
+
friendId,
|
|
186
|
+
channel: "deferred",
|
|
187
|
+
key: "return",
|
|
188
|
+
content,
|
|
189
|
+
timestamp: Date.now(),
|
|
190
|
+
});
|
|
191
|
+
return { status: "deferred", detail: "they'll see it next time" };
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return { status: "failed" };
|
|
195
|
+
}
|
|
196
|
+
/* v8 ignore stop */
|
|
197
|
+
};
|
|
198
|
+
return (0, surface_tool_1.handleSurface)({
|
|
199
|
+
content: args.content ?? "",
|
|
200
|
+
delegationId: args.delegationId,
|
|
201
|
+
friendId: args.friendId,
|
|
202
|
+
queue,
|
|
203
|
+
routeToFriend,
|
|
204
|
+
advanceObligation: (obligationId, update) => {
|
|
205
|
+
/* v8 ignore start -- obligation advance: tested via attention-queue tests @preserve */
|
|
206
|
+
try {
|
|
207
|
+
const name = (() => { try {
|
|
208
|
+
return (0, identity_1.getAgentName)();
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
return "unknown";
|
|
212
|
+
} })();
|
|
213
|
+
(0, obligations_1.advanceReturnObligation)(name, obligationId, {
|
|
214
|
+
status: update.status,
|
|
215
|
+
...(update.returnedAt !== undefined ? { returnedAt: update.returnedAt } : {}),
|
|
216
|
+
...(update.returnTarget !== undefined ? { returnTarget: update.returnTarget } : {}),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// swallowed — obligation advance must never break surface delivery
|
|
221
|
+
}
|
|
222
|
+
/* v8 ignore stop */
|
|
223
|
+
},
|
|
224
|
+
fulfillHeartObligation: (origin) => {
|
|
225
|
+
/* v8 ignore start -- heart obligation fulfillment: tested via surface-tool.test.ts @preserve */
|
|
226
|
+
try {
|
|
227
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
228
|
+
const heartObligation = (0, obligations_1.findPendingObligationForOrigin)(agentRoot, origin);
|
|
229
|
+
if (heartObligation) {
|
|
230
|
+
(0, obligations_1.fulfillObligation)(agentRoot, heartObligation.id);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// swallowed — heart obligation fulfillment must never break surface delivery
|
|
235
|
+
}
|
|
236
|
+
/* v8 ignore stop */
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
summaryKeys: ["content", "delegationId"],
|
|
241
|
+
};
|
|
242
|
+
/* v8 ignore stop */
|
|
@@ -3,24 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
exports.summarizeTeamsArgs = summarizeTeamsArgs;
|
|
6
|
+
exports.teamsToolDefinitions = void 0;
|
|
8
7
|
const graph_client_1 = require("./graph-client");
|
|
9
8
|
const ado_client_1 = require("./ado-client");
|
|
10
9
|
const graph_endpoints_json_1 = __importDefault(require("./data/graph-endpoints.json"));
|
|
11
10
|
const ado_endpoints_json_1 = __importDefault(require("./data/ado-endpoints.json"));
|
|
12
11
|
const runtime_1 = require("../nerves/runtime");
|
|
13
12
|
const MUTATE_METHODS = ["POST", "PATCH", "DELETE"];
|
|
14
|
-
// Map HTTP method to authority action name for canWrite() checks
|
|
15
|
-
const METHOD_TO_ACTION = {
|
|
16
|
-
POST: "createWorkItem",
|
|
17
|
-
PATCH: "updateWorkItem",
|
|
18
|
-
DELETE: "deleteWorkItem",
|
|
19
|
-
};
|
|
20
|
-
// Check if a tool response indicates a 403 PERMISSION_DENIED (authority checker removed; this is now a no-op kept for call-site stability)
|
|
21
|
-
function checkAndRecord403(_result, _integration, _scope, _action, _ctx) {
|
|
22
|
-
// No-op: AuthorityChecker eliminated. 403 recording removed.
|
|
23
|
-
}
|
|
24
13
|
const DEFAULT_ADO_QUERY = "SELECT [System.Id], [System.Title], [System.State], [System.AssignedTo] FROM WorkItems WHERE [System.AssignedTo] = @Me AND [System.State] <> 'Closed' ORDER BY [System.ChangedDate] DESC";
|
|
25
14
|
exports.teamsToolDefinitions = [
|
|
26
15
|
// -- Generic Graph tools --
|
|
@@ -46,6 +35,7 @@ exports.teamsToolDefinitions = [
|
|
|
46
35
|
return (0, graph_client_1.graphRequest)(ctx.graphToken, "GET", args.path);
|
|
47
36
|
},
|
|
48
37
|
integration: "graph",
|
|
38
|
+
summaryKeys: ["path"],
|
|
49
39
|
},
|
|
50
40
|
{
|
|
51
41
|
tool: {
|
|
@@ -75,6 +65,7 @@ exports.teamsToolDefinitions = [
|
|
|
75
65
|
},
|
|
76
66
|
integration: "graph",
|
|
77
67
|
confirmationRequired: true,
|
|
68
|
+
summaryKeys: ["method", "path"],
|
|
78
69
|
},
|
|
79
70
|
// -- Generic ADO tools --
|
|
80
71
|
{
|
|
@@ -101,11 +92,10 @@ exports.teamsToolDefinitions = [
|
|
|
101
92
|
return "AUTH_REQUIRED:ado -- I need access to Azure DevOps. Please sign in when prompted.";
|
|
102
93
|
}
|
|
103
94
|
const method = args.method || "GET";
|
|
104
|
-
|
|
105
|
-
checkAndRecord403(result, "ado", args.organization, method, ctx);
|
|
106
|
-
return result;
|
|
95
|
+
return (0, ado_client_1.adoRequest)(ctx.adoToken, method, args.organization, args.path, args.body, args.host);
|
|
107
96
|
},
|
|
108
97
|
integration: "ado",
|
|
98
|
+
summaryKeys: ["method", "organization", "path"],
|
|
109
99
|
},
|
|
110
100
|
{
|
|
111
101
|
tool: {
|
|
@@ -133,14 +123,11 @@ exports.teamsToolDefinitions = [
|
|
|
133
123
|
if (!MUTATE_METHODS.includes(args.method)) {
|
|
134
124
|
return `Invalid method "${args.method}". Must be one of: ${MUTATE_METHODS.join(", ")}`;
|
|
135
125
|
}
|
|
136
|
-
|
|
137
|
-
const action = METHOD_TO_ACTION[args.method] || args.method;
|
|
138
|
-
const result = await (0, ado_client_1.adoRequest)(ctx.adoToken, args.method, args.organization, args.path, args.body, args.host);
|
|
139
|
-
checkAndRecord403(result, "ado", args.organization, action, ctx);
|
|
140
|
-
return result;
|
|
126
|
+
return (0, ado_client_1.adoRequest)(ctx.adoToken, args.method, args.organization, args.path, args.body, args.host);
|
|
141
127
|
},
|
|
142
128
|
integration: "ado",
|
|
143
129
|
confirmationRequired: true,
|
|
130
|
+
summaryKeys: ["method", "organization", "path"],
|
|
144
131
|
},
|
|
145
132
|
// -- Convenience aliases (backward compat) --
|
|
146
133
|
{
|
|
@@ -159,6 +146,7 @@ exports.teamsToolDefinitions = [
|
|
|
159
146
|
return (0, graph_client_1.getProfile)(ctx.graphToken);
|
|
160
147
|
},
|
|
161
148
|
integration: "graph",
|
|
149
|
+
summaryKeys: [],
|
|
162
150
|
},
|
|
163
151
|
{
|
|
164
152
|
tool: {
|
|
@@ -202,6 +190,7 @@ exports.teamsToolDefinitions = [
|
|
|
202
190
|
return (0, ado_client_1.queryWorkItems)(ctx.adoToken, org, query);
|
|
203
191
|
},
|
|
204
192
|
integration: "ado",
|
|
193
|
+
summaryKeys: ["organization", "query"],
|
|
205
194
|
},
|
|
206
195
|
// -- Proactive messaging --
|
|
207
196
|
{
|
|
@@ -249,6 +238,7 @@ exports.teamsToolDefinitions = [
|
|
|
249
238
|
},
|
|
250
239
|
/* v8 ignore stop */
|
|
251
240
|
confirmationRequired: true,
|
|
241
|
+
summaryKeys: ["user_name", "user_id"],
|
|
252
242
|
},
|
|
253
243
|
// -- Documentation tools --
|
|
254
244
|
{
|
|
@@ -270,6 +260,7 @@ exports.teamsToolDefinitions = [
|
|
|
270
260
|
return searchEndpoints(graph_endpoints_json_1.default, args.query || "");
|
|
271
261
|
},
|
|
272
262
|
integration: "graph",
|
|
263
|
+
summaryKeys: ["query"],
|
|
273
264
|
},
|
|
274
265
|
{
|
|
275
266
|
tool: {
|
|
@@ -290,12 +281,9 @@ exports.teamsToolDefinitions = [
|
|
|
290
281
|
return searchEndpoints(ado_endpoints_json_1.default, args.query || "");
|
|
291
282
|
},
|
|
292
283
|
integration: "ado",
|
|
284
|
+
summaryKeys: ["query"],
|
|
293
285
|
},
|
|
294
286
|
];
|
|
295
|
-
// Backward-compat: extract just the OpenAI tool schemas
|
|
296
|
-
exports.teamsTools = exports.teamsToolDefinitions.map((d) => d.tool);
|
|
297
|
-
// Backward-compat: extract just the handlers by name
|
|
298
|
-
exports.teamsToolHandlers = Object.fromEntries(exports.teamsToolDefinitions.map((d) => [d.tool.function.name, d.handler]));
|
|
299
287
|
function searchEndpoints(entries, query) {
|
|
300
288
|
(0, runtime_1.emitNervesEvent)({
|
|
301
289
|
component: "repertoire",
|
|
@@ -324,38 +312,3 @@ function searchEndpoints(entries, query) {
|
|
|
324
312
|
return lines.join("\n");
|
|
325
313
|
}).join("\n\n");
|
|
326
314
|
}
|
|
327
|
-
function summarizeTeamsArgs(name, args) {
|
|
328
|
-
function summarizeKeyValues(keys) {
|
|
329
|
-
const parts = [];
|
|
330
|
-
for (const key of keys) {
|
|
331
|
-
const raw = args[key];
|
|
332
|
-
if (raw === undefined || raw === null)
|
|
333
|
-
continue;
|
|
334
|
-
const compact = String(raw).replace(/\s+/g, " ").trim();
|
|
335
|
-
if (!compact)
|
|
336
|
-
continue;
|
|
337
|
-
const clipped = compact.length > 60 ? compact.slice(0, 60) + "..." : compact;
|
|
338
|
-
parts.push(`${key}=${clipped}`);
|
|
339
|
-
}
|
|
340
|
-
return parts.join(" ");
|
|
341
|
-
}
|
|
342
|
-
if (name === "graph_profile")
|
|
343
|
-
return "";
|
|
344
|
-
if (name === "ado_work_items")
|
|
345
|
-
return summarizeKeyValues(["organization", "query"]);
|
|
346
|
-
if (name === "graph_query")
|
|
347
|
-
return summarizeKeyValues(["path"]);
|
|
348
|
-
if (name === "graph_mutate")
|
|
349
|
-
return summarizeKeyValues(["method", "path"]);
|
|
350
|
-
if (name === "ado_query")
|
|
351
|
-
return summarizeKeyValues(["method", "organization", "path"]);
|
|
352
|
-
if (name === "ado_mutate")
|
|
353
|
-
return summarizeKeyValues(["method", "organization", "path"]);
|
|
354
|
-
if (name === "graph_docs")
|
|
355
|
-
return summarizeKeyValues(["query"]);
|
|
356
|
-
if (name === "ado_docs")
|
|
357
|
-
return summarizeKeyValues(["query"]);
|
|
358
|
-
if (name === "teams_send_message")
|
|
359
|
-
return summarizeKeyValues(["user_name", "user_id"]);
|
|
360
|
-
return undefined;
|
|
361
|
-
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.travelToolDefinitions = void 0;
|
|
4
|
+
const travel_api_client_1 = require("./travel-api-client");
|
|
5
|
+
const runtime_1 = require("../nerves/runtime");
|
|
6
|
+
exports.travelToolDefinitions = [
|
|
7
|
+
{
|
|
8
|
+
tool: {
|
|
9
|
+
type: "function",
|
|
10
|
+
function: {
|
|
11
|
+
name: "weather_lookup",
|
|
12
|
+
description: "Get current weather for a location. Provide either a city name or lat/lon coordinates.",
|
|
13
|
+
parameters: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
city: { type: "string", description: "City name (e.g. 'London', 'New York')" },
|
|
17
|
+
lat: { type: "string", description: "Latitude (decimal)" },
|
|
18
|
+
lon: { type: "string", description: "Longitude (decimal)" },
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
handler: async (args) => {
|
|
24
|
+
(0, runtime_1.emitNervesEvent)({
|
|
25
|
+
component: "repertoire",
|
|
26
|
+
event: "repertoire.travel_tool_call",
|
|
27
|
+
message: "weather_lookup invoked",
|
|
28
|
+
meta: { tool: "weather_lookup" },
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
if (args.city) {
|
|
32
|
+
const data = await (0, travel_api_client_1.getWeatherByCity)(args.city);
|
|
33
|
+
return JSON.stringify(data, null, 2);
|
|
34
|
+
}
|
|
35
|
+
if (args.lat && args.lon) {
|
|
36
|
+
const data = await (0, travel_api_client_1.getWeather)(parseFloat(args.lat), parseFloat(args.lon));
|
|
37
|
+
return JSON.stringify(data, null, 2);
|
|
38
|
+
}
|
|
39
|
+
return "Please provide either a city name or lat/lon coordinates.";
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
/* v8 ignore next -- defensive: callers throw Error instances @preserve */
|
|
43
|
+
return `Weather lookup error: ${err instanceof Error ? err.message : String(err)}`;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
summaryKeys: ["city", "lat", "lon"],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
tool: {
|
|
50
|
+
type: "function",
|
|
51
|
+
function: {
|
|
52
|
+
name: "travel_advisory",
|
|
53
|
+
description: "Get US State Department travel advisory for a country. Returns advisory level (1-4) and description.",
|
|
54
|
+
parameters: {
|
|
55
|
+
type: "object",
|
|
56
|
+
properties: {
|
|
57
|
+
country_code: {
|
|
58
|
+
type: "string",
|
|
59
|
+
description: "ISO 3166 alpha-2 country code (e.g. 'US', 'GB', 'AF')",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
required: ["country_code"],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
handler: async (args) => {
|
|
67
|
+
(0, runtime_1.emitNervesEvent)({
|
|
68
|
+
component: "repertoire",
|
|
69
|
+
event: "repertoire.travel_tool_call",
|
|
70
|
+
message: "travel_advisory invoked",
|
|
71
|
+
meta: { tool: "travel_advisory" },
|
|
72
|
+
});
|
|
73
|
+
try {
|
|
74
|
+
const data = await (0, travel_api_client_1.getTravelAdvisory)(args.country_code.toUpperCase());
|
|
75
|
+
return JSON.stringify(data, null, 2);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
/* v8 ignore next -- defensive: callers throw Error instances @preserve */
|
|
79
|
+
return `Travel advisory error: ${err instanceof Error ? err.message : String(err)}`;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
summaryKeys: ["country_code"],
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
tool: {
|
|
86
|
+
type: "function",
|
|
87
|
+
function: {
|
|
88
|
+
name: "geocode_search",
|
|
89
|
+
description: "Search for locations, addresses, or points of interest. Returns coordinates and display names.",
|
|
90
|
+
parameters: {
|
|
91
|
+
type: "object",
|
|
92
|
+
properties: {
|
|
93
|
+
query: { type: "string", description: "Search query (e.g. 'Eiffel Tower', '123 Main St')" },
|
|
94
|
+
near_lat: { type: "string", description: "Latitude to search near (for POI search)" },
|
|
95
|
+
near_lon: { type: "string", description: "Longitude to search near (for POI search)" },
|
|
96
|
+
radius_km: { type: "string", description: "Search radius in km (default 10)" },
|
|
97
|
+
},
|
|
98
|
+
required: ["query"],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
handler: async (args) => {
|
|
103
|
+
(0, runtime_1.emitNervesEvent)({
|
|
104
|
+
component: "repertoire",
|
|
105
|
+
event: "repertoire.travel_tool_call",
|
|
106
|
+
message: "geocode_search invoked",
|
|
107
|
+
meta: { tool: "geocode_search" },
|
|
108
|
+
});
|
|
109
|
+
try {
|
|
110
|
+
if (args.near_lat && args.near_lon) {
|
|
111
|
+
const radiusKm = args.radius_km ? parseFloat(args.radius_km) : undefined;
|
|
112
|
+
const data = await (0, travel_api_client_1.searchPOI)(args.query, parseFloat(args.near_lat), parseFloat(args.near_lon), radiusKm);
|
|
113
|
+
return JSON.stringify(data, null, 2);
|
|
114
|
+
}
|
|
115
|
+
const data = await (0, travel_api_client_1.geocode)(args.query);
|
|
116
|
+
return JSON.stringify(data, null, 2);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
/* v8 ignore next -- defensive: callers throw Error instances @preserve */
|
|
120
|
+
return `Geocode error: ${err instanceof Error ? err.message : String(err)}`;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
summaryKeys: ["query"],
|
|
124
|
+
},
|
|
125
|
+
];
|