@ouro.bot/cli 0.1.0-alpha.844 → 0.1.0-alpha.846
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.ouro/bundle-meta.json +1 -1
- package/deploy/unraid/sanctuary.xml +1 -1
- package/dist/senses/sanctuary-install-state-contract.js +43 -0
- package/dist/senses/shared-turn.js +18 -1
- package/dist/senses/telegram.js +4 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
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.846",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Sanctuary: a natural question about the Butler's version ('what version are you on?') now requires a fresh install-state read, and any version it states must match that read. After an upgrade it had answered 'Just checked the live state: 0.1.0-alpha.841' from earlier conversation while running 845, with no tool call."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.1.0-alpha.845",
|
|
12
|
+
"changes": [
|
|
13
|
+
"Senses: a turn that errors now tells the person so instead of going silent (naming the step limit when that is the cause). This was the mechanism behind the Butler's answer-then-greet sequence (D-004): a question hit the provider step limit (D-007), nothing was sent, and each prod became its own turn. The engine still refuses to answer without evidence; the private channel stays silent."
|
|
14
|
+
]
|
|
15
|
+
},
|
|
4
16
|
{
|
|
5
17
|
"version": "0.1.0-alpha.844",
|
|
6
18
|
"changes": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0"?>
|
|
2
2
|
<Container version="2">
|
|
3
3
|
<Name>ouro-butler</Name>
|
|
4
|
-
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.
|
|
4
|
+
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.846</Repository>
|
|
5
5
|
<Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
|
|
6
6
|
<Network>host</Network>
|
|
7
7
|
<Shell>sh</Shell>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sanctuaryInstallStateRequiredToolCalls = sanctuaryInstallStateRequiredToolCalls;
|
|
4
|
+
exports.sanctuaryVersionQuestionRequiredToolCalls = sanctuaryVersionQuestionRequiredToolCalls;
|
|
4
5
|
const runtime_1 = require("../nerves/runtime");
|
|
5
6
|
const TOOL_NAME = "sanctuary_get_install_state";
|
|
6
7
|
const REQUEST = /\b(?:use|run|call)\s+sanctuary_get_install_state\b/iu;
|
|
@@ -124,3 +125,45 @@ function sanctuaryInstallStateRequiredToolCalls(request, advertisedToolNames) {
|
|
|
124
125
|
},
|
|
125
126
|
};
|
|
126
127
|
}
|
|
128
|
+
const VERSION_QUESTION = /\b(?:what|which)(?:'s|\s+is)?\s+(?:your\s+|the\s+)?(?:current\s+|live\s+|installed\s+|running\s+)?version\b|\bversion\s+(?:are|r)\s+(?:you|u)\b|\bwhat\s+(?:are\s+you|you're)\s+(?:on|running)\b|\bare\s+you\s+(?:on|running)\s+(?:the\s+)?(?:latest|newest|new|current)\b/iu;
|
|
129
|
+
const VERSION_CLAIM = /\bv?\d+\.\d+\.\d+(?:-[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*)?\b/gu;
|
|
130
|
+
/**
|
|
131
|
+
* A natural question about the Butler's own version must be answered from a fresh
|
|
132
|
+
* install-state read. After an upgrade the Butler once answered "Just checked the live
|
|
133
|
+
* state: 0.1.0-alpha.841" from earlier conversation while it was running 845, with no
|
|
134
|
+
* tool call at all. Unlike the explicit install-state contract, the wording stays free:
|
|
135
|
+
* only the version it states is checked against the read.
|
|
136
|
+
*/
|
|
137
|
+
function sanctuaryVersionQuestionRequiredToolCalls(request, advertisedToolNames) {
|
|
138
|
+
const normalizedRequest = request.normalize("NFKC").replace(/[‘’]/gu, "'");
|
|
139
|
+
if (!advertisedToolNames.includes(TOOL_NAME) || REQUEST.test(normalizedRequest) || !VERSION_QUESTION.test(normalizedRequest))
|
|
140
|
+
return undefined;
|
|
141
|
+
let current;
|
|
142
|
+
(0, runtime_1.emitNervesEvent)({
|
|
143
|
+
component: "senses",
|
|
144
|
+
event: "senses.sanctuary_version_question_required",
|
|
145
|
+
message: "a question about the running version requires a fresh install-state read",
|
|
146
|
+
meta: { requiredToolName: TOOL_NAME },
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
names: [TOOL_NAME],
|
|
150
|
+
retryMessage: "Call sanctuary_get_install_state with empty arguments now, then state the version from that fresh result, not from earlier conversation.",
|
|
151
|
+
requireSuccessfulResults: true,
|
|
152
|
+
validateRequiredToolResult: (name, result, args) => {
|
|
153
|
+
if (name !== TOOL_NAME || Object.keys(args).length !== 0)
|
|
154
|
+
return false;
|
|
155
|
+
current = parseInstallState(result);
|
|
156
|
+
return current !== undefined;
|
|
157
|
+
},
|
|
158
|
+
validateTerminalAnswer: (answer) => {
|
|
159
|
+
if (!current)
|
|
160
|
+
return "Call sanctuary_get_install_state and state the version from that fresh result.";
|
|
161
|
+
const known = new Set([current.runtimePackageVersion, current.packagedBundleVersion, ...(current.liveBundleVersion ? [current.liveBundleVersion] : [])].map((version) => version.replace(/^v/u, "")));
|
|
162
|
+
const claimed = [...answer.normalize("NFKC").matchAll(VERSION_CLAIM)].map((match) => match[0].replace(/^v/u, ""));
|
|
163
|
+
if (claimed.length === 0)
|
|
164
|
+
return `State the running version from the fresh result: ${current.runtimePackageVersion}.`;
|
|
165
|
+
const stale = claimed.filter((version) => !known.has(version));
|
|
166
|
+
return stale.length === 0 ? undefined : `The fresh install-state result says ${current.runtimePackageVersion}; do not state ${stale.join(", ")} as the current version.`;
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -42,6 +42,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
42
42
|
exports.stripThinkBlocks = stripThinkBlocks;
|
|
43
43
|
exports.extractOutwardSenseDeliveryText = extractOutwardSenseDeliveryText;
|
|
44
44
|
exports.getSenseSessionPath = getSenseSessionPath;
|
|
45
|
+
exports.erroredTurnReply = erroredTurnReply;
|
|
45
46
|
exports.runSenseTurn = runSenseTurn;
|
|
46
47
|
const os = __importStar(require("os"));
|
|
47
48
|
const path = __importStar(require("path"));
|
|
@@ -333,6 +334,17 @@ function getSenseSessionPath(agentName, friendId, channel, sessionKey, agentRoot
|
|
|
333
334
|
* Caller provides channel, session key, friend, and message;
|
|
334
335
|
* this function handles all pipeline wiring.
|
|
335
336
|
*/
|
|
337
|
+
/**
|
|
338
|
+
* What an outward sense says when a turn errors and provider failover has nothing to say.
|
|
339
|
+
* Such turns used to end in silence: the owner saw no reply, prodded, and later got
|
|
340
|
+
* the late answer followed by a greeting to a prod (D-004); the step-limit stop was the
|
|
341
|
+
* observed cause (D-007). The engine still refuses to answer without evidence.
|
|
342
|
+
*/
|
|
343
|
+
function erroredTurnReply(errorMessage) {
|
|
344
|
+
return /iteration limit exhausted/u.test(errorMessage ?? "")
|
|
345
|
+
? "I couldn't finish that one: I ran out of steps before I had an answer I could stand behind. Ask me again, or ask something narrower, and I'll take another run at it."
|
|
346
|
+
: "I couldn't finish that one: something went wrong before I had an answer. Ask me again and I'll retry.";
|
|
347
|
+
}
|
|
336
348
|
async function runSenseTurn(options) {
|
|
337
349
|
return (0, turn_execution_lease_1.withTurnExecutionLease)(async () => {
|
|
338
350
|
const owner = Object.freeze({ agentName: options.agentName, agentRoot: (0, identity_1.getAgentRoot)(options.agentName) });
|
|
@@ -453,6 +465,7 @@ async function runSenseTurnExclusive(options, owner) {
|
|
|
453
465
|
// once the turn completes.
|
|
454
466
|
let committedResponseText = "";
|
|
455
467
|
let pendingResponseText = "";
|
|
468
|
+
let terminalErrorMessage;
|
|
456
469
|
let terminalDeliveryKind = "text";
|
|
457
470
|
const deliveries = [];
|
|
458
471
|
const deliveryFailures = [];
|
|
@@ -535,6 +548,8 @@ async function runSenseTurnExclusive(options, owner) {
|
|
|
535
548
|
emitFrontendEvent({ type: "tool_completed", data: { name, summary: _summary, success } });
|
|
536
549
|
},
|
|
537
550
|
onError: (error, severity) => {
|
|
551
|
+
if (severity === "terminal")
|
|
552
|
+
terminalErrorMessage = error.message;
|
|
538
553
|
emitFrontendEvent({ type: "error", data: { message: error.message, severity } });
|
|
539
554
|
},
|
|
540
555
|
onClearText: () => {
|
|
@@ -661,7 +676,9 @@ async function runSenseTurnExclusive(options, owner) {
|
|
|
661
676
|
const eventView = currentTurnEventView(terminalEvents, existingEventIds, userMessage, options.precommittedIngress, options.ingressRelations);
|
|
662
677
|
let finalDeliveryKind = terminalDeliveryKind;
|
|
663
678
|
const acceptedTerminalOutcome = turnResult.turnOutcome === "settled" || turnResult.turnOutcome === "blocked";
|
|
664
|
-
const failoverText = turnResult.turnOutcome === "errored"
|
|
679
|
+
const failoverText = turnResult.turnOutcome === "errored"
|
|
680
|
+
? turnResult.failoverMessage?.trim() || (channel === "inner" ? undefined : erroredTurnReply(terminalErrorMessage))
|
|
681
|
+
: undefined;
|
|
665
682
|
const expectsOutwardResponse = acceptedTerminalOutcome || turnResult.turnOutcome === "command" || Boolean(failoverText);
|
|
666
683
|
let finalCausalCoordinate;
|
|
667
684
|
if (acceptedTerminalOutcome) {
|
package/dist/senses/telegram.js
CHANGED
|
@@ -1234,9 +1234,12 @@ function createTelegramSenseApp(options) {
|
|
|
1234
1234
|
const installState = isSanctuaryOwner
|
|
1235
1235
|
? (0, sanctuary_install_state_contract_1.sanctuaryInstallStateRequiredToolCalls)(input.userMessage, relationshipAuthorization.advertisedToolNames)
|
|
1236
1236
|
: undefined;
|
|
1237
|
+
const versionQuestion = isSanctuaryOwner
|
|
1238
|
+
? (0, sanctuary_install_state_contract_1.sanctuaryVersionQuestionRequiredToolCalls)(input.userMessage, relationshipAuthorization.advertisedToolNames)
|
|
1239
|
+
: undefined;
|
|
1237
1240
|
if (input.fullVisibilityProgress && fullVisibility)
|
|
1238
1241
|
input.fullVisibilityProgress.fallback = fullVisibility.emptyResponseFallback;
|
|
1239
|
-
const contracts = [storageOptimization, fullVisibility, staleDockerCare, mediaCatalog, installState].filter(Boolean);
|
|
1242
|
+
const contracts = [storageOptimization, fullVisibility, staleDockerCare, mediaCatalog, installState, versionQuestion].filter(Boolean);
|
|
1240
1243
|
const ownedNames = contracts.map((contract) => new Set(contract.names));
|
|
1241
1244
|
const requiredToolCalls = contracts.length === 0 ? undefined : {
|
|
1242
1245
|
names: [...new Set(contracts.flatMap((contract) => [...contract.names]))],
|
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.846",
|
|
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.846",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|