@vellumai/assistant 0.3.5 → 0.3.7

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 (487) hide show
  1. package/README.md +51 -0
  2. package/eslint.config.mjs +31 -0
  3. package/package.json +1 -1
  4. package/scripts/ipc/check-swift-decoder-drift.ts +4 -1
  5. package/scripts/ipc/generate-swift.ts +18 -2
  6. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +338 -1
  7. package/src/__tests__/approval-conversation-turn.test.ts +214 -0
  8. package/src/__tests__/browser-manager.test.ts +1 -0
  9. package/src/__tests__/call-conversation-messages.test.ts +130 -0
  10. package/src/__tests__/call-orchestrator.test.ts +752 -271
  11. package/src/__tests__/call-pointer-messages.test.ts +148 -0
  12. package/src/__tests__/call-recovery.test.ts +3 -0
  13. package/src/__tests__/call-routes-http.test.ts +5 -0
  14. package/src/__tests__/call-store.test.ts +3 -0
  15. package/src/__tests__/channel-approval-routes.test.ts +1260 -85
  16. package/src/__tests__/channel-approval.test.ts +37 -0
  17. package/src/__tests__/channel-approvals.test.ts +4 -65
  18. package/src/__tests__/channel-guardian.test.ts +556 -0
  19. package/src/__tests__/channel-readiness-service.test.ts +74 -7
  20. package/src/__tests__/checker.test.ts +14 -7
  21. package/src/__tests__/clarification-resolver.test.ts +44 -24
  22. package/src/__tests__/commit-message-enrichment-service.test.ts +9 -4
  23. package/src/__tests__/computer-use-session-working-dir.test.ts +8 -0
  24. package/src/__tests__/config-schema.test.ts +12 -7
  25. package/src/__tests__/context-window-manager.test.ts +30 -2
  26. package/src/__tests__/contradiction-checker.test.ts +20 -5
  27. package/src/__tests__/credential-security-invariants.test.ts +6 -2
  28. package/src/__tests__/db-migration-rollback.test.ts +752 -0
  29. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -0
  30. package/src/__tests__/fuzzy-match-property.test.ts +5 -5
  31. package/src/__tests__/guardian-action-store.test.ts +123 -0
  32. package/src/__tests__/guardian-action-sweep.test.ts +277 -0
  33. package/src/__tests__/guardian-dispatch.test.ts +389 -0
  34. package/src/__tests__/guardian-question-copy.test.ts +47 -0
  35. package/src/__tests__/handlers-telegram-config.test.ts +4 -2
  36. package/src/__tests__/handlers-twilio-config.test.ts +126 -0
  37. package/src/__tests__/intent-routing.test.ts +2 -0
  38. package/src/__tests__/ipc-snapshot.test.ts +228 -1
  39. package/src/__tests__/memory-upsert-concurrency.test.ts +828 -0
  40. package/src/__tests__/model-intents.test.ts +96 -0
  41. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +42 -0
  42. package/src/__tests__/oauth2-gateway-transport.test.ts +130 -0
  43. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -0
  44. package/src/__tests__/provider-commit-message-generator.test.ts +89 -13
  45. package/src/__tests__/provider-error-scenarios.test.ts +621 -0
  46. package/src/__tests__/provider-fail-open-selection.test.ts +119 -0
  47. package/src/__tests__/qdrant-manager.test.ts +27 -20
  48. package/src/__tests__/relay-server.test.ts +779 -40
  49. package/src/__tests__/run-orchestrator-assistant-events.test.ts +2 -0
  50. package/src/__tests__/run-orchestrator.test.ts +20 -4
  51. package/src/__tests__/runtime-runs-http.test.ts +17 -1
  52. package/src/__tests__/runtime-runs.test.ts +16 -0
  53. package/src/__tests__/schedule-store.test.ts +18 -4
  54. package/src/__tests__/scheduler-recurrence.test.ts +13 -4
  55. package/src/__tests__/session-abort-tool-results.test.ts +6 -0
  56. package/src/__tests__/session-agent-loop.test.ts +857 -0
  57. package/src/__tests__/session-conflict-gate.test.ts +6 -0
  58. package/src/__tests__/session-pre-run-repair.test.ts +6 -0
  59. package/src/__tests__/session-profile-injection.test.ts +6 -0
  60. package/src/__tests__/session-provider-retry-repair.test.ts +6 -0
  61. package/src/__tests__/session-queue.test.ts +6 -0
  62. package/src/__tests__/session-runtime-assembly.test.ts +237 -13
  63. package/src/__tests__/session-slash-known.test.ts +6 -0
  64. package/src/__tests__/session-slash-queue.test.ts +6 -0
  65. package/src/__tests__/session-slash-unknown.test.ts +6 -0
  66. package/src/__tests__/session-surfaces-task-progress.test.ts +2 -0
  67. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -0
  68. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -0
  69. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -0
  70. package/src/__tests__/session-workspace-injection.test.ts +6 -0
  71. package/src/__tests__/session-workspace-tool-tracking.test.ts +6 -0
  72. package/src/__tests__/skills.test.ts +2 -0
  73. package/src/__tests__/sms-messaging-provider.test.ts +2 -1
  74. package/src/__tests__/starter-task-flow.test.ts +2 -0
  75. package/src/__tests__/swarm-dag-pathological.test.ts +535 -0
  76. package/src/__tests__/system-prompt.test.ts +2 -0
  77. package/src/__tests__/task-management-tools.test.ts +2 -2
  78. package/src/__tests__/task-runner.test.ts +14 -4
  79. package/src/__tests__/terminal-tools.test.ts +25 -19
  80. package/src/__tests__/tool-execution-abort-cleanup.test.ts +545 -0
  81. package/src/__tests__/tool-executor-shell-integration.test.ts +11 -11
  82. package/src/__tests__/tool-executor.test.ts +23 -24
  83. package/src/__tests__/trust-store.test.ts +3 -3
  84. package/src/__tests__/twilio-rest.test.ts +29 -0
  85. package/src/__tests__/twilio-routes-elevenlabs.test.ts +3 -0
  86. package/src/__tests__/twilio-routes-twiml.test.ts +11 -0
  87. package/src/__tests__/twilio-routes.test.ts +141 -21
  88. package/src/__tests__/user-reference.test.ts +2 -0
  89. package/src/__tests__/voice-quality.test.ts +222 -0
  90. package/src/__tests__/web-search.test.ts +45 -29
  91. package/src/agent/loop.ts +1 -1
  92. package/src/agent-heartbeat/agent-heartbeat-service.ts +2 -10
  93. package/src/amazon/client.ts +1418 -0
  94. package/src/amazon/request-extractor.ts +135 -0
  95. package/src/amazon/session.ts +109 -0
  96. package/src/autonomy/autonomy-store.ts +5 -5
  97. package/src/browser-extension-relay/client.ts +124 -0
  98. package/src/browser-extension-relay/protocol.ts +63 -0
  99. package/src/browser-extension-relay/server.ts +177 -0
  100. package/src/bundler/app-bundler.ts +3 -3
  101. package/src/bundler/bundle-signer.ts +1 -1
  102. package/src/bundler/signature-verifier.ts +1 -1
  103. package/src/calls/call-conversation-messages.ts +33 -0
  104. package/src/calls/call-domain.ts +106 -5
  105. package/src/calls/call-orchestrator.ts +252 -54
  106. package/src/calls/call-pointer-messages.ts +53 -0
  107. package/src/calls/call-recovery.ts +3 -8
  108. package/src/calls/call-store.ts +69 -87
  109. package/src/calls/elevenlabs-config.ts +3 -2
  110. package/src/calls/guardian-action-sweep.ts +105 -0
  111. package/src/calls/guardian-dispatch.ts +203 -0
  112. package/src/calls/guardian-question-copy.ts +133 -0
  113. package/src/calls/relay-server.ts +466 -8
  114. package/src/calls/speaker-identification.ts +1 -1
  115. package/src/calls/twilio-config.ts +7 -5
  116. package/src/calls/twilio-provider.ts +6 -4
  117. package/src/calls/twilio-rest.ts +40 -15
  118. package/src/calls/twilio-routes.ts +60 -45
  119. package/src/calls/types.ts +3 -1
  120. package/src/channels/types.ts +25 -0
  121. package/src/cli/amazon.ts +815 -0
  122. package/src/cli/config-commands.ts +2 -2
  123. package/src/cli/core-commands.ts +4 -3
  124. package/src/cli/influencer.ts +244 -0
  125. package/src/cli/map.ts +89 -6
  126. package/src/cli.ts +1 -1
  127. package/src/config/agent-schema.ts +171 -0
  128. package/src/config/bundled-skills/amazon/SKILL.md +127 -0
  129. package/src/config/bundled-skills/amazon/icon.svg +13 -0
  130. package/src/config/bundled-skills/api-mapping/SKILL.md +78 -0
  131. package/src/config/bundled-skills/browser/SKILL.md +1 -0
  132. package/src/config/bundled-skills/browser/TOOLS.json +17 -0
  133. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +25 -0
  134. package/src/config/bundled-skills/doordash/SKILL.md +51 -51
  135. package/src/config/bundled-skills/email-setup/SKILL.md +14 -5
  136. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +183 -0
  137. package/src/config/bundled-skills/influencer/SKILL.md +144 -0
  138. package/src/config/bundled-skills/macos-automation/icon.svg +12 -0
  139. package/src/config/bundled-skills/media-processing/SKILL.md +72 -95
  140. package/src/config/bundled-skills/media-processing/TOOLS.json +57 -147
  141. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +77 -0
  142. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +69 -0
  143. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +303 -0
  144. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +55 -0
  145. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +86 -0
  146. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +339 -0
  147. package/src/config/bundled-skills/media-processing/services/preprocess.ts +551 -0
  148. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +7 -9
  149. package/src/config/bundled-skills/media-processing/services/reduce.ts +197 -0
  150. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +88 -253
  151. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +22 -153
  152. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
  153. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +28 -51
  154. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +35 -270
  155. package/src/config/bundled-skills/messaging/SKILL.md +12 -2
  156. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -7
  157. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +2 -1
  158. package/src/config/bundled-skills/phone-calls/SKILL.md +86 -21
  159. package/src/config/bundled-skills/twitter/icon.svg +14 -0
  160. package/src/config/bundled-tool-registry.ts +310 -0
  161. package/src/config/calls-schema.ts +181 -0
  162. package/src/config/core-schema.ts +309 -0
  163. package/src/config/defaults.ts +27 -3
  164. package/src/config/env-registry.ts +169 -0
  165. package/src/config/env.ts +175 -0
  166. package/src/config/loader.ts +6 -6
  167. package/src/config/memory-schema.ts +528 -0
  168. package/src/config/sandbox-schema.ts +55 -0
  169. package/src/config/schema.ts +157 -1138
  170. package/src/config/skill-state.ts +1 -1
  171. package/src/config/skills-schema.ts +32 -0
  172. package/src/config/skills.ts +35 -24
  173. package/src/config/system-prompt.ts +107 -56
  174. package/src/config/templates/SOUL.md +1 -1
  175. package/src/config/types.ts +1 -0
  176. package/src/config/user-reference.ts +4 -9
  177. package/src/config/vellum-skills/catalog.json +0 -7
  178. package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +5 -1
  179. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +1 -0
  180. package/src/config/vellum-skills/sms-setup/SKILL.md +112 -14
  181. package/src/context/window-manager.ts +27 -7
  182. package/src/daemon/approval-generators.ts +186 -0
  183. package/src/daemon/approved-devices-store.ts +140 -0
  184. package/src/daemon/assistant-attachments.ts +1 -1
  185. package/src/daemon/classifier.ts +35 -32
  186. package/src/daemon/config-watcher.ts +1 -1
  187. package/src/daemon/daemon-control.ts +254 -0
  188. package/src/daemon/handlers/apps.ts +2 -3
  189. package/src/daemon/handlers/config-channels.ts +158 -0
  190. package/src/daemon/handlers/config-inbox.ts +540 -0
  191. package/src/daemon/handlers/config-ingress.ts +231 -0
  192. package/src/daemon/handlers/config-integrations.ts +258 -0
  193. package/src/daemon/handlers/config-model.ts +143 -0
  194. package/src/daemon/handlers/config-parental.ts +163 -0
  195. package/src/daemon/handlers/config-scheduling.ts +172 -0
  196. package/src/daemon/handlers/config-slack.ts +92 -0
  197. package/src/daemon/handlers/config-telegram.ts +301 -0
  198. package/src/daemon/handlers/config-tools.ts +177 -0
  199. package/src/daemon/handlers/config-trust.ts +104 -0
  200. package/src/daemon/handlers/config-twilio.ts +1080 -0
  201. package/src/daemon/handlers/config.ts +53 -2463
  202. package/src/daemon/handlers/diagnostics.ts +1 -1
  203. package/src/daemon/handlers/dictation.ts +4 -6
  204. package/src/daemon/handlers/documents.ts +18 -32
  205. package/src/daemon/handlers/index.ts +9 -0
  206. package/src/daemon/handlers/misc.ts +3 -5
  207. package/src/daemon/handlers/pairing.ts +98 -0
  208. package/src/daemon/handlers/sessions.ts +74 -5
  209. package/src/daemon/handlers/shared.ts +3 -1
  210. package/src/daemon/handlers/skills.ts +1 -1
  211. package/src/daemon/handlers/twitter-auth.ts +2 -0
  212. package/src/daemon/handlers/work-items.ts +2 -2
  213. package/src/daemon/handlers/workspace-files.ts +4 -3
  214. package/src/daemon/install-cli-launchers.ts +113 -0
  215. package/src/daemon/ipc-contract/apps.ts +356 -0
  216. package/src/daemon/ipc-contract/browser.ts +74 -0
  217. package/src/daemon/ipc-contract/computer-use.ts +151 -0
  218. package/src/daemon/ipc-contract/diagnostics.ts +56 -0
  219. package/src/daemon/ipc-contract/documents.ts +74 -0
  220. package/src/daemon/ipc-contract/inbox.ts +209 -0
  221. package/src/daemon/ipc-contract/integrations.ts +284 -0
  222. package/src/daemon/ipc-contract/memory.ts +48 -0
  223. package/src/daemon/ipc-contract/messages.ts +211 -0
  224. package/src/daemon/ipc-contract/pairing.ts +45 -0
  225. package/src/daemon/ipc-contract/parental-control.ts +95 -0
  226. package/src/daemon/ipc-contract/schedules.ts +97 -0
  227. package/src/daemon/ipc-contract/sessions.ts +321 -0
  228. package/src/daemon/ipc-contract/shared.ts +42 -0
  229. package/src/daemon/ipc-contract/skills.ts +120 -0
  230. package/src/daemon/ipc-contract/subagents.ts +58 -0
  231. package/src/daemon/ipc-contract/surfaces.ts +250 -0
  232. package/src/daemon/ipc-contract/trust.ts +60 -0
  233. package/src/daemon/ipc-contract/work-items.ts +225 -0
  234. package/src/daemon/ipc-contract/workspace.ts +113 -0
  235. package/src/daemon/ipc-contract-inventory.json +62 -0
  236. package/src/daemon/ipc-contract-inventory.ts +55 -29
  237. package/src/daemon/ipc-contract.ts +227 -2527
  238. package/src/daemon/ipc-protocol.ts +1 -1
  239. package/src/daemon/ipc-validate.ts +7 -0
  240. package/src/daemon/lifecycle.ts +97 -379
  241. package/src/daemon/pairing-store.ts +177 -0
  242. package/src/daemon/providers-setup.ts +43 -0
  243. package/src/daemon/ride-shotgun-handler.ts +67 -2
  244. package/src/daemon/server.ts +60 -44
  245. package/src/daemon/session-agent-loop-handlers.ts +421 -0
  246. package/src/daemon/session-agent-loop.ts +113 -275
  247. package/src/daemon/session-dynamic-profile.ts +1 -1
  248. package/src/daemon/session-history.ts +1 -1
  249. package/src/daemon/session-media-retry.ts +1 -1
  250. package/src/daemon/session-messaging.ts +37 -2
  251. package/src/daemon/session-notifiers.ts +5 -25
  252. package/src/daemon/session-process.ts +99 -59
  253. package/src/daemon/session-queue-manager.ts +98 -4
  254. package/src/daemon/session-runtime-assembly.ts +149 -15
  255. package/src/daemon/session-surfaces.ts +26 -4
  256. package/src/daemon/session-tool-setup.ts +28 -30
  257. package/src/daemon/session-workspace.ts +1 -1
  258. package/src/daemon/session.ts +24 -1
  259. package/src/daemon/shutdown-handlers.ts +122 -0
  260. package/src/daemon/trace-emitter.ts +1 -1
  261. package/src/daemon/watch-handler.ts +36 -33
  262. package/src/doordash/cart-queries.ts +787 -0
  263. package/src/doordash/client.ts +144 -127
  264. package/src/doordash/order-queries.ts +85 -0
  265. package/src/doordash/queries.ts +10 -1308
  266. package/src/doordash/search-queries.ts +203 -0
  267. package/src/doordash/session.ts +3 -2
  268. package/src/doordash/store-queries.ts +246 -0
  269. package/src/doordash/types.ts +367 -0
  270. package/src/email/providers/agentmail.ts +2 -1
  271. package/src/email/providers/index.ts +3 -2
  272. package/src/email/service.ts +3 -2
  273. package/src/errors.ts +43 -0
  274. package/src/home-base/prebuilt/seed.ts +1 -1
  275. package/src/hooks/cli.ts +6 -5
  276. package/src/hooks/config.ts +6 -8
  277. package/src/hooks/discovery.ts +6 -5
  278. package/src/hooks/manager.ts +4 -3
  279. package/src/hooks/runner.ts +2 -2
  280. package/src/hooks/templates.ts +5 -5
  281. package/src/inbound/public-ingress-urls.ts +3 -1
  282. package/src/index.ts +4 -2
  283. package/src/influencer/client.ts +1104 -0
  284. package/src/instrument.ts +4 -3
  285. package/src/logfire.ts +4 -3
  286. package/src/memory/admin.ts +25 -35
  287. package/src/memory/attachments-store.ts +4 -7
  288. package/src/memory/channel-delivery-store.ts +30 -1
  289. package/src/memory/channel-guardian-store.ts +200 -1
  290. package/src/memory/clarification-resolver.ts +37 -33
  291. package/src/memory/conflict-store.ts +67 -61
  292. package/src/memory/contradiction-checker.ts +141 -117
  293. package/src/memory/conversation-store.ts +335 -51
  294. package/src/memory/db-connection.ts +27 -4
  295. package/src/memory/db-init.ts +121 -4
  296. package/src/memory/db.ts +14 -1
  297. package/src/memory/embedding-backend.ts +27 -5
  298. package/src/memory/embedding-ollama.ts +2 -1
  299. package/src/memory/entity-extractor.ts +38 -35
  300. package/src/memory/guardian-action-store.ts +430 -0
  301. package/src/memory/inbox-escalation-projection.ts +59 -0
  302. package/src/memory/inbox-thread-store.ts +218 -0
  303. package/src/memory/ingress-invite-store.ts +338 -0
  304. package/src/memory/ingress-member-store.ts +350 -0
  305. package/src/memory/items-extractor.ts +91 -97
  306. package/src/memory/job-handlers/index-maintenance.ts +3 -3
  307. package/src/memory/job-handlers/media-processing.ts +11 -42
  308. package/src/memory/job-handlers/summarization.ts +32 -26
  309. package/src/memory/job-utils.ts +3 -10
  310. package/src/memory/jobs-store.ts +6 -9
  311. package/src/memory/jobs-worker.ts +51 -36
  312. package/src/memory/migrations/001-job-deferrals.ts +45 -0
  313. package/src/memory/migrations/002-tool-invocations-fk.ts +43 -0
  314. package/src/memory/migrations/003-memory-fts-backfill.ts +24 -0
  315. package/src/memory/migrations/004-entity-relation-dedup.ts +87 -0
  316. package/src/memory/migrations/005-fingerprint-scope-unique.ts +80 -0
  317. package/src/memory/migrations/006-scope-salted-fingerprints.ts +62 -0
  318. package/src/memory/migrations/007-assistant-id-to-self.ts +254 -0
  319. package/src/memory/migrations/008-remove-assistant-id-columns.ts +208 -0
  320. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +83 -0
  321. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +56 -0
  322. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +63 -0
  323. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +19 -0
  324. package/src/memory/migrations/013-guardian-action-tables.ts +68 -0
  325. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +76 -0
  326. package/src/memory/migrations/015-drop-active-search-index.ts +27 -0
  327. package/src/memory/migrations/016-memory-segments-indexes.ts +11 -0
  328. package/src/memory/migrations/017-memory-items-indexes.ts +12 -0
  329. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -0
  330. package/src/memory/migrations/index.ts +24 -0
  331. package/src/memory/migrations/registry.ts +79 -0
  332. package/src/memory/migrations/validate-migration-state.ts +69 -0
  333. package/src/memory/qdrant-manager.ts +49 -8
  334. package/src/memory/query-builder.ts +1 -1
  335. package/src/memory/raw-query.ts +119 -0
  336. package/src/memory/recall-cache.ts +4 -1
  337. package/src/memory/retriever.ts +163 -47
  338. package/src/memory/schema-migration.ts +25 -984
  339. package/src/memory/schema.ts +130 -7
  340. package/src/memory/search/entity.ts +10 -19
  341. package/src/memory/search/lexical.ts +81 -52
  342. package/src/memory/search/ranking.ts +21 -22
  343. package/src/memory/search/semantic.ts +157 -19
  344. package/src/memory/shared-app-links-store.ts +4 -5
  345. package/src/memory/validation.ts +19 -0
  346. package/src/messaging/draft-store.ts +5 -6
  347. package/src/messaging/providers/sms/adapter.ts +3 -6
  348. package/src/messaging/providers/telegram-bot/adapter.ts +2 -5
  349. package/src/messaging/providers/whatsapp/adapter.ts +136 -0
  350. package/src/messaging/providers/whatsapp/client.ts +67 -0
  351. package/src/messaging/style-analyzer.ts +5 -4
  352. package/src/messaging/thread-summarizer.ts +61 -69
  353. package/src/messaging/triage-engine.ts +62 -71
  354. package/src/migrations/config-merge.ts +53 -0
  355. package/src/migrations/data-layout.ts +68 -0
  356. package/src/migrations/data-merge.ts +33 -0
  357. package/src/migrations/hooks-merge.ts +90 -0
  358. package/src/migrations/index.ts +6 -0
  359. package/src/migrations/log.ts +23 -0
  360. package/src/migrations/skills-merge.ts +33 -0
  361. package/src/migrations/workspace-layout.ts +79 -0
  362. package/src/permissions/checker.ts +126 -11
  363. package/src/permissions/prompter.ts +14 -0
  364. package/src/permissions/shell-identity.ts +31 -1
  365. package/src/permissions/trust-store.ts +21 -1
  366. package/src/providers/anthropic/client.ts +4 -4
  367. package/src/providers/failover.ts +2 -2
  368. package/src/providers/model-intents.ts +70 -0
  369. package/src/providers/ollama/client.ts +2 -1
  370. package/src/providers/provider-send-message.ts +176 -0
  371. package/src/providers/registry.ts +71 -30
  372. package/src/providers/retry.ts +35 -1
  373. package/src/providers/types.ts +12 -1
  374. package/src/runtime/approval-conversation-turn.ts +97 -0
  375. package/src/runtime/approval-message-composer.ts +115 -5
  376. package/src/runtime/assistant-event-hub.ts +3 -1
  377. package/src/runtime/channel-approval-parser.ts +36 -2
  378. package/src/runtime/channel-approvals.ts +0 -21
  379. package/src/runtime/channel-guardian-service.ts +48 -7
  380. package/src/runtime/channel-readiness-service.ts +160 -34
  381. package/src/runtime/channel-readiness-types.ts +10 -4
  382. package/src/runtime/channel-retry-sweep.ts +184 -0
  383. package/src/runtime/guardian-context-resolver.ts +108 -0
  384. package/src/runtime/http-server.ts +289 -745
  385. package/src/runtime/http-types.ts +56 -3
  386. package/src/runtime/middleware/auth.ts +116 -0
  387. package/src/runtime/middleware/error-handler.ts +33 -0
  388. package/src/runtime/middleware/twilio-validation.ts +127 -0
  389. package/src/runtime/routes/app-routes.ts +1 -1
  390. package/src/runtime/routes/call-routes.ts +49 -6
  391. package/src/runtime/routes/channel-delivery-routes.ts +170 -0
  392. package/src/runtime/routes/channel-guardian-routes.ts +1191 -0
  393. package/src/runtime/routes/channel-inbound-routes.ts +1152 -0
  394. package/src/runtime/routes/channel-route-shared.ts +144 -0
  395. package/src/runtime/routes/channel-routes.ts +32 -1634
  396. package/src/runtime/routes/conversation-routes.ts +50 -7
  397. package/src/runtime/routes/events-routes.ts +2 -2
  398. package/src/runtime/routes/identity-routes.ts +126 -0
  399. package/src/runtime/routes/pairing-routes.ts +144 -0
  400. package/src/runtime/routes/run-routes.ts +15 -1
  401. package/src/runtime/run-orchestrator.ts +52 -34
  402. package/src/schedule/schedule-store.ts +36 -32
  403. package/src/schedule/scheduler.ts +3 -3
  404. package/src/security/encrypted-store.ts +5 -7
  405. package/src/security/oauth2.ts +45 -15
  406. package/src/security/parental-control-store.ts +183 -0
  407. package/src/security/secret-allowlist.ts +4 -3
  408. package/src/security/secret-scanner.ts +5 -5
  409. package/src/security/secure-keys.ts +1 -1
  410. package/src/security/token-manager.ts +3 -2
  411. package/src/services/vercel-deploy.ts +6 -2
  412. package/src/skills/tool-manifest.ts +3 -3
  413. package/src/skills/vellum-catalog-remote.ts +75 -16
  414. package/src/slack/slack-webhook.ts +2 -1
  415. package/src/swarm/orchestrator.ts +92 -1
  416. package/src/swarm/router-planner.ts +6 -9
  417. package/src/swarm/worker-prompts.ts +9 -12
  418. package/src/tasks/task-compiler.ts +19 -28
  419. package/src/tasks/task-runner.ts +1 -1
  420. package/src/tools/assets/search.ts +15 -14
  421. package/src/tools/browser/__tests__/auth-detector.test.ts +1 -0
  422. package/src/tools/browser/auto-navigate.ts +1 -0
  423. package/src/tools/browser/browser-execution.ts +13 -1
  424. package/src/tools/browser/browser-manager.ts +119 -4
  425. package/src/tools/browser/network-recorder.ts +5 -0
  426. package/src/tools/credentials/broker.ts +11 -2
  427. package/src/tools/credentials/metadata-store.ts +18 -14
  428. package/src/tools/credentials/post-connect-hooks.ts +61 -0
  429. package/src/tools/credentials/vault.ts +49 -23
  430. package/src/tools/executor.ts +80 -18
  431. package/src/tools/host-terminal/cli-discover.ts +1 -1
  432. package/src/tools/network/script-proxy/http-forwarder.ts +1 -1
  433. package/src/tools/network/script-proxy/mitm-handler.ts +1 -1
  434. package/src/tools/network/script-proxy/server.ts +1 -1
  435. package/src/tools/network/script-proxy/session-manager.ts +6 -5
  436. package/src/tools/network/web-fetch.ts +18 -2
  437. package/src/tools/network/web-search.ts +7 -3
  438. package/src/tools/reminder/reminder-store.ts +14 -15
  439. package/src/tools/schedule/create.ts +1 -0
  440. package/src/tools/schedule/list.ts +2 -1
  441. package/src/tools/shared/filesystem/file-ops-service.ts +5 -7
  442. package/src/tools/skills/skill-script-runner.ts +24 -9
  443. package/src/tools/skills/skill-tool-factory.ts +1 -0
  444. package/src/tools/tasks/work-item-enqueue.ts +2 -2
  445. package/src/tools/terminal/evaluate-typescript.ts +21 -12
  446. package/src/tools/terminal/parser.ts +50 -0
  447. package/src/tools/watcher/delete.ts +6 -0
  448. package/src/tools/weather/service.ts +1 -1
  449. package/src/twitter/client.ts +190 -24
  450. package/src/twitter/session.ts +4 -3
  451. package/src/util/clipboard.ts +1 -1
  452. package/src/util/errors.ts +65 -8
  453. package/src/util/fs.ts +40 -0
  454. package/src/util/json.ts +10 -0
  455. package/src/util/log-redact.ts +189 -0
  456. package/src/util/logger.ts +25 -18
  457. package/src/util/object.ts +3 -0
  458. package/src/util/platform.ts +72 -365
  459. package/src/util/pricing.ts +1 -1
  460. package/src/util/promise-guard.ts +1 -1
  461. package/src/util/retry.ts +19 -0
  462. package/src/util/row-mapper.ts +79 -0
  463. package/src/util/silently.ts +21 -0
  464. package/src/watcher/engine.ts +5 -1
  465. package/src/watcher/provider-types.ts +20 -0
  466. package/src/watcher/providers/github.ts +156 -0
  467. package/src/watcher/providers/gmail.ts +1 -0
  468. package/src/watcher/providers/google-calendar.ts +1 -0
  469. package/src/watcher/providers/linear.ts +460 -0
  470. package/src/watcher/providers/slack.ts +1 -0
  471. package/src/work-items/work-item-runner.ts +1 -1
  472. package/src/workspace/git-service.ts +1 -1
  473. package/src/workspace/provider-commit-message-generator.ts +51 -22
  474. package/src/__tests__/call-bridge.test.ts +0 -517
  475. package/src/__tests__/session-process-bridge.test.ts +0 -244
  476. package/src/calls/call-bridge.ts +0 -168
  477. package/src/config/bundled-skills/media-processing/services/capability-registry.ts +0 -137
  478. package/src/config/bundled-skills/media-processing/services/event-detection-service.ts +0 -280
  479. package/src/config/bundled-skills/media-processing/services/feedback-aggregation.ts +0 -144
  480. package/src/config/bundled-skills/media-processing/services/feedback-store.ts +0 -136
  481. package/src/config/bundled-skills/media-processing/services/retrieval-service.ts +0 -95
  482. package/src/config/bundled-skills/media-processing/services/timeline-service.ts +0 -267
  483. package/src/config/bundled-skills/media-processing/tools/detect-events.ts +0 -110
  484. package/src/config/bundled-skills/media-processing/tools/recalibrate.ts +0 -235
  485. package/src/config/bundled-skills/media-processing/tools/select-tracking-profile.ts +0 -142
  486. package/src/config/bundled-skills/media-processing/tools/submit-feedback.ts +0 -150
  487. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
@@ -1,280 +0,0 @@
1
- /**
2
- * Generic event detection service.
3
- *
4
- * Evaluates configurable detection rules against timeline segments and produces
5
- * scored event candidates. The rule system is fully pluggable — callers supply
6
- * a DetectionConfig that specifies which rules to evaluate and how to weight them.
7
- *
8
- * Example configurations (not hardcoded — these are passed in by the caller):
9
- *
10
- * Basketball turnovers:
11
- * eventType: 'turnover'
12
- * rules: [
13
- * { ruleType: 'segment_transition', params: { field: 'subjects' }, weight: 0.5 },
14
- * { ruleType: 'short_segment', params: { maxDurationSeconds: 5 }, weight: 0.3 },
15
- * { ruleType: 'attribute_match', params: { field: 'actions', pattern: 'steal|turnover' }, weight: 0.2 },
16
- * ]
17
- *
18
- * Scene changes:
19
- * eventType: 'scene_change'
20
- * rules: [
21
- * { ruleType: 'segment_transition', params: { field: 'segmentType' }, weight: 1.0 },
22
- * ]
23
- */
24
-
25
- import {
26
- getMediaAssetById,
27
- getTimelineForAsset,
28
- insertEventsBatch,
29
- deleteEventsForAssetByType,
30
- type MediaTimeline,
31
- type MediaEvent,
32
- } from '../../../../memory/media-store.js';
33
-
34
- // ---------------------------------------------------------------------------
35
- // Public types
36
- // ---------------------------------------------------------------------------
37
-
38
- export interface DetectionRule {
39
- ruleType: string;
40
- params: Record<string, unknown>;
41
- weight: number;
42
- }
43
-
44
- export interface DetectionConfig {
45
- eventType: string;
46
- rules: DetectionRule[];
47
- }
48
-
49
- export interface EventCandidate {
50
- startTime: number;
51
- endTime: number;
52
- confidence: number;
53
- reasons: string[];
54
- metadata: Record<string, unknown>;
55
- }
56
-
57
- export interface DetectionResult {
58
- assetId: string;
59
- eventType: string;
60
- candidateCount: number;
61
- events: MediaEvent[];
62
- }
63
-
64
- // ---------------------------------------------------------------------------
65
- // Rule evaluation
66
- // ---------------------------------------------------------------------------
67
-
68
- interface RuleMatch {
69
- matched: boolean;
70
- reason: string;
71
- metadata?: Record<string, unknown>;
72
- }
73
-
74
- type RuleEvaluator = (
75
- segment: MediaTimeline,
76
- prevSegment: MediaTimeline | null,
77
- nextSegment: MediaTimeline | null,
78
- params: Record<string, unknown>,
79
- ) => RuleMatch;
80
-
81
- const RULE_EVALUATORS: Record<string, RuleEvaluator> = {
82
- /**
83
- * Fires when a specified field changes between adjacent segments.
84
- * params.field: which attribute to compare ('subjects', 'segmentType', etc.)
85
- */
86
- segment_transition: (segment, prevSegment, _next, params) => {
87
- if (!prevSegment) return { matched: false, reason: '' };
88
- const field = (params.field as string) ?? 'segmentType';
89
-
90
- if (field === 'segmentType') {
91
- const changed = segment.segmentType !== prevSegment.segmentType;
92
- return {
93
- matched: changed,
94
- reason: changed
95
- ? `Segment type changed from "${prevSegment.segmentType}" to "${segment.segmentType}"`
96
- : '',
97
- };
98
- }
99
-
100
- // Compare attribute arrays (e.g., subjects)
101
- const prevAttrs = prevSegment.attributes ?? {};
102
- const currAttrs = segment.attributes ?? {};
103
- const prevValues = new Set(Array.isArray(prevAttrs[field]) ? (prevAttrs[field] as string[]) : []);
104
- const currValues = Array.isArray(currAttrs[field]) ? (currAttrs[field] as string[]) : [];
105
-
106
- if (prevValues.size === 0 && currValues.length === 0) {
107
- return { matched: false, reason: '' };
108
- }
109
-
110
- const overlap = currValues.filter((v) => prevValues.has(v)).length;
111
- const unionSize = new Set([...prevValues, ...currValues]).size;
112
- const similarity = unionSize > 0 ? overlap / unionSize : 0;
113
-
114
- // A transition is detected when similarity drops below 50%
115
- const changed = similarity < 0.5;
116
- return {
117
- matched: changed,
118
- reason: changed
119
- ? `${field} changed between segments (similarity: ${(similarity * 100).toFixed(0)}%)`
120
- : '',
121
- metadata: changed ? { similarity, prevValues: [...prevValues], currValues } : undefined,
122
- };
123
- },
124
-
125
- /**
126
- * Fires when a segment's duration is below a threshold.
127
- * params.maxDurationSeconds: maximum segment duration to trigger (default: 5)
128
- */
129
- short_segment: (segment, _prev, _next, params) => {
130
- const maxDuration = (params.maxDurationSeconds as number) ?? 5;
131
- const duration = segment.endTime - segment.startTime;
132
- const matched = duration > 0 && duration <= maxDuration;
133
- return {
134
- matched,
135
- reason: matched
136
- ? `Short segment (${duration.toFixed(1)}s <= ${maxDuration}s threshold)`
137
- : '',
138
- metadata: matched ? { duration } : undefined,
139
- };
140
- },
141
-
142
- /**
143
- * Fires when a segment's attribute values match a regex pattern.
144
- * params.field: which attribute array to search (default: 'actions')
145
- * params.pattern: regex pattern to match against values
146
- */
147
- attribute_match: (segment, _prev, _next, params) => {
148
- const field = (params.field as string) ?? 'actions';
149
- const pattern = params.pattern as string;
150
- if (!pattern) return { matched: false, reason: 'No pattern specified' };
151
-
152
- const attrs = segment.attributes ?? {};
153
- const values = Array.isArray(attrs[field]) ? (attrs[field] as string[]) : [];
154
- const regex = new RegExp(pattern, 'i');
155
- const matchedValues = values.filter((v) => regex.test(v));
156
-
157
- return {
158
- matched: matchedValues.length > 0,
159
- reason: matchedValues.length > 0
160
- ? `${field} matched pattern /${pattern}/: [${matchedValues.join(', ')}]`
161
- : '',
162
- metadata: matchedValues.length > 0 ? { matchedValues } : undefined,
163
- };
164
- },
165
- };
166
-
167
- // ---------------------------------------------------------------------------
168
- // Main detection logic
169
- // ---------------------------------------------------------------------------
170
-
171
- /**
172
- * Detect events in a media asset's timeline using the provided configuration.
173
- *
174
- * For each timeline segment, evaluates all rules and computes a weighted
175
- * confidence score. Segments where at least one rule matches are emitted
176
- * as event candidates. Results are stored in the media_events table (previous
177
- * events of the same type for this asset are replaced).
178
- */
179
- export function detectEvents(
180
- assetId: string,
181
- config: DetectionConfig,
182
- options?: { onProgress?: (message: string) => void },
183
- ): DetectionResult {
184
- const onProgress = options?.onProgress;
185
-
186
- const asset = getMediaAssetById(assetId);
187
- if (!asset) {
188
- throw new Error(`Media asset not found: ${assetId}`);
189
- }
190
-
191
- const segments = getTimelineForAsset(assetId);
192
- if (segments.length === 0) {
193
- throw new Error('No timeline segments found. Run timeline generation first.');
194
- }
195
-
196
- // Sort segments by start time
197
- const sorted = [...segments].sort((a, b) => a.startTime - b.startTime);
198
-
199
- onProgress?.(`Evaluating ${config.rules.length} detection rules against ${sorted.length} segments...`);
200
-
201
- // Normalize weights so they sum to 1
202
- const totalWeight = config.rules.reduce((sum, r) => sum + r.weight, 0);
203
- const normalizedRules = totalWeight > 0
204
- ? config.rules.map((r) => ({ ...r, weight: r.weight / totalWeight }))
205
- : config.rules;
206
-
207
- const candidates: EventCandidate[] = [];
208
-
209
- for (let i = 0; i < sorted.length; i++) {
210
- const segment = sorted[i];
211
- const prev = i > 0 ? sorted[i - 1] : null;
212
- const next = i < sorted.length - 1 ? sorted[i + 1] : null;
213
-
214
- let weightedScore = 0;
215
- const reasons: string[] = [];
216
- const candidateMetadata: Record<string, unknown> = {};
217
- let anyMatched = false;
218
-
219
- for (const rule of normalizedRules) {
220
- const evaluator = RULE_EVALUATORS[rule.ruleType];
221
- if (!evaluator) {
222
- reasons.push(`Unknown rule type: ${rule.ruleType}`);
223
- continue;
224
- }
225
-
226
- const result = evaluator(segment, prev, next, rule.params);
227
- if (result.matched) {
228
- anyMatched = true;
229
- weightedScore += rule.weight;
230
- reasons.push(result.reason);
231
- if (result.metadata) {
232
- candidateMetadata[rule.ruleType] = result.metadata;
233
- }
234
- }
235
- }
236
-
237
- if (anyMatched) {
238
- candidates.push({
239
- startTime: segment.startTime,
240
- endTime: segment.endTime,
241
- confidence: Math.min(weightedScore, 1),
242
- reasons,
243
- metadata: {
244
- segmentId: segment.id,
245
- segmentType: segment.segmentType,
246
- ...candidateMetadata,
247
- },
248
- });
249
- }
250
- }
251
-
252
- // Sort by confidence descending
253
- candidates.sort((a, b) => b.confidence - a.confidence);
254
-
255
- onProgress?.(`Found ${candidates.length} event candidates. Storing results...`);
256
-
257
- // Replace existing events of this type for the asset (scoped to eventType)
258
- deleteEventsForAssetByType(assetId, config.eventType);
259
-
260
- const eventRows = candidates.map((c) => ({
261
- assetId,
262
- eventType: config.eventType,
263
- startTime: c.startTime,
264
- endTime: c.endTime,
265
- confidence: c.confidence,
266
- reasons: c.reasons,
267
- metadata: c.metadata,
268
- }));
269
-
270
- const events = eventRows.length > 0 ? insertEventsBatch(eventRows) : [];
271
-
272
- onProgress?.(`Stored ${events.length} events.`);
273
-
274
- return {
275
- assetId,
276
- eventType: config.eventType,
277
- candidateCount: candidates.length,
278
- events,
279
- };
280
- }
@@ -1,144 +0,0 @@
1
- /**
2
- * Feedback aggregation service for media events.
3
- *
4
- * Computes precision/recall estimates per event type based on user feedback,
5
- * and provides structured JSON export for offline analysis.
6
- *
7
- * All interfaces are generic — works for any event type.
8
- */
9
-
10
- import { getFeedbackForAsset, type EventFeedback } from './feedback-store.js';
11
- import { getEventsForAsset } from '../../../../memory/media-store.js';
12
-
13
- // ---------------------------------------------------------------------------
14
- // Types
15
- // ---------------------------------------------------------------------------
16
-
17
- export interface EventTypeStats {
18
- eventType: string;
19
- totalEvents: number;
20
- correct: number;
21
- incorrect: number;
22
- boundaryEdit: number;
23
- missed: number;
24
- totalFeedback: number;
25
- precision: number | null;
26
- recall: number | null;
27
- }
28
-
29
- export interface AggregationResult {
30
- assetId: string;
31
- totalFeedbackEntries: number;
32
- statsByEventType: EventTypeStats[];
33
- }
34
-
35
- export interface FeedbackExport {
36
- assetId: string;
37
- exportedAt: string;
38
- totalEntries: number;
39
- feedback: EventFeedback[];
40
- }
41
-
42
- // ---------------------------------------------------------------------------
43
- // Aggregation
44
- // ---------------------------------------------------------------------------
45
-
46
- /**
47
- * Compute precision/recall estimates per event type for a given asset.
48
- *
49
- * precision = correct / (correct + incorrect)
50
- * recall = (correct + boundary_edit) / (correct + boundary_edit + missed)
51
- *
52
- * Returns null for precision/recall when the denominator is zero.
53
- */
54
- export function aggregateFeedback(assetId: string): AggregationResult {
55
- const allFeedback = getFeedbackForAsset(assetId);
56
- const allEvents = getEventsForAsset(assetId);
57
-
58
- // Group feedback by event type — we need event type from the events table
59
- const eventTypeById = new Map<string, string>();
60
- for (const event of allEvents) {
61
- eventTypeById.set(event.id, event.eventType);
62
- }
63
-
64
- // Collect counts per event type
65
- const countsMap = new Map<string, {
66
- correct: number;
67
- incorrect: number;
68
- boundaryEdit: number;
69
- missed: number;
70
- totalEvents: number;
71
- }>();
72
-
73
- // Initialize with known event types from existing events
74
- for (const event of allEvents) {
75
- if (!countsMap.has(event.eventType)) {
76
- countsMap.set(event.eventType, { correct: 0, incorrect: 0, boundaryEdit: 0, missed: 0, totalEvents: 0 });
77
- }
78
- countsMap.get(event.eventType)!.totalEvents++;
79
- }
80
-
81
- // Tally feedback
82
- for (const fb of allFeedback) {
83
- const eventType = eventTypeById.get(fb.eventId);
84
- if (!eventType) continue;
85
-
86
- if (!countsMap.has(eventType)) {
87
- countsMap.set(eventType, { correct: 0, incorrect: 0, boundaryEdit: 0, missed: 0, totalEvents: 0 });
88
- }
89
-
90
- const counts = countsMap.get(eventType)!;
91
- switch (fb.feedbackType) {
92
- case 'correct':
93
- counts.correct++;
94
- break;
95
- case 'incorrect':
96
- counts.incorrect++;
97
- break;
98
- case 'boundary_edit':
99
- counts.boundaryEdit++;
100
- break;
101
- case 'missed':
102
- counts.missed++;
103
- break;
104
- }
105
- }
106
-
107
- const statsByEventType: EventTypeStats[] = [];
108
- for (const [eventType, counts] of countsMap) {
109
- const precisionDenom = counts.correct + counts.incorrect;
110
- const recallDenom = counts.correct + counts.boundaryEdit + counts.missed;
111
-
112
- statsByEventType.push({
113
- eventType,
114
- totalEvents: counts.totalEvents,
115
- correct: counts.correct,
116
- incorrect: counts.incorrect,
117
- boundaryEdit: counts.boundaryEdit,
118
- missed: counts.missed,
119
- totalFeedback: counts.correct + counts.incorrect + counts.boundaryEdit + counts.missed,
120
- precision: precisionDenom > 0 ? counts.correct / precisionDenom : null,
121
- recall: recallDenom > 0 ? (counts.correct + counts.boundaryEdit) / recallDenom : null,
122
- });
123
- }
124
-
125
- return {
126
- assetId,
127
- totalFeedbackEntries: allFeedback.length,
128
- statsByEventType,
129
- };
130
- }
131
-
132
- /**
133
- * Export all feedback for an asset as structured JSON for offline analysis.
134
- */
135
- export function exportFeedback(assetId: string): FeedbackExport {
136
- const allFeedback = getFeedbackForAsset(assetId);
137
-
138
- return {
139
- assetId,
140
- exportedAt: new Date().toISOString(),
141
- totalEntries: allFeedback.length,
142
- feedback: allFeedback,
143
- };
144
- }
@@ -1,136 +0,0 @@
1
- /**
2
- * Feedback store service for media event corrections.
3
- *
4
- * Provides CRUD operations for the media_event_feedback table.
5
- * All interfaces are generic — works for any event type, not just turnovers.
6
- */
7
-
8
- import { and, eq } from 'drizzle-orm';
9
- import { v4 as uuid } from 'uuid';
10
- import { getDb } from '../../../../memory/db.js';
11
- import { mediaEventFeedback } from '../../../../memory/schema.js';
12
-
13
- // ---------------------------------------------------------------------------
14
- // Types
15
- // ---------------------------------------------------------------------------
16
-
17
- export type FeedbackType = 'correct' | 'incorrect' | 'boundary_edit' | 'missed';
18
-
19
- export interface EventFeedback {
20
- id: string;
21
- assetId: string;
22
- eventId: string;
23
- feedbackType: FeedbackType;
24
- originalStartTime: number | null;
25
- originalEndTime: number | null;
26
- correctedStartTime: number | null;
27
- correctedEndTime: number | null;
28
- notes: string | null;
29
- createdAt: number;
30
- }
31
-
32
- export interface SubmitFeedbackParams {
33
- assetId: string;
34
- eventId: string;
35
- feedbackType: FeedbackType;
36
- originalStartTime?: number;
37
- originalEndTime?: number;
38
- correctedStartTime?: number;
39
- correctedEndTime?: number;
40
- notes?: string;
41
- }
42
-
43
- // ---------------------------------------------------------------------------
44
- // Validation
45
- // ---------------------------------------------------------------------------
46
-
47
- const VALID_FEEDBACK_TYPES: FeedbackType[] = ['correct', 'incorrect', 'boundary_edit', 'missed'];
48
-
49
- function isValidFeedbackType(type: string): type is FeedbackType {
50
- return VALID_FEEDBACK_TYPES.includes(type as FeedbackType);
51
- }
52
-
53
- // ---------------------------------------------------------------------------
54
- // CRUD
55
- // ---------------------------------------------------------------------------
56
-
57
- export function submitFeedback(params: SubmitFeedbackParams): EventFeedback {
58
- if (!isValidFeedbackType(params.feedbackType)) {
59
- throw new Error(`Invalid feedback type "${params.feedbackType}". Must be one of: ${VALID_FEEDBACK_TYPES.join(', ')}`);
60
- }
61
-
62
- const db = getDb();
63
- const now = Date.now();
64
- const record = {
65
- id: uuid(),
66
- assetId: params.assetId,
67
- eventId: params.eventId,
68
- feedbackType: params.feedbackType,
69
- originalStartTime: params.originalStartTime ?? null,
70
- originalEndTime: params.originalEndTime ?? null,
71
- correctedStartTime: params.correctedStartTime ?? null,
72
- correctedEndTime: params.correctedEndTime ?? null,
73
- notes: params.notes ?? null,
74
- createdAt: now,
75
- };
76
-
77
- db.insert(mediaEventFeedback).values(record).run();
78
-
79
- return record;
80
- }
81
-
82
- export function getFeedbackForAsset(assetId: string): EventFeedback[] {
83
- const db = getDb();
84
- const rows = db
85
- .select()
86
- .from(mediaEventFeedback)
87
- .where(eq(mediaEventFeedback.assetId, assetId))
88
- .all();
89
- return rows.map(parseRow);
90
- }
91
-
92
- export function getFeedbackForEvent(eventId: string): EventFeedback[] {
93
- const db = getDb();
94
- const rows = db
95
- .select()
96
- .from(mediaEventFeedback)
97
- .where(eq(mediaEventFeedback.eventId, eventId))
98
- .all();
99
- return rows.map(parseRow);
100
- }
101
-
102
- export function getFeedbackByType(assetId: string, feedbackType: FeedbackType): EventFeedback[] {
103
- if (!isValidFeedbackType(feedbackType)) {
104
- throw new Error(`Invalid feedback type "${feedbackType}". Must be one of: ${VALID_FEEDBACK_TYPES.join(', ')}`);
105
- }
106
-
107
- const db = getDb();
108
- const rows = db
109
- .select()
110
- .from(mediaEventFeedback)
111
- .where(and(
112
- eq(mediaEventFeedback.assetId, assetId),
113
- eq(mediaEventFeedback.feedbackType, feedbackType),
114
- ))
115
- .all();
116
- return rows.map(parseRow);
117
- }
118
-
119
- // ---------------------------------------------------------------------------
120
- // Row parsing
121
- // ---------------------------------------------------------------------------
122
-
123
- function parseRow(row: typeof mediaEventFeedback.$inferSelect): EventFeedback {
124
- return {
125
- id: row.id,
126
- assetId: row.assetId,
127
- eventId: row.eventId,
128
- feedbackType: row.feedbackType as FeedbackType,
129
- originalStartTime: row.originalStartTime,
130
- originalEndTime: row.originalEndTime,
131
- correctedStartTime: row.correctedStartTime,
132
- correctedEndTime: row.correctedEndTime,
133
- notes: row.notes,
134
- createdAt: row.createdAt,
135
- };
136
- }
@@ -1,95 +0,0 @@
1
- /**
2
- * Generic media event retrieval service.
3
- *
4
- * Pure data retrieval with configurable filters and ranking — no
5
- * domain-specific logic. Callers (e.g. a query tool) are responsible
6
- * for translating domain concepts into filter parameters.
7
- */
8
-
9
- import {
10
- getEventsForAsset,
11
- type MediaEvent,
12
- } from '../../../../memory/media-store.js';
13
-
14
- // ---------------------------------------------------------------------------
15
- // Types
16
- // ---------------------------------------------------------------------------
17
-
18
- export interface RetrievalFilters {
19
- /** Scope results to a specific media asset. */
20
- assetId?: string;
21
- /** Filter by event type label. */
22
- eventType?: string;
23
- /** Minimum confidence threshold (0–1). */
24
- minConfidence?: number;
25
- /** Maximum number of results to return. */
26
- limit?: number;
27
- /** Sort order for results. */
28
- sortBy?: 'confidence' | 'startTime';
29
- /** Only return events that start at or after this time (seconds). */
30
- startTimeMin?: number;
31
- /** Only return events that start at or before this time (seconds). */
32
- startTimeMax?: number;
33
- }
34
-
35
- export interface RetrievalResult {
36
- events: MediaEvent[];
37
- totalReturned: number;
38
- filters: RetrievalFilters;
39
- }
40
-
41
- // ---------------------------------------------------------------------------
42
- // Retrieval
43
- // ---------------------------------------------------------------------------
44
-
45
- /**
46
- * Query the media_events table with the given filters and return ranked
47
- * results with full event metadata.
48
- *
49
- * When `assetId` is not provided the function returns an empty result set
50
- * because the underlying store requires an asset scope. Callers that want
51
- * cross-asset queries should iterate over asset IDs externally.
52
- */
53
- export function retrieveEvents(filters: RetrievalFilters): RetrievalResult {
54
- const {
55
- assetId,
56
- eventType,
57
- minConfidence,
58
- limit = 10,
59
- sortBy = 'confidence',
60
- startTimeMin,
61
- startTimeMax,
62
- } = filters;
63
-
64
- if (!assetId) {
65
- return { events: [], totalReturned: 0, filters };
66
- }
67
-
68
- // Fetch from the store with the subset of filters it supports natively
69
- let events = getEventsForAsset(assetId, {
70
- eventType,
71
- minConfidence,
72
- sortBy,
73
- // Fetch more than needed so we can apply time-range filtering locally
74
- limit: startTimeMin !== undefined || startTimeMax !== undefined ? undefined : limit,
75
- });
76
-
77
- // Apply time-range filters that the store doesn't support directly
78
- if (startTimeMin !== undefined) {
79
- events = events.filter((e) => e.startTime >= startTimeMin);
80
- }
81
- if (startTimeMax !== undefined) {
82
- events = events.filter((e) => e.startTime <= startTimeMax);
83
- }
84
-
85
- // Re-apply limit after local filtering
86
- if (limit && events.length > limit) {
87
- events = events.slice(0, limit);
88
- }
89
-
90
- return {
91
- events,
92
- totalReturned: events.length,
93
- filters,
94
- };
95
- }