@retinue/agentkit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +310 -0
  3. package/dist/adapters/bullmq/consumer.d.ts +33 -0
  4. package/dist/adapters/bullmq/consumer.js +41 -0
  5. package/dist/adapters/bullmq/dispatcher.d.ts +74 -0
  6. package/dist/adapters/bullmq/dispatcher.js +160 -0
  7. package/dist/adapters/bullmq/export.d.ts +31 -0
  8. package/dist/adapters/bullmq/export.js +53 -0
  9. package/dist/adapters/bullmq/extraction.d.ts +42 -0
  10. package/dist/adapters/bullmq/extraction.js +63 -0
  11. package/dist/adapters/bullmq/index.d.ts +13 -0
  12. package/dist/adapters/bullmq/index.js +13 -0
  13. package/dist/adapters/bullmq/lock.d.ts +77 -0
  14. package/dist/adapters/bullmq/lock.js +126 -0
  15. package/dist/adapters/bullmq/queue.d.ts +50 -0
  16. package/dist/adapters/bullmq/queue.js +81 -0
  17. package/dist/adapters/memory/artifact-exports.d.ts +11 -0
  18. package/dist/adapters/memory/artifact-exports.js +102 -0
  19. package/dist/adapters/memory/artifacts.d.ts +15 -0
  20. package/dist/adapters/memory/artifacts.js +134 -0
  21. package/dist/adapters/memory/blobs.d.ts +7 -0
  22. package/dist/adapters/memory/blobs.js +27 -0
  23. package/dist/adapters/memory/evaluation.d.ts +18 -0
  24. package/dist/adapters/memory/evaluation.js +148 -0
  25. package/dist/adapters/memory/files.d.ts +27 -0
  26. package/dist/adapters/memory/files.js +0 -0
  27. package/dist/adapters/memory/flows.d.ts +16 -0
  28. package/dist/adapters/memory/flows.js +117 -0
  29. package/dist/adapters/memory/hitl.d.ts +9 -0
  30. package/dist/adapters/memory/hitl.js +130 -0
  31. package/dist/adapters/memory/idempotency.d.ts +13 -0
  32. package/dist/adapters/memory/idempotency.js +32 -0
  33. package/dist/adapters/memory/index.d.ts +39 -0
  34. package/dist/adapters/memory/index.js +107 -0
  35. package/dist/adapters/memory/knowledge.d.ts +43 -0
  36. package/dist/adapters/memory/knowledge.js +248 -0
  37. package/dist/adapters/memory/mcp.d.ts +9 -0
  38. package/dist/adapters/memory/mcp.js +37 -0
  39. package/dist/adapters/memory/message-store.d.ts +17 -0
  40. package/dist/adapters/memory/message-store.js +70 -0
  41. package/dist/adapters/memory/principal-memory.d.ts +7 -0
  42. package/dist/adapters/memory/principal-memory.js +83 -0
  43. package/dist/adapters/memory/runtime.d.ts +29 -0
  44. package/dist/adapters/memory/runtime.js +0 -0
  45. package/dist/adapters/memory/sessions.d.ts +29 -0
  46. package/dist/adapters/memory/sessions.js +0 -0
  47. package/dist/adapters/memory/skills.d.ts +10 -0
  48. package/dist/adapters/memory/skills.js +41 -0
  49. package/dist/adapters/memory/thread-summary.d.ts +7 -0
  50. package/dist/adapters/memory/thread-summary.js +29 -0
  51. package/dist/adapters/memory/usage-limits.d.ts +13 -0
  52. package/dist/adapters/memory/usage-limits.js +72 -0
  53. package/dist/adapters/memory/usage.d.ts +16 -0
  54. package/dist/adapters/memory/usage.js +279 -0
  55. package/dist/adapters/otel/index.d.ts +111 -0
  56. package/dist/adapters/otel/index.js +133 -0
  57. package/dist/adapters/postgres/artifact-exports.d.ts +12 -0
  58. package/dist/adapters/postgres/artifact-exports.js +117 -0
  59. package/dist/adapters/postgres/artifacts.d.ts +16 -0
  60. package/dist/adapters/postgres/artifacts.js +172 -0
  61. package/dist/adapters/postgres/checkpoint-store.d.ts +16 -0
  62. package/dist/adapters/postgres/checkpoint-store.js +34 -0
  63. package/dist/adapters/postgres/config.d.ts +15 -0
  64. package/dist/adapters/postgres/config.js +187 -0
  65. package/dist/adapters/postgres/conversation-store.d.ts +4 -0
  66. package/dist/adapters/postgres/conversation-store.js +82 -0
  67. package/dist/adapters/postgres/evaluation.d.ts +17 -0
  68. package/dist/adapters/postgres/evaluation.js +193 -0
  69. package/dist/adapters/postgres/file-content.d.ts +30 -0
  70. package/dist/adapters/postgres/file-content.js +111 -0
  71. package/dist/adapters/postgres/files.d.ts +19 -0
  72. package/dist/adapters/postgres/files.js +209 -0
  73. package/dist/adapters/postgres/flows.d.ts +20 -0
  74. package/dist/adapters/postgres/flows.js +206 -0
  75. package/dist/adapters/postgres/hitl.d.ts +5 -0
  76. package/dist/adapters/postgres/hitl.js +247 -0
  77. package/dist/adapters/postgres/index.d.ts +35 -0
  78. package/dist/adapters/postgres/index.js +35 -0
  79. package/dist/adapters/postgres/knowledge.d.ts +48 -0
  80. package/dist/adapters/postgres/knowledge.js +255 -0
  81. package/dist/adapters/postgres/memory.d.ts +14 -0
  82. package/dist/adapters/postgres/memory.js +194 -0
  83. package/dist/adapters/postgres/message-store.d.ts +11 -0
  84. package/dist/adapters/postgres/message-store.js +145 -0
  85. package/dist/adapters/postgres/migrations.d.ts +69 -0
  86. package/dist/adapters/postgres/migrations.js +1594 -0
  87. package/dist/adapters/postgres/pg-executor.d.ts +19 -0
  88. package/dist/adapters/postgres/pg-executor.js +32 -0
  89. package/dist/adapters/postgres/retention.d.ts +26 -0
  90. package/dist/adapters/postgres/retention.js +59 -0
  91. package/dist/adapters/postgres/rollups.d.ts +17 -0
  92. package/dist/adapters/postgres/rollups.js +267 -0
  93. package/dist/adapters/postgres/run-coordinator.d.ts +5 -0
  94. package/dist/adapters/postgres/run-coordinator.js +98 -0
  95. package/dist/adapters/postgres/run-event-log.d.ts +26 -0
  96. package/dist/adapters/postgres/run-event-log.js +30 -0
  97. package/dist/adapters/postgres/run-store.d.ts +4 -0
  98. package/dist/adapters/postgres/run-store.js +199 -0
  99. package/dist/adapters/postgres/schema.d.ts +39 -0
  100. package/dist/adapters/postgres/schema.js +70 -0
  101. package/dist/adapters/postgres/session-state.d.ts +7 -0
  102. package/dist/adapters/postgres/session-state.js +99 -0
  103. package/dist/adapters/postgres/sql.d.ts +8 -0
  104. package/dist/adapters/postgres/sql.js +2 -0
  105. package/dist/adapters/postgres/transaction.d.ts +37 -0
  106. package/dist/adapters/postgres/transaction.js +93 -0
  107. package/dist/adapters/postgres/unit-of-work.d.ts +18 -0
  108. package/dist/adapters/postgres/unit-of-work.js +8 -0
  109. package/dist/adapters/postgres/usage-limits.d.ts +15 -0
  110. package/dist/adapters/postgres/usage-limits.js +136 -0
  111. package/dist/adapters/postgres/usage.d.ts +15 -0
  112. package/dist/adapters/postgres/usage.js +226 -0
  113. package/dist/adapters/redis/index.d.ts +9 -0
  114. package/dist/adapters/redis/index.js +9 -0
  115. package/dist/adapters/redis/realtime.d.ts +74 -0
  116. package/dist/adapters/redis/realtime.js +112 -0
  117. package/dist/adapters/supabase/index.d.ts +88 -0
  118. package/dist/adapters/supabase/index.js +84 -0
  119. package/dist/adapters/supabase/realtime.d.ts +30 -0
  120. package/dist/adapters/supabase/realtime.js +53 -0
  121. package/dist/adapters/supabase/rls.d.ts +99 -0
  122. package/dist/adapters/supabase/rls.js +216 -0
  123. package/dist/adapters/supabase/storage.d.ts +50 -0
  124. package/dist/adapters/supabase/storage.js +207 -0
  125. package/dist/agents/agent.d.ts +66 -0
  126. package/dist/agents/agent.js +209 -0
  127. package/dist/agents/define.d.ts +21 -0
  128. package/dist/agents/define.js +63 -0
  129. package/dist/agents/engine.d.ts +98 -0
  130. package/dist/agents/engine.js +462 -0
  131. package/dist/agents/index.d.ts +50 -0
  132. package/dist/agents/index.js +17 -0
  133. package/dist/artifacts/index.d.ts +114 -0
  134. package/dist/artifacts/index.js +219 -0
  135. package/dist/authorization/index.d.ts +76 -0
  136. package/dist/authorization/index.js +76 -0
  137. package/dist/capabilities/index.d.ts +120 -0
  138. package/dist/capabilities/index.js +167 -0
  139. package/dist/capabilities/runtime.d.ts +89 -0
  140. package/dist/capabilities/runtime.js +84 -0
  141. package/dist/citations/index.d.ts +161 -0
  142. package/dist/citations/index.js +182 -0
  143. package/dist/context/assembler.d.ts +82 -0
  144. package/dist/context/assembler.js +129 -0
  145. package/dist/context/compaction.d.ts +45 -0
  146. package/dist/context/compaction.js +55 -0
  147. package/dist/context/index.d.ts +75 -0
  148. package/dist/context/index.js +17 -0
  149. package/dist/core/content-parts.d.ts +194 -0
  150. package/dist/core/content-parts.js +23 -0
  151. package/dist/core/context.d.ts +51 -0
  152. package/dist/core/context.js +9 -0
  153. package/dist/core/env.d.ts +25 -0
  154. package/dist/core/env.js +41 -0
  155. package/dist/core/errors.d.ts +30 -0
  156. package/dist/core/errors.js +65 -0
  157. package/dist/core/events.d.ts +139 -0
  158. package/dist/core/events.js +99 -0
  159. package/dist/core/ids.d.ts +52 -0
  160. package/dist/core/ids.js +13 -0
  161. package/dist/core/index.d.ts +9 -0
  162. package/dist/core/index.js +9 -0
  163. package/dist/core/tokens.d.ts +22 -0
  164. package/dist/core/tokens.js +22 -0
  165. package/dist/core/validation.d.ts +34 -0
  166. package/dist/core/validation.js +176 -0
  167. package/dist/documents/extraction.d.ts +121 -0
  168. package/dist/documents/extraction.js +293 -0
  169. package/dist/documents/index.d.ts +199 -0
  170. package/dist/documents/index.js +65 -0
  171. package/dist/documents/parsers/pdf.d.ts +47 -0
  172. package/dist/documents/parsers/pdf.js +508 -0
  173. package/dist/documents/parsers/text.d.ts +59 -0
  174. package/dist/documents/parsers/text.js +325 -0
  175. package/dist/documents/read-tool.d.ts +52 -0
  176. package/dist/documents/read-tool.js +109 -0
  177. package/dist/documents/render.d.ts +29 -0
  178. package/dist/documents/render.js +59 -0
  179. package/dist/documents/vision.d.ts +159 -0
  180. package/dist/documents/vision.js +214 -0
  181. package/dist/entries/adapters-bullmq.d.ts +8 -0
  182. package/dist/entries/adapters-bullmq.js +8 -0
  183. package/dist/entries/adapters-otel.d.ts +13 -0
  184. package/dist/entries/adapters-otel.js +13 -0
  185. package/dist/entries/adapters-postgres.d.ts +10 -0
  186. package/dist/entries/adapters-postgres.js +10 -0
  187. package/dist/entries/adapters-redis.d.ts +3 -0
  188. package/dist/entries/adapters-redis.js +3 -0
  189. package/dist/entries/context.d.ts +20 -0
  190. package/dist/entries/context.js +20 -0
  191. package/dist/entries/flows.d.ts +15 -0
  192. package/dist/entries/flows.js +15 -0
  193. package/dist/entries/hitl.d.ts +10 -0
  194. package/dist/entries/hitl.js +10 -0
  195. package/dist/entries/knowledge.d.ts +18 -0
  196. package/dist/entries/knowledge.js +19 -0
  197. package/dist/entries/mcp.d.ts +10 -0
  198. package/dist/entries/mcp.js +10 -0
  199. package/dist/entries/observability.d.ts +14 -0
  200. package/dist/entries/observability.js +16 -0
  201. package/dist/entries/persistence.d.ts +11 -0
  202. package/dist/entries/persistence.js +11 -0
  203. package/dist/entries/providers.d.ts +14 -0
  204. package/dist/entries/providers.js +14 -0
  205. package/dist/entries/runtime.d.ts +13 -0
  206. package/dist/entries/runtime.js +13 -0
  207. package/dist/entries/server.d.ts +24 -0
  208. package/dist/entries/server.js +24 -0
  209. package/dist/entries/tools.d.ts +21 -0
  210. package/dist/entries/tools.js +21 -0
  211. package/dist/entries/usage.d.ts +10 -0
  212. package/dist/entries/usage.js +10 -0
  213. package/dist/evaluation/gate.d.ts +168 -0
  214. package/dist/evaluation/gate.js +180 -0
  215. package/dist/evaluation/graders.d.ts +125 -0
  216. package/dist/evaluation/graders.js +203 -0
  217. package/dist/evaluation/index.d.ts +120 -0
  218. package/dist/evaluation/index.js +183 -0
  219. package/dist/evaluation/judge.d.ts +75 -0
  220. package/dist/evaluation/judge.js +111 -0
  221. package/dist/export/index.d.ts +162 -0
  222. package/dist/export/index.js +363 -0
  223. package/dist/export/markdown.d.ts +19 -0
  224. package/dist/export/markdown.js +29 -0
  225. package/dist/export/pdf.d.ts +73 -0
  226. package/dist/export/pdf.js +407 -0
  227. package/dist/files/context.d.ts +97 -0
  228. package/dist/files/context.js +185 -0
  229. package/dist/files/index.d.ts +210 -0
  230. package/dist/files/index.js +338 -0
  231. package/dist/files/read-tool.d.ts +81 -0
  232. package/dist/files/read-tool.js +163 -0
  233. package/dist/files/turn-parts.d.ts +96 -0
  234. package/dist/files/turn-parts.js +171 -0
  235. package/dist/flows/index.d.ts +270 -0
  236. package/dist/flows/index.js +62 -0
  237. package/dist/flows/interpreter.d.ts +146 -0
  238. package/dist/flows/interpreter.js +426 -0
  239. package/dist/flows/runner.d.ts +145 -0
  240. package/dist/flows/runner.js +270 -0
  241. package/dist/graphql/index.d.ts +8 -0
  242. package/dist/graphql/index.js +8 -0
  243. package/dist/graphql/resolvers.d.ts +237 -0
  244. package/dist/graphql/resolvers.js +253 -0
  245. package/dist/graphql/schema.d.ts +11 -0
  246. package/dist/graphql/schema.js +258 -0
  247. package/dist/graphql/sse.d.ts +77 -0
  248. package/dist/graphql/sse.js +100 -0
  249. package/dist/hitl/approved-execution.d.ts +127 -0
  250. package/dist/hitl/approved-execution.js +177 -0
  251. package/dist/hitl/index.d.ts +79 -0
  252. package/dist/hitl/index.js +12 -0
  253. package/dist/hitl/service.d.ts +221 -0
  254. package/dist/hitl/service.js +268 -0
  255. package/dist/idempotency/index.d.ts +70 -0
  256. package/dist/idempotency/index.js +59 -0
  257. package/dist/index.d.ts +103 -0
  258. package/dist/index.js +60 -0
  259. package/dist/knowledge/chunking.d.ts +57 -0
  260. package/dist/knowledge/chunking.js +158 -0
  261. package/dist/knowledge/index.d.ts +119 -0
  262. package/dist/knowledge/index.js +166 -0
  263. package/dist/knowledge/retrieval.d.ts +146 -0
  264. package/dist/knowledge/retrieval.js +170 -0
  265. package/dist/loadtest/harness.d.ts +168 -0
  266. package/dist/loadtest/harness.js +507 -0
  267. package/dist/loadtest/index.d.ts +13 -0
  268. package/dist/loadtest/index.js +13 -0
  269. package/dist/loadtest/injection.d.ts +89 -0
  270. package/dist/loadtest/injection.js +147 -0
  271. package/dist/loadtest/metrics.d.ts +197 -0
  272. package/dist/loadtest/metrics.js +160 -0
  273. package/dist/loadtest/runbooks.d.ts +28 -0
  274. package/dist/loadtest/runbooks.js +159 -0
  275. package/dist/loadtest/scenario.d.ts +104 -0
  276. package/dist/loadtest/scenario.js +208 -0
  277. package/dist/mcp/egress.d.ts +53 -0
  278. package/dist/mcp/egress.js +115 -0
  279. package/dist/mcp/index.d.ts +93 -0
  280. package/dist/mcp/index.js +33 -0
  281. package/dist/mcp/provider.d.ts +62 -0
  282. package/dist/mcp/provider.js +0 -0
  283. package/dist/models/index.d.ts +98 -0
  284. package/dist/models/index.js +74 -0
  285. package/dist/models/pricing.d.ts +24 -0
  286. package/dist/models/pricing.js +37 -0
  287. package/dist/models/provider-factory.d.ts +31 -0
  288. package/dist/models/provider-factory.js +67 -0
  289. package/dist/models/streaming.d.ts +145 -0
  290. package/dist/models/streaming.js +272 -0
  291. package/dist/models/vision.d.ts +38 -0
  292. package/dist/models/vision.js +62 -0
  293. package/dist/persistence/index.d.ts +1654 -0
  294. package/dist/persistence/index.js +226 -0
  295. package/dist/principal-memory/index.d.ts +106 -0
  296. package/dist/principal-memory/index.js +89 -0
  297. package/dist/retention/index.d.ts +89 -0
  298. package/dist/retention/index.js +70 -0
  299. package/dist/runtime/checkpoint.d.ts +37 -0
  300. package/dist/runtime/checkpoint.js +22 -0
  301. package/dist/runtime/index.d.ts +118 -0
  302. package/dist/runtime/index.js +69 -0
  303. package/dist/runtime/retry.d.ts +95 -0
  304. package/dist/runtime/retry.js +126 -0
  305. package/dist/runtime/serialization.d.ts +85 -0
  306. package/dist/runtime/serialization.js +95 -0
  307. package/dist/runtime/streaming.d.ts +54 -0
  308. package/dist/runtime/streaming.js +115 -0
  309. package/dist/runtime/worker.d.ts +130 -0
  310. package/dist/runtime/worker.js +405 -0
  311. package/dist/security/checklist.d.ts +53 -0
  312. package/dist/security/checklist.js +204 -0
  313. package/dist/security/findings.d.ts +56 -0
  314. package/dist/security/findings.js +168 -0
  315. package/dist/security/index.d.ts +14 -0
  316. package/dist/security/index.js +14 -0
  317. package/dist/security/prompt-safety.d.ts +100 -0
  318. package/dist/security/prompt-safety.js +133 -0
  319. package/dist/server/boot.d.ts +32 -0
  320. package/dist/server/boot.js +36 -0
  321. package/dist/server/cli-worker.d.ts +37 -0
  322. package/dist/server/cli-worker.js +151 -0
  323. package/dist/server/cli.d.ts +27 -0
  324. package/dist/server/cli.js +74 -0
  325. package/dist/server/config.d.ts +42 -0
  326. package/dist/server/config.js +127 -0
  327. package/dist/server/health.d.ts +59 -0
  328. package/dist/server/health.js +90 -0
  329. package/dist/server/host.d.ts +39 -0
  330. package/dist/server/host.js +124 -0
  331. package/dist/server/index.d.ts +15 -0
  332. package/dist/server/index.js +15 -0
  333. package/dist/server/main.d.ts +16 -0
  334. package/dist/server/main.js +31 -0
  335. package/dist/server/sse-route.d.ts +21 -0
  336. package/dist/server/sse-route.js +282 -0
  337. package/dist/skills/index.d.ts +67 -0
  338. package/dist/skills/index.js +31 -0
  339. package/dist/skills/resolver.d.ts +54 -0
  340. package/dist/skills/resolver.js +121 -0
  341. package/dist/teams/index.d.ts +93 -0
  342. package/dist/teams/index.js +207 -0
  343. package/dist/telemetry/index.d.ts +157 -0
  344. package/dist/telemetry/index.js +71 -0
  345. package/dist/telemetry/instrument.d.ts +108 -0
  346. package/dist/telemetry/instrument.js +232 -0
  347. package/dist/telemetry/log-events.d.ts +17 -0
  348. package/dist/telemetry/log-events.js +58 -0
  349. package/dist/telemetry/metrics.d.ts +123 -0
  350. package/dist/telemetry/metrics.js +135 -0
  351. package/dist/telemetry/noop.d.ts +39 -0
  352. package/dist/telemetry/noop.js +143 -0
  353. package/dist/telemetry/redaction.d.ts +64 -0
  354. package/dist/telemetry/redaction.js +153 -0
  355. package/dist/telemetry/spans.d.ts +56 -0
  356. package/dist/telemetry/spans.js +78 -0
  357. package/dist/telemetry/trace-context.d.ts +55 -0
  358. package/dist/telemetry/trace-context.js +60 -0
  359. package/dist/toolkit/compute.d.ts +53 -0
  360. package/dist/toolkit/compute.js +152 -0
  361. package/dist/toolkit/data.d.ts +98 -0
  362. package/dist/toolkit/data.js +235 -0
  363. package/dist/toolkit/http.d.ts +113 -0
  364. package/dist/toolkit/http.js +205 -0
  365. package/dist/toolkit/index.d.ts +21 -0
  366. package/dist/toolkit/index.js +17 -0
  367. package/dist/toolkit/web.d.ts +107 -0
  368. package/dist/toolkit/web.js +147 -0
  369. package/dist/tools/define.d.ts +25 -0
  370. package/dist/tools/define.js +45 -0
  371. package/dist/tools/delegating.d.ts +132 -0
  372. package/dist/tools/delegating.js +211 -0
  373. package/dist/tools/index.d.ts +129 -0
  374. package/dist/tools/index.js +33 -0
  375. package/dist/tools/library/compute.d.ts +11 -0
  376. package/dist/tools/library/compute.js +46 -0
  377. package/dist/tools/library/data.d.ts +16 -0
  378. package/dist/tools/library/data.js +92 -0
  379. package/dist/tools/library/http.d.ts +28 -0
  380. package/dist/tools/library/http.js +71 -0
  381. package/dist/tools/library/index.d.ts +97 -0
  382. package/dist/tools/library/index.js +134 -0
  383. package/dist/tools/library/knowledge.d.ts +39 -0
  384. package/dist/tools/library/knowledge.js +58 -0
  385. package/dist/tools/library/web.d.ts +19 -0
  386. package/dist/tools/library/web.js +65 -0
  387. package/dist/tools/meta-tools.d.ts +19 -0
  388. package/dist/tools/meta-tools.js +36 -0
  389. package/dist/tools/registry.d.ts +146 -0
  390. package/dist/tools/registry.js +291 -0
  391. package/dist/usage/index.d.ts +105 -0
  392. package/dist/usage/index.js +20 -0
  393. package/dist/usage/quota.d.ts +258 -0
  394. package/dist/usage/quota.js +510 -0
  395. package/dist/usage/recorder.d.ts +29 -0
  396. package/dist/usage/recorder.js +96 -0
  397. package/dist/usage/rollups.d.ts +121 -0
  398. package/dist/usage/rollups.js +157 -0
  399. package/dist/worker/export.d.ts +57 -0
  400. package/dist/worker/export.js +81 -0
  401. package/dist/worker/extraction.d.ts +57 -0
  402. package/dist/worker/extraction.js +84 -0
  403. package/dist/worker/main.d.ts +103 -0
  404. package/dist/worker/main.js +159 -0
  405. package/package.json +187 -0
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Hybrid retrieval (#136).
3
+ *
4
+ * Semantic search misses what it was never trained on — a product code, an error number, a campaign
5
+ * identifier. An embedding of `ERR-4021` is an embedding of a string that looks like other strings. Keyword
6
+ * search misses everything phrased differently from the document. Neither is sufficient, which is why docs/05
7
+ * specifies both.
8
+ *
9
+ * **Fusion is reciprocal rank fusion, not weighted score addition**, and the reason is that the two scores are
10
+ * not comparable. A cosine similarity is bounded and roughly linear in relevance; `ts_rank_cd` is unbounded and
11
+ * corpus-dependent. Adding them with weights means choosing a constant that is wrong for some corpus, and the
12
+ * failure is silent — one signal quietly dominates and the hybrid is the worse of the two. RRF uses only the
13
+ * *rank*, so it needs no calibration and cannot be dominated:
14
+ *
15
+ * score(d) = Σ over signals of 1 / (K + rank(d))
16
+ *
17
+ * A document ranked first by one signal and absent from the other still beats one ranked fifth by both, which
18
+ * is the behaviour that makes hybrid better than either — the exact-term hit surfaces even though the semantic
19
+ * signal never saw it.
20
+ *
21
+ * **`K = 60`** is the value from Cormack, Clarke and Buettcher's original TREC work and the one every
22
+ * implementation since has used. It is large relative to the ranks that matter, which flattens the difference
23
+ * between rank 1 and rank 2 and lets *agreement between signals* outweigh a single signal's confidence.
24
+ *
25
+ * **The empty answer is a distinct shape.** `RetrievalOutcome` is a union, so "found nothing" has no success
26
+ * shape to hide in: a caller cannot accidentally treat an empty hit list as a weak answer, and the model is
27
+ * told there is nothing rather than handed the least-bad match — which it would cite. AC-4 is a type here, not
28
+ * a convention.
29
+ */
30
+ import type { TenantId } from "../core/ids.js";
31
+ import type { KeywordIndex, KnowledgeChunk, KnowledgeSourceType, VectorIndex } from "../persistence/index.js";
32
+ import type { EmbeddingProvider } from "./index.js";
33
+ /** The rank-fusion constant. See the note above on why 60 and why rank rather than score. */
34
+ export declare const RRF_K = 60;
35
+ /** How many candidates each signal contributes before fusion. */
36
+ export declare const DEFAULT_CANDIDATES = 20;
37
+ /**
38
+ * Below this fused score, relative to the best result, nothing is returned.
39
+ *
40
+ * The floor that makes AC-4 real. Without one, every query returns *something* — the least-bad match — and a
41
+ * model handed the least-bad match cites it. 0.4 of the best score is loose enough not to discard a genuine
42
+ * second-best answer and tight enough to reject a corpus that simply has nothing to say.
43
+ */
44
+ export declare const DEFAULT_RELEVANCE_FLOOR = 0.4;
45
+ export type RetrievalMode = "semantic" | "keyword" | "hybrid";
46
+ /** What a citation needs, derived from a hit so there is one shape rather than each caller's own (AC-6). */
47
+ export type SourceReference = {
48
+ readonly sourceType: KnowledgeSourceType;
49
+ readonly sourceId: string;
50
+ readonly chunkIndex: number;
51
+ readonly chunkId: string;
52
+ /** The heading path, when the chunker found one. What makes a citation point at a place, not a document. */
53
+ readonly locator?: string;
54
+ };
55
+ export type RetrievalHit = {
56
+ readonly chunk: KnowledgeChunk;
57
+ /** The fused score, 0–1 relative to the best hit. Not comparable across queries, only within one. */
58
+ readonly score: number;
59
+ /** Which signals found it, for explaining a result and for measuring the fusion. */
60
+ readonly signals: readonly RetrievalMode[];
61
+ readonly reference: SourceReference;
62
+ };
63
+ /**
64
+ * Why retrieval returned nothing.
65
+ *
66
+ * Separate values because the assistant's sentence differs: "nothing in your documents mentions that" is a
67
+ * different answer from "you have no indexed documents", and telling a user the first when the second is true
68
+ * sends them looking for content they never uploaded.
69
+ */
70
+ export declare const NO_RESULT_REASONS: readonly ["nothing-indexed", "no-match", "below-threshold", "no-access"];
71
+ export type NoResultReason = (typeof NO_RESULT_REASONS)[number];
72
+ export type RetrievalOutcome = {
73
+ readonly found: true;
74
+ readonly hits: readonly RetrievalHit[];
75
+ readonly mode: RetrievalMode;
76
+ } | {
77
+ readonly found: false;
78
+ readonly reason: NoResultReason;
79
+ readonly message: string;
80
+ readonly mode: RetrievalMode;
81
+ };
82
+ /**
83
+ * Reorders a fused candidate set — AC-5.
84
+ *
85
+ * A port, and **switchable**, because a reranker's value is a claim that has to be provable. A cross-encoder is
86
+ * materially more expensive than the retrieval it reorders, so "we rerank" without a measured contribution is
87
+ * a cost nobody justified. Absent means fusion order stands, which is the honest default.
88
+ */
89
+ export interface Reranker {
90
+ readonly id: string;
91
+ rerank(input: {
92
+ readonly query: string;
93
+ readonly candidates: readonly RetrievalHit[];
94
+ readonly limit: number;
95
+ }): Promise<readonly RetrievalHit[]>;
96
+ }
97
+ export type RetrieverDeps = {
98
+ readonly vector: VectorIndex;
99
+ readonly keyword: KeywordIndex;
100
+ readonly embeddings: EmbeddingProvider;
101
+ readonly reranker?: Reranker;
102
+ readonly candidates?: number;
103
+ /** Relative: how much worse than the best hit is still worth returning. */
104
+ readonly relevanceFloor?: number;
105
+ /**
106
+ * Absolute: how similar a vector hit must be to be a candidate at all.
107
+ *
108
+ * Two floors because they answer different questions, and one cannot do both — a *relative* floor can never
109
+ * reject a uniformly poor result set, because something is always the best of it. This is what makes AC-4
110
+ * possible: without it the vector index returns every chunk it is asked for (0.5 is orthogonal, not
111
+ * "no match"), the best of them normalises to 1.0, and every query finds something.
112
+ */
113
+ readonly semanticFloor?: number;
114
+ };
115
+ export type RetrieveInput = {
116
+ readonly query: string;
117
+ /**
118
+ * The subjects this caller may read.
119
+ *
120
+ * Required, and passed to *both* signals. A filter applied to one and not the other is a filter that does not
121
+ * exist — the unfiltered signal would surface the chunk and fusion would rank it.
122
+ */
123
+ readonly authSubjects: readonly string[];
124
+ readonly limit: number;
125
+ readonly sourceTypes?: readonly KnowledgeSourceType[];
126
+ /** Defaults to `hybrid`. The other two exist so the hybrid claim can be measured against them. */
127
+ readonly mode?: RetrievalMode;
128
+ };
129
+ export declare const createRetriever: (deps: RetrieverDeps) => {
130
+ rerankerId: string | null;
131
+ retrieve(context: {
132
+ readonly tenantId: TenantId;
133
+ }, input: RetrieveInput): Promise<RetrievalOutcome>;
134
+ };
135
+ export type Retriever = ReturnType<typeof createRetriever>;
136
+ /**
137
+ * A reranker that promotes chunks matching the query's rare exact terms.
138
+ *
139
+ * Deliberately simple and deliberately *not* a model: this exists so AC-5's "switchable and measured" has
140
+ * something real to switch on, and so the measurement harness has a baseline that is better than nothing and
141
+ * obviously cheaper than a cross-encoder. It promotes a candidate containing a query term verbatim, which is
142
+ * the signal fusion is weakest on — a rank-based fusion cannot know that one of the two signals matched an
143
+ * exact identifier rather than a common word.
144
+ */
145
+ export declare const createExactTermReranker: () => Reranker;
146
+ //# sourceMappingURL=retrieval.d.ts.map
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Hybrid retrieval (#136).
3
+ *
4
+ * Semantic search misses what it was never trained on — a product code, an error number, a campaign
5
+ * identifier. An embedding of `ERR-4021` is an embedding of a string that looks like other strings. Keyword
6
+ * search misses everything phrased differently from the document. Neither is sufficient, which is why docs/05
7
+ * specifies both.
8
+ *
9
+ * **Fusion is reciprocal rank fusion, not weighted score addition**, and the reason is that the two scores are
10
+ * not comparable. A cosine similarity is bounded and roughly linear in relevance; `ts_rank_cd` is unbounded and
11
+ * corpus-dependent. Adding them with weights means choosing a constant that is wrong for some corpus, and the
12
+ * failure is silent — one signal quietly dominates and the hybrid is the worse of the two. RRF uses only the
13
+ * *rank*, so it needs no calibration and cannot be dominated:
14
+ *
15
+ * score(d) = Σ over signals of 1 / (K + rank(d))
16
+ *
17
+ * A document ranked first by one signal and absent from the other still beats one ranked fifth by both, which
18
+ * is the behaviour that makes hybrid better than either — the exact-term hit surfaces even though the semantic
19
+ * signal never saw it.
20
+ *
21
+ * **`K = 60`** is the value from Cormack, Clarke and Buettcher's original TREC work and the one every
22
+ * implementation since has used. It is large relative to the ranks that matter, which flattens the difference
23
+ * between rank 1 and rank 2 and lets *agreement between signals* outweigh a single signal's confidence.
24
+ *
25
+ * **The empty answer is a distinct shape.** `RetrievalOutcome` is a union, so "found nothing" has no success
26
+ * shape to hide in: a caller cannot accidentally treat an empty hit list as a weak answer, and the model is
27
+ * told there is nothing rather than handed the least-bad match — which it would cite. AC-4 is a type here, not
28
+ * a convention.
29
+ */
30
+ import { SEMANTIC_RELEVANCE_FLOOR } from "../persistence/index.js";
31
+ /** The rank-fusion constant. See the note above on why 60 and why rank rather than score. */
32
+ export const RRF_K = 60;
33
+ /** How many candidates each signal contributes before fusion. */
34
+ export const DEFAULT_CANDIDATES = 20;
35
+ /**
36
+ * Below this fused score, relative to the best result, nothing is returned.
37
+ *
38
+ * The floor that makes AC-4 real. Without one, every query returns *something* — the least-bad match — and a
39
+ * model handed the least-bad match cites it. 0.4 of the best score is loose enough not to discard a genuine
40
+ * second-best answer and tight enough to reject a corpus that simply has nothing to say.
41
+ */
42
+ export const DEFAULT_RELEVANCE_FLOOR = 0.4;
43
+ /**
44
+ * Why retrieval returned nothing.
45
+ *
46
+ * Separate values because the assistant's sentence differs: "nothing in your documents mentions that" is a
47
+ * different answer from "you have no indexed documents", and telling a user the first when the second is true
48
+ * sends them looking for content they never uploaded.
49
+ */
50
+ export const NO_RESULT_REASONS = ["nothing-indexed", "no-match", "below-threshold", "no-access"];
51
+ const referenceFor = (chunk) => ({
52
+ sourceType: chunk.sourceType,
53
+ sourceId: chunk.sourceId,
54
+ chunkIndex: chunk.chunkIndex,
55
+ chunkId: chunk.id,
56
+ ...(chunk.locator === undefined ? {} : { locator: chunk.locator }),
57
+ });
58
+ const NO_RESULT_MESSAGES = {
59
+ "nothing-indexed": "There is no indexed material to search yet.",
60
+ "no-match": "Nothing in the available material matches that.",
61
+ "below-threshold": "Nothing in the available material is a close enough match to rely on.",
62
+ "no-access": "There is no material you have access to that matches that.",
63
+ };
64
+ export const createRetriever = (deps) => {
65
+ const candidateCount = deps.candidates ?? DEFAULT_CANDIDATES;
66
+ const floor = deps.relevanceFloor ?? DEFAULT_RELEVANCE_FLOOR;
67
+ const semanticFloor = deps.semanticFloor ?? SEMANTIC_RELEVANCE_FLOOR;
68
+ return {
69
+ rerankerId: deps.reranker?.id ?? null,
70
+ async retrieve(context, input) {
71
+ const mode = input.mode ?? "hybrid";
72
+ // Checked before either index is asked. An empty subject list is not a query with no results — it is a
73
+ // caller with no access, and the two want different sentences.
74
+ if (input.authSubjects.length === 0)
75
+ return { found: false, reason: "no-access", message: NO_RESULT_MESSAGES["no-access"], mode };
76
+ if (input.query.trim() === "")
77
+ return { found: false, reason: "no-match", message: NO_RESULT_MESSAGES["no-match"], mode };
78
+ const scope = {
79
+ tenantId: context.tenantId,
80
+ authSubjects: input.authSubjects,
81
+ limit: candidateCount,
82
+ ...(input.sourceTypes === undefined ? {} : { sourceTypes: input.sourceTypes }),
83
+ };
84
+ const semantic = mode === "keyword"
85
+ ? []
86
+ : await (async () => {
87
+ const [embedding] = await deps.embeddings.embed([input.query]);
88
+ // The absolute floor goes to the index, not applied afterwards: a chunk that shares nothing with
89
+ // the query must not be a candidate, because fusion would rank it first in a result set where
90
+ // nothing is good.
91
+ return deps.vector.search({ ...scope, embedding: embedding ?? [], minScore: semanticFloor });
92
+ })();
93
+ const lexical = mode === "semantic" ? [] : await deps.keyword.search({ ...scope, query: input.query });
94
+ if (semantic.length === 0 && lexical.length === 0)
95
+ return { found: false, reason: "no-match", message: NO_RESULT_MESSAGES["no-match"], mode };
96
+ // RRF. Rank, not score: see the note at the top on why adding two incomparable scales fails silently.
97
+ const fused = new Map();
98
+ const contribute = (hits, signal) => {
99
+ hits.forEach((hit, rank) => {
100
+ const existing = fused.get(hit.chunk.id);
101
+ const increment = 1 / (RRF_K + rank + 1);
102
+ if (existing === undefined)
103
+ fused.set(hit.chunk.id, { chunk: hit.chunk, score: increment, signals: new Set([signal]) });
104
+ else {
105
+ existing.score += increment;
106
+ existing.signals.add(signal);
107
+ }
108
+ });
109
+ };
110
+ contribute(semantic, "semantic");
111
+ contribute(lexical, "keyword");
112
+ const ordered = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.chunk.id.localeCompare(b.chunk.id));
113
+ const best = ordered[0]?.score ?? 0;
114
+ const candidates = ordered.map((entry) => ({
115
+ chunk: entry.chunk,
116
+ // Normalised against the best fused score, so the floor means the same thing whatever the corpus.
117
+ score: best === 0 ? 0 : entry.score / best,
118
+ signals: [...entry.signals],
119
+ reference: referenceFor(entry.chunk),
120
+ }));
121
+ const relevant = candidates.filter((hit) => hit.score >= floor);
122
+ if (relevant.length === 0)
123
+ // Something was found and none of it was good enough. A distinct reason from "no match", because the
124
+ // useful answer differs: one says rephrase, the other says there is nothing there.
125
+ return { found: false, reason: "below-threshold", message: NO_RESULT_MESSAGES["below-threshold"], mode };
126
+ const hits = deps.reranker === undefined
127
+ ? relevant.slice(0, input.limit)
128
+ : await deps.reranker.rerank({ query: input.query, candidates: relevant, limit: input.limit });
129
+ // A reranker that returned nothing is a reranker that broke; fusion order is a better answer than an
130
+ // empty one, and a silent empty result here would look like AC-4 working.
131
+ return hits.length === 0
132
+ ? { found: true, hits: relevant.slice(0, input.limit), mode }
133
+ : { found: true, hits: hits.slice(0, input.limit), mode };
134
+ },
135
+ };
136
+ };
137
+ /**
138
+ * A reranker that promotes chunks matching the query's rare exact terms.
139
+ *
140
+ * Deliberately simple and deliberately *not* a model: this exists so AC-5's "switchable and measured" has
141
+ * something real to switch on, and so the measurement harness has a baseline that is better than nothing and
142
+ * obviously cheaper than a cross-encoder. It promotes a candidate containing a query term verbatim, which is
143
+ * the signal fusion is weakest on — a rank-based fusion cannot know that one of the two signals matched an
144
+ * exact identifier rather than a common word.
145
+ */
146
+ export const createExactTermReranker = () => ({
147
+ id: "exact-term",
148
+ async rerank({ query, candidates, limit }) {
149
+ const terms = (query.toLowerCase().match(/[a-z0-9]+(?:-[a-z0-9]+)*/g) ?? []).filter(
150
+ // Only terms that look like identifiers: containing a digit or a hyphen. A common word appearing
151
+ // verbatim is not evidence of anything, and boosting on it would just re-rank by word frequency.
152
+ (t) => /[0-9]/.test(t) || t.includes("-"));
153
+ if (terms.length === 0)
154
+ return candidates.slice(0, limit);
155
+ const boosted = candidates.map((hit) => {
156
+ const content = hit.chunk.content.toLowerCase();
157
+ const matched = terms.filter((t) => content.includes(t)).length;
158
+ return { hit, matched };
159
+ });
160
+ return boosted
161
+ .sort((a, b) => b.matched !== a.matched
162
+ ? b.matched - a.matched
163
+ : // Fusion order within a tier, so reranking only ever *promotes* on evidence and never reshuffles
164
+ // arbitrarily.
165
+ b.hit.score - a.hit.score)
166
+ .map((b) => b.hit)
167
+ .slice(0, limit);
168
+ },
169
+ });
170
+ //# sourceMappingURL=retrieval.js.map
@@ -0,0 +1,168 @@
1
+ /**
2
+ * The load and soak driver — AC-1, AC-2, AC-3, AC-4.
3
+ *
4
+ * Drives the **real durable path**: a real Postgres schema, a real BullMQ queue on a real Redis, several real
5
+ * `WorkerRuntime` instances competing for work, real atomic claims, real leases, real checkpoints and a real
6
+ * event log. The only synthetic part is the agent engine, and that is not a shortcut — see `scenario.ts`.
7
+ *
8
+ * What this is *not* is a request against a deployed HTTP endpoint. #144 asks for that, and there is no deployed
9
+ * instance yet; the layers this cannot reach are the GraphQL server and the process boundary between host and
10
+ * worker. Everything below them is exercised for real. That boundary is stated in the report the harness writes,
11
+ * not left for someone to infer from a green tick.
12
+ *
13
+ * Structured so the driver returns **data** and the judging happens in `metrics.ts` and `injection.ts`. A
14
+ * harness that both ran the load and decided whether it passed would be a harness whose verdict nobody could
15
+ * test, and the verdict is the part most likely to be quietly wrong.
16
+ */
17
+ import { type JobConsumer } from "../worker/main.js";
18
+ import type { ConversationId, RunId, TenantId } from "../core/ids.js";
19
+ import type { JobDispatcher } from "../runtime/index.js";
20
+ import type { SqlExecutor } from "../adapters/postgres/sql.js";
21
+ import { type EffectLedger, type TrafficShape } from "./scenario.js";
22
+ import { detectGrowth, type LoadStep, type ResourceSample } from "./metrics.js";
23
+ export type HarnessConfig = {
24
+ readonly tenantId: TenantId;
25
+ /** Worker runtimes competing for the same queue. Several, or a claim race is never exercised. */
26
+ readonly workers: number;
27
+ readonly concurrency: number;
28
+ /** Short, so a killed worker's lease expires inside a test rather than inside a coffee break. */
29
+ readonly leaseMs: number;
30
+ readonly reapEveryMs: number;
31
+ readonly traffic: TrafficShape;
32
+ readonly seed: number;
33
+ /**
34
+ * The queue's bound. Past it, admission is refused.
35
+ *
36
+ * The mechanism AC-4 asks for. Without a bound, "overload" means an unbounded in-memory backlog, which is the
37
+ * failure mode rather than the test.
38
+ */
39
+ readonly maxQueueDepth: number;
40
+ readonly sampleEveryMs: number;
41
+ };
42
+ export declare const DEFAULT_HARNESS: Omit<HarnessConfig, "tenantId">;
43
+ /**
44
+ * An in-process queue with a **bounded** depth and an explicit refusal.
45
+ *
46
+ * Used where the point is backpressure rather than Redis. Deliberately not BullMQ for the overload case: BullMQ's
47
+ * depth is Redis memory, so "bounded queueing" there is a Redis configuration question and the assertion would
48
+ * be about Redis. Here the bound is ours and the refusal is the platform's.
49
+ */
50
+ export declare class QueueFull extends Error {
51
+ readonly depth: number;
52
+ readonly code = "resource-exhausted";
53
+ readonly retryable = true;
54
+ constructor(depth: number);
55
+ }
56
+ export type BoundedQueue = {
57
+ readonly dispatcher: JobDispatcher;
58
+ /**
59
+ * A **fresh consumer per worker**, not one shared object.
60
+ *
61
+ * `JobConsumer.stop()` has no handle to say *which* worker is stopping, so a shared consumer's `stop` had to
62
+ * clear every registration — which meant killing one worker silently stopped all three. The worker-kill
63
+ * injection then hung forever waiting for a drain that could never happen, produced no output at all, and it
64
+ * took a process listing to find. Each worker gets its own view, closing over its own slot.
65
+ */
66
+ consumerFor(): JobConsumer;
67
+ depth(): number;
68
+ peakDepth(): number;
69
+ refused(): number;
70
+ /** Jobs handed to a worker more than once. A pass that needed retries is not a clean first-attempt pass. */
71
+ retried(): number;
72
+ drained(): Promise<void>;
73
+ };
74
+ export declare const createBoundedQueue: (maxDepth: number, perWorkerConcurrency?: number) => BoundedQueue;
75
+ export type WorkerHandle = {
76
+ readonly id: string;
77
+ /** Stop without draining — the worker-kill injector. */
78
+ kill(): Promise<void>;
79
+ shutdown(): Promise<void>;
80
+ };
81
+ export type Harness = {
82
+ readonly effects: EffectLedger;
83
+ readonly queue: BoundedQueue;
84
+ readonly workers: readonly WorkerHandle[];
85
+ /** Admit and enqueue one run. Throws `QueueFull` when the queue is at its bound. */
86
+ admit(input: {
87
+ conversationId: ConversationId;
88
+ runId: RunId;
89
+ }): Promise<void>;
90
+ /** Runs in a terminal state, from the store — not from the harness's own bookkeeping. */
91
+ terminalCount(): Promise<number>;
92
+ /** Every run status and its count, so a paused run is never miscounted as a failure. */
93
+ statusCounts(): Promise<Readonly<Record<string, number>>>;
94
+ /**
95
+ * Approve everything waiting, and re-enqueue it.
96
+ *
97
+ * A load test that left approvals pending would report them as lost work, which is the opposite of the truth:
98
+ * a run waiting for a human is the platform holding state correctly, and it is the longest-lived state it has.
99
+ * Deciding them here is also the only way the resume path is exercised under load.
100
+ *
101
+ * Returns how long each run waited, so approval wait time is measured rather than assumed.
102
+ */
103
+ approvePending(): Promise<readonly number[]>;
104
+ /**
105
+ * Wait until nothing with this id prefix is still in flight, then report what happened.
106
+ *
107
+ * Necessary because "the queue is empty" is not "the work is done": the queue empties when the last job reaches
108
+ * a worker. Without settling, a step's slowest runs are still executing when it is measured, and they count as
109
+ * failures — my first staircase reported `mode: errors` at 20/s for exactly that reason, which would have sent
110
+ * an operator hunting a failure that was really my clock.
111
+ *
112
+ * A run still non-terminal when the timeout expires *does* count as stuck. That is the honest line: waiting
113
+ * forever would hide a genuine hang, and not waiting at all reports one that is not there.
114
+ */
115
+ settle(input: {
116
+ readonly idPrefix: string;
117
+ readonly timeoutMs: number;
118
+ }): Promise<{
119
+ readonly completed: number;
120
+ readonly failed: number;
121
+ readonly stuck: number;
122
+ readonly stuckByStatus?: Readonly<Record<string, number>>;
123
+ readonly approvalWaitsMs: readonly number[];
124
+ }>;
125
+ /**
126
+ * End-to-end latency per finished run, in ms, from the store's own timestamps.
127
+ *
128
+ * The number that matters. Admission latency is a property of the enqueue and stays flat under any backlog;
129
+ * what a user experiences is admission to terminal, and only the store knows both ends.
130
+ */
131
+ terminalLatencies(idPrefix: string): Promise<readonly number[]>;
132
+ admittedCount(): number;
133
+ sample(): ResourceSample;
134
+ stop(): Promise<void>;
135
+ };
136
+ /**
137
+ * Build the harness over an already-migrated schema.
138
+ *
139
+ * Takes a `SqlExecutor` rather than a URL so the caller owns the connection: the database-unavailable injector
140
+ * needs to stop the server underneath a live pool, and a harness that owned the pool would reconnect on its own
141
+ * schedule and the injector could not control the window.
142
+ */
143
+ export declare const createHarness: (input: {
144
+ readonly sql: SqlExecutor;
145
+ readonly config: HarnessConfig;
146
+ readonly now?: () => number;
147
+ readonly sleep?: (ms: number) => Promise<void>;
148
+ }) => Promise<Harness>;
149
+ /**
150
+ * One step of the load staircase.
151
+ *
152
+ * Offers a fixed rate for a fixed duration, then waits for the queue to drain before measuring. Measuring
153
+ * without draining would attribute a step's backlog to the *next* step and the staircase would show capacity
154
+ * that is really borrowed from earlier.
155
+ */
156
+ export declare const runLoadStep: (input: {
157
+ readonly harness: Harness;
158
+ readonly offeredPerSecond: number;
159
+ readonly durationMs: number;
160
+ readonly tenantId: TenantId;
161
+ readonly startIndex: number;
162
+ /** How long to wait for a step's work to finish before calling the remainder stuck. */
163
+ readonly settleTimeoutMs?: number;
164
+ readonly now?: () => number;
165
+ readonly sleep?: (ms: number) => Promise<void>;
166
+ }) => Promise<LoadStep>;
167
+ export { detectGrowth };
168
+ //# sourceMappingURL=harness.d.ts.map