@desplega.ai/agent-swarm 1.157.0 → 1.158.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 (256) hide show
  1. package/dist/{acp-adapter-qhqrk4q0.js → acp-adapter-xaq4n6pc.js} +1 -1
  2. package/dist/{actions-9rrg0zxm.js → actions-p9hz5yat.js} +15 -15
  3. package/dist/{app-enysy1zd.js → app-g26wdcz6.js} +4 -4
  4. package/dist/{artifact-td4q4dch.js → artifact-3v5t9jtg.js} +1 -1
  5. package/dist/{assistant-zegamy48.js → assistant-wydfqkb3.js} +16 -16
  6. package/dist/{boot-reembed-r6shx5qx.js → boot-reembed-g5ckg9yb.js} +6 -6
  7. package/dist/{boot-reembed-zfxb937k.js → boot-reembed-se8zmdcp.js} +5 -5
  8. package/dist/{boot-scrub-logs-k5y0se6r.js → boot-scrub-logs-wfxqan61.js} +3 -3
  9. package/dist/{seed-pricing-vqxa06qf.js → boot-seeds-s3q01xj3.js} +10 -10
  10. package/dist/{claude-adapter-5yc7hxwv.js → claude-adapter-tv2x4f36.js} +7 -7
  11. package/dist/{claude-managed-adapter-ea2aga6w.js → claude-managed-adapter-41b2s7fd.js} +2 -2
  12. package/dist/{claude-sdk-session-j4ywn3xf.js → claude-sdk-session-t442qz6f.js} +8 -8
  13. package/dist/{cli-e781c6f9.js → cli-0xjkj1j7.js} +1 -0
  14. package/dist/{cli-58rgvkt4.js → cli-1hkrch3k.js} +2 -2
  15. package/dist/{cli-yscm6cv8.js → cli-20cj37vt.js} +1866 -9
  16. package/dist/{cli-h0wdadsx.js → cli-4198qc9v.js} +7 -3
  17. package/dist/{cli-awwphhcs.js → cli-47m6dkd3.js} +362 -126
  18. package/dist/{cli-wb2zvbfg.js → cli-53sz8gkz.js} +1 -1
  19. package/dist/{cli-005pze6s.js → cli-5d10vd2m.js} +1 -1
  20. package/dist/{cli-v53rbqp3.js → cli-65hjmev5.js} +57 -17
  21. package/dist/{cli-scwq51gn.js → cli-68w09sjw.js} +7 -1
  22. package/dist/{cli-s98skd5r.js → cli-7gtvvpbh.js} +4 -4
  23. package/dist/{cli-y3nxwx0t.js → cli-7s3syk22.js} +18 -11
  24. package/dist/{cli-74h6f2bp.js → cli-8qmme6vd.js} +2 -2
  25. package/dist/{cli-wsed24mk.js → cli-987hg0aa.js} +2 -2
  26. package/dist/{cli-9n76jszt.js → cli-9httdpyq.js} +1 -1
  27. package/dist/{cli-f3va018d.js → cli-aky8tctm.js} +26 -93
  28. package/dist/{cli-sgyqyyxe.js → cli-c07r9a2m.js} +2 -1
  29. package/dist/{cli-c41wjx0r.js → cli-fgqxwrpv.js} +291 -12
  30. package/dist/{cli-01vfmq8c.js → cli-ftfvggzx.js} +607 -164
  31. package/dist/{cli-ytxs7mn1.js → cli-g8djp6qe.js} +17 -0
  32. package/dist/{cli-avkd6mqv.js → cli-h967nb6r.js} +551 -0
  33. package/dist/{cli-r9ee9c4w.js → cli-j55n64b6.js} +23 -22
  34. package/dist/{cli-9p33cz9h.js → cli-j57qkrpq.js} +86 -28
  35. package/dist/{cli-tjmghmm5.js → cli-q67y4wzm.js} +6 -3
  36. package/dist/{cli-n6zq3kbd.js → cli-rj19hc34.js} +1 -1
  37. package/dist/{cli-jytrw2na.js → cli-rjehvrts.js} +4 -4
  38. package/dist/{cli-tpv97m71.js → cli-rqz8qbw7.js} +245 -75
  39. package/dist/{cli-p37sg0a9.js → cli-s8eet254.js} +1 -1
  40. package/dist/cli-t1ze64h3.js +811 -0
  41. package/dist/{cli-6jjzxv3b.js → cli-ws6rqycm.js} +3 -2
  42. package/dist/{cli-xf5b7y1f.js → cli-wscdvcqz.js} +13 -5
  43. package/dist/{cli-5j7bm4tb.js → cli-x24pshtq.js} +5 -5
  44. package/dist/{cli-nbp6m6gp.js → cli-xberxa1r.js} +51 -26
  45. package/dist/{cli-vx9p3qdt.js → cli-xhaeg2nc.js} +1 -1
  46. package/dist/cli.js +29 -15
  47. package/dist/{codex-adapter-gns3s6c3.js → codex-adapter-cnm8wk11.js} +5 -5
  48. package/dist/{codex-session-runner-gqnxys5w.js → codex-session-runner-gfg547zj.js} +5 -5
  49. package/dist/{commands-hxy2y2sp.js → commands-e3bn0p75.js} +3 -3
  50. package/dist/{db-w8ghhsgf.js → db-03v9kzr2.js} +17 -3
  51. package/dist/{dispatcher-cp1rknjz.js → dispatcher-nrmg8yht.js} +14 -14
  52. package/dist/{dsh-adapter-1dwg97zv.js → dsh-adapter-k03nfqa6.js} +2 -2
  53. package/dist/{handlers-egfhr351.js → handlers-aqcedbyb.js} +17 -17
  54. package/dist/{hook-x4kftwzt.js → hook-7vkskkre.js} +19 -11
  55. package/dist/{hook-fbxjqfjz.js → hook-ybvmrmhq.js} +4 -4
  56. package/dist/{http-c7jfx990.js → http-2eqa8t24.js} +432 -195
  57. package/dist/{index-4k9hct21.js → index-1yks3qcr.js} +14 -14
  58. package/dist/{index-jtvpgb8f.js → index-a3vn96n8.js} +30 -27
  59. package/dist/{index-dc2ek6bw.js → index-c6zsv1bd.js} +5 -5
  60. package/dist/{index-yy07ef2s.js → index-chgdkq36.js} +14 -14
  61. package/dist/{index-r6bty6tb.js → index-x71bvq0p.js} +15 -15
  62. package/dist/{keepalive-f7ekefyc.js → keepalive-vtkf5n99.js} +5 -5
  63. package/dist/{lead-h053syts.js → lead-h3sp357x.js} +26 -26
  64. package/dist/{maintenance-a3w6zs54.js → maintenance-jzeqtk3q.js} +6 -6
  65. package/dist/{oauth-refresh-sweep-vra1dhkd.js → oauth-refresh-sweep-qp3dzmdp.js} +4 -4
  66. package/dist/{onboard-mfgzeqxs.js → onboard-tmsp0qbz.js} +278 -81
  67. package/dist/{opencode-adapter-z64xjzec.js → opencode-adapter-x6x2da1z.js} +3 -3
  68. package/dist/{otel-impl-2ez6xk57.js → otel-impl-9mz73q65.js} +416 -301
  69. package/dist/{pi-mono-adapter-2b7mw16r.js → pi-mono-adapter-m6dvv0dz.js} +2 -2
  70. package/dist/{pricing-refresh-6sw65tck.js → pricing-refresh-v1cbr9te.js} +5 -5
  71. package/dist/{rbac-roles-nm6924sy.js → rbac-roles-c9wqz83x.js} +4 -4
  72. package/dist/{render-v2-f026j6c4.js → render-v2-gryrh9h8.js} +4 -4
  73. package/dist/{setup-w606fr1q.js → setup-q9720bt6.js} +2 -2
  74. package/dist/{virtual-modules-8qheft18.js → virtual-modules-3htpgn8x.js} +1 -1
  75. package/dist/{work-objects-ezmggdne.js → work-objects-b76x7deb.js} +17 -17
  76. package/dist/{worker-1mbyv29k.js → worker-6vrxbv41.js} +26 -26
  77. package/openapi.json +1626 -629
  78. package/package.json +2 -1
  79. package/src/apps/catalog.generated.json +229 -0
  80. package/src/apps/page-validator.ts +71 -16
  81. package/src/apps/row-store.ts +66 -11
  82. package/src/apps/sync.ts +59 -17
  83. package/src/artifact-sdk/browser-sdk.ts +436 -2
  84. package/src/be/approval-sweeps.ts +109 -0
  85. package/src/be/boot-seeds.ts +40 -0
  86. package/src/be/chunking.ts +1 -1
  87. package/src/be/db/agents.ts +20 -0
  88. package/src/be/db/approvals.ts +78 -0
  89. package/src/be/db/tasks/read.ts +197 -39
  90. package/src/be/db/tasks/write.ts +41 -9
  91. package/src/be/db-client.ts +107 -48
  92. package/src/be/db.ts +219 -76
  93. package/src/be/events.ts +33 -1
  94. package/src/be/memory/graph-expansion.ts +10 -3
  95. package/src/be/memory/providers/sqlite-store.ts +55 -13
  96. package/src/be/memory/raters/retrieval.ts +5 -2
  97. package/src/be/memory/reranker.ts +26 -2
  98. package/src/be/memory/types.ts +2 -0
  99. package/src/be/migrations/166_approval_request_auto_cancellation.sql +9 -0
  100. package/src/be/migrations/171_memory_retrieval_relevance.sql +8 -0
  101. package/src/be/migrations/175_workflow_runs_list_index.sql +11 -0
  102. package/src/be/migrations/177_events_event_agent_created_index.sql +11 -0
  103. package/src/be/models-catalog.ts +2 -0
  104. package/src/be/modelsdev-cache.json +1857 -0
  105. package/src/be/modelsdev-cache.ts +14 -1
  106. package/src/be/pricing-normalize.ts +2 -0
  107. package/src/be/scripts/typecheck.ts +1 -0
  108. package/src/be/seed-pricing.ts +3 -1
  109. package/src/be/seed-skills/bundled-files.generated.json +1 -1
  110. package/src/be/steering.ts +53 -3
  111. package/src/be/swarm-config-guard.ts +3 -0
  112. package/src/be/task-citations.ts +29 -0
  113. package/src/cli.tsx +14 -1
  114. package/src/commands/onboard/compose-generator.ts +8 -3
  115. package/src/commands/onboard/container-engine.ts +220 -0
  116. package/src/commands/onboard/manifest.ts +1 -0
  117. package/src/commands/onboard/steps/health-check.tsx +4 -1
  118. package/src/commands/onboard/steps/prereq-check.tsx +50 -54
  119. package/src/commands/onboard/steps/start.tsx +31 -16
  120. package/src/commands/onboard/types.ts +7 -2
  121. package/src/commands/onboard.tsx +39 -4
  122. package/src/commands/profile-sync.ts +79 -26
  123. package/src/commands/runner.ts +8 -1
  124. package/src/extensions/catalog.generated.json +17 -0
  125. package/src/extensions/contract-types.generated.ts +1 -1
  126. package/src/heartbeat/heartbeat.ts +263 -103
  127. package/src/hooks/hook.ts +21 -12
  128. package/src/http/agents.ts +35 -0
  129. package/src/http/approval-requests.ts +136 -64
  130. package/src/http/apps.ts +14 -3
  131. package/src/http/config.ts +15 -1
  132. package/src/http/events.ts +62 -2
  133. package/src/http/index.ts +6 -4
  134. package/src/http/memory.ts +21 -7
  135. package/src/http/schedules.ts +1 -1
  136. package/src/http/session-data.ts +9 -4
  137. package/src/http/sessions.ts +25 -18
  138. package/src/http/stats.ts +19 -7
  139. package/src/http/status.ts +11 -1
  140. package/src/http/tasks.ts +40 -8
  141. package/src/http/webhooks.ts +67 -46
  142. package/src/http/workflows.ts +15 -20
  143. package/src/linear/outbound.ts +37 -15
  144. package/src/otel-impl.ts +151 -1
  145. package/src/otel.ts +14 -3
  146. package/src/prompts/memories.ts +19 -2
  147. package/src/providers/claude-managed-models.ts +8 -0
  148. package/src/providers/modelsdev-reasoning.json +551 -0
  149. package/src/rbac/legacy-policy.ts +16 -0
  150. package/src/rbac/permissions.ts +4 -0
  151. package/src/scheduler/schedule-task.ts +3 -0
  152. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  153. package/src/scripts-runtime/swarm-sdk.ts +9 -0
  154. package/src/scripts-runtime/types/stdlib.d.ts +1 -0
  155. package/src/scripts-runtime/types/swarm-extension.d.ts +1 -0
  156. package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -0
  157. package/src/server.ts +12 -7
  158. package/src/slack/app.ts +35 -4
  159. package/src/slack/connection-state.ts +17 -0
  160. package/src/tasks/context-key.ts +1 -0
  161. package/src/tasks/worker-follow-up.ts +6 -2
  162. package/src/tests/agent-task-activity.test.ts +74 -0
  163. package/src/tests/agents-list-model-display.test.ts +6 -1
  164. package/src/tests/approval-auto-cancellation-migration.test.ts +104 -0
  165. package/src/tests/approval-requests.test.ts +395 -0
  166. package/src/tests/approval-sweeps-config.test.ts +47 -0
  167. package/src/tests/approval-sweeps.test.ts +508 -0
  168. package/src/tests/apps-kibo-blocks.test.ts +77 -0
  169. package/src/tests/apps-spike.test.ts +56 -1
  170. package/src/tests/apps-sync-engine.test.ts +20 -9
  171. package/src/tests/boot-seeds.test.ts +170 -0
  172. package/src/tests/cancel-approval-request-tool.test.ts +115 -0
  173. package/src/tests/claude-managed-adapter.test.ts +6 -0
  174. package/src/tests/config-key-filter.test.ts +80 -0
  175. package/src/tests/context-window.test.ts +1 -0
  176. package/src/tests/db-client-busy-retry.test.ts +96 -0
  177. package/src/tests/db-client.test.ts +60 -1
  178. package/src/tests/db-task-read-contract.test.ts +10 -0
  179. package/src/tests/db-task-write-contract.test.ts +9 -0
  180. package/src/tests/docs-index-footprint.test.js +3 -3
  181. package/src/tests/events-http.test.ts +103 -0
  182. package/src/tests/extensions-catalog.test.ts +22 -17
  183. package/src/tests/extensions-pre-task.test.ts +107 -0
  184. package/src/tests/fixtures/kibo-blocks-definition.json.txt +105 -0
  185. package/src/tests/follow-up-config-inheritance.test.ts +260 -0
  186. package/src/tests/heartbeat-orphan-resume.test.ts +84 -0
  187. package/src/tests/heartbeat-reboot-live.test.ts +95 -0
  188. package/src/tests/heartbeat-stall-cas.test.ts +80 -0
  189. package/src/tests/heartbeat.test.ts +99 -3
  190. package/src/tests/hook-mcp-config.test.ts +29 -0
  191. package/src/tests/http-api-integration.test.ts +16 -2
  192. package/src/tests/kv-storage.test.ts +62 -0
  193. package/src/tests/linear-outbound-sync.test.ts +120 -5
  194. package/src/tests/list-endpoint-slimming.test.ts +91 -0
  195. package/src/tests/memory-graph-organic-route.test.ts +155 -0
  196. package/src/tests/memory-http-recall-gating.test.ts +14 -4
  197. package/src/tests/memory-hybrid.test.ts +161 -1
  198. package/src/tests/memory-prompt-recall-crowdout.test.ts +297 -0
  199. package/src/tests/memory.test.ts +22 -0
  200. package/src/tests/onboard-container-engine.test.ts +240 -0
  201. package/src/tests/otel-event-loop-and-logs.test.ts +99 -0
  202. package/src/tests/pricing-routes.test.ts +14 -0
  203. package/src/tests/profile-sync-warning.test.ts +8 -4
  204. package/src/tests/promote-draft-task-route.test.ts +19 -0
  205. package/src/tests/provider-registration.test.ts +296 -42
  206. package/src/tests/rbac-engine.test.ts +30 -0
  207. package/src/tests/reasoning-effort.test.ts +8 -0
  208. package/src/tests/script-connections.test.ts +7 -0
  209. package/src/tests/sdk-allowlist.test.ts +39 -0
  210. package/src/tests/session-costs-model-key-normalize.test.ts +1 -0
  211. package/src/tests/sessions-detail-batch.test.ts +250 -0
  212. package/src/tests/sessions.test.ts +118 -0
  213. package/src/tests/slack-config.test.ts +22 -0
  214. package/src/tests/sonnet-5-5-registry.test.ts +44 -0
  215. package/src/tests/status.test.ts +36 -1
  216. package/src/tests/swarm-diff.test.ts +316 -10
  217. package/src/tests/task-completion-idempotency.test.ts +2 -1
  218. package/src/tests/tasks-requested-by-filter.test.ts +3 -1
  219. package/src/tests/tool-annotations.test.ts +1 -1
  220. package/src/tests/ui-list-slim-projections.test.ts +158 -0
  221. package/src/tests/webhooks-task-blocked.test.ts +127 -0
  222. package/src/tests/workflow-approval-recovery.test.ts +203 -0
  223. package/src/tests/workflow-hitl-routing.test.ts +22 -1
  224. package/src/tests/workflow-hitl-slack-card.test.ts +52 -0
  225. package/src/tests/workflow-http-v2.test.ts +99 -8
  226. package/src/tests/workflow-retry-validation.test.ts +56 -0
  227. package/src/tests/workflow-tla-races.test.ts +389 -0
  228. package/src/tests/workflow-validation-port-routing.test.ts +113 -1
  229. package/src/tools/cancel-approval-request.ts +57 -0
  230. package/src/tools/memory-search.ts +1 -0
  231. package/src/tools/request-human-input.ts +4 -2
  232. package/src/tools/send-task.ts +4 -0
  233. package/src/tools/templates.ts +19 -0
  234. package/src/tools/tool-config.ts +2 -1
  235. package/src/tools/workflows/list-workflow-runs.ts +1 -0
  236. package/src/types.ts +38 -0
  237. package/src/utils/context-window.ts +1 -0
  238. package/src/workflows/approval-cancel.ts +152 -0
  239. package/src/workflows/approval-notifications.ts +84 -0
  240. package/src/workflows/checkpoint.ts +10 -5
  241. package/src/workflows/definition.ts +21 -0
  242. package/src/workflows/engine.ts +152 -21
  243. package/src/workflows/executors/human-in-the-loop.ts +1 -1
  244. package/src/workflows/recovery.ts +100 -45
  245. package/src/workflows/resume.ts +49 -18
  246. package/src/workflows/retry-poller.ts +71 -21
  247. package/templates/extensions/README.md +1 -0
  248. package/templates/extensions/github-sender-allowlist/README.md +18 -0
  249. package/templates/extensions/github-sender-allowlist/hooks.ts +55 -0
  250. package/templates/extensions/github-sender-allowlist/manifest.json +8 -0
  251. package/templates/skills/apps/content.md +20 -1
  252. package/templates/skills/code-quality/content.md +26 -1
  253. package/templates/skills/pages/content.md +16 -4
  254. package/templates/skills/pages/files/examples/multiplayer-board.html +3 -12
  255. package/dist/cli-2daksqps.js +0 -378
  256. package/dist/rbac-roles-3gxmnb20.js +0 -37
package/src/otel-impl.ts CHANGED
@@ -1,8 +1,12 @@
1
+ import { monitorEventLoopDelay } from "node:perf_hooks";
2
+ import { format } from "node:util";
1
3
  import {
4
+ type BatchObservableResult,
2
5
  type Counter,
3
6
  context,
4
7
  type Gauge,
5
8
  type Histogram,
9
+ type Meter,
6
10
  metrics,
7
11
  propagation,
8
12
  ROOT_CONTEXT,
@@ -12,6 +16,7 @@ import {
12
16
  type Tracer,
13
17
  trace,
14
18
  } from "@opentelemetry/api";
19
+ import { logs, SeverityNumber } from "@opentelemetry/api-logs";
15
20
  import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
16
21
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
17
22
  import {
@@ -149,7 +154,12 @@ export function resolveServiceName(serviceRole: string): string {
149
154
  return serviceRole === "api" ? `${baseServiceName}-api` : baseServiceName;
150
155
  }
151
156
 
152
- export async function boot(serviceRole: string): Promise<void> {
157
+ export interface BootOptions {
158
+ /** Mirror console output into OTel log records (API role only). */
159
+ exportConsoleLogs?: boolean;
160
+ }
161
+
162
+ export async function boot(serviceRole: string, options: BootOptions = {}): Promise<void> {
153
163
  if (sdk) return;
154
164
 
155
165
  const configuredResourceAttributes = parseResourceAttributes();
@@ -191,6 +201,14 @@ export async function boot(serviceRole: string): Promise<void> {
191
201
 
192
202
  sdk.start();
193
203
 
204
+ if (serviceRole === "api") {
205
+ startEventLoopDelayMetrics(metrics.getMeter(METER_NAME));
206
+ // NodeSDK already registers a global LoggerProvider exporting over OTLP
207
+ // to the same endpoint and resource as traces (OTEL_LOGS_EXPORTER
208
+ // defaults to otlp); nothing feeds it until the bridge is installed.
209
+ if (options.exportConsoleLogs) installConsoleLogBridge();
210
+ }
211
+
194
212
  const shutdown = async () => {
195
213
  try {
196
214
  await sdk?.shutdown();
@@ -204,8 +222,140 @@ export async function boot(serviceRole: string): Promise<void> {
204
222
  }
205
223
 
206
224
  export async function shutdown(): Promise<void> {
225
+ // SDK first: its final flush still reads the event-loop gauges and drains
226
+ // bridged log records.
207
227
  await sdk?.shutdown();
208
228
  sdk = undefined;
229
+ stopEventLoopDelayMetrics();
230
+ uninstallConsoleLogBridge();
231
+ }
232
+
233
+ let stopEventLoopDelay: (() => void) | undefined;
234
+
235
+ /**
236
+ * Event-loop delay from `perf_hooks.monitorEventLoopDelay`, exported as the
237
+ * semconv `nodejs.eventloop.delay.*` gauges (seconds). Each collection reads
238
+ * the histogram and resets it, so `max` is the worst stall since the last
239
+ * export. Server spans only start once the loop frees, so a stall never shows
240
+ * in span durations: a request queued behind a 3s synchronous query still
241
+ * reports a 14ms span. This metric is what sees the stall.
242
+ */
243
+ export function startEventLoopDelayMetrics(meter: Meter): void {
244
+ if (stopEventLoopDelay) return;
245
+ const histogram = monitorEventLoopDelay({ resolution: 10 });
246
+ histogram.enable();
247
+ const gauges = {
248
+ min: meter.createObservableGauge("nodejs.eventloop.delay.min", {
249
+ description: "Minimum event loop delay since the last export",
250
+ unit: "s",
251
+ }),
252
+ max: meter.createObservableGauge("nodejs.eventloop.delay.max", {
253
+ description: "Maximum event loop delay since the last export: the longest stall",
254
+ unit: "s",
255
+ }),
256
+ mean: meter.createObservableGauge("nodejs.eventloop.delay.mean", {
257
+ description: "Mean event loop delay since the last export",
258
+ unit: "s",
259
+ }),
260
+ p50: meter.createObservableGauge("nodejs.eventloop.delay.p50", {
261
+ description: "50th percentile event loop delay since the last export",
262
+ unit: "s",
263
+ }),
264
+ p90: meter.createObservableGauge("nodejs.eventloop.delay.p90", {
265
+ description: "90th percentile event loop delay since the last export",
266
+ unit: "s",
267
+ }),
268
+ p99: meter.createObservableGauge("nodejs.eventloop.delay.p99", {
269
+ description: "99th percentile event loop delay since the last export",
270
+ unit: "s",
271
+ }),
272
+ };
273
+ const seconds = (ns: number) => ns / 1e9;
274
+ const collect = (observer: BatchObservableResult) => {
275
+ // No sample yet (first interval shorter than the resolution): the
276
+ // histogram's min is a sentinel then, so report nothing.
277
+ if (histogram.count === 0) return;
278
+ observer.observe(gauges.min, seconds(histogram.min));
279
+ observer.observe(gauges.max, seconds(histogram.max));
280
+ observer.observe(gauges.mean, seconds(histogram.mean));
281
+ observer.observe(gauges.p50, seconds(histogram.percentile(50)));
282
+ observer.observe(gauges.p90, seconds(histogram.percentile(90)));
283
+ observer.observe(gauges.p99, seconds(histogram.percentile(99)));
284
+ histogram.reset();
285
+ };
286
+ const observables = Object.values(gauges);
287
+ meter.addBatchObservableCallback(collect, observables);
288
+ stopEventLoopDelay = () => {
289
+ meter.removeBatchObservableCallback(collect, observables);
290
+ histogram.disable();
291
+ stopEventLoopDelay = undefined;
292
+ };
293
+ }
294
+
295
+ export function stopEventLoopDelayMetrics(): void {
296
+ stopEventLoopDelay?.();
297
+ }
298
+
299
+ const CONSOLE_LOG_BODY_MAX_CHARS = 16_384;
300
+ const CONSOLE_SEVERITY = {
301
+ debug: { number: SeverityNumber.DEBUG, text: "DEBUG" },
302
+ log: { number: SeverityNumber.INFO, text: "INFO" },
303
+ info: { number: SeverityNumber.INFO, text: "INFO" },
304
+ warn: { number: SeverityNumber.WARN, text: "WARN" },
305
+ error: { number: SeverityNumber.ERROR, text: "ERROR" },
306
+ } as const;
307
+ type ConsoleMethod = keyof typeof CONSOLE_SEVERITY;
308
+
309
+ let restoreConsole: (() => void) | undefined;
310
+
311
+ /**
312
+ * Mirror console output into OTel log records (opt-in: OTEL_EXPORT_API_LOGS).
313
+ * stdout/stderr stay the primary sink; each line is also emitted to the
314
+ * global LoggerProvider, scrubbed at this egress point and correlated with
315
+ * the active span.
316
+ */
317
+ export function installConsoleLogBridge(): void {
318
+ if (restoreConsole) return;
319
+ const logger = logs.getLogger(METER_NAME);
320
+ const originals = new Map<ConsoleMethod, (...args: unknown[]) => void>();
321
+ let emitting = false;
322
+ for (const method of Object.keys(CONSOLE_SEVERITY) as ConsoleMethod[]) {
323
+ const original = console[method].bind(console);
324
+ originals.set(method, console[method]);
325
+ console[method] = (...args: unknown[]) => {
326
+ original(...args);
327
+ // An exporter or scrubber that logs must not recurse into itself.
328
+ if (emitting) return;
329
+ emitting = true;
330
+ try {
331
+ // Scrub before truncating so a cut can never split a secret into an
332
+ // unrecognizable fragment.
333
+ const text = scrubSecrets(format(...args));
334
+ const body =
335
+ text.length > CONSOLE_LOG_BODY_MAX_CHARS
336
+ ? `${text.slice(0, CONSOLE_LOG_BODY_MAX_CHARS)}…`
337
+ : text;
338
+ logger.emit({
339
+ severityNumber: CONSOLE_SEVERITY[method].number,
340
+ severityText: CONSOLE_SEVERITY[method].text,
341
+ body,
342
+ attributes: { "log.source": "console" },
343
+ });
344
+ } catch {
345
+ // Log export is best-effort; never break the caller's console call.
346
+ } finally {
347
+ emitting = false;
348
+ }
349
+ };
350
+ }
351
+ restoreConsole = () => {
352
+ for (const [method, original] of originals) console[method] = original;
353
+ restoreConsole = undefined;
354
+ };
355
+ }
356
+
357
+ export function uninstallConsoleLogBridge(): void {
358
+ restoreConsole?.();
209
359
  }
210
360
 
211
361
  export async function withSpan<T>(
package/src/otel.ts CHANGED
@@ -94,18 +94,29 @@ export function isOtelEnabled(): boolean {
94
94
  return otelConfigured();
95
95
  }
96
96
 
97
- export function isPollTracingEnabled(): boolean {
98
- const v = (process.env.OTEL_TRACE_POLL ?? "").trim().toLowerCase();
97
+ function envFlagEnabled(name: string): boolean {
98
+ const v = (process.env[name] ?? "").trim().toLowerCase();
99
99
  return v === "1" || v === "true" || v === "yes" || v === "on";
100
100
  }
101
101
 
102
+ export function isPollTracingEnabled(): boolean {
103
+ return envFlagEnabled("OTEL_TRACE_POLL");
104
+ }
105
+
106
+ /** Mirror the API's console output to the OTLP collector as log records. Off by default. */
107
+ export function isApiLogExportEnabled(): boolean {
108
+ return envFlagEnabled("OTEL_EXPORT_API_LOGS");
109
+ }
110
+
102
111
  export async function initOtel(serviceRole = process.env.AGENT_ROLE || "api"): Promise<void> {
103
112
  if (!otelConfigured() || initialized) return;
104
113
  initialized = true;
105
114
 
106
115
  try {
107
116
  const impl = await import("./otel-impl");
108
- await impl.boot(serviceRole);
117
+ await impl.boot(serviceRole, {
118
+ exportConsoleLogs: serviceRole === "api" && isApiLogExportEnabled(),
119
+ });
109
120
  realWithSpan = impl.withSpan;
110
121
  realStartSpan = impl.startSpan;
111
122
  realWithRemoteContext = impl.withRemoteContext;
@@ -18,9 +18,26 @@ export type RelevantMemory = {
18
18
  name: string;
19
19
  content: string;
20
20
  similarity: number;
21
+ rawSimilarity?: number;
21
22
  };
22
23
 
23
- export const SIMILARITY_THRESHOLD = 0.4;
24
+ /**
25
+ * Minimum pre-boost relevance for a memory to be injected into a task prompt.
26
+ *
27
+ * Compared against `rawSimilarity`, the [0,1] match score every retrieval arm
28
+ * emits before rerank (vec cosine, hybrid fused cosine, graph-derived), never
29
+ * against the composite `similarity`: the reranker's access, source-quality
30
+ * and usefulness multipliers can lift a score up to 4.5x, so a composite
31
+ * threshold admits unrelated rows. 0.55 sits between an unrelated query's best
32
+ * cosine (~0.33 on the production embedding model) and an exact-name hybrid
33
+ * hit (~0.65 fused).
34
+ */
35
+ export const SIMILARITY_THRESHOLD = 0.55;
36
+
37
+ /** The score the injection threshold applies to. Older servers omit `rawSimilarity`. */
38
+ export function memoryRelevance(memory: { similarity: number; rawSimilarity?: number }): number {
39
+ return memory.rawSimilarity ?? memory.similarity;
40
+ }
24
41
 
25
42
  const RATE_TOOL_HINT = `
26
43
 
@@ -35,7 +52,7 @@ This trains the swarm to surface better memories next time. Use sparingly:
35
52
  * append entirely (matching pre-step-5 behaviour).
36
53
  */
37
54
  export function renderMemoriesPrompt(memories: RelevantMemory[]): string | null {
38
- const useful = memories.filter((m) => m.similarity > SIMILARITY_THRESHOLD);
55
+ const useful = memories.filter((m) => memoryRelevance(m) > SIMILARITY_THRESHOLD);
39
56
  if (useful.length === 0) return null;
40
57
 
41
58
  const memoryContext = useful
@@ -31,6 +31,7 @@ export const CLAUDE_MANAGED_MODELS = [
31
31
  "claude-opus-5",
32
32
  "claude-fable-5",
33
33
  "claude-mythos-5",
34
+ "claude-sonnet-5-5",
34
35
  "claude-sonnet-5",
35
36
  "claude-sonnet-4-6",
36
37
  "claude-opus-4-8",
@@ -72,6 +73,7 @@ export interface ClaudeManagedModelPricing extends ClaudeManagedTokenPricing {
72
73
  * - claude-mythos-5: $10 / $50 / $1.00 / $12.50 (limited availability, verified 2026-06-10)
73
74
  * - claude-opus-5-5: $4 / $20 / $0.20 / $5.00 (verified 2026-09-22)
74
75
  * - claude-opus-5: $5 / $25 / $0.50 / $6.25 (verified 2026-07-25)
76
+ * - claude-sonnet-5-5: $2 / $10 / $0.20 / $2.50 (verified 2026-09-28)
75
77
  * - claude-sonnet-5: $2 / $10 / $0.20 / $2.50 (standard rate, verified 2026-08-29)
76
78
  * - claude-sonnet-4-6: $3 / $15 / $0.30 / $3.75 (in / out / cache-read / cache-write)
77
79
  * - claude-opus-4-8: $5 / $25 / $0.50 / $6.25 (verified 2026-05-28)
@@ -116,6 +118,12 @@ export const CLAUDE_MANAGED_MODEL_PRICING: Record<ClaudeManagedModel, ClaudeMana
116
118
  cacheReadPerMillion: 1.0,
117
119
  cacheWritePerMillion: 12.5,
118
120
  },
121
+ "claude-sonnet-5-5": {
122
+ inputPerMillion: 2.0,
123
+ outputPerMillion: 10.0,
124
+ cacheReadPerMillion: 0.2,
125
+ cacheWritePerMillion: 2.5,
126
+ },
119
127
  "claude-sonnet-5": {
120
128
  inputPerMillion: 2.0,
121
129
  outputPerMillion: 10.0,