@ouro.bot/cli 0.1.0-alpha.784 → 0.1.0-alpha.785
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,12 @@
|
|
|
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.785",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Harden Telegram effect recovery so invalid transport-control artifacts cannot crash the butler startup loop."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
4
10
|
{
|
|
5
11
|
"version": "0.1.0-alpha.784",
|
|
6
12
|
"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.785</Repository>
|
|
5
5
|
<Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
|
|
6
6
|
<Network>host</Network>
|
|
7
7
|
<Shell>sh</Shell>
|
|
@@ -241,6 +241,25 @@ class FileTelegramEffectJournal {
|
|
|
241
241
|
const filePath = this.artifactPath(id);
|
|
242
242
|
return fs.existsSync(filePath) ? this.read(id) : null;
|
|
243
243
|
}
|
|
244
|
+
quarantineInvalid(id, reason) {
|
|
245
|
+
this.assertRootIdentity();
|
|
246
|
+
const filePath = this.artifactPath(id);
|
|
247
|
+
if (!fs.existsSync(filePath))
|
|
248
|
+
return;
|
|
249
|
+
const quarantineRoot = path.join(path.dirname(this.root), `${path.basename(this.root)}.quarantine`);
|
|
250
|
+
fs.mkdirSync(quarantineRoot, { recursive: true, mode: 0o700 });
|
|
251
|
+
fs.chmodSync(quarantineRoot, 0o700);
|
|
252
|
+
const quarantinePath = path.join(quarantineRoot, `${id}.${Date.now()}.${process.pid}.invalid.json`);
|
|
253
|
+
fs.renameSync(filePath, quarantinePath);
|
|
254
|
+
fs.chmodSync(quarantinePath, 0o600);
|
|
255
|
+
(0, runtime_1.emitNervesEvent)({
|
|
256
|
+
level: "error",
|
|
257
|
+
component: "senses",
|
|
258
|
+
event: "senses.telegram_effect_artifact_quarantined",
|
|
259
|
+
message: "quarantined invalid Telegram effect artifact",
|
|
260
|
+
meta: { artifactId: id, reason },
|
|
261
|
+
});
|
|
262
|
+
}
|
|
244
263
|
write(artifact) {
|
|
245
264
|
this.assertRootIdentity();
|
|
246
265
|
const filePath = this.artifactPath(artifact.id);
|
|
@@ -268,6 +287,28 @@ class FileTelegramEffectJournal {
|
|
|
268
287
|
.filter((entry) => entry.isFile() && /^[a-f0-9]{64}\.json$/u.test(entry.name))
|
|
269
288
|
.map((entry) => this.read(entry.name.slice(0, -5)));
|
|
270
289
|
}
|
|
290
|
+
listRecoverable() {
|
|
291
|
+
this.assertRootIdentity();
|
|
292
|
+
const entries = fs.readdirSync(this.descriptorRoot, { withFileTypes: true });
|
|
293
|
+
this.assertRootIdentity();
|
|
294
|
+
const artifacts = [];
|
|
295
|
+
for (const entry of entries.filter((candidate) => candidate.isFile() && /^[a-f0-9]{64}\.json$/u.test(candidate.name))) {
|
|
296
|
+
const id = entry.name.slice(0, -5);
|
|
297
|
+
try {
|
|
298
|
+
artifacts.push(this.read(id));
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
(0, runtime_1.emitNervesEvent)({
|
|
302
|
+
level: "error",
|
|
303
|
+
component: "senses",
|
|
304
|
+
event: "senses.telegram_effect_recovery_artifact_skipped",
|
|
305
|
+
message: "skipped invalid Telegram effect artifact during recovery",
|
|
306
|
+
meta: { artifactId: id, error: error instanceof Error ? error.message : String(error) },
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return artifacts;
|
|
311
|
+
}
|
|
271
312
|
}
|
|
272
313
|
exports.FileTelegramEffectJournal = FileTelegramEffectJournal;
|
|
273
314
|
function prepareTelegramEffect(store, input) {
|
|
@@ -281,7 +322,15 @@ function prepareTelegramEffect(store, input) {
|
|
|
281
322
|
if (target.kind === "admission_gate" && input.authorization.transport.chatId !== target.chatId)
|
|
282
323
|
throw new Error("Telegram admission transport route changed");
|
|
283
324
|
const id = artifactId(idempotencyKey);
|
|
284
|
-
|
|
325
|
+
let existing = null;
|
|
326
|
+
try {
|
|
327
|
+
existing = store.readIfExists(id);
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
if (!isTransportOnlyControl({ authorClass: input.authorClass, effect: input.effect, target }))
|
|
331
|
+
throw error;
|
|
332
|
+
store.quarantineInvalid(id, error instanceof Error ? error.message : String(error));
|
|
333
|
+
}
|
|
285
334
|
if (existing) {
|
|
286
335
|
if (JSON.stringify(existing.target) !== JSON.stringify(target)
|
|
287
336
|
|| existing.authorClass !== input.authorClass
|
|
@@ -526,7 +575,7 @@ async function sweepTelegramSystemFailsafes(input) {
|
|
|
526
575
|
}
|
|
527
576
|
async function recoverTelegramEffectOutbox(input) {
|
|
528
577
|
const limit = Math.min(Math.max(input.maxArtifacts ?? 20, 1), 100);
|
|
529
|
-
const candidates = input.store.
|
|
578
|
+
const candidates = input.store.listRecoverable()
|
|
530
579
|
.filter((artifact) => (!input.matches || input.matches(artifact))
|
|
531
580
|
&& !artifact.parts.some((part) => part.state === "attempting" || part.state === "indeterminate")
|
|
532
581
|
&& artifact.parts.some((part) => part.state === "prepared" && (part.attempts ?? 0) < 3))
|
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.785",
|
|
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.785",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|