@namzu/sdk 0.1.4 → 0.1.5-rc.1
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/advisory/executor.d.ts +2 -2
- package/dist/advisory/executor.d.ts.map +1 -1
- package/dist/advisory/executor.js.map +1 -1
- package/dist/agents/AbstractAgent.d.ts +20 -2
- package/dist/agents/AbstractAgent.d.ts.map +1 -1
- package/dist/agents/AbstractAgent.js +23 -1
- package/dist/agents/AbstractAgent.js.map +1 -1
- package/dist/agents/PipelineAgent.d.ts.map +1 -1
- package/dist/agents/PipelineAgent.js +1 -1
- package/dist/agents/PipelineAgent.js.map +1 -1
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +1 -0
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/RouterAgent.d.ts.map +1 -1
- package/dist/agents/RouterAgent.js +4 -2
- package/dist/agents/RouterAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +4 -1
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/__tests__/lock.test.d.ts +2 -0
- package/dist/agents/__tests__/lock.test.d.ts.map +1 -0
- package/dist/agents/__tests__/lock.test.js +131 -0
- package/dist/agents/__tests__/lock.test.js.map +1 -0
- package/dist/agents/index.d.ts +2 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +1 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/lock.d.ts +42 -0
- package/dist/agents/lock.d.ts.map +1 -0
- package/dist/agents/lock.js +54 -0
- package/dist/agents/lock.js.map +1 -0
- package/dist/bridge/a2a/message.d.ts.map +1 -1
- package/dist/bridge/a2a/message.js.map +1 -1
- package/dist/bridge/tools/connector/router.d.ts +4 -5
- package/dist/bridge/tools/connector/router.d.ts.map +1 -1
- package/dist/bridge/tools/connector/router.js.map +1 -1
- package/dist/compaction/__tests__/SlidingWindowManager.test.d.ts +2 -0
- package/dist/compaction/__tests__/SlidingWindowManager.test.d.ts.map +1 -0
- package/dist/compaction/__tests__/SlidingWindowManager.test.js +113 -0
- package/dist/compaction/__tests__/SlidingWindowManager.test.js.map +1 -0
- package/dist/compaction/__tests__/dangling.test.d.ts +2 -0
- package/dist/compaction/__tests__/dangling.test.d.ts.map +1 -0
- package/dist/compaction/__tests__/dangling.test.js +356 -0
- package/dist/compaction/__tests__/dangling.test.js.map +1 -0
- package/dist/compaction/__tests__/factory.test.d.ts +2 -0
- package/dist/compaction/__tests__/factory.test.d.ts.map +1 -0
- package/dist/compaction/__tests__/factory.test.js +43 -0
- package/dist/compaction/__tests__/factory.test.js.map +1 -0
- package/dist/compaction/dangling.d.ts +96 -0
- package/dist/compaction/dangling.d.ts.map +1 -0
- package/dist/compaction/dangling.js +274 -0
- package/dist/compaction/dangling.js.map +1 -0
- package/dist/compaction/factory.d.ts +20 -0
- package/dist/compaction/factory.d.ts.map +1 -0
- package/dist/compaction/factory.js +35 -0
- package/dist/compaction/factory.js.map +1 -0
- package/dist/compaction/index.d.ts +5 -0
- package/dist/compaction/index.d.ts.map +1 -1
- package/dist/compaction/index.js +3 -0
- package/dist/compaction/index.js.map +1 -1
- package/dist/compaction/interface.d.ts +33 -0
- package/dist/compaction/interface.d.ts.map +1 -0
- package/dist/compaction/interface.js +2 -0
- package/dist/compaction/interface.js.map +1 -0
- package/dist/compaction/managers/index.d.ts +4 -0
- package/dist/compaction/managers/index.d.ts.map +1 -0
- package/dist/compaction/managers/index.js +4 -0
- package/dist/compaction/managers/index.js.map +1 -0
- package/dist/compaction/managers/null.d.ts +12 -0
- package/dist/compaction/managers/null.d.ts.map +1 -0
- package/dist/compaction/managers/null.js +15 -0
- package/dist/compaction/managers/null.js.map +1 -0
- package/dist/compaction/managers/slidingWindow.d.ts +27 -0
- package/dist/compaction/managers/slidingWindow.d.ts.map +1 -0
- package/dist/compaction/managers/slidingWindow.js +41 -0
- package/dist/compaction/managers/slidingWindow.js.map +1 -0
- package/dist/compaction/managers/structured.d.ts +23 -0
- package/dist/compaction/managers/structured.d.ts.map +1 -0
- package/dist/compaction/managers/structured.js +144 -0
- package/dist/compaction/managers/structured.js.map +1 -0
- package/dist/compaction/types.d.ts +1 -1
- package/dist/compaction/types.d.ts.map +1 -1
- package/dist/config/runtime.d.ts +16 -16
- package/dist/config/runtime.js +1 -1
- package/dist/config/runtime.js.map +1 -1
- package/dist/constants/agent/index.d.ts +1 -1
- package/dist/constants/agent/index.d.ts.map +1 -1
- package/dist/gateway/local.d.ts +2 -2
- package/dist/gateway/local.d.ts.map +1 -1
- package/dist/gateway/local.js +10 -1
- package/dist/gateway/local.js.map +1 -1
- package/dist/index.d.ts +18 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +3 -2
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +1 -2
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +2 -1
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/plugin/__tests__/lifecycle.test.d.ts +2 -0
- package/dist/plugin/__tests__/lifecycle.test.d.ts.map +1 -0
- package/dist/plugin/__tests__/lifecycle.test.js +332 -0
- package/dist/plugin/__tests__/lifecycle.test.js.map +1 -0
- package/dist/plugin/lifecycle.d.ts +2 -2
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +28 -2
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/plugin/resolver.d.ts +2 -2
- package/dist/plugin/resolver.d.ts.map +1 -1
- package/dist/plugin/resolver.js.map +1 -1
- package/dist/registry/agent/definitions.d.ts +3 -2
- package/dist/registry/agent/definitions.d.ts.map +1 -1
- package/dist/registry/agent/definitions.js.map +1 -1
- package/dist/registry/tool/execute.d.ts +2 -5
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/runtime/decision/parser.d.ts.map +1 -1
- package/dist/runtime/decision/parser.js +15 -40
- package/dist/runtime/decision/parser.js.map +1 -1
- package/dist/runtime/query/context-cache.d.ts +3 -3
- package/dist/runtime/query/context-cache.d.ts.map +1 -1
- package/dist/runtime/query/context-cache.js.map +1 -1
- package/dist/runtime/query/context.d.ts +1 -1
- package/dist/runtime/query/context.d.ts.map +1 -1
- package/dist/runtime/query/context.js.map +1 -1
- package/dist/runtime/query/events.js +11 -11
- package/dist/runtime/query/events.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +4 -2
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +1 -0
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +5 -3
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +2 -1
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +2 -2
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
- package/dist/runtime/query/iteration/phases/checkpoint.d.ts +1 -1
- package/dist/runtime/query/iteration/phases/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/checkpoint.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +2 -2
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/plan.d.ts +1 -1
- package/dist/runtime/query/iteration/phases/plan.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/plan.js.map +1 -1
- package/dist/runtime/query/prompt.d.ts +2 -2
- package/dist/runtime/query/prompt.d.ts.map +1 -1
- package/dist/runtime/query/prompt.js.map +1 -1
- package/dist/runtime/query/result.d.ts +1 -1
- package/dist/runtime/query/result.d.ts.map +1 -1
- package/dist/runtime/query/result.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +4 -2
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +1 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/store/conversation/memory.d.ts +1 -1
- package/dist/store/conversation/memory.d.ts.map +1 -1
- package/dist/store/conversation/memory.js +15 -3
- package/dist/store/conversation/memory.js.map +1 -1
- package/dist/store/run/disk.d.ts +1 -2
- package/dist/store/run/disk.d.ts.map +1 -1
- package/dist/store/run/disk.js +21 -13
- package/dist/store/run/disk.js.map +1 -1
- package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +140 -0
- package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts.map +1 -0
- package/dist/tools/builtins/__tests__/structuredOutput.example.js +183 -0
- package/dist/tools/builtins/__tests__/structuredOutput.example.js.map +1 -0
- package/dist/tools/builtins/__tests__/structuredOutput.test.d.ts +2 -0
- package/dist/tools/builtins/__tests__/structuredOutput.test.d.ts.map +1 -0
- package/dist/tools/builtins/__tests__/structuredOutput.test.js +224 -0
- package/dist/tools/builtins/__tests__/structuredOutput.test.js.map +1 -0
- package/dist/tools/builtins/grep.d.ts.map +1 -1
- package/dist/tools/builtins/grep.js +1 -2
- package/dist/tools/builtins/grep.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +1 -0
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +3 -0
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/ls.d.ts +1 -1
- package/dist/tools/builtins/structuredOutput.d.ts +27 -0
- package/dist/tools/builtins/structuredOutput.d.ts.map +1 -0
- package/dist/tools/builtins/structuredOutput.js +46 -0
- package/dist/tools/builtins/structuredOutput.js.map +1 -0
- package/dist/tools/task/list.d.ts +1 -1
- package/dist/tools/task/list.d.ts.map +1 -1
- package/dist/tools/task/list.js.map +1 -1
- package/dist/types/agent/base.d.ts +4 -1
- package/dist/types/agent/base.d.ts.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/manager.d.ts +27 -0
- package/dist/types/agent/manager.d.ts.map +1 -0
- package/dist/types/agent/manager.js +2 -0
- package/dist/types/agent/manager.js.map +1 -0
- package/dist/types/agent/reactive.d.ts +2 -2
- package/dist/types/agent/reactive.d.ts.map +1 -1
- package/dist/types/agent/supervisor.d.ts +2 -2
- package/dist/types/agent/supervisor.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +0 -2
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/agent/task.js +0 -2
- package/dist/types/agent/task.js.map +1 -1
- package/dist/types/common/index.d.ts +0 -1
- package/dist/types/common/index.d.ts.map +1 -1
- package/dist/types/common/index.js +0 -1
- package/dist/types/common/index.js.map +1 -1
- package/dist/types/hitl/index.d.ts +1 -2
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/invocation/__tests__/state.test.d.ts +2 -0
- package/dist/types/invocation/__tests__/state.test.d.ts.map +1 -0
- package/dist/types/invocation/__tests__/state.test.js +167 -0
- package/dist/types/invocation/__tests__/state.test.js.map +1 -0
- package/dist/types/invocation/index.d.ts +37 -0
- package/dist/types/invocation/index.d.ts.map +1 -0
- package/dist/types/invocation/index.js +23 -0
- package/dist/types/invocation/index.js.map +1 -0
- package/dist/types/plugin/index.d.ts +6 -0
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/plugin/index.js +16 -0
- package/dist/types/plugin/index.js.map +1 -1
- package/dist/types/run/events.d.ts +1 -1
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/index.d.ts +1 -0
- package/dist/types/run/index.d.ts.map +1 -1
- package/dist/types/run/index.js +1 -0
- package/dist/types/run/index.js.map +1 -1
- package/dist/types/run/metadata.d.ts +1 -1
- package/dist/types/run/metadata.d.ts.map +1 -1
- package/dist/types/run/state.d.ts +1 -1
- package/dist/types/run/state.d.ts.map +1 -1
- package/dist/types/run/stop-reason.d.ts +2 -0
- package/dist/types/run/stop-reason.d.ts.map +1 -0
- package/dist/types/run/stop-reason.js +2 -0
- package/dist/types/run/stop-reason.js.map +1 -0
- package/dist/types/structured-output/index.d.ts +51 -0
- package/dist/types/structured-output/index.d.ts.map +1 -0
- package/dist/types/structured-output/index.js +2 -0
- package/dist/types/structured-output/index.js.map +1 -0
- package/dist/types/tool/index.d.ts +36 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/advisory/executor.ts +2 -4
- package/src/agents/AbstractAgent.ts +26 -3
- package/src/agents/PipelineAgent.ts +1 -1
- package/src/agents/ReactiveAgent.ts +1 -0
- package/src/agents/RouterAgent.ts +8 -2
- package/src/agents/SupervisorAgent.ts +5 -1
- package/src/agents/__tests__/lock.test.ts +158 -0
- package/src/agents/index.ts +2 -0
- package/src/agents/lock.ts +66 -0
- package/src/bridge/a2a/message.ts +1 -2
- package/src/bridge/tools/connector/router.ts +4 -5
- package/src/compaction/__tests__/SlidingWindowManager.test.ts +139 -0
- package/src/compaction/__tests__/dangling.test.ts +447 -0
- package/src/compaction/__tests__/factory.test.ts +53 -0
- package/src/compaction/dangling.ts +321 -0
- package/src/compaction/factory.ts +41 -0
- package/src/compaction/index.ts +14 -0
- package/src/compaction/interface.ts +35 -0
- package/src/compaction/managers/index.ts +3 -0
- package/src/compaction/managers/null.ts +19 -0
- package/src/compaction/managers/slidingWindow.ts +57 -0
- package/src/compaction/managers/structured.ts +169 -0
- package/src/compaction/types.ts +1 -1
- package/src/config/runtime.ts +1 -1
- package/src/constants/agent/index.ts +1 -1
- package/src/gateway/local.ts +13 -4
- package/src/index.ts +38 -1
- package/src/manager/agent/lifecycle.ts +3 -2
- package/src/manager/run/persistence.ts +3 -8
- package/src/plugin/__tests__/lifecycle.test.ts +430 -0
- package/src/plugin/lifecycle.ts +32 -6
- package/src/plugin/resolver.ts +3 -3
- package/src/registry/agent/definitions.ts +3 -2
- package/src/registry/tool/execute.ts +2 -5
- package/src/runtime/decision/parser.ts +15 -40
- package/src/runtime/query/context-cache.ts +3 -4
- package/src/runtime/query/context.ts +1 -2
- package/src/runtime/query/events.ts +11 -11
- package/src/runtime/query/executor.ts +5 -3
- package/src/runtime/query/index.ts +11 -4
- package/src/runtime/query/iteration/index.ts +2 -2
- package/src/runtime/query/iteration/phases/advisory.ts +1 -2
- package/src/runtime/query/iteration/phases/checkpoint.ts +1 -2
- package/src/runtime/query/iteration/phases/context.ts +2 -2
- package/src/runtime/query/iteration/phases/plan.ts +1 -2
- package/src/runtime/query/prompt.ts +3 -3
- package/src/runtime/query/result.ts +1 -2
- package/src/runtime/query/tooling.ts +5 -2
- package/src/store/conversation/memory.ts +21 -5
- package/src/store/run/disk.ts +18 -16
- package/src/tools/builtins/__tests__/structuredOutput.example.ts +221 -0
- package/src/tools/builtins/__tests__/structuredOutput.test.ts +275 -0
- package/src/tools/builtins/grep.ts +1 -2
- package/src/tools/builtins/index.ts +3 -0
- package/src/tools/builtins/structuredOutput.ts +55 -0
- package/src/tools/task/list.ts +1 -2
- package/src/types/agent/base.ts +5 -1
- package/src/types/agent/index.ts +1 -0
- package/src/types/agent/manager.ts +36 -0
- package/src/types/agent/reactive.ts +2 -2
- package/src/types/agent/supervisor.ts +2 -2
- package/src/types/agent/task.ts +0 -4
- package/src/types/common/index.ts +0 -2
- package/src/types/hitl/index.ts +1 -2
- package/src/types/invocation/__tests__/state.test.ts +210 -0
- package/src/types/invocation/index.ts +55 -0
- package/src/types/plugin/index.ts +19 -0
- package/src/types/run/events.ts +1 -10
- package/src/types/run/index.ts +1 -0
- package/src/types/run/metadata.ts +1 -1
- package/src/types/run/state.ts +1 -1
- package/src/types/run/stop-reason.ts +10 -0
- package/src/types/structured-output/index.ts +56 -0
- package/src/types/tool/index.ts +45 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { EMPTY_TOKEN_USAGE } from '../constants/limits.js'
|
|
2
2
|
import type {
|
|
3
3
|
Agent,
|
|
4
4
|
AgentCapabilities,
|
|
@@ -8,13 +8,14 @@ import type {
|
|
|
8
8
|
BaseAgentConfig,
|
|
9
9
|
BaseAgentResult,
|
|
10
10
|
} from '../types/agent/index.js'
|
|
11
|
-
import {
|
|
11
|
+
import type { AgentManagerContract } from '../types/agent/manager.js'
|
|
12
12
|
import type { RunId } from '../types/ids/index.js'
|
|
13
13
|
import type { RunEvent, RunEventListener } from '../types/run/index.js'
|
|
14
14
|
import { ZERO_COST } from '../utils/cost.js'
|
|
15
15
|
import { toErrorMessage } from '../utils/error.js'
|
|
16
16
|
import { generateRunId } from '../utils/id.js'
|
|
17
17
|
import { type Logger, getRootLogger } from '../utils/logger.js'
|
|
18
|
+
import { InvocationLock } from './lock.js'
|
|
18
19
|
|
|
19
20
|
export abstract class AbstractAgent<
|
|
20
21
|
TConfig extends BaseAgentConfig = BaseAgentConfig,
|
|
@@ -25,14 +26,16 @@ export abstract class AbstractAgent<
|
|
|
25
26
|
readonly metadata: AgentMetadata
|
|
26
27
|
protected log: Logger
|
|
27
28
|
protected abortController: AbortController
|
|
29
|
+
private readonly invocationLock: InvocationLock
|
|
28
30
|
|
|
29
|
-
protected agentManager?:
|
|
31
|
+
protected agentManager?: AgentManagerContract
|
|
30
32
|
|
|
31
33
|
protected currentRunId?: RunId
|
|
32
34
|
|
|
33
35
|
constructor(metadata: AgentMetadata) {
|
|
34
36
|
this.metadata = metadata
|
|
35
37
|
this.abortController = new AbortController()
|
|
38
|
+
this.invocationLock = new InvocationLock()
|
|
36
39
|
this.log = getRootLogger().child({
|
|
37
40
|
component: `Agent:${metadata.type}`,
|
|
38
41
|
agentId: metadata.id,
|
|
@@ -41,6 +44,26 @@ export abstract class AbstractAgent<
|
|
|
41
44
|
|
|
42
45
|
abstract run(input: AgentInput, config: TConfig, listener?: RunEventListener): Promise<TResult>
|
|
43
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Acquire the invocation lock to prevent concurrent execution.
|
|
49
|
+
* Returns a Disposable that must be disposed to release the lock.
|
|
50
|
+
*
|
|
51
|
+
* Usage:
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const lock = this.acquireInvocationLock()
|
|
54
|
+
* try {
|
|
55
|
+
* // do work
|
|
56
|
+
* } finally {
|
|
57
|
+
* lock[Symbol.dispose]()
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @throws {ConcurrentInvocationError} if the agent is already executing
|
|
62
|
+
*/
|
|
63
|
+
protected acquireInvocationLock() {
|
|
64
|
+
return this.invocationLock.acquire(this.metadata.id)
|
|
65
|
+
}
|
|
66
|
+
|
|
44
67
|
async cancel(): Promise<void> {
|
|
45
68
|
this.abortController.abort()
|
|
46
69
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EMPTY_TOKEN_USAGE } from '../constants/limits.js'
|
|
1
2
|
import type {
|
|
2
3
|
AgentInput,
|
|
3
4
|
AgentMetadata,
|
|
@@ -6,7 +7,6 @@ import type {
|
|
|
6
7
|
PipelineStepResult,
|
|
7
8
|
StepContext,
|
|
8
9
|
} from '../types/agent/index.js'
|
|
9
|
-
import { EMPTY_TOKEN_USAGE } from '../types/common/index.js'
|
|
10
10
|
import type { RunEventListener } from '../types/run/index.js'
|
|
11
11
|
import { ZERO_COST } from '../utils/cost.js'
|
|
12
12
|
import { toErrorMessage } from '../utils/error.js'
|
|
@@ -67,6 +67,7 @@ export class ReactiveAgent extends AbstractAgent<ReactiveAgentConfig, ReactiveAg
|
|
|
67
67
|
taskStore: input.taskStore,
|
|
68
68
|
runtimeToolOverrides: input.runtimeToolOverrides,
|
|
69
69
|
advisory: config.advisory,
|
|
70
|
+
invocationState: config.invocationState,
|
|
70
71
|
},
|
|
71
72
|
listener,
|
|
72
73
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EMPTY_TOKEN_USAGE } from '../constants/limits.js'
|
|
1
2
|
import { FallbackResolver } from '../runtime/decision/fallback.js'
|
|
2
3
|
import { DecisionParser } from '../runtime/decision/parser.js'
|
|
3
4
|
import type {
|
|
@@ -7,8 +8,8 @@ import type {
|
|
|
7
8
|
RouterAgentResult,
|
|
8
9
|
RoutingDecision,
|
|
9
10
|
} from '../types/agent/index.js'
|
|
10
|
-
import { EMPTY_TOKEN_USAGE } from '../types/common/index.js'
|
|
11
11
|
import type { FallbackStrategy } from '../types/decision/index.js'
|
|
12
|
+
import { deriveChildState } from '../types/invocation/index.js'
|
|
12
13
|
import { createSystemMessage, createUserMessage } from '../types/message/index.js'
|
|
13
14
|
import type { RunEventListener } from '../types/run/index.js'
|
|
14
15
|
import { ZERO_COST } from '../utils/cost.js'
|
|
@@ -83,7 +84,12 @@ export class RouterAgent extends AbstractAgent<RouterAgentConfig, RouterAgentRes
|
|
|
83
84
|
targetRoute = fallback
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
const
|
|
87
|
+
const childInvocationState = deriveChildState(config.invocationState, this.metadata.id)
|
|
88
|
+
const delegateResult = await targetRoute.agent.run(
|
|
89
|
+
input,
|
|
90
|
+
{ ...config, invocationState: childInvocationState },
|
|
91
|
+
listener,
|
|
92
|
+
)
|
|
87
93
|
|
|
88
94
|
await this.emitEvent(
|
|
89
95
|
{
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EMPTY_TOKEN_USAGE } from '../constants/limits.js'
|
|
1
2
|
import { LocalTaskGateway } from '../gateway/local.js'
|
|
2
3
|
import { ToolRegistry } from '../registry/tool/execute.js'
|
|
3
4
|
import { drainQuery } from '../runtime/query/index.js'
|
|
@@ -11,8 +12,8 @@ import type {
|
|
|
11
12
|
SupervisorAgentResult,
|
|
12
13
|
} from '../types/agent/index.js'
|
|
13
14
|
import type { AgentTaskContext } from '../types/agent/task.js'
|
|
14
|
-
import { EMPTY_TOKEN_USAGE } from '../types/common/index.js'
|
|
15
15
|
import type { TaskId, ThreadId } from '../types/ids/index.js'
|
|
16
|
+
import { deriveChildState } from '../types/invocation/index.js'
|
|
16
17
|
import type { RunEventListener } from '../types/run/index.js'
|
|
17
18
|
import { ZERO_COST } from '../utils/cost.js'
|
|
18
19
|
import { AbstractAgent } from './AbstractAgent.js'
|
|
@@ -98,6 +99,8 @@ export class SupervisorAgent extends AbstractAgent<SupervisorAgentConfig, Superv
|
|
|
98
99
|
tools.register(tool)
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
const childInvocationState = deriveChildState(config.invocationState, this.metadata.id)
|
|
103
|
+
|
|
101
104
|
const run = await drainQuery(
|
|
102
105
|
{
|
|
103
106
|
systemPrompt: config.systemPrompt,
|
|
@@ -129,6 +132,7 @@ export class SupervisorAgent extends AbstractAgent<SupervisorAgentConfig, Superv
|
|
|
129
132
|
taskGateway: gateway,
|
|
130
133
|
launchedTasks,
|
|
131
134
|
advisory: config.advisory,
|
|
135
|
+
invocationState: childInvocationState,
|
|
132
136
|
},
|
|
133
137
|
listener,
|
|
134
138
|
)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { ConcurrentInvocationError, InvocationLock } from '../lock.js'
|
|
3
|
+
|
|
4
|
+
describe('InvocationLock', () => {
|
|
5
|
+
describe('acquire', () => {
|
|
6
|
+
it('should acquire lock when not locked', () => {
|
|
7
|
+
const lock = new InvocationLock()
|
|
8
|
+
const agentId = 'agent-123'
|
|
9
|
+
|
|
10
|
+
const disposable = lock.acquire(agentId)
|
|
11
|
+
|
|
12
|
+
expect(disposable).toBeDefined()
|
|
13
|
+
expect(disposable[Symbol.dispose]).toBeDefined()
|
|
14
|
+
expect(lock.isActive()).toBe(true)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should throw ConcurrentInvocationError when already locked', () => {
|
|
18
|
+
const lock = new InvocationLock()
|
|
19
|
+
const agentId = 'agent-123'
|
|
20
|
+
|
|
21
|
+
lock.acquire(agentId)
|
|
22
|
+
|
|
23
|
+
expect(() => lock.acquire(agentId)).toThrow(ConcurrentInvocationError)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('should throw with correct agent ID in error', () => {
|
|
27
|
+
const lock = new InvocationLock()
|
|
28
|
+
const agentId = 'agent-456'
|
|
29
|
+
|
|
30
|
+
lock.acquire(agentId)
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
lock.acquire(agentId)
|
|
34
|
+
expect.fail('Should have thrown ConcurrentInvocationError')
|
|
35
|
+
} catch (err) {
|
|
36
|
+
if (err instanceof ConcurrentInvocationError) {
|
|
37
|
+
expect(err.agentId).toBe(agentId)
|
|
38
|
+
expect(err.message).toContain(agentId)
|
|
39
|
+
} else {
|
|
40
|
+
throw err
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('dispose', () => {
|
|
47
|
+
it('should release lock when disposed', () => {
|
|
48
|
+
const lock = new InvocationLock()
|
|
49
|
+
const agentId = 'agent-123'
|
|
50
|
+
|
|
51
|
+
const disposable = lock.acquire(agentId)
|
|
52
|
+
expect(lock.isActive()).toBe(true)
|
|
53
|
+
|
|
54
|
+
disposable[Symbol.dispose]()
|
|
55
|
+
expect(lock.isActive()).toBe(false)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('should allow re-acquisition after disposal', () => {
|
|
59
|
+
const lock = new InvocationLock()
|
|
60
|
+
const agentId = 'agent-123'
|
|
61
|
+
|
|
62
|
+
const disposable1 = lock.acquire(agentId)
|
|
63
|
+
disposable1[Symbol.dispose]()
|
|
64
|
+
|
|
65
|
+
// Should not throw
|
|
66
|
+
const disposable2 = lock.acquire(agentId)
|
|
67
|
+
expect(disposable2).toBeDefined()
|
|
68
|
+
expect(lock.isActive()).toBe(true)
|
|
69
|
+
|
|
70
|
+
disposable2[Symbol.dispose]()
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
describe('isActive', () => {
|
|
75
|
+
it('should return false when not locked', () => {
|
|
76
|
+
const lock = new InvocationLock()
|
|
77
|
+
expect(lock.isActive()).toBe(false)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('should return true when locked', () => {
|
|
81
|
+
const lock = new InvocationLock()
|
|
82
|
+
lock.acquire('agent-123')
|
|
83
|
+
expect(lock.isActive()).toBe(true)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('should return false after disposal', () => {
|
|
87
|
+
const lock = new InvocationLock()
|
|
88
|
+
const disposable = lock.acquire('agent-123')
|
|
89
|
+
expect(lock.isActive()).toBe(true)
|
|
90
|
+
|
|
91
|
+
disposable[Symbol.dispose]()
|
|
92
|
+
expect(lock.isActive()).toBe(false)
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe('try/finally pattern', () => {
|
|
97
|
+
it('should release lock in finally block', () => {
|
|
98
|
+
const lock = new InvocationLock()
|
|
99
|
+
const agentId = 'agent-123'
|
|
100
|
+
|
|
101
|
+
const disposable = lock.acquire(agentId)
|
|
102
|
+
try {
|
|
103
|
+
expect(lock.isActive()).toBe(true)
|
|
104
|
+
} finally {
|
|
105
|
+
disposable[Symbol.dispose]()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
expect(lock.isActive()).toBe(false)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('should release lock even if error thrown', () => {
|
|
112
|
+
const lock = new InvocationLock()
|
|
113
|
+
const agentId = 'agent-123'
|
|
114
|
+
|
|
115
|
+
const disposable = lock.acquire(agentId)
|
|
116
|
+
try {
|
|
117
|
+
throw new Error('Test error')
|
|
118
|
+
} catch {
|
|
119
|
+
disposable[Symbol.dispose]()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
expect(lock.isActive()).toBe(false)
|
|
123
|
+
|
|
124
|
+
// Should be able to acquire again
|
|
125
|
+
const disposable2 = lock.acquire(agentId)
|
|
126
|
+
expect(disposable2).toBeDefined()
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
describe('ConcurrentInvocationError', () => {
|
|
132
|
+
it('should be an instance of Error', () => {
|
|
133
|
+
const error = new ConcurrentInvocationError('agent-123')
|
|
134
|
+
expect(error).toBeInstanceOf(Error)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('should have correct name', () => {
|
|
138
|
+
const error = new ConcurrentInvocationError('agent-123')
|
|
139
|
+
expect(error.name).toBe('ConcurrentInvocationError')
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('should store agentId', () => {
|
|
143
|
+
const agentId = 'agent-abc'
|
|
144
|
+
const error = new ConcurrentInvocationError(agentId)
|
|
145
|
+
expect(error.agentId).toBe(agentId)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('should include agent ID in message', () => {
|
|
149
|
+
const agentId = 'agent-xyz'
|
|
150
|
+
const error = new ConcurrentInvocationError(agentId)
|
|
151
|
+
expect(error.message).toContain(agentId)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('should mention concurrent invocations in message', () => {
|
|
155
|
+
const error = new ConcurrentInvocationError('agent-123')
|
|
156
|
+
expect(error.message.toLowerCase()).toContain('concurrent')
|
|
157
|
+
})
|
|
158
|
+
})
|
package/src/agents/index.ts
CHANGED
|
@@ -5,3 +5,5 @@ export { RouterAgent } from './RouterAgent.js'
|
|
|
5
5
|
export { SupervisorAgent } from './SupervisorAgent.js'
|
|
6
6
|
export { defineAgent } from './defineAgent.js'
|
|
7
7
|
export type { DefineAgentOptions } from './defineAgent.js'
|
|
8
|
+
export { InvocationLock, ConcurrentInvocationError } from './lock.js'
|
|
9
|
+
export type { ConcurrencyMode, Disposable } from './lock.js'
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invocation lock to prevent concurrent execution of the same agent instance.
|
|
3
|
+
* Uses a simple boolean flag with RAII-style cleanup via Disposable pattern.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type ConcurrencyMode = 'throw' | 'queue'
|
|
7
|
+
|
|
8
|
+
export interface Disposable {
|
|
9
|
+
[Symbol.dispose](): void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class ConcurrentInvocationError extends Error {
|
|
13
|
+
readonly agentId: string
|
|
14
|
+
|
|
15
|
+
constructor(agentId: string) {
|
|
16
|
+
super(`Agent ${agentId} is already processing. Concurrent invocations are not allowed.`)
|
|
17
|
+
this.name = 'ConcurrentInvocationError'
|
|
18
|
+
this.agentId = agentId
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Simple lock mechanism to prevent concurrent invocations of the same agent.
|
|
24
|
+
*
|
|
25
|
+
* When the lock is acquired:
|
|
26
|
+
* - Returns a Disposable object that releases the lock when disposed
|
|
27
|
+
* - If already locked, throws ConcurrentInvocationError
|
|
28
|
+
*
|
|
29
|
+
* Usage with try/finally:
|
|
30
|
+
* ```
|
|
31
|
+
* const lock = this.invocationLock.acquire(agentId)
|
|
32
|
+
* try {
|
|
33
|
+
* // do work
|
|
34
|
+
* } finally {
|
|
35
|
+
* lock[Symbol.dispose]()
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export class InvocationLock {
|
|
40
|
+
private isLocked = false
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Acquire the lock. Returns a Disposable that releases the lock when disposed.
|
|
44
|
+
* @throws {ConcurrentInvocationError} if the lock is already held
|
|
45
|
+
*/
|
|
46
|
+
acquire(agentId: string): Disposable {
|
|
47
|
+
if (this.isLocked) {
|
|
48
|
+
throw new ConcurrentInvocationError(agentId)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.isLocked = true
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
[Symbol.dispose]: () => {
|
|
55
|
+
this.isLocked = false
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if the lock is currently active (held).
|
|
62
|
+
*/
|
|
63
|
+
isActive(): boolean {
|
|
64
|
+
return this.isLocked
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ThreadMessage } from '../../contracts/index.js'
|
|
2
2
|
import type { A2AMessage, A2AMessageRole, A2APart, TextPart } from '../../types/a2a/index.js'
|
|
3
|
-
import type { MessageRole } from '../../types/message/index.js'
|
|
4
|
-
import type { Message } from '../../types/message/index.js'
|
|
3
|
+
import type { Message, MessageRole } from '../../types/message/index.js'
|
|
5
4
|
|
|
6
5
|
function toA2ARole(role: MessageRole): A2AMessageRole {
|
|
7
6
|
switch (role) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ConnectorManager } from '../../../manager/connector/lifecycle.js'
|
|
2
|
-
import type {
|
|
3
|
-
import type { ToolDefinition } from '../../../types/tool/index.js'
|
|
2
|
+
import type { ToolDefinition, ToolRegistryContract } from '../../../types/tool/index.js'
|
|
4
3
|
import { toErrorMessage } from '../../../utils/error.js'
|
|
5
4
|
import { type Logger, getRootLogger } from '../../../utils/logger.js'
|
|
6
5
|
import { connectorInstanceToTools, createConnectorRouterTool } from './adapter.js'
|
|
@@ -43,7 +42,7 @@ export class ConnectorToolRouter {
|
|
|
43
42
|
return tools
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
registerTools(toolRegistry:
|
|
45
|
+
registerTools(toolRegistry: ToolRegistryContract): string[] {
|
|
47
46
|
const tools = this.getTools()
|
|
48
47
|
const names: string[] = []
|
|
49
48
|
for (const tool of tools) {
|
|
@@ -54,14 +53,14 @@ export class ConnectorToolRouter {
|
|
|
54
53
|
return names
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
unregisterTools(toolRegistry:
|
|
56
|
+
unregisterTools(toolRegistry: ToolRegistryContract, toolNames: string[]): void {
|
|
58
57
|
for (const name of toolNames) {
|
|
59
58
|
toolRegistry.unregister(name)
|
|
60
59
|
}
|
|
61
60
|
this.log.info(`Unregistered ${toolNames.length} connector tools`)
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
refreshTools(toolRegistry:
|
|
63
|
+
refreshTools(toolRegistry: ToolRegistryContract, previousNames: string[]): string[] {
|
|
65
64
|
this.unregisterTools(toolRegistry, previousNames)
|
|
66
65
|
return this.registerTools(toolRegistry)
|
|
67
66
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
createAssistantMessage,
|
|
4
|
+
createToolMessage,
|
|
5
|
+
createUserMessage,
|
|
6
|
+
} from '../../types/message/index.js'
|
|
7
|
+
import { SlidingWindowManager } from '../managers/slidingWindow.js'
|
|
8
|
+
|
|
9
|
+
describe('SlidingWindowManager', () => {
|
|
10
|
+
it('should have correct name', () => {
|
|
11
|
+
const manager = new SlidingWindowManager()
|
|
12
|
+
expect(manager.name).toBe('sliding-window')
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('should not trim messages under window size', () => {
|
|
16
|
+
const manager = new SlidingWindowManager({ keepRecentMessages: 4 })
|
|
17
|
+
const messages = [
|
|
18
|
+
createUserMessage('msg 1'),
|
|
19
|
+
createAssistantMessage('response 1'),
|
|
20
|
+
createUserMessage('msg 2'),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
const result = manager.applyManagement(messages)
|
|
24
|
+
expect(result).toHaveLength(3)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should trim messages exceeding window size', () => {
|
|
28
|
+
const manager = new SlidingWindowManager({ keepRecentMessages: 2 })
|
|
29
|
+
const messages = [
|
|
30
|
+
createUserMessage('msg 1'),
|
|
31
|
+
createAssistantMessage('response 1'),
|
|
32
|
+
createUserMessage('msg 2'),
|
|
33
|
+
createAssistantMessage('response 2'),
|
|
34
|
+
createUserMessage('msg 3'),
|
|
35
|
+
createAssistantMessage('response 3'),
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
const result = manager.applyManagement(messages)
|
|
39
|
+
expect(result.length).toBeLessThanOrEqual(messages.length)
|
|
40
|
+
expect(result.length).toBeGreaterThanOrEqual(2)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('should preserve recent messages', () => {
|
|
44
|
+
const manager = new SlidingWindowManager({ keepRecentMessages: 2 })
|
|
45
|
+
const msg1 = createUserMessage('msg 1')
|
|
46
|
+
const msg2 = createAssistantMessage('response 1')
|
|
47
|
+
const msg3 = createUserMessage('msg 2')
|
|
48
|
+
const msg4 = createAssistantMessage('response 2')
|
|
49
|
+
|
|
50
|
+
const messages = [msg1, msg2, msg3, msg4]
|
|
51
|
+
const result = manager.applyManagement(messages)
|
|
52
|
+
|
|
53
|
+
// Should include the most recent messages
|
|
54
|
+
expect(result).toContain(msg3)
|
|
55
|
+
expect(result).toContain(msg4)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('should preserve tool call/result pairs', () => {
|
|
59
|
+
const manager = new SlidingWindowManager({ keepRecentMessages: 2 })
|
|
60
|
+
const messages = [
|
|
61
|
+
createUserMessage('old message'),
|
|
62
|
+
createAssistantMessage(null, [
|
|
63
|
+
{
|
|
64
|
+
id: 'call_1',
|
|
65
|
+
type: 'function',
|
|
66
|
+
function: { name: 'test_tool', arguments: '{}' },
|
|
67
|
+
},
|
|
68
|
+
]),
|
|
69
|
+
createToolMessage('result 1', 'call_1'),
|
|
70
|
+
createUserMessage('recent message'),
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
const result = manager.applyManagement(messages)
|
|
74
|
+
|
|
75
|
+
// Should keep the tool call/result pair together if included
|
|
76
|
+
const callIdx = result.findIndex(
|
|
77
|
+
(m) => m.role === 'assistant' && 'toolCalls' in m && m.toolCalls?.length === 1,
|
|
78
|
+
)
|
|
79
|
+
const resultIdx = result.findIndex(
|
|
80
|
+
(m) => m.role === 'tool' && 'toolCallId' in m && m.toolCallId === 'call_1',
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if (callIdx !== -1) {
|
|
84
|
+
// If call is present, result should be present and after it
|
|
85
|
+
expect(resultIdx).toBeGreaterThan(callIdx)
|
|
86
|
+
} else {
|
|
87
|
+
// If call is removed, result should also be removed
|
|
88
|
+
expect(resultIdx).toBe(-1)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('should return false from reduceContext if already minimal', () => {
|
|
93
|
+
const manager = new SlidingWindowManager({ keepRecentMessages: 1 })
|
|
94
|
+
const messages = [createUserMessage('msg')]
|
|
95
|
+
|
|
96
|
+
const result = manager.reduceContext(messages, 1000)
|
|
97
|
+
expect(result).toBe(false)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('should return true from reduceContext if reduction possible', () => {
|
|
101
|
+
const manager = new SlidingWindowManager({ keepRecentMessages: 4 })
|
|
102
|
+
const messages = [
|
|
103
|
+
createUserMessage('msg 1'),
|
|
104
|
+
createAssistantMessage('response 1'),
|
|
105
|
+
createUserMessage('msg 2'),
|
|
106
|
+
createAssistantMessage('response 2'),
|
|
107
|
+
createUserMessage('msg 3'),
|
|
108
|
+
createAssistantMessage('response 3'),
|
|
109
|
+
createUserMessage('msg 4'),
|
|
110
|
+
createAssistantMessage('response 4'),
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
const result = manager.reduceContext(messages, 1000)
|
|
114
|
+
expect(result).toBe(true)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('should use default keepRecentMessages when not provided', () => {
|
|
118
|
+
const manager = new SlidingWindowManager()
|
|
119
|
+
const messages = Array(10)
|
|
120
|
+
.fill(null)
|
|
121
|
+
.map((_, i) => createUserMessage(`msg ${i}`))
|
|
122
|
+
|
|
123
|
+
const result = manager.applyManagement(messages)
|
|
124
|
+
expect(result.length).toBeLessThanOrEqual(4) // default is 4
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('should handle empty message array', () => {
|
|
128
|
+
const manager = new SlidingWindowManager()
|
|
129
|
+
const result = manager.applyManagement([])
|
|
130
|
+
expect(result).toHaveLength(0)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('should handle single message', () => {
|
|
134
|
+
const manager = new SlidingWindowManager({ keepRecentMessages: 2 })
|
|
135
|
+
const messages = [createUserMessage('only message')]
|
|
136
|
+
const result = manager.applyManagement(messages)
|
|
137
|
+
expect(result).toEqual(messages)
|
|
138
|
+
})
|
|
139
|
+
})
|