@maudecode/talaria-web 1.17.2 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (623) hide show
  1. package/_release.json +8 -8
  2. package/dist/api/auth-raw.d.ts +1 -1
  3. package/dist/api/auth-raw.js +20 -20
  4. package/dist/api/auth-raw.js.map +1 -1
  5. package/dist/api/automation-raw.d.ts +7 -1
  6. package/dist/api/automation-raw.js +74 -27
  7. package/dist/api/automation-raw.js.map +1 -1
  8. package/dist/api/automation-router.d.ts +128 -23
  9. package/dist/api/automation-router.js +29 -13
  10. package/dist/api/automation-router.js.map +1 -1
  11. package/dist/api/chat-router.d.ts +1845 -40
  12. package/dist/api/chat-router.js +196 -114
  13. package/dist/api/chat-router.js.map +1 -1
  14. package/dist/api/git-router.d.ts +37 -3
  15. package/dist/api/git-router.js +47 -48
  16. package/dist/api/git-router.js.map +1 -1
  17. package/dist/api/raw-routes.d.ts +9 -1
  18. package/dist/api/raw-routes.js +286 -73
  19. package/dist/api/raw-routes.js.map +1 -1
  20. package/dist/api/router.d.ts +16 -6
  21. package/dist/api/router.js +28 -26
  22. package/dist/api/router.js.map +1 -1
  23. package/dist/api/session-visibility.d.ts +4 -4
  24. package/dist/api/session-visibility.js +26 -16
  25. package/dist/api/session-visibility.js.map +1 -1
  26. package/dist/api/sessions-router.d.ts +3312 -131
  27. package/dist/api/sessions-router.js +287 -157
  28. package/dist/api/sessions-router.js.map +1 -1
  29. package/dist/api/settings-router.d.ts +457 -8
  30. package/dist/api/settings-router.js +54 -33
  31. package/dist/api/settings-router.js.map +1 -1
  32. package/dist/api/sse-routes.d.ts +7 -2
  33. package/dist/api/sse-routes.js +109 -62
  34. package/dist/api/sse-routes.js.map +1 -1
  35. package/dist/api/tools-raw.d.ts +5 -0
  36. package/dist/api/tools-raw.js +63 -55
  37. package/dist/api/tools-raw.js.map +1 -1
  38. package/dist/api/tools-router.d.ts +998 -85
  39. package/dist/api/tools-router.js +447 -61
  40. package/dist/api/tools-router.js.map +1 -1
  41. package/dist/api/transcribe-stream.d.ts +16 -0
  42. package/dist/api/transcribe-stream.js +172 -0
  43. package/dist/api/transcribe-stream.js.map +1 -0
  44. package/dist/app.d.ts +4 -1
  45. package/dist/app.js +98 -59
  46. package/dist/app.js.map +1 -1
  47. package/dist/auth/gate.js +15 -11
  48. package/dist/auth/gate.js.map +1 -1
  49. package/dist/auth/oidc.d.ts +5 -2
  50. package/dist/auth/oidc.js +8 -7
  51. package/dist/auth/oidc.js.map +1 -1
  52. package/dist/auth/passkeys.d.ts +15 -14
  53. package/dist/auth/passkeys.js +89 -91
  54. package/dist/auth/passkeys.js.map +1 -1
  55. package/dist/auth/store.d.ts +17 -7
  56. package/dist/auth/store.js +93 -52
  57. package/dist/auth/store.js.map +1 -1
  58. package/dist/bin/talaria-web.js +12 -81
  59. package/dist/bin/talaria-web.js.map +1 -1
  60. package/dist/cli/ctl.js +2 -1
  61. package/dist/cli/ctl.js.map +1 -1
  62. package/dist/cli/dotenv.d.ts +5 -0
  63. package/dist/cli/dotenv.js +15 -2
  64. package/dist/cli/dotenv.js.map +1 -1
  65. package/dist/cli/launcher.js +5 -5
  66. package/dist/cli/launcher.js.map +1 -1
  67. package/dist/cli/main.d.ts +1 -0
  68. package/dist/cli/main.js +85 -0
  69. package/dist/cli/main.js.map +1 -0
  70. package/dist/cli/supervise.d.ts +2 -0
  71. package/dist/cli/supervise.js +67 -4
  72. package/dist/cli/supervise.js.map +1 -1
  73. package/dist/config/agent-config.d.ts +34 -11
  74. package/dist/config/agent-config.js +116 -60
  75. package/dist/config/agent-config.js.map +1 -1
  76. package/dist/config.d.ts +4 -0
  77. package/dist/config.js +19 -6
  78. package/dist/config.js.map +1 -1
  79. package/dist/fs/atomic.d.ts +1 -0
  80. package/dist/fs/atomic.js +4 -1
  81. package/dist/fs/atomic.js.map +1 -1
  82. package/dist/fs/stat.d.ts +1 -0
  83. package/dist/fs/stat.js +11 -0
  84. package/dist/fs/stat.js.map +1 -0
  85. package/dist/http/context.d.ts +31 -12
  86. package/dist/http/context.js +60 -24
  87. package/dist/http/context.js.map +1 -1
  88. package/dist/http/csp.d.ts +2 -1
  89. package/dist/http/csp.js +3 -2
  90. package/dist/http/csp.js.map +1 -1
  91. package/dist/onboarding.d.ts +2 -2
  92. package/dist/onboarding.js +10 -8
  93. package/dist/onboarding.js.map +1 -1
  94. package/dist/profiles/profiles.d.ts +20 -4
  95. package/dist/profiles/profiles.js +115 -30
  96. package/dist/profiles/profiles.js.map +1 -1
  97. package/dist/projects.d.ts +15 -6
  98. package/dist/projects.js +55 -47
  99. package/dist/projects.js.map +1 -1
  100. package/dist/providers/catalog.d.ts +84 -14
  101. package/dist/providers/catalog.js +474 -151
  102. package/dist/providers/catalog.js.map +1 -1
  103. package/dist/providers/env-file.d.ts +10 -3
  104. package/dist/providers/env-file.js +24 -75
  105. package/dist/providers/env-file.js.map +1 -1
  106. package/dist/providers/runtime-env.d.ts +4 -2
  107. package/dist/providers/runtime-env.js +9 -6
  108. package/dist/providers/runtime-env.js.map +1 -1
  109. package/dist/providers/tables.d.ts +3 -1
  110. package/dist/providers/tables.js +4 -2
  111. package/dist/providers/tables.js.map +1 -1
  112. package/dist/raster-image.d.ts +7 -0
  113. package/dist/raster-image.js +267 -0
  114. package/dist/raster-image.js.map +1 -0
  115. package/dist/redact.js +342 -46
  116. package/dist/redact.js.map +1 -1
  117. package/dist/release.d.ts +7 -0
  118. package/dist/release.js +14 -0
  119. package/dist/release.js.map +1 -1
  120. package/dist/runtime.d.ts +5 -1
  121. package/dist/runtime.js +305 -96
  122. package/dist/runtime.js.map +1 -1
  123. package/dist/server.js +15 -0
  124. package/dist/server.js.map +1 -1
  125. package/dist/sessions/anchor.d.ts +9 -3
  126. package/dist/sessions/anchor.js +28 -36
  127. package/dist/sessions/anchor.js.map +1 -1
  128. package/dist/sessions/background-events.d.ts +2 -0
  129. package/dist/sessions/background-events.js +10 -0
  130. package/dist/sessions/background-events.js.map +1 -0
  131. package/dist/sessions/background-tasks.d.ts +26 -27
  132. package/dist/sessions/background-tasks.js +89 -97
  133. package/dist/sessions/background-tasks.js.map +1 -1
  134. package/dist/sessions/background-updates.d.ts +15 -8
  135. package/dist/sessions/background-updates.js +101 -25
  136. package/dist/sessions/background-updates.js.map +1 -1
  137. package/dist/sessions/cli-sessions.d.ts +27 -6
  138. package/dist/sessions/cli-sessions.js +152 -42
  139. package/dist/sessions/cli-sessions.js.map +1 -1
  140. package/dist/sessions/completions.d.ts +77 -9
  141. package/dist/sessions/completions.js +482 -45
  142. package/dist/sessions/completions.js.map +1 -1
  143. package/dist/sessions/compress.d.ts +8 -0
  144. package/dist/sessions/compress.js +2 -2
  145. package/dist/sessions/compress.js.map +1 -1
  146. package/dist/sessions/drafts.d.ts +14 -10
  147. package/dist/sessions/drafts.js +38 -43
  148. package/dist/sessions/drafts.js.map +1 -1
  149. package/dist/sessions/export.d.ts +5 -0
  150. package/dist/sessions/export.js +30 -0
  151. package/dist/sessions/export.js.map +1 -1
  152. package/dist/sessions/gateway-sessions.d.ts +46 -0
  153. package/dist/sessions/gateway-sessions.js +378 -0
  154. package/dist/sessions/gateway-sessions.js.map +1 -0
  155. package/dist/sessions/gateway-watcher.d.ts +7 -3
  156. package/dist/sessions/gateway-watcher.js +31 -19
  157. package/dist/sessions/gateway-watcher.js.map +1 -1
  158. package/dist/sessions/goals.d.ts +31 -0
  159. package/dist/sessions/goals.js +75 -0
  160. package/dist/sessions/goals.js.map +1 -0
  161. package/dist/sessions/handoff.d.ts +32 -0
  162. package/dist/sessions/handoff.js +114 -0
  163. package/dist/sessions/handoff.js.map +1 -0
  164. package/dist/sessions/journal.d.ts +5 -79
  165. package/dist/sessions/journal.js +15 -606
  166. package/dist/sessions/journal.js.map +1 -1
  167. package/dist/sessions/list.d.ts +31 -16
  168. package/dist/sessions/list.js +139 -129
  169. package/dist/sessions/list.js.map +1 -1
  170. package/dist/sessions/merge.d.ts +69 -13
  171. package/dist/sessions/merge.js +265 -64
  172. package/dist/sessions/merge.js.map +1 -1
  173. package/dist/sessions/notices.d.ts +22 -0
  174. package/dist/sessions/notices.js +72 -0
  175. package/dist/sessions/notices.js.map +1 -0
  176. package/dist/sessions/pending.d.ts +10 -4
  177. package/dist/sessions/pending.js +83 -7
  178. package/dist/sessions/pending.js.map +1 -1
  179. package/dist/sessions/prefix-index.d.ts +82 -0
  180. package/dist/sessions/prefix-index.js +232 -0
  181. package/dist/sessions/prefix-index.js.map +1 -0
  182. package/dist/sessions/recovery.d.ts +19 -0
  183. package/dist/sessions/recovery.js +322 -0
  184. package/dist/sessions/recovery.js.map +1 -0
  185. package/dist/sessions/relay.d.ts +38 -19
  186. package/dist/sessions/relay.js +302 -79
  187. package/dist/sessions/relay.js.map +1 -1
  188. package/dist/sessions/service.d.ts +260 -55
  189. package/dist/sessions/service.js +1448 -462
  190. package/dist/sessions/service.js.map +1 -1
  191. package/dist/sessions/session.d.ts +24 -2
  192. package/dist/sessions/session.js +69 -7
  193. package/dist/sessions/session.js.map +1 -1
  194. package/dist/sessions/shares.d.ts +7 -6
  195. package/dist/sessions/shares.js +22 -45
  196. package/dist/sessions/shares.js.map +1 -1
  197. package/dist/sessions/source-kind.js +1 -0
  198. package/dist/sessions/source-kind.js.map +1 -1
  199. package/dist/sessions/state-db-identity.d.ts +18 -0
  200. package/dist/sessions/state-db-identity.js +67 -0
  201. package/dist/sessions/state-db-identity.js.map +1 -0
  202. package/dist/sessions/state-db-worker.d.ts +1 -0
  203. package/dist/sessions/state-db-worker.js +35 -0
  204. package/dist/sessions/state-db-worker.js.map +1 -0
  205. package/dist/sessions/state-db.d.ts +113 -7
  206. package/dist/sessions/state-db.js +861 -44
  207. package/dist/sessions/state-db.js.map +1 -1
  208. package/dist/sessions/storage/backend.d.ts +162 -0
  209. package/dist/sessions/storage/backend.js +19 -0
  210. package/dist/sessions/storage/backend.js.map +1 -0
  211. package/dist/sessions/storage/conformance.d.ts +20 -0
  212. package/dist/sessions/storage/conformance.js +237 -0
  213. package/dist/sessions/storage/conformance.js.map +1 -0
  214. package/dist/sessions/storage/document.d.ts +16 -0
  215. package/dist/sessions/storage/document.js +44 -0
  216. package/dist/sessions/storage/document.js.map +1 -0
  217. package/dist/sessions/storage/json-documents.d.ts +23 -0
  218. package/dist/sessions/storage/json-documents.js +233 -0
  219. package/dist/sessions/storage/json-documents.js.map +1 -0
  220. package/dist/sessions/storage/json-files.d.ts +12 -0
  221. package/dist/sessions/storage/json-files.js +124 -0
  222. package/dist/sessions/storage/json-files.js.map +1 -0
  223. package/dist/sessions/storage/json-installation.d.ts +3 -0
  224. package/dist/sessions/storage/json-installation.js +31 -0
  225. package/dist/sessions/storage/json-installation.js.map +1 -0
  226. package/dist/sessions/storage/json-journal.d.ts +114 -0
  227. package/dist/sessions/storage/json-journal.js +686 -0
  228. package/dist/sessions/storage/json-journal.js.map +1 -0
  229. package/dist/sessions/storage/json-recovery.d.ts +4 -0
  230. package/dist/sessions/storage/json-recovery.js +195 -0
  231. package/dist/sessions/storage/json-recovery.js.map +1 -0
  232. package/dist/sessions/storage/json.d.ts +68 -0
  233. package/dist/sessions/storage/json.js +258 -0
  234. package/dist/sessions/storage/json.js.map +1 -0
  235. package/dist/sessions/storage/row.d.ts +6 -0
  236. package/dist/sessions/storage/row.js +49 -0
  237. package/dist/sessions/storage/row.js.map +1 -0
  238. package/dist/sessions/storage/search-text.d.ts +4 -0
  239. package/dist/sessions/storage/search-text.js +16 -0
  240. package/dist/sessions/storage/search-text.js.map +1 -0
  241. package/dist/sessions/store.d.ts +65 -68
  242. package/dist/sessions/store.js +305 -602
  243. package/dist/sessions/store.js.map +1 -1
  244. package/dist/sessions/streams.d.ts +4 -0
  245. package/dist/sessions/streams.js +9 -1
  246. package/dist/sessions/streams.js.map +1 -1
  247. package/dist/sessions/titles.d.ts +2 -0
  248. package/dist/sessions/titles.js +5 -1
  249. package/dist/sessions/titles.js.map +1 -1
  250. package/dist/sessions/todo.d.ts +5 -0
  251. package/dist/sessions/todo.js +28 -21
  252. package/dist/sessions/todo.js.map +1 -1
  253. package/dist/sessions/tool-display.d.ts +5 -4
  254. package/dist/sessions/tool-display.js +30 -50
  255. package/dist/sessions/tool-display.js.map +1 -1
  256. package/dist/sessions/turn-context.d.ts +11 -2
  257. package/dist/sessions/turn-context.js +18 -11
  258. package/dist/sessions/turn-context.js.map +1 -1
  259. package/dist/sessions/turn.d.ts +122 -17
  260. package/dist/sessions/turn.js +939 -358
  261. package/dist/sessions/turn.js.map +1 -1
  262. package/dist/sessions/wakeup-pause.d.ts +54 -0
  263. package/dist/sessions/wakeup-pause.js +163 -0
  264. package/dist/sessions/wakeup-pause.js.map +1 -0
  265. package/dist/sessions/window.js +13 -12
  266. package/dist/sessions/window.js.map +1 -1
  267. package/dist/settings.d.ts +19 -7
  268. package/dist/settings.js +178 -184
  269. package/dist/settings.js.map +1 -1
  270. package/dist/sidecar/client.d.ts +17 -3
  271. package/dist/sidecar/client.js +78 -8
  272. package/dist/sidecar/client.js.map +1 -1
  273. package/dist/sidecar/discover.d.ts +2 -1
  274. package/dist/sidecar/discover.js +93 -10
  275. package/dist/sidecar/discover.js.map +1 -1
  276. package/dist/sidecar/env.d.ts +4 -0
  277. package/dist/sidecar/env.js +3 -0
  278. package/dist/sidecar/env.js.map +1 -0
  279. package/dist/sidecar/fake.d.ts +2 -2
  280. package/dist/sidecar/fake.js +19 -2
  281. package/dist/sidecar/fake.js.map +1 -1
  282. package/dist/startup.d.ts +13 -5
  283. package/dist/startup.js +48 -0
  284. package/dist/startup.js.map +1 -1
  285. package/dist/test/env-file.d.ts +5 -0
  286. package/dist/test/env-file.js +88 -0
  287. package/dist/test/env-file.js.map +1 -0
  288. package/dist/test/harness.d.ts +1 -0
  289. package/dist/test/harness.js +1 -1
  290. package/dist/test/harness.js.map +1 -1
  291. package/dist/test/passkeys.d.ts +22 -0
  292. package/dist/test/passkeys.js +62 -0
  293. package/dist/test/passkeys.js.map +1 -0
  294. package/dist/test/storage.d.ts +15 -0
  295. package/dist/test/storage.js +26 -0
  296. package/dist/test/storage.js.map +1 -0
  297. package/dist/test/ts-worker-hooks.d.ts +1 -0
  298. package/dist/test/ts-worker-hooks.js +24 -0
  299. package/dist/test/ts-worker-hooks.js.map +1 -0
  300. package/dist/text/diff.d.ts +9 -14
  301. package/dist/text/diff.js +74 -108
  302. package/dist/text/diff.js.map +1 -1
  303. package/dist/tools/commands.d.ts +6 -1
  304. package/dist/tools/commands.js +8 -2
  305. package/dist/tools/commands.js.map +1 -1
  306. package/dist/tools/connectors.d.ts +33 -0
  307. package/dist/tools/connectors.js +121 -0
  308. package/dist/tools/connectors.js.map +1 -0
  309. package/dist/tools/crons.d.ts +38 -1
  310. package/dist/tools/crons.js +122 -18
  311. package/dist/tools/crons.js.map +1 -1
  312. package/dist/tools/dashboard-plugins.d.ts +53 -0
  313. package/dist/tools/dashboard-plugins.js +188 -0
  314. package/dist/tools/dashboard-plugins.js.map +1 -0
  315. package/dist/tools/extensions.d.ts +18 -5
  316. package/dist/tools/extensions.js +344 -266
  317. package/dist/tools/extensions.js.map +1 -1
  318. package/dist/tools/gateway-restart.d.ts +62 -0
  319. package/dist/tools/gateway-restart.js +142 -0
  320. package/dist/tools/gateway-restart.js.map +1 -0
  321. package/dist/tools/health.d.ts +44 -0
  322. package/dist/tools/health.js +201 -46
  323. package/dist/tools/health.js.map +1 -1
  324. package/dist/tools/hygiene.d.ts +4 -3
  325. package/dist/tools/hygiene.js +23 -9
  326. package/dist/tools/hygiene.js.map +1 -1
  327. package/dist/tools/kanban.d.ts +4 -2
  328. package/dist/tools/kanban.js +28 -19
  329. package/dist/tools/kanban.js.map +1 -1
  330. package/dist/tools/mcp.d.ts +13 -0
  331. package/dist/tools/mcp.js +88 -0
  332. package/dist/tools/mcp.js.map +1 -1
  333. package/dist/tools/memory-masks.d.ts +5 -0
  334. package/dist/tools/memory-masks.js +256 -0
  335. package/dist/tools/memory-masks.js.map +1 -0
  336. package/dist/tools/memory.d.ts +29 -3
  337. package/dist/tools/memory.js +69 -27
  338. package/dist/tools/memory.js.map +1 -1
  339. package/dist/tools/plugin-settings.d.ts +15 -0
  340. package/dist/tools/plugin-settings.js +90 -0
  341. package/dist/tools/plugin-settings.js.map +1 -0
  342. package/dist/tools/project-os.d.ts +11 -0
  343. package/dist/tools/project-os.js +267 -0
  344. package/dist/tools/project-os.js.map +1 -0
  345. package/dist/tools/skills.d.ts +14 -5
  346. package/dist/tools/skills.js +49 -16
  347. package/dist/tools/skills.js.map +1 -1
  348. package/dist/tools/update-notifications.d.ts +34 -15
  349. package/dist/tools/update-notifications.js +141 -57
  350. package/dist/tools/update-notifications.js.map +1 -1
  351. package/dist/tools/update-rollback.d.ts +11 -0
  352. package/dist/tools/update-rollback.js +28 -0
  353. package/dist/tools/update-rollback.js.map +1 -0
  354. package/dist/tools/updates.d.ts +110 -32
  355. package/dist/tools/updates.js +1112 -294
  356. package/dist/tools/updates.js.map +1 -1
  357. package/dist/tools/wiki.d.ts +68 -0
  358. package/dist/tools/wiki.js +413 -0
  359. package/dist/tools/wiki.js.map +1 -0
  360. package/dist/util.d.ts +2 -0
  361. package/dist/util.js +5 -0
  362. package/dist/util.js.map +1 -1
  363. package/dist/workspace/escape.d.ts +61 -0
  364. package/dist/workspace/escape.js +149 -0
  365. package/dist/workspace/escape.js.map +1 -0
  366. package/dist/workspace/extract.d.ts +22 -0
  367. package/dist/workspace/extract.js +308 -0
  368. package/dist/workspace/extract.js.map +1 -0
  369. package/dist/workspace/fs.d.ts +12 -0
  370. package/dist/workspace/fs.js +92 -23
  371. package/dist/workspace/fs.js.map +1 -1
  372. package/dist/workspace/git.d.ts +34 -1
  373. package/dist/workspace/git.js +328 -35
  374. package/dist/workspace/git.js.map +1 -1
  375. package/dist/workspace/media.d.ts +16 -13
  376. package/dist/workspace/media.js +43 -61
  377. package/dist/workspace/media.js.map +1 -1
  378. package/dist/workspace/rollback.d.ts +36 -22
  379. package/dist/workspace/rollback.js +178 -272
  380. package/dist/workspace/rollback.js.map +1 -1
  381. package/dist/workspace/unzip.js +4 -1
  382. package/dist/workspace/unzip.js.map +1 -1
  383. package/dist/workspace/upload.d.ts +7 -4
  384. package/dist/workspace/upload.js +5 -2
  385. package/dist/workspace/upload.js.map +1 -1
  386. package/dist/workspace/workspaces.d.ts +15 -19
  387. package/dist/workspace/workspaces.js +55 -127
  388. package/dist/workspace/workspaces.js.map +1 -1
  389. package/dist/workspace/worktrees.d.ts +2 -1
  390. package/dist/workspace/worktrees.js +179 -42
  391. package/dist/workspace/worktrees.js.map +1 -1
  392. package/package.json +7 -3
  393. package/sidecar/agent_dependency.json +4 -4
  394. package/sidecar/agent_support.json +26 -0
  395. package/sidecar/scripts/record-fixtures.py +12 -3
  396. package/sidecar/scripts/replay_sidecar.py +32 -0
  397. package/sidecar/scripts/suite_runner.py +302 -0
  398. package/sidecar/scripts/test.sh +12 -4
  399. package/sidecar/talaria_sidecar/__init__.py +6 -1
  400. package/sidecar/talaria_sidecar/__main__.py +4 -2
  401. package/sidecar/talaria_sidecar/agent_mutation.py +975 -0
  402. package/sidecar/talaria_sidecar/agent_services.py +1053 -0
  403. package/sidecar/talaria_sidecar/dependency_sync.py +85 -0
  404. package/sidecar/talaria_sidecar/home.py +56 -3
  405. package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
  406. package/sidecar/talaria_sidecar/methods/aux.py +166 -24
  407. package/sidecar/talaria_sidecar/methods/chat.py +852 -135
  408. package/sidecar/talaria_sidecar/methods/checkpoints.py +89 -0
  409. package/sidecar/talaria_sidecar/methods/commands.py +294 -4
  410. package/sidecar/talaria_sidecar/methods/config.py +123 -4
  411. package/sidecar/talaria_sidecar/methods/connectors.py +343 -0
  412. package/sidecar/talaria_sidecar/methods/cron.py +395 -36
  413. package/sidecar/talaria_sidecar/methods/cron_execution.py +284 -0
  414. package/sidecar/talaria_sidecar/methods/gateway.py +212 -55
  415. package/sidecar/talaria_sidecar/methods/gateway_sessions.py +234 -0
  416. package/sidecar/talaria_sidecar/methods/goals.py +81 -41
  417. package/sidecar/talaria_sidecar/methods/kanban.py +108 -34
  418. package/sidecar/talaria_sidecar/methods/mcp.py +1 -1
  419. package/sidecar/talaria_sidecar/methods/memory.py +84 -0
  420. package/sidecar/talaria_sidecar/methods/oauth.py +5 -2
  421. package/sidecar/talaria_sidecar/methods/process.py +218 -15
  422. package/sidecar/talaria_sidecar/methods/profiles.py +121 -13
  423. package/sidecar/talaria_sidecar/methods/providers.py +217 -28
  424. package/sidecar/talaria_sidecar/methods/runtime.py +69 -1
  425. package/sidecar/talaria_sidecar/methods/skills.py +67 -4
  426. package/sidecar/talaria_sidecar/methods/state_db.py +316 -75
  427. package/sidecar/talaria_sidecar/methods/stt.py +159 -78
  428. package/sidecar/talaria_sidecar/methods/text.py +14 -1
  429. package/sidecar/talaria_sidecar/methods/toolsets.py +49 -0
  430. package/sidecar/talaria_sidecar/methods/usage.py +113 -14
  431. package/sidecar/talaria_sidecar/methods/worktree.py +26 -19
  432. package/sidecar/talaria_sidecar/methods/write_approval.py +181 -0
  433. package/sidecar/talaria_sidecar/rpc.py +45 -4
  434. package/sidecar/talaria_sidecar/runtime.py +98 -13
  435. package/sidecar/talaria_sidecar/speed.py +35 -0
  436. package/static/dist/FILES.txt +126 -126
  437. package/static/dist/assets/AppShell-cey33v9s.js +8 -0
  438. package/static/dist/assets/ChatPage-i8wnugr7.js +18 -0
  439. package/static/dist/assets/ConnectTargets-hg19553x.js +1 -0
  440. package/static/dist/assets/ExtensionRoute-cly4apm5.js +1 -0
  441. package/static/dist/assets/Field-j8uqoigz.js +9 -0
  442. package/static/dist/assets/HubRoute-e4bgz41j.js +2 -0
  443. package/static/dist/assets/Markdown-lahuichm.js +598 -0
  444. package/static/dist/assets/RightPanel-lbo4i0fn.js +1 -0
  445. package/static/dist/assets/Select-gqatm2e0.js +1 -0
  446. package/static/dist/assets/SessionListPanel-mfqayfjh.js +1 -0
  447. package/static/dist/assets/SettingsLayout-b8980u7k.js +1 -0
  448. package/static/dist/assets/States-e7dkgtxf.js +1 -0
  449. package/static/dist/assets/Toaster-bfqqy786.js +1 -0
  450. package/static/dist/assets/_app-n1n6pfx1.js +1 -0
  451. package/static/dist/assets/{_app.ext._extensionId-opyh9y0v.js → _app.ext._extensionId-buxjxav3.js} +1 -1
  452. package/static/dist/assets/_app.index-jt8zwiu2.js +1 -0
  453. package/static/dist/assets/_app.insights-cv76ml71.js +1 -0
  454. package/static/dist/assets/_app.kanban-h6ts53j7.js +1 -0
  455. package/static/dist/assets/_app.logs-dm873z90.js +1 -0
  456. package/static/dist/assets/_app.memory-glk5y6m8.js +1 -0
  457. package/static/dist/assets/_app.profiles-ka6zpstq.js +1 -0
  458. package/static/dist/assets/{_app.session._sessionId-bfd4h3id.js → _app.session._sessionId-g2vzghvc.js} +1 -1
  459. package/static/dist/assets/_app.settings-hgjdhzcd.js +1 -0
  460. package/static/dist/assets/_app.settings._section-jf2kmhae.js +3 -0
  461. package/static/dist/assets/_app.skills-cii852yq.js +1 -0
  462. package/static/dist/assets/_app.tasks-fp9q7atm.js +1 -0
  463. package/static/dist/assets/_app.todos-dw94qzue.js +1 -0
  464. package/static/dist/assets/_app.workspaces-inyygzze.js +1 -0
  465. package/static/dist/assets/{abnfDiagram-VCTEODGH-b2x1lqot.js → abnfDiagram-VCTEODGH-gjayq3ra.js} +1 -1
  466. package/static/dist/assets/architecture-7GRP2DOG-lp56972r.js +1 -0
  467. package/static/dist/assets/{architectureDiagram-5GKGNRK7-h38o5l7b.js → architectureDiagram-5GKGNRK7-nwb3xovn.js} +1 -1
  468. package/static/dist/assets/archive-b1j004vn.js +1 -0
  469. package/static/dist/assets/back-g74gkozu.js +1 -0
  470. package/static/dist/assets/{blockDiagram-I7D4REHJ-bqquxv2u.js → blockDiagram-I7D4REHJ-joedghi3.js} +1 -1
  471. package/static/dist/assets/{c4Diagram-7LVT6UL2-f3fb8w6z.js → c4Diagram-7LVT6UL2-hyrjrohe.js} +1 -1
  472. package/static/dist/assets/channel-es95o4y8.js +1 -0
  473. package/static/dist/assets/{chunk-4HAMMTFA-bzfyyzp3.js → chunk-4HAMMTFA-koouqbut.js} +1 -1
  474. package/static/dist/assets/{chunk-75Z2AOVW-ly99rfx5.js → chunk-75Z2AOVW-bl4bhdnt.js} +1 -1
  475. package/static/dist/assets/{chunk-DU6HZSFF-bg6ecfqf.js → chunk-DU6HZSFF-gpedttsp.js} +3 -3
  476. package/static/dist/assets/{chunk-F27PBJKO-e8k7mmqw.js → chunk-F27PBJKO-d8xxi0zi.js} +1 -1
  477. package/static/dist/assets/{chunk-GMAD6QVW-cmalnoaj.js → chunk-GMAD6QVW-jro0hl73.js} +1 -1
  478. package/static/dist/assets/{chunk-GVQU2GXP-gmif5o01.js → chunk-GVQU2GXP-djn6gbyu.js} +1 -1
  479. package/static/dist/assets/{chunk-IMKFNOWR-f1nwwh6u.js → chunk-IMKFNOWR-vw4p5p7o.js} +1 -1
  480. package/static/dist/assets/{chunk-L3NEJ4N5-oktfh5v7.js → chunk-L3NEJ4N5-n1hj77q8.js} +1 -1
  481. package/static/dist/assets/{chunk-OSK3NFVY-b1sdx96z.js → chunk-OSK3NFVY-oy0gwn2n.js} +1 -1
  482. package/static/dist/assets/{chunk-P2QGCYS3-fhu4nzxt.js → chunk-P2QGCYS3-onf1hz6c.js} +1 -1
  483. package/static/dist/assets/{chunk-POPQ4Y6H-em31rnef.js → chunk-POPQ4Y6H-m8sqn7cs.js} +1 -1
  484. package/static/dist/assets/{chunk-PWAF6VOD-bxhhyftw.js → chunk-PWAF6VOD-ek4smc8x.js} +1 -1
  485. package/static/dist/assets/{chunk-SHT3W25Y-fmrvwcav.js → chunk-SHT3W25Y-g9gfvefo.js} +3 -3
  486. package/static/dist/assets/{chunk-SVP7TREG-lymukl2j.js → chunk-SVP7TREG-f9nfv2cu.js} +1 -1
  487. package/static/dist/assets/{chunk-TICWLB2K-lmza6k23.js → chunk-TICWLB2K-bnk3m1mq.js} +1 -1
  488. package/static/dist/assets/classDiagram-ZZMXUADV-kmihoqxh.js +1 -0
  489. package/static/dist/assets/classDiagram-v2-VYDZK3BY-kmihoqxh.js +1 -0
  490. package/static/dist/assets/copied-bli9tbcx.js +1 -0
  491. package/static/dist/assets/{copy-fw5b1pc6.js → copy-jamtd1pf.js} +1 -1
  492. package/static/dist/assets/{cynefin-OW5HDTMX-czlhbyhs.js → cynefin-OW5HDTMX-f8xfdd3f.js} +1 -1
  493. package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-gq7mvswb.js → cynefinDiagram-5FMLGOSQ-n9lb99h9.js} +1 -1
  494. package/static/dist/assets/{dagre-GXQ25YYZ-cqdbf7dr.js → dagre-GXQ25YYZ-dgailddi.js} +4 -4
  495. package/static/dist/assets/{diagram-S7CK7UJ4-o6arxa58.js → diagram-S7CK7UJ4-m6aeoe7c.js} +1 -1
  496. package/static/dist/assets/{diagram-UQ7AKVKN-nhnd68tz.js → diagram-UQ7AKVKN-jall3j0x.js} +1 -1
  497. package/static/dist/assets/{diagram-VSXAHHWV-dk2sclzn.js → diagram-VSXAHHWV-hbawi7hn.js} +1 -1
  498. package/static/dist/assets/{diagram-VX7I27RA-n3k5nyx3.js → diagram-VX7I27RA-hendl2tt.js} +1 -1
  499. package/static/dist/assets/{diagram-Z3DM3KII-m6q9cwdh.js → diagram-Z3DM3KII-igwc35p3.js} +1 -1
  500. package/static/dist/assets/{ebnfDiagram-PWID7BFC-lsa5641p.js → ebnfDiagram-PWID7BFC-c64knz08.js} +1 -1
  501. package/static/dist/assets/{erDiagram-RLTQ6QDP-fo2ckbe6.js → erDiagram-RLTQ6QDP-brdu9lcm.js} +1 -1
  502. package/static/dist/assets/eventmodeling-NTZA5JFV-njk1j8wl.js +1 -0
  503. package/static/dist/assets/flowDiagram-HODETNUW-nma6f0ga.js +1 -0
  504. package/static/dist/assets/folder-plus-lvt9kudb.js +1 -0
  505. package/static/dist/assets/{ganttDiagram-EL5Y4UJY-nzqz6x9g.js → ganttDiagram-EL5Y4UJY-ma6jxj5i.js} +1 -1
  506. package/static/dist/assets/{gitGraph-4MIJSDKK-gukvcxe6.js → gitGraph-4MIJSDKK-naa9w6xa.js} +1 -1
  507. package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-lqhdp8f0.js → gitGraphDiagram-WWUBYQGX-hzltvsod.js} +1 -1
  508. package/static/dist/assets/{highlighted-body-KPVGNVTW-igw6cp39.js → highlighted-body-KPVGNVTW-ghoavj8d.js} +1 -1
  509. package/static/dist/assets/host-hzm8n85n.js +1 -0
  510. package/static/dist/assets/index-drdcaqeq.css +2 -0
  511. package/static/dist/assets/index-jzm844he.js +11 -0
  512. package/static/dist/assets/{info-A6RAGUB7-gvu7a93l.js → info-A6RAGUB7-mn2ut5ko.js} +1 -1
  513. package/static/dist/assets/{infoDiagram-27XIBGKW-m8t8g6w1.js → infoDiagram-27XIBGKW-h6kuqvsb.js} +1 -1
  514. package/static/dist/assets/{ishikawaDiagram-5VMMS53U-l07vkbgj.js → ishikawaDiagram-5VMMS53U-e7bnwq7h.js} +1 -1
  515. package/static/dist/assets/{journeyDiagram-3NMN7TZE-hybkgj8l.js → journeyDiagram-3NMN7TZE-etd1bi6p.js} +1 -1
  516. package/static/dist/assets/{kanban-definition-UXKFOSKX-by13uvtn.js → kanban-definition-UXKFOSKX-emb1g9dz.js} +4 -4
  517. package/static/dist/assets/lazyRouteComponent-o816ytzl.js +1 -0
  518. package/static/dist/assets/{line-osxq6fq7.js → line-h0ojzsvs.js} +1 -1
  519. package/static/dist/assets/link-k01ryaf9.js +1 -0
  520. package/static/dist/assets/login-bsae49ew.js +1 -0
  521. package/static/dist/assets/mermaid-HWGCJPDP-ihl34s74.js +1 -0
  522. package/static/dist/assets/{mermaid-parser.core-i91oxmou.js → mermaid-parser.core-bnre27u8.js} +3 -3
  523. package/static/dist/assets/{mindmap-definition-YA3MSWOX-m82mx8ww.js → mindmap-definition-YA3MSWOX-o1vathns.js} +1 -1
  524. package/static/dist/assets/onboarding-c65tysya.js +1 -0
  525. package/static/dist/assets/onboarding_model_label-gpn28uix.js +1 -0
  526. package/static/dist/assets/{packet-AYTQ26CC-nbtgge2o.js → packet-AYTQ26CC-hatq7m2e.js} +1 -1
  527. package/static/dist/assets/pcmTap.worklet-74EKjWAZ.js +1 -0
  528. package/static/dist/assets/{pegDiagram-XKGWAZYB-f1zxzga1.js → pegDiagram-XKGWAZYB-gwisz8jv.js} +1 -1
  529. package/static/dist/assets/{pie-WAS4IAKB-of8vuhxs.js → pie-WAS4IAKB-fpftf0mk.js} +1 -1
  530. package/static/dist/assets/{pieDiagram-E7YTZNPT-o7y8ftio.js → pieDiagram-E7YTZNPT-khm1o9a6.js} +1 -1
  531. package/static/dist/assets/{quadrantDiagram-AXDQQJYC-iqiwia1t.js → quadrantDiagram-AXDQQJYC-owqc4uqn.js} +1 -1
  532. package/static/dist/assets/{radar-RG4KPBEZ-delnsy2v.js → radar-RG4KPBEZ-cntfwjpq.js} +1 -1
  533. package/static/dist/assets/{railroad-74A4TZTK-nspnyq9u.js → railroad-74A4TZTK-a7t5eibp.js} +1 -1
  534. package/static/dist/assets/railroad-abnf-HS5TGJTU-ol8cdktf.js +1 -0
  535. package/static/dist/assets/railroad-ebnf-LZEXJU2U-i8vzd429.js +1 -0
  536. package/static/dist/assets/railroad-peg-WCYAUIDC-nw3ulewz.js +1 -0
  537. package/static/dist/assets/{railroadDiagram-O6MQD6OU-z41tqx5z.js → railroadDiagram-O6MQD6OU-etuh0qa0.js} +1 -1
  538. package/static/dist/assets/{refresh-cw-nt1dtsx4.js → refresh-cw-mqbkv2a3.js} +1 -1
  539. package/static/dist/assets/refresh-l29ljp76.js +1 -0
  540. package/static/dist/assets/{requirementDiagram-BXWQKSXE-bdvif194.js → requirementDiagram-BXWQKSXE-oq2ulk22.js} +1 -1
  541. package/static/dist/assets/{sankeyDiagram-P5KCCOFB-h73e0rol.js → sankeyDiagram-P5KCCOFB-iqc02emv.js} +1 -1
  542. package/static/dist/assets/saved-ndd4t2xb.js +1 -0
  543. package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-iv95mb1z.js → sequenceDiagram-WJ2MYXX4-i0v116q0.js} +2 -2
  544. package/static/dist/assets/settings_section_extensions_title-jhfo6o8z.js +1 -0
  545. package/static/dist/assets/share._token-c1ri0hy1.js +2 -0
  546. package/static/dist/assets/sliders-horizontal-j3jjt9tv.js +1 -0
  547. package/static/dist/assets/{stateDiagram-D77RDMKH-k417ixmf.js → stateDiagram-D77RDMKH-dnpt1ato.js} +1 -1
  548. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-bxjacpk6.js +1 -0
  549. package/static/dist/assets/{swimlanes-42K2YHIH-esola70w.js → swimlanes-42K2YHIH-loqbdazb.js} +1 -1
  550. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-id62p9hz.js +8 -0
  551. package/static/dist/assets/{timeline-definition-24CTP7MA-getrz2y8.js → timeline-definition-24CTP7MA-ol2hnvma.js} +1 -1
  552. package/static/dist/assets/toast-i3h34v6o.js +64 -0
  553. package/static/dist/assets/{treeView-Q6P3EWNA-hc7ap1q7.js → treeView-Q6P3EWNA-idrj6iox.js} +1 -1
  554. package/static/dist/assets/{treemap-WGGIJYW6-b7k1syy5.js → treemap-WGGIJYW6-lzr49vv5.js} +1 -1
  555. package/static/dist/assets/untitled-oaoya4qj.js +1 -0
  556. package/static/dist/assets/useForm-nfaxgmsk.js +1 -0
  557. package/static/dist/assets/{useParams-lhg566ew.js → useParams-gjc70qru.js} +1 -1
  558. package/static/dist/assets/{useSearch-lbrh6ejn.js → useSearch-e6ae539u.js} +1 -1
  559. package/static/dist/assets/{vennDiagram-4TSXK5OY-n6pcy5qb.js → vennDiagram-4TSXK5OY-bvwr9o2z.js} +1 -1
  560. package/static/dist/assets/{wardley-WFR3VGLG-lpa18vz1.js → wardley-WFR3VGLG-31ui8tma.js} +1 -1
  561. package/static/dist/assets/{wardleyDiagram-VM6X3IG4-kpclwwg7.js → wardleyDiagram-VM6X3IG4-k5wqtx4b.js} +1 -1
  562. package/static/dist/assets/{xychartDiagram-S5SC5T6Z-paa2n8y0.js → xychartDiagram-S5SC5T6Z-aqbgvujg.js} +1 -1
  563. package/static/dist/index.html +1 -1
  564. package/static/dist/sw.js +1 -1
  565. package/static/dist/assets/AppShell-fb2td9zi.js +0 -1
  566. package/static/dist/assets/ChatPage-cj96kiy9.js +0 -25
  567. package/static/dist/assets/Dialog-kxcg7ard.js +0 -1
  568. package/static/dist/assets/ExtensionRoute-jf7h0754.js +0 -1
  569. package/static/dist/assets/HubRoute-gmanpd5y.js +0 -2
  570. package/static/dist/assets/Markdown-mdwlvj3w.js +0 -598
  571. package/static/dist/assets/RightPanel-ftvrjlcp.js +0 -1
  572. package/static/dist/assets/Select-bilaypej.js +0 -1
  573. package/static/dist/assets/SessionListPanel-og8n36qs.js +0 -1
  574. package/static/dist/assets/SettingsLayout-jonjefmj.js +0 -1
  575. package/static/dist/assets/States-nmejrwrm.js +0 -1
  576. package/static/dist/assets/Toaster-nnl8zkt9.js +0 -1
  577. package/static/dist/assets/_app-gdidzd94.js +0 -1
  578. package/static/dist/assets/_app.index-hbarzbjx.js +0 -1
  579. package/static/dist/assets/_app.insights-luywlarz.js +0 -1
  580. package/static/dist/assets/_app.kanban-kincnbr8.js +0 -1
  581. package/static/dist/assets/_app.logs-oi2gr3gs.js +0 -1
  582. package/static/dist/assets/_app.memory-b6jfivt6.js +0 -1
  583. package/static/dist/assets/_app.profiles-lpvixmqp.js +0 -1
  584. package/static/dist/assets/_app.settings-vowx3iq0.js +0 -1
  585. package/static/dist/assets/_app.settings._section-cnntg1tu.js +0 -3
  586. package/static/dist/assets/_app.skills-fb57lpau.js +0 -1
  587. package/static/dist/assets/_app.tasks-eszpx1q7.js +0 -2
  588. package/static/dist/assets/_app.todos-nr05ac6w.js +0 -1
  589. package/static/dist/assets/_app.workspaces-d2luomu6.js +0 -1
  590. package/static/dist/assets/architecture-7GRP2DOG-hd0o7bde.js +0 -1
  591. package/static/dist/assets/back-bemaer09.js +0 -1
  592. package/static/dist/assets/cancel-drd0g6d9.js +0 -1
  593. package/static/dist/assets/channel-cpdgf867.js +0 -1
  594. package/static/dist/assets/classDiagram-ZZMXUADV-ko09sguk.js +0 -1
  595. package/static/dist/assets/classDiagram-v2-VYDZK3BY-ko09sguk.js +0 -1
  596. package/static/dist/assets/copied-ima3pysb.js +0 -1
  597. package/static/dist/assets/endpoints-d33siokx.js +0 -64
  598. package/static/dist/assets/eventmodeling-NTZA5JFV-emctlo64.js +0 -1
  599. package/static/dist/assets/flowDiagram-HODETNUW-bfi3moqa.js +0 -1
  600. package/static/dist/assets/index-cxq58xb1.js +0 -11
  601. package/static/dist/assets/index-hgtx08n5.css +0 -2
  602. package/static/dist/assets/lazyRouteComponent-af0lvgjx.js +0 -1
  603. package/static/dist/assets/link-jyxicdhg.js +0 -1
  604. package/static/dist/assets/login-ec21t39x.js +0 -1
  605. package/static/dist/assets/mermaid-HWGCJPDP-gfl8z3ep.js +0 -1
  606. package/static/dist/assets/onboarding-btnltvyz.js +0 -1
  607. package/static/dist/assets/onboarding_model_label-dp7xffoh.js +0 -1
  608. package/static/dist/assets/railroad-abnf-HS5TGJTU-nst1qxyn.js +0 -1
  609. package/static/dist/assets/railroad-ebnf-LZEXJU2U-ci37x8qy.js +0 -1
  610. package/static/dist/assets/railroad-peg-WCYAUIDC-aimkk07z.js +0 -1
  611. package/static/dist/assets/refresh-b4uams1i.js +0 -1
  612. package/static/dist/assets/saved-kg52csy7.js +0 -1
  613. package/static/dist/assets/settings_section_extensions_title-ej0iapxe.js +0 -1
  614. package/static/dist/assets/share._token-f97e94r0.js +0 -2
  615. package/static/dist/assets/sliders-horizontal-fj18it47.js +0 -1
  616. package/static/dist/assets/sse-fwpqtzbg.js +0 -1
  617. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hwn4apct.js +0 -1
  618. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-d1h97oyg.js +0 -8
  619. package/static/dist/assets/todoStore-eginf9h4.js +0 -1
  620. package/static/dist/assets/tts-lxdxnmjd.js +0 -1
  621. package/static/dist/assets/untitled-ovpfthg4.js +0 -1
  622. package/static/dist/assets/useForm-bcblv1rx.js +0 -1
  623. package/static/dist/assets/useLocale-fi5jb8ma.js +0 -1
package/dist/redact.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { str } from './util.js';
2
+ import { diffHunks } from './text/diff.js';
3
+ import { isRasterDataUri } from './raster-image.js';
2
4
  import { snapshotArgs, toolArgs, toolDisplay, toolName } from './sessions/tool-display.js';
3
- import { messageText } from './sessions/merge.js';
5
+ import { hasNativeImages, messageText, normalizeUserDisplay } from './sessions/merge.js';
4
6
  import { stripAttachedFilesMarker } from './sessions/session.js';
5
7
  /**
6
8
  * Credential redaction and the public session projection (Python
@@ -258,39 +260,56 @@ const ANSI_PAYLOAD_GAPS_RE = new RegExp([SEQ_CSI, String.raw `${SEQ_ESC}[\]PX^_]
258
260
  * terminal title can hold a token), and without control characters only (an escape's final byte can be a token's).
259
261
  */
260
262
  const SPLIT_VIEWS = [ANSI_GAPS_RE, ANSI_PAYLOAD_GAPS_RE, CONTROL_CHARS_RE];
263
+ /** `ANSI_GAPS_RE` without the whitespace controls, so a view keeps its lines and words apart. */
264
+ const DISPLAY_GAPS_RE = new RegExp(String.raw `(?![\t-\r])(?:${ANSI_GAPS_RE.source})`, 'g');
261
265
  const ANSI_GAP_AT_RE = new RegExp(ANSI_GAPS_RE.source, 'y');
262
266
  const TOKEN_CHAR_RE = /[A-Za-z0-9_-]/;
267
+ /** A character a credential's prefix or body can hold (`SG.`, `glrt-a.b`, `gAAAA…=`): what a fail-closed run walks. */
268
+ const RUN_CHAR_RE = /[A-Za-z0-9_.=-]/;
263
269
  /** A string sequence's opener, with an OSC's command number (`8;`), which is no payload. */
264
270
  const STRING_OPENER_RE = new RegExp(String.raw `^(?:(?:${SEQ_ESC}\]|\x9d)(?:\d*;)?|${SEQ_ESC}[PX^_]|[\x90\x98\x9e\x9f])`);
265
271
  const PAYLOAD_RUN_CAP = 65_536;
266
- const CRED_TEST_RE = new RegExp(CRED_RE.source);
272
+ /**
273
+ * The token families a split token is joined for, each with its own boundaries: `CRED_RE`'s prefixes, and `JWT_RE`, whose
274
+ * `\b` lets a JWT start after a `-` and which has no right boundary.
275
+ */
276
+ const TOKEN_TEST_RE = new RegExp(`${CRED_RE.source}|${JWT_RE.source}`);
267
277
  /** `CRED_RE`'s prefix and body from a position, without its boundaries (a split token checks the original ones). */
268
278
  const CRED_RUN_RE = new RegExp(CRED_RE.source.replace(/^\(\?<!\[A-Za-z0-9_-\]\)/, '').replace(/\(\?!\[A-Za-z0-9_-\]\)$/, ''), 'y');
279
+ const JWT_RUN_SOURCE = JWT_RE.source.replace(/^\\b/, '');
280
+ /** A credential's or JWT's prefix and body from a position, without its boundaries. */
281
+ const TOKEN_RUN_RE = new RegExp(`${CRED_RUN_RE.source}|${JWT_RUN_SOURCE}`, 'y');
269
282
  const SPLIT_TOKEN_CAP = 1024;
270
283
  /** Where a `CRED_RE` prefix and body start at a boundary, however they end. */
271
284
  const CRED_START_RE = new RegExp(CRED_RE.source.replace(/\(\?!\[A-Za-z0-9_-\]\)$/, ''), 'g');
272
- const CRED_WHOLE_RE = new RegExp(`^${CRED_RE.source}$`);
273
- /** `CRED_START_RE` and `CRED_RUN_RE` without their body: a credential's prefix, however little of its body follows. */
274
- const CRED_PREFIX_RE = new RegExp(CRED_START_RE.source.replace(/\{\d+,?\}/g, '{0}'), 'g');
275
- const CRED_PREFIX_RUN_RE = new RegExp(CRED_RUN_RE.source.replace(/\{\d+,?\}/g, '{0}'), 'y');
285
+ const TOKEN_START_RE = new RegExp(`${CRED_START_RE.source}|${JWT_RE.source}`, 'g');
286
+ const TOKEN_WHOLE_RE = new RegExp(`^(?:${CRED_RE.source}|${JWT_RE.source})$`);
287
+ /** `TOKEN_START_RE` and `TOKEN_RUN_RE` without their body: a token's prefix, however little of its body follows. */
288
+ const TOKEN_PREFIX_RE = new RegExp(`${CRED_START_RE.source.replace(/\{\d+,?\}/g, '{0}')}|\\beyJ`, 'g');
289
+ const TOKEN_PREFIX_RUN_RE = new RegExp(`${CRED_RUN_RE.source.replace(/\{\d+,?\}/g, '{0}')}|eyJ`, 'y');
276
290
  /** A URL query parameter's value, up to the next `&` or `#`. */
277
291
  const QUERY_VALUE_RE = /[^&#]*/y;
278
- const PRIVKEY_RE = /-----BEGIN[A-Z ]*PRIVATE KEY-----[\s\S]*?-----END[A-Z ]*PRIVATE KEY-----/g;
279
- /** A private key whose end marker is missing (a display cap cut it off): masked to the end of the text. */
280
- const PRIVKEY_OPEN_RE = /-----BEGIN[A-Z ]*PRIVATE KEY-----[\s\S]*$/;
292
+ const PEM_OPENER = '-----BEGIN';
293
+ /**
294
+ * A private key through its end marker (captured) or, when that is missing (a display cap cut it off), to the end of the
295
+ * text.
296
+ */
297
+ const PRIVKEY_RE = /-----BEGIN[A-Z ]*PRIVATE KEY-----(?:[\s\S]*?(-----END[A-Z ]*PRIVATE KEY-----)|[\s\S]*$)/g;
298
+ /** `PRIVKEY_RE` after its opener, from a position. */
299
+ const PRIVKEY_REST_RE = new RegExp(PRIVKEY_RE.source.slice(PEM_OPENER.length), 'y');
281
300
  const CODE_ENV_KEY_LITERAL_RE = /([A-Z0-9_]{0,50}(?:API_?KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)[A-Z0-9_]{0,50}=)(["'][)\]:,]+|[)\]:,]+)/y;
282
301
  const ENV_KEY_PREFIX_RE = /([A-Z0-9_]{0,50}(?:API_?KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)[A-Z0-9_]{0,50}=)/g;
283
302
  const REDACTED_ENV_VALUE_RE = /(?:\*{3,}|[A-Za-z0-9][A-Za-z0-9_.:/+-]{0,32}\.\.\.[A-Za-z0-9_.:/+-]{1,16})/y;
284
303
  /**
285
- * Where a credential split by control or zero-width characters (`ghp_abc\x1bdef`, `ghp_abc\ndef…`) starting at `i` of the
304
+ * Where a credential or JWT split by control or zero-width characters (`ghp_abc\x1bdef`, `ghp_abc\ndef…`) starting at `i` of the
286
305
  * stripped text ends there, or -1. The run of its prefix and body is read once (capped), then the longest candidate is
287
- * taken that ends at a piece boundary of the original, is a whole credential, is not the name of a `KEY=` that follows,
306
+ * taken that ends at a piece boundary of the original, is a whole token, is not the name of a `KEY=` that follows,
288
307
  * and never reaches a line holding a whole token itself (that line is the prefix pass's and joins nothing).
289
308
  */
290
309
  function splitTokenEnd(text, stripped, kept, i) {
291
- CRED_RUN_RE.lastIndex = 0;
310
+ TOKEN_RUN_RE.lastIndex = 0;
292
311
  // ponytail: a split credential longer than SPLIT_TOKEN_CAP is cut at the cap; raise it if longer tokens appear.
293
- const run = CRED_RUN_RE.exec(stripped.slice(i, i + SPLIT_TOKEN_CAP))?.[0];
312
+ const run = TOKEN_RUN_RE.exec(stripped.slice(i, i + SPLIT_TOKEN_CAP))?.[0];
294
313
  if (!run)
295
314
  return -1;
296
315
  const start = kept[i];
@@ -298,7 +317,7 @@ function splitTokenEnd(text, stripped, kept, i) {
298
317
  for (let lineStart = start; lineStart < limit;) {
299
318
  const lineEnd = text.slice(lineStart, limit).search(/[\r\n]/);
300
319
  const end = lineEnd === -1 ? limit : lineStart + lineEnd;
301
- if (CRED_TEST_RE.test(text.slice(lineStart, end))) {
320
+ if (TOKEN_TEST_RE.test(text.slice(lineStart, end))) {
302
321
  limit = lineStart === start ? end : lineStart;
303
322
  break;
304
323
  }
@@ -309,23 +328,17 @@ function splitTokenEnd(text, stripped, kept, i) {
309
328
  for (let e = i + run.length; e > i; e -= 1) {
310
329
  const atBoundary = e === stripped.length || kept[e] - kept[e - 1] > 1 || (e === i + run.length && !/[A-Za-z0-9_-]/.test(stripped[e]));
311
330
  const originalEnd = kept[e - 1] + 1;
312
- if (!atBoundary || originalEnd > limit || !CRED_WHOLE_RE.test(stripped.slice(i, e)) || /^[ \t]*=/.test(text.slice(originalEnd, originalEnd + 64)))
331
+ if (!atBoundary || originalEnd > limit || !TOKEN_WHOLE_RE.test(stripped.slice(i, e)) || /^[ \t]*=/.test(text.slice(originalEnd, originalEnd + 64)))
313
332
  continue;
314
333
  return e;
315
334
  }
316
335
  return -1;
317
336
  }
318
- /**
319
- * The original spans, and the joined text, of prefixed credentials whose body a gap of one of `SPLIT_VIEWS` splits,
320
- * matched on the text without those gaps, plus `payloadRunSpan`'s from each prefix. A token starts at a boundary of the
321
- * stripped text, or where a stripped gap hid the original one (`note\nghp_…`); one starting inside a token already
322
- * masked is part of it.
323
- */
324
- function splitTokenSpans(text, gaps) {
337
+ /** The text without the gaps of `gaps`, and the original index of each kept character, or null when it has none. */
338
+ function splitView(text, gaps) {
325
339
  const stripped = text.replace(gaps, '');
326
340
  if (stripped.length === text.length)
327
- return [];
328
- // The original index of each kept character.
341
+ return null;
329
342
  const kept = [];
330
343
  let at = 0;
331
344
  for (const m of text.matchAll(gaps)) {
@@ -335,14 +348,27 @@ function splitTokenSpans(text, gaps) {
335
348
  }
336
349
  while (at < text.length)
337
350
  kept.push(at++);
338
- const starts = [...stripped.matchAll(CRED_START_RE)].map((m) => m.index);
339
- const prefixStarts = [...stripped.matchAll(CRED_PREFIX_RE)].map((m) => m.index);
351
+ return { stripped, kept };
352
+ }
353
+ /**
354
+ * The original spans, and the joined text, of prefixed credentials and JWTs whose body a gap of one of `SPLIT_VIEWS` splits,
355
+ * matched on the text without those gaps, plus `payloadRunSpan`'s from each prefix. A token starts at a boundary of the
356
+ * stripped text, or where a stripped gap hid the original one (`note\nghp_…`); one starting inside a token already
357
+ * masked is part of it.
358
+ */
359
+ function splitTokenSpans(text, gaps) {
360
+ const view = splitView(text, gaps);
361
+ if (!view)
362
+ return [];
363
+ const { stripped, kept } = view;
364
+ const starts = [...stripped.matchAll(TOKEN_START_RE)].map((m) => m.index);
365
+ const prefixStarts = [...stripped.matchAll(TOKEN_PREFIX_RE)].map((m) => m.index);
340
366
  for (let i = 1; i < kept.length; i += 1) {
341
367
  if (kept[i] - kept[i - 1] <= 1 || !TOKEN_CHAR_RE.test(stripped[i - 1]))
342
368
  continue;
343
369
  starts.push(i);
344
- CRED_PREFIX_RUN_RE.lastIndex = i;
345
- if (CRED_PREFIX_RUN_RE.test(stripped))
370
+ TOKEN_PREFIX_RUN_RE.lastIndex = i;
371
+ if (TOKEN_PREFIX_RUN_RE.test(stripped))
346
372
  prefixStarts.push(i);
347
373
  }
348
374
  const spans = [];
@@ -356,17 +382,103 @@ function splitTokenSpans(text, gaps) {
356
382
  spans.push([kept[i], kept[e - 1] + 1, stripped.slice(i, e)]);
357
383
  scanned = e;
358
384
  }
385
+ return [...spans, ...payloadRunSpans(text, prefixStarts.map((i) => kept[i]))];
386
+ }
387
+ /** `payloadRunSpan`'s spans from credential prefixes at these original indices, each run walked once. */
388
+ function payloadRunSpans(text, starts) {
389
+ const spans = [];
359
390
  let walked = 0;
360
- for (const i of prefixStarts.sort((a, b) => a - b)) {
361
- if (kept[i] < walked)
391
+ for (const start of starts.sort((a, b) => a - b)) {
392
+ if (start < walked)
362
393
  continue;
363
- const [span, reached] = payloadRunSpan(text, kept[i]);
394
+ const [span, reached] = payloadRunSpan(text, start);
364
395
  if (span)
365
396
  spans.push(span);
366
397
  walked = reached;
367
398
  }
368
399
  return spans;
369
400
  }
401
+ /** A string sequence's terminator: BEL (OSC only), ST, or CAN or SUB cancelling it. */
402
+ const STRING_END_RE = /(?:\x07|\x1b\\|\x9c|[\x18\x1a])$/;
403
+ /** Tags a candidate that can grow only into a JWT prefix: one starting after a `-`, a boundary for `JWT_RE`'s `\b` alone. */
404
+ const JWT_ONLY = '\0';
405
+ /**
406
+ * What a piece after `prev` (undefined after a gap) seeds: any prefix after a non-token character, only a JWT's after a
407
+ * `-`, none after a word character.
408
+ */
409
+ const seedAfter = (prev) => (prev === undefined || !TOKEN_CHAR_RE.test(prev) ? '' : prev === '-' ? JWT_ONLY : null);
410
+ /**
411
+ * Where a credential or JWT prefix or a private key's opener starts, where it ends, and which marker it is, when its
412
+ * pieces lie apart in a run of token characters and escape sequences, with a string payload between them taken whole or
413
+ * skipped (`g\x1b]0;x\x07h\x1b]0;p_\x07…`), so that no view holds it whole.
414
+ * Display characters are mandatory and each payload's optional. A piece starts on the display after a gap or a non-token
415
+ * character (`.`), or in a payload's trailing run after its start or a non-token character, where `payloadRunSpan` can
416
+ * walk from it; a JWT's also after a `-`.
417
+ * Candidates live only while they can grow into a prefix, which bounds them and keeps the scan linear.
418
+ */
419
+ function crossPayloadPrefixStarts(text) {
420
+ const starts = [];
421
+ if (!/[\x1b\x90\x98\x9d-\x9f]/.test(text))
422
+ return starts;
423
+ // Each candidate string, with the original index of its earliest start.
424
+ let candidates = new Map();
425
+ // Grows a candidate by the run characters of `chars`, which starts at original index `at`.
426
+ const grow = (into, candidate, start, chars, at) => {
427
+ for (let j = 0; j < chars.length; j += 1) {
428
+ if (!RUN_CHAR_RE.test(chars[j]))
429
+ continue;
430
+ candidate += chars[j];
431
+ if (PAYLOAD_MARKERS.has(candidate))
432
+ return void starts.push([start, at + j + 1, candidate]);
433
+ if (!PAYLOAD_MARKER_STEMS.has(candidate))
434
+ return;
435
+ }
436
+ const seen = into.get(candidate);
437
+ if (seen === undefined || start < seen)
438
+ into.set(candidate, start);
439
+ };
440
+ // The last display character, unless a gap came after it: what a piece starting here may seed.
441
+ let prev;
442
+ for (let k = 0; k < text.length;) {
443
+ ANSI_GAP_AT_RE.lastIndex = k;
444
+ const gap = ANSI_GAP_AT_RE.exec(text)?.[0];
445
+ if (gap) {
446
+ const from = STRING_OPENER_RE.exec(gap)?.[0].length ?? gap.length;
447
+ const next = new Map(candidates);
448
+ for (const [candidate, start] of candidates)
449
+ grow(next, candidate, start, gap.slice(from), k + from);
450
+ const end = Math.max(from, gap.length - (STRING_END_RE.exec(gap)?.[0].length ?? 0));
451
+ let tail = end;
452
+ while (tail > from && RUN_CHAR_RE.test(gap[tail - 1]))
453
+ tail -= 1;
454
+ for (let j = tail; j < end; j += 1) {
455
+ const seed = seedAfter(j === tail ? undefined : gap[j - 1]);
456
+ if (seed !== null)
457
+ grow(next, seed, k + j, gap.slice(j, end), k + j);
458
+ }
459
+ candidates = next;
460
+ prev = undefined;
461
+ k += gap.length;
462
+ }
463
+ else if (RUN_CHAR_RE.test(text[k])) {
464
+ const next = new Map();
465
+ for (const [candidate, start] of candidates)
466
+ grow(next, candidate, start, text[k], k);
467
+ const seed = seedAfter(prev);
468
+ if (seed !== null)
469
+ grow(next, seed, k, text[k], k);
470
+ candidates = next;
471
+ prev = text[k];
472
+ k += 1;
473
+ }
474
+ else {
475
+ candidates.clear();
476
+ prev = undefined;
477
+ k += 1;
478
+ }
479
+ }
480
+ return starts;
481
+ }
370
482
  /**
371
483
  * Fail-closed for a token split across string payloads: from a credential prefix at `start`, the span through the run of
372
484
  * token characters and whole escape sequences after it, when a string payload in the run holds token characters, and
@@ -385,7 +497,7 @@ function payloadRunSpan(text, start) {
385
497
  if (gap) {
386
498
  const from = STRING_OPENER_RE.exec(gap)?.[0].length ?? gap.length;
387
499
  for (let j = from; j < gap.length; j += 1) {
388
- if (!TOKEN_CHAR_RE.test(gap[j]))
500
+ if (!RUN_CHAR_RE.test(gap[j]))
389
501
  continue;
390
502
  token += gap[j];
391
503
  end = k + j + 1;
@@ -393,7 +505,7 @@ function payloadRunSpan(text, start) {
393
505
  }
394
506
  k += gap.length;
395
507
  }
396
- else if (TOKEN_CHAR_RE.test(text[k])) {
508
+ else if (RUN_CHAR_RE.test(text[k])) {
397
509
  token += text[k];
398
510
  end = k += 1;
399
511
  }
@@ -402,9 +514,51 @@ function payloadRunSpan(text, start) {
402
514
  }
403
515
  return [hidden ? [start, end, token] : null, k];
404
516
  }
517
+ /**
518
+ * The original spans of private keys a gap of one of `SPLIT_VIEWS` splits (`-----BE\x1b[1mGIN …`), matched on each view,
519
+ * and of those whose opener lies apart across string payloads (`-----B\x1b]0;x\x07E\x1b]0;GIN\x07 …`), matched on each
520
+ * view from where the opener ends. A whole key is `PRIVKEY_RE`'s on the text itself. A key one view leaves open runs to
521
+ * the end of the text only when no view closes one there (`-----END PRI\x1b[1mVATE KEY-----`).
522
+ */
523
+ function privateKeySpans(text) {
524
+ const openers = crossPayloadPrefixStarts(text).filter(([, , marker]) => marker === PEM_OPENER).sort((a, b) => a[1] - b[1]);
525
+ const closed = [];
526
+ const open = [];
527
+ for (const gaps of SPLIT_VIEWS) {
528
+ const view = splitView(text, gaps);
529
+ if (!view)
530
+ continue;
531
+ const { stripped, kept } = view;
532
+ // A key running to the end of the view runs to the end of the text, past any trailing gap.
533
+ const end = (e) => (e === stripped.length ? text.length : kept[e - 1] + 1);
534
+ for (const m of stripped.matchAll(PRIVKEY_RE))
535
+ (m[1] ? closed : open).push([kept[m.index], end(m.index + m[0].length), '']);
536
+ let i = 0;
537
+ let scanned = 0;
538
+ for (const [start, opened] of openers) {
539
+ if (opened < scanned)
540
+ continue;
541
+ while (i < kept.length && kept[i] < opened)
542
+ i += 1;
543
+ PRIVKEY_REST_RE.lastIndex = i;
544
+ const m = PRIVKEY_REST_RE.exec(stripped);
545
+ if (!m)
546
+ continue;
547
+ scanned = end(PRIVKEY_REST_RE.lastIndex);
548
+ const spans = m[1] ? closed : open;
549
+ spans.push([start, scanned, '']);
550
+ }
551
+ }
552
+ return [...closed, ...open.filter(([start]) => !closed.some(([from, to]) => from <= start && start < to))];
553
+ }
405
554
  /** Masks each union of the split-token spans every view finds, so no view masks a piece of a token another one joins. */
406
555
  function maskSplitTokens(text) {
407
- const spans = SPLIT_VIEWS.flatMap((gaps) => splitTokenSpans(text, gaps)).sort((a, b) => a[0] - b[0]);
556
+ const starts = crossPayloadPrefixStarts(text).flatMap(([start, , marker]) => (marker === PEM_OPENER ? [] : [start]));
557
+ return maskSpans(text, [...SPLIT_VIEWS.flatMap((gaps) => splitTokenSpans(text, gaps)), ...payloadRunSpans(text, starts)], mask);
558
+ }
559
+ /** Replaces each union of overlapping original spans, given the longest of their texts. */
560
+ function maskSpans(text, found, replace) {
561
+ const spans = found.sort((a, b) => a[0] - b[0]);
408
562
  let out = '';
409
563
  let last = 0;
410
564
  for (let k = 0; k < spans.length;) {
@@ -416,7 +570,7 @@ function maskSplitTokens(text) {
416
570
  if (nextToken.length > token.length)
417
571
  token = nextToken;
418
572
  }
419
- out += text.slice(last, start) + mask(token);
573
+ out += text.slice(last, start) + replace(token);
420
574
  last = end;
421
575
  }
422
576
  return out + text.slice(last);
@@ -938,7 +1092,10 @@ const REDIRECT_RE = /[0-9]*(?:&>>?|<<<|<<-?|<>|>>|>&|<&|>\||[<>])/y;
938
1092
  */
939
1093
  function commandWords(text, from, enclosing, list) {
940
1094
  const spans = [];
941
- const [gap, close, stop] = list ? [/[ \t,<>]/, /[\n;&|()\]}]/, /[\s;&|()<>,\]}]/] : [/[ \t]/, /[\n;&|()]/, /[\s;&|()<>]/];
1095
+ const [gap, close] = list ? [/[ \t,<>]/, /[\n;&|()\]}]/] : [/[ \t]/, /[\n;&|()]/];
1096
+ // A word ends only where the scan can step on (a gap, a redirection) or the command ends, so it always advances. Other
1097
+ // whitespace (`\r`, a no-break space) is part of the word, as the shell reads it, so a secret holding one is masked whole.
1098
+ const stop = new RegExp(`${gap.source}|${close.source}|[<>]`);
942
1099
  let i = from;
943
1100
  let redirect = false;
944
1101
  for (;;) {
@@ -1606,6 +1763,69 @@ function secretTokenCounts(text) {
1606
1763
  export function redactSensitive(text) {
1607
1764
  if (!text)
1608
1765
  return text;
1766
+ const redacted = redactShellText(text);
1767
+ // An escape sequence in a key or between a key and its value (`\x1b[1;31mAPI_KEY\x1b[m=…`, `pass\x1b[1mword …`) hides
1768
+ // it from the rules. A unit of the text the view without sequences masks anywhere is masked in the text's redaction,
1769
+ // wherever it still shows, removing a sequence inside one and keeping the rest.
1770
+ const stripped = text.replace(DISPLAY_GAPS_RE, '');
1771
+ if (stripped.length === text.length)
1772
+ return redacted;
1773
+ const shown = redactShellText(stripped);
1774
+ const base = unitCounts(stripped);
1775
+ const shownCounts = unitCounts(shown);
1776
+ const view = splitView(redacted, DISPLAY_GAPS_RE);
1777
+ const plain = view?.stripped ?? redacted;
1778
+ const at = (i) => (view ? view.kept[i] : i);
1779
+ const raw = unitCounts(plain);
1780
+ // Hidden by a redaction showing `counts`: fewer than the text holds, or fewer than another redaction shows (a value
1781
+ // equal to a mask made elsewhere, `ghp_ab...cdef`, fails closed). Only a unit of the text is masked, never a mask.
1782
+ const hides = (counts, other, unit) => {
1783
+ const n = counts.get(unit) ?? 0;
1784
+ return base.has(unit) && (n < base.get(unit) || n < (other.get(unit) ?? 0));
1785
+ };
1786
+ // Masked units only blanks apart are one value (`'correct horse battery'`), masked whole so its word count stays hidden.
1787
+ const spans = [];
1788
+ let last = -1;
1789
+ for (const m of plain.matchAll(MASK_OR_UNIT_RE)) {
1790
+ if (!hides(shownCounts, raw, m[0]))
1791
+ continue;
1792
+ const end = at(m.index + m[0].length - 1) + 1;
1793
+ if (last !== -1 && /^[ \t]+$/.test(plain.slice(last, m.index)))
1794
+ spans.at(-1)[1] = end;
1795
+ else
1796
+ spans.push([at(m.index), end, m[0]]);
1797
+ last = m.index + m[0].length;
1798
+ }
1799
+ const out = spans.length ? maskSpans(redacted, spans, () => '***') : redacted;
1800
+ // A credential of delimiters only (`Bear\x1b[1mer $$$$`) has no unit to mask: when the view shows fewer of a delimiter
1801
+ // than the text's redaction, the view's redaction is returned, without escape sequences, with each unit the text's
1802
+ // redaction hides masked in it too.
1803
+ const plainOut = out.replace(DISPLAY_GAPS_RE, '');
1804
+ const outCounts = delimiterCounts(plainOut);
1805
+ const viewCounts = delimiterCounts(shown);
1806
+ if (![...outCounts].some(([char, count]) => (viewCounts.get(char) ?? 0) < count))
1807
+ return out;
1808
+ const hidden = unitCounts(plainOut);
1809
+ return shown.replace(MASK_OR_UNIT_RE, (unit) => (hides(hidden, shownCounts, unit) ? '***' : unit));
1810
+ }
1811
+ const PRIVATE_KEY_MASK = '[REDACTED PRIVATE KEY]';
1812
+ /** A private key's mask, as one unit (its words are no units of their own), or a `SECRET_UNIT_RE` unit. */
1813
+ const MASK_OR_UNIT_RE = new RegExp(String.raw `\[REDACTED PRIVATE KEY\]|${SECRET_UNIT_RE.source}`, 'gu');
1814
+ /** A text's `MASK_OR_UNIT_RE` units, counted. */
1815
+ function unitCounts(text) {
1816
+ const counts = new Map();
1817
+ for (const [unit] of text.matchAll(MASK_OR_UNIT_RE))
1818
+ counts.set(unit, (counts.get(unit) ?? 0) + 1);
1819
+ return counts;
1820
+ }
1821
+ /** A text's delimiters, `SECRET_UNIT_RE`'s but whitespace, counted outside the masks `***` and a private key's. */
1822
+ function delimiterCounts(text) {
1823
+ const counts = new Map();
1824
+ for (const [char] of text.replaceAll(PRIVATE_KEY_MASK, '').replace(/(?<!\*)\*{3}(?!\*)/g, '').matchAll(/['"`$\\=:@/;&|<>(){}[\],*]/g))
1825
+ counts.set(char, (counts.get(char) ?? 0) + 1);
1826
+ return counts;
1827
+ }
1828
+ function redactShellText(text) {
1609
1829
  // Line continuations join their lines as the shell runs them (`--user \⏎ bob:pw`, `--pass\⏎word=x`): that view is
1610
1830
  // redacted, and a text with nothing to mask keeps its lines as written.
1611
1831
  const joined = text.replace(/\\\r?\n/g, '');
@@ -1783,7 +2003,7 @@ export function redactSensitive(text) {
1783
2003
  function redactRules(text) {
1784
2004
  if (!text)
1785
2005
  return text;
1786
- let out = maskSplitTokens(text).replace(CRED_RE, (_, t) => mask(t));
2006
+ let out = maskSplitTokens(maskSpans(text, privateKeySpans(text), () => '[REDACTED PRIVATE KEY]')).replace(CRED_RE, (_, t) => mask(t));
1787
2007
  out = out.replace(EMBEDDED_AWS_RE, (t) => mask(t));
1788
2008
  out = redactHeaderCredentials(out, AUTH_HDR_RE);
1789
2009
  out = out.replace(JWT_RE, (t) => mask(t));
@@ -1813,7 +2033,7 @@ function redactRules(text) {
1813
2033
  out = redactUserFlags(out);
1814
2034
  out = redactCommandFlags(out);
1815
2035
  out = out.replace(QUERY_KEY_RE, (whole, head, value) => (/[A-Za-z0-9]/.test(value) ? head + mask(value) : whole));
1816
- out = out.replace(PRIVKEY_RE, '[REDACTED PRIVATE KEY]').replace(PRIVKEY_OPEN_RE, '[REDACTED PRIVATE KEY]');
2036
+ out = out.replace(PRIVKEY_RE, '[REDACTED PRIVATE KEY]');
1817
2037
  return restoreCodeEnvKeyLiterals(text, out);
1818
2038
  }
1819
2039
  const CASE_MARKERS = [
@@ -1822,6 +2042,11 @@ const CASE_MARKERS = [
1822
2042
  'gsk_', 'syt_', 'retaindb_', 'hsk-', 'mem0_', 'brv_', 'xapp-', 'xai-', 'ntn_', 'fw-', 'fw_', 'fpk_', 'glpat-', 'gloas-', 'gldt-', 'glrt-', 'glrtr-',
1823
2043
  'glcbt-', 'glptt-', 'glft-', 'glimt-', 'glagent-', 'glsoat-', 'glffct-', 'glwt-', 'GR1348941', 'pk-lf-', 'eyJ', '-----BEGIN',
1824
2044
  ];
2045
+ /** The literal prefixes of `CRED_RE` (`xapp-` stands for `xapp-1-`) and `JWT_RE`, the JWT's also as `JWT_ONLY`'s. */
2046
+ const TOKEN_MARKERS = new Set([...CASE_MARKERS.filter((m) => ((TOKEN_PREFIX_RUN_RE.lastIndex = 0), TOKEN_PREFIX_RUN_RE.test(`${m}0-`))), `${JWT_ONLY}eyJ`]);
2047
+ /** What a cross-payload scan assembles: `TOKEN_MARKERS` and a private key's opener, and their proper prefixes. */
2048
+ const PAYLOAD_MARKERS = new Set([...TOKEN_MARKERS, PEM_OPENER]);
2049
+ const PAYLOAD_MARKER_STEMS = new Set([...PAYLOAD_MARKERS].flatMap((m) => Array.from({ length: m.length - 1 }, (_, n) => m.slice(0, n + 1))));
1825
2050
  const LOWER_MARKERS = [
1826
2051
  'authorization: bearer ', 'authorization: bot ', 'private key', 'postgres://', 'postgresql://', 'mysql://', 'mongodb://', 'redis://', 'amqp://', '://',
1827
2052
  'access_token', 'refresh_token', 'id_token', 'api_key', 'apikey', 'client_secret', 'auth_token', 'raw_secret', 'secret_input', 'key_material',
@@ -1838,6 +2063,12 @@ export function mightContainSensitiveText(text) {
1838
2063
  const views = SPLIT_VIEWS.map((gaps) => text.replace(gaps, ''));
1839
2064
  if (CASE_MARKERS.some((m) => views.some((view) => view.includes(m))))
1840
2065
  return true;
2066
+ if (crossPayloadPrefixStarts(text).length)
2067
+ return true;
2068
+ // So is a key or token an escape sequence splits (`pass\x1b[1mword`, `123456789\x1b[0m:…`).
2069
+ return mightContainKeyword(text) || (views[0] !== text && mightContainKeyword(views[0]));
2070
+ }
2071
+ function mightContainKeyword(text) {
1841
2072
  const lower = text.toLowerCase();
1842
2073
  if (LOWER_MARKERS.some((m) => lower.includes(m)))
1843
2074
  return true;
@@ -1901,11 +2132,15 @@ export function redactValue(v, enabled) {
1901
2132
  return redactText(v, enabled);
1902
2133
  if (Array.isArray(v))
1903
2134
  return v.map((item) => redactValue(item, enabled));
1904
- if (v && typeof v === 'object')
1905
- return Object.fromEntries(Object.entries(v).map(([k, val]) => [k, redactValue(val, enabled)]));
1906
- return v;
2135
+ if (!v || typeof v !== 'object')
2136
+ return v;
2137
+ const out = Object.fromEntries(Object.entries(v).map(([k, val]) => [k, redactValue(val, enabled)]));
2138
+ // TAL-604: a diff's `hunks` are re-parsed from its redacted text, which masks spans (a private key) that no single line shows.
2139
+ if (enabled && Array.isArray(out.hunks) && typeof out.diff === 'string')
2140
+ out.hunks = diffHunks(out.diff);
2141
+ return out;
1907
2142
  }
1908
- export const PUBLIC_MESSAGE_INTERNAL_FIELDS = new Set(['api_content', '_row_id', '_state_db_row_id', '_state_db_generation', '_db_row_id', 'state_db_row_id', '_active_turn_token', '_active_turn_user', '_fork_child_turn']);
2143
+ export const PUBLIC_MESSAGE_INTERNAL_FIELDS = new Set(['_background_review_terminal', 'api_content', '_absorbed_message_uids', '_row_id', '_state_db_row_id', '_state_db_message_uid', '_state_db_generation', '_state_db_authored_change', '_state_db_source_key', '_db_row_id', 'state_db_row_id', '_active_turn_token', '_active_turn_user', '_fork_child_turn']);
1909
2144
  export function copyJson(value) {
1910
2145
  if (Array.isArray(value))
1911
2146
  return value.map((v) => copyJson(v));
@@ -2016,25 +2251,68 @@ export function buildActiveTurnToken(streamId, pendingStartedAt) {
2016
2251
  const COLLAPSIBLE_USER_MESSAGE_LINES = 20;
2017
2252
  const COLLAPSIBLE_USER_MESSAGE_CHARS = 2000;
2018
2253
  /**
2019
- * Whether a public (redacted) row is a typed user message (no steer, wakeup or marker) longer than either limit, measured
2254
+ * Whether a public (redacted) row is a typed user message (no steer, wakeup, marker or delivery) longer than either limit, measured
2020
2255
  * without the `[Attached files: ...]` line clients hide.
2021
2256
  */
2022
2257
  function isCollapsibleUserMessage(item) {
2023
- if (item.role !== 'user' || item._steer !== undefined || item._background_update !== undefined || item._marker_kind !== undefined)
2258
+ if (item.role !== 'user' || item._steer !== undefined || item._background_update !== undefined || item._marker_kind !== undefined || item._delivery !== undefined)
2024
2259
  return false;
2025
2260
  const text = stripAttachedFilesMarker(messageText(item.content));
2026
2261
  return text.length > COLLAPSIBLE_USER_MESSAGE_CHARS || text.split('\n').length > COLLAPSIBLE_USER_MESSAGE_LINES;
2027
2262
  }
2263
+ /**
2264
+ * TAL-600: how clients show a public row. A tool result or consumed steer shows only inside its turn's activity scene
2265
+ * (`in_scene`); a silent background reply, or a row with nothing to show, not at all (`hidden`); every other row on its own.
2266
+ */
2267
+ function messageDisplay(item) {
2268
+ if (item.role === 'tool' || item._steer)
2269
+ return 'in_scene';
2270
+ if (!item.role || item._background_silent || item.display_kind === 'hidden')
2271
+ return 'hidden';
2272
+ if (item._marker_kind)
2273
+ return 'row';
2274
+ const shown = Boolean(messageText(item.content).trim()) || (Array.isArray(item.attachments) && item.attachments.length > 0) || (item.role === 'user' && hasNativeImages([item]));
2275
+ if (item.role !== 'assistant')
2276
+ return shown ? 'row' : 'hidden';
2277
+ const hasTools = Array.isArray(item.tool_calls) && item.tool_calls.length > 0;
2278
+ return shown || hasTools || Boolean(item.reasoning || item._anchor_activity_scene) ? 'row' : 'hidden';
2279
+ }
2280
+ /**
2281
+ * One user `content[*]` part (Python `_redact_message_content_part`): an `image_url.url` raster data URI passes through
2282
+ * unscanned (TAL-583). The exemption exists only at this schema position; image-shaped values elsewhere are redacted.
2283
+ */
2284
+ function redactUserContentPart(part, enabled) {
2285
+ if (!enabled || !part || typeof part !== 'object' || Array.isArray(part))
2286
+ return redactValue(part, enabled);
2287
+ const p = part;
2288
+ const image = p.image_url;
2289
+ if (p.type !== 'image_url' || !image || typeof image !== 'object' || Array.isArray(image))
2290
+ return redactValue(part, enabled);
2291
+ const url = image.url;
2292
+ if (!isRasterDataUri(url))
2293
+ return redactValue(part, enabled);
2294
+ const rest = Object.fromEntries(Object.entries(image).filter(([k]) => k !== 'url'));
2295
+ const redacted = redactValue({ ...p, image_url: rest }, enabled);
2296
+ redacted.image_url = { ...redacted.image_url, url };
2297
+ return redacted;
2298
+ }
2028
2299
  function publicMessageProjection(message, enabled, activeTurnToken) {
2029
2300
  const isActive = Boolean(message && typeof message === 'object' && message.role === 'user' && activeTurnToken !== null && message._active_turn_token === activeTurnToken);
2030
- const scrubbed = scrubInternalReplayFields([message], { messageRecords: true })[0];
2301
+ // Exports and nested public documents bypass scene hydration; project their user content at this boundary too.
2302
+ const scrubbed = normalizeUserDisplay(scrubInternalReplayFields([message], { messageRecords: true })[0]);
2031
2303
  if (!scrubbed || typeof scrubbed !== 'object' || Array.isArray(scrubbed))
2032
2304
  return redactValue(scrubbed, enabled);
2033
2305
  const item = {};
2034
2306
  for (const [key, value] of Object.entries(scrubbed)) {
2035
2307
  if (PUBLIC_MESSAGE_INTERNAL_FIELDS.has(key))
2036
2308
  continue;
2037
- item[key] = redactValue(value, enabled);
2309
+ // TAL-909: a tool row's metadata carries the whole edit diff, which ships capped and redacted as its call's `edit_diff`.
2310
+ if (key === 'display_metadata' && scrubbed.role === 'tool')
2311
+ continue;
2312
+ const userParts = key === 'content' && Array.isArray(value) && scrubbed.role === 'user';
2313
+ // Preserve the string/parts/null contract and redact JSON credential fields with their key context intact.
2314
+ const publicValue = key === 'content' && value != null && typeof value !== 'string' && !Array.isArray(value) ? JSON.stringify(value) : value;
2315
+ item[key] = userParts ? value.map((part) => redactUserContentPart(part, enabled)) : redactValue(publicValue, enabled);
2038
2316
  }
2039
2317
  if (isActive)
2040
2318
  item._active_turn_user = true;
@@ -2043,6 +2321,24 @@ function publicMessageProjection(message, enabled, activeTurnToken) {
2043
2321
  item._collapsible = true;
2044
2322
  else
2045
2323
  delete item._collapsible;
2324
+ item._display = messageDisplay(item);
2325
+ // TAL-598: stored and Agent rows may carry these as numeric strings or mixed arrays; ship the contract types or nothing.
2326
+ for (const key of ['_ts', '_turnDuration', '_turnTps']) {
2327
+ if (!(key in item))
2328
+ continue;
2329
+ const n = typeof item[key] === 'string' && item[key] !== '' ? Number(item[key]) : item[key];
2330
+ if (typeof n === 'number' && Number.isFinite(n))
2331
+ item[key] = n;
2332
+ else
2333
+ Reflect.deleteProperty(item, key);
2334
+ }
2335
+ if ('reasoning_titles' in item) {
2336
+ const titles = Array.isArray(item.reasoning_titles) ? item.reasoning_titles.filter((t) => typeof t === 'string' && Boolean(t.trim())) : [];
2337
+ if (titles.length)
2338
+ item.reasoning_titles = titles;
2339
+ else
2340
+ delete item.reasoning_titles;
2341
+ }
2046
2342
  return withMessageToolDisplay(scrubbed, item, enabled);
2047
2343
  }
2048
2344
  /**