@namzu/sdk 1.0.0 → 1.1.0
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.md +167 -0
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +5 -0
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts +22 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +47 -14
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/__tests__/supervisor-ledger.test.d.ts +2 -0
- package/dist/agents/__tests__/supervisor-ledger.test.d.ts.map +1 -0
- package/dist/agents/__tests__/supervisor-ledger.test.js +131 -0
- package/dist/agents/__tests__/supervisor-ledger.test.js.map +1 -0
- package/dist/config/runtime.d.ts +24 -0
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/runtime.js +9 -0
- package/dist/config/runtime.js.map +1 -1
- package/dist/connector/builtins/webhook.test.js +17 -0
- package/dist/connector/builtins/webhook.test.js.map +1 -1
- package/dist/connector/index.d.ts +1 -0
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +1 -0
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +4 -0
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/index.d.ts +1 -0
- package/dist/connector/mcp/index.d.ts.map +1 -1
- package/dist/connector/mcp/index.js +1 -0
- package/dist/connector/mcp/index.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts +22 -0
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -0
- package/dist/connector/mcp/streamable-http.js +128 -0
- package/dist/connector/mcp/streamable-http.js.map +1 -0
- package/dist/connector/mcp/streamable-http.test.d.ts +2 -0
- package/dist/connector/mcp/streamable-http.test.d.ts.map +1 -0
- package/dist/connector/mcp/streamable-http.test.js +132 -0
- package/dist/connector/mcp/streamable-http.test.js.map +1 -0
- package/dist/persona/assembler.d.ts.map +1 -1
- package/dist/persona/assembler.js +18 -9
- package/dist/persona/assembler.js.map +1 -1
- package/dist/provider/collect.d.ts.map +1 -1
- package/dist/provider/collect.js +4 -1
- package/dist/provider/collect.js.map +1 -1
- package/dist/public-runtime.d.ts +1 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +1 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/registry/tool/execute.d.ts +27 -0
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +124 -21
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/registry/tool/execute.test.d.ts +9 -6
- package/dist/registry/tool/execute.test.d.ts.map +1 -1
- package/dist/registry/tool/execute.test.js +72 -10
- package/dist/registry/tool/execute.test.js.map +1 -1
- package/dist/registry/toolset/catalog.test.js +62 -0
- package/dist/registry/toolset/catalog.test.js.map +1 -1
- package/dist/runtime/query/__tests__/deferred-tools.test.js +43 -5
- package/dist/runtime/query/__tests__/deferred-tools.test.js.map +1 -1
- package/dist/runtime/query/__tests__/long-document-flow.test.d.ts +2 -0
- package/dist/runtime/query/__tests__/long-document-flow.test.d.ts.map +1 -0
- package/dist/runtime/query/__tests__/long-document-flow.test.js +154 -0
- package/dist/runtime/query/__tests__/long-document-flow.test.js.map +1 -0
- package/dist/runtime/query/__tests__/prompt.test.js +15 -11
- package/dist/runtime/query/__tests__/prompt.test.js.map +1 -1
- package/dist/runtime/query/index.d.ts +9 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +23 -2
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +2 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +99 -6
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/checkpoint.js +2 -2
- package/dist/runtime/query/iteration/phases/checkpoint.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.d.ts +8 -0
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +84 -3
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +12 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js +53 -0
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts +2 -0
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js +73 -0
- package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js.map +1 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts +2 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js +120 -0
- package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js.map +1 -0
- package/dist/runtime/query/iteration/phases/tool-review.d.ts +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +7 -2
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts +19 -0
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js +177 -0
- package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js.map +1 -0
- package/dist/runtime/query/iteration/phases/working-memory.d.ts +31 -0
- package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/working-memory.js +81 -0
- package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -0
- package/dist/session/workspace/__tests__/shared-run.test.js +1 -1
- package/dist/session/workspace/__tests__/shared-run.test.js.map +1 -1
- package/dist/session/workspace/shared-run.js +1 -0
- package/dist/session/workspace/shared-run.js.map +1 -1
- package/dist/skills/loader.test.js +8 -8
- package/dist/skills/loader.test.js.map +1 -1
- package/dist/streaming/coalesce.test.js.map +1 -1
- package/dist/tools/builtins/__tests__/payload-budget.test.js +48 -0
- package/dist/tools/builtins/__tests__/payload-budget.test.js.map +1 -1
- package/dist/tools/builtins/__tests__/read-file.test.js +9 -0
- package/dist/tools/builtins/__tests__/read-file.test.js.map +1 -1
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +50 -2
- package/dist/tools/builtins/read-file.js.map +1 -1
- package/dist/tools/builtins/search-tools.d.ts.map +1 -1
- package/dist/tools/builtins/search-tools.js +32 -7
- package/dist/tools/builtins/search-tools.js.map +1 -1
- package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts +2 -0
- package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts.map +1 -0
- package/dist/tools/coordinator/__tests__/approve-plan.test.js +114 -0
- package/dist/tools/coordinator/__tests__/approve-plan.test.js.map +1 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts +2 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts.map +1 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.js +309 -0
- package/dist/tools/coordinator/__tests__/ask-user-question.test.js.map +1 -0
- package/dist/tools/coordinator/index.d.ts +8 -0
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +195 -15
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/types/agent/index.d.ts +1 -0
- package/dist/types/agent/index.d.ts.map +1 -1
- package/dist/types/agent/index.js +1 -0
- package/dist/types/agent/index.js.map +1 -1
- package/dist/types/agent/reactive.d.ts +15 -0
- package/dist/types/agent/reactive.d.ts.map +1 -1
- package/dist/types/agent/supervisor.d.ts +18 -0
- package/dist/types/agent/supervisor.d.ts.map +1 -1
- package/dist/types/agent/working-memory.d.ts +29 -0
- package/dist/types/agent/working-memory.d.ts.map +1 -0
- package/dist/types/agent/working-memory.js +2 -0
- package/dist/types/agent/working-memory.js.map +1 -0
- package/dist/types/common/index.d.ts +10 -0
- package/dist/types/common/index.d.ts.map +1 -1
- package/dist/types/common/index.js +18 -0
- package/dist/types/common/index.js.map +1 -1
- package/dist/types/common/usage-merge.test.d.ts +2 -0
- package/dist/types/common/usage-merge.test.d.ts.map +1 -0
- package/dist/types/common/usage-merge.test.js +48 -0
- package/dist/types/common/usage-merge.test.js.map +1 -0
- package/dist/types/connector/mcp.d.ts +9 -2
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/hitl/index.d.ts +42 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js +11 -0
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/provider/chat.d.ts +9 -0
- package/dist/types/provider/chat.d.ts.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +25 -4
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/ReactiveAgent.ts +5 -0
- package/src/agents/SupervisorAgent.ts +56 -16
- package/src/agents/__tests__/supervisor-ledger.test.ts +185 -0
- package/src/config/runtime.ts +9 -0
- package/src/connector/builtins/webhook.test.ts +21 -0
- package/src/connector/index.ts +1 -0
- package/src/connector/mcp/client.ts +4 -0
- package/src/connector/mcp/index.ts +1 -0
- package/src/connector/mcp/streamable-http.test.ts +169 -0
- package/src/connector/mcp/streamable-http.ts +152 -0
- package/src/persona/assembler.ts +18 -6
- package/src/provider/collect.ts +4 -1
- package/src/public-runtime.ts +1 -0
- package/src/registry/tool/execute.test.ts +85 -10
- package/src/registry/tool/execute.ts +124 -21
- package/src/registry/toolset/catalog.test.ts +68 -0
- package/src/runtime/query/__tests__/deferred-tools.test.ts +52 -5
- package/src/runtime/query/__tests__/long-document-flow.test.ts +180 -0
- package/src/runtime/query/__tests__/prompt.test.ts +15 -11
- package/src/runtime/query/index.ts +34 -2
- package/src/runtime/query/iteration/index.ts +98 -6
- package/src/runtime/query/iteration/phases/checkpoint.ts +7 -2
- package/src/runtime/query/iteration/phases/compaction.ts +89 -3
- package/src/runtime/query/iteration/phases/context.ts +58 -0
- package/src/runtime/query/iteration/phases/hitl-abort-race.test.ts +86 -0
- package/src/runtime/query/iteration/phases/hitl-answer-question.test.ts +139 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +7 -3
- package/src/runtime/query/iteration/phases/working-memory-compaction.test.ts +215 -0
- package/src/runtime/query/iteration/phases/working-memory.ts +86 -0
- package/src/session/workspace/__tests__/shared-run.test.ts +1 -1
- package/src/session/workspace/shared-run.ts +1 -0
- package/src/skills/loader.test.ts +8 -8
- package/src/streaming/coalesce.test.ts +3 -3
- package/src/tools/builtins/__tests__/payload-budget.test.ts +63 -0
- package/src/tools/builtins/__tests__/read-file.test.ts +12 -0
- package/src/tools/builtins/read-file.ts +50 -2
- package/src/tools/builtins/search-tools.ts +38 -7
- package/src/tools/coordinator/__tests__/approve-plan.test.ts +139 -0
- package/src/tools/coordinator/__tests__/ask-user-question.test.ts +370 -0
- package/src/tools/coordinator/index.ts +227 -17
- package/src/types/agent/index.ts +1 -0
- package/src/types/agent/reactive.ts +17 -0
- package/src/types/agent/supervisor.ts +20 -0
- package/src/types/agent/working-memory.ts +29 -0
- package/src/types/common/index.ts +19 -0
- package/src/types/common/usage-merge.test.ts +53 -0
- package/src/types/connector/mcp.ts +14 -2
- package/src/types/hitl/index.ts +52 -1
- package/src/types/provider/chat.ts +10 -0
- package/src/version.ts +26 -4
|
@@ -6,6 +6,7 @@ import type { PlanManager } from '../../../../manager/plan/lifecycle.js';
|
|
|
6
6
|
import type { RunPersistence } from '../../../../manager/run/persistence.js';
|
|
7
7
|
import type { ActivityStore } from '../../../../store/activity/memory.js';
|
|
8
8
|
import type { TaskGateway, TaskHandle } from '../../../../types/agent/gateway.js';
|
|
9
|
+
import type { WorkingMemoryProvider } from '../../../../types/agent/working-memory.js';
|
|
9
10
|
import type { HITLResumeDecision, ResumeHandler } from '../../../../types/hitl/index.js';
|
|
10
11
|
import type { TaskId } from '../../../../types/ids/index.js';
|
|
11
12
|
import type { LLMProvider } from '../../../../types/provider/index.js';
|
|
@@ -54,11 +55,22 @@ export interface IterationContext {
|
|
|
54
55
|
readonly launchedTasks: Map<TaskId, LaunchedTaskMeta>;
|
|
55
56
|
readonly compactionConfig?: CompactionConfig;
|
|
56
57
|
readonly workingStateManager?: WorkingStateManager;
|
|
58
|
+
readonly workingMemoryProvider?: WorkingMemoryProvider;
|
|
57
59
|
readonly advisoryCtx?: AdvisoryContext;
|
|
58
60
|
readonly agentBus?: AgentBus;
|
|
59
61
|
readonly verificationGate?: import('../../../../verification/gate.js').VerificationGate;
|
|
60
62
|
readonly pluginManager?: import('../../../../plugin/lifecycle.js').PluginLifecycleManager;
|
|
61
63
|
}
|
|
62
64
|
export type PhaseSignal = 'continue' | 'stop';
|
|
65
|
+
/**
|
|
66
|
+
* Await a HITL `resumeHandler` decision, but RACE it against the run's abort
|
|
67
|
+
* signal. A Stop that arrives while the run is parked on a tool-review or
|
|
68
|
+
* iteration checkpoint used to do nothing until the host eventually answered
|
|
69
|
+
* (the park await was not cancellable). Racing the signal lets a Stop resolve
|
|
70
|
+
* the park immediately as an `abort` decision, which `handleHITLDecision`
|
|
71
|
+
* turns into `setStopReason('cancelled') + markCancelled + stop`. Fails closed:
|
|
72
|
+
* a resume-handler rejection also resolves to `abort` rather than hanging.
|
|
73
|
+
*/
|
|
74
|
+
export declare function awaitDecisionOrAbort(ctx: IterationContext, request: Parameters<ResumeHandler>[0]): Promise<HITLResumeDecision>;
|
|
63
75
|
export declare function handleHITLDecision(ctx: IterationContext, decision: HITLResumeDecision, checkpointId: string, context: string): AsyncGenerator<RunEvent, PhaseSignal>;
|
|
64
76
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/context.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Await a HITL `resumeHandler` decision, but RACE it against the run's abort
|
|
3
|
+
* signal. A Stop that arrives while the run is parked on a tool-review or
|
|
4
|
+
* iteration checkpoint used to do nothing until the host eventually answered
|
|
5
|
+
* (the park await was not cancellable). Racing the signal lets a Stop resolve
|
|
6
|
+
* the park immediately as an `abort` decision, which `handleHITLDecision`
|
|
7
|
+
* turns into `setStopReason('cancelled') + markCancelled + stop`. Fails closed:
|
|
8
|
+
* a resume-handler rejection also resolves to `abort` rather than hanging.
|
|
9
|
+
*/
|
|
10
|
+
export async function awaitDecisionOrAbort(ctx, request) {
|
|
11
|
+
const signal = ctx.abortController?.signal;
|
|
12
|
+
// No abort signal wired (e.g. a minimal test harness) → behave exactly as a
|
|
13
|
+
// direct resumeHandler await, no race. In production RunContextFactory always
|
|
14
|
+
// provides the controller, so the race below is live.
|
|
15
|
+
if (!signal)
|
|
16
|
+
return ctx.resumeHandler(request);
|
|
17
|
+
const abortDecision = {
|
|
18
|
+
action: 'abort',
|
|
19
|
+
reason: 'run aborted while parked for HITL',
|
|
20
|
+
};
|
|
21
|
+
if (signal.aborted)
|
|
22
|
+
return abortDecision;
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
let settled = false;
|
|
25
|
+
const onAbort = () => {
|
|
26
|
+
if (settled)
|
|
27
|
+
return;
|
|
28
|
+
settled = true;
|
|
29
|
+
resolve(abortDecision);
|
|
30
|
+
};
|
|
31
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
32
|
+
Promise.resolve(ctx.resumeHandler(request)).then((decision) => {
|
|
33
|
+
if (settled)
|
|
34
|
+
return;
|
|
35
|
+
settled = true;
|
|
36
|
+
signal.removeEventListener('abort', onAbort);
|
|
37
|
+
resolve(decision);
|
|
38
|
+
}, (err) => {
|
|
39
|
+
if (settled)
|
|
40
|
+
return;
|
|
41
|
+
settled = true;
|
|
42
|
+
signal.removeEventListener('abort', onAbort);
|
|
43
|
+
resolve({
|
|
44
|
+
action: 'abort',
|
|
45
|
+
reason: err instanceof Error ? err.message : 'resume handler failed',
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
1
50
|
export async function* handleHITLDecision(ctx, decision, checkpointId, context) {
|
|
2
51
|
switch (decision.action) {
|
|
3
52
|
case 'pause': {
|
|
@@ -44,6 +93,10 @@ export async function* handleHITLDecision(ctx, decision, checkpointId, context)
|
|
|
44
93
|
case 'approve_tools':
|
|
45
94
|
case 'modify_tools':
|
|
46
95
|
case 'reject_tools':
|
|
96
|
+
// 'answer_question' can only arrive misdirected at an iteration
|
|
97
|
+
// checkpoint (answers are consumed inside the ask_user_question
|
|
98
|
+
// tool's own park); treat it as a plain continue.
|
|
99
|
+
case 'answer_question':
|
|
47
100
|
return 'continue';
|
|
48
101
|
default: {
|
|
49
102
|
const _exhaustive = decision;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl-abort-race.test.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/hitl-abort-race.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { awaitDecisionOrAbort } from './context.js';
|
|
3
|
+
/**
|
|
4
|
+
* C12: a Stop that arrives while the run is parked on a HITL decision must
|
|
5
|
+
* interrupt the park (resolve as `abort`) instead of hanging until the host
|
|
6
|
+
* eventually answers. `awaitDecisionOrAbort` races `resumeHandler` against
|
|
7
|
+
* `ctx.abortController.signal`.
|
|
8
|
+
*/
|
|
9
|
+
function ctxWith(opts) {
|
|
10
|
+
return {
|
|
11
|
+
abortController: opts.controller,
|
|
12
|
+
resumeHandler: opts.resumeHandler,
|
|
13
|
+
runMgr: { id: 'run_abort_test' },
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const REVIEW_REQUEST = {
|
|
17
|
+
type: 'tool_review',
|
|
18
|
+
runId: 'run_abort_test',
|
|
19
|
+
checkpointId: 'cp_1',
|
|
20
|
+
toolCalls: [],
|
|
21
|
+
};
|
|
22
|
+
describe('awaitDecisionOrAbort (C12 — cancellable HITL park)', () => {
|
|
23
|
+
it('returns abort immediately when the signal is already aborted', async () => {
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
controller.abort();
|
|
26
|
+
const ctx = ctxWith({
|
|
27
|
+
controller,
|
|
28
|
+
// A handler that never resolves — proving we did not wait on it.
|
|
29
|
+
resumeHandler: () => new Promise(() => { }),
|
|
30
|
+
});
|
|
31
|
+
const decision = await awaitDecisionOrAbort(ctx, REVIEW_REQUEST);
|
|
32
|
+
expect(decision.action).toBe('abort');
|
|
33
|
+
});
|
|
34
|
+
it('resolves as abort when the signal fires DURING the park', async () => {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const ctx = ctxWith({
|
|
37
|
+
controller,
|
|
38
|
+
resumeHandler: () => new Promise(() => { }), // never answers
|
|
39
|
+
});
|
|
40
|
+
const pending = awaitDecisionOrAbort(ctx, REVIEW_REQUEST);
|
|
41
|
+
controller.abort();
|
|
42
|
+
const decision = await pending;
|
|
43
|
+
expect(decision.action).toBe('abort');
|
|
44
|
+
});
|
|
45
|
+
it('returns the real decision when the handler answers before any abort', async () => {
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
const ctx = ctxWith({
|
|
48
|
+
controller,
|
|
49
|
+
resumeHandler: async () => ({ action: 'approve_tools' }),
|
|
50
|
+
});
|
|
51
|
+
const decision = await awaitDecisionOrAbort(ctx, REVIEW_REQUEST);
|
|
52
|
+
expect(decision.action).toBe('approve_tools');
|
|
53
|
+
});
|
|
54
|
+
it('degrades to a direct resumeHandler await when no controller is wired', async () => {
|
|
55
|
+
const ctx = ctxWith({
|
|
56
|
+
resumeHandler: async () => ({ action: 'reject_tools' }),
|
|
57
|
+
});
|
|
58
|
+
const decision = await awaitDecisionOrAbort(ctx, REVIEW_REQUEST);
|
|
59
|
+
expect(decision.action).toBe('reject_tools');
|
|
60
|
+
});
|
|
61
|
+
it('fails closed to abort when the resume handler rejects', async () => {
|
|
62
|
+
const controller = new AbortController();
|
|
63
|
+
const ctx = ctxWith({
|
|
64
|
+
controller,
|
|
65
|
+
resumeHandler: async () => {
|
|
66
|
+
throw new Error('handler boom');
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
const decision = await awaitDecisionOrAbort(ctx, REVIEW_REQUEST);
|
|
70
|
+
expect(decision.action).toBe('abort');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=hitl-abort-race.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl-abort-race.test.js","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/hitl-abort-race.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl-answer-question.test.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/hitl-answer-question.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { autoApproveHandler } from '../../../../types/hitl/index.js';
|
|
3
|
+
import { handleHITLDecision } from './context.js';
|
|
4
|
+
import { runToolReview } from './tool-review.js';
|
|
5
|
+
async function drainGenerator(gen) {
|
|
6
|
+
const events = [];
|
|
7
|
+
let next = await gen.next();
|
|
8
|
+
while (!next.done) {
|
|
9
|
+
events.push(next.value);
|
|
10
|
+
next = await gen.next();
|
|
11
|
+
}
|
|
12
|
+
return { events, value: next.value };
|
|
13
|
+
}
|
|
14
|
+
describe('autoApproveHandler user_question case', () => {
|
|
15
|
+
it('returns the non-fabricating no-answer sentinel with the questionId echoed', async () => {
|
|
16
|
+
const decision = await autoApproveHandler({
|
|
17
|
+
type: 'user_question',
|
|
18
|
+
runId: 'run_headless_test',
|
|
19
|
+
checkpointId: 'cp_question_toolu_1',
|
|
20
|
+
question: {
|
|
21
|
+
questionId: 'toolu_1',
|
|
22
|
+
question: 'Pick one?',
|
|
23
|
+
options: [
|
|
24
|
+
{ id: 'opt_1', label: 'A' },
|
|
25
|
+
{ id: 'opt_2', label: 'B' },
|
|
26
|
+
],
|
|
27
|
+
multiSelect: false,
|
|
28
|
+
allowFreeText: true,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
expect(decision).toEqual({
|
|
32
|
+
action: 'answer_question',
|
|
33
|
+
selectedOptionIds: [],
|
|
34
|
+
freeText: 'No user is available to answer. Proceed using your best judgment.',
|
|
35
|
+
questionId: 'toolu_1',
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe('handleHITLDecision answer_question case', () => {
|
|
40
|
+
it("treats a misdirected 'answer_question' at an iteration checkpoint as continue", async () => {
|
|
41
|
+
// The branch returns without touching the context — answers are
|
|
42
|
+
// consumed inside the ask_user_question tool's own park, so an
|
|
43
|
+
// answer arriving here can only be misdirected.
|
|
44
|
+
const ctx = {};
|
|
45
|
+
const { events, value } = await drainGenerator(handleHITLDecision(ctx, { action: 'answer_question', selectedOptionIds: ['opt_1'] }, 'cp_checkpoint_1', 'iteration checkpoint'));
|
|
46
|
+
expect(value).toBe('continue');
|
|
47
|
+
expect(events).toEqual([]);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('runToolReview answer_question case', () => {
|
|
51
|
+
function reviewContext(decision) {
|
|
52
|
+
const warns = [];
|
|
53
|
+
const pushed = [];
|
|
54
|
+
let batches = 0;
|
|
55
|
+
const ctx = {
|
|
56
|
+
tools: { get: () => undefined },
|
|
57
|
+
checkpointMgr: {
|
|
58
|
+
create: async () => ({ id: 'cp_review_1' }),
|
|
59
|
+
},
|
|
60
|
+
emitEvent: async () => { },
|
|
61
|
+
drainPending: () => [][Symbol.iterator](),
|
|
62
|
+
resumeHandler: async () => decision,
|
|
63
|
+
log: {
|
|
64
|
+
debug: () => { },
|
|
65
|
+
info: () => { },
|
|
66
|
+
warn: (message) => {
|
|
67
|
+
warns.push(message);
|
|
68
|
+
},
|
|
69
|
+
error: () => { },
|
|
70
|
+
},
|
|
71
|
+
runMgr: {
|
|
72
|
+
id: 'run_tool_review_test',
|
|
73
|
+
pushMessage: (message) => {
|
|
74
|
+
pushed.push(message);
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
toolExecutor: {
|
|
78
|
+
executeBatch: async () => {
|
|
79
|
+
batches += 1;
|
|
80
|
+
return { messages: [], results: [] };
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
return { ctx, warns, pushed, batchCount: () => batches };
|
|
85
|
+
}
|
|
86
|
+
const response = {
|
|
87
|
+
id: 'resp_1',
|
|
88
|
+
model: 'test-model',
|
|
89
|
+
message: {
|
|
90
|
+
role: 'assistant',
|
|
91
|
+
content: null,
|
|
92
|
+
toolCalls: [
|
|
93
|
+
{
|
|
94
|
+
id: 'toolu_review_1',
|
|
95
|
+
type: 'function',
|
|
96
|
+
function: { name: 'ask_user_question', arguments: '{}' },
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
finishReason: 'tool_calls',
|
|
101
|
+
usage: {
|
|
102
|
+
promptTokens: 0,
|
|
103
|
+
completionTokens: 0,
|
|
104
|
+
totalTokens: 0,
|
|
105
|
+
cachedTokens: 0,
|
|
106
|
+
cacheWriteTokens: 0,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
it("warns and executes the batch on a misdirected 'answer_question' instead of stalling", async () => {
|
|
110
|
+
const { ctx, warns, batchCount } = reviewContext({
|
|
111
|
+
action: 'answer_question',
|
|
112
|
+
selectedOptionIds: [],
|
|
113
|
+
});
|
|
114
|
+
const { value } = await drainGenerator(runToolReview(ctx, response, 1));
|
|
115
|
+
expect(value).toBe('executed');
|
|
116
|
+
expect(batchCount()).toBe(1);
|
|
117
|
+
expect(warns).toHaveLength(1);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=hitl-answer-question.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl-answer-question.test.js","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/hitl-answer-question.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChatCompletionResponse } from '../../../../types/provider/index.js';
|
|
2
2
|
import type { RunEvent } from '../../../../types/run/index.js';
|
|
3
3
|
import type { VerificationGate } from '../../../../verification/index.js';
|
|
4
|
-
import type
|
|
4
|
+
import { type IterationContext } from './context.js';
|
|
5
5
|
interface VerificationAwareContext extends IterationContext {
|
|
6
6
|
readonly verificationGate?: VerificationGate;
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-review.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/tool-review.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"tool-review.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/tool-review.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,KAAK,gBAAgB,EAAwB,MAAM,cAAc,CAAA;AAE1E,UAAU,wBAAyB,SAAQ,gBAAgB;IAC1D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CAC5C;AAED,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAEhE,wBAAuB,aAAa,CACnC,GAAG,EAAE,wBAAwB,EAC7B,QAAQ,EAAE,sBAAsB,EAChC,YAAY,EAAE,MAAM,GAClB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CA8M7C"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createUserMessage } from '../../../../types/message/index.js';
|
|
2
|
+
import { awaitDecisionOrAbort } from './context.js';
|
|
2
3
|
export async function* runToolReview(ctx, response, iterationNum) {
|
|
3
4
|
const toolCalls = response.message.toolCalls;
|
|
4
5
|
if (!toolCalls || toolCalls.length === 0) {
|
|
@@ -68,7 +69,7 @@ export async function* runToolReview(ctx, response, iterationNum) {
|
|
|
68
69
|
iteration: iterationNum,
|
|
69
70
|
});
|
|
70
71
|
yield* ctx.drainPending();
|
|
71
|
-
const reviewDecision = await ctx
|
|
72
|
+
const reviewDecision = await awaitDecisionOrAbort(ctx, {
|
|
72
73
|
type: 'tool_review',
|
|
73
74
|
runId: ctx.runMgr.id,
|
|
74
75
|
checkpointId: reviewCheckpoint.id,
|
|
@@ -158,7 +159,11 @@ export async function* runToolReview(ctx, response, iterationNum) {
|
|
|
158
159
|
return 'executed';
|
|
159
160
|
}
|
|
160
161
|
case 'approve_plan':
|
|
161
|
-
case 'reject_plan':
|
|
162
|
+
case 'reject_plan':
|
|
163
|
+
// 'answer_question' belongs to an ask_user_question park, not a
|
|
164
|
+
// tool review — like the misdirected plan decisions above, warn
|
|
165
|
+
// and proceed with execution rather than stalling the run.
|
|
166
|
+
case 'answer_question': {
|
|
162
167
|
ctx.log.warn('Unexpected plan decision during tool review', {
|
|
163
168
|
action: reviewDecision.action,
|
|
164
169
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-review.js","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/tool-review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;
|
|
1
|
+
{"version":3,"file":"tool-review.js","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/tool-review.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for the ses_055 Layer-B SDK seam (#104):
|
|
3
|
+
*
|
|
4
|
+
* 1. **Compaction FIRES** under a small `contextWindowTokens` even with the
|
|
5
|
+
* run-level `tokenBudget = 0` (UNLIMITED) — proving the F1 fix repointed
|
|
6
|
+
* BOTH the `<= 0` guard AND the divisor, closing the silent-no-op trap.
|
|
7
|
+
* 2. **The pinned working-memory slot SURVIVES** the compaction pass (it is a
|
|
8
|
+
* leading system message → preserved by header identity).
|
|
9
|
+
* 3. **No premature stop** from `tokenBudget = 0` alone: with NO
|
|
10
|
+
* `contextWindowTokens`, the same overflowing run does NOT compact (the
|
|
11
|
+
* legacy fallback), so consumers that never set the new field are
|
|
12
|
+
* byte-identical.
|
|
13
|
+
*
|
|
14
|
+
* The test drives `refreshWorkingMemory` (to pin the slot) then
|
|
15
|
+
* `runCompactionCheck` directly against a mock `IterationContext`, which is the
|
|
16
|
+
* exact sequence the iteration loop runs each turn.
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=working-memory-compaction.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-memory-compaction.test.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/query/iteration/phases/working-memory-compaction.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for the ses_055 Layer-B SDK seam (#104):
|
|
3
|
+
*
|
|
4
|
+
* 1. **Compaction FIRES** under a small `contextWindowTokens` even with the
|
|
5
|
+
* run-level `tokenBudget = 0` (UNLIMITED) — proving the F1 fix repointed
|
|
6
|
+
* BOTH the `<= 0` guard AND the divisor, closing the silent-no-op trap.
|
|
7
|
+
* 2. **The pinned working-memory slot SURVIVES** the compaction pass (it is a
|
|
8
|
+
* leading system message → preserved by header identity).
|
|
9
|
+
* 3. **No premature stop** from `tokenBudget = 0` alone: with NO
|
|
10
|
+
* `contextWindowTokens`, the same overflowing run does NOT compact (the
|
|
11
|
+
* legacy fallback), so consumers that never set the new field are
|
|
12
|
+
* byte-identical.
|
|
13
|
+
*
|
|
14
|
+
* The test drives `refreshWorkingMemory` (to pin the slot) then
|
|
15
|
+
* `runCompactionCheck` directly against a mock `IterationContext`, which is the
|
|
16
|
+
* exact sequence the iteration loop runs each turn.
|
|
17
|
+
*/
|
|
18
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
19
|
+
import { findDanglingMessages } from '../../../../compaction/dangling.js';
|
|
20
|
+
import { WorkingStateManager } from '../../../../compaction/manager.js';
|
|
21
|
+
import { CompactionConfigSchema } from '../../../../config/runtime.js';
|
|
22
|
+
import { createAssistantMessage, createSystemMessage, createToolMessage, createUserMessage, } from '../../../../types/message/index.js';
|
|
23
|
+
import { runCompactionCheck } from './compaction.js';
|
|
24
|
+
import { WORKING_MEMORY_HEADER, refreshWorkingMemory } from './working-memory.js';
|
|
25
|
+
function makeLogger() {
|
|
26
|
+
const self = {
|
|
27
|
+
info: vi.fn(),
|
|
28
|
+
warn: vi.fn(),
|
|
29
|
+
error: vi.fn(),
|
|
30
|
+
debug: vi.fn(),
|
|
31
|
+
child: vi.fn(),
|
|
32
|
+
};
|
|
33
|
+
self.child = vi.fn(() => self);
|
|
34
|
+
return self;
|
|
35
|
+
}
|
|
36
|
+
/** A long string so a handful of messages overflow a small context window. */
|
|
37
|
+
const FILLER = 'x'.repeat(200);
|
|
38
|
+
function buildOverflowingMessages() {
|
|
39
|
+
const msgs = [createSystemMessage(`STATIC SYSTEM PROMPT ${FILLER}`, 'cache')];
|
|
40
|
+
for (let i = 0; i < 8; i++) {
|
|
41
|
+
msgs.push(createUserMessage(`user turn ${i} ${FILLER}`));
|
|
42
|
+
msgs.push(createAssistantMessage(`assistant turn ${i} ${FILLER}`));
|
|
43
|
+
}
|
|
44
|
+
return msgs;
|
|
45
|
+
}
|
|
46
|
+
function makeCtx(opts) {
|
|
47
|
+
const config = CompactionConfigSchema.parse({
|
|
48
|
+
strategy: 'structured',
|
|
49
|
+
llmVerification: false,
|
|
50
|
+
...(opts.contextWindowTokens !== undefined
|
|
51
|
+
? { contextWindowTokens: opts.contextWindowTokens }
|
|
52
|
+
: {}),
|
|
53
|
+
});
|
|
54
|
+
const manager = new WorkingStateManager(config);
|
|
55
|
+
// Seed a couple of slots so serializeState produces non-trivial output.
|
|
56
|
+
manager.addDecision('built the report as .docx');
|
|
57
|
+
return {
|
|
58
|
+
runConfig: { tokenBudget: 0 }, // UNLIMITED cumulative cost cap
|
|
59
|
+
compactionConfig: config,
|
|
60
|
+
workingStateManager: manager,
|
|
61
|
+
workingMemoryProvider: opts.workingMemoryProvider,
|
|
62
|
+
log: makeLogger(),
|
|
63
|
+
runMgr: {
|
|
64
|
+
id: 'run_1',
|
|
65
|
+
currentIteration: 3,
|
|
66
|
+
messages: opts.messages,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const WM_BLOCK = 'ARTIFACTS\n • report.docx · Word document · 48.2 KB · imp:H\n path: /mnt/user-data/outputs/report.docx';
|
|
71
|
+
describe('Layer-B compaction seam (ses_055 #104)', () => {
|
|
72
|
+
it('FIRES on small contextWindowTokens with tokenBudget=0 AND preserves the pinned WM slot', async () => {
|
|
73
|
+
const messages = buildOverflowingMessages();
|
|
74
|
+
const ctx = makeCtx({
|
|
75
|
+
messages,
|
|
76
|
+
contextWindowTokens: 100,
|
|
77
|
+
workingMemoryProvider: () => WM_BLOCK,
|
|
78
|
+
});
|
|
79
|
+
await refreshWorkingMemory(ctx);
|
|
80
|
+
// The slot is pinned as the last leading system message (index 1).
|
|
81
|
+
expect(messages[1]?.role).toBe('system');
|
|
82
|
+
expect(messages[1]?.content?.startsWith(WORKING_MEMORY_HEADER)).toBe(true);
|
|
83
|
+
const before = messages.length;
|
|
84
|
+
await runCompactionCheck(ctx);
|
|
85
|
+
// (1) compaction fired: a [COMPACTED CONTEXT] message appeared and the
|
|
86
|
+
// transcript shrank.
|
|
87
|
+
expect(messages.length).toBeLessThan(before);
|
|
88
|
+
expect(messages.some((m) => m.content?.includes('[COMPACTED CONTEXT]'))).toBe(true);
|
|
89
|
+
// (2) the pinned working-memory slot survived by header identity.
|
|
90
|
+
const wm = messages.filter((m) => m.role === 'system' && m.content?.startsWith(WORKING_MEMORY_HEADER));
|
|
91
|
+
expect(wm).toHaveLength(1);
|
|
92
|
+
expect(wm[0]?.content).toContain('report.docx');
|
|
93
|
+
});
|
|
94
|
+
it('does NOT compact when contextWindowTokens is absent and tokenBudget=0 (byte-identical fallback)', async () => {
|
|
95
|
+
const messages = buildOverflowingMessages();
|
|
96
|
+
const ctx = makeCtx({ messages });
|
|
97
|
+
const before = messages.length;
|
|
98
|
+
await runCompactionCheck(ctx);
|
|
99
|
+
// budget = tokenBudget = 0 → guard returns; no compaction, no mutation.
|
|
100
|
+
expect(messages.length).toBe(before);
|
|
101
|
+
expect(messages.some((m) => m.content?.includes('[COMPACTED CONTEXT]'))).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
it('removes the slot when the provider returns an empty block', async () => {
|
|
104
|
+
const messages = buildOverflowingMessages();
|
|
105
|
+
const ctx = makeCtx({
|
|
106
|
+
messages,
|
|
107
|
+
contextWindowTokens: 100,
|
|
108
|
+
workingMemoryProvider: () => WM_BLOCK,
|
|
109
|
+
});
|
|
110
|
+
await refreshWorkingMemory(ctx);
|
|
111
|
+
expect(messages.some((m) => m.content?.startsWith(WORKING_MEMORY_HEADER))).toBe(true);
|
|
112
|
+
// Same transcript, provider now returns blank ⇒ the slot is removed.
|
|
113
|
+
const blankCtx = makeCtx({
|
|
114
|
+
messages,
|
|
115
|
+
contextWindowTokens: 100,
|
|
116
|
+
workingMemoryProvider: () => ' ',
|
|
117
|
+
});
|
|
118
|
+
await refreshWorkingMemory(blankCtx);
|
|
119
|
+
expect(messages.some((m) => m.content?.startsWith(WORKING_MEMORY_HEADER))).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
it('keeps the prior slot when the provider throws (failure-isolated)', async () => {
|
|
122
|
+
const messages = buildOverflowingMessages();
|
|
123
|
+
const ctx = makeCtx({
|
|
124
|
+
messages,
|
|
125
|
+
contextWindowTokens: 100,
|
|
126
|
+
workingMemoryProvider: () => WM_BLOCK,
|
|
127
|
+
});
|
|
128
|
+
await refreshWorkingMemory(ctx);
|
|
129
|
+
const throwingCtx = makeCtx({
|
|
130
|
+
messages,
|
|
131
|
+
contextWindowTokens: 100,
|
|
132
|
+
workingMemoryProvider: () => {
|
|
133
|
+
throw new Error('provider boom');
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
await refreshWorkingMemory(throwingCtx);
|
|
137
|
+
// Prior slot retained; run not broken.
|
|
138
|
+
expect(messages.some((m) => m.content?.startsWith(WORKING_MEMORY_HEADER))).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
it('does NOT orphan a tool_result when the recent-window cut splits a tool pair (C1)', async () => {
|
|
141
|
+
// keepRecentMessages defaults to 4. Lay the transcript out so the NAIVE
|
|
142
|
+
// cut (length - 4 = index 5) lands right AFTER the assistant-with-toolCall
|
|
143
|
+
// (index 4) but BEFORE... no — exactly ON its tool result (index 5), which
|
|
144
|
+
// a naive slice would keep in the recent window while dropping the
|
|
145
|
+
// assistant into the summarized older set → an orphaned tool_result at the
|
|
146
|
+
// head of the recent window → Anthropic 400. The fix snaps keepStart
|
|
147
|
+
// forward past the complete pair.
|
|
148
|
+
const toolCall = {
|
|
149
|
+
id: 't1',
|
|
150
|
+
type: 'function',
|
|
151
|
+
function: { name: 'read', arguments: '{}' },
|
|
152
|
+
};
|
|
153
|
+
const messages = [
|
|
154
|
+
createSystemMessage(`STATIC SYSTEM PROMPT ${FILLER}`, 'cache'),
|
|
155
|
+
createUserMessage(`user 0 ${FILLER}`),
|
|
156
|
+
createAssistantMessage(`assistant 0 ${FILLER}`),
|
|
157
|
+
createUserMessage(`user 1 ${FILLER}`),
|
|
158
|
+
createAssistantMessage(`calling a tool ${FILLER}`, [toolCall]), // idx 4
|
|
159
|
+
createToolMessage(`tool result ${FILLER}`, 't1'), // idx 5 — naive recent[0]
|
|
160
|
+
createAssistantMessage(`assistant 2 ${FILLER}`),
|
|
161
|
+
createUserMessage(`user 3 ${FILLER}`),
|
|
162
|
+
createAssistantMessage(`assistant 3 ${FILLER}`),
|
|
163
|
+
];
|
|
164
|
+
const ctx = makeCtx({ messages, contextWindowTokens: 100 });
|
|
165
|
+
await runCompactionCheck(ctx);
|
|
166
|
+
// Compaction fired.
|
|
167
|
+
expect(messages.some((m) => m.content?.includes('[COMPACTED CONTEXT]'))).toBe(true);
|
|
168
|
+
// The surviving transcript has NO dangling tool pair — the tool result
|
|
169
|
+
// whose assistant was summarized away was moved into the older set too,
|
|
170
|
+
// so no orphaned tool_result remains to 400 the next provider turn.
|
|
171
|
+
expect(findDanglingMessages(messages).isValid).toBe(true);
|
|
172
|
+
// And a `tool` message never leads the recent window.
|
|
173
|
+
const firstNonSystem = messages.find((m) => m.role !== 'system');
|
|
174
|
+
expect(firstNonSystem?.role).not.toBe('tool');
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=working-memory-compaction.test.js.map
|