@ouro.bot/cli 0.1.0-alpha.810 → 0.1.0-alpha.811
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/changelog.json +12 -0
- package/deploy/unraid/sanctuary-acceptance-contract.json +1 -1
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +8 -7
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +1 -1
- package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +1 -1
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +2 -2
- package/deploy/unraid/sanctuary.xml +1 -1
- package/dist/heart/config.js +32 -2
- package/dist/heart/core.js +167 -115
- package/dist/heart/daemon/daemon.js +19 -9
- package/dist/heart/daemon/sanctuary-acceptance-adapter.js +88 -50
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +53 -15
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +6 -26
- package/dist/heart/frontend-approval-runtime.js +87 -13
- package/dist/heart/identity.js +17 -5
- package/dist/heart/session-events.js +8 -1
- package/dist/heart/tool-approval.js +64 -31
- package/dist/mind/pending.js +4 -4
- package/dist/repertoire/mcp-manager.js +365 -381
- package/dist/repertoire/mcp-tools.js +66 -25
- package/dist/repertoire/plugin-mcp.js +3 -3
- package/dist/repertoire/shell-sessions.js +8 -7
- package/dist/repertoire/tool-arguments.js +30 -8
- package/dist/repertoire/tools-session.js +30 -5
- package/dist/repertoire/tools-shell.js +30 -14
- package/dist/repertoire/tools-voice.js +6 -6
- package/dist/repertoire/tools.js +231 -205
- package/dist/senses/bluebubbles/index.js +4 -2
- package/dist/senses/cli.js +6 -5
- package/dist/senses/private-runtime.js +9 -3
- package/dist/senses/shared-turn.js +12 -9
- package/dist/senses/teams.js +15 -12
- package/dist/senses/telegram-approval-runtime.js +129 -20
- package/dist/senses/telegram-client.js +19 -2
- package/dist/senses/telegram.js +54 -15
- package/dist/senses/voice/twilio-phone.js +123 -173
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/senses/cli.js
CHANGED
|
@@ -951,7 +951,9 @@ async function main(agentName, options) {
|
|
|
951
951
|
// Fail fast if provider is misconfigured (triggers human-readable error + exit)
|
|
952
952
|
(0, core_1.getProvider)("human");
|
|
953
953
|
// Resolve context kernel (identity + channel) for CLI
|
|
954
|
-
const
|
|
954
|
+
const currentAgentName = (0, identity_1.getAgentName)();
|
|
955
|
+
const owner = { agentName: currentAgentName, agentRoot: (0, identity_1.getAgentRoot)(currentAgentName) };
|
|
956
|
+
const friendsPath = path.join(owner.agentRoot, "friends");
|
|
955
957
|
const friendStore = new friends_1.FileFriendStore(friendsPath);
|
|
956
958
|
const username = os.userInfo().username;
|
|
957
959
|
const localExternalId = username;
|
|
@@ -975,13 +977,11 @@ async function main(agentName, options) {
|
|
|
975
977
|
let existing = null;
|
|
976
978
|
let sessionState;
|
|
977
979
|
let sessionEvents = [];
|
|
978
|
-
const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)() ?? undefined;
|
|
979
980
|
const sessionMessages = [
|
|
980
981
|
{ role: "system", content: (0, prompt_1.flattenSystemPrompt)(await (0, prompt_1.buildSystem)("cli", {}, resolvedContext)) },
|
|
981
982
|
];
|
|
982
983
|
// Per-turn pipeline input: CLI capabilities and pending dir
|
|
983
984
|
const cliCapabilities = (0, friends_1.getChannelCapabilities)("cli");
|
|
984
|
-
const currentAgentName = (0, identity_1.getAgentName)();
|
|
985
985
|
const pendingDir = (0, pending_1.getPendingDir)(currentAgentName, friendId, "cli", "session");
|
|
986
986
|
const summarize = (0, core_1.createSummarize)("human");
|
|
987
987
|
const cliFailoverState = { pending: null };
|
|
@@ -1077,12 +1077,14 @@ async function main(agentName, options) {
|
|
|
1077
1077
|
enforceTrustGate: trust_gate_1.enforceTrustGate,
|
|
1078
1078
|
drainPending: pending_1.drainPending,
|
|
1079
1079
|
drainDeferredReturns: (deferredFriendId) => (0, pending_1.drainDeferredReturns)(currentAgentName, deferredFriendId),
|
|
1080
|
-
runAgent: (msgs, cb, channel, sig, opts) => (0, core_1.runAgent)(msgs, cb, channel, sig, {
|
|
1080
|
+
runAgent: async (msgs, cb, channel, sig, opts) => (0, core_1.runAgent)(msgs, cb, channel, sig, {
|
|
1081
1081
|
...opts,
|
|
1082
|
+
mcpManager: opts?.hardDisableTools ? undefined : await (0, mcp_manager_1.getSharedMcpManager)(owner) ?? undefined,
|
|
1082
1083
|
toolContext: {
|
|
1083
1084
|
/* v8 ignore next -- default no-op signin; pipeline provides the real one @preserve */
|
|
1084
1085
|
signin: async () => undefined,
|
|
1085
1086
|
...opts?.toolContext,
|
|
1087
|
+
...owner,
|
|
1086
1088
|
summarize,
|
|
1087
1089
|
},
|
|
1088
1090
|
}),
|
|
@@ -1102,7 +1104,6 @@ async function main(agentName, options) {
|
|
|
1102
1104
|
runAgentOptions: {
|
|
1103
1105
|
toolChoiceRequired: (0, commands_1.getToolChoiceRequired)(),
|
|
1104
1106
|
traceId: (0, nerves_1.createTraceId)(),
|
|
1105
|
-
mcpManager,
|
|
1106
1107
|
toolContext,
|
|
1107
1108
|
},
|
|
1108
1109
|
failoverState,
|
|
@@ -1157,7 +1157,8 @@ async function runPrivateRuntimeTurn(options) {
|
|
|
1157
1157
|
const innerCapabilities = (0, friends_1.getChannelCapabilities)("inner");
|
|
1158
1158
|
const selfFriend = createSelfFriend(agentName);
|
|
1159
1159
|
const selfContext = { friend: selfFriend, channel: innerCapabilities };
|
|
1160
|
-
const
|
|
1160
|
+
const mcpOwner = { agentName, agentRoot: (0, identity_1.getAgentRoot)(agentName) };
|
|
1161
|
+
const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)(mcpOwner) ?? undefined;
|
|
1161
1162
|
const relationshipAwaitCoordinatesValue = parsedAwait ? relationshipAwaitCoordinates(parsedAwait) : null;
|
|
1162
1163
|
const relationshipAwait = relationshipAwaitCoordinatesValue
|
|
1163
1164
|
? await (async () => {
|
|
@@ -1301,11 +1302,15 @@ async function runPrivateRuntimeTurn(options) {
|
|
|
1301
1302
|
}
|
|
1302
1303
|
const externalEventExcludedTools = new Set(["rest", "settle", "speak"]);
|
|
1303
1304
|
const externalEventToolsResolved = options?.externalEvent
|
|
1304
|
-
? (0, tools_1.
|
|
1305
|
+
? (0, tools_1.getToolsForChannel)(innerCapabilities, undefined, undefined, undefined, undefined, undefined, {
|
|
1306
|
+
agentName, relationshipAuthorization: externalEventRelationship.relationshipAuthorization,
|
|
1307
|
+
})
|
|
1305
1308
|
.filter((tool) => !externalEventExcludedTools.has(tool.function.name))
|
|
1306
1309
|
: undefined;
|
|
1307
1310
|
const relationshipAwaitToolsResolved = relationshipAwait
|
|
1308
|
-
? (0, tools_1.
|
|
1311
|
+
? (0, tools_1.getToolsForChannel)(innerCapabilities, undefined, undefined, undefined, undefined, undefined, {
|
|
1312
|
+
agentName, relationshipAuthorization: relationshipAwait.relationshipAuthorization,
|
|
1313
|
+
})
|
|
1309
1314
|
: undefined;
|
|
1310
1315
|
const effectiveHabitSession = options?.noSend === true
|
|
1311
1316
|
? reduceHabitSessionToNoSend(options.habitSession)
|
|
@@ -1429,6 +1434,7 @@ async function runPrivateRuntimeTurn(options) {
|
|
|
1429
1434
|
} : {}),
|
|
1430
1435
|
...(options?.noSend ? { noSend: true } : {}),
|
|
1431
1436
|
...(effectiveHabitSession ? { habitSession: effectiveHabitSession } : {}),
|
|
1437
|
+
...mcpOwner,
|
|
1432
1438
|
},
|
|
1433
1439
|
...(effectiveHabitSession ? { habitSession: effectiveHabitSession } : {}),
|
|
1434
1440
|
},
|
|
@@ -66,9 +66,9 @@ const OUTWARD_DELIVERY_TOOL_ACKS = new Map([
|
|
|
66
66
|
["settle", "(delivered)"],
|
|
67
67
|
["speak", "(spoken)"],
|
|
68
68
|
]);
|
|
69
|
-
async function releaseRuntimeMcpServersAfterTurn() {
|
|
69
|
+
async function releaseRuntimeMcpServersAfterTurn(owner) {
|
|
70
70
|
const manager = await Promise.resolve().then(() => __importStar(require("../repertoire/mcp-manager")));
|
|
71
|
-
await manager.releaseRuntimeMcpServers();
|
|
71
|
+
await manager.releaseRuntimeMcpServers(owner);
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Strip MiniMax-style `<think>...</think>` reasoning blocks from a response
|
|
@@ -323,19 +323,21 @@ function getSenseSessionPath(agentName, friendId, channel, sessionKey, agentRoot
|
|
|
323
323
|
*/
|
|
324
324
|
async function runSenseTurn(options) {
|
|
325
325
|
return (0, turn_execution_lease_1.withTurnExecutionLease)(async () => {
|
|
326
|
-
(0, identity_1.
|
|
326
|
+
const owner = Object.freeze({ agentName: options.agentName, agentRoot: (0, identity_1.getAgentRoot)(options.agentName) });
|
|
327
|
+
(0, identity_1.setAgentName)(owner.agentName);
|
|
327
328
|
try {
|
|
328
|
-
return await runSenseTurnExclusive(options);
|
|
329
|
+
return await runSenseTurnExclusive(options, owner);
|
|
329
330
|
}
|
|
330
331
|
finally {
|
|
331
332
|
if (options.runtimeMcpServers && !options.disableTools) {
|
|
332
|
-
await releaseRuntimeMcpServersAfterTurn();
|
|
333
|
+
await releaseRuntimeMcpServersAfterTurn(owner);
|
|
333
334
|
}
|
|
334
335
|
}
|
|
335
336
|
});
|
|
336
337
|
}
|
|
337
|
-
async function runSenseTurnExclusive(options) {
|
|
338
|
-
const {
|
|
338
|
+
async function runSenseTurnExclusive(options, owner) {
|
|
339
|
+
const { channel, sessionKey, friendId, userMessage } = options;
|
|
340
|
+
const { agentName, agentRoot } = owner;
|
|
339
341
|
(0, runtime_1.emitNervesEvent)({
|
|
340
342
|
component: "senses",
|
|
341
343
|
event: "senses.shared_turn_start",
|
|
@@ -343,7 +345,6 @@ async function runSenseTurnExclusive(options) {
|
|
|
343
345
|
meta: { agentName, channel, sessionKey, friendId },
|
|
344
346
|
});
|
|
345
347
|
// Resolve context
|
|
346
|
-
const agentRoot = (0, identity_1.getAgentRoot)(agentName);
|
|
347
348
|
const friendsPath = path.join(agentRoot, "friends");
|
|
348
349
|
const friendStore = new friends_1.FileFriendStore(friendsPath);
|
|
349
350
|
const capabilities = (0, friends_1.getChannelCapabilities)(channel);
|
|
@@ -386,7 +387,7 @@ async function runSenseTurnExclusive(options) {
|
|
|
386
387
|
// Runtime MCP servers (e.g. Workbench's ouro_workbench) are passed per-turn for THIS agent only.
|
|
387
388
|
const mcpManager = options.disableTools
|
|
388
389
|
? undefined
|
|
389
|
-
: await (0, mcp_manager_1.getSharedMcpManager)(
|
|
390
|
+
: await (0, mcp_manager_1.getSharedMcpManager)({ ...owner, runtimeServers: options.runtimeMcpServers }) ?? undefined;
|
|
390
391
|
// Session path and loading
|
|
391
392
|
const ephemeralRoot = options.disablePersistence
|
|
392
393
|
? fs.mkdtempSync(path.join(os.tmpdir(), "ouro-observe-only-"))
|
|
@@ -576,6 +577,8 @@ async function runSenseTurnExclusive(options) {
|
|
|
576
577
|
toolContext: {
|
|
577
578
|
signin: async () => undefined,
|
|
578
579
|
...(options.toolContext ? options.toolContext : {}),
|
|
580
|
+
agentName,
|
|
581
|
+
agentRoot,
|
|
579
582
|
currentUserMessage: userMessage,
|
|
580
583
|
},
|
|
581
584
|
},
|
package/dist/senses/teams.js
CHANGED
|
@@ -643,6 +643,8 @@ function handleTeamsSlashCommand(text, registry, friendId, conversationId, strea
|
|
|
643
643
|
// Handle an incoming Teams message
|
|
644
644
|
async function handleTeamsMessage(text, stream, conversationId, teamsContext, sendMessage, reactionOverrides, runtimeOverrides) {
|
|
645
645
|
const turnKey = teamsTurnKey(conversationId);
|
|
646
|
+
const agentName = (0, identity_1.getAgentName)();
|
|
647
|
+
const owner = { agentName, agentRoot: (0, identity_1.getAgentRoot)(agentName) };
|
|
646
648
|
// NOTE: Confirmation resolution is handled in the app.on("message") handler
|
|
647
649
|
// BEFORE the conversation lock. By the time we get here, any pending
|
|
648
650
|
// confirmation has already been resolved and the reply consumed.
|
|
@@ -668,7 +670,7 @@ async function handleTeamsMessage(text, stream, conversationId, teamsContext, se
|
|
|
668
670
|
const traceId = (0, nerves_1.createTraceId)();
|
|
669
671
|
const sessPath = (0, config_2.sessionPath)(friendId, "teams", conversationId);
|
|
670
672
|
const teamsCapabilities = (0, friends_1.getChannelCapabilities)("teams");
|
|
671
|
-
const pendingDir = (0, pending_1.getPendingDir)(
|
|
673
|
+
const pendingDir = (0, pending_1.getPendingDir)(agentName, friendId, "teams", conversationId);
|
|
672
674
|
const runWithLease = runtimeOverrides?._withSessionTurnLease ?? session_transaction_1.withSessionTurnLease;
|
|
673
675
|
try {
|
|
674
676
|
await runWithLease(sessPath, async (sessionTurnLease) => {
|
|
@@ -678,17 +680,17 @@ async function handleTeamsMessage(text, stream, conversationId, teamsContext, se
|
|
|
678
680
|
}
|
|
679
681
|
await new Promise(r => setImmediate(r));
|
|
680
682
|
// Build Teams-specific toolContext fields for injection into the pipeline
|
|
681
|
-
const teamsToolContext = teamsContext ? {
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
683
|
+
const teamsToolContext = { ...owner, ...(teamsContext ? {
|
|
684
|
+
graphToken: teamsContext.graphToken,
|
|
685
|
+
adoToken: teamsContext.adoToken,
|
|
686
|
+
githubToken: teamsContext.githubToken,
|
|
687
|
+
signin: teamsContext.signin,
|
|
688
|
+
summarize: (0, core_1.createSummarize)("human"),
|
|
689
|
+
tenantId: teamsContext.tenantId,
|
|
690
|
+
botApi: teamsContext.botApi,
|
|
691
|
+
} : {}) };
|
|
690
692
|
let currentText = text;
|
|
691
|
-
const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)() ?? undefined;
|
|
693
|
+
const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)(owner) ?? undefined;
|
|
692
694
|
while (true) {
|
|
693
695
|
let drainedSteeringFollowUps = [];
|
|
694
696
|
// Build runAgentOptions with Teams-specific fields
|
|
@@ -759,13 +761,14 @@ async function handleTeamsMessage(text, stream, conversationId, teamsContext, se
|
|
|
759
761
|
hasExistingGroupWithFamily: false,
|
|
760
762
|
enforceTrustGate: trust_gate_1.enforceTrustGate,
|
|
761
763
|
drainPending: pending_1.drainPending,
|
|
762
|
-
drainDeferredReturns: (deferredFriendId) => (0, pending_1.drainDeferredReturns)(
|
|
764
|
+
drainDeferredReturns: (deferredFriendId) => (0, pending_1.drainDeferredReturns)(agentName, deferredFriendId),
|
|
763
765
|
runAgent: (msgs, cb, channel, sig, opts) => (0, core_1.runAgent)(msgs, cb, channel, sig, {
|
|
764
766
|
...opts,
|
|
765
767
|
toolContext: {
|
|
766
768
|
/* v8 ignore next -- default no-op signin; pipeline provides the real one @preserve */
|
|
767
769
|
signin: async () => undefined,
|
|
768
770
|
...opts?.toolContext,
|
|
771
|
+
...owner,
|
|
769
772
|
summarize: teamsToolContext.summarize,
|
|
770
773
|
},
|
|
771
774
|
}),
|
|
@@ -41,6 +41,7 @@ exports.executeApprovedTelegramTool = executeApprovedTelegramTool;
|
|
|
41
41
|
exports.createTelegramApprovalRuntime = createTelegramApprovalRuntime;
|
|
42
42
|
const path = __importStar(require("node:path"));
|
|
43
43
|
const node_crypto_1 = require("node:crypto");
|
|
44
|
+
const friends_1 = require("@ouro.bot/friends");
|
|
44
45
|
const approval_files_1 = require("../heart/approval-files");
|
|
45
46
|
const approval_store_1 = require("../heart/approval-store");
|
|
46
47
|
const tool_approval_1 = require("../heart/tool-approval");
|
|
@@ -52,6 +53,7 @@ const telegram_1 = require("./telegram");
|
|
|
52
53
|
const context_1 = require("../mind/context");
|
|
53
54
|
const session_transaction_1 = require("../mind/session-transaction");
|
|
54
55
|
const tools_1 = require("../repertoire/tools");
|
|
56
|
+
const mcp_manager_1 = require("../repertoire/mcp-manager");
|
|
55
57
|
const runtime_1 = require("../nerves/runtime");
|
|
56
58
|
const telegram_client_1 = require("./telegram-client");
|
|
57
59
|
function telegramApprovalCommitBarrierHooks(effectBarrier) {
|
|
@@ -89,7 +91,17 @@ async function executeApprovedTelegramTool(name, args, execute, scenarioHandleDi
|
|
|
89
91
|
});
|
|
90
92
|
try {
|
|
91
93
|
effectBarrier();
|
|
92
|
-
const
|
|
94
|
+
const outcome = await execute(name, args);
|
|
95
|
+
if (outcome.kind !== "handler_succeeded") {
|
|
96
|
+
if (name === "unraid_restart_container")
|
|
97
|
+
(0, runtime_1.emitNervesEvent)({
|
|
98
|
+
level: "error", component: "senses", event: "senses.telegram_approved_restart_error",
|
|
99
|
+
message: "approved Sanctuary restart did not complete",
|
|
100
|
+
meta: { ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}), ...(approvalId ? { approvalId } : {}), outcome: outcome.kind },
|
|
101
|
+
});
|
|
102
|
+
return outcome;
|
|
103
|
+
}
|
|
104
|
+
const result = outcome.text;
|
|
93
105
|
if (name === "sanctuary_resume_download_queue") {
|
|
94
106
|
let parsed;
|
|
95
107
|
try {
|
|
@@ -99,14 +111,14 @@ async function executeApprovedTelegramTool(name, args, execute, scenarioHandleDi
|
|
|
99
111
|
throw new tool_approval_1.ApprovalExecutionFailedError("approved download resume returned an invalid result");
|
|
100
112
|
}
|
|
101
113
|
const data = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
102
|
-
const
|
|
103
|
-
const after =
|
|
104
|
-
if (data?.ok !== true ||
|
|
114
|
+
const verification = data?.data && typeof data.data === "object" && !Array.isArray(data.data) ? data.data : null;
|
|
115
|
+
const after = verification?.after && typeof verification.after === "object" && !Array.isArray(verification.after) ? verification.after : null;
|
|
116
|
+
if (data?.ok !== true || verification?.verified !== true || after?.paused !== false)
|
|
105
117
|
throw new tool_approval_1.ApprovalExecutionFailedError("approved download resume was not independently verified");
|
|
106
|
-
return
|
|
118
|
+
return outcome;
|
|
107
119
|
}
|
|
108
120
|
if (name !== "unraid_restart_container")
|
|
109
|
-
return
|
|
121
|
+
return outcome;
|
|
110
122
|
let parsed;
|
|
111
123
|
try {
|
|
112
124
|
parsed = JSON.parse(result);
|
|
@@ -147,7 +159,7 @@ async function executeApprovedTelegramTool(name, args, execute, scenarioHandleDi
|
|
|
147
159
|
message: "approved Sanctuary restart execution completed",
|
|
148
160
|
meta: { ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}), ...(approvalId ? { approvalId } : {}), observedRestart: true },
|
|
149
161
|
});
|
|
150
|
-
return
|
|
162
|
+
return outcome;
|
|
151
163
|
}
|
|
152
164
|
catch (error) {
|
|
153
165
|
if (name === "unraid_restart_container")
|
|
@@ -176,9 +188,42 @@ function createTelegramApprovalRuntime(options) {
|
|
|
176
188
|
const acceptanceMarker = options.dependencies?.acceptanceMarker ?? (() => (0, sanctuary_acceptance_marker_1.readSanctuaryAcceptanceMarker)(options.agentName));
|
|
177
189
|
const provider = options.dependencies?.runProvider ?? core_1.runAgent;
|
|
178
190
|
const resolveTool = options.dependencies?.resolveTool ?? tools_1.resolveToolDefinition;
|
|
179
|
-
const executeTool = options.dependencies?.executeTool ?? tools_1.execTool;
|
|
180
191
|
const agentRoot = options.dependencies?.agentRoot ?? (0, identity_1.getAgentRoot)(options.agentName);
|
|
181
|
-
const
|
|
192
|
+
const owner = Object.freeze({ agentName: options.agentName, agentRoot });
|
|
193
|
+
const currentOptions = async (record) => {
|
|
194
|
+
try {
|
|
195
|
+
if (!options.resolveLiveToolContext)
|
|
196
|
+
throw new Error("current owner authority producer is unavailable");
|
|
197
|
+
const context = await options.resolveLiveToolContext(record);
|
|
198
|
+
const relationship = context.relationshipAuthorization;
|
|
199
|
+
if (context.agentName !== owner.agentName || context.agentRoot !== owner.agentRoot
|
|
200
|
+
|| relationship?.profileId !== "sanctuary-owner" || relationship.actor?.trustLevel !== "family"
|
|
201
|
+
|| context.context?.friend.trustLevel !== "family" || context.context.friend.id !== relationship.actor.friendId
|
|
202
|
+
|| context.currentSession?.friendId !== relationship.actor.friendId
|
|
203
|
+
|| context.currentSession.key !== record.sessionKey || context.currentSession.sessionPath !== record.sessionPath) {
|
|
204
|
+
throw new Error("current approval owner coordinates are not exact");
|
|
205
|
+
}
|
|
206
|
+
const runtime = await (options.dependencies?.getProviderRuntime ?? core_1.getProviderRuntime)("human", owner);
|
|
207
|
+
const mcpManager = await (options.dependencies?.getSharedMcpManager ?? mcp_manager_1.getSharedMcpManager)(owner) ?? undefined;
|
|
208
|
+
const selectCurrentTools = () => (0, tools_1.selectToolsForChannel)((0, friends_1.getChannelCapabilities)("telegram"), context.context?.friend.toolPreferences, context.context, runtime.capabilities, mcpManager, runtime.model, context);
|
|
209
|
+
return {
|
|
210
|
+
providerRuntimeOverride: runtime, mcpManager,
|
|
211
|
+
toolContext: { ...context, toolSelection: selectCurrentTools(), selectCurrentTools },
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
(0, runtime_1.emitNervesEvent)({
|
|
216
|
+
level: "warn", component: "senses", event: "senses.telegram_approval_authority_unavailable",
|
|
217
|
+
message: "current approval authority could not be reconstructed; execution remains disabled",
|
|
218
|
+
meta: { approvalId: record.approvalId, category: error instanceof Error ? error.name : "unknown" },
|
|
219
|
+
});
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
const invocationContext = (current, definition) => ({
|
|
224
|
+
...current.toolContext,
|
|
225
|
+
toolSelection: Object.freeze({ ordinary: Object.freeze([definition]), engine: Object.freeze([]) }),
|
|
226
|
+
});
|
|
182
227
|
const stateRoot = path.join(agentRoot, "state", "approvals");
|
|
183
228
|
const store = (0, approval_store_1.openApprovalStore)({ databasePath: path.join(stateRoot, "approvals.sqlite"), now: () => new Date(now()) });
|
|
184
229
|
const checkpoints = new approval_files_1.FileApprovalCheckpointStore(path.join(stateRoot, "checkpoints.json"));
|
|
@@ -297,6 +342,8 @@ function createTelegramApprovalRuntime(options) {
|
|
|
297
342
|
const continuationOwnerId = `telegram-continuation-${(0, node_crypto_1.randomUUID)()}`;
|
|
298
343
|
let continuationEpoch = 0;
|
|
299
344
|
let continuationCausalEventId;
|
|
345
|
+
let continuationAuthorized = false;
|
|
346
|
+
let controlNotice;
|
|
300
347
|
const continuationCoordinator = {
|
|
301
348
|
propose: (request) => coordinator({
|
|
302
349
|
sessionPath: record.sessionPath,
|
|
@@ -321,7 +368,11 @@ function createTelegramApprovalRuntime(options) {
|
|
|
321
368
|
markContinuationAttempted: () => { effectBarrier(); store.markContinuationAttempted({ approvalId: record.approvalId, ownerId: continuationOwnerId, epoch: continuationEpoch }); },
|
|
322
369
|
completeContinuation: () => { effectBarrier(); store.completeContinuation({ approvalId: record.approvalId, ownerId: continuationOwnerId, epoch: continuationEpoch }); },
|
|
323
370
|
runAgent: provider,
|
|
324
|
-
|
|
371
|
+
revalidate: async () => {
|
|
372
|
+
const current = await currentOptions(record);
|
|
373
|
+
continuationAuthorized = current !== null;
|
|
374
|
+
return current ? { ...current, ...approvalContinuationRunAgentOptions(current.toolContext, continuationCoordinator) } : null;
|
|
375
|
+
},
|
|
325
376
|
persist: (messages, result) => {
|
|
326
377
|
effectBarrier();
|
|
327
378
|
const existingEventIds = new Set((0, session_events_1.loadSessionEnvelopeFile)(record.sessionPath)?.events.map((event) => event.id) ?? []);
|
|
@@ -332,6 +383,15 @@ function createTelegramApprovalRuntime(options) {
|
|
|
332
383
|
},
|
|
333
384
|
deliver: async (text) => {
|
|
334
385
|
effectBarrier();
|
|
386
|
+
if (!continuationAuthorized) {
|
|
387
|
+
controlNotice = text;
|
|
388
|
+
(0, runtime_1.emitNervesEvent)({
|
|
389
|
+
component: "senses", event: "senses.telegram_approval_control_only",
|
|
390
|
+
message: "approval result will use its existing terminal control instead of an unauthorized Butler message",
|
|
391
|
+
meta: { approvalId: record.approvalId, state: record.state },
|
|
392
|
+
});
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
335
395
|
const messageIds = await options.effects.sendText({ idempotencyKey: `approval:${record.approvalId}:continuation:${(0, node_crypto_1.createHash)("sha256").update(text).digest("hex")}`, chatId: options.authorizedChatId, text, authorClass: "butler", ...(continuationCausalEventId ? { causalEventId: continuationCausalEventId } : {}) });
|
|
336
396
|
effectBarrier();
|
|
337
397
|
if (acceptanceBinding) {
|
|
@@ -352,7 +412,7 @@ function createTelegramApprovalRuntime(options) {
|
|
|
352
412
|
}
|
|
353
413
|
},
|
|
354
414
|
});
|
|
355
|
-
return terminalOutcome(record);
|
|
415
|
+
return { ...terminalOutcome(record), ...(controlNotice ? { terminalText: controlNotice } : {}) };
|
|
356
416
|
});
|
|
357
417
|
};
|
|
358
418
|
transport = (0, telegram_client_1.createTelegramApprovalTransport)({
|
|
@@ -397,6 +457,7 @@ function createTelegramApprovalRuntime(options) {
|
|
|
397
457
|
}
|
|
398
458
|
else if (existing.state === "proposed") {
|
|
399
459
|
const ownerId = `telegram-decision-${(0, node_crypto_1.randomUUID)()}`;
|
|
460
|
+
let definition;
|
|
400
461
|
record = await (0, session_transaction_1.withSessionTurnLease)(existing.sessionPath, async (lease) => (0, tool_approval_1.executeApprovalDecision)({
|
|
401
462
|
approvalStore: store,
|
|
402
463
|
checkpointStore: checkpoints,
|
|
@@ -410,16 +471,31 @@ function createTelegramApprovalRuntime(options) {
|
|
|
410
471
|
},
|
|
411
472
|
ownerId,
|
|
412
473
|
currentSessionRevision: (0, session_transaction_1.readSessionTransaction)(existing.sessionPath, lease).revision,
|
|
413
|
-
resolveTool
|
|
414
|
-
|
|
474
|
+
resolveTool: async (name) => {
|
|
475
|
+
const current = await currentOptions(existing);
|
|
476
|
+
definition = current ? resolveTool(name, current.toolContext.toolSelection) : undefined;
|
|
477
|
+
return definition;
|
|
478
|
+
},
|
|
479
|
+
resolveApprovalPolicy: async (name, args) => {
|
|
480
|
+
const current = await currentOptions(existing);
|
|
481
|
+
return current ? (0, tools_1.approvalPolicyForInvocation)(name, args, current.toolContext) : { kind: "not_required" };
|
|
482
|
+
},
|
|
415
483
|
liveGuard: async () => ({ ok: true }),
|
|
416
484
|
liveRisk: async () => ({ ok: true }),
|
|
485
|
+
preflight: async (context) => {
|
|
486
|
+
const current = await currentOptions(existing);
|
|
487
|
+
if (!current)
|
|
488
|
+
return { ok: false, reason: "current tool authority is unavailable" };
|
|
489
|
+
const result = await (0, tools_1.preflightToolCall)(context.record.toolName, context.arguments, invocationContext(current, context.definition));
|
|
490
|
+
return result.kind === "ready" ? { ok: true } : { ok: false, reason: result.text };
|
|
491
|
+
},
|
|
417
492
|
hooks: telegramApprovalDecisionBarrierHooks(effectBarrier),
|
|
418
|
-
execute: (name, args) => {
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
:
|
|
422
|
-
const
|
|
493
|
+
execute: async (name, args) => {
|
|
494
|
+
const current = await currentOptions(existing);
|
|
495
|
+
if (!current || !definition)
|
|
496
|
+
return { kind: "rejected_before_handler", text: "current approved tool authority is unavailable" };
|
|
497
|
+
const approvedToolContext = invocationContext(current, definition);
|
|
498
|
+
const execute = () => executeApprovedTelegramTool(name, args, (toolName, toolArgs) => (0, tools_1.executeTool)(toolName, toolArgs, approvedToolContext, options.dependencies?.executeTool), decisionScenarioDigest, existing.approvalId, effectBarrier);
|
|
423
499
|
return decisionScenarioDigest
|
|
424
500
|
? (0, sanctuary_acceptance_marker_1.runWithSanctuaryAcceptanceApproval)({ approvalId: existing.approvalId, argumentDigest: existing.argumentDigest }, execute)
|
|
425
501
|
: execute();
|
|
@@ -460,7 +536,7 @@ function createTelegramApprovalRuntime(options) {
|
|
|
460
536
|
if (!existing) {
|
|
461
537
|
if (mustFailClosed)
|
|
462
538
|
throw new Error("Telegram fenced approval journal is unavailable");
|
|
463
|
-
const orphanRecovery = await transport.terminalizeOrphaned(pending.approvalId, "⚠️ Approval record is unavailable —
|
|
539
|
+
const orphanRecovery = await transport.terminalizeOrphaned(pending.approvalId, "⚠️ Approval record is unavailable — the action outcome is unknown and will not be retried");
|
|
464
540
|
(0, runtime_1.emitNervesEvent)({
|
|
465
541
|
component: "senses",
|
|
466
542
|
event: "senses.telegram_approval_orphan_recovered",
|
|
@@ -562,5 +638,38 @@ function createTelegramApprovalRuntime(options) {
|
|
|
562
638
|
subject: options.subject,
|
|
563
639
|
});
|
|
564
640
|
};
|
|
565
|
-
|
|
641
|
+
const isPendingTerminalControl = async (input) => {
|
|
642
|
+
if (input.authorClass !== "control")
|
|
643
|
+
return false;
|
|
644
|
+
const effect = input.effect;
|
|
645
|
+
for (const pending of transport.listPendingDeliveries()) {
|
|
646
|
+
const record = store.read(pending.approvalId);
|
|
647
|
+
if (!record || !pending.messageId || record.transport !== "telegram"
|
|
648
|
+
|| record.requesterId !== options.subject || record.transportUserId !== options.subject
|
|
649
|
+
|| record.transportChatId !== options.subject || record.sessionKey !== `telegram:${options.subject}`
|
|
650
|
+
|| record.transportMessageId !== opaqueTelegramMessageBinding(options.subject, pending.messageId)
|
|
651
|
+
|| !["succeeded", "failed", "attempted_indeterminate", "denied", "expired", "drifted", "session_head_changed", "abandoned_before_attempt"].includes(record.state)
|
|
652
|
+
|| (pending.terminal && pending.terminal.accepted !== (record.state === "succeeded")))
|
|
653
|
+
continue;
|
|
654
|
+
let matches = false;
|
|
655
|
+
if (effect.kind === "callback_ack") {
|
|
656
|
+
const digest = (0, node_crypto_1.createHash)("sha256").update(effect.callbackQueryId).digest("hex");
|
|
657
|
+
matches = Boolean(pending.terminal && effect.text === undefined && effect.showAlert !== true
|
|
658
|
+
&& pending.decisionAttempt?.queryIdDigest === digest && input.idempotencyKey === `approval-callback:${digest}`);
|
|
659
|
+
}
|
|
660
|
+
else if (effect.kind === "edit") {
|
|
661
|
+
const terminalText = pending.terminal?.terminalText
|
|
662
|
+
?? (record.state === "expired" && pending.expiryObservation?.deadlineAt === pending.expiresAt
|
|
663
|
+
&& pending.expiryObservation.observedAt >= pending.expiresAt ? telegram_client_1.TELEGRAM_APPROVAL_EXPIRED_TEXT : undefined);
|
|
664
|
+
matches = terminalText !== undefined && effect.text === terminalText && effect.messageId === Number(pending.messageId)
|
|
665
|
+
&& input.idempotencyKey === `approval:${pending.approvalId}:edit:${(0, node_crypto_1.createHash)("sha256").update(terminalText).digest("hex")}`;
|
|
666
|
+
}
|
|
667
|
+
if (!matches)
|
|
668
|
+
continue;
|
|
669
|
+
await transport.validatePendingTerminalControl(pending.approvalId);
|
|
670
|
+
return true;
|
|
671
|
+
}
|
|
672
|
+
return false;
|
|
673
|
+
};
|
|
674
|
+
return { transport, coordinator, legacySubjects, migrateIdentity, recover, isPendingTerminalControl, close: () => store.close() };
|
|
566
675
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TELEGRAM_APPROVAL_TOMBSTONE_TTL_MS = exports.TELEGRAM_APPROVAL_TERMINAL_EDIT_TIMEOUT_MS = exports.TELEGRAM_APPROVAL_TTL_MS = exports.FileTelegramPendingApprovalStore = exports.FileTelegramUpdateInboxStore = exports.FileTelegramOffsetStore = exports.TelegramApiError = void 0;
|
|
3
|
+
exports.TELEGRAM_APPROVAL_TOMBSTONE_TTL_MS = exports.TELEGRAM_APPROVAL_TERMINAL_EDIT_TIMEOUT_MS = exports.TELEGRAM_APPROVAL_EXPIRED_TEXT = exports.TELEGRAM_APPROVAL_TTL_MS = exports.FileTelegramPendingApprovalStore = exports.FileTelegramUpdateInboxStore = exports.FileTelegramOffsetStore = exports.TelegramApiError = void 0;
|
|
4
4
|
exports.createTelegramLongPoll = createTelegramLongPoll;
|
|
5
5
|
exports.classifyTelegramPersistedApprovalState = classifyTelegramPersistedApprovalState;
|
|
6
6
|
exports.createTelegramApprovalTransport = createTelegramApprovalTransport;
|
|
@@ -788,6 +788,7 @@ class FileTelegramPendingApprovalStore {
|
|
|
788
788
|
}
|
|
789
789
|
exports.FileTelegramPendingApprovalStore = FileTelegramPendingApprovalStore;
|
|
790
790
|
exports.TELEGRAM_APPROVAL_TTL_MS = 300_000;
|
|
791
|
+
exports.TELEGRAM_APPROVAL_EXPIRED_TEXT = "⚠️ Approval expired";
|
|
791
792
|
exports.TELEGRAM_APPROVAL_TERMINAL_EDIT_TIMEOUT_MS = 30_000;
|
|
792
793
|
exports.TELEGRAM_APPROVAL_TOMBSTONE_TTL_MS = 600_000;
|
|
793
794
|
function assertTelegramCallbackData(value) {
|
|
@@ -1208,7 +1209,7 @@ function createTelegramApprovalTransport(options) {
|
|
|
1208
1209
|
}
|
|
1209
1210
|
const observation = ensureExpiryObservation(current);
|
|
1210
1211
|
await options.onExpire?.(current.approvalId);
|
|
1211
|
-
const terminalizedAt = await editTerminal(current,
|
|
1212
|
+
const terminalizedAt = await editTerminal(current, exports.TELEGRAM_APPROVAL_EXPIRED_TEXT, observation.observedAt);
|
|
1212
1213
|
if (current.acceptanceBinding)
|
|
1213
1214
|
persistMutation(current, () => retainTerminalTombstone(current, terminalizedAt));
|
|
1214
1215
|
else {
|
|
@@ -1225,6 +1226,22 @@ function createTelegramApprovalTransport(options) {
|
|
|
1225
1226
|
throw firstFailure;
|
|
1226
1227
|
};
|
|
1227
1228
|
return {
|
|
1229
|
+
async validatePendingTerminalControl(approvalId) {
|
|
1230
|
+
const pending = uniquePending().find((entry) => entry.approvalId === approvalId);
|
|
1231
|
+
if (!pending || !options.signAcceptanceEvidence)
|
|
1232
|
+
throw new Error("Telegram terminal control integrity is unavailable");
|
|
1233
|
+
const state = classifyTelegramPersistedApprovalState(pending);
|
|
1234
|
+
if (state === "action_terminal") {
|
|
1235
|
+
await validateDecisionAttempt(pending);
|
|
1236
|
+
validateTerminalOutcome(pending);
|
|
1237
|
+
}
|
|
1238
|
+
else if (state === "expiry_observed") {
|
|
1239
|
+
validateExpiryObservation(pending);
|
|
1240
|
+
}
|
|
1241
|
+
else {
|
|
1242
|
+
throw new Error("Telegram pending terminal control is not authenticated");
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
1228
1245
|
async sendApproval(input) {
|
|
1229
1246
|
effectBarrier();
|
|
1230
1247
|
const approveCallbackData = `a:${options.createOpaqueHandle()}`;
|
package/dist/senses/telegram.js
CHANGED
|
@@ -846,6 +846,7 @@ function createTelegramSenseApp(options) {
|
|
|
846
846
|
throw primaryError;
|
|
847
847
|
};
|
|
848
848
|
let effectJournal;
|
|
849
|
+
let approvalRuntime;
|
|
849
850
|
const getEffectJournal = () => {
|
|
850
851
|
effectJournal ??= new telegram_effect_adapter_1.FileTelegramEffectJournal(path.join(agentRoot, "state", "telegram", "effects"));
|
|
851
852
|
return effectJournal;
|
|
@@ -867,6 +868,13 @@ function createTelegramSenseApp(options) {
|
|
|
867
868
|
if (input.authorClass === "system_failsafe" && (input.effect.kind !== "text" || input.effect.text !== telegram_effect_adapter_1.FIXED_USENET_SYSTEM_FAILSAFE || !input.idempotencyKey.startsWith("system-failsafe:"))) {
|
|
868
869
|
return { allowed: false, reason: "system failsafe shape is not fixed" };
|
|
869
870
|
}
|
|
871
|
+
if (target.friendId === configuredOwnerFriendId && target.sessionKey === configuredOwnerSessionKey
|
|
872
|
+
&& await approvalRuntime?.isPendingTerminalControl?.(input)) {
|
|
873
|
+
return {
|
|
874
|
+
allowed: true, receiptId: `approval-terminal:${(0, node_crypto_1.createHash)("sha256").update(input.idempotencyKey).digest("hex")}`,
|
|
875
|
+
expiresAt: new Date(Date.now() + 5 * 60_000).toISOString(), transport: { chatId: authorizedChatId },
|
|
876
|
+
};
|
|
877
|
+
}
|
|
870
878
|
if (options.authorizeRelationshipEffect) {
|
|
871
879
|
if (target.friendId === configuredOwnerFriendId && target.sessionKey !== configuredOwnerSessionKey)
|
|
872
880
|
return { allowed: false, reason: "owner relationship session binding changed" };
|
|
@@ -891,7 +899,6 @@ function createTelegramSenseApp(options) {
|
|
|
891
899
|
};
|
|
892
900
|
const approvalEffects = (0, telegram_effect_adapter_1.createTelegramApprovalEffectPort)({ target: configuredOwnerTarget(), chatId: authorizedChatId, execute: executeAuthorizedEffect, record: recordConfiguredOwnerEffect });
|
|
893
901
|
let toolContext;
|
|
894
|
-
let approvalRuntime;
|
|
895
902
|
let approvalTransport;
|
|
896
903
|
let interactiveControl;
|
|
897
904
|
try {
|
|
@@ -906,9 +913,38 @@ function createTelegramSenseApp(options) {
|
|
|
906
913
|
subject,
|
|
907
914
|
identityKey,
|
|
908
915
|
toolContext: toolContext ?? {},
|
|
916
|
+
resolveLiveToolContext: async (record) => {
|
|
917
|
+
const sessionPath = (0, shared_turn_1.getSenseSessionPath)(options.agentName, configuredOwnerFriendId, "telegram", configuredOwnerSessionKey, agentRoot);
|
|
918
|
+
if (record.transport !== "telegram" || record.requesterId !== subject
|
|
919
|
+
|| record.transportUserId !== subject || record.transportChatId !== subject
|
|
920
|
+
|| record.sessionKey !== configuredOwnerSessionKey || path.resolve(record.sessionPath) !== path.resolve(sessionPath)) {
|
|
921
|
+
throw new Error("approval is not bound to the configured owner session");
|
|
922
|
+
}
|
|
923
|
+
const envelope = (0, session_events_1.loadSessionEnvelopeFile)(sessionPath);
|
|
924
|
+
const ingress = envelope && (0, session_events_1.selectEffectiveSessionEvents)(envelope.events).findLast((event) => event.role === "user");
|
|
925
|
+
if (!ingress)
|
|
926
|
+
throw new Error("approval owner ingress is unavailable");
|
|
927
|
+
const relationshipAuthorization = await resolveLiveRelationshipAuthorization({
|
|
928
|
+
friendId: configuredOwnerFriendId, requestId: `approval:${record.approvalId}`, sessionEventId: ingress.id,
|
|
929
|
+
botId: botId, userId: authorizedUserId, chatId: authorizedChatId, sessionKey: configuredOwnerSessionKey,
|
|
930
|
+
});
|
|
931
|
+
if (relationshipAuthorization.profileId !== "sanctuary-owner")
|
|
932
|
+
throw new Error("approval owner profile is unavailable");
|
|
933
|
+
const friendStore = new friends_1.FileFriendStore(path.join(agentRoot, "friends"));
|
|
934
|
+
const friend = await friendStore.get(configuredOwnerFriendId);
|
|
935
|
+
if (!friend)
|
|
936
|
+
throw new Error("approval owner Friend is unavailable");
|
|
937
|
+
return {
|
|
938
|
+
...toolContext, signin: async () => undefined, agentName: options.agentName, agentRoot,
|
|
939
|
+
currentSession: { friendId: friend.id, channel: "telegram", key: configuredOwnerSessionKey, sessionPath },
|
|
940
|
+
currentUserMessage: (0, session_events_1.extractEventText)(ingress),
|
|
941
|
+
context: { friend, channel: (0, friends_1.getChannelCapabilities)("telegram") }, friendStore, relationshipAuthorization,
|
|
942
|
+
};
|
|
943
|
+
},
|
|
909
944
|
effects: approvalEffects,
|
|
910
945
|
effectBarrier: acceptanceAuditBarrier,
|
|
911
946
|
dependencies: {
|
|
947
|
+
agentRoot,
|
|
912
948
|
acceptanceMarker: () => {
|
|
913
949
|
const scenarioHandleDigest = readScenarioHandleDigest();
|
|
914
950
|
return scenarioHandleDigest ? { scenarioHandleDigest } : null;
|
|
@@ -1075,25 +1111,28 @@ function createTelegramSenseApp(options) {
|
|
|
1075
1111
|
(0, runtime_1.emitNervesEvent)({ level: "error", component: "senses", event: "senses.telegram_system_failsafe_error", message: "Telegram system failsafe reconciliation failed", meta: { agentName: options.agentName, subject, error: transportError(error) } });
|
|
1076
1112
|
}
|
|
1077
1113
|
};
|
|
1114
|
+
async function resolveLiveRelationshipAuthorization(input) {
|
|
1115
|
+
if (!options.resolveRelationshipAuthorization)
|
|
1116
|
+
throw new Error("Telegram relationship authorization resolver is unavailable");
|
|
1117
|
+
const authorization = await options.resolveRelationshipAuthorization(input);
|
|
1118
|
+
if (authorization.subject.friendId !== input.friendId || authorization.subject.admissionState !== "active")
|
|
1119
|
+
throw new Error("Telegram relationship admission is not active");
|
|
1120
|
+
return {
|
|
1121
|
+
requestId: input.requestId,
|
|
1122
|
+
profileId: authorization.profileId,
|
|
1123
|
+
authorizedContextScopes: authorization.authorizedContextScopes,
|
|
1124
|
+
advertisedToolNames: authorization.advertisedToolNames,
|
|
1125
|
+
actor: authorization.actor,
|
|
1126
|
+
resolveCurrent: () => resolveLiveRelationshipAuthorization(input),
|
|
1127
|
+
authorizeTool: async (name, args) => (await options.resolveRelationshipAuthorization(input)).authorizeTool(name, args),
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1078
1130
|
const prepareRelationshipRunAgentOptions = (input) => {
|
|
1079
1131
|
if (!options.resolveRelationshipAuthorization)
|
|
1080
1132
|
throw new Error("Telegram relationship authorization resolver is unavailable");
|
|
1081
1133
|
const relationshipCoordinates = { ...input, botId: botId };
|
|
1082
|
-
const resolveLiveRelationshipAuthorization = async () => {
|
|
1083
|
-
const authorization = await options.resolveRelationshipAuthorization(relationshipCoordinates);
|
|
1084
|
-
if (authorization.subject.friendId !== input.friendId || authorization.subject.admissionState !== "active")
|
|
1085
|
-
throw new Error("Telegram relationship admission is not active");
|
|
1086
|
-
return {
|
|
1087
|
-
requestId: input.requestId,
|
|
1088
|
-
profileId: authorization.profileId,
|
|
1089
|
-
authorizedContextScopes: authorization.authorizedContextScopes,
|
|
1090
|
-
advertisedToolNames: authorization.advertisedToolNames,
|
|
1091
|
-
actor: authorization.actor,
|
|
1092
|
-
authorizeTool: async (name, args) => (await options.resolveRelationshipAuthorization(relationshipCoordinates)).authorizeTool(name, args),
|
|
1093
|
-
};
|
|
1094
|
-
};
|
|
1095
1134
|
return async ({ runAgentOptions, activeCares = [], careEvidenceNow = Date.now() }) => {
|
|
1096
|
-
const relationshipAuthorization = await resolveLiveRelationshipAuthorization();
|
|
1135
|
+
const relationshipAuthorization = await resolveLiveRelationshipAuthorization(relationshipCoordinates);
|
|
1097
1136
|
const isSanctuaryOwner = options.agentName === "sanctuary" && relationshipAuthorization.profileId === "sanctuary-owner";
|
|
1098
1137
|
const isSanctuaryHouseholdConversation = options.agentName === "sanctuary"
|
|
1099
1138
|
&& (relationshipAuthorization.profileId === "sanctuary-owner" || relationshipAuthorization.profileId === "sanctuary-household");
|