@ouro.bot/cli 0.1.0-alpha.821 → 0.1.0-alpha.823
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
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
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.823",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Make a promised follow-up an obligation the Butler returns to unasked."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.1.0-alpha.822",
|
|
12
|
+
"changes": [
|
|
13
|
+
"Suppress a proactive Telegram message that repeats a recent one apart from its clock reading.",
|
|
14
|
+
"Evict the repetition guard's oldest entry in insertion order, removing a comparison branch monotonic time could never take."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
4
17
|
{
|
|
5
18
|
"version": "0.1.0-alpha.821",
|
|
6
19
|
"changes": [
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
- For Ari's whole-household status questions, read current evidence before answering and separate active work, waiting on Ari, snoozed wake times, intentionally quiet services, healthy systems, and other current issues. Do not narrate daemon, event-queue, provider-lane, or backend service internals; translate them into compact household outcomes only when they are currently relevant.
|
|
8
8
|
- For household media questions, use the media tools when they are available and the restricted catalog read otherwise. Answer like a tasteful steward of the shelf: pick, recommend, compare, or confirm from current evidence without volunteering an AI or `I cannot watch` disclaimer.
|
|
9
9
|
- Check shelf state before naming a title. Never suggest going to find something that is already here, and never name a title the current search did not return.
|
|
10
|
+
- A promise of follow-up is an obligation, not a pleasantry. When I say I will watch something, check back, or tell Ari when it lands, I file the watch in the same turn and I return to it unasked — when it happens, when it clearly will not, or when I have been quiet long enough that silence has become the answer. Ari should never have to ask whether I am still on it.
|
|
11
|
+
- Closing a loop is worth a short message even when the news is dull. "Still nothing, here is why, next check is X" is a better neighbour than silence.
|
|
10
12
|
- Do not open a reply by announcing its honesty. Say the true thing plainly; `Honest:`, `Honest answer:`, and `To be honest` add nothing and read as apology. Report a limit once, without ceremony, and never in place of an answer that the tools can actually give.
|
|
11
13
|
- Never touch array/parity/disk configuration, permissions, network/security settings, or `/mnt/user` paths.
|
|
12
14
|
- Never send server data off-box or enter credentials into another system.
|
|
@@ -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.823</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/senses/telegram.js
CHANGED
|
@@ -51,6 +51,7 @@ exports.loadTelegramSenseCredentials = loadTelegramSenseCredentials;
|
|
|
51
51
|
exports.createProductionTelegramRelationshipComposition = createProductionTelegramRelationshipComposition;
|
|
52
52
|
exports.startTelegramSenseApp = startTelegramSenseApp;
|
|
53
53
|
exports.sendTelegramExternalEventDecision = sendTelegramExternalEventDecision;
|
|
54
|
+
exports.createProactiveRepetitionGuard = createProactiveRepetitionGuard;
|
|
54
55
|
exports.withTelegramTypingIndicator = withTelegramTypingIndicator;
|
|
55
56
|
exports.sendTelegramAwaitFollowUp = sendTelegramAwaitFollowUp;
|
|
56
57
|
const node_crypto_1 = require("node:crypto");
|
|
@@ -720,6 +721,7 @@ function createTelegramSenseApp(options) {
|
|
|
720
721
|
const api = authorityTransport?.api ?? options.api ?? (0, telegram_client_1.createTelegramBotApi)({ token: botToken });
|
|
721
722
|
// Only the root authority transport admits sendChatAction, so presence is offered
|
|
722
723
|
// exactly where it is actually supported rather than attempted everywhere.
|
|
724
|
+
const proactiveRepetitionGuard = createProactiveRepetitionGuard();
|
|
723
725
|
const sendTypingIndicator = authorityTransport
|
|
724
726
|
? async (chatId) => { await api.request("sendChatAction", { chat_id: chatId, action: "typing" }); }
|
|
725
727
|
: undefined;
|
|
@@ -1879,7 +1881,20 @@ function createTelegramSenseApp(options) {
|
|
|
1879
1881
|
},
|
|
1880
1882
|
async sendProactive(text, signal) {
|
|
1881
1883
|
await runWithAcceptanceAuditOwner(async () => {
|
|
1882
|
-
const
|
|
1884
|
+
const proactiveText = requiredText(text, "proactive message");
|
|
1885
|
+
// Unsolicited repetition is the one thing a household agent cannot take
|
|
1886
|
+
// back. External-event decisions are deliberately not guarded here:
|
|
1887
|
+
// dropping one could leave its event undispositioned.
|
|
1888
|
+
if (!proactiveRepetitionGuard.shouldSend(proactiveText)) {
|
|
1889
|
+
(0, runtime_1.emitNervesEvent)({
|
|
1890
|
+
component: "senses",
|
|
1891
|
+
event: "senses.telegram_proactive_repetition_suppressed",
|
|
1892
|
+
message: "suppressed a proactive message repeating a recent one",
|
|
1893
|
+
meta: { agentName: options.agentName, subject },
|
|
1894
|
+
});
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
const effect = await deliverButlerEffect(proactiveText, `proactive:${(0, node_crypto_1.randomUUID)()}`, signal);
|
|
1883
1898
|
const sessionPath = (0, shared_turn_1.getSenseSessionPath)(options.agentName, configuredOwnerFriendId, "telegram", configuredOwnerSessionKey, agentRoot);
|
|
1884
1899
|
await recordAcceptedEffects(sessionPath, [effect]);
|
|
1885
1900
|
});
|
|
@@ -2234,6 +2249,51 @@ async function sendTelegramExternalEventDecision(agentName, input) {
|
|
|
2234
2249
|
await app.stop();
|
|
2235
2250
|
}
|
|
2236
2251
|
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Suppresses a proactive message that repeats one sent recently.
|
|
2254
|
+
*
|
|
2255
|
+
* Ari received four probe messages in about two minutes, three of them identical
|
|
2256
|
+
* apart from the clock reading. Only the clock is normalised away — counts and
|
|
2257
|
+
* every other number are the payload, so "3 of 10 episodes" and "7 of 10" stay
|
|
2258
|
+
* distinct and both send.
|
|
2259
|
+
*
|
|
2260
|
+
* This catches verbatim-apart-from-the-clock repetition, not semantic near
|
|
2261
|
+
* duplicates: a message reworded between sends still goes out.
|
|
2262
|
+
*/
|
|
2263
|
+
function createProactiveRepetitionGuard(options) {
|
|
2264
|
+
const windowMs = options?.windowMs ?? 900_000;
|
|
2265
|
+
const now = options?.now ?? (() => Date.now());
|
|
2266
|
+
const maxEntries = options?.maxEntries ?? 32;
|
|
2267
|
+
const seen = new Map();
|
|
2268
|
+
const normalize = (text) => text
|
|
2269
|
+
.trim()
|
|
2270
|
+
.replace(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?/gu, "<timestamp>")
|
|
2271
|
+
.replace(/\b\d{1,2}:\d{2}(?::\d{2})?\b/gu, "<clock>")
|
|
2272
|
+
.replace(/\s+/gu, " ");
|
|
2273
|
+
return {
|
|
2274
|
+
shouldSend(text) {
|
|
2275
|
+
const at = now();
|
|
2276
|
+
for (const [key, sentAt] of [...seen]) {
|
|
2277
|
+
if (at - sentAt >= windowMs)
|
|
2278
|
+
seen.delete(key);
|
|
2279
|
+
}
|
|
2280
|
+
const key = normalize(text);
|
|
2281
|
+
const previous = seen.get(key);
|
|
2282
|
+
if (previous !== undefined && at - previous < windowMs)
|
|
2283
|
+
return false;
|
|
2284
|
+
seen.set(key, at);
|
|
2285
|
+
// A Map keeps insertion order and entries are inserted in send order, so
|
|
2286
|
+
// the earliest key is the oldest; scanning for a minimum would carry a
|
|
2287
|
+
// comparison branch that monotonic time can never take.
|
|
2288
|
+
for (const oldest of seen.keys()) {
|
|
2289
|
+
if (seen.size <= maxEntries)
|
|
2290
|
+
break;
|
|
2291
|
+
seen.delete(oldest);
|
|
2292
|
+
}
|
|
2293
|
+
return true;
|
|
2294
|
+
},
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2237
2297
|
/**
|
|
2238
2298
|
* Telegram clears a typing indicator after roughly five seconds, so a turn that
|
|
2239
2299
|
* thinks for longer has to refresh it or the chat goes silent while the Butler is
|
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.823",
|
|
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.823",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|