@ouro.bot/cli 0.1.0-alpha.764 → 0.1.0-alpha.766
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 +15 -0
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +1 -1
- package/deploy/unraid/sanctuary.xml +1 -1
- package/dist/heart/core.js +56 -8
- package/dist/mind/prompt.js +3 -0
- package/dist/repertoire/tools-continuity.js +19 -1
- package/dist/senses/sanctuary-full-visibility-contract.js +52 -2
- package/dist/senses/telegram-effect-adapter.js +9 -2
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.766",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Keep Sanctuary status summaries grounded in successful current reads and stale-care-safe evidence.",
|
|
8
|
+
"Render Butler Telegram replies without literal bold markers while preserving commands and data.",
|
|
9
|
+
"Keep the packaged visibility contract clear of retired module markers."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.1.0-alpha.765",
|
|
14
|
+
"changes": [
|
|
15
|
+
"Require configured turn-local reads before accepting either tool-based or plain-text terminal responses, and fail closed at the bounded provider-turn cap when those reads never run.",
|
|
16
|
+
"Give Telegram concise phone-native plain-text response guidance instead of Teams Markdown guidance."
|
|
17
|
+
]
|
|
18
|
+
},
|
|
4
19
|
{
|
|
5
20
|
"version": "0.1.0-alpha.764",
|
|
6
21
|
"changes": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0"?>
|
|
2
2
|
<Container version="2">
|
|
3
3
|
<Name>Mendelow Cloud Butler</Name>
|
|
4
|
-
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.
|
|
4
|
+
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.766</Repository>
|
|
5
5
|
<Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
|
|
6
6
|
<Network>host</Network>
|
|
7
7
|
<Shell>sh</Shell>
|
package/dist/heart/core.js
CHANGED
|
@@ -569,6 +569,11 @@ function toolResultIndicatesFailure(content) {
|
|
|
569
569
|
|| normalized.startsWith("blocked:")
|
|
570
570
|
|| normalized.startsWith("rejected:");
|
|
571
571
|
}
|
|
572
|
+
function requiredToolResultSucceeded(name, content, validate) {
|
|
573
|
+
if (toolResultIndicatesFailure(content))
|
|
574
|
+
return false;
|
|
575
|
+
return validate?.(name, content) ?? true;
|
|
576
|
+
}
|
|
572
577
|
function effectFingerprint(name, rawArguments) {
|
|
573
578
|
let args;
|
|
574
579
|
try {
|
|
@@ -1122,6 +1127,18 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1122
1127
|
let providerIterations = 0;
|
|
1123
1128
|
const requiredToolCallNames = [...new Set(options?.requiredToolCalls?.names ?? [])];
|
|
1124
1129
|
const dispatchedRequiredToolCalls = new Set();
|
|
1130
|
+
const pendingRequiredToolCalls = () => {
|
|
1131
|
+
const missing = requiredToolCallNames.filter((name) => !dispatchedRequiredToolCalls.has(name));
|
|
1132
|
+
return missing.length > 0
|
|
1133
|
+
? { missing, message: `${options.requiredToolCalls.retryMessage} Missing required tool calls: ${missing.join(", ")}.` }
|
|
1134
|
+
: null;
|
|
1135
|
+
};
|
|
1136
|
+
const queueRequiredCorrection = (message, limitContext) => {
|
|
1137
|
+
if (providerIterations >= exports.MAX_PROVIDER_ITERATIONS)
|
|
1138
|
+
throw new Error(`provider iteration limit exhausted at response ${exports.MAX_PROVIDER_ITERATIONS} ${limitContext}`);
|
|
1139
|
+
messages.push({ role: "user", content: message });
|
|
1140
|
+
providerRuntime.resetTurnState(messages);
|
|
1141
|
+
};
|
|
1125
1142
|
const toolLoopState = (0, tool_loop_1.createToolLoopState)();
|
|
1126
1143
|
const toolFrictionLedger = (0, tool_friction_1.createToolFrictionLedger)();
|
|
1127
1144
|
const finishTerminalProviderError = (error, classification) => {
|
|
@@ -1520,6 +1537,28 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1520
1537
|
});
|
|
1521
1538
|
continue;
|
|
1522
1539
|
}
|
|
1540
|
+
const requiredToolCallsGate = pendingRequiredToolCalls();
|
|
1541
|
+
if (requiredToolCallsGate) {
|
|
1542
|
+
streamCallbackBuffer?.discard();
|
|
1543
|
+
callbacks.onClearText?.();
|
|
1544
|
+
queueRequiredCorrection(requiredToolCallsGate.message, "before required tool calls completed");
|
|
1545
|
+
(0, runtime_1.emitNervesEvent)({
|
|
1546
|
+
level: "warn",
|
|
1547
|
+
component: "engine",
|
|
1548
|
+
event: "engine.required_tool_calls_pending",
|
|
1549
|
+
message: "terminal response rejected until required tool handlers dispatch",
|
|
1550
|
+
meta: { missingToolNames: requiredToolCallsGate.missing },
|
|
1551
|
+
});
|
|
1552
|
+
continue;
|
|
1553
|
+
}
|
|
1554
|
+
const requiredAnswerRejection = options?.requiredToolCalls?.validateTerminalAnswer?.(String(msg.content ?? ""));
|
|
1555
|
+
if (requiredAnswerRejection) {
|
|
1556
|
+
streamCallbackBuffer?.discard();
|
|
1557
|
+
callbacks.onClearText?.();
|
|
1558
|
+
queueRequiredCorrection(requiredAnswerRejection, "before required terminal answer validation completed");
|
|
1559
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.required_tool_answer_rejected", message: "unsupported terminal answer rejected after required reads", meta: { answerLength: String(msg.content ?? "").length } });
|
|
1560
|
+
continue;
|
|
1561
|
+
}
|
|
1523
1562
|
if (privateReturnTextAckRetryError) {
|
|
1524
1563
|
streamCallbackBuffer?.discard();
|
|
1525
1564
|
callbacks.onClearText?.();
|
|
@@ -1722,21 +1761,18 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1722
1761
|
if (isSoleSettle) {
|
|
1723
1762
|
const settleArgs = validatedCallArguments.get(result.toolCalls[0]);
|
|
1724
1763
|
callbacks.onToolStart("settle", settleArgs);
|
|
1725
|
-
const
|
|
1726
|
-
if (
|
|
1764
|
+
const requiredToolCallsGate = pendingRequiredToolCalls();
|
|
1765
|
+
if (requiredToolCallsGate) {
|
|
1727
1766
|
streamCallbackBuffer?.discard();
|
|
1728
1767
|
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), false);
|
|
1729
1768
|
callbacks.onClearText?.();
|
|
1730
|
-
|
|
1731
|
-
const gateMessage = `${options.requiredToolCalls.retryMessage} Missing required tool calls: ${missingRequiredToolCalls.join(", ")}.`;
|
|
1732
|
-
pushGenerated({ role: "tool", tool_call_id: result.toolCalls[0].id, content: gateMessage });
|
|
1733
|
-
providerRuntime.appendToolOutput(result.toolCalls[0].id, gateMessage);
|
|
1769
|
+
queueRequiredCorrection(requiredToolCallsGate.message, "before required tool calls completed");
|
|
1734
1770
|
(0, runtime_1.emitNervesEvent)({
|
|
1735
1771
|
level: "warn",
|
|
1736
1772
|
component: "engine",
|
|
1737
1773
|
event: "engine.required_tool_calls_pending",
|
|
1738
1774
|
message: "settle rejected until required tool handlers dispatch",
|
|
1739
|
-
meta: { missingToolNames:
|
|
1775
|
+
meta: { missingToolNames: requiredToolCallsGate.missing },
|
|
1740
1776
|
});
|
|
1741
1777
|
continue;
|
|
1742
1778
|
}
|
|
@@ -1755,6 +1791,15 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1755
1791
|
// Extract answer from the tool call arguments.
|
|
1756
1792
|
// Supports: {"answer":"text","intent":"..."} or "text" (JSON string).
|
|
1757
1793
|
const { answer, intent } = parseSettlePayload(result.toolCalls[0].arguments);
|
|
1794
|
+
const requiredAnswerRejection = options?.requiredToolCalls?.validateTerminalAnswer?.(answer);
|
|
1795
|
+
if (requiredAnswerRejection) {
|
|
1796
|
+
streamCallbackBuffer?.discard();
|
|
1797
|
+
callbacks.onToolEnd("settle", (0, tools_1.summarizeArgs)("settle", settleArgs), false);
|
|
1798
|
+
callbacks.onClearText?.();
|
|
1799
|
+
queueRequiredCorrection(requiredAnswerRejection, "before required terminal answer validation completed");
|
|
1800
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.required_tool_answer_rejected", message: "unsupported settle answer rejected after required reads", meta: { answerLength: answer.length } });
|
|
1801
|
+
continue;
|
|
1802
|
+
}
|
|
1758
1803
|
// Private-runtime settle: no CompletionMetadata, "(settled)" ack
|
|
1759
1804
|
if (isPrivateRuntimeChannel) {
|
|
1760
1805
|
streamCallbackBuffer?.discard();
|
|
@@ -2266,7 +2311,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2266
2311
|
const execToolFn = options?.execTool ?? tools_1.execTool;
|
|
2267
2312
|
const routineActionSelection = approvalCalls.find((entry) => entry.call.id === tc.id)?.routineActionSelection;
|
|
2268
2313
|
const executionToolContext = routineActionSelection && augmentedToolContext ? { ...augmentedToolContext, routineActionSelection } : augmentedToolContext;
|
|
2269
|
-
if (requiredToolCallNames.includes(tc.name))
|
|
2314
|
+
if (requiredToolCallNames.includes(tc.name) && !options?.requiredToolCalls?.requireSuccessfulResults)
|
|
2270
2315
|
dispatchedRequiredToolCalls.add(tc.name);
|
|
2271
2316
|
toolResult = await execToolFn(tc.name, args, executionToolContext);
|
|
2272
2317
|
success = true;
|
|
@@ -2276,6 +2321,9 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
2276
2321
|
success = false;
|
|
2277
2322
|
augmentedToolContext?.habitSession?.recordError?.(toolResult);
|
|
2278
2323
|
}
|
|
2324
|
+
if (success && requiredToolCallNames.includes(tc.name) && options?.requiredToolCalls?.requireSuccessfulResults
|
|
2325
|
+
&& requiredToolResultSucceeded(tc.name, toolResult, options.requiredToolCalls.validateRequiredToolResult))
|
|
2326
|
+
dispatchedRequiredToolCalls.add(tc.name);
|
|
2279
2327
|
if (success && currentEffectFingerprint && !toolResultIndicatesFailure(toolResult)) {
|
|
2280
2328
|
unresolvedHistoricalEffects = unresolvedHistoricalEffects.filter((effect) => effect.fingerprint !== currentEffectFingerprint);
|
|
2281
2329
|
}
|
package/dist/mind/prompt.js
CHANGED
|
@@ -410,6 +410,9 @@ function runtimeInfoSection(channel, options) {
|
|
|
410
410
|
else if (channel === "mcp") {
|
|
411
411
|
lines.push("this message arrived via a dev tool (e.g. claude code, codex) on behalf of a friend in a sense session. the user can see our conversation. if the dev-tool user asks a direct question, requests stop/pause/confirmation, or the work is complete, i answer with settle. during an active browser/tool/task flow, process comments are feedback to absorb; i keep using tools instead of settling for status. if friction appears, i first look for ad-hoc repairs with the tools i already have. if the friction reveals a harness gap, i create or revise a ponder packet and keep working. ponder does not create an outward deferral by itself.");
|
|
412
412
|
}
|
|
413
|
+
else if (channel === "telegram") {
|
|
414
|
+
lines.push("i am responding in Telegram. i keep replies concise and phone-native. i do not use markdown. i do not introduce myself on boot.");
|
|
415
|
+
}
|
|
413
416
|
else if (channel === "bluebubbles") {
|
|
414
417
|
lines.push("i am responding in iMessage through BlueBubbles. i keep replies short and phone-native. i do not use markdown. i do not introduce myself on boot.");
|
|
415
418
|
lines.push("during an active browser/tool/task flow, process comments from my friend are feedback to absorb, not a reason to settle. i speak once if useful, then keep working until complete, blocked, asked to stop/pause, or confirmation is required. timeout/recovery state is internal, not iMessage copy.");
|
|
@@ -45,6 +45,24 @@ const presence_1 = require("../arc/presence");
|
|
|
45
45
|
const intentions_1 = require("../arc/intentions");
|
|
46
46
|
const steward_policy_1 = require("../heart/steward-policy");
|
|
47
47
|
const await_parser_1 = require("../heart/awaiting/await-parser");
|
|
48
|
+
function presentCare(care) {
|
|
49
|
+
const staleAt = care.nextCheckAt ? Date.parse(care.nextCheckAt) : Number.NaN;
|
|
50
|
+
if (care.kind !== "system" || !["active", "watching"].includes(care.status) || care.nextCheckAt === null)
|
|
51
|
+
return care;
|
|
52
|
+
if (Number.isFinite(staleAt) && staleAt >= Date.now())
|
|
53
|
+
return care;
|
|
54
|
+
return {
|
|
55
|
+
id: care.id,
|
|
56
|
+
kind: care.kind,
|
|
57
|
+
status: care.status,
|
|
58
|
+
salience: care.salience,
|
|
59
|
+
steward: care.steward,
|
|
60
|
+
evidenceStatus: "stale",
|
|
61
|
+
recheckRequired: true,
|
|
62
|
+
staleAt: care.nextCheckAt,
|
|
63
|
+
lastAssessedAt: care.updatedAt,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
48
66
|
exports.continuityToolDefinitions = [
|
|
49
67
|
// ── Continuity tools ──────────────────────────────────────────────
|
|
50
68
|
{
|
|
@@ -308,7 +326,7 @@ exports.continuityToolDefinitions = [
|
|
|
308
326
|
},
|
|
309
327
|
handler: (a) => {
|
|
310
328
|
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
311
|
-
const cares = a.status === "all" ? (0, cares_1.readCares)(agentRoot) : (0, cares_1.readActiveCares)(agentRoot);
|
|
329
|
+
const cares = (a.status === "all" ? (0, cares_1.readCares)(agentRoot) : (0, cares_1.readActiveCares)(agentRoot)).map(presentCare);
|
|
312
330
|
(0, runtime_1.emitNervesEvent)({ component: "repertoire", event: "repertoire.query_cares", message: `queried ${cares.length} cares`, meta: { count: cares.length } });
|
|
313
331
|
return JSON.stringify(cares, null, 2);
|
|
314
332
|
},
|
|
@@ -2,8 +2,55 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sanctuaryFullVisibilityRequiredToolCalls = sanctuaryFullVisibilityRequiredToolCalls;
|
|
4
4
|
const runtime_1 = require("../nerves/runtime");
|
|
5
|
-
const REQUIRED_TOOL_NAMES = ["query_active_work", "query_cares", "unraid_get_system", "unraid_list_containers"];
|
|
5
|
+
const REQUIRED_TOOL_NAMES = ["query_active_work", "query_cares", "unraid_get_system", "unraid_list_containers", "unraid_get_storage", "sanctuary_get_download_queue"];
|
|
6
6
|
const WHOLE_STATUS_REQUESTS = new Set(["what are you working on", "what's going on with sanctuary"]);
|
|
7
|
+
function unsupportedCurrentClaim(answer) {
|
|
8
|
+
const unsupported = answer.replace(/docker\.img/giu, "docker image").split(/[,;!?\n]|(?<!\d)\.(?!\d)/u).some((sentence) => {
|
|
9
|
+
if (!/docker image(?: disk)?/iu.test(sentence))
|
|
10
|
+
return false;
|
|
11
|
+
const uncertaintyOnly = /\b(?:cannot|can't|unable to) (?:currently )?(?:verify|measure)\b|\b(?:unknown|unverified)\b|\bneeds? (?:a )?(?:fresh |authoritative )*(?:check|measurement)\b/iu.test(sentence);
|
|
12
|
+
const stateClaim = /\b\d+(?:\.\d+)?\s*%|\bfull\b|\b(?:no|out of) space\b|\bwrites? (?:will |may )?fail\b|\b(?:healthy|unhealthy|running|stopped)\b/iu.test(sentence);
|
|
13
|
+
return stateClaim || !uncertaintyOnly;
|
|
14
|
+
});
|
|
15
|
+
if (unsupported)
|
|
16
|
+
return "No current Butler tool measures Docker image utilization. Do not report a Docker image percentage or full state as current; say that the stale care needs a fresh authoritative check.";
|
|
17
|
+
const unsupportedProviderClaim = answer.split(/[,;!?\n]|(?<!\d)\.(?!\d)/u).some((clause) => {
|
|
18
|
+
const explicitlyUnverified = /\b(?:cannot|can't|unable to) (?:currently )?(?:verify|confirm)|\b(?:unknown|unverified|stale|historical|previous|prior)\b|\bneeds? (?:a )?(?:fresh |authoritative )*(?:check|verification)\b/iu.test(clause);
|
|
19
|
+
if (explicitlyUnverified)
|
|
20
|
+
return false;
|
|
21
|
+
if (/\b(?:Astraweb|Usenet provider|download provider|(?:block|prepaid|download|provider) credit)\b/iu.test(clause))
|
|
22
|
+
return true;
|
|
23
|
+
return /\bSABnzbd\b/iu.test(clause) && /\b(?:auth(?:entication)?|authenticated|credentials?)\b/iu.test(clause);
|
|
24
|
+
});
|
|
25
|
+
return unsupportedProviderClaim ? "The current queue read does not prove provider credit or authentication status. Do not report Astraweb, block-credit, or authentication failure as current; say that the provider needs a fresh authoritative check." : undefined;
|
|
26
|
+
}
|
|
27
|
+
function successfulCurrentResult(name, result) {
|
|
28
|
+
if (Buffer.byteLength(result, "utf8") > 1_000_000)
|
|
29
|
+
return false;
|
|
30
|
+
if (name === "query_active_work")
|
|
31
|
+
return result.trimStart().startsWith("this is my current top-level live world-state.");
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(result);
|
|
34
|
+
if (name === "query_cares")
|
|
35
|
+
return Array.isArray(parsed);
|
|
36
|
+
if (name === "sanctuary_get_download_queue") {
|
|
37
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
38
|
+
return false;
|
|
39
|
+
const queue = parsed;
|
|
40
|
+
const exactKeys = ["observedAt", "paused", "queuedJobs", "stateDigest", "status"];
|
|
41
|
+
return JSON.stringify(Object.keys(queue).sort()) === JSON.stringify(exactKeys)
|
|
42
|
+
&& typeof queue.paused === "boolean"
|
|
43
|
+
&& typeof queue.status === "string" && Buffer.byteLength(queue.status, "utf8") <= 64
|
|
44
|
+
&& Number.isSafeInteger(queue.queuedJobs) && Number(queue.queuedJobs) >= 0 && Number(queue.queuedJobs) <= 1_000_000
|
|
45
|
+
&& typeof queue.observedAt === "string" && Number.isFinite(Date.parse(queue.observedAt)) && new Date(queue.observedAt).toISOString() === queue.observedAt
|
|
46
|
+
&& typeof queue.stateDigest === "string" && /^[a-f0-9]{64}$/u.test(queue.stateDigest);
|
|
47
|
+
}
|
|
48
|
+
return !!parsed && typeof parsed === "object" && !Array.isArray(parsed) && parsed.ok === true;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
7
54
|
function sanctuaryFullVisibilityRequiredToolCalls(request, advertisedToolNames) {
|
|
8
55
|
const normalized = request.normalize("NFKC").trim().toLocaleLowerCase("en-US").replaceAll("’", "'").replace(/[?!.\s]+$/gu, "");
|
|
9
56
|
if (!WHOLE_STATUS_REQUESTS.has(normalized) || !REQUIRED_TOOL_NAMES.every((name) => advertisedToolNames.includes(name)))
|
|
@@ -11,6 +58,9 @@ function sanctuaryFullVisibilityRequiredToolCalls(request, advertisedToolNames)
|
|
|
11
58
|
(0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_full_visibility_reads_required", message: "required current Sanctuary visibility reads", meta: { toolCount: REQUIRED_TOOL_NAMES.length } });
|
|
12
59
|
return {
|
|
13
60
|
names: REQUIRED_TOOL_NAMES,
|
|
14
|
-
retryMessage: "Before answering, read current active work, cares, system health, and
|
|
61
|
+
retryMessage: "Before answering, read current active work, cares, system health, service state, storage, and the download queue. Current tool facts outrank care history; a stale care is a recheck item, not a present-tense fact. Then give Ari one compact household summary; do not ask him to choose a status slice.",
|
|
62
|
+
requireSuccessfulResults: true,
|
|
63
|
+
validateRequiredToolResult: successfulCurrentResult,
|
|
64
|
+
validateTerminalAnswer: unsupportedCurrentClaim,
|
|
15
65
|
};
|
|
16
66
|
}
|
|
@@ -76,6 +76,12 @@ function preparedTexts(effect) {
|
|
|
76
76
|
return [requireText(effect.text, "Telegram text")];
|
|
77
77
|
return [effect.text?.trim() || null];
|
|
78
78
|
}
|
|
79
|
+
function telegramPlainText(text) {
|
|
80
|
+
return text.replace(/(^|[\s([{])\*\*([\p{L}\p{N}][^*\n]*?)\*\*(?=$|[\s.,;!?)\]}])/gmu, "$1$2");
|
|
81
|
+
}
|
|
82
|
+
function presentTelegramEffect(authorClass, effect) {
|
|
83
|
+
return authorClass === "butler" && effect.kind === "text" ? { ...effect, text: telegramPlainText(effect.text) } : effect;
|
|
84
|
+
}
|
|
79
85
|
function assertEffectTarget(target, effect, idempotencyKey) {
|
|
80
86
|
if (target.kind === "admission_gate") {
|
|
81
87
|
if (effect.kind !== "admission_ack" || effect.text !== exports.FIXED_ADMISSION_ACKNOWLEDGEMENT || idempotencyKey !== `ack:${target.admissionId}`) {
|
|
@@ -425,11 +431,12 @@ function createTelegramAuthorizedEffectExecutor(options) {
|
|
|
425
431
|
if (input.signal?.aborted)
|
|
426
432
|
throw input.signal.reason;
|
|
427
433
|
barrier();
|
|
428
|
-
const
|
|
434
|
+
const presentedInput = { ...input, effect: presentTelegramEffect(input.authorClass, input.effect) };
|
|
435
|
+
const authorization = await options.authorize({ phase: "prepare", ...presentedInput });
|
|
429
436
|
if (!authorization.allowed)
|
|
430
437
|
throw new Error(`Telegram effect authorization denied: ${authorization.reason}`);
|
|
431
438
|
const store = getStore();
|
|
432
|
-
const prepared = prepareTelegramEffect(store, { ...
|
|
439
|
+
const prepared = prepareTelegramEffect(store, { ...presentedInput, authorization });
|
|
433
440
|
try {
|
|
434
441
|
const executed = await executeTelegramEffect(store, prepared.id, options.api, async (artifact) => {
|
|
435
442
|
if (input.signal?.aborted)
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouro.bot/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.766",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@ouro.bot/cli",
|
|
9
|
-
"version": "0.1.0-alpha.
|
|
9
|
+
"version": "0.1.0-alpha.766",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|