@falai/agent 4.0.0-alpha.2 → 4.0.0-alpha.20

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 (300) hide show
  1. package/README.md +5 -3
  2. package/dist/cjs/core/Agent.d.ts +8 -1
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +18 -0
  5. package/dist/cjs/core/Agent.js.map +1 -1
  6. package/dist/cjs/core/CompactionEngine.d.ts.map +1 -1
  7. package/dist/cjs/core/CompactionEngine.js +8 -3
  8. package/dist/cjs/core/CompactionEngine.js.map +1 -1
  9. package/dist/cjs/core/FlowSpec.d.ts +21 -2
  10. package/dist/cjs/core/FlowSpec.d.ts.map +1 -1
  11. package/dist/cjs/core/FlowSpec.js +324 -51
  12. package/dist/cjs/core/FlowSpec.js.map +1 -1
  13. package/dist/cjs/core/Migrate.d.ts.map +1 -1
  14. package/dist/cjs/core/Migrate.js +3 -1
  15. package/dist/cjs/core/Migrate.js.map +1 -1
  16. package/dist/cjs/core/Prompt.d.ts +16 -0
  17. package/dist/cjs/core/Prompt.d.ts.map +1 -1
  18. package/dist/cjs/core/Prompt.js +46 -1
  19. package/dist/cjs/core/Prompt.js.map +1 -1
  20. package/dist/cjs/core/Runner.d.ts +37 -4
  21. package/dist/cjs/core/Runner.d.ts.map +1 -1
  22. package/dist/cjs/core/Runner.js +269 -74
  23. package/dist/cjs/core/Runner.js.map +1 -1
  24. package/dist/cjs/core/Speak.d.ts.map +1 -1
  25. package/dist/cjs/core/Speak.js +50 -19
  26. package/dist/cjs/core/Speak.js.map +1 -1
  27. package/dist/cjs/core/Understand.d.ts +4 -3
  28. package/dist/cjs/core/Understand.d.ts.map +1 -1
  29. package/dist/cjs/core/Understand.js +22 -51
  30. package/dist/cjs/core/Understand.js.map +1 -1
  31. package/dist/cjs/core/contracts.d.ts +11 -6
  32. package/dist/cjs/core/contracts.d.ts.map +1 -1
  33. package/dist/cjs/index.d.ts +1 -1
  34. package/dist/cjs/index.d.ts.map +1 -1
  35. package/dist/cjs/persistence/OpenSearchStore.d.ts +2 -1
  36. package/dist/cjs/persistence/OpenSearchStore.d.ts.map +1 -1
  37. package/dist/cjs/persistence/OpenSearchStore.js +2 -2
  38. package/dist/cjs/persistence/OpenSearchStore.js.map +1 -1
  39. package/dist/cjs/persistence/RedisStore.d.ts +1 -1
  40. package/dist/cjs/persistence/RedisStore.d.ts.map +1 -1
  41. package/dist/cjs/providers/AnthropicProvider.d.ts +2 -5
  42. package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
  43. package/dist/cjs/providers/AnthropicProvider.js +3 -4
  44. package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
  45. package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
  46. package/dist/cjs/providers/DeepSeekProvider.js +3 -4
  47. package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
  48. package/dist/cjs/providers/FallbackAiProvider.js +1 -1
  49. package/dist/cjs/providers/FallbackAiProvider.js.map +1 -1
  50. package/dist/cjs/providers/GeminiProvider.d.ts +1 -2
  51. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  52. package/dist/cjs/providers/GeminiProvider.js +3 -4
  53. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  54. package/dist/cjs/providers/GenericOpenAICompatibleProvider.js +4 -4
  55. package/dist/cjs/providers/GenericOpenAICompatibleProvider.js.map +1 -1
  56. package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
  57. package/dist/cjs/providers/OpenAIProvider.js +3 -4
  58. package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
  59. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  60. package/dist/cjs/providers/OpenRouterProvider.js +4 -3
  61. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  62. package/dist/cjs/providers/ProviderAdapter.d.ts +15 -10
  63. package/dist/cjs/providers/ProviderAdapter.d.ts.map +1 -1
  64. package/dist/cjs/providers/ProviderAdapter.js +8 -3
  65. package/dist/cjs/providers/ProviderAdapter.js.map +1 -1
  66. package/dist/cjs/providers/ZaiProvider.js +1 -1
  67. package/dist/cjs/providers/ZaiProvider.js.map +1 -1
  68. package/dist/cjs/types/agent.d.ts +19 -4
  69. package/dist/cjs/types/agent.d.ts.map +1 -1
  70. package/dist/cjs/types/ai.d.ts +4 -6
  71. package/dist/cjs/types/ai.d.ts.map +1 -1
  72. package/dist/cjs/types/compaction.d.ts +1 -0
  73. package/dist/cjs/types/compaction.d.ts.map +1 -1
  74. package/dist/cjs/types/errors.d.ts +4 -9
  75. package/dist/cjs/types/errors.d.ts.map +1 -1
  76. package/dist/cjs/types/errors.js +12 -12
  77. package/dist/cjs/types/errors.js.map +1 -1
  78. package/dist/cjs/types/flow.d.ts +15 -1
  79. package/dist/cjs/types/flow.d.ts.map +1 -1
  80. package/dist/cjs/types/history.d.ts +0 -7
  81. package/dist/cjs/types/history.d.ts.map +1 -1
  82. package/dist/cjs/types/index.d.ts +2 -2
  83. package/dist/cjs/types/index.d.ts.map +1 -1
  84. package/dist/cjs/types/session.d.ts +4 -2
  85. package/dist/cjs/types/session.d.ts.map +1 -1
  86. package/dist/cjs/utils/clock.js +1 -1
  87. package/dist/cjs/utils/clock.js.map +1 -1
  88. package/dist/cjs/utils/outcomes.d.ts +1 -0
  89. package/dist/cjs/utils/outcomes.d.ts.map +1 -1
  90. package/dist/cjs/utils/outcomes.js +1 -0
  91. package/dist/cjs/utils/outcomes.js.map +1 -1
  92. package/dist/cjs/utils/phrases.d.ts +25 -0
  93. package/dist/cjs/utils/phrases.d.ts.map +1 -0
  94. package/dist/cjs/utils/phrases.js +38 -0
  95. package/dist/cjs/utils/phrases.js.map +1 -0
  96. package/dist/cjs/utils/schema.d.ts +3 -12
  97. package/dist/cjs/utils/schema.d.ts.map +1 -1
  98. package/dist/cjs/utils/schema.js +3 -43
  99. package/dist/cjs/utils/schema.js.map +1 -1
  100. package/dist/cjs/utils/template.d.ts +8 -0
  101. package/dist/cjs/utils/template.d.ts.map +1 -1
  102. package/dist/cjs/utils/template.js +47 -3
  103. package/dist/cjs/utils/template.js.map +1 -1
  104. package/dist/core/Agent.d.ts +8 -1
  105. package/dist/core/Agent.d.ts.map +1 -1
  106. package/dist/core/Agent.js +19 -1
  107. package/dist/core/Agent.js.map +1 -1
  108. package/dist/core/CompactionEngine.d.ts.map +1 -1
  109. package/dist/core/CompactionEngine.js +8 -3
  110. package/dist/core/CompactionEngine.js.map +1 -1
  111. package/dist/core/FlowSpec.d.ts +21 -2
  112. package/dist/core/FlowSpec.d.ts.map +1 -1
  113. package/dist/core/FlowSpec.js +323 -52
  114. package/dist/core/FlowSpec.js.map +1 -1
  115. package/dist/core/Migrate.d.ts.map +1 -1
  116. package/dist/core/Migrate.js +3 -1
  117. package/dist/core/Migrate.js.map +1 -1
  118. package/dist/core/Prompt.d.ts +16 -0
  119. package/dist/core/Prompt.d.ts.map +1 -1
  120. package/dist/core/Prompt.js +44 -1
  121. package/dist/core/Prompt.js.map +1 -1
  122. package/dist/core/Runner.d.ts +37 -4
  123. package/dist/core/Runner.d.ts.map +1 -1
  124. package/dist/core/Runner.js +270 -75
  125. package/dist/core/Runner.js.map +1 -1
  126. package/dist/core/Speak.d.ts.map +1 -1
  127. package/dist/core/Speak.js +51 -20
  128. package/dist/core/Speak.js.map +1 -1
  129. package/dist/core/Understand.d.ts +4 -3
  130. package/dist/core/Understand.d.ts.map +1 -1
  131. package/dist/core/Understand.js +22 -51
  132. package/dist/core/Understand.js.map +1 -1
  133. package/dist/core/contracts.d.ts +11 -6
  134. package/dist/core/contracts.d.ts.map +1 -1
  135. package/dist/index.d.ts +1 -1
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/persistence/OpenSearchStore.d.ts +2 -1
  138. package/dist/persistence/OpenSearchStore.d.ts.map +1 -1
  139. package/dist/persistence/OpenSearchStore.js +2 -2
  140. package/dist/persistence/OpenSearchStore.js.map +1 -1
  141. package/dist/persistence/RedisStore.d.ts +1 -1
  142. package/dist/persistence/RedisStore.d.ts.map +1 -1
  143. package/dist/providers/AnthropicProvider.d.ts +2 -5
  144. package/dist/providers/AnthropicProvider.d.ts.map +1 -1
  145. package/dist/providers/AnthropicProvider.js +3 -4
  146. package/dist/providers/AnthropicProvider.js.map +1 -1
  147. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  148. package/dist/providers/DeepSeekProvider.js +3 -4
  149. package/dist/providers/DeepSeekProvider.js.map +1 -1
  150. package/dist/providers/FallbackAiProvider.js +1 -1
  151. package/dist/providers/FallbackAiProvider.js.map +1 -1
  152. package/dist/providers/GeminiProvider.d.ts +1 -2
  153. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  154. package/dist/providers/GeminiProvider.js +3 -4
  155. package/dist/providers/GeminiProvider.js.map +1 -1
  156. package/dist/providers/GenericOpenAICompatibleProvider.js +4 -4
  157. package/dist/providers/GenericOpenAICompatibleProvider.js.map +1 -1
  158. package/dist/providers/OpenAIProvider.d.ts.map +1 -1
  159. package/dist/providers/OpenAIProvider.js +3 -4
  160. package/dist/providers/OpenAIProvider.js.map +1 -1
  161. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  162. package/dist/providers/OpenRouterProvider.js +4 -3
  163. package/dist/providers/OpenRouterProvider.js.map +1 -1
  164. package/dist/providers/ProviderAdapter.d.ts +15 -10
  165. package/dist/providers/ProviderAdapter.d.ts.map +1 -1
  166. package/dist/providers/ProviderAdapter.js +8 -3
  167. package/dist/providers/ProviderAdapter.js.map +1 -1
  168. package/dist/providers/ZaiProvider.js +1 -1
  169. package/dist/providers/ZaiProvider.js.map +1 -1
  170. package/dist/types/agent.d.ts +19 -4
  171. package/dist/types/agent.d.ts.map +1 -1
  172. package/dist/types/ai.d.ts +4 -6
  173. package/dist/types/ai.d.ts.map +1 -1
  174. package/dist/types/compaction.d.ts +1 -0
  175. package/dist/types/compaction.d.ts.map +1 -1
  176. package/dist/types/errors.d.ts +4 -9
  177. package/dist/types/errors.d.ts.map +1 -1
  178. package/dist/types/errors.js +12 -12
  179. package/dist/types/errors.js.map +1 -1
  180. package/dist/types/flow.d.ts +15 -1
  181. package/dist/types/flow.d.ts.map +1 -1
  182. package/dist/types/history.d.ts +0 -7
  183. package/dist/types/history.d.ts.map +1 -1
  184. package/dist/types/index.d.ts +2 -2
  185. package/dist/types/index.d.ts.map +1 -1
  186. package/dist/types/session.d.ts +4 -2
  187. package/dist/types/session.d.ts.map +1 -1
  188. package/dist/utils/clock.js +1 -1
  189. package/dist/utils/clock.js.map +1 -1
  190. package/dist/utils/outcomes.d.ts +1 -0
  191. package/dist/utils/outcomes.d.ts.map +1 -1
  192. package/dist/utils/outcomes.js +1 -0
  193. package/dist/utils/outcomes.js.map +1 -1
  194. package/dist/utils/phrases.d.ts +25 -0
  195. package/dist/utils/phrases.d.ts.map +1 -0
  196. package/dist/utils/phrases.js +35 -0
  197. package/dist/utils/phrases.js.map +1 -0
  198. package/dist/utils/schema.d.ts +3 -12
  199. package/dist/utils/schema.d.ts.map +1 -1
  200. package/dist/utils/schema.js +3 -42
  201. package/dist/utils/schema.js.map +1 -1
  202. package/dist/utils/template.d.ts +8 -0
  203. package/dist/utils/template.d.ts.map +1 -1
  204. package/dist/utils/template.js +47 -3
  205. package/dist/utils/template.js.map +1 -1
  206. package/docs/concepts/architecture.md +3 -3
  207. package/docs/concepts/collection.md +40 -5
  208. package/docs/concepts/pipeline.md +12 -10
  209. package/docs/concepts/runs-and-waits.md +2 -2
  210. package/docs/guides/actions-and-events.md +2 -2
  211. package/docs/guides/branching.md +4 -2
  212. package/docs/guides/compaction.md +2 -2
  213. package/docs/guides/conditions.md +1 -1
  214. package/docs/guides/error-handling.md +3 -1
  215. package/docs/guides/flow-control.md +4 -2
  216. package/docs/guides/persistence.md +2 -2
  217. package/docs/guides/testing.md +1 -1
  218. package/docs/guides/triggers.md +5 -5
  219. package/docs/migration/v3-to-v4.md +16 -11
  220. package/docs/reference/actions-events-conditions.md +2 -2
  221. package/docs/reference/agent.md +11 -7
  222. package/docs/reference/branches.md +1 -1
  223. package/docs/reference/errors.md +10 -7
  224. package/docs/reference/fields.md +5 -3
  225. package/docs/reference/flow-spec.md +36 -9
  226. package/docs/reference/flow.md +8 -3
  227. package/docs/reference/outcomes.md +3 -2
  228. package/docs/reference/providers.md +2 -0
  229. package/docs/reference/session.md +2 -0
  230. package/docs/reference/step.md +8 -5
  231. package/docs/reference/stores.md +5 -3
  232. package/docs/reference/trigger.md +24 -4
  233. package/docs/rfc/v4-one-flow.md +7 -5
  234. package/docs/start/01-install.md +5 -3
  235. package/docs/start/04-add-tools.md +1 -1
  236. package/docs/start/05-go-to-production.md +18 -1
  237. package/examples/05-branches.ts +1 -1
  238. package/examples/06-triggers-and-waits.ts +4 -3
  239. package/package.json +5 -3
  240. package/src/core/Agent.ts +23 -2
  241. package/src/core/CompactionEngine.ts +10 -3
  242. package/src/core/FlowSpec.ts +352 -60
  243. package/src/core/Migrate.ts +2 -1
  244. package/src/core/Prompt.ts +47 -1
  245. package/src/core/Runner.ts +266 -71
  246. package/src/core/Speak.ts +53 -19
  247. package/src/core/Understand.ts +17 -50
  248. package/src/core/contracts.ts +11 -4
  249. package/src/index.ts +1 -1
  250. package/src/persistence/OpenSearchStore.ts +3 -2
  251. package/src/persistence/RedisStore.ts +1 -1
  252. package/src/providers/AnthropicProvider.ts +4 -9
  253. package/src/providers/DeepSeekProvider.ts +2 -4
  254. package/src/providers/FallbackAiProvider.ts +1 -1
  255. package/src/providers/GeminiProvider.ts +3 -6
  256. package/src/providers/GenericOpenAICompatibleProvider.ts +4 -4
  257. package/src/providers/OpenAIProvider.ts +3 -4
  258. package/src/providers/OpenRouterProvider.ts +4 -2
  259. package/src/providers/ProviderAdapter.ts +18 -13
  260. package/src/providers/ZaiProvider.ts +1 -1
  261. package/src/types/agent.ts +20 -5
  262. package/src/types/ai.ts +4 -6
  263. package/src/types/compaction.ts +1 -0
  264. package/src/types/errors.ts +11 -12
  265. package/src/types/flow.ts +15 -1
  266. package/src/types/history.ts +0 -10
  267. package/src/types/index.ts +1 -1
  268. package/src/types/session.ts +4 -1
  269. package/src/utils/clock.ts +1 -1
  270. package/src/utils/outcomes.ts +1 -0
  271. package/src/utils/phrases.ts +40 -0
  272. package/src/utils/schema.ts +3 -48
  273. package/src/utils/template.ts +46 -3
  274. package/dist/cjs/providers/index.d.ts +0 -26
  275. package/dist/cjs/providers/index.d.ts.map +0 -1
  276. package/dist/cjs/providers/index.js +0 -30
  277. package/dist/cjs/providers/index.js.map +0 -1
  278. package/dist/cjs/utils/clone.d.ts +0 -8
  279. package/dist/cjs/utils/clone.d.ts.map +0 -1
  280. package/dist/cjs/utils/clone.js +0 -32
  281. package/dist/cjs/utils/clone.js.map +0 -1
  282. package/dist/cjs/utils/index.d.ts +0 -9
  283. package/dist/cjs/utils/index.d.ts.map +0 -1
  284. package/dist/cjs/utils/index.js +0 -29
  285. package/dist/cjs/utils/index.js.map +0 -1
  286. package/dist/providers/index.d.ts +0 -26
  287. package/dist/providers/index.d.ts.map +0 -1
  288. package/dist/providers/index.js +0 -17
  289. package/dist/providers/index.js.map +0 -1
  290. package/dist/utils/clone.d.ts +0 -8
  291. package/dist/utils/clone.d.ts.map +0 -1
  292. package/dist/utils/clone.js +0 -29
  293. package/dist/utils/clone.js.map +0 -1
  294. package/dist/utils/index.d.ts +0 -9
  295. package/dist/utils/index.d.ts.map +0 -1
  296. package/dist/utils/index.js +0 -9
  297. package/dist/utils/index.js.map +0 -1
  298. package/src/providers/index.ts +0 -38
  299. package/src/utils/clone.ts +0 -34
  300. package/src/utils/index.ts +0 -18
@@ -170,7 +170,7 @@ A `wait` longer than 10 seconds, a `silence` trigger or an `event` trigger with
170
170
  { key: "triagem#wamid.HBgL:w1:1790244000000", at: new Date("2026-09-24T10:00:00.000Z") }
171
171
  ```
172
172
 
173
- A `silence` trigger's wake also carries `replaces`: the earlier silence wake it supersedes. Put the entry in your queue with `jobId = key` and the session id in the payload. When `replaces` is set, remove that job; it is best effort, a stale wake is harmless. When the job fires:
173
+ A `silence` trigger's wake also carries `replaces`: the earlier silence wake it supersedes. Put the entry in your queue with the key and the session id in the payload, under a job id made from the key: every key contains `:`, and BullMQ refuses a custom job id with a `:` in it unless it splits into exactly three parts, so encode it as `encodeURIComponent(key)`. When `replaces` is set, remove the job whose id is `encodeURIComponent(replaces)`; it is best effort, a stale wake is harmless. When the job fires:
174
174
 
175
175
  ```ts fragment
176
176
  await handle({ sessionId: job.data.sessionId, wake: job.data.key });
@@ -178,6 +178,21 @@ await handle({ sessionId: job.data.sessionId, wake: job.data.key });
178
178
 
179
179
  Only the run still waiting on that exact key honours the wake. Anything else returns `changed: false` with one line in `r.outcomes`: `code: 'stale-wake'` for a wait that a reply already resolved, `code: 'silence-broken'` when the customer wrote after the silence wake was set, `code: 'no-session'` when there is no session. So you do not have to cancel jobs: fire every one and the framework drops the stale ones.
180
180
 
181
+ ### When the queue loses its jobs
182
+
183
+ A flushed Redis, or sessions lifted from 3.x by `migrateSession`, leave conversations waiting on wakes nobody will fire. `agent.pendingWakes({ session, context })` returns every wake a saved session waits on: each parked run's, and each silence flow's counted from `lastAssistantAt`, with the trigger's `if` and `repeat` judged on the `context` and `claims` you pass, as a turn would. It changes nothing and spends no model call. Enqueue what it returns as you would a turn's `schedule[]`:
184
+
185
+ ```ts fragment
186
+ for (const wake of agent.pendingWakes({ session, context })) {
187
+ await queue.add("wake", { sessionId: session.id, key: wake.key }, {
188
+ jobId: encodeURIComponent(wake.key),
189
+ delay: Math.max(0, wake.at.getTime() - Date.now()),
190
+ });
191
+ }
192
+ ```
193
+
194
+ Running it twice is safe: BullMQ ignores a job whose id is already queued, and a wake that fires twice is dropped the second time as stale.
195
+
181
196
  `fakeClock` and `MemoryScheduler` are the test doubles for this: [Testing](../guides/testing.md) plays a two-day follow-up in one test.
182
197
 
183
198
  ## On every input
@@ -197,6 +212,8 @@ const history: History = [
197
212
 
198
213
  A run that was already asking stays asking and speaks when the gate opens. A run that reaches a new talk step while silenced ends, and the log says `code: 'silenced'` with your reason in `detail`. Keep calling `turn()` for every inbound even while a human owns the customer, so waits resolve and the state stays true. `silenced: { reason, understand: true }` still spends the understand call, so fields keep landing while nothing is said.
199
214
 
215
+ A closed 24-hour window stops messages, not the follow-up. Pass `silenced: { reason, skip: true }` for a gate like that: a talk or `say` step is skipped (`status: 'skipped'`, `code: 'silenced'`) and the run takes the step's `then`, so the `do` step after it still alerts the team. Keep the plain string for a human owner or a paused assistant, where the whole run must stop.
216
+
200
217
  **`context`** is the per-turn data your flows and actions read, such as the customer record. It is typed once, `falai<Ctx>()`, and passed on every input. Ana has none. [Agent](../reference/agent.md) has the full `TurnInput`.
201
218
 
202
219
  ## Sessions from before v4
@@ -54,7 +54,7 @@ const agent = f.agent({
54
54
  then: "dados",
55
55
  },
56
56
  ],
57
- // After the last step the run stays on it, so follow-up questions land here.
57
+ // After the last step the run goes back to the last talk step it took, so follow-up questions land there.
58
58
  onEnd: "stay",
59
59
  }),
60
60
  f.flow({
@@ -117,9 +117,10 @@ const agent = f.agent({
117
117
  });
118
118
 
119
119
  // ─── The host loop ─────────────────────────────────────────────────────────
120
- // Real hosts persist `session`, enqueue each `schedule[]` entry with
121
- // `jobId = key`, and call `turn({ wake: key })` when it fires. Here we keep
122
- // them in memory and jump the clock.
120
+ // Real hosts persist `session`, enqueue each `schedule[]` entry under the job
121
+ // id `encodeURIComponent(key)` (BullMQ refuses a `:` in a custom id), and call
122
+ // `turn({ wake: key })` when it fires. Here we keep them in memory and jump
123
+ // the clock.
123
124
 
124
125
  const context: Ctx = { lead: { id: "456", nome: "Ana", etapa: "proposta", dono: "ia", tags: [] } };
125
126
  const timers: ScheduleEntry[] = [];
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@falai/agent",
3
- "version": "4.0.0-alpha.2",
3
+ "packageManager": "bun@1.4.2",
4
+ "version": "4.0.0-alpha.20",
4
5
  "description": "Conversational state engine for TypeScript where the AI understands, but the code is in control",
5
6
  "type": "module",
6
7
  "main": "./dist/cjs/index.js",
@@ -59,7 +60,8 @@
59
60
  "release:alpha": "bun publish --tag alpha",
60
61
  "release": "bun publish",
61
62
  "test": "bun test tests/*.test.ts tests/scenarios/*.test.ts",
62
- "eval:live": "bun run scripts/eval/live.ts"
63
+ "eval:live": "bun run scripts/eval/live.ts",
64
+ "eval:exclusions": "bun run scripts/eval/exclusions.ts"
63
65
  },
64
66
  "keywords": [
65
67
  "ai",
@@ -95,7 +97,7 @@
95
97
  "typescript-eslint": "^8.18.2"
96
98
  },
97
99
  "dependencies": {
98
- "@providerkit/core": "^0.11.1",
100
+ "@providerkit/core": "^0.12.2",
99
101
  "loglevel": "^1.9.2"
100
102
  },
101
103
  "peerDependencies": {
package/src/core/Agent.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * provider call apiece, and Runner settles what they returned.
8
8
  */
9
9
 
10
- import type { AgentOptions, TurnInput, TurnResult, TurnStreamChunk } from "../types/agent.js";
10
+ import type { AgentOptions, PendingWakesInput, ScheduleEntry, TurnInput, TurnResult, TurnStreamChunk } from "../types/agent.js";
11
11
  import type { TokenUsage } from "../types/ai.js";
12
12
  import type { CompactionOptions } from "../types/compaction.js";
13
13
  import { FlowConfigurationError } from "../types/errors.js";
@@ -15,7 +15,7 @@ import { logger, LoggerLevel } from "../utils/logger.js";
15
15
  import { addUsage } from "../utils/usage.js";
16
16
  import { CompactionEngine } from "./CompactionEngine.js";
17
17
  import type { IdleRequest, SpeakOutcome, TalkRequest } from "./contracts.js";
18
- import { validateFlow } from "./FlowSpec.js";
18
+ import { BUILT_IN_CONDITIONS, checkPred, validateFlow } from "./FlowSpec.js";
19
19
  import { Runner, type Turn } from "./Runner.js";
20
20
  import { Speak } from "./Speak.js";
21
21
  import { Understand } from "./Understand.js";
@@ -56,6 +56,16 @@ export class Agent<C = unknown, D = unknown> {
56
56
  yield { done: true, result: this.runner.finish(turn) };
57
57
  }
58
58
 
59
+ /**
60
+ * Every wake a saved session is waiting on, as its turns scheduled them: each parked run's,
61
+ * and each silence flow's since the assistant last spoke. For a queue that lost its jobs, and
62
+ * for sessions no turn has armed yet, such as blobs lifted by `migrateSession`. It changes
63
+ * nothing and spends no call: enqueue the entries as you would a turn's `schedule[]`.
64
+ */
65
+ pendingWakes(input: PendingWakesInput<C, D>): ScheduleEntry[] {
66
+ return this.runner.pendingWakes(input);
67
+ }
68
+
59
69
  /** Load, Ingest, Understand, Decide and Run: everything before the one speaker is known. */
60
70
  private async open(input: TurnInput<C, D>): Promise<{ turn: Turn<C, D>; talk: TalkRequest<C, D> | IdleRequest<C, D> | null }> {
61
71
  const { runner } = this;
@@ -100,6 +110,16 @@ function compactionOptions<C, D>(options: AgentOptions<C, D>): CompactionOptions
100
110
 
101
111
  /** Every name a flow uses must resolve now, not on the turn that first reaches it. */
102
112
  function validate<C, D>(options: AgentOptions<C, D>): void {
113
+ // A host condition under a built-in's name is never called: the built-in answers first.
114
+ for (const name of Object.keys(options.conditions ?? {})) {
115
+ if (BUILT_IN_CONDITIONS.includes(name)) {
116
+ throw new FlowConfigurationError(
117
+ `[FlowConfigurationError] condition "${name}" shadows a built-in: ${BUILT_IN_CONDITIONS.join(", ")} are reserved. Rename it.`,
118
+ );
119
+ }
120
+ }
121
+ // An agent-level `if` is judged on every turn, so an unknown name here would throw on every turn.
122
+ options.instructions?.forEach((ins, i) => checkPred(ins.if, "agent", `instructions[${i}].if`, options));
103
123
  const ids = new Set<string>();
104
124
  for (const flow of options.flows ?? []) {
105
125
  if (ids.has(flow.id)) {
@@ -124,6 +144,7 @@ function validate<C, D>(options: AgentOptions<C, D>): void {
124
144
  }
125
145
  const { idle } = options;
126
146
  if (idle && idle !== "silent") {
147
+ idle.instructions?.forEach((ins, i) => checkPred(ins.if, "idle", `instructions[${i}].if`, options));
127
148
  const known = new Set((options.tools ?? []).map((tool) => tool.id));
128
149
  for (const name of idle.tools ?? []) {
129
150
  if (!known.has(name)) {
@@ -19,13 +19,20 @@ export class CompactionEngine {
19
19
  * Validate CompactionOptions. Throws on invalid values.
20
20
  */
21
21
  static validateOptions(options: CompactionOptions): void {
22
+ if (typeof options.maxTokens !== "number" || !(options.maxTokens > 0)) {
23
+ throw new Error(
24
+ `[CompactionEngine] maxTokens is ${String(options.maxTokens)}: it must be above 0. ` +
25
+ `Set it to the most history, in tokens, each call should carry, e.g. 100000.`
26
+ );
27
+ }
22
28
  if (
23
29
  typeof options.compactionThreshold !== "number" ||
24
30
  options.compactionThreshold < 0.5 ||
25
31
  options.compactionThreshold > 0.95
26
32
  ) {
27
33
  throw new Error(
28
- `compactionThreshold must be between 0.5 and 0.95, got ${options.compactionThreshold}`
34
+ `[CompactionEngine] compactionThreshold is ${String(options.compactionThreshold)}: it must be between 0.5 and 0.95. ` +
35
+ `Use 0.8 unless you measured otherwise.`
29
36
  );
30
37
  }
31
38
  if (
@@ -33,7 +40,7 @@ export class CompactionEngine {
33
40
  options.preserveRecentCount < 2
34
41
  ) {
35
42
  throw new Error(
36
- `preserveRecentCount must be >= 2, got ${options.preserveRecentCount}`
43
+ `[CompactionEngine] preserveRecentCount is ${String(options.preserveRecentCount)}: it must be 2 or more. Use 4, the default.`
37
44
  );
38
45
  }
39
46
  if (
@@ -41,7 +48,7 @@ export class CompactionEngine {
41
48
  options.maxToolResultChars <= 0
42
49
  ) {
43
50
  throw new Error(
44
- `maxToolResultChars must be > 0, got ${options.maxToolResultChars}`
51
+ `[CompactionEngine] maxToolResultChars is ${String(options.maxToolResultChars)}: it must be above 0. Use 5000, the default.`
45
52
  );
46
53
  }
47
54
  }