@animalabs/agent-framework 0.6.4 → 0.6.5
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/README.md +5 -0
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +20 -0
- package/dist/src/agent.js.map +1 -1
- package/dist/src/framework.d.ts +44 -1
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +264 -143
- package/dist/src/framework.js.map +1 -1
- package/dist/src/types/framework.d.ts +9 -0
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/test/activation-request-sanitize.test.d.ts +2 -0
- package/dist/test/activation-request-sanitize.test.d.ts.map +1 -0
- package/dist/test/activation-request-sanitize.test.js +89 -0
- package/dist/test/activation-request-sanitize.test.js.map +1 -0
- package/dist/test/ephemeral-settle.test.d.ts +2 -0
- package/dist/test/ephemeral-settle.test.d.ts.map +1 -0
- package/dist/test/ephemeral-settle.test.js +351 -0
- package/dist/test/ephemeral-settle.test.js.map +1 -0
- package/dist/test/maintenance-timer.test.js +49 -0
- package/dist/test/maintenance-timer.test.js.map +1 -1
- package/dist/test/overbudget-drain-breaker.test.d.ts +2 -0
- package/dist/test/overbudget-drain-breaker.test.d.ts.map +1 -0
- package/dist/test/overbudget-drain-breaker.test.js +157 -0
- package/dist/test/overbudget-drain-breaker.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/agent.ts +22 -0
- package/src/framework.ts +295 -143
- package/src/types/framework.ts +10 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OverBudget deadlock breaker (PR #58, 15befaa): when compile throws
|
|
3
|
+
* context-manager's OverBudgetError, the compression drain never runs — it is
|
|
4
|
+
* driven by successful activity, which the over-budget state prevents. A
|
|
5
|
+
* closed loop with no internal exit (field data 2026-07-10: 36 minutes
|
|
6
|
+
* hard-down, zero self-rescue). noteInferenceExhausted breaks it by kicking
|
|
7
|
+
* the strategy drain (cm.tick()) directly.
|
|
8
|
+
*
|
|
9
|
+
* The trigger is the classified errorType 'over_budget' (err.name ===
|
|
10
|
+
* 'OverBudgetError' — CM does not export the class, so no cross-package
|
|
11
|
+
* instanceof; the message-prose match is only a fallback). These tests pin
|
|
12
|
+
* that classification so a CM message rewording cannot silently kill the
|
|
13
|
+
* breaker.
|
|
14
|
+
*/
|
|
15
|
+
import { test } from 'node:test';
|
|
16
|
+
import assert from 'node:assert/strict';
|
|
17
|
+
import { AgentFramework } from '../src/framework.js';
|
|
18
|
+
import { MembraneError } from '@animalabs/membrane';
|
|
19
|
+
function makeHarness(tick) {
|
|
20
|
+
const cm = {
|
|
21
|
+
addMessage: () => 'marker-id',
|
|
22
|
+
tick,
|
|
23
|
+
};
|
|
24
|
+
const fw = Object.create(AgentFramework.prototype);
|
|
25
|
+
fw.consecutiveInferenceFailures = new Map();
|
|
26
|
+
fw.exhaustionRewinds = new Map();
|
|
27
|
+
fw.rewindEpisode = new Map();
|
|
28
|
+
fw.lastInferenceAt = new Map();
|
|
29
|
+
fw.overBudgetDrainInFlight = new Set();
|
|
30
|
+
fw.opsAlertLastSent = new Map();
|
|
31
|
+
fw.pendingRequests = [];
|
|
32
|
+
fw.traceListeners = [];
|
|
33
|
+
fw.inferenceFailureEscalationThreshold = 3;
|
|
34
|
+
fw.agents = new Map([['cairn', {
|
|
35
|
+
name: 'cairn',
|
|
36
|
+
refusalHandling: { maxRewinds: 3 },
|
|
37
|
+
getContextManager: () => cm,
|
|
38
|
+
}]]);
|
|
39
|
+
const errs = [];
|
|
40
|
+
const orig = console.error;
|
|
41
|
+
console.error = (...a) => { errs.push(a.join(' ')); };
|
|
42
|
+
const restore = () => { console.error = orig; };
|
|
43
|
+
return { fw, errs, restore };
|
|
44
|
+
}
|
|
45
|
+
/** Let the fire-and-forget drain IIFE's microtask chain run to quiescence. */
|
|
46
|
+
async function settle(rounds = 3) {
|
|
47
|
+
for (let i = 0; i < rounds; i++)
|
|
48
|
+
await new Promise((r) => setImmediate(r));
|
|
49
|
+
}
|
|
50
|
+
const OVER_BUDGET_REASON = 'Compile plan would exceed hard budget: head=41200 tail=8100 middle=62000 budget=100000';
|
|
51
|
+
test('classification: err.name OverBudgetError → over_budget, regardless of message wording', () => {
|
|
52
|
+
const fw = Object.create(AgentFramework.prototype);
|
|
53
|
+
// The load-bearing pin: classification must NOT depend on CM's message
|
|
54
|
+
// prose, which CM can reword without knowing AF gates a breaker on it.
|
|
55
|
+
const reworded = new Error('context plan no longer fits (reworded in some future CM)');
|
|
56
|
+
reworded.name = 'OverBudgetError';
|
|
57
|
+
assert.deepEqual(fw.classifyInferenceError(reworded), { errorType: 'over_budget' });
|
|
58
|
+
// Membrane errors keep their own typed classification.
|
|
59
|
+
const membraneErr = new MembraneError({
|
|
60
|
+
type: 'invalid_request',
|
|
61
|
+
message: '400 bad request',
|
|
62
|
+
retryable: false,
|
|
63
|
+
rawError: null,
|
|
64
|
+
});
|
|
65
|
+
assert.deepEqual(fw.classifyInferenceError(membraneErr), { retryable: false, errorType: 'invalid_request' });
|
|
66
|
+
// Anything else stays unclassified.
|
|
67
|
+
assert.deepEqual(fw.classifyInferenceError(new Error('boom')), {});
|
|
68
|
+
});
|
|
69
|
+
test('errorType over_budget kicks the drain: 8 ticks, honest success log', async () => {
|
|
70
|
+
let ticks = 0;
|
|
71
|
+
const { fw, errs, restore } = makeHarness(async () => { ticks++; });
|
|
72
|
+
try {
|
|
73
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, 'over_budget');
|
|
74
|
+
await settle(20);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
restore();
|
|
78
|
+
}
|
|
79
|
+
assert.equal(ticks, 8);
|
|
80
|
+
assert.ok(errs.some((e) => e.includes('drain kicked for cairn') && e.includes('8 ticks')), `success log with real tick count, got: ${errs.join(' | ')}`);
|
|
81
|
+
});
|
|
82
|
+
test('message fallback: "exceed hard budget" prose kicks even without errorType', async () => {
|
|
83
|
+
let ticks = 0;
|
|
84
|
+
const { fw, restore } = makeHarness(async () => { ticks++; });
|
|
85
|
+
try {
|
|
86
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, undefined);
|
|
87
|
+
await settle(20);
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
restore();
|
|
91
|
+
}
|
|
92
|
+
assert.equal(ticks, 8);
|
|
93
|
+
});
|
|
94
|
+
test('unrelated failures never kick the drain', async () => {
|
|
95
|
+
let ticks = 0;
|
|
96
|
+
const { fw, restore } = makeHarness(async () => { ticks++; });
|
|
97
|
+
try {
|
|
98
|
+
fw.noteInferenceExhausted('cairn', '529 overloaded', true, 'server');
|
|
99
|
+
fw.noteInferenceExhausted('cairn', '400 invalid request', false, 'invalid_request');
|
|
100
|
+
fw.noteInferenceExhausted('cairn', 'weird transport error', undefined, undefined);
|
|
101
|
+
await settle(20);
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
restore();
|
|
105
|
+
}
|
|
106
|
+
assert.equal(ticks, 0);
|
|
107
|
+
});
|
|
108
|
+
test('overlapping kicks are suppressed: one drain per agent at a time', async () => {
|
|
109
|
+
let started = 0;
|
|
110
|
+
const gates = [];
|
|
111
|
+
const { fw, errs, restore } = makeHarness(() => { started++; return new Promise((r) => { gates.push(r); }); });
|
|
112
|
+
try {
|
|
113
|
+
// The scenario the breaker exists for: every activation fails, repeatedly.
|
|
114
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, 'over_budget');
|
|
115
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, 'over_budget');
|
|
116
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, 'over_budget');
|
|
117
|
+
await settle();
|
|
118
|
+
// Only ONE kick started; its first tick is still in flight.
|
|
119
|
+
assert.equal(started, 1);
|
|
120
|
+
// Release ticks one at a time — exactly 8 run, then the drain finishes.
|
|
121
|
+
for (let i = 0; i < 8; i++) {
|
|
122
|
+
gates[i]();
|
|
123
|
+
await settle();
|
|
124
|
+
}
|
|
125
|
+
assert.equal(started, 8, 'exactly one drain worth of ticks, not three');
|
|
126
|
+
assert.equal(errs.filter((e) => e.includes('drain kicked for cairn')).length, 1);
|
|
127
|
+
// The in-flight flag was cleared: a NEW failure kicks again.
|
|
128
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, 'over_budget');
|
|
129
|
+
await settle();
|
|
130
|
+
assert.equal(started, 9);
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
restore();
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
test('a failing tick is logged with the real count and clears the in-flight flag', async () => {
|
|
137
|
+
let calls = 0;
|
|
138
|
+
const { fw, errs, restore } = makeHarness(async () => {
|
|
139
|
+
calls++;
|
|
140
|
+
if (calls === 3)
|
|
141
|
+
throw new Error('strategy exploded');
|
|
142
|
+
});
|
|
143
|
+
try {
|
|
144
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, 'over_budget');
|
|
145
|
+
await settle(20);
|
|
146
|
+
assert.ok(errs.some((e) => e.includes('drain kick failed for cairn after 2 ticks')));
|
|
147
|
+
assert.equal(fw.overBudgetDrainInFlight.size, 0, 'flag cleared on failure');
|
|
148
|
+
// Recovery: the next failure can kick again.
|
|
149
|
+
fw.noteInferenceExhausted('cairn', OVER_BUDGET_REASON, undefined, 'over_budget');
|
|
150
|
+
await settle(20);
|
|
151
|
+
assert.ok(calls > 3, 'subsequent kick ran');
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
restore();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=overbudget-drain-breaker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overbudget-drain-breaker.test.js","sourceRoot":"","sources":["../../test/overbudget-drain-breaker.test.ts"],"names":[],"mappings":"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"}
|