@nookplot/runtime 0.5.109 → 0.5.114
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/dist/__tests__/autonomous.doomLoop.test.d.ts +2 -0
- package/dist/__tests__/autonomous.doomLoop.test.d.ts.map +1 -0
- package/dist/__tests__/autonomous.doomLoop.test.js +126 -0
- package/dist/__tests__/autonomous.doomLoop.test.js.map +1 -0
- package/dist/__tests__/autonomous.getAvailableActions.test.js +41 -0
- package/dist/__tests__/autonomous.getAvailableActions.test.js.map +1 -1
- package/dist/__tests__/autonomous.loadedSkillRefs.test.d.ts +2 -0
- package/dist/__tests__/autonomous.loadedSkillRefs.test.d.ts.map +1 -0
- package/dist/__tests__/autonomous.loadedSkillRefs.test.js +150 -0
- package/dist/__tests__/autonomous.loadedSkillRefs.test.js.map +1 -0
- package/dist/__tests__/codegen-drift.test.d.ts +23 -0
- package/dist/__tests__/codegen-drift.test.d.ts.map +1 -0
- package/dist/__tests__/codegen-drift.test.js +185 -0
- package/dist/__tests__/codegen-drift.test.js.map +1 -0
- package/dist/__tests__/doomLoop.test.d.ts +6 -0
- package/dist/__tests__/doomLoop.test.d.ts.map +1 -0
- package/dist/__tests__/doomLoop.test.js +144 -0
- package/dist/__tests__/doomLoop.test.js.map +1 -0
- package/dist/__tests__/goalLoop.test.js +111 -0
- package/dist/__tests__/goalLoop.test.js.map +1 -1
- package/dist/__tests__/hooks.test.js +4 -0
- package/dist/__tests__/hooks.test.js.map +1 -1
- package/dist/__tests__/onChainActions.parity.test.d.ts +12 -0
- package/dist/__tests__/onChainActions.parity.test.d.ts.map +1 -0
- package/dist/__tests__/onChainActions.parity.test.js +104 -0
- package/dist/__tests__/onChainActions.parity.test.js.map +1 -0
- package/dist/__tests__/presetLoader.test.js +42 -42
- package/dist/__tests__/sandbox.test.js +24 -24
- package/dist/__tests__/signing.test.d.ts +2 -0
- package/dist/__tests__/signing.test.d.ts.map +1 -0
- package/dist/__tests__/signing.test.js +260 -0
- package/dist/__tests__/signing.test.js.map +1 -0
- package/dist/actionCatalog.generated.d.ts +1 -1
- package/dist/actionCatalog.generated.d.ts.map +1 -1
- package/dist/actionCatalog.generated.js +117 -22
- package/dist/actionCatalog.generated.js.map +1 -1
- package/dist/actionCatalog.js +1 -1
- package/dist/actionCatalog.js.map +1 -1
- package/dist/autonomous.d.ts +11 -0
- package/dist/autonomous.d.ts.map +1 -1
- package/dist/autonomous.js +93 -0
- package/dist/autonomous.js.map +1 -1
- package/dist/conversation/modelLimits.js +17 -17
- package/dist/doomLoop.d.ts +52 -0
- package/dist/doomLoop.d.ts.map +1 -0
- package/dist/doomLoop.js +173 -0
- package/dist/doomLoop.js.map +1 -0
- package/dist/goal/goalLoop.d.ts +3 -0
- package/dist/goal/goalLoop.d.ts.map +1 -1
- package/dist/goal/goalLoop.js +30 -1
- package/dist/goal/goalLoop.js.map +1 -1
- package/dist/goal/goalPrompts.js +27 -27
- package/dist/hooks.d.ts +10 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js.map +1 -1
- package/dist/signalActionMap.d.ts +13 -1
- package/dist/signalActionMap.d.ts.map +1 -1
- package/dist/signalActionMap.js +25 -2
- package/dist/signalActionMap.js.map +1 -1
- package/dist/signing.js +2 -2
- package/dist/signing.js.map +1 -1
- package/package.json +60 -60
- package/dist/__tests__/lineage.test.d.ts +0 -2
- package/dist/__tests__/lineage.test.d.ts.map +0 -1
- package/dist/__tests__/lineage.test.js +0 -131
- package/dist/__tests__/lineage.test.js.map +0 -1
- package/dist/lineage.d.ts +0 -69
- package/dist/lineage.d.ts.map +0 -1
- package/dist/lineage.js +0 -72
- package/dist/lineage.js.map +0 -1
package/dist/autonomous.js
CHANGED
|
@@ -47,6 +47,9 @@ import { WakeUpStack } from "./wakeUpStack.js";
|
|
|
47
47
|
import { GoalLoop } from "./goal/goalLoop.js";
|
|
48
48
|
import { hooks as defaultHooks } from "./hooks.js";
|
|
49
49
|
import { guardrails as defaultGuardrails, GuardrailTripped, InputGuardrailTripped, } from "./guardrails.js";
|
|
50
|
+
import { buildCorrectivePrompt, checkForDoomLoopFromSignatures, makeSignature, } from "./doomLoop.js";
|
|
51
|
+
const AUTONOMOUS_DOOM_LOOP_MAX_TRIGGERS = 3;
|
|
52
|
+
const AUTONOMOUS_DOOM_LOOP_SIGNATURE_WINDOW = 30;
|
|
50
53
|
// ----------------------------------------------------------------
|
|
51
54
|
// AutonomousAgent
|
|
52
55
|
// ----------------------------------------------------------------
|
|
@@ -150,6 +153,17 @@ export class AutonomousAgent {
|
|
|
150
153
|
processedSignals = new Map();
|
|
151
154
|
/** Dynamic tool browsing: categories loaded via browse_tools. */
|
|
152
155
|
loadedCategories = new Set();
|
|
156
|
+
/** Doom-loop detector state: ring buffer of recent action signatures + trigger counter. */
|
|
157
|
+
toolSignatures = [];
|
|
158
|
+
doomLoopTriggers = 0;
|
|
159
|
+
/**
|
|
160
|
+
* SRA Phase 4b — rolling buffer of skills loaded via nookplot_load_skill.
|
|
161
|
+
* Captured post-dispatch; flushed into args.loadedSkillRefs pre-dispatch on
|
|
162
|
+
* submit_reasoning_trace / submit_subtask_trace. Cap 64 (drop oldest); the
|
|
163
|
+
* gateway intersects against (agent, used=true, last 24h) signals so stale
|
|
164
|
+
* or unauthorized refs are dropped silently. Format on the wire: `${kind}:${ref}`.
|
|
165
|
+
*/
|
|
166
|
+
loadedSkillRefs = [];
|
|
153
167
|
/** Tiered knowledge context: L0 identity + L1 essentials (session-cached) + L2 on-demand. */
|
|
154
168
|
wakeUpStack;
|
|
155
169
|
constructor(runtime, options = {}) {
|
|
@@ -2790,6 +2804,58 @@ export class AutonomousAgent {
|
|
|
2790
2804
|
}
|
|
2791
2805
|
const startTime = Date.now();
|
|
2792
2806
|
hooks.emitFireAndForget("action_start", { actionType, args, actionId, agentAddress });
|
|
2807
|
+
// ── Doom-loop detection (parity with goal_loop.ts) ──
|
|
2808
|
+
// Push the action signature into a 30-slot ring; if the recent tail
|
|
2809
|
+
// shows 3+ identical calls or an A,B,A,B-style cycle, increment the
|
|
2810
|
+
// trigger counter. After 3 triggers in this agent's lifetime, abort
|
|
2811
|
+
// the current cycle so the outer proactive scheduler can re-route —
|
|
2812
|
+
// keeping the autonomous loop from spending NOOK on a stuck bug.
|
|
2813
|
+
this.toolSignatures.push(makeSignature(actionType, args));
|
|
2814
|
+
if (this.toolSignatures.length > AUTONOMOUS_DOOM_LOOP_SIGNATURE_WINDOW) {
|
|
2815
|
+
this.toolSignatures = this.toolSignatures.slice(-AUTONOMOUS_DOOM_LOOP_SIGNATURE_WINDOW);
|
|
2816
|
+
}
|
|
2817
|
+
const doomOffender = checkForDoomLoopFromSignatures(this.toolSignatures);
|
|
2818
|
+
if (doomOffender) {
|
|
2819
|
+
this.doomLoopTriggers++;
|
|
2820
|
+
hooks.emitFireAndForget("doom_loop_detected", {
|
|
2821
|
+
offender: doomOffender,
|
|
2822
|
+
triggers: this.doomLoopTriggers,
|
|
2823
|
+
actionType,
|
|
2824
|
+
});
|
|
2825
|
+
// Track C.2: also push to gateway as fire-and-forget telemetry so
|
|
2826
|
+
// ops dashboards can answer "which tools most often misbehave?"
|
|
2827
|
+
// and "is this agent stuck right now?" — see
|
|
2828
|
+
// gateway/src/services/doomLoopMetrics.ts. Errors are swallowed so
|
|
2829
|
+
// a backend outage never blocks the runtime's recovery path.
|
|
2830
|
+
void this.runtime.connection
|
|
2831
|
+
.request("POST", "/v1/agents/me/doom-loop-event", {
|
|
2832
|
+
offender: doomOffender,
|
|
2833
|
+
triggers: this.doomLoopTriggers,
|
|
2834
|
+
actionType,
|
|
2835
|
+
})
|
|
2836
|
+
.catch(() => { });
|
|
2837
|
+
if (this.doomLoopTriggers >= AUTONOMOUS_DOOM_LOOP_MAX_TRIGGERS) {
|
|
2838
|
+
if (this.verbose) {
|
|
2839
|
+
console.warn(`[autonomous] ✗ doom loop on '${doomOffender}' (${this.doomLoopTriggers} triggers) — aborting cycle`);
|
|
2840
|
+
}
|
|
2841
|
+
const reason = buildCorrectivePrompt(doomOffender);
|
|
2842
|
+
hooks.emitFireAndForget("action_error", {
|
|
2843
|
+
actionType, args, error: new Error(reason),
|
|
2844
|
+
durationMs: Date.now() - startTime, actionId,
|
|
2845
|
+
});
|
|
2846
|
+
if (actionId) {
|
|
2847
|
+
try {
|
|
2848
|
+
await this.runtime.proactive.rejectDelegatedAction(actionId, reason);
|
|
2849
|
+
}
|
|
2850
|
+
catch { /* best-effort */ }
|
|
2851
|
+
}
|
|
2852
|
+
// Reset trigger counter so the agent can recover after the outer
|
|
2853
|
+
// scheduler reroutes — but keep the signature ring so a doom loop
|
|
2854
|
+
// resurfacing on the next action still trips the detector.
|
|
2855
|
+
this.doomLoopTriggers = 0;
|
|
2856
|
+
return;
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2793
2859
|
// ── Input guardrails (Phase 3) ──
|
|
2794
2860
|
// Run BEFORE the action body so a tripped guardrail prevents dispatch.
|
|
2795
2861
|
// `tool_input` fires regardless so observability sees the call attempt;
|
|
@@ -2885,10 +2951,37 @@ export class AutonomousAgent {
|
|
|
2885
2951
|
...args,
|
|
2886
2952
|
...(suggestedContent ? { suggestedContent } : {}),
|
|
2887
2953
|
};
|
|
2954
|
+
// SRA Phase 4b — flush loaded-skill buffer into submit traces. If the
|
|
2955
|
+
// caller already set loadedSkillRefs explicitly, respect it; otherwise
|
|
2956
|
+
// populate from the buffer. Drop entries older than 24h client-side
|
|
2957
|
+
// (server enforces the same window via intersection, but this keeps the
|
|
2958
|
+
// payload small).
|
|
2959
|
+
if ((actionType === "submit_reasoning_trace" || actionType === "submit_subtask_trace") &&
|
|
2960
|
+
dispatchPayload.loadedSkillRefs == null &&
|
|
2961
|
+
this.loadedSkillRefs.length > 0) {
|
|
2962
|
+
const cutoff = Date.now() - 24 * 60 * 60 * 1000;
|
|
2963
|
+
this.loadedSkillRefs = this.loadedSkillRefs.filter(e => e.loadedAt >= cutoff);
|
|
2964
|
+
if (this.loadedSkillRefs.length > 0) {
|
|
2965
|
+
dispatchPayload.loadedSkillRefs = this.loadedSkillRefs.map(e => `${e.kind}:${e.ref}`);
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2888
2968
|
const dispatchResult = await this.runtime.connection.request("POST", "/v1/actions/execute", { toolName, payload: dispatchPayload });
|
|
2889
2969
|
switch (dispatchResult.status) {
|
|
2890
2970
|
case "completed": {
|
|
2891
2971
|
result = (dispatchResult.result ?? {});
|
|
2972
|
+
// SRA Phase 4b — capture canonical_ref from load_skill responses so
|
|
2973
|
+
// the next submit_reasoning_trace can declare them. The gateway's
|
|
2974
|
+
// recordLoad() already flips used=true on its skill_utility_signals
|
|
2975
|
+
// row; we just need to remember the ref for the trace-linkage step.
|
|
2976
|
+
if (actionType === "load_skill" && typeof result.canonical_ref === "string") {
|
|
2977
|
+
const kind = args.kind;
|
|
2978
|
+
if (typeof kind === "string") {
|
|
2979
|
+
this.loadedSkillRefs.push({ kind, ref: result.canonical_ref, loadedAt: Date.now() });
|
|
2980
|
+
if (this.loadedSkillRefs.length > 64) {
|
|
2981
|
+
this.loadedSkillRefs = this.loadedSkillRefs.slice(-64);
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2892
2985
|
break;
|
|
2893
2986
|
}
|
|
2894
2987
|
case "sign_required": {
|