@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.
Files changed (324) hide show
  1. package/dist/advisory/executor.d.ts +2 -2
  2. package/dist/advisory/executor.d.ts.map +1 -1
  3. package/dist/advisory/executor.js.map +1 -1
  4. package/dist/agents/AbstractAgent.d.ts +20 -2
  5. package/dist/agents/AbstractAgent.d.ts.map +1 -1
  6. package/dist/agents/AbstractAgent.js +23 -1
  7. package/dist/agents/AbstractAgent.js.map +1 -1
  8. package/dist/agents/PipelineAgent.d.ts.map +1 -1
  9. package/dist/agents/PipelineAgent.js +1 -1
  10. package/dist/agents/PipelineAgent.js.map +1 -1
  11. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  12. package/dist/agents/ReactiveAgent.js +1 -0
  13. package/dist/agents/ReactiveAgent.js.map +1 -1
  14. package/dist/agents/RouterAgent.d.ts.map +1 -1
  15. package/dist/agents/RouterAgent.js +4 -2
  16. package/dist/agents/RouterAgent.js.map +1 -1
  17. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  18. package/dist/agents/SupervisorAgent.js +4 -1
  19. package/dist/agents/SupervisorAgent.js.map +1 -1
  20. package/dist/agents/__tests__/lock.test.d.ts +2 -0
  21. package/dist/agents/__tests__/lock.test.d.ts.map +1 -0
  22. package/dist/agents/__tests__/lock.test.js +131 -0
  23. package/dist/agents/__tests__/lock.test.js.map +1 -0
  24. package/dist/agents/index.d.ts +2 -0
  25. package/dist/agents/index.d.ts.map +1 -1
  26. package/dist/agents/index.js +1 -0
  27. package/dist/agents/index.js.map +1 -1
  28. package/dist/agents/lock.d.ts +42 -0
  29. package/dist/agents/lock.d.ts.map +1 -0
  30. package/dist/agents/lock.js +54 -0
  31. package/dist/agents/lock.js.map +1 -0
  32. package/dist/bridge/a2a/message.d.ts.map +1 -1
  33. package/dist/bridge/a2a/message.js.map +1 -1
  34. package/dist/bridge/tools/connector/router.d.ts +4 -5
  35. package/dist/bridge/tools/connector/router.d.ts.map +1 -1
  36. package/dist/bridge/tools/connector/router.js.map +1 -1
  37. package/dist/compaction/__tests__/SlidingWindowManager.test.d.ts +2 -0
  38. package/dist/compaction/__tests__/SlidingWindowManager.test.d.ts.map +1 -0
  39. package/dist/compaction/__tests__/SlidingWindowManager.test.js +113 -0
  40. package/dist/compaction/__tests__/SlidingWindowManager.test.js.map +1 -0
  41. package/dist/compaction/__tests__/dangling.test.d.ts +2 -0
  42. package/dist/compaction/__tests__/dangling.test.d.ts.map +1 -0
  43. package/dist/compaction/__tests__/dangling.test.js +356 -0
  44. package/dist/compaction/__tests__/dangling.test.js.map +1 -0
  45. package/dist/compaction/__tests__/factory.test.d.ts +2 -0
  46. package/dist/compaction/__tests__/factory.test.d.ts.map +1 -0
  47. package/dist/compaction/__tests__/factory.test.js +43 -0
  48. package/dist/compaction/__tests__/factory.test.js.map +1 -0
  49. package/dist/compaction/dangling.d.ts +96 -0
  50. package/dist/compaction/dangling.d.ts.map +1 -0
  51. package/dist/compaction/dangling.js +274 -0
  52. package/dist/compaction/dangling.js.map +1 -0
  53. package/dist/compaction/factory.d.ts +20 -0
  54. package/dist/compaction/factory.d.ts.map +1 -0
  55. package/dist/compaction/factory.js +35 -0
  56. package/dist/compaction/factory.js.map +1 -0
  57. package/dist/compaction/index.d.ts +5 -0
  58. package/dist/compaction/index.d.ts.map +1 -1
  59. package/dist/compaction/index.js +3 -0
  60. package/dist/compaction/index.js.map +1 -1
  61. package/dist/compaction/interface.d.ts +33 -0
  62. package/dist/compaction/interface.d.ts.map +1 -0
  63. package/dist/compaction/interface.js +2 -0
  64. package/dist/compaction/interface.js.map +1 -0
  65. package/dist/compaction/managers/index.d.ts +4 -0
  66. package/dist/compaction/managers/index.d.ts.map +1 -0
  67. package/dist/compaction/managers/index.js +4 -0
  68. package/dist/compaction/managers/index.js.map +1 -0
  69. package/dist/compaction/managers/null.d.ts +12 -0
  70. package/dist/compaction/managers/null.d.ts.map +1 -0
  71. package/dist/compaction/managers/null.js +15 -0
  72. package/dist/compaction/managers/null.js.map +1 -0
  73. package/dist/compaction/managers/slidingWindow.d.ts +27 -0
  74. package/dist/compaction/managers/slidingWindow.d.ts.map +1 -0
  75. package/dist/compaction/managers/slidingWindow.js +41 -0
  76. package/dist/compaction/managers/slidingWindow.js.map +1 -0
  77. package/dist/compaction/managers/structured.d.ts +23 -0
  78. package/dist/compaction/managers/structured.d.ts.map +1 -0
  79. package/dist/compaction/managers/structured.js +144 -0
  80. package/dist/compaction/managers/structured.js.map +1 -0
  81. package/dist/compaction/types.d.ts +1 -1
  82. package/dist/compaction/types.d.ts.map +1 -1
  83. package/dist/config/runtime.d.ts +16 -16
  84. package/dist/config/runtime.js +1 -1
  85. package/dist/config/runtime.js.map +1 -1
  86. package/dist/constants/agent/index.d.ts +1 -1
  87. package/dist/constants/agent/index.d.ts.map +1 -1
  88. package/dist/gateway/local.d.ts +2 -2
  89. package/dist/gateway/local.d.ts.map +1 -1
  90. package/dist/gateway/local.js +10 -1
  91. package/dist/gateway/local.js.map +1 -1
  92. package/dist/index.d.ts +18 -4
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +12 -2
  95. package/dist/index.js.map +1 -1
  96. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  97. package/dist/manager/agent/lifecycle.js +3 -2
  98. package/dist/manager/agent/lifecycle.js.map +1 -1
  99. package/dist/manager/run/persistence.d.ts +1 -2
  100. package/dist/manager/run/persistence.d.ts.map +1 -1
  101. package/dist/manager/run/persistence.js +2 -1
  102. package/dist/manager/run/persistence.js.map +1 -1
  103. package/dist/plugin/__tests__/lifecycle.test.d.ts +2 -0
  104. package/dist/plugin/__tests__/lifecycle.test.d.ts.map +1 -0
  105. package/dist/plugin/__tests__/lifecycle.test.js +332 -0
  106. package/dist/plugin/__tests__/lifecycle.test.js.map +1 -0
  107. package/dist/plugin/lifecycle.d.ts +2 -2
  108. package/dist/plugin/lifecycle.d.ts.map +1 -1
  109. package/dist/plugin/lifecycle.js +28 -2
  110. package/dist/plugin/lifecycle.js.map +1 -1
  111. package/dist/plugin/resolver.d.ts +2 -2
  112. package/dist/plugin/resolver.d.ts.map +1 -1
  113. package/dist/plugin/resolver.js.map +1 -1
  114. package/dist/registry/agent/definitions.d.ts +3 -2
  115. package/dist/registry/agent/definitions.d.ts.map +1 -1
  116. package/dist/registry/agent/definitions.js.map +1 -1
  117. package/dist/registry/tool/execute.d.ts +2 -5
  118. package/dist/registry/tool/execute.d.ts.map +1 -1
  119. package/dist/registry/tool/execute.js.map +1 -1
  120. package/dist/runtime/decision/parser.d.ts.map +1 -1
  121. package/dist/runtime/decision/parser.js +15 -40
  122. package/dist/runtime/decision/parser.js.map +1 -1
  123. package/dist/runtime/query/context-cache.d.ts +3 -3
  124. package/dist/runtime/query/context-cache.d.ts.map +1 -1
  125. package/dist/runtime/query/context-cache.js.map +1 -1
  126. package/dist/runtime/query/context.d.ts +1 -1
  127. package/dist/runtime/query/context.d.ts.map +1 -1
  128. package/dist/runtime/query/context.js.map +1 -1
  129. package/dist/runtime/query/events.js +11 -11
  130. package/dist/runtime/query/events.js.map +1 -1
  131. package/dist/runtime/query/executor.d.ts +4 -2
  132. package/dist/runtime/query/executor.d.ts.map +1 -1
  133. package/dist/runtime/query/executor.js +1 -0
  134. package/dist/runtime/query/executor.js.map +1 -1
  135. package/dist/runtime/query/index.d.ts +5 -3
  136. package/dist/runtime/query/index.d.ts.map +1 -1
  137. package/dist/runtime/query/index.js +2 -1
  138. package/dist/runtime/query/index.js.map +1 -1
  139. package/dist/runtime/query/iteration/index.d.ts +2 -2
  140. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  141. package/dist/runtime/query/iteration/index.js.map +1 -1
  142. package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
  143. package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
  144. package/dist/runtime/query/iteration/phases/checkpoint.d.ts +1 -1
  145. package/dist/runtime/query/iteration/phases/checkpoint.d.ts.map +1 -1
  146. package/dist/runtime/query/iteration/phases/checkpoint.js.map +1 -1
  147. package/dist/runtime/query/iteration/phases/context.d.ts +2 -2
  148. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  149. package/dist/runtime/query/iteration/phases/plan.d.ts +1 -1
  150. package/dist/runtime/query/iteration/phases/plan.d.ts.map +1 -1
  151. package/dist/runtime/query/iteration/phases/plan.js.map +1 -1
  152. package/dist/runtime/query/prompt.d.ts +2 -2
  153. package/dist/runtime/query/prompt.d.ts.map +1 -1
  154. package/dist/runtime/query/prompt.js.map +1 -1
  155. package/dist/runtime/query/result.d.ts +1 -1
  156. package/dist/runtime/query/result.d.ts.map +1 -1
  157. package/dist/runtime/query/result.js.map +1 -1
  158. package/dist/runtime/query/tooling.d.ts +4 -2
  159. package/dist/runtime/query/tooling.d.ts.map +1 -1
  160. package/dist/runtime/query/tooling.js +1 -0
  161. package/dist/runtime/query/tooling.js.map +1 -1
  162. package/dist/store/conversation/memory.d.ts +1 -1
  163. package/dist/store/conversation/memory.d.ts.map +1 -1
  164. package/dist/store/conversation/memory.js +15 -3
  165. package/dist/store/conversation/memory.js.map +1 -1
  166. package/dist/store/run/disk.d.ts +1 -2
  167. package/dist/store/run/disk.d.ts.map +1 -1
  168. package/dist/store/run/disk.js +21 -13
  169. package/dist/store/run/disk.js.map +1 -1
  170. package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts +140 -0
  171. package/dist/tools/builtins/__tests__/structuredOutput.example.d.ts.map +1 -0
  172. package/dist/tools/builtins/__tests__/structuredOutput.example.js +183 -0
  173. package/dist/tools/builtins/__tests__/structuredOutput.example.js.map +1 -0
  174. package/dist/tools/builtins/__tests__/structuredOutput.test.d.ts +2 -0
  175. package/dist/tools/builtins/__tests__/structuredOutput.test.d.ts.map +1 -0
  176. package/dist/tools/builtins/__tests__/structuredOutput.test.js +224 -0
  177. package/dist/tools/builtins/__tests__/structuredOutput.test.js.map +1 -0
  178. package/dist/tools/builtins/grep.d.ts.map +1 -1
  179. package/dist/tools/builtins/grep.js +1 -2
  180. package/dist/tools/builtins/grep.js.map +1 -1
  181. package/dist/tools/builtins/index.d.ts +1 -0
  182. package/dist/tools/builtins/index.d.ts.map +1 -1
  183. package/dist/tools/builtins/index.js +3 -0
  184. package/dist/tools/builtins/index.js.map +1 -1
  185. package/dist/tools/builtins/ls.d.ts +1 -1
  186. package/dist/tools/builtins/structuredOutput.d.ts +27 -0
  187. package/dist/tools/builtins/structuredOutput.d.ts.map +1 -0
  188. package/dist/tools/builtins/structuredOutput.js +46 -0
  189. package/dist/tools/builtins/structuredOutput.js.map +1 -0
  190. package/dist/tools/task/list.d.ts +1 -1
  191. package/dist/tools/task/list.d.ts.map +1 -1
  192. package/dist/tools/task/list.js.map +1 -1
  193. package/dist/types/agent/base.d.ts +4 -1
  194. package/dist/types/agent/base.d.ts.map +1 -1
  195. package/dist/types/agent/index.d.ts +1 -0
  196. package/dist/types/agent/index.d.ts.map +1 -1
  197. package/dist/types/agent/index.js +1 -0
  198. package/dist/types/agent/index.js.map +1 -1
  199. package/dist/types/agent/manager.d.ts +27 -0
  200. package/dist/types/agent/manager.d.ts.map +1 -0
  201. package/dist/types/agent/manager.js +2 -0
  202. package/dist/types/agent/manager.js.map +1 -0
  203. package/dist/types/agent/reactive.d.ts +2 -2
  204. package/dist/types/agent/reactive.d.ts.map +1 -1
  205. package/dist/types/agent/supervisor.d.ts +2 -2
  206. package/dist/types/agent/supervisor.d.ts.map +1 -1
  207. package/dist/types/agent/task.d.ts +0 -2
  208. package/dist/types/agent/task.d.ts.map +1 -1
  209. package/dist/types/agent/task.js +0 -2
  210. package/dist/types/agent/task.js.map +1 -1
  211. package/dist/types/common/index.d.ts +0 -1
  212. package/dist/types/common/index.d.ts.map +1 -1
  213. package/dist/types/common/index.js +0 -1
  214. package/dist/types/common/index.js.map +1 -1
  215. package/dist/types/hitl/index.d.ts +1 -2
  216. package/dist/types/hitl/index.d.ts.map +1 -1
  217. package/dist/types/hitl/index.js.map +1 -1
  218. package/dist/types/invocation/__tests__/state.test.d.ts +2 -0
  219. package/dist/types/invocation/__tests__/state.test.d.ts.map +1 -0
  220. package/dist/types/invocation/__tests__/state.test.js +167 -0
  221. package/dist/types/invocation/__tests__/state.test.js.map +1 -0
  222. package/dist/types/invocation/index.d.ts +37 -0
  223. package/dist/types/invocation/index.d.ts.map +1 -0
  224. package/dist/types/invocation/index.js +23 -0
  225. package/dist/types/invocation/index.js.map +1 -0
  226. package/dist/types/plugin/index.d.ts +6 -0
  227. package/dist/types/plugin/index.d.ts.map +1 -1
  228. package/dist/types/plugin/index.js +16 -0
  229. package/dist/types/plugin/index.js.map +1 -1
  230. package/dist/types/run/events.d.ts +1 -1
  231. package/dist/types/run/events.d.ts.map +1 -1
  232. package/dist/types/run/index.d.ts +1 -0
  233. package/dist/types/run/index.d.ts.map +1 -1
  234. package/dist/types/run/index.js +1 -0
  235. package/dist/types/run/index.js.map +1 -1
  236. package/dist/types/run/metadata.d.ts +1 -1
  237. package/dist/types/run/metadata.d.ts.map +1 -1
  238. package/dist/types/run/state.d.ts +1 -1
  239. package/dist/types/run/state.d.ts.map +1 -1
  240. package/dist/types/run/stop-reason.d.ts +2 -0
  241. package/dist/types/run/stop-reason.d.ts.map +1 -0
  242. package/dist/types/run/stop-reason.js +2 -0
  243. package/dist/types/run/stop-reason.js.map +1 -0
  244. package/dist/types/structured-output/index.d.ts +51 -0
  245. package/dist/types/structured-output/index.d.ts.map +1 -0
  246. package/dist/types/structured-output/index.js +2 -0
  247. package/dist/types/structured-output/index.js.map +1 -0
  248. package/dist/types/tool/index.d.ts +36 -0
  249. package/dist/types/tool/index.d.ts.map +1 -1
  250. package/package.json +1 -1
  251. package/src/advisory/executor.ts +2 -4
  252. package/src/agents/AbstractAgent.ts +26 -3
  253. package/src/agents/PipelineAgent.ts +1 -1
  254. package/src/agents/ReactiveAgent.ts +1 -0
  255. package/src/agents/RouterAgent.ts +8 -2
  256. package/src/agents/SupervisorAgent.ts +5 -1
  257. package/src/agents/__tests__/lock.test.ts +158 -0
  258. package/src/agents/index.ts +2 -0
  259. package/src/agents/lock.ts +66 -0
  260. package/src/bridge/a2a/message.ts +1 -2
  261. package/src/bridge/tools/connector/router.ts +4 -5
  262. package/src/compaction/__tests__/SlidingWindowManager.test.ts +139 -0
  263. package/src/compaction/__tests__/dangling.test.ts +447 -0
  264. package/src/compaction/__tests__/factory.test.ts +53 -0
  265. package/src/compaction/dangling.ts +321 -0
  266. package/src/compaction/factory.ts +41 -0
  267. package/src/compaction/index.ts +14 -0
  268. package/src/compaction/interface.ts +35 -0
  269. package/src/compaction/managers/index.ts +3 -0
  270. package/src/compaction/managers/null.ts +19 -0
  271. package/src/compaction/managers/slidingWindow.ts +57 -0
  272. package/src/compaction/managers/structured.ts +169 -0
  273. package/src/compaction/types.ts +1 -1
  274. package/src/config/runtime.ts +1 -1
  275. package/src/constants/agent/index.ts +1 -1
  276. package/src/gateway/local.ts +13 -4
  277. package/src/index.ts +38 -1
  278. package/src/manager/agent/lifecycle.ts +3 -2
  279. package/src/manager/run/persistence.ts +3 -8
  280. package/src/plugin/__tests__/lifecycle.test.ts +430 -0
  281. package/src/plugin/lifecycle.ts +32 -6
  282. package/src/plugin/resolver.ts +3 -3
  283. package/src/registry/agent/definitions.ts +3 -2
  284. package/src/registry/tool/execute.ts +2 -5
  285. package/src/runtime/decision/parser.ts +15 -40
  286. package/src/runtime/query/context-cache.ts +3 -4
  287. package/src/runtime/query/context.ts +1 -2
  288. package/src/runtime/query/events.ts +11 -11
  289. package/src/runtime/query/executor.ts +5 -3
  290. package/src/runtime/query/index.ts +11 -4
  291. package/src/runtime/query/iteration/index.ts +2 -2
  292. package/src/runtime/query/iteration/phases/advisory.ts +1 -2
  293. package/src/runtime/query/iteration/phases/checkpoint.ts +1 -2
  294. package/src/runtime/query/iteration/phases/context.ts +2 -2
  295. package/src/runtime/query/iteration/phases/plan.ts +1 -2
  296. package/src/runtime/query/prompt.ts +3 -3
  297. package/src/runtime/query/result.ts +1 -2
  298. package/src/runtime/query/tooling.ts +5 -2
  299. package/src/store/conversation/memory.ts +21 -5
  300. package/src/store/run/disk.ts +18 -16
  301. package/src/tools/builtins/__tests__/structuredOutput.example.ts +221 -0
  302. package/src/tools/builtins/__tests__/structuredOutput.test.ts +275 -0
  303. package/src/tools/builtins/grep.ts +1 -2
  304. package/src/tools/builtins/index.ts +3 -0
  305. package/src/tools/builtins/structuredOutput.ts +55 -0
  306. package/src/tools/task/list.ts +1 -2
  307. package/src/types/agent/base.ts +5 -1
  308. package/src/types/agent/index.ts +1 -0
  309. package/src/types/agent/manager.ts +36 -0
  310. package/src/types/agent/reactive.ts +2 -2
  311. package/src/types/agent/supervisor.ts +2 -2
  312. package/src/types/agent/task.ts +0 -4
  313. package/src/types/common/index.ts +0 -2
  314. package/src/types/hitl/index.ts +1 -2
  315. package/src/types/invocation/__tests__/state.test.ts +210 -0
  316. package/src/types/invocation/index.ts +55 -0
  317. package/src/types/plugin/index.ts +19 -0
  318. package/src/types/run/events.ts +1 -10
  319. package/src/types/run/index.ts +1 -0
  320. package/src/types/run/metadata.ts +1 -1
  321. package/src/types/run/state.ts +1 -1
  322. package/src/types/run/stop-reason.ts +10 -0
  323. package/src/types/structured-output/index.ts +56 -0
  324. package/src/types/tool/index.ts +45 -0
@@ -1,4 +1,4 @@
1
- import type { AgentManager } from '../manager/agent/lifecycle.js'
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 { EMPTY_TOKEN_USAGE } from '../types/common/index.js'
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?: 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 delegateResult = await targetRoute.agent.run(input, config, listener)
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
+ })
@@ -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 { ToolRegistry } from '../../../registry/tool/execute.js'
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: ToolRegistry): string[] {
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: ToolRegistry, toolNames: string[]): void {
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: ToolRegistry, previousNames: string[]): string[] {
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
+ })