wicked-crew 0.16.11 → 0.16.13

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 (341) hide show
  1. package/README.md +28 -8
  2. package/dist/api/artifact-outline.d.ts +64 -0
  3. package/dist/api/artifact-outline.d.ts.map +1 -0
  4. package/dist/api/artifact-outline.js +254 -0
  5. package/dist/api/artifact-outline.js.map +1 -0
  6. package/dist/api/beneath.d.ts +76 -0
  7. package/dist/api/beneath.d.ts.map +1 -0
  8. package/dist/api/beneath.js +214 -0
  9. package/dist/api/beneath.js.map +1 -0
  10. package/dist/api/capture.d.ts +2 -2
  11. package/dist/api/chat-citations.d.ts +25 -1
  12. package/dist/api/chat-citations.d.ts.map +1 -1
  13. package/dist/api/chat-citations.js +186 -61
  14. package/dist/api/chat-citations.js.map +1 -1
  15. package/dist/api/chat-context.d.ts +236 -0
  16. package/dist/api/chat-context.d.ts.map +1 -0
  17. package/dist/api/chat-context.js +808 -0
  18. package/dist/api/chat-context.js.map +1 -0
  19. package/dist/api/chat-history.d.ts +20 -0
  20. package/dist/api/chat-history.d.ts.map +1 -1
  21. package/dist/api/chat-history.js +46 -1
  22. package/dist/api/chat-history.js.map +1 -1
  23. package/dist/api/chat-proposals.d.ts +534 -0
  24. package/dist/api/chat-proposals.d.ts.map +1 -0
  25. package/dist/api/chat-proposals.js +1562 -0
  26. package/dist/api/chat-proposals.js.map +1 -0
  27. package/dist/api/chat-scope.d.ts +41 -0
  28. package/dist/api/chat-scope.d.ts.map +1 -1
  29. package/dist/api/chat-scope.js +87 -15
  30. package/dist/api/chat-scope.js.map +1 -1
  31. package/dist/api/chat-transcripts.d.ts +27 -2
  32. package/dist/api/chat-transcripts.d.ts.map +1 -1
  33. package/dist/api/chat-transcripts.js +105 -4
  34. package/dist/api/chat-transcripts.js.map +1 -1
  35. package/dist/api/diagnostics.d.ts +15 -0
  36. package/dist/api/diagnostics.d.ts.map +1 -1
  37. package/dist/api/diagnostics.js +56 -0
  38. package/dist/api/diagnostics.js.map +1 -1
  39. package/dist/api/elicitation-cache.d.ts +13 -0
  40. package/dist/api/elicitation-cache.d.ts.map +1 -1
  41. package/dist/api/elicitation-cache.js +12 -0
  42. package/dist/api/elicitation-cache.js.map +1 -1
  43. package/dist/api/eval-sample.d.ts +12 -12
  44. package/dist/api/frame-guard.d.ts +62 -0
  45. package/dist/api/frame-guard.d.ts.map +1 -0
  46. package/dist/api/frame-guard.js +97 -0
  47. package/dist/api/frame-guard.js.map +1 -0
  48. package/dist/api/governance-steering.d.ts +4 -4
  49. package/dist/api/multiscope.d.ts +3 -0
  50. package/dist/api/multiscope.d.ts.map +1 -1
  51. package/dist/api/multiscope.js +13 -0
  52. package/dist/api/multiscope.js.map +1 -1
  53. package/dist/api/needs.d.ts +6 -0
  54. package/dist/api/needs.d.ts.map +1 -1
  55. package/dist/api/needs.js +31 -4
  56. package/dist/api/needs.js.map +1 -1
  57. package/dist/api/product.d.ts.map +1 -1
  58. package/dist/api/product.js +13 -2
  59. package/dist/api/product.js.map +1 -1
  60. package/dist/api/project-aggregates.d.ts +6 -6
  61. package/dist/api/project-aggregates.d.ts.map +1 -1
  62. package/dist/api/project-aggregates.js +16 -24
  63. package/dist/api/project-aggregates.js.map +1 -1
  64. package/dist/api/requirements.d.ts +261 -6
  65. package/dist/api/requirements.d.ts.map +1 -1
  66. package/dist/api/requirements.js +344 -64
  67. package/dist/api/requirements.js.map +1 -1
  68. package/dist/api/routes.d.ts +156 -4
  69. package/dist/api/routes.d.ts.map +1 -1
  70. package/dist/api/routes.js +851 -78
  71. package/dist/api/routes.js.map +1 -1
  72. package/dist/api/run-brief.d.ts +78 -0
  73. package/dist/api/run-brief.d.ts.map +1 -0
  74. package/dist/api/run-brief.js +318 -0
  75. package/dist/api/run-brief.js.map +1 -0
  76. package/dist/api/run-files.d.ts.map +1 -1
  77. package/dist/api/run-files.js +5 -1
  78. package/dist/api/run-files.js.map +1 -1
  79. package/dist/api/run-timing-index.d.ts +27 -0
  80. package/dist/api/run-timing-index.d.ts.map +1 -1
  81. package/dist/api/run-timing-index.js +65 -0
  82. package/dist/api/run-timing-index.js.map +1 -1
  83. package/dist/api/seat-images.d.ts +102 -0
  84. package/dist/api/seat-images.d.ts.map +1 -0
  85. package/dist/api/seat-images.js +333 -0
  86. package/dist/api/seat-images.js.map +1 -0
  87. package/dist/api/server.d.ts +3 -0
  88. package/dist/api/server.d.ts.map +1 -1
  89. package/dist/api/server.js +265 -2
  90. package/dist/api/server.js.map +1 -1
  91. package/dist/api/steering-landing.d.ts +48 -1
  92. package/dist/api/steering-landing.d.ts.map +1 -1
  93. package/dist/api/steering-landing.js +116 -42
  94. package/dist/api/steering-landing.js.map +1 -1
  95. package/dist/api/system-snapshot.d.ts +51 -2
  96. package/dist/api/system-snapshot.d.ts.map +1 -1
  97. package/dist/api/system-snapshot.js +151 -15
  98. package/dist/api/system-snapshot.js.map +1 -1
  99. package/dist/api/testing.d.ts +4 -4
  100. package/dist/api/testing.js +2 -2
  101. package/dist/api/testing.js.map +1 -1
  102. package/dist/apps/spec.d.ts +3009 -0
  103. package/dist/apps/spec.d.ts.map +1 -0
  104. package/dist/apps/spec.js +870 -0
  105. package/dist/apps/spec.js.map +1 -0
  106. package/dist/campaigns/routes.js +1 -1
  107. package/dist/campaigns/routes.js.map +1 -1
  108. package/dist/cli/index.js +3 -3
  109. package/dist/cli/index.js.map +1 -1
  110. package/dist/core/adapter.d.ts +12 -0
  111. package/dist/core/adapter.d.ts.map +1 -1
  112. package/dist/core/adapter.js +36 -1
  113. package/dist/core/adapter.js.map +1 -1
  114. package/dist/core/deliver-text.d.ts.map +1 -1
  115. package/dist/core/deliver-text.js +22 -10
  116. package/dist/core/deliver-text.js.map +1 -1
  117. package/dist/core/estate-mcp-client.d.ts +7 -1
  118. package/dist/core/estate-mcp-client.d.ts.map +1 -1
  119. package/dist/core/estate-mcp-client.js +10 -2
  120. package/dist/core/estate-mcp-client.js.map +1 -1
  121. package/dist/core/exec.d.ts +12 -0
  122. package/dist/core/exec.d.ts.map +1 -1
  123. package/dist/core/exec.js +23 -0
  124. package/dist/core/exec.js.map +1 -1
  125. package/dist/core/reassign-refusal.d.ts.map +1 -1
  126. package/dist/core/reassign-refusal.js +23 -3
  127. package/dist/core/reassign-refusal.js.map +1 -1
  128. package/dist/core/repoPaths.d.ts +32 -7
  129. package/dist/core/repoPaths.d.ts.map +1 -1
  130. package/dist/core/repoPaths.js +56 -9
  131. package/dist/core/repoPaths.js.map +1 -1
  132. package/dist/core/requirements-graph-setting.d.ts +32 -0
  133. package/dist/core/requirements-graph-setting.d.ts.map +1 -0
  134. package/dist/core/requirements-graph-setting.js +84 -0
  135. package/dist/core/requirements-graph-setting.js.map +1 -0
  136. package/dist/core/run-boot-resume.d.ts +4 -1
  137. package/dist/core/run-boot-resume.d.ts.map +1 -1
  138. package/dist/core/run-boot-resume.js +6 -1
  139. package/dist/core/run-boot-resume.js.map +1 -1
  140. package/dist/core/run-identity.d.ts.map +1 -1
  141. package/dist/core/run-identity.js +6 -0
  142. package/dist/core/run-identity.js.map +1 -1
  143. package/dist/core/types.d.ts +14 -0
  144. package/dist/core/types.d.ts.map +1 -1
  145. package/dist/core/types.js.map +1 -1
  146. package/dist/decisions/chat-recorder.d.ts +14 -3
  147. package/dist/decisions/chat-recorder.d.ts.map +1 -1
  148. package/dist/decisions/chat-recorder.js +54 -9
  149. package/dist/decisions/chat-recorder.js.map +1 -1
  150. package/dist/editors/csp.d.ts +24 -4
  151. package/dist/editors/csp.d.ts.map +1 -1
  152. package/dist/editors/csp.js +35 -8
  153. package/dist/editors/csp.js.map +1 -1
  154. package/dist/editors/registry.d.ts +46 -21
  155. package/dist/editors/registry.d.ts.map +1 -1
  156. package/dist/editors/registry.js +13 -2
  157. package/dist/editors/registry.js.map +1 -1
  158. package/dist/editors/routes.d.ts +4 -1
  159. package/dist/editors/routes.d.ts.map +1 -1
  160. package/dist/editors/routes.js +30 -3
  161. package/dist/editors/routes.js.map +1 -1
  162. package/dist/editors/visuals.d.ts +51 -0
  163. package/dist/editors/visuals.d.ts.map +1 -0
  164. package/dist/editors/visuals.js +164 -0
  165. package/dist/editors/visuals.js.map +1 -0
  166. package/dist/editors/webrtc-guard.d.ts +94 -0
  167. package/dist/editors/webrtc-guard.d.ts.map +1 -0
  168. package/dist/editors/webrtc-guard.js +506 -0
  169. package/dist/editors/webrtc-guard.js.map +1 -0
  170. package/dist/inspect/reading.d.ts +110 -0
  171. package/dist/inspect/reading.d.ts.map +1 -0
  172. package/dist/inspect/reading.js +325 -0
  173. package/dist/inspect/reading.js.map +1 -0
  174. package/dist/inspect/routes.d.ts +14 -0
  175. package/dist/inspect/routes.d.ts.map +1 -0
  176. package/dist/inspect/routes.js +44 -0
  177. package/dist/inspect/routes.js.map +1 -0
  178. package/dist/inspect/service.d.ts +161 -0
  179. package/dist/inspect/service.d.ts.map +1 -0
  180. package/dist/inspect/service.js +466 -0
  181. package/dist/inspect/service.js.map +1 -0
  182. package/dist/interactive/bridge-pool.d.ts +11 -2
  183. package/dist/interactive/bridge-pool.d.ts.map +1 -1
  184. package/dist/interactive/bridge-pool.js +10 -1
  185. package/dist/interactive/bridge-pool.js.map +1 -1
  186. package/dist/interactive/doc-binding.d.ts +156 -0
  187. package/dist/interactive/doc-binding.d.ts.map +1 -0
  188. package/dist/interactive/doc-binding.js +277 -0
  189. package/dist/interactive/doc-binding.js.map +1 -0
  190. package/dist/interactive/doc-delete-routes.d.ts +3 -0
  191. package/dist/interactive/doc-delete-routes.d.ts.map +1 -1
  192. package/dist/interactive/doc-delete-routes.js +4 -0
  193. package/dist/interactive/doc-delete-routes.js.map +1 -1
  194. package/dist/interactive/draft-events.d.ts +89 -3
  195. package/dist/interactive/draft-events.d.ts.map +1 -1
  196. package/dist/interactive/draft-events.js +441 -30
  197. package/dist/interactive/draft-events.js.map +1 -1
  198. package/dist/interactive/draft-skill.d.ts +7 -0
  199. package/dist/interactive/draft-skill.d.ts.map +1 -1
  200. package/dist/interactive/draft-skill.js +10 -3
  201. package/dist/interactive/draft-skill.js.map +1 -1
  202. package/dist/interactive/edit-events.d.ts +2 -0
  203. package/dist/interactive/edit-events.d.ts.map +1 -1
  204. package/dist/interactive/edit-events.js +11 -0
  205. package/dist/interactive/edit-events.js.map +1 -1
  206. package/dist/interactive/proposal-create.d.ts +143 -0
  207. package/dist/interactive/proposal-create.d.ts.map +1 -0
  208. package/dist/interactive/proposal-create.js +318 -0
  209. package/dist/interactive/proposal-create.js.map +1 -0
  210. package/dist/interactive/proxy-routes.d.ts +60 -3
  211. package/dist/interactive/proxy-routes.d.ts.map +1 -1
  212. package/dist/interactive/proxy-routes.js +217 -3
  213. package/dist/interactive/proxy-routes.js.map +1 -1
  214. package/dist/interactive/source-packet.d.ts +126 -0
  215. package/dist/interactive/source-packet.d.ts.map +1 -0
  216. package/dist/interactive/source-packet.js +482 -0
  217. package/dist/interactive/source-packet.js.map +1 -0
  218. package/dist/learnings/estate.d.ts +16 -0
  219. package/dist/learnings/estate.d.ts.map +1 -0
  220. package/dist/learnings/estate.js +68 -0
  221. package/dist/learnings/estate.js.map +1 -0
  222. package/dist/learnings/extract.d.ts +56 -0
  223. package/dist/learnings/extract.d.ts.map +1 -0
  224. package/dist/learnings/extract.js +252 -0
  225. package/dist/learnings/extract.js.map +1 -0
  226. package/dist/learnings/recall.d.ts +43 -0
  227. package/dist/learnings/recall.d.ts.map +1 -0
  228. package/dist/learnings/recall.js +104 -0
  229. package/dist/learnings/recall.js.map +1 -0
  230. package/dist/learnings/service.d.ts +183 -0
  231. package/dist/learnings/service.d.ts.map +1 -0
  232. package/dist/learnings/service.js +571 -0
  233. package/dist/learnings/service.js.map +1 -0
  234. package/dist/mcp/ask-server.d.ts.map +1 -1
  235. package/dist/mcp/ask-server.js +37 -4
  236. package/dist/mcp/ask-server.js.map +1 -1
  237. package/dist/mcp/broker.d.ts +12 -1
  238. package/dist/mcp/broker.d.ts.map +1 -1
  239. package/dist/mcp/broker.js +24 -5
  240. package/dist/mcp/broker.js.map +1 -1
  241. package/dist/mcp/invoke.d.ts +26 -2
  242. package/dist/mcp/invoke.d.ts.map +1 -1
  243. package/dist/mcp/invoke.js +51 -5
  244. package/dist/mcp/invoke.js.map +1 -1
  245. package/dist/persona/routes.d.ts +92 -0
  246. package/dist/persona/routes.d.ts.map +1 -0
  247. package/dist/persona/routes.js +69 -0
  248. package/dist/persona/routes.js.map +1 -0
  249. package/dist/persona/store.d.ts +104 -0
  250. package/dist/persona/store.d.ts.map +1 -0
  251. package/dist/persona/store.js +176 -0
  252. package/dist/persona/store.js.map +1 -0
  253. package/dist/persona/voice.d.ts +4 -0
  254. package/dist/persona/voice.d.ts.map +1 -0
  255. package/dist/persona/voice.js +58 -0
  256. package/dist/persona/voice.js.map +1 -0
  257. package/dist/projects/routes.d.ts +2 -2
  258. package/dist/setup/known.d.ts +56 -0
  259. package/dist/setup/known.d.ts.map +1 -0
  260. package/dist/setup/known.js +159 -0
  261. package/dist/setup/known.js.map +1 -0
  262. package/dist/setup/routes.d.ts +13 -0
  263. package/dist/setup/routes.d.ts.map +1 -0
  264. package/dist/setup/routes.js +20 -0
  265. package/dist/setup/routes.js.map +1 -0
  266. package/dist/standing-orders/history.d.ts +2 -0
  267. package/dist/standing-orders/history.d.ts.map +1 -1
  268. package/dist/standing-orders/history.js +1 -0
  269. package/dist/standing-orders/history.js.map +1 -1
  270. package/dist/studio/assets/WickedSans-Regular-fb698rcD.woff2 +0 -0
  271. package/dist/studio/assets/WickedSans-SemiBold-CD53n1AC.woff2 +0 -0
  272. package/dist/studio/assets/WickedScript-Regular-CY5juO6I.woff2 +0 -0
  273. package/dist/studio/assets/WickedSerif-Regular-mdPEjaVZ.woff2 +0 -0
  274. package/dist/studio/assets/index-BUZ_-Syk.css +32 -0
  275. package/dist/studio/assets/index-u4O_7N-b.js +986 -0
  276. package/dist/studio/editors/wicked-deck/editor.json +6 -1
  277. package/dist/studio/editors/wicked-deck/icon.svg +1 -0
  278. package/dist/studio/editors/wicked-deck/index.html +1 -1
  279. package/dist/studio/editors/wicked-doc/editor.json +6 -1
  280. package/dist/studio/editors/wicked-doc/icon.svg +1 -0
  281. package/dist/studio/editors/wicked-doc/index.html +1 -1
  282. package/dist/studio/editors/wicked-insights/editor.json +6 -1
  283. package/dist/studio/editors/wicked-insights/icon.svg +1 -0
  284. package/dist/studio/editors/wicked-insights/index.html +1 -1
  285. package/dist/studio/editors/wicked-page/editor.json +6 -1
  286. package/dist/studio/editors/wicked-page/icon.svg +1 -0
  287. package/dist/studio/editors/wicked-page/index.html +1 -1
  288. package/dist/studio/editors/wicked-video/editor.json +6 -1
  289. package/dist/studio/editors/wicked-video/icon.svg +1 -0
  290. package/dist/studio/editors/wicked-video/index.html +1 -1
  291. package/dist/studio/index.html +2 -2
  292. package/dist/studio/testid-inventory.json +5155 -2707
  293. package/dist/voice/dashboard.d.ts +376 -0
  294. package/dist/voice/dashboard.d.ts.map +1 -0
  295. package/dist/voice/dashboard.js +92 -0
  296. package/dist/voice/dashboard.js.map +1 -0
  297. package/dist/voice/inject-input.d.ts +51 -0
  298. package/dist/voice/inject-input.d.ts.map +1 -0
  299. package/dist/voice/inject-input.js +126 -0
  300. package/dist/voice/inject-input.js.map +1 -0
  301. package/dist/voice/routes.d.ts +41 -0
  302. package/dist/voice/routes.d.ts.map +1 -0
  303. package/dist/voice/routes.js +116 -0
  304. package/dist/voice/routes.js.map +1 -0
  305. package/dist/voice/service.d.ts +177 -0
  306. package/dist/voice/service.d.ts.map +1 -0
  307. package/dist/voice/service.js +400 -0
  308. package/dist/voice/service.js.map +1 -0
  309. package/dist/workflow-catalog/build.d.ts +35 -0
  310. package/dist/workflow-catalog/build.d.ts.map +1 -0
  311. package/dist/workflow-catalog/build.js +229 -0
  312. package/dist/workflow-catalog/build.js.map +1 -0
  313. package/dist/workflow-catalog/catalog-data.d.ts +36 -0
  314. package/dist/workflow-catalog/catalog-data.d.ts.map +1 -0
  315. package/dist/workflow-catalog/catalog-data.js +430 -0
  316. package/dist/workflow-catalog/catalog-data.js.map +1 -0
  317. package/dist/working-doc/event-lines.d.ts +76 -0
  318. package/dist/working-doc/event-lines.d.ts.map +1 -0
  319. package/dist/working-doc/event-lines.js +247 -0
  320. package/dist/working-doc/event-lines.js.map +1 -0
  321. package/dist/working-doc/routes.d.ts +1 -1
  322. package/dist/working-doc/routes.d.ts.map +1 -1
  323. package/dist/working-doc/routes.js +2 -1
  324. package/dist/working-doc/routes.js.map +1 -1
  325. package/dist/working-doc/sections.d.ts +3 -1
  326. package/dist/working-doc/sections.d.ts.map +1 -1
  327. package/dist/working-doc/sections.js +4 -2
  328. package/dist/working-doc/sections.js.map +1 -1
  329. package/dist/working-doc/service.d.ts +66 -1
  330. package/dist/working-doc/service.d.ts.map +1 -1
  331. package/dist/working-doc/service.js +298 -22
  332. package/dist/working-doc/service.js.map +1 -1
  333. package/dist/working-doc/store.d.ts +8 -2
  334. package/dist/working-doc/store.d.ts.map +1 -1
  335. package/dist/working-doc/store.js.map +1 -1
  336. package/endpoint-manifest.json +205 -2
  337. package/package.json +5 -4
  338. package/workflows/distill-learnings.json +27 -0
  339. package/workflows/inspect-unit.json +27 -0
  340. package/dist/studio/assets/index-B-f_VEL2.css +0 -32
  341. package/dist/studio/assets/index-DhkxIK-0.js +0 -845
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Voice mode's routes (program DES-VOICE §3, §6; api-types `VoiceStatus`, `VoiceTranscribeResponse`,
3
+ * `VoiceDashboard`):
4
+ *
5
+ * GET /voice/status the engine and the model on this machine, and a download in progress
6
+ * POST /voice/model {consent: true} → start fetching the model (202); audited
7
+ * DELETE /voice/model remove the model; audited
8
+ * POST /voice/transcribe audio/wav body → {text, ms, model}; the audio is never stored
9
+ * GET /voice/dashboard this person's dashboard layout and user widgets
10
+ * PUT /voice/dashboard {layout, widgets} → the same shape
11
+ *
12
+ * Every voice route is the human operator's alone and answers only a loopback caller: a worker's bearer (a
13
+ * non-human actor) gets 403, and a request from another host gets 403 even on a daemon bound wider.
14
+ */
15
+ import type { FastifyInstance, FastifyRequest } from 'fastify';
16
+ import { z } from 'zod';
17
+ import type { AuditLog } from '../api/audit.js';
18
+ import type { Actor } from '../core/types.js';
19
+ import { type VoiceDashboardStore } from './dashboard.js';
20
+ import { type VoiceService } from './service.js';
21
+ export declare const PostVoiceModelSchema: z.ZodObject<{
22
+ consent: z.ZodLiteral<true>;
23
+ }, "strict", z.ZodTypeAny, {
24
+ consent: true;
25
+ }, {
26
+ consent: true;
27
+ }>;
28
+ export interface VoiceRouteDeps {
29
+ voice: VoiceService;
30
+ dashboard: VoiceDashboardStore | null;
31
+ audit: Pick<AuditLog, 'record'>;
32
+ }
33
+ /** The loopback, human-operator fence every voice route shares; null = allowed. */
34
+ export declare function voiceRefusal(req: FastifyRequest & {
35
+ actor?: Actor;
36
+ }): {
37
+ error: string;
38
+ code: string;
39
+ } | null;
40
+ export declare function registerVoiceRoutes(app: FastifyInstance, deps: VoiceRouteDeps): void;
41
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/voice/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgB,cAAc,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAA2B,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAqC,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAIpF,eAAO,MAAM,oBAAoB;;;;;;EAAkD,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACtC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;CACjC;AAID,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG;IAAE,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAU5G;AAOD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAgGpF"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Voice mode's routes (program DES-VOICE §3, §6; api-types `VoiceStatus`, `VoiceTranscribeResponse`,
3
+ * `VoiceDashboard`):
4
+ *
5
+ * GET /voice/status the engine and the model on this machine, and a download in progress
6
+ * POST /voice/model {consent: true} → start fetching the model (202); audited
7
+ * DELETE /voice/model remove the model; audited
8
+ * POST /voice/transcribe audio/wav body → {text, ms, model}; the audio is never stored
9
+ * GET /voice/dashboard this person's dashboard layout and user widgets
10
+ * PUT /voice/dashboard {layout, widgets} → the same shape
11
+ *
12
+ * Every voice route is the human operator's alone and answers only a loopback caller: a worker's bearer (a
13
+ * non-human actor) gets 403, and a request from another host gets 403 even on a daemon bound wider.
14
+ */
15
+ import { z } from 'zod';
16
+ import { API_PREFIX } from '../api/api-prefix.js';
17
+ import { LOCAL_ACTOR } from '../api/auth.js';
18
+ import { isHumanOperator } from '../api/watch-routes.js';
19
+ import { PutVoiceDashboardSchema } from './dashboard.js';
20
+ import { VOICE_MAX_AUDIO_BYTES, VoiceError } from './service.js';
21
+ const V = API_PREFIX;
22
+ export const PostVoiceModelSchema = z.object({ consent: z.literal(true) }).strict();
23
+ const LOOPBACK = new Set(['127.0.0.1', '::1', '::ffff:127.0.0.1']);
24
+ /** The loopback, human-operator fence every voice route shares; null = allowed. */
25
+ export function voiceRefusal(req) {
26
+ const ip = req.socket?.remoteAddress ?? req.ip;
27
+ if (ip !== undefined && !LOOPBACK.has(ip)) {
28
+ return { error: 'Voice is answered only on this machine (a loopback caller).', code: 'voice_loopback_only' };
29
+ }
30
+ const actor = req.actor ?? LOCAL_ACTOR;
31
+ if (!isHumanOperator(actor)) {
32
+ return { error: `Voice is the human operator's alone (you are ${actor.kind}/${actor.trust}).`, code: 'human_operator_only' };
33
+ }
34
+ return null;
35
+ }
36
+ function fail(reply, e) {
37
+ if (e instanceof VoiceError)
38
+ return reply.code(e.status).send(e.body());
39
+ return reply.code(500).send({ error: e instanceof Error ? e.message : String(e), code: 'voice_failed' });
40
+ }
41
+ export function registerVoiceRoutes(app, deps) {
42
+ const actorOf = (req) => req.actor ?? LOCAL_ACTOR;
43
+ void app.register(async (scope) => {
44
+ // The fence runs on request, before any body is read: a refused caller never gets to stream audio in.
45
+ scope.addHook('onRequest', async (req, reply) => {
46
+ const refused = voiceRefusal(req);
47
+ if (refused !== null)
48
+ return reply.code(403).send(refused);
49
+ return undefined;
50
+ });
51
+ // The recording arrives as raw bytes, buffered by a parser scoped to the transcribe route alone (and its
52
+ // media-type error speaks only for that route).
53
+ void scope.register(async (audio) => {
54
+ for (const type of ['audio/wav', 'audio/x-wav', 'audio/wave']) {
55
+ audio.addContentTypeParser(type, { parseAs: 'buffer', bodyLimit: VOICE_MAX_AUDIO_BYTES + 1024 }, (_req, body, done) => done(null, body));
56
+ }
57
+ audio.setErrorHandler((err, _req, reply) => {
58
+ const code = err.code;
59
+ if (code === 'FST_ERR_CTP_BODY_TOO_LARGE') {
60
+ return reply.code(413).send({ error: `The recording is over ${Math.round(VOICE_MAX_AUDIO_BYTES / 1048576)} MiB; speak in shorter turns.`, code: 'voice_audio_too_large' });
61
+ }
62
+ if (code === 'FST_ERR_CTP_INVALID_MEDIA_TYPE') {
63
+ return reply.code(415).send({ error: 'Send the recording as audio/wav.', code: 'voice_audio_invalid' });
64
+ }
65
+ return reply.send(err);
66
+ });
67
+ audio.post(`${V}/voice/transcribe`, { config: { manifest: { requestType: 'audio/wav', responseType: 'VoiceTranscribeResponse', statusCodes: [200, 400, 403, 409, 413, 415, 429, 500, 504] } } }, async (req, reply) => {
68
+ if (!Buffer.isBuffer(req.body))
69
+ return reply.code(415).send({ error: 'Send the recording as audio/wav.', code: 'voice_audio_invalid' });
70
+ try {
71
+ // Nothing about the audio is logged or audited: not its bytes, not its words.
72
+ return await deps.voice.transcribe(req.body);
73
+ }
74
+ catch (e) {
75
+ return fail(reply, e);
76
+ }
77
+ });
78
+ });
79
+ scope.get(`${V}/voice/status`, { config: { manifest: { responseType: 'VoiceStatus', statusCodes: [200, 403] } } }, async () => deps.voice.status());
80
+ scope.post(`${V}/voice/model`, { config: { manifest: { requestType: 'PostVoiceModelBody', responseType: 'VoiceStatus', statusCodes: [200, 202, 400, 403, 409] } } }, async (req, reply) => {
81
+ const parsed = PostVoiceModelSchema.safeParse(req.body);
82
+ if (!parsed.success) {
83
+ return reply.code(400).send({ error: 'Downloading the speech model needs your consent: send {"consent": true}.', code: 'voice_consent_required' });
84
+ }
85
+ try {
86
+ const { started } = deps.voice.startDownload();
87
+ if (started)
88
+ deps.audit.record('voice.model.download_started', actorOf(req), { detail: { model: deps.voice.status().model.name } });
89
+ return reply.code(started ? 202 : 200).send(deps.voice.status());
90
+ }
91
+ catch (e) {
92
+ return fail(reply, e);
93
+ }
94
+ });
95
+ scope.delete(`${V}/voice/model`, { config: { manifest: { responseType: 'VoiceStatus', statusCodes: [200, 403] } } }, async (req) => {
96
+ const { removed } = deps.voice.removeModel();
97
+ if (removed)
98
+ deps.audit.record('voice.model.removed', actorOf(req), { detail: { model: deps.voice.status().model.name } });
99
+ return deps.voice.status();
100
+ });
101
+ scope.get(`${V}/voice/dashboard`, { config: { manifest: { responseType: 'VoiceDashboard', statusCodes: [200, 403, 503] } } }, async (req, reply) => {
102
+ if (deps.dashboard === null)
103
+ return reply.code(503).send({ error: 'This daemon keeps no dashboard store.', code: 'voice_dashboard_unavailable' });
104
+ return deps.dashboard.get(actorOf(req).id);
105
+ });
106
+ scope.put(`${V}/voice/dashboard`, { config: { manifest: { requestType: 'PutVoiceDashboardBody', responseType: 'VoiceDashboard', statusCodes: [200, 400, 403, 503] } } }, async (req, reply) => {
107
+ if (deps.dashboard === null)
108
+ return reply.code(503).send({ error: 'This daemon keeps no dashboard store.', code: 'voice_dashboard_unavailable' });
109
+ const parsed = PutVoiceDashboardSchema.safeParse(req.body);
110
+ if (!parsed.success)
111
+ return reply.code(400).send({ error: 'Invalid dashboard', details: parsed.error.issues });
112
+ return deps.dashboard.put(actorOf(req).id, parsed.data);
113
+ });
114
+ });
115
+ }
116
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/voice/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,uBAAuB,EAA4B,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAqB,MAAM,cAAc,CAAC;AAEpF,MAAM,CAAC,GAAG,UAAU,CAAC;AAErB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAQpF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEnE,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,GAAuC;IAClE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,IAAI,GAAG,CAAC,EAAE,CAAC;IAC/C,IAAI,EAAE,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,6DAA6D,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC;IAC/G,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,WAAW,CAAC;IACvC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,gDAAgD,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC;IAC/H,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,IAAI,CAAC,KAAmB,EAAE,CAAU;IAC3C,IAAI,CAAC,YAAY,UAAU;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;AAC3G,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAoB,EAAE,IAAoB;IAC5E,MAAM,OAAO,GAAG,CAAC,GAAsB,EAAS,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,WAAW,CAAC;IAE5E,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAChC,sGAAsG;QACtG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,GAAyC,CAAC,CAAC;YACxE,IAAI,OAAO,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3D,OAAO,SAAS,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,yGAAyG;QACzG,gDAAgD;QAChD,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAClC,KAAK,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC;gBAC9D,KAAK,CAAC,oBAAoB,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,qBAAqB,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3I,CAAC;YACD,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;gBACzC,MAAM,IAAI,GAAI,GAA0B,CAAC,IAAI,CAAC;gBAC9C,IAAI,IAAI,KAAK,4BAA4B,EAAE,CAAC;oBAC1C,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,IAAI,CAAC,KAAK,CAAC,qBAAqB,GAAG,OAAO,CAAC,+BAA+B,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC,CAAC;gBAC7K,CAAC;gBACD,IAAI,IAAI,KAAK,gCAAgC,EAAE,CAAC;oBAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kCAAkC,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,CAAC;gBAC1G,CAAC;gBACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,mBAAmB,EACvB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAC3J,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACnB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kCAAkC,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,CAAC;gBACxI,IAAI,CAAC;oBACH,8EAA8E;oBAC9E,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC/C,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,GAAG,CACP,GAAG,CAAC,eAAe,EACnB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAClF,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAChC,CAAC;QAEF,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,cAAc,EAClB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,oBAAoB,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EACpI,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACnB,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0EAA0E,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC,CAAC;YACrJ,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;gBAC/C,IAAI,OAAO;oBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,8BAA8B,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACpI,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YACnE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACxB,CAAC;QACH,CAAC,CACF,CAAC;QAEF,KAAK,CAAC,MAAM,CACV,GAAG,CAAC,cAAc,EAClB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAClF,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,OAAO;gBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3H,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7B,CAAC,CACF,CAAC;QAEF,KAAK,CAAC,GAAG,CACP,GAAG,CAAC,kBAAkB,EACtB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAC1F,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACnB,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uCAAuC,EAAE,IAAI,EAAE,6BAA6B,EAAE,CAAC,CAAC;YAClJ,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC,CACF,CAAC;QAEF,KAAK,CAAC,GAAG,CACP,GAAG,CAAC,kBAAkB,EACtB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,uBAAuB,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EACrI,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACnB,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uCAAuC,EAAE,IAAI,EAAE,6BAA6B,EAAE,CAAC,CAAC;YAClJ,MAAM,MAAM,GAAG,uBAAuB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/G,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1D,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * VOICE MODE, PHASE 1 (program DES-VOICE §3): speech to text on THIS machine.
3
+ *
4
+ * Studio records the person's speech in the browser, encodes it as a 16 kHz mono WAV, and posts it to
5
+ * `POST /voice/transcribe`. Crew hands the bytes to whisper.cpp's CLI on stdin (`-f -`) and answers with the
6
+ * text. The audio is held in memory for that one call and dropped: it is never written to disk, never kept with
7
+ * a run, never sent off the machine.
8
+ *
9
+ * Two local pieces, each said plainly in `GET /voice/status`:
10
+ * - the whisper.cpp CLI (`whisper-cli`): found on PATH, or named by `WICKED_CREW_WHISPER_BIN`. Crew does not
11
+ * install it; the status names the install command for this platform.
12
+ * - one model file (`ggml-base.en.bin`, 142 MiB): downloaded ONLY when the person consents
13
+ * (`POST /voice/model {consent: true}`), checked against its published SHA-1, kept in the voice cache dir
14
+ * (`WICKED_CREW_VOICE_DIR`, default the OS cache dir). Not under the state home: the worker fence classifies
15
+ * every top-level entry there, and a model directory is not one of them.
16
+ *
17
+ * One transcription runs at a time and one may wait; a third is refused with 429 `voice_busy` (a streaming
18
+ * partial just skips that beat).
19
+ */
20
+ import { type ChildProcess, type SpawnOptions } from 'node:child_process';
21
+ /** The one model phase 1 ships with. Published by whisper.cpp (models/README.md: 142 MiB, this SHA-1). */
22
+ export declare const VOICE_MODEL: Readonly<VoiceModel>;
23
+ /** A WAV over this is refused (about 4 minutes of 16 kHz mono 16-bit speech). */
24
+ export declare const VOICE_MAX_AUDIO_BYTES: number;
25
+ /** One transcription that runs longer than this is killed and answered 504. */
26
+ export declare const TRANSCRIBE_TIMEOUT_MS = 60000;
27
+ /** Threads whisper.cpp may use (the host runs seats and checks too). */
28
+ export declare const TRANSCRIBE_THREADS = 4;
29
+ export type VoiceErrorCode = 'voice_engine_missing' | 'voice_engine_outdated' | 'voice_model_missing' | 'voice_audio_invalid' | 'voice_audio_too_large' | 'voice_busy' | 'voice_timeout' | 'voice_failed' | 'voice_consent_required' | 'voice_download_running' | 'voice_download_failed';
30
+ export declare class VoiceError extends Error {
31
+ readonly status: number;
32
+ readonly code: VoiceErrorCode;
33
+ constructor(status: number, code: VoiceErrorCode, message: string);
34
+ body(): {
35
+ error: string;
36
+ code: VoiceErrorCode;
37
+ };
38
+ }
39
+ export interface VoiceDownloadState {
40
+ state: 'running' | 'failed';
41
+ receivedBytes: number;
42
+ totalBytes: number | null;
43
+ startedAt: string;
44
+ error: string | null;
45
+ }
46
+ /** `GET /voice/status` (api-types `VoiceStatus`). */
47
+ export interface VoiceStatusBody {
48
+ /** Audio is transcribed on this machine; nothing is sent anywhere. Always true in phase 1. */
49
+ local: true;
50
+ /** Transcription can run now: the engine and the model are both here. */
51
+ ready: boolean;
52
+ engine: {
53
+ name: 'whisper.cpp';
54
+ found: boolean;
55
+ /** Where it was found (a path); null when not found. */
56
+ path: string | null;
57
+ /** How to install (or upgrade) it on this platform, when it is missing or too old. */
58
+ install: string | null;
59
+ /** The version it reports (`--version`); null when not found or when it reports none (too old). */
60
+ version: string | null;
61
+ /** It is new enough: a stdin transcription prints its text to stdout and writes no file. */
62
+ supported: boolean;
63
+ };
64
+ model: {
65
+ name: string;
66
+ present: boolean;
67
+ bytes: number | null;
68
+ approxBytes: number;
69
+ source: string;
70
+ download: VoiceDownloadState | null;
71
+ };
72
+ }
73
+ /** The injectable edges (tests stub every one). */
74
+ /** How whisper.cpp is started (tests give a stand-in). */
75
+ export type VoiceSpawn = (command: string, args: readonly string[], options: SpawnOptions) => ChildProcess;
76
+ export interface VoiceDeps {
77
+ /** The voice cache dir (the model lives here). */
78
+ dir: string;
79
+ /** The whisper.cpp CLI, or null to look it up on PATH. */
80
+ bin?: string | null;
81
+ env?: NodeJS.ProcessEnv;
82
+ platform?: NodeJS.Platform;
83
+ fetch?: typeof fetch;
84
+ spawn?: VoiceSpawn;
85
+ exists?: (p: string) => boolean;
86
+ timeoutMs?: number;
87
+ /** The model to fetch and use (tests give their own checksum). */
88
+ model?: VoiceModel;
89
+ /** What `<bin> --version` prints (tests stand it in); null when it fails. */
90
+ versionOf?: (bin: string) => string | null;
91
+ }
92
+ export interface VoiceModel {
93
+ name: string;
94
+ file: string;
95
+ url: string;
96
+ sha1: string;
97
+ approxBytes: number;
98
+ source: string;
99
+ }
100
+ /** The OS cache dir for crew's voice files (`WICKED_CREW_VOICE_DIR` wins). */
101
+ export declare function defaultVoiceDir(env?: NodeJS.ProcessEnv, plat?: NodeJS.Platform, home?: string): string;
102
+ /** How to install whisper.cpp here, in one line. */
103
+ export declare function installHint(plat: NodeJS.Platform): string;
104
+ /** The oldest engine voice runs: it must report `--version` (whisper.cpp 1.8.0 does not), and be at least this. */
105
+ export declare const MIN_WHISPER: readonly [1, 8, 0];
106
+ /** `whisper.cpp version: 1.9.5` → `1.9.5`; anything else → null. */
107
+ export declare function parseWhisperVersion(out: string | null): string | null;
108
+ /**
109
+ * Is this engine safe to hand audio on stdin? From whisper.cpp 1.8.0 a stdin run (`-f -`) writes its `-otxt` output
110
+ * to stdout; 1.7.x writes it to a FILE named `-.txt` in the working directory, which would keep a transcript on disk.
111
+ * 1.8.0 itself cannot say its version, so voice asks for an engine that reports one (`--version`) at 1.8.0 or later,
112
+ * and refuses the rest before any audio is sent.
113
+ */
114
+ export declare function whisperSupported(version: string | null): boolean;
115
+ /** How to upgrade whisper.cpp here, in one line. */
116
+ export declare function upgradeHint(plat: NodeJS.Platform): string;
117
+ /** Find the whisper.cpp CLI: `WICKED_CREW_WHISPER_BIN`, else `whisper-cli` (or the older `whisper-cpp`) on PATH. */
118
+ export declare function findWhisper(env: NodeJS.ProcessEnv, plat: NodeJS.Platform, exists: (p: string) => boolean): string | null;
119
+ /**
120
+ * Is it the WAV studio sends: RIFF/WAVE with a PCM `fmt ` chunk (16 kHz, mono, 16-bit) and a non-empty `data`
121
+ * chunk, every chunk inside the buffer? Anything else is refused before the engine is started.
122
+ */
123
+ export declare function wavProblem(buf: Buffer): string | null;
124
+ /** Is it a WAV this route takes? */
125
+ export declare function isWav(buf: Buffer): boolean;
126
+ /** whisper.cpp's plain-text output as one line: no timestamps, no non-speech tags ([BLANK_AUDIO], (music)). */
127
+ export declare function cleanTranscript(raw: string): string;
128
+ export declare class VoiceService {
129
+ private readonly deps;
130
+ private readonly env;
131
+ private readonly plat;
132
+ private readonly exists;
133
+ private readonly fetchImpl;
134
+ private readonly spawnImpl;
135
+ private readonly timeoutMs;
136
+ private readonly model;
137
+ private readonly versionOf;
138
+ /** `--version` per engine path, read once. */
139
+ private readonly versions;
140
+ private download;
141
+ /** The download in flight: removal aborts it and bumps the generation, so it can never land afterwards. */
142
+ private inflight;
143
+ private gen;
144
+ /** One transcription holds the slot; one waits for it (the slot is handed over, never re-contested). */
145
+ private busy;
146
+ private waiting;
147
+ constructor(deps: VoiceDeps);
148
+ modelPath(): string;
149
+ private bin;
150
+ private engineVersion;
151
+ private tooOld;
152
+ private modelBytes;
153
+ status(): VoiceStatusBody;
154
+ /**
155
+ * Fetch the model, once, with the person's consent. Returns at once; the download runs on and
156
+ * `status().model.download` reports it. The file lands under a `.part` name, is checked against the published
157
+ * SHA-1, and only then takes its real name; a failed or mismatched download leaves nothing behind.
158
+ */
159
+ startDownload(): {
160
+ started: boolean;
161
+ };
162
+ private fetchModel;
163
+ /** Remove the model (the person's "Remove the speech model"). A download in flight is cancelled first. */
164
+ removeModel(): {
165
+ removed: boolean;
166
+ };
167
+ /** Transcribe one WAV held in memory. The bytes go to whisper.cpp on stdin and are dropped after. */
168
+ transcribe(audio: Buffer): Promise<{
169
+ text: string;
170
+ ms: number;
171
+ model: string;
172
+ }>;
173
+ /** The engine and the model, or the refusal that names the missing one. */
174
+ private ready;
175
+ private run;
176
+ }
177
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/voice/service.ts"],"names":[],"mappings":"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"}