@theokit/sdk 5.14.0 → 5.15.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.
Files changed (212) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/{agent-Dfw3VsIX.d.ts → agent-B6C9i_qu.d.ts} +23 -213
  3. package/dist/{agent-DExqjqYy.d.cts → agent-B6FQad6P.d.cts} +23 -213
  4. package/dist/{agent-T34LCGQM.js → agent-DRDGUU6T.js} +18 -17
  5. package/dist/{agent-T34LCGQM.js.map → agent-DRDGUU6T.js.map} +1 -1
  6. package/dist/{agent-TL4K7BTG.cjs → agent-VI2HITPT.cjs} +19 -18
  7. package/dist/{agent-TL4K7BTG.cjs.map → agent-VI2HITPT.cjs.map} +1 -1
  8. package/dist/agent.d.ts +2 -3
  9. package/dist/{batch-EP3FCL6D.js → batch-N2XDYZED.js} +4 -4
  10. package/dist/{batch-EP3FCL6D.js.map → batch-N2XDYZED.js.map} +1 -1
  11. package/dist/{batch-IZ5EDKJ5.cjs → batch-VFR2MAUE.cjs} +7 -7
  12. package/dist/{batch-IZ5EDKJ5.cjs.map → batch-VFR2MAUE.cjs.map} +1 -1
  13. package/dist/{chunk-3ONIVO2I.js → chunk-23SS4ID4.js} +3 -3
  14. package/dist/{chunk-3ONIVO2I.js.map → chunk-23SS4ID4.js.map} +1 -1
  15. package/dist/{chunk-2C24NSNV.js → chunk-3BBTHFGJ.js} +3 -3
  16. package/dist/{chunk-2C24NSNV.js.map → chunk-3BBTHFGJ.js.map} +1 -1
  17. package/dist/{chunk-NP362THY.cjs → chunk-3F53FLQ7.cjs} +5 -7
  18. package/dist/chunk-3F53FLQ7.cjs.map +1 -0
  19. package/dist/{chunk-SXH37C7X.cjs → chunk-55LLQFHW.cjs} +6 -6
  20. package/dist/{chunk-SXH37C7X.cjs.map → chunk-55LLQFHW.cjs.map} +1 -1
  21. package/dist/{chunk-GARVAUCU.js → chunk-5M5GQYBM.js} +534 -236
  22. package/dist/chunk-5M5GQYBM.js.map +1 -0
  23. package/dist/{chunk-2WY2OFSC.cjs → chunk-64ECM3XM.cjs} +616 -318
  24. package/dist/chunk-64ECM3XM.cjs.map +1 -0
  25. package/dist/{chunk-ZJAYFSVI.js → chunk-7ACS6P5Z.js} +5 -7
  26. package/dist/chunk-7ACS6P5Z.js.map +1 -0
  27. package/dist/{chunk-NAVUTK6X.js → chunk-ARC2V7NY.js} +3 -3
  28. package/dist/{chunk-NAVUTK6X.js.map → chunk-ARC2V7NY.js.map} +1 -1
  29. package/dist/{chunk-WDVG5R2Q.cjs → chunk-AUH2EVWY.cjs} +4 -3
  30. package/dist/chunk-AUH2EVWY.cjs.map +1 -0
  31. package/dist/chunk-BNEUB52I.cjs +55 -0
  32. package/dist/chunk-BNEUB52I.cjs.map +1 -0
  33. package/dist/chunk-BPL5CVZ5.js +53 -0
  34. package/dist/chunk-BPL5CVZ5.js.map +1 -0
  35. package/dist/{chunk-NVQSBRG6.js → chunk-CBBT42VX.js} +3 -3
  36. package/dist/{chunk-NVQSBRG6.js.map → chunk-CBBT42VX.js.map} +1 -1
  37. package/dist/chunk-CHKV2L2Y.cjs +416 -0
  38. package/dist/chunk-CHKV2L2Y.cjs.map +1 -0
  39. package/dist/{chunk-SNVYOX46.cjs → chunk-DJKGDLYZ.cjs} +91 -61
  40. package/dist/chunk-DJKGDLYZ.cjs.map +1 -0
  41. package/dist/{chunk-354F3OF5.js → chunk-FGGVSHDW.js} +3 -3
  42. package/dist/{chunk-354F3OF5.js.map → chunk-FGGVSHDW.js.map} +1 -1
  43. package/dist/{chunk-6OCJWGVD.cjs → chunk-FTXY4D44.cjs} +4 -4
  44. package/dist/{chunk-6OCJWGVD.cjs.map → chunk-FTXY4D44.cjs.map} +1 -1
  45. package/dist/chunk-INVEGVGO.js +405 -0
  46. package/dist/chunk-INVEGVGO.js.map +1 -0
  47. package/dist/{chunk-ZOL3L4EH.js → chunk-IOBHFP2E.js} +49 -19
  48. package/dist/chunk-IOBHFP2E.js.map +1 -0
  49. package/dist/{chunk-BZK5QL3N.cjs → chunk-KMFBNKCT.cjs} +4 -4
  50. package/dist/{chunk-BZK5QL3N.cjs.map → chunk-KMFBNKCT.cjs.map} +1 -1
  51. package/dist/{chunk-DF77RBF4.js → chunk-LCCT5ZXJ.js} +6 -6
  52. package/dist/{chunk-DF77RBF4.js.map → chunk-LCCT5ZXJ.js.map} +1 -1
  53. package/dist/{chunk-G7XBVM3T.cjs → chunk-MHUOVS5I.cjs} +5 -5
  54. package/dist/{chunk-G7XBVM3T.cjs.map → chunk-MHUOVS5I.cjs.map} +1 -1
  55. package/dist/{chunk-CWQPQTUZ.cjs → chunk-NEH3BPFD.cjs} +15 -15
  56. package/dist/{chunk-CWQPQTUZ.cjs.map → chunk-NEH3BPFD.cjs.map} +1 -1
  57. package/dist/{chunk-5AR6O7GW.js → chunk-NK5EOTDY.js} +3 -3
  58. package/dist/{chunk-5AR6O7GW.js.map → chunk-NK5EOTDY.js.map} +1 -1
  59. package/dist/{chunk-4TEGFMSP.cjs → chunk-P7QYG4RZ.cjs} +23 -15
  60. package/dist/chunk-P7QYG4RZ.cjs.map +1 -0
  61. package/dist/chunk-PPU2D4FZ.js +19 -0
  62. package/dist/chunk-PPU2D4FZ.js.map +1 -0
  63. package/dist/{chunk-AB4OPJLD.js → chunk-RGVMJU57.js} +3 -3
  64. package/dist/{chunk-AB4OPJLD.js.map → chunk-RGVMJU57.js.map} +1 -1
  65. package/dist/{chunk-4KBI37F3.cjs → chunk-RTDVSHJR.cjs} +5 -5
  66. package/dist/{chunk-4KBI37F3.cjs.map → chunk-RTDVSHJR.cjs.map} +1 -1
  67. package/dist/{chunk-CJN5CEI3.js → chunk-RZL2W4C3.js} +23 -15
  68. package/dist/chunk-RZL2W4C3.js.map +1 -0
  69. package/dist/chunk-SPEN7RJU.cjs +18 -0
  70. package/dist/{chunk-R5UQL2R5.cjs.map → chunk-SPEN7RJU.cjs.map} +1 -1
  71. package/dist/{chunk-ZF2LDKQQ.cjs → chunk-U3DW3WDE.cjs} +9 -8
  72. package/dist/chunk-U3DW3WDE.cjs.map +1 -0
  73. package/dist/{chunk-LXG6VL6R.cjs → chunk-U7PRI3XM.cjs} +3 -3
  74. package/dist/{chunk-LXG6VL6R.cjs.map → chunk-U7PRI3XM.cjs.map} +1 -1
  75. package/dist/{chunk-H7G65PNI.js → chunk-VCQ37TC5.js} +3 -3
  76. package/dist/{chunk-H7G65PNI.js.map → chunk-VCQ37TC5.js.map} +1 -1
  77. package/dist/{chunk-SDZ4XDWS.cjs → chunk-VWYFGE27.cjs} +9 -9
  78. package/dist/{chunk-SDZ4XDWS.cjs.map → chunk-VWYFGE27.cjs.map} +1 -1
  79. package/dist/{chunk-RN3XDZGS.js → chunk-WM646HEN.js} +4 -3
  80. package/dist/chunk-WM646HEN.js.map +1 -0
  81. package/dist/chunk-X7CE7Y5W.js +305 -0
  82. package/dist/chunk-X7CE7Y5W.js.map +1 -0
  83. package/dist/{chunk-CGH4BCIY.cjs → chunk-XE3CAY6Z.cjs} +5 -5
  84. package/dist/{chunk-CGH4BCIY.cjs.map → chunk-XE3CAY6Z.cjs.map} +1 -1
  85. package/dist/chunk-XOU3CL7S.cjs +312 -0
  86. package/dist/chunk-XOU3CL7S.cjs.map +1 -0
  87. package/dist/{chunk-ULEK4OM4.js → chunk-YKNBTHMD.js} +3 -3
  88. package/dist/{chunk-ULEK4OM4.js.map → chunk-YKNBTHMD.js.map} +1 -1
  89. package/dist/{compact-session-D2MQDB6G.cjs → compact-session-NX7HUNTB.cjs} +16 -16
  90. package/dist/{compact-session-D2MQDB6G.cjs.map → compact-session-NX7HUNTB.cjs.map} +1 -1
  91. package/dist/{compact-session-N2PPHQO6.js → compact-session-Q5IGNFPW.js} +7 -7
  92. package/dist/{compact-session-N2PPHQO6.js.map → compact-session-Q5IGNFPW.js.map} +1 -1
  93. package/dist/{cron-CK2v0VWA.d.cts → cron-Bh3aWgQ2.d.cts} +2 -2
  94. package/dist/{cron-BubDpFJG.d.ts → cron-CCDxeeFZ.d.ts} +2 -2
  95. package/dist/cron.cjs +18 -17
  96. package/dist/cron.d.cts +4 -3
  97. package/dist/cron.d.ts +4 -3
  98. package/dist/cron.js +17 -16
  99. package/dist/eval.cjs +17 -16
  100. package/dist/eval.cjs.map +1 -1
  101. package/dist/eval.js +16 -15
  102. package/dist/eval.js.map +1 -1
  103. package/dist/fs-session-store-CYNTEPJZ.cjs +20 -0
  104. package/dist/{fs-session-store-S2AXVJIX.cjs.map → fs-session-store-CYNTEPJZ.cjs.map} +1 -1
  105. package/dist/fs-session-store-MYQEVUFL.js +11 -0
  106. package/dist/{fs-session-store-6ZCCJX3K.js.map → fs-session-store-MYQEVUFL.js.map} +1 -1
  107. package/dist/{index-manager-HO456AVW.cjs → index-manager-2KH75BRW.cjs} +7 -7
  108. package/dist/{index-manager-HO456AVW.cjs.map → index-manager-2KH75BRW.cjs.map} +1 -1
  109. package/dist/{index-manager-QDH56FER.js → index-manager-NF2WRLOU.js} +6 -6
  110. package/dist/{index-manager-QDH56FER.js.map → index-manager-NF2WRLOU.js.map} +1 -1
  111. package/dist/index.cjs +66 -262
  112. package/dist/index.cjs.map +1 -1
  113. package/dist/index.d.cts +10 -46
  114. package/dist/index.d.ts +10 -46
  115. package/dist/index.js +27 -227
  116. package/dist/index.js.map +1 -1
  117. package/dist/{inject-session-J26SHHIO.js → inject-session-4ROYLZHY.js} +3 -3
  118. package/dist/{inject-session-J26SHHIO.js.map → inject-session-4ROYLZHY.js.map} +1 -1
  119. package/dist/{inject-session-3ICZIJ2N.cjs → inject-session-AWKDCGHV.cjs} +4 -4
  120. package/dist/{inject-session-3ICZIJ2N.cjs.map → inject-session-AWKDCGHV.cjs.map} +1 -1
  121. package/dist/internal/agent-loop/doom-loop-tracker.d.ts +3 -0
  122. package/dist/internal/agent-loop/types.d.ts +6 -0
  123. package/dist/internal/error-mappers/anthropic.d.ts +3 -0
  124. package/dist/internal/error-mappers/openai-compatible.d.ts +2 -3
  125. package/dist/internal/local-agent/local-agent-dispatch.d.ts +3 -1
  126. package/dist/internal/local-agent/send-queue.d.ts +31 -0
  127. package/dist/internal/mcp/client.d.ts +2 -0
  128. package/dist/internal/mcp/oauth-bearer.d.ts +2 -0
  129. package/dist/internal/memory/adapters/index.cjs +3 -3
  130. package/dist/internal/memory/adapters/index.js +2 -2
  131. package/dist/internal/memory/dreaming/phases.d.ts +15 -0
  132. package/dist/internal/memory/dreaming/run.d.ts +29 -0
  133. package/dist/internal/memory/sdk-memory-peer-loader.d.ts +2 -0
  134. package/dist/internal/memory/storage/index.cjs +51 -35
  135. package/dist/internal/memory/storage/index.d.cts +2 -0
  136. package/dist/internal/memory/storage/index.d.ts +2 -0
  137. package/dist/internal/memory/storage/index.js +4 -4
  138. package/dist/internal/persistence/cwd-mutex.d.cts +4 -2
  139. package/dist/internal/persistence/cwd-mutex.d.ts +4 -2
  140. package/dist/internal/persistence/index.cjs +4 -4
  141. package/dist/internal/persistence/index.js +2 -2
  142. package/dist/internal/persistence/sqlite-session-store.d.cts +25 -0
  143. package/dist/internal/persistence/sqlite-session-store.d.ts +25 -0
  144. package/dist/internal/providers/registry.d.ts +5 -1
  145. package/dist/mcp-auth.cjs +25 -307
  146. package/dist/mcp-auth.cjs.map +1 -1
  147. package/dist/mcp-auth.js +5 -305
  148. package/dist/mcp-auth.js.map +1 -1
  149. package/dist/models.cjs +9 -9
  150. package/dist/models.js +2 -2
  151. package/dist/persistence.cjs +9 -4
  152. package/dist/persistence.cjs.map +1 -1
  153. package/dist/persistence.d.cts +744 -40
  154. package/dist/persistence.d.ts +744 -40
  155. package/dist/persistence.js +3 -2
  156. package/dist/persistence.js.map +1 -1
  157. package/dist/providers.cjs +4 -4
  158. package/dist/providers.js +2 -2
  159. package/dist/sandbox/docker-sandbox.d.cts +58 -0
  160. package/dist/sandbox/docker-sandbox.d.ts +58 -0
  161. package/dist/sandbox/index.cjs +129 -1
  162. package/dist/sandbox/index.cjs.map +1 -1
  163. package/dist/sandbox/index.d.cts +1 -0
  164. package/dist/sandbox/index.d.ts +1 -0
  165. package/dist/sandbox/index.js +132 -5
  166. package/dist/sandbox/index.js.map +1 -1
  167. package/dist/{sdk-agent-DwzHcuxy.d.cts → sdk-agent-BA_6_wtc.d.cts} +30 -2
  168. package/dist/{sdk-agent-a3fW1xUK.d.ts → sdk-agent-CnwPODYH.d.ts} +30 -2
  169. package/dist/session-store-Dh07jr9N.d.cts +209 -0
  170. package/dist/session-store-Dh07jr9N.d.ts +209 -0
  171. package/dist/sqlite-session-store-BbcpKY1L.d.ts +64 -0
  172. package/dist/sqlite-session-store-TKXtT4ON.d.cts +64 -0
  173. package/dist/subagents-loader-KLWF4QPD.cjs +16 -0
  174. package/dist/{subagents-loader-TXOA5EJJ.cjs.map → subagents-loader-KLWF4QPD.cjs.map} +1 -1
  175. package/dist/subagents-loader-SXETS2F2.js +7 -0
  176. package/dist/{subagents-loader-Z744TAKD.js.map → subagents-loader-SXETS2F2.js.map} +1 -1
  177. package/dist/subagents-loader.cjs +2 -2
  178. package/dist/subagents-loader.d.cts +3 -2
  179. package/dist/subagents-loader.d.ts +3 -2
  180. package/dist/subagents-loader.js +1 -1
  181. package/dist/types/agent.d.ts +14 -1
  182. package/dist/types/budget-tracker.d.ts +6 -2
  183. package/dist/types/mcp.d.ts +14 -0
  184. package/dist/types/run.d.ts +15 -1
  185. package/dist/workflow.d.cts +1 -1
  186. package/dist/workflow.d.ts +1 -1
  187. package/docs/adr/mutation-testing-scope.md +12 -2
  188. package/docs/error-codes.md +41 -40
  189. package/docs/harness-capability-map.md +32 -6
  190. package/package.json +1 -1
  191. package/dist/chunk-2WY2OFSC.cjs.map +0 -1
  192. package/dist/chunk-4TEGFMSP.cjs.map +0 -1
  193. package/dist/chunk-6CXRYPG7.cjs +0 -211
  194. package/dist/chunk-6CXRYPG7.cjs.map +0 -1
  195. package/dist/chunk-CJN5CEI3.js.map +0 -1
  196. package/dist/chunk-GARVAUCU.js.map +0 -1
  197. package/dist/chunk-MSEL5E5P.js +0 -204
  198. package/dist/chunk-MSEL5E5P.js.map +0 -1
  199. package/dist/chunk-NP362THY.cjs.map +0 -1
  200. package/dist/chunk-Q5EWJPRY.js +0 -18
  201. package/dist/chunk-Q5EWJPRY.js.map +0 -1
  202. package/dist/chunk-R5UQL2R5.cjs +0 -18
  203. package/dist/chunk-RN3XDZGS.js.map +0 -1
  204. package/dist/chunk-SNVYOX46.cjs.map +0 -1
  205. package/dist/chunk-WDVG5R2Q.cjs.map +0 -1
  206. package/dist/chunk-ZF2LDKQQ.cjs.map +0 -1
  207. package/dist/chunk-ZJAYFSVI.js.map +0 -1
  208. package/dist/chunk-ZOL3L4EH.js.map +0 -1
  209. package/dist/fs-session-store-6ZCCJX3K.js +0 -11
  210. package/dist/fs-session-store-S2AXVJIX.cjs +0 -20
  211. package/dist/subagents-loader-TXOA5EJJ.cjs +0 -16
  212. package/dist/subagents-loader-Z744TAKD.js +0 -7
@@ -1,16 +1,17 @@
1
1
  import { submit, emitRunEvent } from './chunk-HWMGR3HA.js';
2
- import { enqueueSessionWrite, hydrateSession, persistTurnToTranscript, flushSessionWrites, appendSessionMessage, getSessionMessages, discardSession, clearSession } from './chunk-3ONIVO2I.js';
3
- import { IndexManager } from './chunk-2C24NSNV.js';
2
+ import { enqueueSessionWrite, hydrateSession, persistTurnToTranscript, flushSessionWrites, appendSessionMessage, getSessionMessages, discardSession, clearSession } from './chunk-23SS4ID4.js';
3
+ import { IndexManager } from './chunk-3BBTHFGJ.js';
4
4
  import { currentPersonalityContext, warnPersonalitySwitchInsideFork } from './chunk-HJ2LV464.js';
5
5
  import { extractCodePlugins, isCodePlugin } from './chunk-2SFBB54R.js';
6
- import { createOpenAiCompatibleRuntime } from './chunk-H7G65PNI.js';
6
+ import { createOpenAiCompatibleRuntime } from './chunk-VCQ37TC5.js';
7
7
  import { persistActiveMemoryTranscript } from './chunk-QK2ERTO3.js';
8
- import { resolveMaxFacts, writeSessionSummary, resolveMemoryRoot, MEMORY_KINDS, appendFact, readFacts, legacyMemoryJsonPath, memoryMdPath, appendFactToMarkdown } from './chunk-DF77RBF4.js';
9
- import { FsSessionStore } from './chunk-AB4OPJLD.js';
10
- import { discoverProviderPlugins, validateApiKeyShape, getConfiguredBaseUrl, httpRequest, isFixtureApiKey, presentProviderCredentialEnvVars, readTrustArray, buildDefaultSummarizer, shouldUseRealLocalRuntime, parseSseStream, CircuitBreaker, trustFilePath, resolveRunProvider, mergeExplicitApiKey, resolveProviderChain, abortError, tryFirstEvent, relayStream, renderToolResultContentText } from './chunk-ZOL3L4EH.js';
8
+ import { resolveMaxFacts, writeSessionSummary, resolveMemoryRoot, MEMORY_KINDS, appendFact, readFacts, legacyMemoryJsonPath, memoryMdPath, appendFactToMarkdown } from './chunk-LCCT5ZXJ.js';
9
+ import { FsSessionStore } from './chunk-RGVMJU57.js';
10
+ import { discoverProviderPlugins, validateApiKeyShape, getConfiguredBaseUrl, httpRequest, isFixtureApiKey, presentProviderCredentialEnvVars, readTrustArray, buildDefaultSummarizer, shouldUseRealLocalRuntime, parseSseStream, CircuitBreaker, trustFilePath, resolveRunProvider, mergeExplicitApiKey, resolveProviderChain, abortError, tryFirstEvent, relayStream, renderToolResultContentText } from './chunk-IOBHFP2E.js';
11
11
  import { resolveChildEnv } from './chunk-HKCKOAIO.js';
12
12
  import { DEFAULT_MAX_BYTES_PER_FILE, runDiscovery, truncateWithMarker } from './chunk-KCM3RMKR.js';
13
13
  import { warnFailureOnce, loadHookConfig, warnOnce } from './chunk-XJ3WU5CZ.js';
14
+ import { getTokens, lockedRefresh, refreshAccessToken, runPkceFlow, setTokens } from './chunk-X7CE7Y5W.js';
14
15
  import { readVersionedJson, writeVersionedJson } from './chunk-OLJOI4LK.js';
15
16
  import { toJsonSchema } from './chunk-7I5Z3UBJ.js';
16
17
  import { sanitizeToolInput } from './chunk-FJWQP6EE.js';
@@ -22,21 +23,21 @@ import { validateArtifactPath, PathTraversalError, safePathJoin } from './chunk-
22
23
  import { insideRoot, atOrInsideRoot } from './chunk-UKMBRMGT.js';
23
24
  import { mapWithConcurrency } from './chunk-ORLTGPOS.js';
24
25
  import { expandTilde, defaultBaseDir } from './chunk-XESYJ4JC.js';
25
- import { withFileLock } from './chunk-354F3OF5.js';
26
- import { withCwdMutex } from './chunk-Q5EWJPRY.js';
26
+ import { withFileLock } from './chunk-FGGVSHDW.js';
27
+ import { withCwdMutex } from './chunk-PPU2D4FZ.js';
27
28
  import { sweepStaleAtomicTemps, atomicWriteJson } from './chunk-M4U24U6G.js';
28
- import { loadSubagents, pluginBundleDirs } from './chunk-RN3XDZGS.js';
29
+ import { loadSubagents, pluginBundleDirs } from './chunk-WM646HEN.js';
29
30
  import { reportUndeclaredSources, theokitConfigRoot, undefinedVariablesIn, getTheokitHome, adapterForConfigPath, adaptersForSurface, projectConfigRoots, pluginBundleRoots } from './chunk-YMVTUV5K.js';
30
31
  import { readWorkspaceDir, parseSimpleYaml } from './chunk-Q7UG242V.js';
31
32
  import { resolveEffectiveContextWindow, CONTEXT_WINDOW_FLOOR, CONTEXT_WINDOW_MARGIN } from './chunk-SZQFCHU6.js';
32
- import { isAnthropicFamilyModel } from './chunk-NVQSBRG6.js';
33
+ import { isAnthropicFamilyModel } from './chunk-CBBT42VX.js';
33
34
  import { parseModelId } from './chunk-R7WIIPUR.js';
34
- import { getProviderProfile } from './chunk-ULEK4OM4.js';
35
- import { getCatalogModelInfo, isPatchedModelKey } from './chunk-CJN5CEI3.js';
35
+ import { getProviderProfile } from './chunk-YKNBTHMD.js';
36
+ import { getCatalogModelInfo, isPatchedModelKey } from './chunk-RZL2W4C3.js';
36
37
  import { globalSingleton } from './chunk-AGACYRJ2.js';
37
38
  import { boundFetch } from './chunk-Q7GYMXVC.js';
38
- import { AgentRunError, coerceToKnownAgentRunErrorCode, UnknownAgentError, ConfigurationError, AuthenticationError, AgentDisposedError, UnsupportedRunOperationError, NetworkError, TheokitAgentError } from './chunk-TNFOU6SB.js';
39
- import { diag, resolveApiKey, API_KEY_ENV_VAR, redactSecrets, diagFailure } from './chunk-3OY6H3I7.js';
39
+ import { AgentRunError, coerceToKnownAgentRunErrorCode, UnknownAgentError, ConfigurationError, AuthenticationError, AgentDisposedError, UnsupportedRunOperationError, TheokitAgentError, NetworkError } from './chunk-TNFOU6SB.js';
40
+ import { diag, resolveApiKey, diagFailure, API_KEY_ENV_VAR, redactSecrets } from './chunk-3OY6H3I7.js';
40
41
  import { stat, mkdir, readFile, readdir, access, unlink } from 'fs/promises';
41
42
  import { randomUUID, createHash } from 'crypto';
42
43
  import { join, dirname, isAbsolute, delimiter, resolve, relative } from 'path';
@@ -1673,7 +1674,10 @@ var RealCloudRun = class extends FixtureRunBase {
1673
1674
  await this.consumeStream(response);
1674
1675
  } catch (cause) {
1675
1676
  if (this.terminated) return;
1676
- this.fail(cause instanceof Error ? cause.message : String(cause));
1677
+ this.fail(
1678
+ cause instanceof Error ? cause.message : String(cause),
1679
+ cause instanceof TheokitAgentError ? cause : void 0
1680
+ );
1677
1681
  }
1678
1682
  }
1679
1683
  async postRun(apiKey, baseUrl) {
@@ -1751,13 +1755,17 @@ var RealCloudRun = class extends FixtureRunBase {
1751
1755
  message: { role: "assistant", content: [{ type: "text", text }] }
1752
1756
  };
1753
1757
  }
1754
- fail(message, code) {
1758
+ fail(message, cause) {
1755
1759
  const event = this.buildAssistantEvent(message);
1756
1760
  this.script.events.push(event);
1757
1761
  this.notifyNewEvents();
1758
1762
  this.script.result = message;
1759
1763
  if (this.script.errorDetail === void 0) {
1760
- this.script.errorDetail = { message, ...code !== void 0 ? { code } : {} };
1764
+ this.script.errorDetail = {
1765
+ message,
1766
+ ...cause?.code !== void 0 ? { code: cause.code } : {},
1767
+ ...cause !== void 0 ? { cause } : {}
1768
+ };
1761
1769
  }
1762
1770
  this.transitionTo("error");
1763
1771
  }
@@ -3163,6 +3171,177 @@ async function importEntry(candidate) {
3163
3171
  function isGeneralPlugin(value) {
3164
3172
  return isCodePlugin(value) && value.kind === "general" && typeof value.name === "string";
3165
3173
  }
3174
+
3175
+ // src/internal/runtime/registry/live-agent-registry.ts
3176
+ var DEFAULT_MAX_AGENTS = 100;
3177
+ var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
3178
+ var DEFAULT_SWEEP_INTERVAL_MS = 6e4;
3179
+ var LiveAgentRegistry = class {
3180
+ #agents = /* @__PURE__ */ new Map();
3181
+ #maxAgents = DEFAULT_MAX_AGENTS;
3182
+ #idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_MS;
3183
+ #sweepIntervalMs = DEFAULT_SWEEP_INTERVAL_MS;
3184
+ #onEvict;
3185
+ #sweepTimer;
3186
+ /**
3187
+ * Reconfigure registry behavior. Process-wide singleton (D310) — last
3188
+ * configure call wins for all subsequent operations.
3189
+ */
3190
+ configure(opts) {
3191
+ if (opts.maxAgents !== void 0) this.#maxAgents = Math.max(0, opts.maxAgents);
3192
+ if (opts.idleTimeoutMs !== void 0) this.#idleTimeoutMs = Math.max(0, opts.idleTimeoutMs);
3193
+ if (opts.sweepIntervalMs !== void 0)
3194
+ this.#sweepIntervalMs = Math.max(1e3, opts.sweepIntervalMs);
3195
+ this.#onEvict = opts.onEvict;
3196
+ this.#stopSweep();
3197
+ if (this.#idleTimeoutMs > 0) this.#startSweep();
3198
+ }
3199
+ /**
3200
+ * Lookup a cached agent. `get` is a use — refreshes `lastUsedAt` so the
3201
+ * entry survives LRU eviction.
3202
+ */
3203
+ get(id) {
3204
+ const entry = this.#agents.get(id);
3205
+ if (entry === void 0) return void 0;
3206
+ entry.lastUsedAt = Date.now();
3207
+ return entry.agent;
3208
+ }
3209
+ /**
3210
+ * Insert or overwrite an agent in the cache. Triggers fire-and-forget LRU
3211
+ * eviction when `size > maxAgents`.
3212
+ *
3213
+ * EC-4: when `id` already maps to a DIFFERENT agent instance, dispose the
3214
+ * old one before overwriting (race protection against two `getOrCreate`
3215
+ * calls creating two agents but only the second being cached — the first
3216
+ * would leak file handles + lifecycle controllers).
3217
+ */
3218
+ set(id, agent) {
3219
+ if (this.#maxAgents === 0) return;
3220
+ const existing = this.#agents.get(id);
3221
+ if (existing !== void 0 && existing.agent !== agent) {
3222
+ void existing.agent.dispose().catch(() => {
3223
+ diag(`[theokit-sdk] dispose during overwrite failed (${id})
3224
+ `);
3225
+ });
3226
+ }
3227
+ this.#agents.set(id, { agent, lastUsedAt: Date.now() });
3228
+ if (this.#agents.size > this.#maxAgents) void this.#evictLRU();
3229
+ }
3230
+ /**
3231
+ * Remove the entry from the cache WITHOUT calling `dispose()` or
3232
+ * `onEvict`. Used by `LocalAgent.dispose()` itself so the disposed
3233
+ * instance can never be returned by a subsequent `get(id)` (dispose-cache
3234
+ * race fix). Idempotent — calling on an unknown id is a no-op.
3235
+ *
3236
+ * @internal
3237
+ */
3238
+ forget(id) {
3239
+ this.#agents.delete(id);
3240
+ }
3241
+ /**
3242
+ * Explicitly evict an agent by id. Returns `true` when the entry was
3243
+ * present (false = already gone). Calls `agent.dispose()` + `onEvict`
3244
+ * with reason `"explicit"`.
3245
+ */
3246
+ async evict(id) {
3247
+ const entry = this.#agents.get(id);
3248
+ if (entry === void 0) return false;
3249
+ this.#agents.delete(id);
3250
+ await this.#disposeAndNotify(id, entry.agent, "explicit");
3251
+ return true;
3252
+ }
3253
+ /**
3254
+ * Evict every cached agent. Used by graceful shutdown (`process.on('SIGTERM')`)
3255
+ * or end-of-test cleanup.
3256
+ */
3257
+ async evictAll() {
3258
+ const entries = Array.from(this.#agents.entries());
3259
+ this.#agents.clear();
3260
+ this.#stopSweep();
3261
+ for (const [id, entry] of entries) {
3262
+ await this.#disposeAndNotify(id, entry.agent, "explicit");
3263
+ }
3264
+ }
3265
+ /** Number of currently cached agents. */
3266
+ size() {
3267
+ return this.#agents.size;
3268
+ }
3269
+ /** Ids of cached agents, newest first (by lastUsedAt). */
3270
+ ids() {
3271
+ return Array.from(this.#agents.entries()).sort((a, b) => b[1].lastUsedAt - a[1].lastUsedAt).map(([id]) => id);
3272
+ }
3273
+ /**
3274
+ * LRU eviction: drop the entry with the smallest `lastUsedAt`. Runs only
3275
+ * when `size > maxAgents`. Asynchronous because `dispose()` is a Promise;
3276
+ * the hot-path caller (`set`) does not await.
3277
+ *
3278
+ * @internal
3279
+ */
3280
+ async #evictLRU() {
3281
+ if (this.#agents.size <= this.#maxAgents) return;
3282
+ let oldestId;
3283
+ let oldestAt = Infinity;
3284
+ for (const [id, entry2] of this.#agents) {
3285
+ if (entry2.lastUsedAt < oldestAt) {
3286
+ oldestAt = entry2.lastUsedAt;
3287
+ oldestId = id;
3288
+ }
3289
+ }
3290
+ if (oldestId === void 0) return;
3291
+ const entry = this.#agents.get(oldestId);
3292
+ if (entry === void 0) return;
3293
+ this.#agents.delete(oldestId);
3294
+ await this.#disposeAndNotify(oldestId, entry.agent, "lru");
3295
+ }
3296
+ /** Background sweep — drops entries whose `lastUsedAt < now - idleTimeoutMs`. */
3297
+ async #sweepIdle() {
3298
+ if (this.#idleTimeoutMs === 0) return;
3299
+ const threshold = Date.now() - this.#idleTimeoutMs;
3300
+ const toEvict = [];
3301
+ for (const [id, entry] of this.#agents) {
3302
+ if (entry.lastUsedAt < threshold) toEvict.push([id, entry]);
3303
+ }
3304
+ for (const [id, entry] of toEvict) {
3305
+ const current = this.#agents.get(id);
3306
+ if (current === void 0 || current.agent !== entry.agent) continue;
3307
+ this.#agents.delete(id);
3308
+ await this.#disposeAndNotify(id, entry.agent, "idle");
3309
+ }
3310
+ }
3311
+ #startSweep() {
3312
+ this.#sweepTimer = setInterval(() => void this.#sweepIdle(), this.#sweepIntervalMs);
3313
+ this.#sweepTimer.unref?.();
3314
+ }
3315
+ #stopSweep() {
3316
+ if (this.#sweepTimer !== void 0) {
3317
+ clearInterval(this.#sweepTimer);
3318
+ this.#sweepTimer = void 0;
3319
+ }
3320
+ }
3321
+ /** Dispose + notify with errors swallowed (D309). Single chokepoint. */
3322
+ async #disposeAndNotify(id, agent, reason) {
3323
+ try {
3324
+ await agent.dispose();
3325
+ } catch (cause) {
3326
+ const msg = cause instanceof Error ? cause.message : String(cause);
3327
+ diag(`[theokit-sdk] dispose during eviction failed (${id}): ${msg}
3328
+ `);
3329
+ }
3330
+ if (this.#onEvict !== void 0) {
3331
+ try {
3332
+ this.#onEvict(id, reason);
3333
+ } catch (cause) {
3334
+ const msg = cause instanceof Error ? cause.message : String(cause);
3335
+ diag(`[theokit-sdk] onEvict listener threw (${id}): ${msg}
3336
+ `);
3337
+ }
3338
+ }
3339
+ }
3340
+ };
3341
+ var liveAgentRegistry = globalSingleton(
3342
+ "theokit-sdk.runtime.live-agents",
3343
+ () => new LiveAgentRegistry()
3344
+ );
3166
3345
  function executableExtensions() {
3167
3346
  return process.platform === "win32" ? ["", ...(process.env.PATHEXT ?? ".EXE;.CMD").split(";")] : [""];
3168
3347
  }
@@ -3182,8 +3361,9 @@ function binaryOnPath(bin) {
3182
3361
  );
3183
3362
  }
3184
3363
  var SkillsManager = class {
3185
- constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline, compatSources = [], bundledDirs = []) {
3364
+ constructor(cwd, enabled, settingSourcesIncludeProject, skillsDir, inline, compatSources = [], bundledDirs = []) {
3186
3365
  this.cwd = cwd;
3366
+ this.enabled = enabled;
3187
3367
  this.settingSourcesIncludeProject = settingSourcesIncludeProject;
3188
3368
  this.skillsDir = skillsDir;
3189
3369
  this.inline = inline;
@@ -3191,6 +3371,7 @@ var SkillsManager = class {
3191
3371
  this.bundledDirs = bundledDirs;
3192
3372
  }
3193
3373
  cwd;
3374
+ enabled;
3194
3375
  settingSourcesIncludeProject;
3195
3376
  skillsDir;
3196
3377
  inline;
@@ -3236,8 +3417,12 @@ var SkillsManager = class {
3236
3417
  const inlineNames = new Set(this.inline.map((s) => s.name));
3237
3418
  return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
3238
3419
  }
3420
+ visible() {
3421
+ const allowed = this.enabled;
3422
+ return allowed === void 0 ? this.skills : this.skills.filter((s) => allowed.includes(s.name));
3423
+ }
3239
3424
  list() {
3240
- return Promise.resolve(this.skills);
3425
+ return Promise.resolve(this.visible());
3241
3426
  }
3242
3427
  /**
3243
3428
  * SE20 — resolve a skill by name INCLUDING its body. Inline (`createSkill`)
@@ -3246,7 +3431,7 @@ var SkillsManager = class {
3246
3431
  * enabled skill matches (malformed skills were already excluded at discovery).
3247
3432
  */
3248
3433
  async get(name) {
3249
- const skill = this.skills.find((s) => s.name === name);
3434
+ const skill = this.visible().find((s) => s.name === name);
3250
3435
  if (skill === void 0) return void 0;
3251
3436
  const instructions = typeof skill.instructions === "string" ? skill.instructions : stripSkillFrontmatter(await readFile(skill.source, "utf8"));
3252
3437
  const references = skill.references;
@@ -3674,6 +3859,23 @@ function validateMcpServers(options) {
3674
3859
  { code: "cloud_stdio_cwd_rejected" }
3675
3860
  );
3676
3861
  }
3862
+ rejectUnhonourableAuth(name, config, options.cloud !== void 0);
3863
+ }
3864
+ }
3865
+ function rejectUnhonourableAuth(name, config, cloud) {
3866
+ const auth = config.auth;
3867
+ if (auth === void 0) return;
3868
+ if (auth.oauth === void 0) {
3869
+ throw new ConfigurationError(
3870
+ `MCP server "${name}" declares auth without auth.oauth, which the SDK cannot honour; use auth.oauth or set an Authorization header`,
3871
+ { code: "mcp_auth_unsupported" }
3872
+ );
3873
+ }
3874
+ if (cloud) {
3875
+ throw new ConfigurationError(
3876
+ `MCP server "${name}" declares auth.oauth, which the SDK cannot run for a cloud agent`,
3877
+ { code: "mcp_auth_unsupported" }
3878
+ );
3677
3879
  }
3678
3880
  }
3679
3881
  function isStdioWithCwd(config) {
@@ -4190,8 +4392,13 @@ function wrapSpan(span, openSpans) {
4190
4392
  setAttribute: (k, v) => safe(() => span.setAttribute(k, redactAttrValue(v)), void 0),
4191
4393
  setAttributes: (attrs) => safe(() => span.setAttributes(redactAttrs(attrs)), void 0),
4192
4394
  addEvent: (name, attrs) => safe(() => span.addEvent(name, attrs ? redactAttrs(attrs) : void 0), void 0),
4193
- setStatus: (status) => safe(() => span.setStatus(status), void 0),
4194
- recordException: (err) => safe(() => span.recordException(err), void 0),
4395
+ setStatus: (status) => safe(
4396
+ () => span.setStatus(
4397
+ status.message === void 0 ? status : { ...status, message: redactSecrets(status.message) }
4398
+ ),
4399
+ void 0
4400
+ ),
4401
+ recordException: (err) => safe(() => span.recordException(redactException(err)), void 0),
4195
4402
  end: (endTime) => {
4196
4403
  safe(() => span.end(endTime), void 0);
4197
4404
  openSpans.delete(span);
@@ -4200,6 +4407,18 @@ function wrapSpan(span, openSpans) {
4200
4407
  isRecording: () => safe(() => span.isRecording(), false)
4201
4408
  };
4202
4409
  }
4410
+ function redactException(err) {
4411
+ if (typeof err === "string") return redactSecrets(err);
4412
+ if (typeof err !== "object" || err === null) return err;
4413
+ const src = err;
4414
+ const out = {};
4415
+ for (const k of ["name", "code", "message", "stack"]) {
4416
+ const v = src[k];
4417
+ if (typeof v === "string") out[k] = redactSecrets(v);
4418
+ else if (typeof v === "number") out[k] = v;
4419
+ }
4420
+ return out;
4421
+ }
4203
4422
  function redactAttrValue(value) {
4204
4423
  if (typeof value !== "string") return value;
4205
4424
  return redactSecrets(value);
@@ -5164,7 +5383,9 @@ function evaluateBudgetGate(tracker) {
5164
5383
  return {
5165
5384
  allowed: false,
5166
5385
  reason: "custom",
5167
- detail: `budget_tracker_check_threw: ${message}`
5386
+ detail: `budget_tracker_check_threw: ${message}`,
5387
+ // Keep the thrown value so the run's error can carry it as its cause.
5388
+ cause: error
5168
5389
  };
5169
5390
  }
5170
5391
  }
@@ -5174,11 +5395,12 @@ function createDoomLoopTracker(option) {
5174
5395
  if (option === false) return void 0;
5175
5396
  return new DoomLoopTracker(option);
5176
5397
  }
5177
- var DEFAULT_CONFIG = { softThreshold: 3, hardThreshold: 5 };
5178
- function assertValidThresholds(soft, hard) {
5398
+ var DEFAULT_CONFIG = { softThreshold: 3, hardThreshold: 5, churnThreshold: 6 };
5399
+ function assertValidThresholds(soft, hard, churn) {
5179
5400
  for (const [label, value] of [
5180
5401
  ["softThreshold", soft],
5181
- ["hardThreshold", hard]
5402
+ ["hardThreshold", hard],
5403
+ ["churnThreshold", churn]
5182
5404
  ]) {
5183
5405
  if (!Number.isInteger(value) || value < 1) {
5184
5406
  throw new ConfigurationError(
@@ -5215,17 +5437,40 @@ var DoomLoopTracker = class {
5215
5437
  #config;
5216
5438
  #lastSignature = "";
5217
5439
  #count = 0;
5440
+ #lastName = "";
5441
+ #lastResult;
5442
+ #churn = 0;
5218
5443
  constructor(config) {
5219
5444
  const softThreshold = config?.softThreshold ?? DEFAULT_CONFIG.softThreshold;
5220
5445
  const hardThreshold = config?.hardThreshold ?? DEFAULT_CONFIG.hardThreshold;
5221
- assertValidThresholds(softThreshold, hardThreshold);
5222
- this.#config = { softThreshold, hardThreshold };
5446
+ const churnThreshold = config?.churnThreshold ?? DEFAULT_CONFIG.churnThreshold;
5447
+ assertValidThresholds(softThreshold, hardThreshold, churnThreshold);
5448
+ this.#config = { softThreshold, hardThreshold, churnThreshold };
5223
5449
  }
5224
5450
  inspect(call) {
5225
5451
  const signature = signatureOf(call);
5226
- this.#count = signature === this.#lastSignature ? this.#count + 1 : 1;
5452
+ const identical = signature === this.#lastSignature;
5453
+ const churning = !identical && call.name === this.#lastName && call.result !== void 0 && call.result === this.#lastResult;
5454
+ this.#churn = churning ? this.#churn + 1 : 1;
5455
+ this.#lastName = call.name;
5456
+ this.#lastResult = call.result;
5457
+ this.#count = identical ? this.#count + 1 : 1;
5227
5458
  this.#lastSignature = signature;
5228
5459
  const count = this.#count;
5460
+ const churn = this.#churn;
5461
+ const churnHard = this.#config.churnThreshold;
5462
+ if (churn >= churnHard) {
5463
+ return {
5464
+ kind: "hard",
5465
+ message: `Detected argument churn: ${churn} consecutive calls to \`${call.name}\` with different arguments and no change in the result; stopping to avoid a loop.`
5466
+ };
5467
+ }
5468
+ if (churn > 1 && churn === Math.max(2, churnHard - 2)) {
5469
+ return {
5470
+ kind: "soft",
5471
+ message: `Detected argument churn: ${churn} consecutive calls to \`${call.name}\` with different arguments and no change in the result; try a different approach.`
5472
+ };
5473
+ }
5229
5474
  if (count >= this.#config.hardThreshold) {
5230
5475
  return {
5231
5476
  kind: "hard",
@@ -5243,6 +5488,9 @@ var DoomLoopTracker = class {
5243
5488
  reset() {
5244
5489
  this.#lastSignature = "";
5245
5490
  this.#count = 0;
5491
+ this.#lastName = "";
5492
+ this.#lastResult = void 0;
5493
+ this.#churn = 0;
5246
5494
  }
5247
5495
  };
5248
5496
  function firstDoomLoopVerdict(tracker, calls) {
@@ -5487,7 +5735,16 @@ async function initLoopContext(inputs) {
5487
5735
  ),
5488
5736
  buildUserEvent(inputs)
5489
5737
  ]);
5490
- if (inputs.onLoopEvent !== void 0) events.subscribe(inputs.onLoopEvent);
5738
+ if (inputs.onLoopEvent !== void 0) {
5739
+ const sink = inputs.onLoopEvent;
5740
+ for (const seeded of events) {
5741
+ try {
5742
+ sink(seeded);
5743
+ } catch {
5744
+ }
5745
+ }
5746
+ events.subscribe(sink);
5747
+ }
5491
5748
  const priorMessages = replayMessages(inputs.priorMessages ?? []);
5492
5749
  let memorySystemPromptAdditions;
5493
5750
  if (inputs.memoryProvider !== void 0 && memoryProviderHandle !== void 0) {
@@ -5576,7 +5833,8 @@ async function collectTools(mcp, withheld, sink) {
5576
5833
  inputSchema: tool.inputSchema,
5577
5834
  origin: "mcp",
5578
5835
  mcpServerName: serverName,
5579
- mcpToolName: tool.name
5836
+ mcpToolName: tool.name,
5837
+ ...client.sequential === true ? { mcpSequential: true } : {}
5580
5838
  });
5581
5839
  }
5582
5840
  }
@@ -6563,11 +6821,35 @@ function raceToolExecution(exec, opts) {
6563
6821
  // src/internal/agent-loop/tool-dispatch.ts
6564
6822
  async function dispatchTools(inputs, tools, toolCalls, events, parentSpan) {
6565
6823
  const maxConcurrent = inputs.maxConcurrentTools ?? 4;
6566
- return mapWithConcurrency(
6567
- toolCalls,
6568
- maxConcurrent,
6569
- (call) => dispatchSingleCall(inputs, tools, call, events, parentSpan)
6570
- );
6824
+ const units = [];
6825
+ const bySequentialServer = /* @__PURE__ */ new Map();
6826
+ toolCalls.forEach((call, index) => {
6827
+ const tool = tools.find((t) => t.name === call.name);
6828
+ if (tool?.mcpSequential === true && tool.mcpServerName !== void 0) {
6829
+ let unit = bySequentialServer.get(tool.mcpServerName);
6830
+ if (unit === void 0) {
6831
+ unit = { indexes: [] };
6832
+ bySequentialServer.set(tool.mcpServerName, unit);
6833
+ units.push(unit);
6834
+ }
6835
+ unit.indexes.push(index);
6836
+ } else {
6837
+ units.push({ indexes: [index] });
6838
+ }
6839
+ });
6840
+ const results = new Array(toolCalls.length);
6841
+ await mapWithConcurrency(units, maxConcurrent, async (unit) => {
6842
+ for (const index of unit.indexes) {
6843
+ results[index] = await dispatchSingleCall(
6844
+ inputs,
6845
+ tools,
6846
+ toolCalls[index],
6847
+ events,
6848
+ parentSpan
6849
+ );
6850
+ }
6851
+ });
6852
+ return results;
6571
6853
  }
6572
6854
  async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
6573
6855
  const { call: workingCall, repairs } = applyRepairAndExtractCall(tools, call);
@@ -6944,12 +7226,17 @@ async function runAgentLoop(inputs) {
6944
7226
  const budget = inputs.budget ?? new IterationBudget({ maxIterations: inputs.maxIterations ?? 8 });
6945
7227
  let lastTurnDecision;
6946
7228
  while (budget.shouldContinue()) {
7229
+ injectSteered(ctx, inputs.steerQueue?.drain());
6947
7230
  if (inputs.budgetTracker !== void 0) {
6948
7231
  const decision2 = evaluateBudgetGate(inputs.budgetTracker);
6949
7232
  if (decision2.allowed === false) {
6950
7233
  ctx.finalStatus = "error";
6951
7234
  if (decision2.detail !== void 0) {
6952
- ctx.error = { message: decision2.detail, code: decision2.reason ?? "budget" };
7235
+ ctx.error = {
7236
+ message: decision2.detail,
7237
+ code: decision2.reason ?? "budget",
7238
+ ...decision2.cause !== void 0 ? { cause: decision2.cause } : {}
7239
+ };
6953
7240
  }
6954
7241
  if (decision2.reason === "iteration_limit") {
6955
7242
  ctx.stoppedAtIterationLimit = true;
@@ -6961,7 +7248,13 @@ async function runAgentLoop(inputs) {
6961
7248
  if (usingGrace) budget.useGraceCall();
6962
7249
  const decision = await runIteration(inputs, ctx);
6963
7250
  lastTurnDecision = decision;
6964
- if (decision === "done") break;
7251
+ if (decision === "done") {
7252
+ const late = inputs.steerQueue?.drainOrClose() ?? [];
7253
+ if (late.length === 0) break;
7254
+ injectSteered(ctx, late);
7255
+ budget.consume();
7256
+ continue;
7257
+ }
6965
7258
  if (decision === "error") {
6966
7259
  ctx.finalStatus = "error";
6967
7260
  break;
@@ -7089,6 +7382,10 @@ async function finishOrReflect(inputs, ctx, llmOutput) {
7089
7382
  ctx.finalStatus = "finished";
7090
7383
  return "done";
7091
7384
  }
7385
+ function injectSteered(ctx, texts) {
7386
+ if (texts === void 0) return;
7387
+ for (const text of texts) ctx.messages.push({ role: "user", content: [{ type: "text", text }] });
7388
+ }
7092
7389
  async function runIteration(inputs, ctx) {
7093
7390
  const hookCtx = { agentId: inputs.agentId, runId: inputs.runId };
7094
7391
  await inputs.pluginManager?.runPreLlmCallHooks(hookCtx);
@@ -7102,12 +7399,11 @@ function trackTurnUsage(inputs, llmOutput) {
7102
7399
  const tracker = inputs.budgetTracker;
7103
7400
  if (tracker === void 0) return;
7104
7401
  const model = inputs.model.id ?? "auto";
7105
- trackEvent(tracker, { tokens: promptTokens(llmOutput), model, type: "input" });
7402
+ trackEvent(tracker, { tokens: llmOutput.inputTokens ?? 0, model, type: "input" });
7403
+ trackEvent(tracker, { tokens: llmOutput.cacheReadTokens ?? 0, model, type: "cache_read" });
7404
+ trackEvent(tracker, { tokens: llmOutput.cacheWriteTokens ?? 0, model, type: "cache_write" });
7106
7405
  trackEvent(tracker, { tokens: llmOutput.outputTokens ?? 0, model, type: "output" });
7107
7406
  }
7108
- function promptTokens(llmOutput) {
7109
- return (llmOutput.inputTokens ?? 0) + (llmOutput.cacheReadTokens ?? 0) + (llmOutput.cacheWriteTokens ?? 0);
7110
- }
7111
7407
  function trackEvent(tracker, event) {
7112
7408
  if (event.tokens <= 0) return;
7113
7409
  try {
@@ -7166,12 +7462,22 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
7166
7462
  }
7167
7463
  }
7168
7464
  pushToolConversationSteps(ctx, llmOutput.toolCalls, toolResults);
7169
- if (await inspectDoomLoop(inputs, ctx, llmOutput.toolCalls) === "stop") return "done";
7465
+ if (await inspectDoomLoop(inputs, ctx, llmOutput.toolCalls, toolResults) === "stop")
7466
+ return "done";
7170
7467
  return handleToolErrorContinuation(inputs, ctx, toolResults);
7171
7468
  }
7172
- async function inspectDoomLoop(inputs, ctx, toolCalls) {
7469
+ async function inspectDoomLoop(inputs, ctx, toolCalls, toolResults) {
7173
7470
  if (ctx.doomLoop === void 0) return "continue";
7174
- const verdict = firstDoomLoopVerdict(ctx.doomLoop, toolCalls);
7471
+ const resultById = /* @__PURE__ */ new Map();
7472
+ for (const part of toolResults) {
7473
+ if (part.type === "tool_result") {
7474
+ resultById.set(part.toolUseId, JSON.stringify([part.content, part.isError === true]));
7475
+ }
7476
+ }
7477
+ const verdict = firstDoomLoopVerdict(
7478
+ ctx.doomLoop,
7479
+ toolCalls.map((c) => ({ name: c.name, input: c.input, result: resultById.get(c.id) }))
7480
+ );
7175
7481
  if (verdict.kind === "hard") {
7176
7482
  ctx.stoppedByDoomLoop = true;
7177
7483
  await emitAssistantTextStep(
@@ -7248,6 +7554,34 @@ function handshakeAwareTimeout(input) {
7248
7554
  return isReconnectHandshake ? Math.max(input.requestTimeoutMs, HANDSHAKE_FLOOR_MS) : input.requestTimeoutMs;
7249
7555
  }
7250
7556
 
7557
+ // src/internal/mcp/oauth-bearer.ts
7558
+ var EXPIRY_SKEW_MS = 3e4;
7559
+ async function obtain(serverName, clientId, scopes, oauth) {
7560
+ const stored = await getTokens(serverName);
7561
+ if (stored?.accessToken !== void 0 && stored.expiresAt - EXPIRY_SKEW_MS > Date.now()) {
7562
+ return stored;
7563
+ }
7564
+ const refreshToken = stored?.refreshToken;
7565
+ if (refreshToken !== void 0) {
7566
+ try {
7567
+ return await lockedRefresh(
7568
+ serverName,
7569
+ () => refreshAccessToken(serverName, clientId, refreshToken, oauth)
7570
+ );
7571
+ } catch {
7572
+ }
7573
+ }
7574
+ const fresh = await runPkceFlow(serverName, clientId, scopes, oauth);
7575
+ await setTokens(serverName, fresh);
7576
+ return fresh;
7577
+ }
7578
+ async function resolveBearer(serverName, auth) {
7579
+ if (auth.oauth === void 0)
7580
+ throw new Error(`MCP server "${serverName}" declares no auth.oauth`);
7581
+ const tokens = await obtain(serverName, auth.CLIENT_ID, auth.scopes, auth.oauth);
7582
+ return `Bearer ${tokens.accessToken}`;
7583
+ }
7584
+
7251
7585
  // src/internal/mcp/client.ts
7252
7586
  function createMcpClient(name, config, fetchImpl = fetch) {
7253
7587
  if (isStdio(config)) return new StdioMcpClient(name, config);
@@ -7328,6 +7662,9 @@ var StdioMcpClient = class extends BaseMcpClient {
7328
7662
  reconnectPromise;
7329
7663
  /** True only while `reconnect()`'s handshake is in flight — see `timeoutFor`. */
7330
7664
  reconnecting = false;
7665
+ get sequential() {
7666
+ return this.config.sequential === true;
7667
+ }
7331
7668
  get timeoutMs() {
7332
7669
  return this.config.requestTimeoutMs ?? DEFAULT_MCP_TIMEOUT_MS;
7333
7670
  }
@@ -7534,6 +7871,9 @@ var HttpMcpClient = class extends BaseMcpClient {
7534
7871
  */
7535
7872
  sessionId;
7536
7873
  fetchImpl;
7874
+ get sequential() {
7875
+ return this.config.sequential === true;
7876
+ }
7537
7877
  close() {
7538
7878
  return Promise.resolve();
7539
7879
  }
@@ -7546,7 +7886,9 @@ var HttpMcpClient = class extends BaseMcpClient {
7546
7886
  * override contract predates this change and is the only escape a user has while a server
7547
7887
  * misbehaves.
7548
7888
  */
7549
- buildHeaders() {
7889
+ async buildHeaders() {
7890
+ const auth = this.config.auth;
7891
+ const bearer = auth?.oauth !== void 0 ? await resolveBearer(this.name, auth) : void 0;
7550
7892
  return {
7551
7893
  "content-type": "application/json",
7552
7894
  // Streamable HTTP asks for BOTH media types. Declaring only `application/json` makes a
@@ -7555,6 +7897,7 @@ var HttpMcpClient = class extends BaseMcpClient {
7555
7897
  // Present only for a STATEFUL server. For a stateless one nothing is sent — inventing a
7556
7898
  // header would trade one broken transport for another.
7557
7899
  ...this.sessionId !== void 0 ? { "mcp-session-id": this.sessionId } : {},
7900
+ ...bearer !== void 0 ? { authorization: bearer } : {},
7558
7901
  ...this.config.headers ?? {}
7559
7902
  };
7560
7903
  }
@@ -7597,7 +7940,7 @@ var HttpMcpClient = class extends BaseMcpClient {
7597
7940
  async request(method, params) {
7598
7941
  const id = this.nextId++;
7599
7942
  const payload = { jsonrpc: "2.0", id, method, params };
7600
- const headers = this.buildHeaders();
7943
+ const headers = await this.buildHeaders();
7601
7944
  const timeoutMs = this.config.requestTimeoutMs ?? DEFAULT_MCP_TIMEOUT_MS;
7602
7945
  let response;
7603
7946
  try {
@@ -7944,6 +8287,7 @@ function buildLoopInputs(options, runId, userText, userImages) {
7944
8287
  ...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
7945
8288
  // SE2 — forward the opt-in typed runtime-event sink to the loop.
7946
8289
  ...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
8290
+ ...options.steerQueue !== void 0 ? { steerQueue: options.steerQueue } : {},
7947
8291
  ...toolResultPolicyInputs(options.sendOptions),
7948
8292
  // M1-2: per-send iteration ceiling (validated above). The loop reads
7949
8293
  // inputs.maxIterations (default 8 when unset).
@@ -8165,7 +8509,8 @@ function buildRealRunOptions(args) {
8165
8509
  ...args.priorMessages.length > 0 ? { priorMessages: args.priorMessages } : {},
8166
8510
  ...args.memoryTools !== void 0 && args.memoryTools.length > 0 ? { memoryTools: args.memoryTools } : {},
8167
8511
  ...args.personalityToolWhitelist !== void 0 ? { personalityToolWhitelist: args.personalityToolWhitelist } : {},
8168
- ...args.personalityName !== void 0 ? { personalityName: args.personalityName } : {}
8512
+ ...args.personalityName !== void 0 ? { personalityName: args.personalityName } : {},
8513
+ ...args.steerQueue !== void 0 ? { steerQueue: args.steerQueue } : {}
8169
8514
  };
8170
8515
  }
8171
8516
  async function createFixtureRunHelper(args) {
@@ -8197,6 +8542,7 @@ async function dispatchLocalRun(args) {
8197
8542
  systemPrompt: args.systemPrompt,
8198
8543
  priorMessages: args.priorMessages,
8199
8544
  memoryTools: args.memoryTools,
8545
+ ...args.steerQueue !== void 0 ? { steerQueue: args.steerQueue } : {},
8200
8546
  ...args.activePreset?.tools !== void 0 ? { personalityToolWhitelist: args.activePreset.tools } : {},
8201
8547
  ...args.activePreset !== void 0 ? { personalityName: args.activePreset.name } : {}
8202
8548
  })
@@ -8249,177 +8595,6 @@ async function consumePending(agentId, pending, clear, refresh) {
8249
8595
  await applyDeferredInvalidation(agentId, pending, refresh);
8250
8596
  }
8251
8597
 
8252
- // src/internal/runtime/registry/live-agent-registry.ts
8253
- var DEFAULT_MAX_AGENTS = 100;
8254
- var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
8255
- var DEFAULT_SWEEP_INTERVAL_MS = 6e4;
8256
- var LiveAgentRegistry = class {
8257
- #agents = /* @__PURE__ */ new Map();
8258
- #maxAgents = DEFAULT_MAX_AGENTS;
8259
- #idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_MS;
8260
- #sweepIntervalMs = DEFAULT_SWEEP_INTERVAL_MS;
8261
- #onEvict;
8262
- #sweepTimer;
8263
- /**
8264
- * Reconfigure registry behavior. Process-wide singleton (D310) — last
8265
- * configure call wins for all subsequent operations.
8266
- */
8267
- configure(opts) {
8268
- if (opts.maxAgents !== void 0) this.#maxAgents = Math.max(0, opts.maxAgents);
8269
- if (opts.idleTimeoutMs !== void 0) this.#idleTimeoutMs = Math.max(0, opts.idleTimeoutMs);
8270
- if (opts.sweepIntervalMs !== void 0)
8271
- this.#sweepIntervalMs = Math.max(1e3, opts.sweepIntervalMs);
8272
- this.#onEvict = opts.onEvict;
8273
- this.#stopSweep();
8274
- if (this.#idleTimeoutMs > 0) this.#startSweep();
8275
- }
8276
- /**
8277
- * Lookup a cached agent. `get` is a use — refreshes `lastUsedAt` so the
8278
- * entry survives LRU eviction.
8279
- */
8280
- get(id) {
8281
- const entry = this.#agents.get(id);
8282
- if (entry === void 0) return void 0;
8283
- entry.lastUsedAt = Date.now();
8284
- return entry.agent;
8285
- }
8286
- /**
8287
- * Insert or overwrite an agent in the cache. Triggers fire-and-forget LRU
8288
- * eviction when `size > maxAgents`.
8289
- *
8290
- * EC-4: when `id` already maps to a DIFFERENT agent instance, dispose the
8291
- * old one before overwriting (race protection against two `getOrCreate`
8292
- * calls creating two agents but only the second being cached — the first
8293
- * would leak file handles + lifecycle controllers).
8294
- */
8295
- set(id, agent) {
8296
- if (this.#maxAgents === 0) return;
8297
- const existing = this.#agents.get(id);
8298
- if (existing !== void 0 && existing.agent !== agent) {
8299
- void existing.agent.dispose().catch(() => {
8300
- diag(`[theokit-sdk] dispose during overwrite failed (${id})
8301
- `);
8302
- });
8303
- }
8304
- this.#agents.set(id, { agent, lastUsedAt: Date.now() });
8305
- if (this.#agents.size > this.#maxAgents) void this.#evictLRU();
8306
- }
8307
- /**
8308
- * Remove the entry from the cache WITHOUT calling `dispose()` or
8309
- * `onEvict`. Used by `LocalAgent.dispose()` itself so the disposed
8310
- * instance can never be returned by a subsequent `get(id)` (dispose-cache
8311
- * race fix). Idempotent — calling on an unknown id is a no-op.
8312
- *
8313
- * @internal
8314
- */
8315
- forget(id) {
8316
- this.#agents.delete(id);
8317
- }
8318
- /**
8319
- * Explicitly evict an agent by id. Returns `true` when the entry was
8320
- * present (false = already gone). Calls `agent.dispose()` + `onEvict`
8321
- * with reason `"explicit"`.
8322
- */
8323
- async evict(id) {
8324
- const entry = this.#agents.get(id);
8325
- if (entry === void 0) return false;
8326
- this.#agents.delete(id);
8327
- await this.#disposeAndNotify(id, entry.agent, "explicit");
8328
- return true;
8329
- }
8330
- /**
8331
- * Evict every cached agent. Used by graceful shutdown (`process.on('SIGTERM')`)
8332
- * or end-of-test cleanup.
8333
- */
8334
- async evictAll() {
8335
- const entries = Array.from(this.#agents.entries());
8336
- this.#agents.clear();
8337
- this.#stopSweep();
8338
- for (const [id, entry] of entries) {
8339
- await this.#disposeAndNotify(id, entry.agent, "explicit");
8340
- }
8341
- }
8342
- /** Number of currently cached agents. */
8343
- size() {
8344
- return this.#agents.size;
8345
- }
8346
- /** Ids of cached agents, newest first (by lastUsedAt). */
8347
- ids() {
8348
- return Array.from(this.#agents.entries()).sort((a, b) => b[1].lastUsedAt - a[1].lastUsedAt).map(([id]) => id);
8349
- }
8350
- /**
8351
- * LRU eviction: drop the entry with the smallest `lastUsedAt`. Runs only
8352
- * when `size > maxAgents`. Asynchronous because `dispose()` is a Promise;
8353
- * the hot-path caller (`set`) does not await.
8354
- *
8355
- * @internal
8356
- */
8357
- async #evictLRU() {
8358
- if (this.#agents.size <= this.#maxAgents) return;
8359
- let oldestId;
8360
- let oldestAt = Infinity;
8361
- for (const [id, entry2] of this.#agents) {
8362
- if (entry2.lastUsedAt < oldestAt) {
8363
- oldestAt = entry2.lastUsedAt;
8364
- oldestId = id;
8365
- }
8366
- }
8367
- if (oldestId === void 0) return;
8368
- const entry = this.#agents.get(oldestId);
8369
- if (entry === void 0) return;
8370
- this.#agents.delete(oldestId);
8371
- await this.#disposeAndNotify(oldestId, entry.agent, "lru");
8372
- }
8373
- /** Background sweep — drops entries whose `lastUsedAt < now - idleTimeoutMs`. */
8374
- async #sweepIdle() {
8375
- if (this.#idleTimeoutMs === 0) return;
8376
- const threshold = Date.now() - this.#idleTimeoutMs;
8377
- const toEvict = [];
8378
- for (const [id, entry] of this.#agents) {
8379
- if (entry.lastUsedAt < threshold) toEvict.push([id, entry]);
8380
- }
8381
- for (const [id, entry] of toEvict) {
8382
- const current = this.#agents.get(id);
8383
- if (current === void 0 || current.agent !== entry.agent) continue;
8384
- this.#agents.delete(id);
8385
- await this.#disposeAndNotify(id, entry.agent, "idle");
8386
- }
8387
- }
8388
- #startSweep() {
8389
- this.#sweepTimer = setInterval(() => void this.#sweepIdle(), this.#sweepIntervalMs);
8390
- this.#sweepTimer.unref?.();
8391
- }
8392
- #stopSweep() {
8393
- if (this.#sweepTimer !== void 0) {
8394
- clearInterval(this.#sweepTimer);
8395
- this.#sweepTimer = void 0;
8396
- }
8397
- }
8398
- /** Dispose + notify with errors swallowed (D309). Single chokepoint. */
8399
- async #disposeAndNotify(id, agent, reason) {
8400
- try {
8401
- await agent.dispose();
8402
- } catch (cause) {
8403
- const msg = cause instanceof Error ? cause.message : String(cause);
8404
- diag(`[theokit-sdk] dispose during eviction failed (${id}): ${msg}
8405
- `);
8406
- }
8407
- if (this.#onEvict !== void 0) {
8408
- try {
8409
- this.#onEvict(id, reason);
8410
- } catch (cause) {
8411
- const msg = cause instanceof Error ? cause.message : String(cause);
8412
- diag(`[theokit-sdk] onEvict listener threw (${id}): ${msg}
8413
- `);
8414
- }
8415
- }
8416
- }
8417
- };
8418
- var liveAgentRegistry = globalSingleton(
8419
- "theokit-sdk.runtime.live-agents",
8420
- () => new LiveAgentRegistry()
8421
- );
8422
-
8423
8598
  // src/internal/local-agent/local-agent-lifecycle.ts
8424
8599
  async function acquireLeaseIfPossible(store, agentId) {
8425
8600
  if (typeof store.acquire !== "function") return;
@@ -10138,6 +10313,14 @@ async function applyInputProcessors(inputs, message, rawUserText, options, sendM
10138
10313
  const effectiveMessage = typeof message === "string" ? res.value : { ...message, text: res.value };
10139
10314
  return { userText: res.value, effectiveMessage };
10140
10315
  }
10316
+ var lastSendAt = /* @__PURE__ */ new Map();
10317
+ function applyIdleReset(agentId, minutes) {
10318
+ const now = Date.now();
10319
+ const previous = lastSendAt.get(agentId);
10320
+ lastSendAt.set(agentId, now);
10321
+ if (minutes === void 0 || !Number.isFinite(minutes) || minutes <= 0) return;
10322
+ if (previous !== void 0 && now - previous > minutes * 6e4) clearSession(agentId);
10323
+ }
10141
10324
  async function executeSendLocked(inputs, message, options) {
10142
10325
  if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
10143
10326
  await consumePending(
@@ -10152,6 +10335,7 @@ async function executeSendLocked(inputs, message, options) {
10152
10335
  const gated = await applyInputProcessors(inputs, message, rawUserText, options, sendModel);
10153
10336
  if ("tripwireRun" in gated) return gated.tripwireRun;
10154
10337
  const { userText, effectiveMessage } = gated;
10338
+ applyIdleReset(inputs.agentId, inputs.options.sessionIdleResetMinutes);
10155
10339
  if (inputs.options.onBeforeSend !== void 0) {
10156
10340
  await inputs.options.onBeforeSend({
10157
10341
  conversationId: inputs.agentId,
@@ -10337,6 +10521,43 @@ function reportUnknownLocalOptions(local) {
10337
10521
  }
10338
10522
  }
10339
10523
 
10524
+ // src/internal/local-agent/send-queue.ts
10525
+ var TurnSteerQueue = class {
10526
+ pending = [];
10527
+ closed = false;
10528
+ /** @returns false when the turn can no longer pick the message up. */
10529
+ push(text) {
10530
+ if (this.closed) return false;
10531
+ this.pending.push(text);
10532
+ return true;
10533
+ }
10534
+ drain() {
10535
+ const taken = this.pending;
10536
+ this.pending = [];
10537
+ return taken;
10538
+ }
10539
+ drainOrClose() {
10540
+ const taken = this.drain();
10541
+ if (taken.length === 0) this.closed = true;
10542
+ return taken;
10543
+ }
10544
+ /** Stop accepting and hand back what no loop iteration picked up. */
10545
+ closeAndTake() {
10546
+ this.closed = true;
10547
+ return this.drain();
10548
+ }
10549
+ };
10550
+ function joinCollected(messages) {
10551
+ if (messages.length === 1) return messages[0];
10552
+ const texts = messages.map((m) => typeof m === "string" ? m : m.text);
10553
+ const images = messages.flatMap((m) => typeof m === "string" ? [] : m.images ?? []);
10554
+ const text = texts.join("\n\n");
10555
+ return images.length > 0 ? { text, images } : text;
10556
+ }
10557
+ function hasImages(message) {
10558
+ return typeof message !== "string" && (message.images?.length ?? 0) > 0;
10559
+ }
10560
+
10340
10561
  // src/internal/local-agent/local-agent.ts
10341
10562
  var LocalAgent = class {
10342
10563
  /**
@@ -10385,6 +10606,9 @@ var LocalAgent = class {
10385
10606
  settingSourcesIncludePlugins;
10386
10607
  resolvedSubagents = {};
10387
10608
  disposed = false;
10609
+ activeTurn;
10610
+ inflight = 0;
10611
+ collectBatch;
10388
10612
  invalidationPending;
10389
10613
  skillsManager;
10390
10614
  pluginsManager;
@@ -10509,10 +10733,48 @@ var LocalAgent = class {
10509
10733
  agentId: this.agentId,
10510
10734
  ...this.model?.id !== void 0 ? { model: this.model.id } : {}
10511
10735
  });
10736
+ return this.enqueueSend(message, options, sendSpan);
10737
+ }
10738
+ /** Queue one send behind the lock, or fold it into the running turn / pending batch. */
10739
+ enqueueSend(message, options, sendSpan) {
10740
+ const mode = options.queueMode ?? "followup";
10741
+ const text = typeof message === "string" ? message : message.text;
10742
+ const active = this.activeTurn;
10743
+ if (mode === "steer" && active !== void 0 && !hasImages(message) && active.steer.push(text)) {
10744
+ sendSpan.end();
10745
+ return active.run;
10746
+ }
10747
+ if (mode === "collect" && this.collectBatch !== void 0) {
10748
+ this.collectBatch.messages.push(message);
10749
+ sendSpan.end();
10750
+ return this.collectBatch.run;
10751
+ }
10752
+ const key = `agent-send:${this.agentId}`;
10753
+ this.inflight += 1;
10754
+ const release = () => {
10755
+ this.inflight -= 1;
10756
+ };
10757
+ if (mode === "collect" && this.inflight > 1) {
10758
+ const messages = [message];
10759
+ const run = new Promise((resolve, reject) => {
10760
+ void withCwdMutex(key, () => {
10761
+ this.collectBatch = void 0;
10762
+ return this.runLockedSendCycle(
10763
+ joinCollected(messages),
10764
+ options,
10765
+ sendSpan,
10766
+ resolve,
10767
+ reject
10768
+ ).finally(release);
10769
+ });
10770
+ });
10771
+ this.collectBatch = { messages, run };
10772
+ return run;
10773
+ }
10512
10774
  return new Promise((resolve, reject) => {
10513
10775
  void withCwdMutex(
10514
- `agent-send:${this.agentId}`,
10515
- () => this.runLockedSendCycle(message, options, sendSpan, resolve, reject)
10776
+ key,
10777
+ () => this.runLockedSendCycle(message, options, sendSpan, resolve, reject).finally(release)
10516
10778
  );
10517
10779
  });
10518
10780
  }
@@ -10528,20 +10790,40 @@ var LocalAgent = class {
10528
10790
  const declared = this.model?.contextWindow;
10529
10791
  return declared !== void 0 ? { contextWindow: declared } : {};
10530
10792
  }
10793
+ /** A steered message the loop never picked up (run errored, was cancelled) still gets answered. */
10794
+ followUpUnsteered(leftover) {
10795
+ if (leftover.length === 0) return;
10796
+ this.send(leftover.join("\n\n")).catch(
10797
+ (err) => diagFailure(`[theokit-sdk] steered message followup failed: ${String(err)}`)
10798
+ );
10799
+ }
10531
10800
  async runLockedSendCycle(message, options, sendSpan, resolve, reject) {
10532
10801
  const userText = typeof message === "string" ? message : message.text;
10533
10802
  let run;
10803
+ const steer = new TurnSteerQueue();
10804
+ let res = () => void 0;
10805
+ let rej = () => void 0;
10806
+ const turnRun = new Promise((a, b) => {
10807
+ res = a;
10808
+ rej = b;
10809
+ });
10810
+ turnRun.catch(() => void 0);
10811
+ this.activeTurn = { steer, run: turnRun };
10534
10812
  try {
10535
10813
  run = await this.sendLocked(message, options);
10536
10814
  } catch (err) {
10537
10815
  sendSpan.recordException(err);
10538
10816
  sendSpan.setStatus({ code: 2, message: err instanceof Error ? err.message : String(err) });
10539
10817
  sendSpan.end();
10818
+ this.activeTurn = void 0;
10819
+ rej(err);
10540
10820
  reject(err);
10541
10821
  return;
10542
10822
  }
10543
10823
  if (options.task !== void 0) registerRunAsTask(run, this.agentId, options.task, userText);
10544
- resolve(callerView(run, this.options.throwOnError));
10824
+ const view = callerView(run, this.options.throwOnError);
10825
+ res(view);
10826
+ resolve(view);
10545
10827
  try {
10546
10828
  await runPostRunLifecycle({
10547
10829
  run,
@@ -10565,6 +10847,8 @@ var LocalAgent = class {
10565
10847
  });
10566
10848
  } finally {
10567
10849
  sendSpan.end();
10850
+ this.activeTurn = void 0;
10851
+ this.followUpUnsteered(steer.closeAndTake());
10568
10852
  }
10569
10853
  }
10570
10854
  async sendLocked(message, options) {
@@ -10672,11 +10956,13 @@ var LocalAgent = class {
10672
10956
  memoryFacts,
10673
10957
  priorMessages,
10674
10958
  memoryTools,
10675
- activePreset: this.activePreset()
10959
+ activePreset: this.activePreset(),
10960
+ ...this.activeTurn !== void 0 ? { steerQueue: this.activeTurn.steer } : {}
10676
10961
  });
10677
10962
  }
10678
10963
  close() {
10679
10964
  this.disposed = true;
10965
+ liveAgentRegistry.forget(this.agentId);
10680
10966
  }
10681
10967
  async reload() {
10682
10968
  this.resolvedSubagents = await reloadLocalAgent(this);
@@ -11027,6 +11313,7 @@ function paginateByKey(all, keyOf, limit, cursor, sortByKey) {
11027
11313
 
11028
11314
  // src/agent.ts
11029
11315
  var streamObjectImport;
11316
+ var getOrCreateInFlight = /* @__PURE__ */ new Map();
11030
11317
  var Agent = class _Agent {
11031
11318
  constructor() {
11032
11319
  }
@@ -11211,7 +11498,7 @@ var Agent = class _Agent {
11211
11498
  * @public
11212
11499
  */
11213
11500
  static async batch(prompts, options) {
11214
- const { batchImpl } = await import('./batch-EP3FCL6D.js');
11501
+ const { batchImpl } = await import('./batch-N2XDYZED.js');
11215
11502
  return batchImpl(prompts, options, { create: (opts) => _Agent.create(opts) });
11216
11503
  }
11217
11504
  /**
@@ -11241,18 +11528,27 @@ var Agent = class _Agent {
11241
11528
  * The agent-builder's M85 interrupt rotates the session id to work around a
11242
11529
  * constraint that does not exist.
11243
11530
  *
11244
- * - `close()` marks the handle disposed WITHOUT evicting the cache entry. It is
11245
- * internal and unused today; if it becomes reachable, this bullet stops being true
11246
- * for that path.
11531
+ * - `close()` marks the handle disposed AND drops its cache entry, so the next call
11532
+ * builds a fresh handle.
11247
11533
  *
11248
11534
  * @public
11249
11535
  */
11250
11536
  static async getOrCreate(agentId, options) {
11251
11537
  const cached = _Agent.registry.get(agentId);
11252
11538
  if (cached !== void 0) return cached;
11253
- const fresh = await getOrCreateUncached(agentId, options);
11254
- _Agent.registry.set(agentId, fresh);
11255
- return fresh;
11539
+ const inFlight = getOrCreateInFlight.get(agentId);
11540
+ if (inFlight !== void 0) return inFlight;
11541
+ const build = (async () => {
11542
+ const fresh = await getOrCreateUncached(agentId, options);
11543
+ _Agent.registry.set(agentId, fresh);
11544
+ return fresh;
11545
+ })();
11546
+ getOrCreateInFlight.set(agentId, build);
11547
+ try {
11548
+ return await build;
11549
+ } finally {
11550
+ if (getOrCreateInFlight.get(agentId) === build) getOrCreateInFlight.delete(agentId);
11551
+ }
11256
11552
  }
11257
11553
  /**
11258
11554
  * List agents (local or cloud). M107 — `cwd` is READ, not ignored. B-115 (2026-08-19) —
@@ -11363,7 +11659,7 @@ var Agent = class _Agent {
11363
11659
  */
11364
11660
  static async compact(agentId, options = {}) {
11365
11661
  const reg = await requireLocalAgent(agentId, "compact");
11366
- const { compactSessionTranscript, buildDefaultSummarizer: buildDefaultSummarizer2 } = await import('./compact-session-N2PPHQO6.js');
11662
+ const { compactSessionTranscript, buildDefaultSummarizer: buildDefaultSummarizer2 } = await import('./compact-session-Q5IGNFPW.js');
11367
11663
  const { cwd, model, store } = await openLocalStore(reg);
11368
11664
  return enqueueSessionWrite(
11369
11665
  cwd,
@@ -11393,7 +11689,7 @@ var Agent = class _Agent {
11393
11689
  */
11394
11690
  static async injectSessionTurn(agentId, turn) {
11395
11691
  const reg = await requireLocalAgent(agentId, "injectSessionTurn");
11396
- const { injectSessionTurn } = await import('./inject-session-J26SHHIO.js');
11692
+ const { injectSessionTurn } = await import('./inject-session-4ROYLZHY.js');
11397
11693
  const { cwd, model, store } = await openLocalStore(reg);
11398
11694
  await injectSessionTurn({
11399
11695
  store,
@@ -11444,7 +11740,7 @@ var Agent = class _Agent {
11444
11740
  */
11445
11741
  static async describe(agentId) {
11446
11742
  const agent = await getRegisteredAgentOrThrow(agentId);
11447
- const { loadSubagents: loadSubagents2 } = await import('./subagents-loader-Z744TAKD.js');
11743
+ const { loadSubagents: loadSubagents2 } = await import('./subagents-loader-SXETS2F2.js');
11448
11744
  const settingSources = agent.options.local?.settingSources;
11449
11745
  const subagents = await loadSubagents2(
11450
11746
  agent.cwd ?? process.cwd(),
@@ -11543,7 +11839,9 @@ async function openLocalStore(reg) {
11543
11839
  const cwd = reg.cwd ?? process.cwd();
11544
11840
  const optModel = reg.options.model;
11545
11841
  const model = reg.model?.id ?? (typeof optModel === "string" ? optModel : optModel?.id) ?? "unknown";
11546
- const { FsSessionStore: FsSessionStore2 } = await import('./fs-session-store-6ZCCJX3K.js');
11842
+ const injected = reg.options.local?.sessionStore;
11843
+ if (injected !== void 0) return { cwd, model, store: injected };
11844
+ const { FsSessionStore: FsSessionStore2 } = await import('./fs-session-store-MYQEVUFL.js');
11547
11845
  const { defaultBaseDir: defaultBaseDir2, expandTilde: expandTilde2 } = await import('./session-transcript-BSHZYYY6.js');
11548
11846
  const configuredSessionDir = reg.options.local?.sessionDir ?? reg.options.local?.baseDir;
11549
11847
  const baseDir = configuredSessionDir !== void 0 ? expandTilde2(configuredSessionDir) : defaultBaseDir2();
@@ -11551,5 +11849,5 @@ async function openLocalStore(reg) {
11551
11849
  }
11552
11850
 
11553
11851
  export { Agent, AgentBuilder, DEFAULT_AGENTIC_MODEL_ID, MEMORY_EMBEDDING_ADAPTERS, Tool, ToolError, UsageAccumulator, computeCost, generateCronId, getPricingEntry, managedSettingsPathFor, openRouterMemoryEmbeddingProviderAdapter, readManagedSettings, resolveSessionDir };
11554
- //# sourceMappingURL=chunk-GARVAUCU.js.map
11555
- //# sourceMappingURL=chunk-GARVAUCU.js.map
11852
+ //# sourceMappingURL=chunk-5M5GQYBM.js.map
11853
+ //# sourceMappingURL=chunk-5M5GQYBM.js.map