@evalops/maestro 0.10.22 → 0.10.24

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 (387) hide show
  1. package/README.md +4 -4
  2. package/dist/agent/agent.d.ts +2 -2
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/agent.js +1 -1
  5. package/dist/agent/agent.js.map +1 -1
  6. package/dist/agent/keys.d.ts +2 -5
  7. package/dist/agent/keys.d.ts.map +1 -1
  8. package/dist/agent/keys.js +4 -5
  9. package/dist/agent/keys.js.map +1 -1
  10. package/dist/agent/modes.d.ts +2 -2
  11. package/dist/agent/modes.d.ts.map +1 -1
  12. package/dist/agent/modes.js +6 -7
  13. package/dist/agent/modes.js.map +1 -1
  14. package/dist/agent/providers/anthropic.d.ts.map +1 -1
  15. package/dist/agent/providers/anthropic.js +4 -4
  16. package/dist/agent/providers/anthropic.js.map +1 -1
  17. package/dist/agent/providers/google.js +1 -1
  18. package/dist/agent/swarm/executor.d.ts +2 -0
  19. package/dist/agent/swarm/executor.d.ts.map +1 -1
  20. package/dist/agent/swarm/executor.js +208 -35
  21. package/dist/agent/swarm/executor.js.map +1 -1
  22. package/dist/agent/swarm/types.d.ts +2 -0
  23. package/dist/agent/swarm/types.d.ts.map +1 -1
  24. package/dist/agent/swarm/types.js.map +1 -1
  25. package/dist/agent/tool-capability-types.d.ts +36 -0
  26. package/dist/agent/tool-capability-types.d.ts.map +1 -0
  27. package/dist/agent/tool-capability-types.js +2 -0
  28. package/dist/agent/tool-capability-types.js.map +1 -0
  29. package/dist/agent/transport/tool-execution-bridge.d.ts +13 -0
  30. package/dist/agent/transport/tool-execution-bridge.d.ts.map +1 -1
  31. package/dist/agent/transport/tool-execution-bridge.js +28 -15
  32. package/dist/agent/transport/tool-execution-bridge.js.map +1 -1
  33. package/dist/agent/transport/transport-utils.d.ts.map +1 -1
  34. package/dist/agent/transport/transport-utils.js +2 -3
  35. package/dist/agent/transport/transport-utils.js.map +1 -1
  36. package/dist/agent/transport.js +1 -1
  37. package/dist/agent/transport.js.map +1 -1
  38. package/dist/agent/type-guards.d.ts +1 -1
  39. package/dist/agent/type-guards.js +1 -1
  40. package/dist/agent/type-guards.js.map +1 -1
  41. package/dist/agent/types.d.ts +5 -3
  42. package/dist/agent/types.d.ts.map +1 -1
  43. package/dist/agent/types.js +2 -2
  44. package/dist/agent/types.js.map +1 -1
  45. package/dist/app-server/daemon-lifecycle-api.d.ts +31 -0
  46. package/dist/app-server/daemon-lifecycle-api.d.ts.map +1 -0
  47. package/dist/app-server/daemon-lifecycle-api.js +259 -0
  48. package/dist/app-server/daemon-lifecycle-api.js.map +1 -0
  49. package/dist/app-server/external-agent-import-api.d.ts +30 -0
  50. package/dist/app-server/external-agent-import-api.d.ts.map +1 -0
  51. package/dist/app-server/external-agent-import-api.js +553 -0
  52. package/dist/app-server/external-agent-import-api.js.map +1 -0
  53. package/dist/app-server/host-control-api.d.ts +30 -0
  54. package/dist/app-server/host-control-api.d.ts.map +1 -0
  55. package/dist/app-server/host-control-api.js +343 -0
  56. package/dist/app-server/host-control-api.js.map +1 -0
  57. package/dist/app-server/in-process-client.d.ts +2 -2
  58. package/dist/app-server/in-process-client.d.ts.map +1 -1
  59. package/dist/app-server/in-process-client.js.map +1 -1
  60. package/dist/app-server/network-governance-api.d.ts +26 -0
  61. package/dist/app-server/network-governance-api.d.ts.map +1 -0
  62. package/dist/app-server/network-governance-api.js +476 -0
  63. package/dist/app-server/network-governance-api.js.map +1 -0
  64. package/dist/app-server/plugin-bundle-api.d.ts +17 -0
  65. package/dist/app-server/plugin-bundle-api.d.ts.map +1 -0
  66. package/dist/app-server/plugin-bundle-api.js +219 -0
  67. package/dist/app-server/plugin-bundle-api.js.map +1 -0
  68. package/dist/app-server/policy-control-api.d.ts +14 -0
  69. package/dist/app-server/policy-control-api.d.ts.map +1 -0
  70. package/dist/app-server/policy-control-api.js +200 -0
  71. package/dist/app-server/policy-control-api.js.map +1 -0
  72. package/dist/app-server/protocol-modes-api.d.ts +22 -0
  73. package/dist/app-server/protocol-modes-api.d.ts.map +1 -0
  74. package/dist/app-server/protocol-modes-api.js +124 -0
  75. package/dist/app-server/protocol-modes-api.js.map +1 -0
  76. package/dist/app-server/sandbox-proof-api.d.ts +21 -0
  77. package/dist/app-server/sandbox-proof-api.d.ts.map +1 -0
  78. package/dist/app-server/sandbox-proof-api.js +127 -0
  79. package/dist/app-server/sandbox-proof-api.js.map +1 -0
  80. package/dist/app-server/session-api.d.ts +93 -3
  81. package/dist/app-server/session-api.d.ts.map +1 -1
  82. package/dist/app-server/session-api.js +706 -18
  83. package/dist/app-server/session-api.js.map +1 -1
  84. package/dist/audit/logger.d.ts +1 -1
  85. package/dist/bootstrap/auth-setup.d.ts.map +1 -1
  86. package/dist/bootstrap/auth-setup.js +17 -2
  87. package/dist/bootstrap/auth-setup.js.map +1 -1
  88. package/dist/bootstrap/model-resolution-setup.d.ts.map +1 -1
  89. package/dist/bootstrap/model-resolution-setup.js +19 -4
  90. package/dist/bootstrap/model-resolution-setup.js.map +1 -1
  91. package/dist/cli/args.d.ts +2 -2
  92. package/dist/cli/args.d.ts.map +1 -1
  93. package/dist/cli/args.js +2 -2
  94. package/dist/cli/args.js.map +1 -1
  95. package/dist/cli/commands/a2a.d.ts.map +1 -1
  96. package/dist/cli/commands/a2a.js +226 -14
  97. package/dist/cli/commands/a2a.js.map +1 -1
  98. package/dist/cli/commands/anthropic.d.ts +1 -1
  99. package/dist/cli/commands/anthropic.d.ts.map +1 -1
  100. package/dist/cli/commands/anthropic.js +3 -68
  101. package/dist/cli/commands/anthropic.js.map +1 -1
  102. package/dist/cli/commands/modes.js +1 -1
  103. package/dist/cli/commands/modes.js.map +1 -1
  104. package/dist/cli/help.d.ts.map +1 -1
  105. package/dist/cli/help.js +5 -7
  106. package/dist/cli/help.js.map +1 -1
  107. package/dist/cli/rpc-mode.d.ts +1 -1
  108. package/dist/cli/rpc-mode.js +1 -1
  109. package/dist/cli/rpc-mode.js.map +1 -1
  110. package/dist/cli/session.js +1 -1
  111. package/dist/cli/session.js.map +1 -1
  112. package/dist/cli-tui/commands/command-catalog.d.ts.map +1 -1
  113. package/dist/cli-tui/commands/command-catalog.js +7 -12
  114. package/dist/cli-tui/commands/command-catalog.js.map +1 -1
  115. package/dist/cli-tui/commands/subcommands/auth-commands.d.ts +1 -1
  116. package/dist/cli-tui/commands/subcommands/auth-commands.d.ts.map +1 -1
  117. package/dist/cli-tui/commands/subcommands/auth-commands.js +4 -12
  118. package/dist/cli-tui/commands/subcommands/auth-commands.js.map +1 -1
  119. package/dist/cli-tui/custom-editor.d.ts +1 -1
  120. package/dist/cli-tui/custom-editor.js +2 -2
  121. package/dist/cli-tui/custom-editor.js.map +1 -1
  122. package/dist/cli-tui/oauth/oauth-flow-controller.d.ts.map +1 -1
  123. package/dist/cli-tui/oauth/oauth-flow-controller.js +19 -23
  124. package/dist/cli-tui/oauth/oauth-flow-controller.js.map +1 -1
  125. package/dist/cli-tui/selectors/model-selector.d.ts.map +1 -1
  126. package/dist/cli-tui/selectors/model-selector.js +0 -1
  127. package/dist/cli-tui/selectors/model-selector.js.map +1 -1
  128. package/dist/cli-tui/selectors/oauth-selector-view.d.ts +2 -2
  129. package/dist/cli-tui/selectors/oauth-selector-view.d.ts.map +1 -1
  130. package/dist/cli-tui/selectors/oauth-selector-view.js.map +1 -1
  131. package/dist/cli-tui/selectors/oauth-selector.d.ts +2 -2
  132. package/dist/cli-tui/selectors/oauth-selector.d.ts.map +1 -1
  133. package/dist/cli-tui/selectors/oauth-selector.js +3 -4
  134. package/dist/cli-tui/selectors/oauth-selector.js.map +1 -1
  135. package/dist/cli-tui/tui-renderer/mcp-events-setup.js +1 -1
  136. package/dist/cli-tui/tui-renderer/mcp-events-setup.js.map +1 -1
  137. package/dist/cli-tui/tui-renderer.js +2 -2
  138. package/dist/cli-tui/tui-renderer.js.map +1 -1
  139. package/dist/cli-tui/utils/footer-utils.d.ts +1 -1
  140. package/dist/cli-tui/utils/footer-utils.js +1 -1
  141. package/dist/cli-tui/utils/footer-utils.js.map +1 -1
  142. package/dist/cli.js +15171 -14298
  143. package/dist/commands/prompts.d.ts +1 -1
  144. package/dist/commands/prompts.js +1 -1
  145. package/dist/commands/prompts.js.map +1 -1
  146. package/dist/config/constants.d.ts +2 -2
  147. package/dist/config/constants.d.ts.map +1 -1
  148. package/dist/config/constants.js +2 -2
  149. package/dist/config/constants.js.map +1 -1
  150. package/dist/config/index.d.ts +1 -1
  151. package/dist/config/index.js +1 -1
  152. package/dist/config/index.js.map +1 -1
  153. package/dist/config/toml-config.js +3 -3
  154. package/dist/config/toml-config.js.map +1 -1
  155. package/dist/db/client.d.ts +2 -2
  156. package/dist/db/client.js +2 -2
  157. package/dist/db/client.js.map +1 -1
  158. package/dist/db/migrate.d.ts +1 -1
  159. package/dist/db/migrate.js +1 -1
  160. package/dist/db/migrate.js.map +1 -1
  161. package/dist/db/schema.d.ts +2 -2
  162. package/dist/db/schema.js +1 -1
  163. package/dist/db/schema.js.map +1 -1
  164. package/dist/errors/index.d.ts +2 -2
  165. package/dist/errors/index.js +2 -2
  166. package/dist/errors/index.js.map +1 -1
  167. package/dist/main.d.ts +4 -5
  168. package/dist/main.d.ts.map +1 -1
  169. package/dist/main.js +17 -14
  170. package/dist/main.js.map +1 -1
  171. package/dist/mcp/config.d.ts +15 -2
  172. package/dist/mcp/config.d.ts.map +1 -1
  173. package/dist/mcp/config.js +50 -26
  174. package/dist/mcp/config.js.map +1 -1
  175. package/dist/mcp/fathom-cua.d.ts.map +1 -1
  176. package/dist/mcp/fathom-cua.js +10 -0
  177. package/dist/mcp/fathom-cua.js.map +1 -1
  178. package/dist/mcp/manager.d.ts.map +1 -1
  179. package/dist/mcp/manager.js +32 -1
  180. package/dist/mcp/manager.js.map +1 -1
  181. package/dist/mcp/tool-bridge.d.ts.map +1 -1
  182. package/dist/mcp/tool-bridge.js +12 -3
  183. package/dist/mcp/tool-bridge.js.map +1 -1
  184. package/dist/mcp/tool-capabilities.d.ts +5 -0
  185. package/dist/mcp/tool-capabilities.d.ts.map +1 -0
  186. package/dist/mcp/tool-capabilities.js +271 -0
  187. package/dist/mcp/tool-capabilities.js.map +1 -0
  188. package/dist/mcp/types.d.ts +6 -1
  189. package/dist/mcp/types.d.ts.map +1 -1
  190. package/dist/mcp/types.js.map +1 -1
  191. package/dist/models/config-loader.d.ts +1 -1
  192. package/dist/models/factory-integration.d.ts +1 -1
  193. package/dist/models/factory-integration.js +1 -1
  194. package/dist/models/factory-integration.js.map +1 -1
  195. package/dist/node_modules/@evalops/contracts/dist/artifacts.d.ts +58 -0
  196. package/dist/node_modules/@evalops/contracts/dist/artifacts.d.ts.map +1 -0
  197. package/dist/node_modules/@evalops/contracts/dist/artifacts.js +191 -0
  198. package/dist/node_modules/@evalops/contracts/dist/artifacts.js.map +1 -0
  199. package/dist/node_modules/@evalops/contracts/dist/headless-protocol-schemas.generated.d.ts +10 -10
  200. package/dist/node_modules/@evalops/contracts/dist/index.d.ts +4 -3
  201. package/dist/node_modules/@evalops/contracts/dist/index.d.ts.map +1 -1
  202. package/dist/node_modules/@evalops/contracts/dist/index.js +3 -2
  203. package/dist/node_modules/@evalops/contracts/dist/index.js.map +1 -1
  204. package/dist/node_modules/@evalops/contracts/dist/maestro-app-server.d.ts +1182 -14
  205. package/dist/node_modules/@evalops/contracts/dist/maestro-app-server.d.ts.map +1 -1
  206. package/dist/node_modules/@evalops/contracts/dist/maestro-app-server.js +450 -1
  207. package/dist/node_modules/@evalops/contracts/dist/maestro-app-server.js.map +1 -1
  208. package/dist/node_modules/@evalops/contracts/dist/runtime-app-server.d.ts +1 -1
  209. package/dist/node_modules/@evalops/contracts/dist/runtime-server-request.d.ts +3 -3
  210. package/dist/node_modules/@evalops/contracts/package.json +1 -1
  211. package/dist/node_modules/@evalops/tui/package.json +1 -1
  212. package/dist/oauth/connectors.d.ts +2 -2
  213. package/dist/oauth/connectors.d.ts.map +1 -1
  214. package/dist/oauth/connectors.js +3 -5
  215. package/dist/oauth/connectors.js.map +1 -1
  216. package/dist/oauth/github-copilot.d.ts +1 -1
  217. package/dist/oauth/github-copilot.js +1 -1
  218. package/dist/oauth/github-copilot.js.map +1 -1
  219. package/dist/oauth/index.d.ts +10 -8
  220. package/dist/oauth/index.d.ts.map +1 -1
  221. package/dist/oauth/index.js +54 -31
  222. package/dist/oauth/index.js.map +1 -1
  223. package/dist/oauth/openai.d.ts +1 -1
  224. package/dist/oauth/openai.js +2 -2
  225. package/dist/oauth/openai.js.map +1 -1
  226. package/dist/platform/a2a-completion-audit.d.ts +41 -0
  227. package/dist/platform/a2a-completion-audit.d.ts.map +1 -0
  228. package/dist/platform/a2a-completion-audit.js +177 -0
  229. package/dist/platform/a2a-completion-audit.js.map +1 -0
  230. package/dist/platform/a2a-task-ledger.d.ts.map +1 -1
  231. package/dist/platform/a2a-task-ledger.js +17 -0
  232. package/dist/platform/a2a-task-ledger.js.map +1 -1
  233. package/dist/platform/a2a-telemetry-inspect.d.ts +58 -0
  234. package/dist/platform/a2a-telemetry-inspect.d.ts.map +1 -0
  235. package/dist/platform/a2a-telemetry-inspect.js +224 -0
  236. package/dist/platform/a2a-telemetry-inspect.js.map +1 -0
  237. package/dist/platform/agent-registry-client.d.ts +8 -0
  238. package/dist/platform/agent-registry-client.d.ts.map +1 -1
  239. package/dist/platform/agent-registry-client.js +9 -1
  240. package/dist/platform/agent-registry-client.js.map +1 -1
  241. package/dist/providers/api-keys.d.ts +2 -2
  242. package/dist/providers/api-keys.js +2 -2
  243. package/dist/providers/api-keys.js.map +1 -1
  244. package/dist/providers/auth.d.ts +3 -6
  245. package/dist/providers/auth.d.ts.map +1 -1
  246. package/dist/providers/auth.js +1 -40
  247. package/dist/providers/auth.js.map +1 -1
  248. package/dist/rpc/index.d.ts +2 -2
  249. package/dist/rpc/index.js +2 -2
  250. package/dist/rpc/index.js.map +1 -1
  251. package/dist/rpc/rpc-types.d.ts +1 -1
  252. package/dist/rpc/rpc-types.js +1 -1
  253. package/dist/rpc/rpc-types.js.map +1 -1
  254. package/dist/safety/nested-agent-guard.js +1 -1
  255. package/dist/safety/nested-agent-guard.js.map +1 -1
  256. package/dist/safety/policy.d.ts +2 -2
  257. package/dist/safety/policy.js +2 -2
  258. package/dist/safety/policy.js.map +1 -1
  259. package/dist/safety/validators/network-policy-validator.d.ts +8 -0
  260. package/dist/safety/validators/network-policy-validator.d.ts.map +1 -1
  261. package/dist/safety/validators/network-policy-validator.js +29 -4
  262. package/dist/safety/validators/network-policy-validator.js.map +1 -1
  263. package/dist/sandbox/local-sandbox.d.ts +1 -1
  264. package/dist/sandbox/local-sandbox.js +1 -1
  265. package/dist/sandbox/local-sandbox.js.map +1 -1
  266. package/dist/server/app-context.d.ts +2 -0
  267. package/dist/server/app-context.d.ts.map +1 -1
  268. package/dist/server/app-context.js.map +1 -1
  269. package/dist/server/handlers/attachments.d.ts.map +1 -1
  270. package/dist/server/handlers/attachments.js +1 -0
  271. package/dist/server/handlers/attachments.js.map +1 -1
  272. package/dist/server/handlers/models.d.ts.map +1 -1
  273. package/dist/server/handlers/models.js +3 -1
  274. package/dist/server/handlers/models.js.map +1 -1
  275. package/dist/server/handlers/session-artifacts.d.ts.map +1 -1
  276. package/dist/server/handlers/session-artifacts.js +13 -74
  277. package/dist/server/handlers/session-artifacts.js.map +1 -1
  278. package/dist/server/handlers/session-attachments.d.ts.map +1 -1
  279. package/dist/server/handlers/session-attachments.js +2 -0
  280. package/dist/server/handlers/session-attachments.js.map +1 -1
  281. package/dist/server/handlers/sessions.js +1 -1
  282. package/dist/server/handlers/sessions.js.map +1 -1
  283. package/dist/server/handlers/status.d.ts +2 -0
  284. package/dist/server/handlers/status.d.ts.map +1 -1
  285. package/dist/server/handlers/status.js +3 -2
  286. package/dist/server/handlers/status.js.map +1 -1
  287. package/dist/server/headless-runtime-service.d.ts.map +1 -1
  288. package/dist/server/headless-runtime-service.js +32 -3
  289. package/dist/server/headless-runtime-service.js.map +1 -1
  290. package/dist/server/hosted-session-manager.d.ts +2 -0
  291. package/dist/server/hosted-session-manager.d.ts.map +1 -1
  292. package/dist/server/hosted-session-manager.js +9 -0
  293. package/dist/server/hosted-session-manager.js.map +1 -1
  294. package/dist/server/model-selection.d.ts.map +1 -1
  295. package/dist/server/model-selection.js +9 -1
  296. package/dist/server/model-selection.js.map +1 -1
  297. package/dist/server/rate-limiter.d.ts +1 -1
  298. package/dist/server/rate-limiter.js +1 -1
  299. package/dist/server/rate-limiter.js.map +1 -1
  300. package/dist/server/router.d.ts +2 -2
  301. package/dist/server/router.js.map +1 -1
  302. package/dist/server/session-serialization.d.ts +9 -9
  303. package/dist/server/session-serialization.js +15 -15
  304. package/dist/server/session-serialization.js.map +1 -1
  305. package/dist/session/manager.d.ts +5 -0
  306. package/dist/session/manager.d.ts.map +1 -1
  307. package/dist/session/manager.js +56 -8
  308. package/dist/session/manager.js.map +1 -1
  309. package/dist/session/session-catalog.d.ts +2 -0
  310. package/dist/session/session-catalog.d.ts.map +1 -1
  311. package/dist/session/session-catalog.js +6 -0
  312. package/dist/session/session-catalog.js.map +1 -1
  313. package/dist/session/session-context.d.ts +2 -0
  314. package/dist/session/session-context.d.ts.map +1 -1
  315. package/dist/session/session-context.js +15 -0
  316. package/dist/session/session-context.js.map +1 -1
  317. package/dist/session/types.d.ts +7 -0
  318. package/dist/session/types.d.ts.map +1 -1
  319. package/dist/session/types.js.map +1 -1
  320. package/dist/session/wire-format.generated.d.ts +1 -0
  321. package/dist/session/wire-format.generated.d.ts.map +1 -1
  322. package/dist/session/wire-format.generated.js +1 -0
  323. package/dist/session/wire-format.generated.js.map +1 -1
  324. package/dist/shared-memory/contract.d.ts +4 -4
  325. package/dist/shared-memory/contract.js +2 -2
  326. package/dist/shared-memory/contract.js.map +1 -1
  327. package/dist/telemetry/index.d.ts +2 -2
  328. package/dist/telemetry/index.d.ts.map +1 -1
  329. package/dist/telemetry/index.js +2 -2
  330. package/dist/telemetry/index.js.map +1 -1
  331. package/dist/telemetry/maestro-event-bus.d.ts +57 -0
  332. package/dist/telemetry/maestro-event-bus.d.ts.map +1 -1
  333. package/dist/telemetry/maestro-event-bus.js +59 -1
  334. package/dist/telemetry/maestro-event-bus.js.map +1 -1
  335. package/dist/telemetry/maestro-event-catalog.d.ts +17 -1
  336. package/dist/telemetry/maestro-event-catalog.d.ts.map +1 -1
  337. package/dist/telemetry/maestro-event-catalog.js +24 -0
  338. package/dist/telemetry/maestro-event-catalog.js.map +1 -1
  339. package/dist/telemetry/mcp-beacon.d.ts +2 -0
  340. package/dist/telemetry/mcp-beacon.d.ts.map +1 -1
  341. package/dist/telemetry/mcp-beacon.js +15 -0
  342. package/dist/telemetry/mcp-beacon.js.map +1 -1
  343. package/dist/telemetry/metrics.d.ts +62 -0
  344. package/dist/telemetry/metrics.d.ts.map +1 -1
  345. package/dist/telemetry/metrics.js +84 -0
  346. package/dist/telemetry/metrics.js.map +1 -1
  347. package/dist/telemetry.d.ts +44 -0
  348. package/dist/telemetry.d.ts.map +1 -1
  349. package/dist/telemetry.js +84 -2
  350. package/dist/telemetry.js.map +1 -1
  351. package/dist/theme/theme-loader.js +2 -2
  352. package/dist/theme/theme-loader.js.map +1 -1
  353. package/dist/theme/theme-schema.json +2 -2
  354. package/dist/theme/theme.d.ts +1 -1
  355. package/dist/theme/theme.js.map +1 -1
  356. package/dist/tools/background/task-types.d.ts +1 -1
  357. package/dist/tools/extract-document.d.ts +1 -0
  358. package/dist/tools/extract-document.d.ts.map +1 -1
  359. package/dist/tools/extract-document.js +2 -1
  360. package/dist/tools/extract-document.js.map +1 -1
  361. package/dist/tools/index.d.ts +55 -55
  362. package/dist/tools/index.js +1 -1
  363. package/dist/tools/index.js.map +1 -1
  364. package/dist/tools/tool-dsl.d.ts +1 -1
  365. package/dist/tools/tool-dsl.js +1 -1
  366. package/dist/tools/tool-dsl.js.map +1 -1
  367. package/dist/utils/document-extractor.d.ts +1 -0
  368. package/dist/utils/document-extractor.d.ts.map +1 -1
  369. package/dist/utils/document-extractor.js +320 -40
  370. package/dist/utils/document-extractor.js.map +1 -1
  371. package/dist/utils/logger.d.ts +1 -1
  372. package/dist/utils/logger.js +1 -1
  373. package/dist/utils/logger.js.map +1 -1
  374. package/dist/version.json +2 -2
  375. package/dist/web-server.d.ts +1 -1
  376. package/dist/web-server.d.ts.map +1 -1
  377. package/dist/web-server.js +12 -8
  378. package/dist/web-server.js.map +1 -1
  379. package/package.json +4 -2
  380. package/dist/oauth/anthropic.d.ts +0 -17
  381. package/dist/oauth/anthropic.d.ts.map +0 -1
  382. package/dist/oauth/anthropic.js +0 -81
  383. package/dist/oauth/anthropic.js.map +0 -1
  384. package/dist/providers/anthropic-auth.d.ts +0 -75
  385. package/dist/providers/anthropic-auth.d.ts.map +0 -1
  386. package/dist/providers/anthropic-auth.js +0 -221
  387. package/dist/providers/anthropic-auth.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/server/handlers/attachments.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extractDocumentText } from \"../../utils/document-extractor.js\";\nimport {\n\treadJsonBody,\n\trespondWithApiError,\n\tsendJson,\n} from \"../server-utils.js\";\n\ninterface ExtractAttachmentBody {\n\tfileName: string;\n\tmimeType?: string;\n\tcontentBase64: string;\n\tmaxChars?: number;\n}\n\nfunction normalizeBase64(input: string): string {\n\treturn input.replace(/\\s+/g, \"\");\n}\n\nfunction isValidBase64(input: string): boolean {\n\tif (!input) return false;\n\tconst mod = input.length % 4;\n\tif (mod === 1) return false;\n\treturn /^[A-Za-z0-9+/]*={0,2}$/.test(input);\n}\n\nexport async function handleAttachmentExtract(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tcors: Record<string, string>,\n) {\n\ttry {\n\t\tif (req.method !== \"POST\") {\n\t\t\tsendJson(res, 405, { error: \"Method not allowed\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\t// Allow large JSON payloads (base64 content); enforce actual byte limits in extractor.\n\t\tconst body = await readJsonBody<Partial<ExtractAttachmentBody>>(\n\t\t\treq,\n\t\t\t80 * 1024 * 1024,\n\t\t);\n\n\t\tconst fileName =\n\t\t\ttypeof body.fileName === \"string\" ? body.fileName.trim() : \"\";\n\t\tconst mimeType =\n\t\t\ttypeof body.mimeType === \"string\" ? body.mimeType.trim() : undefined;\n\t\tconst contentBase64 =\n\t\t\ttypeof body.contentBase64 === \"string\" ? body.contentBase64.trim() : \"\";\n\t\tconst maxChars =\n\t\t\ttypeof body.maxChars === \"number\" && Number.isFinite(body.maxChars)\n\t\t\t\t? body.maxChars\n\t\t\t\t: undefined;\n\n\t\tif (!fileName) {\n\t\t\tsendJson(res, 400, { error: \"fileName is required\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tif (!contentBase64) {\n\t\t\tsendJson(res, 400, { error: \"contentBase64 is required\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalized = normalizeBase64(contentBase64);\n\t\tif (!isValidBase64(normalized)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid base64 content\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst buffer = Buffer.from(normalized, \"base64\");\n\n\t\tconst extracted = await extractDocumentText({\n\t\t\tbuffer,\n\t\t\tfileName,\n\t\t\tmimeType,\n\t\t\tmaxChars,\n\t\t});\n\n\t\tif (!extracted.extractedText && extracted.format === \"unknown\") {\n\t\t\tsendJson(res, 400, { error: \"Unsupported document format\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tfileName,\n\t\t\t\tformat: extracted.format,\n\t\t\t\tsize: extracted.sizeBytes,\n\t\t\t\ttruncated: extracted.truncated,\n\t\t\t\textractedText: extracted.extractedText,\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (error) {\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t}\n}\n"]}
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/server/handlers/attachments.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extractDocumentText } from \"../../utils/document-extractor.js\";\nimport {\n\treadJsonBody,\n\trespondWithApiError,\n\tsendJson,\n} from \"../server-utils.js\";\n\ninterface ExtractAttachmentBody {\n\tfileName: string;\n\tmimeType?: string;\n\tcontentBase64: string;\n\tmaxChars?: number;\n}\n\nfunction normalizeBase64(input: string): string {\n\treturn input.replace(/\\s+/g, \"\");\n}\n\nfunction isValidBase64(input: string): boolean {\n\tif (!input) return false;\n\tconst mod = input.length % 4;\n\tif (mod === 1) return false;\n\treturn /^[A-Za-z0-9+/]*={0,2}$/.test(input);\n}\n\nexport async function handleAttachmentExtract(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tcors: Record<string, string>,\n) {\n\ttry {\n\t\tif (req.method !== \"POST\") {\n\t\t\tsendJson(res, 405, { error: \"Method not allowed\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\t// Allow large JSON payloads (base64 content); enforce actual byte limits in extractor.\n\t\tconst body = await readJsonBody<Partial<ExtractAttachmentBody>>(\n\t\t\treq,\n\t\t\t80 * 1024 * 1024,\n\t\t);\n\n\t\tconst fileName =\n\t\t\ttypeof body.fileName === \"string\" ? body.fileName.trim() : \"\";\n\t\tconst mimeType =\n\t\t\ttypeof body.mimeType === \"string\" ? body.mimeType.trim() : undefined;\n\t\tconst contentBase64 =\n\t\t\ttypeof body.contentBase64 === \"string\" ? body.contentBase64.trim() : \"\";\n\t\tconst maxChars =\n\t\t\ttypeof body.maxChars === \"number\" && Number.isFinite(body.maxChars)\n\t\t\t\t? body.maxChars\n\t\t\t\t: undefined;\n\n\t\tif (!fileName) {\n\t\t\tsendJson(res, 400, { error: \"fileName is required\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tif (!contentBase64) {\n\t\t\tsendJson(res, 400, { error: \"contentBase64 is required\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalized = normalizeBase64(contentBase64);\n\t\tif (!isValidBase64(normalized)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid base64 content\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst buffer = Buffer.from(normalized, \"base64\");\n\n\t\tconst extracted = await extractDocumentText({\n\t\t\tbuffer,\n\t\t\tfileName,\n\t\t\tmimeType,\n\t\t\tmaxChars,\n\t\t});\n\n\t\tif (!extracted.extractedText && extracted.format === \"unknown\") {\n\t\t\tsendJson(res, 400, { error: \"Unsupported document format\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tfileName,\n\t\t\t\tformat: extracted.format,\n\t\t\t\textractor: extracted.extractor,\n\t\t\t\tsize: extracted.sizeBytes,\n\t\t\t\ttruncated: extracted.truncated,\n\t\t\t\textractedText: extracted.extractedText,\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (error) {\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAa1D,wBAAsB,YAAY,CACjC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAoB5B;AAgCD,wBAAsB,WAAW,CAChC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,gBAAgB,iBAwEzB"}
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAa1D,wBAAsB,YAAY,CACjC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAoB5B;AAgCD,wBAAsB,WAAW,CAChC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,gBAAgB,iBA0EzB"}
@@ -76,7 +76,9 @@ export async function handleModel(req, res, context) {
76
76
  }, cors, req);
77
77
  return;
78
78
  }
79
- await ensureCredential(registeredModel.provider);
79
+ if (registeredModel.api !== "openai-codex-app-server") {
80
+ await ensureCredential(registeredModel.provider);
81
+ }
80
82
  if (onSelect)
81
83
  onSelect(registeredModel);
82
84
  respondWithModel(res, registeredModel, cors, req);
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../src/server/handlers/models.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { getRegisteredModels } from \"../../models/registry.js\";\nimport type { RegisteredModel } from \"../../models/registry.js\";\nimport { evaluateModelPolicy } from \"../../services/workspace-config/policy.js\";\nimport type { WebServerContext } from \"../app-context.js\";\nimport {\n\tdetermineModelSelection,\n\tgetRegisteredModelOrThrow,\n} from \"../model-selection.js\";\nimport { getWorkspaceConfigContext } from \"../request-context.js\";\nimport { respondWithApiError, sendJson } from \"../server-utils.js\";\nimport {\n\ttype ModelSetInput,\n\tModelSetSchema,\n\tparseAndValidateJson,\n} from \"../validation.js\";\n\nexport async function handleModels(\n\t_req: IncomingMessage,\n\tres: ServerResponse,\n\tcors: Record<string, string>,\n) {\n\tconst models = getRegisteredModels();\n\tconst modelList = models.map((m) => ({\n\t\tid: m.id,\n\t\tprovider: m.provider,\n\t\tname: m.name || m.id,\n\t\tapi: m.api,\n\t\tcontextWindow: m.contextWindow,\n\t\tmaxTokens: m.maxTokens,\n\t\tcost: m.cost,\n\t\tcapabilities: {\n\t\t\tstreaming: true,\n\t\t\ttools: true,\n\t\t\tvision: m.input?.includes(\"image\") || false,\n\t\t\treasoning: m.reasoning || false,\n\t\t},\n\t}));\n\n\tsendJson(res, 200, { models: modelList }, cors, _req);\n}\n\nfunction respondWithModel(\n\tres: ServerResponse,\n\tmodel: RegisteredModel,\n\tcors: Record<string, string>,\n\treq?: IncomingMessage,\n) {\n\tsendJson(\n\t\tres,\n\t\t200,\n\t\t{\n\t\t\tid: model.id,\n\t\t\tprovider: model.provider,\n\t\t\tname: model.name || model.id,\n\t\t\tapi: model.api,\n\t\t\tcontextWindow: model.contextWindow,\n\t\t\tmaxTokens: model.maxTokens,\n\t\t\tcost: model.cost,\n\t\t\tcapabilities: {\n\t\t\t\tstreaming: true,\n\t\t\t\ttools: true,\n\t\t\t\tvision: model.input?.includes(\"image\") || false,\n\t\t\t\treasoning: model.reasoning || false,\n\t\t\t},\n\t\t\treasoning: model.reasoning,\n\t\t},\n\t\tcors,\n\t\treq,\n\t);\n}\n\nexport async function handleModel(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tcontext: WebServerContext,\n) {\n\tconst {\n\t\tcorsHeaders: cors,\n\t\tgetCurrentSelection,\n\t\tensureCredential,\n\t\tsetModelSelection: onSelect,\n\t} = context;\n\tconst defaults = getCurrentSelection();\n\n\tif (req.method === \"GET\") {\n\t\tconst models = getRegisteredModels();\n\t\tconst active =\n\t\t\tmodels.find(\n\t\t\t\t(entry) =>\n\t\t\t\t\tentry.provider === defaults.provider && entry.id === defaults.modelId,\n\t\t\t) ?? models[0];\n\t\tif (!active) {\n\t\t\tres.writeHead(404, {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...cors,\n\t\t\t});\n\t\t\tres.end(JSON.stringify({ error: \"No models registered\" }));\n\t\t\treturn;\n\t\t}\n\t\trespondWithModel(res, active, cors, req);\n\t\treturn;\n\t}\n\n\tif (req.method === \"POST\") {\n\t\t// Remove try/catch, let router handle it\n\t\tconst payload = await parseAndValidateJson<ModelSetInput>(\n\t\t\treq,\n\t\t\tModelSetSchema,\n\t\t);\n\t\tconst modelInput = payload.model.trim();\n\n\t\tconst selection = determineModelSelection(\n\t\t\tmodelInput,\n\t\t\tdefaults.provider,\n\t\t\tdefaults.modelId,\n\t\t);\n\t\tconst registeredModel = getRegisteredModelOrThrow(selection);\n\t\tconst violation = evaluateModelPolicy(getWorkspaceConfigContext()?.config, {\n\t\t\tprovider: registeredModel.provider,\n\t\t\tmodelId: registeredModel.id,\n\t\t});\n\t\tif (violation) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t403,\n\t\t\t\t{\n\t\t\t\t\terror: violation.message,\n\t\t\t\t\tcode: violation.code,\n\t\t\t\t\tworkspaceId: violation.workspaceId,\n\t\t\t\t},\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tawait ensureCredential(registeredModel.provider);\n\t\tif (onSelect) onSelect(registeredModel);\n\t\trespondWithModel(res, registeredModel, cors, req);\n\t\treturn;\n\t}\n\n\tres.writeHead(405, {\n\t\t\"Content-Type\": \"application/json\",\n\t\t...cors,\n\t});\n\tres.end(JSON.stringify({ error: \"Method not allowed\" }));\n}\n"]}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../src/server/handlers/models.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAEhF,OAAO,EACN,uBAAuB,EACvB,yBAAyB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAuB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAEN,cAAc,EACd,oBAAoB,GACpB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,IAAqB,EACrB,GAAmB,EACnB,IAA4B;IAE5B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpC,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE;QACpB,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,aAAa,EAAE,CAAC,CAAC,aAAa;QAC9B,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,YAAY,EAAE;YACb,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK;YAC3C,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,KAAK;SAC/B;KACD,CAAC,CAAC,CAAC;IAEJ,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,gBAAgB,CACxB,GAAmB,EACnB,KAAsB,EACtB,IAA4B,EAC5B,GAAqB;IAErB,QAAQ,CACP,GAAG,EACH,GAAG,EACH;QACC,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE;QAC5B,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,YAAY,EAAE;YACb,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK;YAC/C,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK;SACnC;QACD,SAAS,EAAE,KAAK,CAAC,SAAS;KAC1B,EACD,IAAI,EACJ,GAAG,CACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,GAAoB,EACpB,GAAmB,EACnB,OAAyB;IAEzB,MAAM,EACL,WAAW,EAAE,IAAI,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EAAE,QAAQ,GAC3B,GAAG,OAAO,CAAC;IACZ,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IAEvC,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACrC,MAAM,MAAM,GACX,MAAM,CAAC,IAAI,CACV,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,OAAO,CACtE,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;QAChB,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;gBAClB,cAAc,EAAE,kBAAkB;gBAClC,GAAG,IAAI;aACP,CAAC,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC;YAC3D,OAAO;QACR,CAAC;QACD,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QACzC,OAAO;IACR,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC3B,yCAAyC;QACzC,MAAM,OAAO,GAAG,MAAM,oBAAoB,CACzC,GAAG,EACH,cAAc,CACd,CAAC;QACF,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAExC,MAAM,SAAS,GAAG,uBAAuB,CACxC,UAAU,EACV,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,OAAO,CAChB,CAAC;QACF,MAAM,eAAe,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,mBAAmB,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE;YAC1E,QAAQ,EAAE,eAAe,CAAC,QAAQ;YAClC,OAAO,EAAE,eAAe,CAAC,EAAE;SAC3B,CAAC,CAAC;QACH,IAAI,SAAS,EAAE,CAAC;YACf,QAAQ,CACP,GAAG,EACH,GAAG,EACH;gBACC,KAAK,EAAE,SAAS,CAAC,OAAO;gBACxB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,WAAW,EAAE,SAAS,CAAC,WAAW;aAClC,EACD,IAAI,EACJ,GAAG,CACH,CAAC;YACF,OAAO;QACR,CAAC;QACD,IAAI,eAAe,CAAC,GAAG,KAAK,yBAAyB,EAAE,CAAC;YACvD,MAAM,gBAAgB,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,QAAQ;YAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;QACxC,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAClD,OAAO;IACR,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QAClB,cAAc,EAAE,kBAAkB;QAClC,GAAG,IAAI;KACP,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { getRegisteredModels } from \"../../models/registry.js\";\nimport type { RegisteredModel } from \"../../models/registry.js\";\nimport { evaluateModelPolicy } from \"../../services/workspace-config/policy.js\";\nimport type { WebServerContext } from \"../app-context.js\";\nimport {\n\tdetermineModelSelection,\n\tgetRegisteredModelOrThrow,\n} from \"../model-selection.js\";\nimport { getWorkspaceConfigContext } from \"../request-context.js\";\nimport { respondWithApiError, sendJson } from \"../server-utils.js\";\nimport {\n\ttype ModelSetInput,\n\tModelSetSchema,\n\tparseAndValidateJson,\n} from \"../validation.js\";\n\nexport async function handleModels(\n\t_req: IncomingMessage,\n\tres: ServerResponse,\n\tcors: Record<string, string>,\n) {\n\tconst models = getRegisteredModels();\n\tconst modelList = models.map((m) => ({\n\t\tid: m.id,\n\t\tprovider: m.provider,\n\t\tname: m.name || m.id,\n\t\tapi: m.api,\n\t\tcontextWindow: m.contextWindow,\n\t\tmaxTokens: m.maxTokens,\n\t\tcost: m.cost,\n\t\tcapabilities: {\n\t\t\tstreaming: true,\n\t\t\ttools: true,\n\t\t\tvision: m.input?.includes(\"image\") || false,\n\t\t\treasoning: m.reasoning || false,\n\t\t},\n\t}));\n\n\tsendJson(res, 200, { models: modelList }, cors, _req);\n}\n\nfunction respondWithModel(\n\tres: ServerResponse,\n\tmodel: RegisteredModel,\n\tcors: Record<string, string>,\n\treq?: IncomingMessage,\n) {\n\tsendJson(\n\t\tres,\n\t\t200,\n\t\t{\n\t\t\tid: model.id,\n\t\t\tprovider: model.provider,\n\t\t\tname: model.name || model.id,\n\t\t\tapi: model.api,\n\t\t\tcontextWindow: model.contextWindow,\n\t\t\tmaxTokens: model.maxTokens,\n\t\t\tcost: model.cost,\n\t\t\tcapabilities: {\n\t\t\t\tstreaming: true,\n\t\t\t\ttools: true,\n\t\t\t\tvision: model.input?.includes(\"image\") || false,\n\t\t\t\treasoning: model.reasoning || false,\n\t\t\t},\n\t\t\treasoning: model.reasoning,\n\t\t},\n\t\tcors,\n\t\treq,\n\t);\n}\n\nexport async function handleModel(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tcontext: WebServerContext,\n) {\n\tconst {\n\t\tcorsHeaders: cors,\n\t\tgetCurrentSelection,\n\t\tensureCredential,\n\t\tsetModelSelection: onSelect,\n\t} = context;\n\tconst defaults = getCurrentSelection();\n\n\tif (req.method === \"GET\") {\n\t\tconst models = getRegisteredModels();\n\t\tconst active =\n\t\t\tmodels.find(\n\t\t\t\t(entry) =>\n\t\t\t\t\tentry.provider === defaults.provider && entry.id === defaults.modelId,\n\t\t\t) ?? models[0];\n\t\tif (!active) {\n\t\t\tres.writeHead(404, {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...cors,\n\t\t\t});\n\t\t\tres.end(JSON.stringify({ error: \"No models registered\" }));\n\t\t\treturn;\n\t\t}\n\t\trespondWithModel(res, active, cors, req);\n\t\treturn;\n\t}\n\n\tif (req.method === \"POST\") {\n\t\t// Remove try/catch, let router handle it\n\t\tconst payload = await parseAndValidateJson<ModelSetInput>(\n\t\t\treq,\n\t\t\tModelSetSchema,\n\t\t);\n\t\tconst modelInput = payload.model.trim();\n\n\t\tconst selection = determineModelSelection(\n\t\t\tmodelInput,\n\t\t\tdefaults.provider,\n\t\t\tdefaults.modelId,\n\t\t);\n\t\tconst registeredModel = getRegisteredModelOrThrow(selection);\n\t\tconst violation = evaluateModelPolicy(getWorkspaceConfigContext()?.config, {\n\t\t\tprovider: registeredModel.provider,\n\t\t\tmodelId: registeredModel.id,\n\t\t});\n\t\tif (violation) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t403,\n\t\t\t\t{\n\t\t\t\t\terror: violation.message,\n\t\t\t\t\tcode: violation.code,\n\t\t\t\t\tworkspaceId: violation.workspaceId,\n\t\t\t\t},\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (registeredModel.api !== \"openai-codex-app-server\") {\n\t\t\tawait ensureCredential(registeredModel.provider);\n\t\t}\n\t\tif (onSelect) onSelect(registeredModel);\n\t\trespondWithModel(res, registeredModel, cors, req);\n\t\treturn;\n\t}\n\n\tres.writeHead(405, {\n\t\t\"Content-Type\": \"application/json\",\n\t\t...cors,\n\t});\n\tres.end(JSON.stringify({ error: \"Method not allowed\" }));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session-artifacts.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AA2UjE,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiC5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAsF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAuE5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA4S5B;AAED,wBAAsB,4BAA4B,CACjD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA6C5B"}
1
+ {"version":3,"file":"session-artifacts.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAuQjE,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiC5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAsF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAuE5B;AAED,wBAAsB,2BAA2B,CAChD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA4S5B;AAED,wBAAsB,4BAA4B,CACjD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAiF5B;AAED,wBAAsB,yBAAyB,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA6C5B"}
@@ -1,3 +1,4 @@
1
+ import { artifactContentsByFilename, isValidArtifactFilename, reconstructArtifactsFromMessages as reconstructArtifactStateFromMessages, } from "@evalops/contracts";
1
2
  import { lookup as lookupMimeType } from "mime-types";
2
3
  import { createLogger } from "../../utils/logger.js";
3
4
  import { ARTIFACT_ACCESS_HEADER, getArtifactAccessGrantFromRequest, getArtifactAccessTokenFromRequest, issueArtifactAccessGrant, } from "../artifact-access.js";
@@ -126,82 +127,20 @@ function injectArtifactsSnapshotRuntime(htmlContent, artifacts) {
126
127
  }
127
128
  return `${html}\n${runtime}`;
128
129
  }
129
- function asString(value) {
130
- return typeof value === "string" ? value : undefined;
131
- }
132
- function hasControlCharacter(value) {
133
- for (let index = 0; index < value.length; index += 1) {
134
- const code = value.charCodeAt(index);
135
- if (code < 32 || code === 127)
136
- return true;
137
- }
138
- return false;
139
- }
140
- function isValidArtifactFilename(filename) {
141
- return (filename.length > 0 &&
142
- !filename.includes("..") &&
143
- !filename.includes("/") &&
144
- !filename.includes("\\") &&
145
- !hasControlCharacter(filename));
146
- }
147
130
  function reconstructArtifactsFromMessages(messages) {
148
- const byFilename = new Map();
149
- for (const msg of messages) {
150
- const tools = msg.tools ?? [];
151
- for (const tool of tools) {
152
- if (tool.name !== "artifacts")
153
- continue;
154
- if (tool.status !== "completed")
155
- continue;
156
- if (tool.result && typeof tool.result === "object") {
157
- const maybeErr = tool.result;
158
- if (maybeErr.isError)
159
- continue;
160
- }
161
- const args = (tool.args && typeof tool.args === "object"
162
- ? tool.args
163
- : {});
164
- const command = asString(args.command);
165
- const filename = asString(args.filename)?.trim();
166
- if (!command || !filename)
167
- continue;
168
- if (!isValidArtifactFilename(filename))
169
- continue;
170
- if (command === "get" || command === "logs")
171
- continue;
172
- if (command === "create") {
173
- if (byFilename.has(filename))
174
- continue;
175
- byFilename.set(filename, asString(args.content) ?? "");
176
- continue;
177
- }
178
- if (command === "rewrite") {
179
- if (!byFilename.has(filename))
180
- continue;
181
- byFilename.set(filename, asString(args.content) ?? "");
182
- continue;
183
- }
184
- if (command === "update") {
185
- const current = byFilename.get(filename);
186
- if (current === undefined)
187
- continue;
188
- const oldStr = asString(args.old_str);
189
- const newStr = asString(args.new_str);
190
- if (oldStr === undefined || newStr === undefined)
191
- continue;
192
- if (oldStr.length === 0)
193
- continue;
194
- if (!current.includes(oldStr))
195
- continue;
196
- byFilename.set(filename, current.replace(oldStr, newStr));
197
- continue;
198
- }
199
- if (command === "delete") {
200
- byFilename.delete(filename);
201
- }
202
- }
131
+ const diagnostics = [];
132
+ const state = reconstructArtifactStateFromMessages(messages, {
133
+ onDiagnostic: (diagnostic) => {
134
+ diagnostics.push(diagnostic.code);
135
+ },
136
+ });
137
+ if (diagnostics.length > 0) {
138
+ logger.warn("Skipped invalid persisted artifact commands", {
139
+ count: diagnostics.length,
140
+ codes: diagnostics,
141
+ });
203
142
  }
204
- return byFilename;
143
+ return artifactContentsByFilename(state);
205
144
  }
206
145
  async function loadComposerMessages(req, sessionId) {
207
146
  const sessionManager = createWebSessionManagerForRequest(req, true);
@@ -1 +1 @@
1
- {"version":3,"file":"session-artifacts.js","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ComposerMessage } from \"@evalops/contracts\";\nimport { lookup as lookupMimeType } from \"mime-types\";\nimport { createLogger } from \"../../utils/logger.js\";\nimport {\n\tARTIFACT_ACCESS_HEADER,\n\ttype ArtifactAccessAction,\n\tgetArtifactAccessGrantFromRequest,\n\tgetArtifactAccessTokenFromRequest,\n\tissueArtifactAccessGrant,\n} from \"../artifact-access.js\";\nimport { subscribeArtifactUpdates } from \"../artifacts-live-reload.js\";\nimport {\n\tApiError,\n\tbuildContentDisposition,\n\tsendJson,\n} from \"../server-utils.js\";\nimport {\n\tcreateWebSessionManagerForRequest,\n\tresolveSessionScope,\n} from \"../session-scope.js\";\nimport { convertAppMessagesToComposer } from \"../session-serialization.js\";\n\nconst logger = createLogger(\"session-artifacts\");\nconst sessionIdPattern = /^[a-zA-Z0-9._-]+$/;\n\nfunction escapeScriptContent(code: string): string {\n\treturn code.replace(/<\\/script/gi, \"<\\\\/script\");\n}\n\nfunction injectLiveReload(html: string, eventsUrl: string): string {\n\treturn injectLiveReloadWithAuth(html, eventsUrl);\n}\n\nfunction injectLiveReloadWithAuth(\n\thtml: string,\n\teventsUrl: string,\n\taccessToken?: string | null,\n): string {\n\tconst authHeaders = accessToken\n\t\t? `{ ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: ${JSON.stringify(accessToken)} }`\n\t\t: \"undefined\";\n\tconst scriptBody = `\n\t(function() {\n\t try {\n\t const reload = () => location.reload();\n\t const connect = ${\n\t\t\t\taccessToken\n\t\t\t\t\t? `async () => {\n\t const response = await fetch(${JSON.stringify(eventsUrl)}, {\n\t headers: ${authHeaders},\n\t cache: \"no-store\",\n\t });\n\t if (!response.body) throw new Error(\"Missing response body\");\n\t const reader = response.body.getReader();\n\t const decoder = new TextDecoder();\n\t let buffer = \"\";\n\t while (true) {\n\t const { done, value } = await reader.read();\n\t if (done) break;\n\t buffer += decoder.decode(value, { stream: true });\n\t let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t while (boundary !== -1) {\n\t const chunk = buffer.slice(0, boundary);\n\t buffer = buffer.slice(boundary + 2);\n\t const dataLine = chunk\n\t .split(\"\\\\n\")\n\t .find((line) => line.startsWith(\"data:\"));\n\t if (dataLine) {\n\t reload();\n\t return;\n\t }\n\t boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t }\n\t }\n\t }`\n\t\t\t\t\t: `() => {\n\t const es = new EventSource(${JSON.stringify(eventsUrl)});\n\t es.onmessage = (e) => {\n\t try {\n\t const data = JSON.parse(e.data);\n\t if (data && data.type === \"artifact_updated\") {\n\t reload();\n\t }\n\t } catch (err) { console.error(\"[Maestro] Failed to parse live reload event:\", err); }\n\t };\n\t }`\n\t\t\t};\n\t Promise.resolve(connect()).catch((err) => {\n\t console.error(\"[Maestro] Failed to setup live reload transport:\", err);\n\t });\n\t } catch (err) { console.error(\"[Maestro] Failed to setup live reload EventSource:\", err); }\n\t})();\n\t`.trim();\n\tconst script = `<script>\\n${escapeScriptContent(scriptBody)}\\n</script>`;\n\tconst injected = `\\n${script}\\n`;\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `${injected}</body>`);\n\t}\n\treturn `${html}${injected}`;\n}\n\nfunction wrapHtmlDocument(htmlContent: string): string {\n\tconst trimmed = htmlContent.trim();\n\tconst looksLikeDocument =\n\t\t/^<!doctype/i.test(trimmed) || /<html[\\s>]/i.test(trimmed);\n\n\tif (looksLikeDocument) return trimmed;\n\n\treturn `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n${trimmed}\n </body>\n</html>`;\n}\n\nfunction injectArtifactsSnapshotRuntime(\n\thtmlContent: string,\n\tartifacts: Map<string, string>,\n): string {\n\tconst snapshot: Record<string, string> = {};\n\tfor (const [name, content] of artifacts) {\n\t\tsnapshot[name] = content;\n\t}\n\n\tconst runtime = `\n<script>\n(function() {\n try {\n window.artifacts = ${escapeScriptContent(JSON.stringify(snapshot))};\n } catch (err) {\n console.error(\"[Maestro] Failed to initialize artifacts snapshot:\", err);\n window.artifacts = {};\n }\n\n const isJson = (f) => (f || \"\").toLowerCase().endsWith(\".json\");\n\n window.listArtifacts = async () => Object.keys(window.artifacts || {});\n\n window.getArtifact = async (filename) => {\n const content = (window.artifacts || {})[filename];\n if (typeof content !== \"string\") throw new Error(\"Artifact not found: \" + filename);\n if (isJson(filename)) {\n try { return JSON.parse(content); } catch (e) { throw new Error(\"Failed to parse JSON: \" + e); }\n }\n return content;\n };\n})();\n</script>\n`.trim();\n\n\tconst html = wrapHtmlDocument(htmlContent);\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `\\n${runtime}\\n</body>`);\n\t}\n\treturn `${html}\\n${runtime}`;\n}\n\ntype ArtifactsCommand =\n\t| \"create\"\n\t| \"update\"\n\t| \"rewrite\"\n\t| \"get\"\n\t| \"delete\"\n\t| \"logs\";\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction hasControlCharacter(value: string): boolean {\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst code = value.charCodeAt(index);\n\t\tif (code < 32 || code === 127) return true;\n\t}\n\treturn false;\n}\n\nfunction isValidArtifactFilename(filename: string): boolean {\n\treturn (\n\t\tfilename.length > 0 &&\n\t\t!filename.includes(\"..\") &&\n\t\t!filename.includes(\"/\") &&\n\t\t!filename.includes(\"\\\\\") &&\n\t\t!hasControlCharacter(filename)\n\t);\n}\n\nfunction reconstructArtifactsFromMessages(\n\tmessages: ComposerMessage[],\n): Map<string, string> {\n\tconst byFilename = new Map<string, string>();\n\n\tfor (const msg of messages) {\n\t\tconst tools = msg.tools ?? [];\n\t\tfor (const tool of tools) {\n\t\t\tif (tool.name !== \"artifacts\") continue;\n\t\t\tif (tool.status !== \"completed\") continue;\n\t\t\tif (tool.result && typeof tool.result === \"object\") {\n\t\t\t\tconst maybeErr = tool.result as { isError?: boolean };\n\t\t\t\tif (maybeErr.isError) continue;\n\t\t\t}\n\n\t\t\tconst args = (\n\t\t\t\ttool.args && typeof tool.args === \"object\"\n\t\t\t\t\t? (tool.args as Record<string, unknown>)\n\t\t\t\t\t: {}\n\t\t\t) as Record<string, unknown>;\n\n\t\t\tconst command = asString(args.command) as ArtifactsCommand | undefined;\n\t\t\tconst filename = asString(args.filename)?.trim();\n\n\t\t\tif (!command || !filename) continue;\n\t\t\tif (!isValidArtifactFilename(filename)) continue;\n\t\t\tif (command === \"get\" || command === \"logs\") continue;\n\n\t\t\tif (command === \"create\") {\n\t\t\t\tif (byFilename.has(filename)) continue;\n\t\t\t\tbyFilename.set(filename, asString(args.content) ?? \"\");\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (command === \"rewrite\") {\n\t\t\t\tif (!byFilename.has(filename)) continue;\n\t\t\t\tbyFilename.set(filename, asString(args.content) ?? \"\");\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (command === \"update\") {\n\t\t\t\tconst current = byFilename.get(filename);\n\t\t\t\tif (current === undefined) continue;\n\t\t\t\tconst oldStr = asString(args.old_str);\n\t\t\t\tconst newStr = asString(args.new_str);\n\t\t\t\tif (oldStr === undefined || newStr === undefined) continue;\n\t\t\t\tif (oldStr.length === 0) continue;\n\t\t\t\tif (!current.includes(oldStr)) continue;\n\t\t\t\tbyFilename.set(filename, current.replace(oldStr, newStr));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (command === \"delete\") {\n\t\t\t\tbyFilename.delete(filename);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn byFilename;\n}\n\nasync function loadComposerMessages(\n\treq: IncomingMessage,\n\tsessionId: string,\n): Promise<ComposerMessage[]> {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\tconst session = await sessionManager.loadSession(sessionId);\n\tif (!session) {\n\t\tthrow new ApiError(404, \"Session not found\");\n\t}\n\treturn convertAppMessagesToComposer(session.messages || []);\n}\n\nfunction validateFilename(filename: string): void {\n\t// Keep this strict: no path traversal, no folder hierarchies.\n\tif (!isValidArtifactFilename(filename.trim())) {\n\t\tthrow new ApiError(400, \"Invalid filename\");\n\t}\n}\n\nfunction buildSessionArtifactFileUrl(\n\tsessionId: string,\n\tfilename: string,\n\toptions?: {\n\t\tdownload?: boolean;\n\t\traw?: boolean;\n\t\tstandalone?: boolean;\n\t},\n): string {\n\tconst path = `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}`;\n\tconst url = new URL(path, \"http://localhost\");\n\tif (options?.download) url.searchParams.set(\"download\", \"1\");\n\tif (options?.raw) url.searchParams.set(\"raw\", \"1\");\n\tif (options?.standalone) url.searchParams.set(\"standalone\", \"1\");\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactViewerUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}/view`;\n}\n\nfunction buildSessionArtifactsEventsUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\tconst url = new URL(\n\t\t`/api/sessions/${encodeURIComponent(sessionId)}/artifacts/events`,\n\t\t\"http://localhost\",\n\t);\n\turl.searchParams.set(\"filename\", filename);\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactsZipUrl(sessionId: string): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts.zip`;\n}\n\nfunction resolveArtifactAccessContext(req: IncomingMessage): {\n\taccessToken: string | null;\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>;\n} {\n\tconst grant = getArtifactAccessGrantFromRequest(req);\n\treturn {\n\t\taccessToken: grant ? getArtifactAccessTokenFromRequest(req) : null,\n\t\tgrant,\n\t};\n}\n\nfunction canUseArtifactAccess(\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>,\n\taction: ArtifactAccessAction,\n): boolean {\n\treturn Boolean(grant?.actions.includes(action));\n}\n\nexport async function handleSessionArtifactsIndex(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tsessionId,\n\t\t\t\tfilenames: Array.from(artifacts.keys()).sort((a, b) =>\n\t\t\t\t\ta.localeCompare(b),\n\t\t\t\t),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactAccess(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filename = url.searchParams.get(\"filename\")?.trim() || undefined;\n\t\tconst actions = Array.from(\n\t\t\tnew Set(\n\t\t\t\t(url.searchParams.get(\"actions\") || \"\")\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((action) => action.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t),\n\t\t).filter((action): action is ArtifactAccessAction => {\n\t\t\treturn [\"view\", \"file\", \"events\", \"zip\"].includes(action);\n\t\t});\n\n\t\tif (actions.length === 0) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"At least one artifact access action is required\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (filename) {\n\t\t\tvalidateFilename(filename);\n\t\t}\n\n\t\tif (!filename && actions.some((action) => action !== \"zip\")) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"filename is required for artifact file access\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\tif (filename && !artifacts.has(filename)) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst access = issueArtifactAccessGrant({\n\t\t\tsessionId,\n\t\t\tscope: resolveSessionScope(req),\n\t\t\tfilename,\n\t\t\tactions,\n\t\t});\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\ttoken: access.token,\n\t\t\t\texpiresAt: access.expiresAtIso,\n\t\t\t\tactions: access.actions,\n\t\t\t\tsessionId,\n\t\t\t\t...(filename ? { filename } : {}),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactFile(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst wantsDownload = url.searchParams.get(\"download\") === \"1\";\n\t\tconst wantsRaw = url.searchParams.get(\"raw\") === \"1\";\n\t\tconst wantsStandalone = url.searchParams.get(\"standalone\") === \"1\";\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\n\t\tlet body =\n\t\t\tisHtml && !wantsRaw && eventsUrl\n\t\t\t\t? injectLiveReloadWithAuth(content, eventsUrl, accessToken)\n\t\t\t\t: content;\n\n\t\t// Standalone download: force attachment and embed artifacts snapshot + helpers.\n\t\tif (isHtml && wantsStandalone) {\n\t\t\tbody = injectArtifactsSnapshotRuntime(body, artifacts);\n\t\t}\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": String(mime),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...(wantsDownload || wantsStandalone\n\t\t\t\t? {\n\t\t\t\t\t\t\"Content-Disposition\": buildContentDisposition(filename),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...cors,\n\t\t});\n\t\tres.end(body);\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to serve artifact\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t\tfilename,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactViewer(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst title = `Maestro Artifact · ${filename}`;\n\t\tconst viewerUrl = buildSessionArtifactViewerUrl(sessionId, filename);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\t\tconst zipUrl = canUseArtifactAccess(grant, \"zip\")\n\t\t\t? buildSessionArtifactsZipUrl(sessionId)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsZipUrl(sessionId);\n\t\tconst rawDownloadUrl = canUseArtifactAccess(grant, \"file\")\n\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\tdownload: true,\n\t\t\t\t\traw: true,\n\t\t\t\t})\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\traw: true,\n\t\t\t\t\t});\n\t\tconst standaloneDownloadUrl = isHtml\n\t\t\t? canUseArtifactAccess(grant, \"file\")\n\t\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t})\n\t\t\t\t: accessToken\n\t\t\t\t\t? null\n\t\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t\t})\n\t\t\t: null;\n\n\t\tconst zipAction = zipUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-zip\" class=\"hint-button\" type=\"button\">Download ZIP</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${zipUrl}\" target=\"_blank\" rel=\"noopener\">Download ZIP</a>`\n\t\t\t: \"\";\n\t\tconst rawDownloadAction = rawDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-raw\" class=\"hint-button\" type=\"button\">Download Raw</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${rawDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Raw</a>`\n\t\t\t: \"\";\n\t\tconst standaloneDownloadAction = standaloneDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-standalone\" class=\"hint-button\" type=\"button\">Download Standalone</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${standaloneDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Standalone</a>`\n\t\t\t: \"\";\n\t\tconst zipDownloadName = `${sessionId}-artifacts.zip`;\n\n\t\tconst srcdoc = isHtml\n\t\t\t? injectArtifactsSnapshotRuntime(content, artifacts)\n\t\t\t: wrapHtmlDocument(\n\t\t\t\t\t`<pre style=\"white-space:pre-wrap; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 13px; line-height: 1.4; padding: 16px; margin: 0;\">${content\n\t\t\t\t\t\t.replace(/&/g, \"&amp;\")\n\t\t\t\t\t\t.replace(/</g, \"&lt;\")\n\t\t\t\t\t\t.replace(/>/g, \"&gt;\")}</pre>`,\n\t\t\t\t);\n\n\t\tconst openExternalHandler = `\n<script>\nwindow.addEventListener(\"message\", (e) => {\n if (!e || !e.data) return;\n if (e.data.type !== \"open-external-url\") return;\n const url = e.data.url;\n if (typeof url !== \"string\") return;\n let parsed;\n try { parsed = new URL(url); } catch { return; }\n if (!parsed || (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\")) return;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n});\n</script>\n`.trim();\n\n\t\tconst viewerHtml = `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</title>\n <style>\n html, body { height: 100%; margin: 0; background: #0b0c0f; color: #e6edf3; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }\n .bar { display:flex; align-items:center; gap:12px; padding:10px 12px; border-bottom: 1px solid #1e2023; background: #08090a; position: sticky; top: 0; z-index: 1; }\n .title { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 12px; color: #9da3af; }\n .spacer { flex: 1; }\n a, button { font: inherit; }\n button { background: transparent; border: 1px solid #30363d; color: #c9d1d9; padding: 6px 10px; cursor: pointer; }\n button:hover { border-color: #58a6ff; color: #58a6ff; }\n iframe { width: 100%; height: calc(100% - 52px); border: 0; display:block; background: #fff; }\n .hint { font-size: 12px; color: #7d8590; }\n .hint-button { padding: 0; border: 0; color: #7d8590; font-size: 12px; }\n </style>\n </head>\n <body>\n <div class=\"bar\">\n <div class=\"title\">${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</div>\n <div class=\"spacer\"></div>\n ${zipAction}\n ${rawDownloadAction}\n ${standaloneDownloadAction}\n <button id=\"reload\">Reload</button>\n </div>\n ${openExternalHandler}\n <iframe id=\"frame\" sandbox=\"allow-scripts allow-modals allow-downloads\"></iframe>\n <script>\n const frame = document.getElementById(\"frame\");\n const reloadBtn = document.getElementById(\"reload\");\n const viewerUrl = ${JSON.stringify(viewerUrl)};\n const eventsUrl = ${JSON.stringify(eventsUrl)};\n const zipUrl = ${JSON.stringify(zipUrl)};\n const rawDownloadUrl = ${JSON.stringify(rawDownloadUrl)};\n const standaloneDownloadUrl = ${JSON.stringify(standaloneDownloadUrl)};\n const artifactAccessToken = ${JSON.stringify(accessToken)};\n const artifactAccessHeaders = artifactAccessToken\n ? { ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: artifactAccessToken }\n : undefined;\n\n const setDoc = (html) => {\n frame.srcdoc = html;\n };\n\n const parseDownloadFilename = (response, fallbackName) => {\n const contentDisposition = response.headers.get(\"content-disposition\") || \"\";\n const utf8Match = contentDisposition.match(/filename\\*=UTF-8''([^;]+)/i);\n if (utf8Match?.[1]) {\n try {\n return decodeURIComponent(utf8Match[1]);\n } catch {\n return utf8Match[1];\n }\n }\n const quotedMatch = contentDisposition.match(/filename=\"([^\"]+)\"/i);\n if (quotedMatch?.[1]) {\n return quotedMatch[1];\n }\n const bareMatch = contentDisposition.match(/filename=([^;]+)/i);\n return bareMatch?.[1]?.trim() || fallbackName || \"\";\n };\n\n const fetchViewerResource = async (url) => {\n const response = await fetch(url, {\n cache: \"no-store\",\n ...(artifactAccessHeaders ? { headers: artifactAccessHeaders } : {}),\n });\n if (!response.ok) {\n\t\t throw new Error(\"Request failed (\" + response.status + \")\");\n }\n return response;\n };\n\n const downloadViewerResource = async (url, fallbackName) => {\n const response = await fetchViewerResource(url);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = objectUrl;\n const downloadName = parseDownloadFilename(response, fallbackName);\n if (downloadName) {\n link.download = downloadName;\n }\n link.rel = \"noopener\";\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000);\n };\n\n const refreshViewer = async () => {\n if (!artifactAccessHeaders) {\n location.reload();\n return;\n }\n const response = await fetchViewerResource(viewerUrl);\n const nextHtml = await response.text();\n const nextUrl = URL.createObjectURL(\n new Blob([nextHtml], { type: \"text/html\" }),\n );\n setTimeout(() => URL.revokeObjectURL(nextUrl), 60_000);\n location.replace(nextUrl);\n };\n\n const triggerRefresh = () => {\n void refreshViewer().catch((err) => {\n console.error(\"[Maestro] Failed to refresh viewer:\", err);\n });\n };\n\n const bindDownloadButton = (id, url, fallbackName) => {\n const button = document.getElementById(id);\n if (!button || !url || !artifactAccessHeaders) {\n return;\n }\n button.addEventListener(\"click\", () => {\n void downloadViewerResource(url, fallbackName).catch((err) => {\n console.error(\"[Maestro] Failed to download artifact:\", err);\n });\n });\n };\n\n const srcdoc = ${JSON.stringify(srcdoc)};\n setDoc(srcdoc);\n\n\t\t\t\tbindDownloadButton(\"download-zip\", zipUrl, ${JSON.stringify(zipDownloadName)});\n bindDownloadButton(\"download-raw\", rawDownloadUrl, ${JSON.stringify(filename)});\n bindDownloadButton(\"download-standalone\", standaloneDownloadUrl, ${JSON.stringify(filename)});\n\n reloadBtn.addEventListener(\"click\", () => triggerRefresh());\n\n ${\n\t\t\t\teventsUrl\n\t\t\t\t\t? `try {\n\t\tconst reload = () => triggerRefresh();\n const connect = ${\n\t\t\t\t\taccessToken\n\t\t\t\t\t\t? `async () => {\n\t\t const response = await fetchViewerResource(eventsUrl);\n if (!response.body) throw new Error(\"Missing response body\");\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n while (boundary !== -1) {\n const chunk = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary + 2);\n const dataLine = chunk\n .split(\"\\\\n\")\n .find((line) => line.startsWith(\"data:\"));\n if (dataLine) {\n reload();\n return;\n }\n boundary = buffer.indexOf(\"\\\\n\\\\n\");\n }\n }\n }`\n\t\t\t\t\t\t: `() => {\n const es = new EventSource(${JSON.stringify(eventsUrl)});\n es.onmessage = () => reload();\n }`\n\t\t\t\t};\n Promise.resolve(connect()).catch((err) => {\n console.error(\"[Maestro] Failed to setup viewer live reload transport:\", err);\n });\n } catch (err) { console.error(\"[Maestro] Failed to setup viewer EventSource:\", err); }`\n\t\t\t\t\t: \"\"\n\t\t\t}\n </script>\n </body>\n</html>`;\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/html; charset=utf-8\",\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(viewerHtml);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsEvents(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filenameFilter = url.searchParams.get(\"filename\");\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\tConnection: \"keep-alive\",\n\t\t\t...cors,\n\t\t});\n\n\t\tlet closed = false;\n\t\tconst canWrite = () =>\n\t\t\tres.writable !== false && !res.writableEnded && !res.destroyed;\n\t\tconst safeWrite = (payload: string) => {\n\t\t\tif (!canWrite()) return false;\n\t\t\ttry {\n\t\t\t\tres.write(payload);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\tlet heartbeat: ReturnType<typeof setInterval> | null = null;\n\t\tlet unsubscribe: () => void = () => {};\n\n\t\tconst cleanup = () => {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tif (heartbeat) {\n\t\t\t\tclearInterval(heartbeat);\n\t\t\t\theartbeat = null;\n\t\t\t}\n\t\t\tunsubscribe();\n\t\t\treq.off(\"close\", cleanup);\n\t\t\tres.off(\"close\", cleanup);\n\t\t};\n\n\t\tunsubscribe = subscribeArtifactUpdates(sessionId, (event) => {\n\t\t\tif (filenameFilter && event.filename !== filenameFilter) return;\n\t\t\tif (!safeWrite(`data: ${JSON.stringify(event)}\\n\\n`)) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t});\n\n\t\theartbeat = setInterval(() => {\n\t\t\tif (!safeWrite(\": ping\\n\\n\")) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t}, 15_000);\n\n\t\tif (heartbeat.unref) {\n\t\t\theartbeat.unref();\n\t\t}\n\n\t\tif (!safeWrite(\": ok\\n\\n\")) {\n\t\t\tcleanup();\n\t\t\treturn;\n\t\t}\n\n\t\treq.on(\"close\", cleanup);\n\t\tres.on(\"close\", cleanup);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsZip(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\t// Lazy import to keep startup cost low.\n\t\tconst { strToU8, zipSync } = await import(\"fflate\");\n\n\t\tconst entries: Record<string, Uint8Array> = {};\n\t\tfor (const [filename, content] of artifacts) {\n\t\t\tentries[filename] = strToU8(content);\n\t\t}\n\n\t\tconst zipBytes = zipSync(entries, { level: 6 });\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"application/zip\",\n\t\t\t\"Content-Disposition\": buildContentDisposition(\n\t\t\t\t`artifacts-${sessionId}.zip`,\n\t\t\t),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(Buffer.from(zipBytes));\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to export artifacts zip\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n"]}
1
+ {"version":3,"file":"session-artifacts.js","sourceRoot":"","sources":["../../../src/server/handlers/session-artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport {\n\ttype ComposerMessage,\n\tartifactContentsByFilename,\n\tisValidArtifactFilename,\n\treconstructArtifactsFromMessages as reconstructArtifactStateFromMessages,\n} from \"@evalops/contracts\";\nimport { lookup as lookupMimeType } from \"mime-types\";\nimport { createLogger } from \"../../utils/logger.js\";\nimport {\n\tARTIFACT_ACCESS_HEADER,\n\ttype ArtifactAccessAction,\n\tgetArtifactAccessGrantFromRequest,\n\tgetArtifactAccessTokenFromRequest,\n\tissueArtifactAccessGrant,\n} from \"../artifact-access.js\";\nimport { subscribeArtifactUpdates } from \"../artifacts-live-reload.js\";\nimport {\n\tApiError,\n\tbuildContentDisposition,\n\tsendJson,\n} from \"../server-utils.js\";\nimport {\n\tcreateWebSessionManagerForRequest,\n\tresolveSessionScope,\n} from \"../session-scope.js\";\nimport { convertAppMessagesToComposer } from \"../session-serialization.js\";\n\nconst logger = createLogger(\"session-artifacts\");\nconst sessionIdPattern = /^[a-zA-Z0-9._-]+$/;\n\nfunction escapeScriptContent(code: string): string {\n\treturn code.replace(/<\\/script/gi, \"<\\\\/script\");\n}\n\nfunction injectLiveReload(html: string, eventsUrl: string): string {\n\treturn injectLiveReloadWithAuth(html, eventsUrl);\n}\n\nfunction injectLiveReloadWithAuth(\n\thtml: string,\n\teventsUrl: string,\n\taccessToken?: string | null,\n): string {\n\tconst authHeaders = accessToken\n\t\t? `{ ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: ${JSON.stringify(accessToken)} }`\n\t\t: \"undefined\";\n\tconst scriptBody = `\n\t(function() {\n\t try {\n\t const reload = () => location.reload();\n\t const connect = ${\n\t\t\t\taccessToken\n\t\t\t\t\t? `async () => {\n\t const response = await fetch(${JSON.stringify(eventsUrl)}, {\n\t headers: ${authHeaders},\n\t cache: \"no-store\",\n\t });\n\t if (!response.body) throw new Error(\"Missing response body\");\n\t const reader = response.body.getReader();\n\t const decoder = new TextDecoder();\n\t let buffer = \"\";\n\t while (true) {\n\t const { done, value } = await reader.read();\n\t if (done) break;\n\t buffer += decoder.decode(value, { stream: true });\n\t let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t while (boundary !== -1) {\n\t const chunk = buffer.slice(0, boundary);\n\t buffer = buffer.slice(boundary + 2);\n\t const dataLine = chunk\n\t .split(\"\\\\n\")\n\t .find((line) => line.startsWith(\"data:\"));\n\t if (dataLine) {\n\t reload();\n\t return;\n\t }\n\t boundary = buffer.indexOf(\"\\\\n\\\\n\");\n\t }\n\t }\n\t }`\n\t\t\t\t\t: `() => {\n\t const es = new EventSource(${JSON.stringify(eventsUrl)});\n\t es.onmessage = (e) => {\n\t try {\n\t const data = JSON.parse(e.data);\n\t if (data && data.type === \"artifact_updated\") {\n\t reload();\n\t }\n\t } catch (err) { console.error(\"[Maestro] Failed to parse live reload event:\", err); }\n\t };\n\t }`\n\t\t\t};\n\t Promise.resolve(connect()).catch((err) => {\n\t console.error(\"[Maestro] Failed to setup live reload transport:\", err);\n\t });\n\t } catch (err) { console.error(\"[Maestro] Failed to setup live reload EventSource:\", err); }\n\t})();\n\t`.trim();\n\tconst script = `<script>\\n${escapeScriptContent(scriptBody)}\\n</script>`;\n\tconst injected = `\\n${script}\\n`;\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `${injected}</body>`);\n\t}\n\treturn `${html}${injected}`;\n}\n\nfunction wrapHtmlDocument(htmlContent: string): string {\n\tconst trimmed = htmlContent.trim();\n\tconst looksLikeDocument =\n\t\t/^<!doctype/i.test(trimmed) || /<html[\\s>]/i.test(trimmed);\n\n\tif (looksLikeDocument) return trimmed;\n\n\treturn `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n${trimmed}\n </body>\n</html>`;\n}\n\nfunction injectArtifactsSnapshotRuntime(\n\thtmlContent: string,\n\tartifacts: Map<string, string>,\n): string {\n\tconst snapshot: Record<string, string> = {};\n\tfor (const [name, content] of artifacts) {\n\t\tsnapshot[name] = content;\n\t}\n\n\tconst runtime = `\n<script>\n(function() {\n try {\n window.artifacts = ${escapeScriptContent(JSON.stringify(snapshot))};\n } catch (err) {\n console.error(\"[Maestro] Failed to initialize artifacts snapshot:\", err);\n window.artifacts = {};\n }\n\n const isJson = (f) => (f || \"\").toLowerCase().endsWith(\".json\");\n\n window.listArtifacts = async () => Object.keys(window.artifacts || {});\n\n window.getArtifact = async (filename) => {\n const content = (window.artifacts || {})[filename];\n if (typeof content !== \"string\") throw new Error(\"Artifact not found: \" + filename);\n if (isJson(filename)) {\n try { return JSON.parse(content); } catch (e) { throw new Error(\"Failed to parse JSON: \" + e); }\n }\n return content;\n };\n})();\n</script>\n`.trim();\n\n\tconst html = wrapHtmlDocument(htmlContent);\n\tif (/<\\/body>/i.test(html)) {\n\t\treturn html.replace(/<\\/body>/i, `\\n${runtime}\\n</body>`);\n\t}\n\treturn `${html}\\n${runtime}`;\n}\n\nfunction reconstructArtifactsFromMessages(\n\tmessages: ComposerMessage[],\n): Map<string, string> {\n\tconst diagnostics: string[] = [];\n\tconst state = reconstructArtifactStateFromMessages(messages, {\n\t\tonDiagnostic: (diagnostic) => {\n\t\t\tdiagnostics.push(diagnostic.code);\n\t\t},\n\t});\n\tif (diagnostics.length > 0) {\n\t\tlogger.warn(\"Skipped invalid persisted artifact commands\", {\n\t\t\tcount: diagnostics.length,\n\t\t\tcodes: diagnostics,\n\t\t});\n\t}\n\treturn artifactContentsByFilename(state);\n}\n\nasync function loadComposerMessages(\n\treq: IncomingMessage,\n\tsessionId: string,\n): Promise<ComposerMessage[]> {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\tconst session = await sessionManager.loadSession(sessionId);\n\tif (!session) {\n\t\tthrow new ApiError(404, \"Session not found\");\n\t}\n\treturn convertAppMessagesToComposer(session.messages || []);\n}\n\nfunction validateFilename(filename: string): void {\n\t// Keep this strict: no path traversal, no folder hierarchies.\n\tif (!isValidArtifactFilename(filename.trim())) {\n\t\tthrow new ApiError(400, \"Invalid filename\");\n\t}\n}\n\nfunction buildSessionArtifactFileUrl(\n\tsessionId: string,\n\tfilename: string,\n\toptions?: {\n\t\tdownload?: boolean;\n\t\traw?: boolean;\n\t\tstandalone?: boolean;\n\t},\n): string {\n\tconst path = `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}`;\n\tconst url = new URL(path, \"http://localhost\");\n\tif (options?.download) url.searchParams.set(\"download\", \"1\");\n\tif (options?.raw) url.searchParams.set(\"raw\", \"1\");\n\tif (options?.standalone) url.searchParams.set(\"standalone\", \"1\");\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactViewerUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts/${encodeURIComponent(filename)}/view`;\n}\n\nfunction buildSessionArtifactsEventsUrl(\n\tsessionId: string,\n\tfilename: string,\n): string {\n\tconst url = new URL(\n\t\t`/api/sessions/${encodeURIComponent(sessionId)}/artifacts/events`,\n\t\t\"http://localhost\",\n\t);\n\turl.searchParams.set(\"filename\", filename);\n\treturn `${url.pathname}${url.search}`;\n}\n\nfunction buildSessionArtifactsZipUrl(sessionId: string): string {\n\treturn `/api/sessions/${encodeURIComponent(sessionId)}/artifacts.zip`;\n}\n\nfunction resolveArtifactAccessContext(req: IncomingMessage): {\n\taccessToken: string | null;\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>;\n} {\n\tconst grant = getArtifactAccessGrantFromRequest(req);\n\treturn {\n\t\taccessToken: grant ? getArtifactAccessTokenFromRequest(req) : null,\n\t\tgrant,\n\t};\n}\n\nfunction canUseArtifactAccess(\n\tgrant: ReturnType<typeof getArtifactAccessGrantFromRequest>,\n\taction: ArtifactAccessAction,\n): boolean {\n\treturn Boolean(grant?.actions.includes(action));\n}\n\nexport async function handleSessionArtifactsIndex(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tsessionId,\n\t\t\t\tfilenames: Array.from(artifacts.keys()).sort((a, b) =>\n\t\t\t\t\ta.localeCompare(b),\n\t\t\t\t),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactAccess(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filename = url.searchParams.get(\"filename\")?.trim() || undefined;\n\t\tconst actions = Array.from(\n\t\t\tnew Set(\n\t\t\t\t(url.searchParams.get(\"actions\") || \"\")\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((action) => action.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t),\n\t\t).filter((action): action is ArtifactAccessAction => {\n\t\t\treturn [\"view\", \"file\", \"events\", \"zip\"].includes(action);\n\t\t});\n\n\t\tif (actions.length === 0) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"At least one artifact access action is required\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (filename) {\n\t\t\tvalidateFilename(filename);\n\t\t}\n\n\t\tif (!filename && actions.some((action) => action !== \"zip\")) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t400,\n\t\t\t\t{ error: \"filename is required for artifact file access\" },\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\tif (filename && !artifacts.has(filename)) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst access = issueArtifactAccessGrant({\n\t\t\tsessionId,\n\t\t\tscope: resolveSessionScope(req),\n\t\t\tfilename,\n\t\t\tactions,\n\t\t});\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\ttoken: access.token,\n\t\t\t\texpiresAt: access.expiresAtIso,\n\t\t\t\tactions: access.actions,\n\t\t\t\tsessionId,\n\t\t\t\t...(filename ? { filename } : {}),\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactFile(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst wantsDownload = url.searchParams.get(\"download\") === \"1\";\n\t\tconst wantsRaw = url.searchParams.get(\"raw\") === \"1\";\n\t\tconst wantsStandalone = url.searchParams.get(\"standalone\") === \"1\";\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\n\t\tlet body =\n\t\t\tisHtml && !wantsRaw && eventsUrl\n\t\t\t\t? injectLiveReloadWithAuth(content, eventsUrl, accessToken)\n\t\t\t\t: content;\n\n\t\t// Standalone download: force attachment and embed artifacts snapshot + helpers.\n\t\tif (isHtml && wantsStandalone) {\n\t\t\tbody = injectArtifactsSnapshotRuntime(body, artifacts);\n\t\t}\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": String(mime),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...(wantsDownload || wantsStandalone\n\t\t\t\t? {\n\t\t\t\t\t\t\"Content-Disposition\": buildContentDisposition(filename),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...cors,\n\t\t});\n\t\tres.end(body);\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to serve artifact\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t\tfilename,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactViewer(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; filename: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\tconst filename = decodeURIComponent(params.filename || \"\");\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tvalidateFilename(filename);\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\t\tconst content = artifacts.get(filename);\n\t\tif (content === undefined) {\n\t\t\tsendJson(res, 404, { error: \"Artifact not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst mime = lookupMimeType(filename) || \"text/plain; charset=utf-8\";\n\t\tconst isHtml = String(mime).startsWith(\"text/html\");\n\t\tconst { accessToken, grant } = resolveArtifactAccessContext(req);\n\n\t\tconst title = `Maestro Artifact · ${filename}`;\n\t\tconst viewerUrl = buildSessionArtifactViewerUrl(sessionId, filename);\n\n\t\tconst eventsUrl = canUseArtifactAccess(grant, \"events\")\n\t\t\t? buildSessionArtifactsEventsUrl(sessionId, filename)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsEventsUrl(sessionId, filename);\n\t\tconst zipUrl = canUseArtifactAccess(grant, \"zip\")\n\t\t\t? buildSessionArtifactsZipUrl(sessionId)\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactsZipUrl(sessionId);\n\t\tconst rawDownloadUrl = canUseArtifactAccess(grant, \"file\")\n\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\tdownload: true,\n\t\t\t\t\traw: true,\n\t\t\t\t})\n\t\t\t: accessToken\n\t\t\t\t? null\n\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\traw: true,\n\t\t\t\t\t});\n\t\tconst standaloneDownloadUrl = isHtml\n\t\t\t? canUseArtifactAccess(grant, \"file\")\n\t\t\t\t? buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t})\n\t\t\t\t: accessToken\n\t\t\t\t\t? null\n\t\t\t\t\t: buildSessionArtifactFileUrl(sessionId, filename, {\n\t\t\t\t\t\t\tdownload: true,\n\t\t\t\t\t\t\tstandalone: true,\n\t\t\t\t\t\t})\n\t\t\t: null;\n\n\t\tconst zipAction = zipUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-zip\" class=\"hint-button\" type=\"button\">Download ZIP</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${zipUrl}\" target=\"_blank\" rel=\"noopener\">Download ZIP</a>`\n\t\t\t: \"\";\n\t\tconst rawDownloadAction = rawDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-raw\" class=\"hint-button\" type=\"button\">Download Raw</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${rawDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Raw</a>`\n\t\t\t: \"\";\n\t\tconst standaloneDownloadAction = standaloneDownloadUrl\n\t\t\t? accessToken\n\t\t\t\t? `<button id=\"download-standalone\" class=\"hint-button\" type=\"button\">Download Standalone</button>`\n\t\t\t\t: `<a class=\"hint\" href=\"${standaloneDownloadUrl}\" target=\"_blank\" rel=\"noopener\">Download Standalone</a>`\n\t\t\t: \"\";\n\t\tconst zipDownloadName = `${sessionId}-artifacts.zip`;\n\n\t\tconst srcdoc = isHtml\n\t\t\t? injectArtifactsSnapshotRuntime(content, artifacts)\n\t\t\t: wrapHtmlDocument(\n\t\t\t\t\t`<pre style=\"white-space:pre-wrap; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 13px; line-height: 1.4; padding: 16px; margin: 0;\">${content\n\t\t\t\t\t\t.replace(/&/g, \"&amp;\")\n\t\t\t\t\t\t.replace(/</g, \"&lt;\")\n\t\t\t\t\t\t.replace(/>/g, \"&gt;\")}</pre>`,\n\t\t\t\t);\n\n\t\tconst openExternalHandler = `\n<script>\nwindow.addEventListener(\"message\", (e) => {\n if (!e || !e.data) return;\n if (e.data.type !== \"open-external-url\") return;\n const url = e.data.url;\n if (typeof url !== \"string\") return;\n let parsed;\n try { parsed = new URL(url); } catch { return; }\n if (!parsed || (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\")) return;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n});\n</script>\n`.trim();\n\n\t\tconst viewerHtml = `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</title>\n <style>\n html, body { height: 100%; margin: 0; background: #0b0c0f; color: #e6edf3; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }\n .bar { display:flex; align-items:center; gap:12px; padding:10px 12px; border-bottom: 1px solid #1e2023; background: #08090a; position: sticky; top: 0; z-index: 1; }\n .title { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 12px; color: #9da3af; }\n .spacer { flex: 1; }\n a, button { font: inherit; }\n button { background: transparent; border: 1px solid #30363d; color: #c9d1d9; padding: 6px 10px; cursor: pointer; }\n button:hover { border-color: #58a6ff; color: #58a6ff; }\n iframe { width: 100%; height: calc(100% - 52px); border: 0; display:block; background: #fff; }\n .hint { font-size: 12px; color: #7d8590; }\n .hint-button { padding: 0; border: 0; color: #7d8590; font-size: 12px; }\n </style>\n </head>\n <body>\n <div class=\"bar\">\n <div class=\"title\">${title.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}</div>\n <div class=\"spacer\"></div>\n ${zipAction}\n ${rawDownloadAction}\n ${standaloneDownloadAction}\n <button id=\"reload\">Reload</button>\n </div>\n ${openExternalHandler}\n <iframe id=\"frame\" sandbox=\"allow-scripts allow-modals allow-downloads\"></iframe>\n <script>\n const frame = document.getElementById(\"frame\");\n const reloadBtn = document.getElementById(\"reload\");\n const viewerUrl = ${JSON.stringify(viewerUrl)};\n const eventsUrl = ${JSON.stringify(eventsUrl)};\n const zipUrl = ${JSON.stringify(zipUrl)};\n const rawDownloadUrl = ${JSON.stringify(rawDownloadUrl)};\n const standaloneDownloadUrl = ${JSON.stringify(standaloneDownloadUrl)};\n const artifactAccessToken = ${JSON.stringify(accessToken)};\n const artifactAccessHeaders = artifactAccessToken\n ? { ${JSON.stringify(ARTIFACT_ACCESS_HEADER)}: artifactAccessToken }\n : undefined;\n\n const setDoc = (html) => {\n frame.srcdoc = html;\n };\n\n const parseDownloadFilename = (response, fallbackName) => {\n const contentDisposition = response.headers.get(\"content-disposition\") || \"\";\n const utf8Match = contentDisposition.match(/filename\\*=UTF-8''([^;]+)/i);\n if (utf8Match?.[1]) {\n try {\n return decodeURIComponent(utf8Match[1]);\n } catch {\n return utf8Match[1];\n }\n }\n const quotedMatch = contentDisposition.match(/filename=\"([^\"]+)\"/i);\n if (quotedMatch?.[1]) {\n return quotedMatch[1];\n }\n const bareMatch = contentDisposition.match(/filename=([^;]+)/i);\n return bareMatch?.[1]?.trim() || fallbackName || \"\";\n };\n\n const fetchViewerResource = async (url) => {\n const response = await fetch(url, {\n cache: \"no-store\",\n ...(artifactAccessHeaders ? { headers: artifactAccessHeaders } : {}),\n });\n if (!response.ok) {\n\t\t throw new Error(\"Request failed (\" + response.status + \")\");\n }\n return response;\n };\n\n const downloadViewerResource = async (url, fallbackName) => {\n const response = await fetchViewerResource(url);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = objectUrl;\n const downloadName = parseDownloadFilename(response, fallbackName);\n if (downloadName) {\n link.download = downloadName;\n }\n link.rel = \"noopener\";\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000);\n };\n\n const refreshViewer = async () => {\n if (!artifactAccessHeaders) {\n location.reload();\n return;\n }\n const response = await fetchViewerResource(viewerUrl);\n const nextHtml = await response.text();\n const nextUrl = URL.createObjectURL(\n new Blob([nextHtml], { type: \"text/html\" }),\n );\n setTimeout(() => URL.revokeObjectURL(nextUrl), 60_000);\n location.replace(nextUrl);\n };\n\n const triggerRefresh = () => {\n void refreshViewer().catch((err) => {\n console.error(\"[Maestro] Failed to refresh viewer:\", err);\n });\n };\n\n const bindDownloadButton = (id, url, fallbackName) => {\n const button = document.getElementById(id);\n if (!button || !url || !artifactAccessHeaders) {\n return;\n }\n button.addEventListener(\"click\", () => {\n void downloadViewerResource(url, fallbackName).catch((err) => {\n console.error(\"[Maestro] Failed to download artifact:\", err);\n });\n });\n };\n\n const srcdoc = ${JSON.stringify(srcdoc)};\n setDoc(srcdoc);\n\n\t\t\t\tbindDownloadButton(\"download-zip\", zipUrl, ${JSON.stringify(zipDownloadName)});\n bindDownloadButton(\"download-raw\", rawDownloadUrl, ${JSON.stringify(filename)});\n bindDownloadButton(\"download-standalone\", standaloneDownloadUrl, ${JSON.stringify(filename)});\n\n reloadBtn.addEventListener(\"click\", () => triggerRefresh());\n\n ${\n\t\t\t\teventsUrl\n\t\t\t\t\t? `try {\n\t\tconst reload = () => triggerRefresh();\n const connect = ${\n\t\t\t\t\taccessToken\n\t\t\t\t\t\t? `async () => {\n\t\t const response = await fetchViewerResource(eventsUrl);\n if (!response.body) throw new Error(\"Missing response body\");\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let boundary = buffer.indexOf(\"\\\\n\\\\n\");\n while (boundary !== -1) {\n const chunk = buffer.slice(0, boundary);\n buffer = buffer.slice(boundary + 2);\n const dataLine = chunk\n .split(\"\\\\n\")\n .find((line) => line.startsWith(\"data:\"));\n if (dataLine) {\n reload();\n return;\n }\n boundary = buffer.indexOf(\"\\\\n\\\\n\");\n }\n }\n }`\n\t\t\t\t\t\t: `() => {\n const es = new EventSource(${JSON.stringify(eventsUrl)});\n es.onmessage = () => reload();\n }`\n\t\t\t\t};\n Promise.resolve(connect()).catch((err) => {\n console.error(\"[Maestro] Failed to setup viewer live reload transport:\", err);\n });\n } catch (err) { console.error(\"[Maestro] Failed to setup viewer EventSource:\", err); }`\n\t\t\t\t\t: \"\"\n\t\t\t}\n </script>\n </body>\n</html>`;\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/html; charset=utf-8\",\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(viewerHtml);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsEvents(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url || \"\", \"http://localhost\");\n\t\tconst filenameFilter = url.searchParams.get(\"filename\");\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\tConnection: \"keep-alive\",\n\t\t\t...cors,\n\t\t});\n\n\t\tlet closed = false;\n\t\tconst canWrite = () =>\n\t\t\tres.writable !== false && !res.writableEnded && !res.destroyed;\n\t\tconst safeWrite = (payload: string) => {\n\t\t\tif (!canWrite()) return false;\n\t\t\ttry {\n\t\t\t\tres.write(payload);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\tlet heartbeat: ReturnType<typeof setInterval> | null = null;\n\t\tlet unsubscribe: () => void = () => {};\n\n\t\tconst cleanup = () => {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tif (heartbeat) {\n\t\t\t\tclearInterval(heartbeat);\n\t\t\t\theartbeat = null;\n\t\t\t}\n\t\t\tunsubscribe();\n\t\t\treq.off(\"close\", cleanup);\n\t\t\tres.off(\"close\", cleanup);\n\t\t};\n\n\t\tunsubscribe = subscribeArtifactUpdates(sessionId, (event) => {\n\t\t\tif (filenameFilter && event.filename !== filenameFilter) return;\n\t\t\tif (!safeWrite(`data: ${JSON.stringify(event)}\\n\\n`)) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t});\n\n\t\theartbeat = setInterval(() => {\n\t\t\tif (!safeWrite(\": ping\\n\\n\")) {\n\t\t\t\tcleanup();\n\t\t\t}\n\t\t}, 15_000);\n\n\t\tif (heartbeat.unref) {\n\t\t\theartbeat.unref();\n\t\t}\n\n\t\tif (!safeWrite(\": ok\\n\\n\")) {\n\t\t\tcleanup();\n\t\t\treturn;\n\t\t}\n\n\t\treq.on(\"close\", cleanup);\n\t\tres.on(\"close\", cleanup);\n\t} catch (err) {\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n\nexport async function handleSessionArtifactsZip(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionId = params.id;\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tres.writeHead(405, cors);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst messages = await loadComposerMessages(req, sessionId);\n\t\tconst artifacts = reconstructArtifactsFromMessages(messages);\n\n\t\t// Lazy import to keep startup cost low.\n\t\tconst { strToU8, zipSync } = await import(\"fflate\");\n\n\t\tconst entries: Record<string, Uint8Array> = {};\n\t\tfor (const [filename, content] of artifacts) {\n\t\t\tentries[filename] = strToU8(content);\n\t\t}\n\n\t\tconst zipBytes = zipSync(entries, { level: 6 });\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": \"application/zip\",\n\t\t\t\"Content-Disposition\": buildContentDisposition(\n\t\t\t\t`artifacts-${sessionId}.zip`,\n\t\t\t),\n\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t...cors,\n\t\t});\n\t\tres.end(Buffer.from(zipBytes));\n\t} catch (err) {\n\t\tlogger.warn(\"Failed to export artifacts zip\", {\n\t\t\terr: err instanceof Error ? err.message : String(err),\n\t\t\tsessionId,\n\t\t});\n\t\tconst error =\n\t\t\terr instanceof ApiError ? err : new ApiError(500, \"Internal error\");\n\t\tsendJson(res, error.statusCode, { error: error.message }, cors, req);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session-attachments.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/session-attachments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AA4DjE,wBAAsB,uBAAuB,CAC5C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC5C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAuD5B;AAED,wBAAsB,8BAA8B,CACnD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC5C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA4F5B"}
1
+ {"version":3,"file":"session-attachments.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/session-attachments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AA4DjE,wBAAsB,uBAAuB,CAC5C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC5C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBAuD5B;AAED,wBAAsB,8BAA8B,CACnD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC5C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA8F5B"}
@@ -120,6 +120,7 @@ export async function handleSessionAttachmentExtract(req, res, params, cors) {
120
120
  sendJson(res, 200, {
121
121
  fileName: attachment.fileName,
122
122
  format: "unknown",
123
+ extractor: "native",
123
124
  size: attachment.size ?? 0,
124
125
  truncated: false,
125
126
  extractedText: attachment.extractedText,
@@ -145,6 +146,7 @@ export async function handleSessionAttachmentExtract(req, res, params, cors) {
145
146
  sendJson(res, 200, {
146
147
  fileName: attachment.fileName,
147
148
  format: extracted.format,
149
+ extractor: extracted.extractor,
148
150
  size: extracted.sizeBytes,
149
151
  truncated: extracted.truncated,
150
152
  extractedText: extracted.extractedText,
@@ -1 +1 @@
1
- {"version":3,"file":"session-attachments.js","sourceRoot":"","sources":["../../../src/server/handlers/session-attachments.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extractDocumentText } from \"../../utils/document-extractor.js\";\nimport {\n\tbuildContentDisposition,\n\trespondWithApiError,\n\tsendJson,\n} from \"../server-utils.js\";\nimport { createWebSessionManagerForRequest } from \"../session-scope.js\";\n\nconst sessionIdPattern = /^[a-zA-Z0-9._-]+$/;\nconst attachmentIdPattern = /^[a-zA-Z0-9._-]+$/;\n\nfunction findAttachmentInSession(\n\tsession: { messages?: Array<unknown> },\n\tattachmentId: string,\n): {\n\tfileName: string;\n\tmimeType: string;\n\tcontentBase64: string;\n\tsize?: number;\n\textractedText?: string;\n} | null {\n\tconst messages = Array.isArray(session.messages) ? session.messages : [];\n\tfor (const msg of messages) {\n\t\tif (!msg || typeof msg !== \"object\") continue;\n\t\tconst maybeAttachments = (msg as { attachments?: unknown }).attachments;\n\t\tif (!Array.isArray(maybeAttachments)) continue;\n\n\t\tfor (const att of maybeAttachments) {\n\t\t\tif (!att || typeof att !== \"object\") continue;\n\t\t\tconst a = att as {\n\t\t\t\tid?: unknown;\n\t\t\t\tfileName?: unknown;\n\t\t\t\tmimeType?: unknown;\n\t\t\t\tcontent?: unknown;\n\t\t\t\tsize?: unknown;\n\t\t\t\textractedText?: unknown;\n\t\t\t};\n\t\t\tif (a.id !== attachmentId) continue;\n\t\t\tif (typeof a.fileName !== \"string\" || !a.fileName) return null;\n\t\t\tif (typeof a.mimeType !== \"string\" || !a.mimeType) return null;\n\t\t\tif (typeof a.content !== \"string\" || !a.content) return null;\n\t\t\treturn {\n\t\t\t\tfileName: a.fileName,\n\t\t\t\tmimeType: a.mimeType,\n\t\t\t\tcontentBase64: a.content,\n\t\t\t\tsize:\n\t\t\t\t\ttypeof a.size === \"number\" && Number.isFinite(a.size)\n\t\t\t\t\t\t? a.size\n\t\t\t\t\t\t: undefined,\n\t\t\t\textractedText:\n\t\t\t\t\ttypeof a.extractedText === \"string\" && a.extractedText.length > 0\n\t\t\t\t\t\t? a.extractedText\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n}\n\nexport async function handleSessionAttachment(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; attachmentId: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tsendJson(res, 405, { error: \"Method not allowed\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst sessionId = params.id;\n\t\tconst attachmentId = params.attachmentId;\n\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tif (!attachmentIdPattern.test(attachmentId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid attachment id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst session = await sessionManager.loadSession(sessionId);\n\t\tif (!session) {\n\t\t\tsendJson(res, 404, { error: \"Session not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst attachment = findAttachmentInSession(session, attachmentId);\n\t\tif (!attachment) {\n\t\t\tsendJson(res, 404, { error: \"Attachment not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst bytes = Buffer.from(attachment.contentBase64, \"base64\");\n\n\t\tconst requestUrl = new URL(req.url || \"/\", \"http://localhost\");\n\t\tconst download = requestUrl.searchParams.get(\"download\");\n\t\tconst shouldDownload = download === \"1\" || download === \"true\";\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": attachment.mimeType,\n\t\t\t\"Content-Length\": bytes.length,\n\t\t\t\"Cache-Control\": \"private, max-age=3600\",\n\t\t\t...(shouldDownload\n\t\t\t\t? {\n\t\t\t\t\t\t\"Content-Disposition\": buildContentDisposition(attachment.fileName),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...cors,\n\t\t});\n\t\tres.end(bytes);\n\t} catch (error) {\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t}\n}\n\nexport async function handleSessionAttachmentExtract(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; attachmentId: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\n\ttry {\n\t\tif (req.method !== \"POST\") {\n\t\t\tsendJson(res, 405, { error: \"Method not allowed\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst sessionId = params.id;\n\t\tconst attachmentId = params.attachmentId;\n\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tif (!attachmentIdPattern.test(attachmentId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid attachment id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst requestUrl = new URL(req.url || \"/\", \"http://localhost\");\n\t\tconst force = requestUrl.searchParams.get(\"force\");\n\t\tconst shouldForce = force === \"1\" || force === \"true\";\n\n\t\tconst session = await sessionManager.loadSession(sessionId);\n\t\tif (!session) {\n\t\t\tsendJson(res, 404, { error: \"Session not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst attachment = findAttachmentInSession(session, attachmentId);\n\t\tif (!attachment) {\n\t\t\tsendJson(res, 404, { error: \"Attachment not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tif (attachment.extractedText && !shouldForce) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t200,\n\t\t\t\t{\n\t\t\t\t\tfileName: attachment.fileName,\n\t\t\t\t\tformat: \"unknown\",\n\t\t\t\t\tsize: attachment.size ?? 0,\n\t\t\t\t\ttruncated: false,\n\t\t\t\t\textractedText: attachment.extractedText,\n\t\t\t\t\tcached: true,\n\t\t\t\t},\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst bytes = Buffer.from(attachment.contentBase64, \"base64\");\n\t\tconst extracted = await extractDocumentText({\n\t\t\tbuffer: bytes,\n\t\t\tfileName: attachment.fileName,\n\t\t\tmimeType: attachment.mimeType,\n\t\t});\n\n\t\tconst sessionFile = sessionManager.getSessionFileById(sessionId);\n\t\tif (sessionFile && typeof extracted.extractedText === \"string\") {\n\t\t\ttry {\n\t\t\t\tsessionManager.saveAttachmentExtraction(\n\t\t\t\t\tsessionFile,\n\t\t\t\t\tattachmentId,\n\t\t\t\t\textracted.extractedText,\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\t// ignore persistence errors; extraction result still returned\n\t\t\t}\n\t\t}\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tfileName: attachment.fileName,\n\t\t\t\tformat: extracted.format,\n\t\t\t\tsize: extracted.sizeBytes,\n\t\t\t\ttruncated: extracted.truncated,\n\t\t\t\textractedText: extracted.extractedText,\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (error) {\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t}\n}\n"]}
1
+ {"version":3,"file":"session-attachments.js","sourceRoot":"","sources":["../../../src/server/handlers/session-attachments.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extractDocumentText } from \"../../utils/document-extractor.js\";\nimport {\n\tbuildContentDisposition,\n\trespondWithApiError,\n\tsendJson,\n} from \"../server-utils.js\";\nimport { createWebSessionManagerForRequest } from \"../session-scope.js\";\n\nconst sessionIdPattern = /^[a-zA-Z0-9._-]+$/;\nconst attachmentIdPattern = /^[a-zA-Z0-9._-]+$/;\n\nfunction findAttachmentInSession(\n\tsession: { messages?: Array<unknown> },\n\tattachmentId: string,\n): {\n\tfileName: string;\n\tmimeType: string;\n\tcontentBase64: string;\n\tsize?: number;\n\textractedText?: string;\n} | null {\n\tconst messages = Array.isArray(session.messages) ? session.messages : [];\n\tfor (const msg of messages) {\n\t\tif (!msg || typeof msg !== \"object\") continue;\n\t\tconst maybeAttachments = (msg as { attachments?: unknown }).attachments;\n\t\tif (!Array.isArray(maybeAttachments)) continue;\n\n\t\tfor (const att of maybeAttachments) {\n\t\t\tif (!att || typeof att !== \"object\") continue;\n\t\t\tconst a = att as {\n\t\t\t\tid?: unknown;\n\t\t\t\tfileName?: unknown;\n\t\t\t\tmimeType?: unknown;\n\t\t\t\tcontent?: unknown;\n\t\t\t\tsize?: unknown;\n\t\t\t\textractedText?: unknown;\n\t\t\t};\n\t\t\tif (a.id !== attachmentId) continue;\n\t\t\tif (typeof a.fileName !== \"string\" || !a.fileName) return null;\n\t\t\tif (typeof a.mimeType !== \"string\" || !a.mimeType) return null;\n\t\t\tif (typeof a.content !== \"string\" || !a.content) return null;\n\t\t\treturn {\n\t\t\t\tfileName: a.fileName,\n\t\t\t\tmimeType: a.mimeType,\n\t\t\t\tcontentBase64: a.content,\n\t\t\t\tsize:\n\t\t\t\t\ttypeof a.size === \"number\" && Number.isFinite(a.size)\n\t\t\t\t\t\t? a.size\n\t\t\t\t\t\t: undefined,\n\t\t\t\textractedText:\n\t\t\t\t\ttypeof a.extractedText === \"string\" && a.extractedText.length > 0\n\t\t\t\t\t\t? a.extractedText\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t}\n\t}\n\treturn null;\n}\n\nexport async function handleSessionAttachment(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; attachmentId: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\n\ttry {\n\t\tif (req.method !== \"GET\") {\n\t\t\tsendJson(res, 405, { error: \"Method not allowed\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst sessionId = params.id;\n\t\tconst attachmentId = params.attachmentId;\n\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tif (!attachmentIdPattern.test(attachmentId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid attachment id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst session = await sessionManager.loadSession(sessionId);\n\t\tif (!session) {\n\t\t\tsendJson(res, 404, { error: \"Session not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst attachment = findAttachmentInSession(session, attachmentId);\n\t\tif (!attachment) {\n\t\t\tsendJson(res, 404, { error: \"Attachment not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst bytes = Buffer.from(attachment.contentBase64, \"base64\");\n\n\t\tconst requestUrl = new URL(req.url || \"/\", \"http://localhost\");\n\t\tconst download = requestUrl.searchParams.get(\"download\");\n\t\tconst shouldDownload = download === \"1\" || download === \"true\";\n\n\t\tres.writeHead(200, {\n\t\t\t\"Content-Type\": attachment.mimeType,\n\t\t\t\"Content-Length\": bytes.length,\n\t\t\t\"Cache-Control\": \"private, max-age=3600\",\n\t\t\t...(shouldDownload\n\t\t\t\t? {\n\t\t\t\t\t\t\"Content-Disposition\": buildContentDisposition(attachment.fileName),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...cors,\n\t\t});\n\t\tres.end(bytes);\n\t} catch (error) {\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t}\n}\n\nexport async function handleSessionAttachmentExtract(\n\treq: IncomingMessage,\n\tres: ServerResponse,\n\tparams: { id: string; attachmentId: string },\n\tcors: Record<string, string>,\n) {\n\tconst sessionManager = createWebSessionManagerForRequest(req, true);\n\n\ttry {\n\t\tif (req.method !== \"POST\") {\n\t\t\tsendJson(res, 405, { error: \"Method not allowed\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst sessionId = params.id;\n\t\tconst attachmentId = params.attachmentId;\n\n\t\tif (!sessionIdPattern.test(sessionId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid session id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\t\tif (!attachmentIdPattern.test(attachmentId)) {\n\t\t\tsendJson(res, 400, { error: \"Invalid attachment id\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst requestUrl = new URL(req.url || \"/\", \"http://localhost\");\n\t\tconst force = requestUrl.searchParams.get(\"force\");\n\t\tconst shouldForce = force === \"1\" || force === \"true\";\n\n\t\tconst session = await sessionManager.loadSession(sessionId);\n\t\tif (!session) {\n\t\t\tsendJson(res, 404, { error: \"Session not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tconst attachment = findAttachmentInSession(session, attachmentId);\n\t\tif (!attachment) {\n\t\t\tsendJson(res, 404, { error: \"Attachment not found\" }, cors, req);\n\t\t\treturn;\n\t\t}\n\n\t\tif (attachment.extractedText && !shouldForce) {\n\t\t\tsendJson(\n\t\t\t\tres,\n\t\t\t\t200,\n\t\t\t\t{\n\t\t\t\t\tfileName: attachment.fileName,\n\t\t\t\t\tformat: \"unknown\",\n\t\t\t\t\textractor: \"native\",\n\t\t\t\t\tsize: attachment.size ?? 0,\n\t\t\t\t\ttruncated: false,\n\t\t\t\t\textractedText: attachment.extractedText,\n\t\t\t\t\tcached: true,\n\t\t\t\t},\n\t\t\t\tcors,\n\t\t\t\treq,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst bytes = Buffer.from(attachment.contentBase64, \"base64\");\n\t\tconst extracted = await extractDocumentText({\n\t\t\tbuffer: bytes,\n\t\t\tfileName: attachment.fileName,\n\t\t\tmimeType: attachment.mimeType,\n\t\t});\n\n\t\tconst sessionFile = sessionManager.getSessionFileById(sessionId);\n\t\tif (sessionFile && typeof extracted.extractedText === \"string\") {\n\t\t\ttry {\n\t\t\t\tsessionManager.saveAttachmentExtraction(\n\t\t\t\t\tsessionFile,\n\t\t\t\t\tattachmentId,\n\t\t\t\t\textracted.extractedText,\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\t// ignore persistence errors; extraction result still returned\n\t\t\t}\n\t\t}\n\n\t\tsendJson(\n\t\t\tres,\n\t\t\t200,\n\t\t\t{\n\t\t\t\tfileName: attachment.fileName,\n\t\t\t\tformat: extracted.format,\n\t\t\t\textractor: extracted.extractor,\n\t\t\t\tsize: extracted.sizeBytes,\n\t\t\t\ttruncated: extracted.truncated,\n\t\t\t\textractedText: extracted.extractedText,\n\t\t\t},\n\t\t\tcors,\n\t\t\treq,\n\t\t);\n\t} catch (error) {\n\t\trespondWithApiError(res, error, 500, cors, req);\n\t}\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @fileoverview Session Management HTTP Handlers
3
3
  *
4
- * This module provides REST API endpoints for managing Composer sessions,
4
+ * This module provides REST API endpoints for managing Maestro sessions,
5
5
  * including CRUD operations, session sharing, and export functionality.
6
6
  *
7
7
  * ## Endpoints