@otto-assistant/bridge 0.4.92

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 (483) hide show
  1. package/bin.js +2 -0
  2. package/dist/agent-model.e2e.test.js +755 -0
  3. package/dist/ai-tool-to-genai.js +233 -0
  4. package/dist/ai-tool-to-genai.test.js +267 -0
  5. package/dist/ai-tool.js +6 -0
  6. package/dist/anthropic-auth-plugin.js +728 -0
  7. package/dist/anthropic-auth-plugin.test.js +125 -0
  8. package/dist/anthropic-auth-state.js +231 -0
  9. package/dist/bin.js +90 -0
  10. package/dist/channel-management.js +227 -0
  11. package/dist/cli-parsing.test.js +137 -0
  12. package/dist/cli-send-thread.e2e.test.js +356 -0
  13. package/dist/cli.js +3276 -0
  14. package/dist/commands/abort.js +65 -0
  15. package/dist/commands/action-buttons.js +245 -0
  16. package/dist/commands/add-project.js +113 -0
  17. package/dist/commands/agent.js +335 -0
  18. package/dist/commands/ask-question.js +274 -0
  19. package/dist/commands/btw.js +116 -0
  20. package/dist/commands/compact.js +120 -0
  21. package/dist/commands/context-usage.js +140 -0
  22. package/dist/commands/create-new-project.js +130 -0
  23. package/dist/commands/diff.js +63 -0
  24. package/dist/commands/file-upload.js +275 -0
  25. package/dist/commands/fork.js +220 -0
  26. package/dist/commands/gemini-apikey.js +70 -0
  27. package/dist/commands/login.js +885 -0
  28. package/dist/commands/mcp.js +239 -0
  29. package/dist/commands/memory-snapshot.js +24 -0
  30. package/dist/commands/mention-mode.js +44 -0
  31. package/dist/commands/merge-worktree.js +159 -0
  32. package/dist/commands/model-variant.js +364 -0
  33. package/dist/commands/model.js +776 -0
  34. package/dist/commands/new-worktree.js +366 -0
  35. package/dist/commands/paginated-select.js +57 -0
  36. package/dist/commands/permissions.js +274 -0
  37. package/dist/commands/queue.js +206 -0
  38. package/dist/commands/remove-project.js +115 -0
  39. package/dist/commands/restart-opencode-server.js +127 -0
  40. package/dist/commands/resume.js +149 -0
  41. package/dist/commands/run-command.js +79 -0
  42. package/dist/commands/screenshare.js +303 -0
  43. package/dist/commands/screenshare.test.js +20 -0
  44. package/dist/commands/session-id.js +78 -0
  45. package/dist/commands/session.js +176 -0
  46. package/dist/commands/share.js +80 -0
  47. package/dist/commands/tasks.js +205 -0
  48. package/dist/commands/types.js +2 -0
  49. package/dist/commands/undo-redo.js +305 -0
  50. package/dist/commands/unset-model.js +138 -0
  51. package/dist/commands/upgrade.js +42 -0
  52. package/dist/commands/user-command.js +155 -0
  53. package/dist/commands/verbosity.js +125 -0
  54. package/dist/commands/worktree-settings.js +43 -0
  55. package/dist/commands/worktrees.js +410 -0
  56. package/dist/condense-memory.js +33 -0
  57. package/dist/config.js +94 -0
  58. package/dist/context-awareness-plugin.js +363 -0
  59. package/dist/context-awareness-plugin.test.js +124 -0
  60. package/dist/critique-utils.js +95 -0
  61. package/dist/database.js +1310 -0
  62. package/dist/db.js +251 -0
  63. package/dist/db.test.js +138 -0
  64. package/dist/debounce-timeout.js +28 -0
  65. package/dist/debounced-process-flush.js +77 -0
  66. package/dist/discord-bot.js +1008 -0
  67. package/dist/discord-command-registration.js +524 -0
  68. package/dist/discord-urls.js +81 -0
  69. package/dist/discord-utils.js +591 -0
  70. package/dist/discord-utils.test.js +134 -0
  71. package/dist/errors.js +157 -0
  72. package/dist/escape-backticks.test.js +429 -0
  73. package/dist/event-stream-real-capture.e2e.test.js +533 -0
  74. package/dist/eventsource-parser.test.js +327 -0
  75. package/dist/exec-async.js +26 -0
  76. package/dist/external-opencode-sync.js +480 -0
  77. package/dist/format-tables.js +302 -0
  78. package/dist/format-tables.test.js +308 -0
  79. package/dist/forum-sync/config.js +79 -0
  80. package/dist/forum-sync/discord-operations.js +154 -0
  81. package/dist/forum-sync/index.js +5 -0
  82. package/dist/forum-sync/markdown.js +113 -0
  83. package/dist/forum-sync/sync-to-discord.js +417 -0
  84. package/dist/forum-sync/sync-to-files.js +190 -0
  85. package/dist/forum-sync/types.js +53 -0
  86. package/dist/forum-sync/watchers.js +307 -0
  87. package/dist/gateway-proxy-reconnect.e2e.test.js +394 -0
  88. package/dist/gateway-proxy.e2e.test.js +483 -0
  89. package/dist/genai-worker-wrapper.js +111 -0
  90. package/dist/genai-worker.js +311 -0
  91. package/dist/genai.js +232 -0
  92. package/dist/generated/browser.js +17 -0
  93. package/dist/generated/client.js +37 -0
  94. package/dist/generated/commonInputTypes.js +10 -0
  95. package/dist/generated/enums.js +52 -0
  96. package/dist/generated/internal/class.js +49 -0
  97. package/dist/generated/internal/prismaNamespace.js +253 -0
  98. package/dist/generated/internal/prismaNamespaceBrowser.js +223 -0
  99. package/dist/generated/models/bot_api_keys.js +1 -0
  100. package/dist/generated/models/bot_tokens.js +1 -0
  101. package/dist/generated/models/channel_agents.js +1 -0
  102. package/dist/generated/models/channel_directories.js +1 -0
  103. package/dist/generated/models/channel_mention_mode.js +1 -0
  104. package/dist/generated/models/channel_models.js +1 -0
  105. package/dist/generated/models/channel_verbosity.js +1 -0
  106. package/dist/generated/models/channel_worktrees.js +1 -0
  107. package/dist/generated/models/forum_sync_configs.js +1 -0
  108. package/dist/generated/models/global_models.js +1 -0
  109. package/dist/generated/models/ipc_requests.js +1 -0
  110. package/dist/generated/models/part_messages.js +1 -0
  111. package/dist/generated/models/scheduled_tasks.js +1 -0
  112. package/dist/generated/models/session_agents.js +1 -0
  113. package/dist/generated/models/session_events.js +1 -0
  114. package/dist/generated/models/session_models.js +1 -0
  115. package/dist/generated/models/session_start_sources.js +1 -0
  116. package/dist/generated/models/thread_sessions.js +1 -0
  117. package/dist/generated/models/thread_worktrees.js +1 -0
  118. package/dist/generated/models.js +1 -0
  119. package/dist/heap-monitor.js +122 -0
  120. package/dist/hrana-server.js +263 -0
  121. package/dist/hrana-server.test.js +370 -0
  122. package/dist/html-actions.js +123 -0
  123. package/dist/html-actions.test.js +70 -0
  124. package/dist/html-components.js +117 -0
  125. package/dist/html-components.test.js +34 -0
  126. package/dist/image-optimizer-plugin.js +153 -0
  127. package/dist/image-utils.js +112 -0
  128. package/dist/interaction-handler.js +397 -0
  129. package/dist/ipc-polling.js +252 -0
  130. package/dist/ipc-tools-plugin.js +193 -0
  131. package/dist/kimaki-digital-twin.e2e.test.js +161 -0
  132. package/dist/kimaki-opencode-plugin-loading.e2e.test.js +87 -0
  133. package/dist/kimaki-opencode-plugin.js +17 -0
  134. package/dist/kimaki-opencode-plugin.test.js +98 -0
  135. package/dist/limit-heading-depth.js +25 -0
  136. package/dist/limit-heading-depth.test.js +105 -0
  137. package/dist/logger.js +165 -0
  138. package/dist/markdown.js +342 -0
  139. package/dist/markdown.test.js +257 -0
  140. package/dist/message-finish-field.e2e.test.js +165 -0
  141. package/dist/message-formatting.js +413 -0
  142. package/dist/message-formatting.test.js +73 -0
  143. package/dist/message-preprocessing.js +330 -0
  144. package/dist/onboarding-tutorial.js +172 -0
  145. package/dist/onboarding-welcome.js +37 -0
  146. package/dist/openai-realtime.js +224 -0
  147. package/dist/opencode-command-detection.js +65 -0
  148. package/dist/opencode-command-detection.test.js +240 -0
  149. package/dist/opencode-command.js +129 -0
  150. package/dist/opencode-command.test.js +48 -0
  151. package/dist/opencode-interrupt-plugin.js +361 -0
  152. package/dist/opencode-interrupt-plugin.test.js +458 -0
  153. package/dist/opencode.js +861 -0
  154. package/dist/otto/branding.js +22 -0
  155. package/dist/otto/index.js +21 -0
  156. package/dist/parse-permission-rules.test.js +117 -0
  157. package/dist/patch-text-parser.js +97 -0
  158. package/dist/plugin-logger.js +59 -0
  159. package/dist/privacy-sanitizer.js +105 -0
  160. package/dist/queue-advanced-abort.e2e.test.js +293 -0
  161. package/dist/queue-advanced-action-buttons.e2e.test.js +206 -0
  162. package/dist/queue-advanced-e2e-setup.js +786 -0
  163. package/dist/queue-advanced-footer.e2e.test.js +472 -0
  164. package/dist/queue-advanced-model-switch.e2e.test.js +299 -0
  165. package/dist/queue-advanced-permissions-typing.e2e.test.js +180 -0
  166. package/dist/queue-advanced-question.e2e.test.js +261 -0
  167. package/dist/queue-advanced-typing-interrupt.e2e.test.js +114 -0
  168. package/dist/queue-advanced-typing.e2e.test.js +153 -0
  169. package/dist/queue-drain-after-interactive-ui.e2e.test.js +119 -0
  170. package/dist/queue-interrupt-drain.e2e.test.js +135 -0
  171. package/dist/queue-question-select-drain.e2e.test.js +120 -0
  172. package/dist/runtime-idle-sweeper.js +52 -0
  173. package/dist/runtime-lifecycle.e2e.test.js +508 -0
  174. package/dist/sentry.js +23 -0
  175. package/dist/session-handler/agent-utils.js +67 -0
  176. package/dist/session-handler/event-stream-state.js +420 -0
  177. package/dist/session-handler/event-stream-state.test.js +563 -0
  178. package/dist/session-handler/model-utils.js +124 -0
  179. package/dist/session-handler/opencode-session-event-log.js +94 -0
  180. package/dist/session-handler/thread-runtime-state.js +104 -0
  181. package/dist/session-handler/thread-session-runtime.js +3258 -0
  182. package/dist/session-handler.js +9 -0
  183. package/dist/session-search.js +100 -0
  184. package/dist/session-search.test.js +40 -0
  185. package/dist/session-title-rename.test.js +80 -0
  186. package/dist/startup-service.js +153 -0
  187. package/dist/startup-time.e2e.test.js +296 -0
  188. package/dist/store.js +17 -0
  189. package/dist/system-message.js +613 -0
  190. package/dist/system-message.test.js +602 -0
  191. package/dist/task-runner.js +295 -0
  192. package/dist/task-schedule.js +209 -0
  193. package/dist/task-schedule.test.js +71 -0
  194. package/dist/test-utils.js +299 -0
  195. package/dist/thinking-utils.js +35 -0
  196. package/dist/thread-message-queue.e2e.test.js +999 -0
  197. package/dist/tools.js +357 -0
  198. package/dist/undo-redo.e2e.test.js +161 -0
  199. package/dist/unnest-code-blocks.js +146 -0
  200. package/dist/unnest-code-blocks.test.js +673 -0
  201. package/dist/upgrade.js +114 -0
  202. package/dist/utils.js +144 -0
  203. package/dist/voice-attachment.js +34 -0
  204. package/dist/voice-handler.js +646 -0
  205. package/dist/voice-message.e2e.test.js +1021 -0
  206. package/dist/voice.js +447 -0
  207. package/dist/voice.test.js +235 -0
  208. package/dist/wait-session.js +94 -0
  209. package/dist/websockify.js +69 -0
  210. package/dist/worker-types.js +4 -0
  211. package/dist/worktree-lifecycle.e2e.test.js +308 -0
  212. package/dist/worktree-utils.js +3 -0
  213. package/dist/worktrees.js +929 -0
  214. package/dist/worktrees.test.js +189 -0
  215. package/dist/xml.js +92 -0
  216. package/dist/xml.test.js +32 -0
  217. package/package.json +98 -0
  218. package/schema.prisma +295 -0
  219. package/skills/batch/SKILL.md +87 -0
  220. package/skills/critique/SKILL.md +112 -0
  221. package/skills/egaki/SKILL.md +100 -0
  222. package/skills/errore/SKILL.md +647 -0
  223. package/skills/event-sourcing-state/SKILL.md +252 -0
  224. package/skills/gitchamber/SKILL.md +93 -0
  225. package/skills/goke/SKILL.md +644 -0
  226. package/skills/jitter/EDITOR.md +219 -0
  227. package/skills/jitter/EXPORT-INTERNALS.md +309 -0
  228. package/skills/jitter/SKILL.md +158 -0
  229. package/skills/jitter/jitter-clipboard.json +1042 -0
  230. package/skills/jitter/package.json +14 -0
  231. package/skills/jitter/tsconfig.json +15 -0
  232. package/skills/jitter/utils/actions.ts +212 -0
  233. package/skills/jitter/utils/export.ts +114 -0
  234. package/skills/jitter/utils/index.ts +141 -0
  235. package/skills/jitter/utils/snapshot.ts +154 -0
  236. package/skills/jitter/utils/traverse.ts +246 -0
  237. package/skills/jitter/utils/types.ts +279 -0
  238. package/skills/jitter/utils/wait.ts +133 -0
  239. package/skills/lintcn/SKILL.md +873 -0
  240. package/skills/new-skill/SKILL.md +211 -0
  241. package/skills/npm-package/SKILL.md +239 -0
  242. package/skills/playwriter/SKILL.md +35 -0
  243. package/skills/proxyman/SKILL.md +215 -0
  244. package/skills/security-review/SKILL.md +208 -0
  245. package/skills/simplify/SKILL.md +58 -0
  246. package/skills/spiceflow/SKILL.md +14 -0
  247. package/skills/termcast/SKILL.md +945 -0
  248. package/skills/tuistory/SKILL.md +250 -0
  249. package/skills/usecomputer/SKILL.md +264 -0
  250. package/skills/x-articles/SKILL.md +554 -0
  251. package/skills/zele/SKILL.md +112 -0
  252. package/skills/zustand-centralized-state/SKILL.md +1004 -0
  253. package/src/agent-model.e2e.test.ts +976 -0
  254. package/src/ai-tool-to-genai.test.ts +296 -0
  255. package/src/ai-tool-to-genai.ts +283 -0
  256. package/src/ai-tool.ts +39 -0
  257. package/src/anthropic-auth-plugin.test.ts +159 -0
  258. package/src/anthropic-auth-plugin.ts +861 -0
  259. package/src/anthropic-auth-state.ts +282 -0
  260. package/src/bin.ts +111 -0
  261. package/src/channel-management.ts +334 -0
  262. package/src/cli-parsing.test.ts +195 -0
  263. package/src/cli-send-thread.e2e.test.ts +464 -0
  264. package/src/cli.ts +4581 -0
  265. package/src/commands/abort.ts +89 -0
  266. package/src/commands/action-buttons.ts +364 -0
  267. package/src/commands/add-project.ts +149 -0
  268. package/src/commands/agent.ts +473 -0
  269. package/src/commands/ask-question.ts +390 -0
  270. package/src/commands/btw.ts +164 -0
  271. package/src/commands/compact.ts +157 -0
  272. package/src/commands/context-usage.ts +199 -0
  273. package/src/commands/create-new-project.ts +190 -0
  274. package/src/commands/diff.ts +91 -0
  275. package/src/commands/file-upload.ts +389 -0
  276. package/src/commands/fork.ts +321 -0
  277. package/src/commands/gemini-apikey.ts +104 -0
  278. package/src/commands/login.ts +1173 -0
  279. package/src/commands/mcp.ts +307 -0
  280. package/src/commands/memory-snapshot.ts +30 -0
  281. package/src/commands/mention-mode.ts +68 -0
  282. package/src/commands/merge-worktree.ts +223 -0
  283. package/src/commands/model-variant.ts +483 -0
  284. package/src/commands/model.ts +1053 -0
  285. package/src/commands/new-worktree.ts +510 -0
  286. package/src/commands/paginated-select.ts +81 -0
  287. package/src/commands/permissions.ts +397 -0
  288. package/src/commands/queue.ts +271 -0
  289. package/src/commands/remove-project.ts +155 -0
  290. package/src/commands/restart-opencode-server.ts +162 -0
  291. package/src/commands/resume.ts +230 -0
  292. package/src/commands/run-command.ts +123 -0
  293. package/src/commands/screenshare.test.ts +30 -0
  294. package/src/commands/screenshare.ts +366 -0
  295. package/src/commands/session-id.ts +109 -0
  296. package/src/commands/session.ts +227 -0
  297. package/src/commands/share.ts +106 -0
  298. package/src/commands/tasks.ts +293 -0
  299. package/src/commands/types.ts +25 -0
  300. package/src/commands/undo-redo.ts +386 -0
  301. package/src/commands/unset-model.ts +173 -0
  302. package/src/commands/upgrade.ts +52 -0
  303. package/src/commands/user-command.ts +198 -0
  304. package/src/commands/verbosity.ts +173 -0
  305. package/src/commands/worktree-settings.ts +70 -0
  306. package/src/commands/worktrees.ts +552 -0
  307. package/src/condense-memory.ts +36 -0
  308. package/src/config.ts +111 -0
  309. package/src/context-awareness-plugin.test.ts +142 -0
  310. package/src/context-awareness-plugin.ts +510 -0
  311. package/src/critique-utils.ts +139 -0
  312. package/src/database.ts +1876 -0
  313. package/src/db.test.ts +162 -0
  314. package/src/db.ts +286 -0
  315. package/src/debounce-timeout.ts +43 -0
  316. package/src/debounced-process-flush.ts +104 -0
  317. package/src/discord-bot.ts +1330 -0
  318. package/src/discord-command-registration.ts +693 -0
  319. package/src/discord-urls.ts +88 -0
  320. package/src/discord-utils.test.ts +153 -0
  321. package/src/discord-utils.ts +800 -0
  322. package/src/errors.ts +201 -0
  323. package/src/escape-backticks.test.ts +469 -0
  324. package/src/event-stream-real-capture.e2e.test.ts +692 -0
  325. package/src/eventsource-parser.test.ts +351 -0
  326. package/src/exec-async.ts +35 -0
  327. package/src/external-opencode-sync.ts +685 -0
  328. package/src/format-tables.test.ts +335 -0
  329. package/src/format-tables.ts +445 -0
  330. package/src/forum-sync/config.ts +92 -0
  331. package/src/forum-sync/discord-operations.ts +241 -0
  332. package/src/forum-sync/index.ts +9 -0
  333. package/src/forum-sync/markdown.ts +172 -0
  334. package/src/forum-sync/sync-to-discord.ts +595 -0
  335. package/src/forum-sync/sync-to-files.ts +294 -0
  336. package/src/forum-sync/types.ts +175 -0
  337. package/src/forum-sync/watchers.ts +454 -0
  338. package/src/gateway-proxy-reconnect.e2e.test.ts +523 -0
  339. package/src/gateway-proxy.e2e.test.ts +640 -0
  340. package/src/genai-worker-wrapper.ts +164 -0
  341. package/src/genai-worker.ts +386 -0
  342. package/src/genai.ts +321 -0
  343. package/src/generated/browser.ts +114 -0
  344. package/src/generated/client.ts +138 -0
  345. package/src/generated/commonInputTypes.ts +736 -0
  346. package/src/generated/enums.ts +88 -0
  347. package/src/generated/internal/class.ts +384 -0
  348. package/src/generated/internal/prismaNamespace.ts +2386 -0
  349. package/src/generated/internal/prismaNamespaceBrowser.ts +326 -0
  350. package/src/generated/models/bot_api_keys.ts +1288 -0
  351. package/src/generated/models/bot_tokens.ts +1656 -0
  352. package/src/generated/models/channel_agents.ts +1256 -0
  353. package/src/generated/models/channel_directories.ts +1859 -0
  354. package/src/generated/models/channel_mention_mode.ts +1300 -0
  355. package/src/generated/models/channel_models.ts +1288 -0
  356. package/src/generated/models/channel_verbosity.ts +1228 -0
  357. package/src/generated/models/channel_worktrees.ts +1300 -0
  358. package/src/generated/models/forum_sync_configs.ts +1452 -0
  359. package/src/generated/models/global_models.ts +1288 -0
  360. package/src/generated/models/ipc_requests.ts +1485 -0
  361. package/src/generated/models/part_messages.ts +1302 -0
  362. package/src/generated/models/scheduled_tasks.ts +2320 -0
  363. package/src/generated/models/session_agents.ts +1086 -0
  364. package/src/generated/models/session_events.ts +1439 -0
  365. package/src/generated/models/session_models.ts +1114 -0
  366. package/src/generated/models/session_start_sources.ts +1408 -0
  367. package/src/generated/models/thread_sessions.ts +1781 -0
  368. package/src/generated/models/thread_worktrees.ts +1356 -0
  369. package/src/generated/models.ts +30 -0
  370. package/src/heap-monitor.ts +152 -0
  371. package/src/hrana-server.test.ts +434 -0
  372. package/src/hrana-server.ts +314 -0
  373. package/src/html-actions.test.ts +87 -0
  374. package/src/html-actions.ts +174 -0
  375. package/src/html-components.test.ts +38 -0
  376. package/src/html-components.ts +181 -0
  377. package/src/image-optimizer-plugin.ts +194 -0
  378. package/src/image-utils.ts +149 -0
  379. package/src/interaction-handler.ts +576 -0
  380. package/src/ipc-polling.ts +326 -0
  381. package/src/ipc-tools-plugin.ts +236 -0
  382. package/src/kimaki-digital-twin.e2e.test.ts +199 -0
  383. package/src/kimaki-opencode-plugin-loading.e2e.test.ts +109 -0
  384. package/src/kimaki-opencode-plugin.test.ts +108 -0
  385. package/src/kimaki-opencode-plugin.ts +18 -0
  386. package/src/limit-heading-depth.test.ts +116 -0
  387. package/src/limit-heading-depth.ts +26 -0
  388. package/src/logger.ts +208 -0
  389. package/src/markdown.test.ts +308 -0
  390. package/src/markdown.ts +410 -0
  391. package/src/message-finish-field.e2e.test.ts +192 -0
  392. package/src/message-formatting.test.ts +81 -0
  393. package/src/message-formatting.ts +533 -0
  394. package/src/message-preprocessing.ts +455 -0
  395. package/src/onboarding-tutorial.ts +176 -0
  396. package/src/onboarding-welcome.ts +49 -0
  397. package/src/openai-realtime.ts +358 -0
  398. package/src/opencode-command-detection.test.ts +307 -0
  399. package/src/opencode-command-detection.ts +76 -0
  400. package/src/opencode-command.test.ts +70 -0
  401. package/src/opencode-command.ts +188 -0
  402. package/src/opencode-interrupt-plugin.test.ts +677 -0
  403. package/src/opencode-interrupt-plugin.ts +477 -0
  404. package/src/opencode.ts +1110 -0
  405. package/src/otto/branding.ts +23 -0
  406. package/src/otto/index.ts +22 -0
  407. package/src/parse-permission-rules.test.ts +127 -0
  408. package/src/patch-text-parser.ts +107 -0
  409. package/src/plugin-logger.ts +68 -0
  410. package/src/privacy-sanitizer.ts +142 -0
  411. package/src/queue-advanced-abort.e2e.test.ts +382 -0
  412. package/src/queue-advanced-action-buttons.e2e.test.ts +268 -0
  413. package/src/queue-advanced-e2e-setup.ts +873 -0
  414. package/src/queue-advanced-footer.e2e.test.ts +576 -0
  415. package/src/queue-advanced-model-switch.e2e.test.ts +383 -0
  416. package/src/queue-advanced-permissions-typing.e2e.test.ts +245 -0
  417. package/src/queue-advanced-question.e2e.test.ts +316 -0
  418. package/src/queue-advanced-typing-interrupt.e2e.test.ts +146 -0
  419. package/src/queue-advanced-typing.e2e.test.ts +199 -0
  420. package/src/queue-drain-after-interactive-ui.e2e.test.ts +151 -0
  421. package/src/queue-interrupt-drain.e2e.test.ts +166 -0
  422. package/src/queue-question-select-drain.e2e.test.ts +152 -0
  423. package/src/runtime-idle-sweeper.ts +76 -0
  424. package/src/runtime-lifecycle.e2e.test.ts +641 -0
  425. package/src/schema.sql +173 -0
  426. package/src/sentry.ts +26 -0
  427. package/src/session-handler/agent-utils.ts +97 -0
  428. package/src/session-handler/event-stream-fixtures/real-session-action-buttons.jsonl +45 -0
  429. package/src/session-handler/event-stream-fixtures/real-session-footer-suppressed-on-pre-idle-interrupt.jsonl +40 -0
  430. package/src/session-handler/event-stream-fixtures/real-session-permission-external-file.jsonl +23 -0
  431. package/src/session-handler/event-stream-fixtures/real-session-task-normal.jsonl +22 -0
  432. package/src/session-handler/event-stream-fixtures/real-session-task-three-parallel-sleeps.jsonl +277 -0
  433. package/src/session-handler/event-stream-fixtures/real-session-task-user-interruption.jsonl +46 -0
  434. package/src/session-handler/event-stream-fixtures/session-abort-after-idle-race.jsonl +21 -0
  435. package/src/session-handler/event-stream-fixtures/session-concurrent-messages-serialized.jsonl +56 -0
  436. package/src/session-handler/event-stream-fixtures/session-explicit-abort.jsonl +44 -0
  437. package/src/session-handler/event-stream-fixtures/session-normal-completion.jsonl +29 -0
  438. package/src/session-handler/event-stream-fixtures/session-tool-call-noisy-stream.jsonl +29 -0
  439. package/src/session-handler/event-stream-fixtures/session-two-completions-same-session.jsonl +50 -0
  440. package/src/session-handler/event-stream-fixtures/session-user-interruption.jsonl +59 -0
  441. package/src/session-handler/event-stream-fixtures/session-voice-queued-followup.jsonl +52 -0
  442. package/src/session-handler/event-stream-state.test.ts +645 -0
  443. package/src/session-handler/event-stream-state.ts +608 -0
  444. package/src/session-handler/model-utils.ts +183 -0
  445. package/src/session-handler/opencode-session-event-log.ts +130 -0
  446. package/src/session-handler/thread-runtime-state.ts +212 -0
  447. package/src/session-handler/thread-session-runtime.ts +4281 -0
  448. package/src/session-handler.ts +15 -0
  449. package/src/session-search.test.ts +50 -0
  450. package/src/session-search.ts +148 -0
  451. package/src/session-title-rename.test.ts +112 -0
  452. package/src/startup-service.ts +200 -0
  453. package/src/startup-time.e2e.test.ts +373 -0
  454. package/src/store.ts +122 -0
  455. package/src/system-message.test.ts +612 -0
  456. package/src/system-message.ts +723 -0
  457. package/src/task-runner.ts +421 -0
  458. package/src/task-schedule.test.ts +84 -0
  459. package/src/task-schedule.ts +311 -0
  460. package/src/test-utils.ts +435 -0
  461. package/src/thinking-utils.ts +61 -0
  462. package/src/thread-message-queue.e2e.test.ts +1219 -0
  463. package/src/tools.ts +430 -0
  464. package/src/undici.d.ts +12 -0
  465. package/src/undo-redo.e2e.test.ts +209 -0
  466. package/src/unnest-code-blocks.test.ts +713 -0
  467. package/src/unnest-code-blocks.ts +185 -0
  468. package/src/upgrade.ts +127 -0
  469. package/src/utils.ts +212 -0
  470. package/src/voice-attachment.ts +51 -0
  471. package/src/voice-handler.ts +908 -0
  472. package/src/voice-message.e2e.test.ts +1255 -0
  473. package/src/voice.test.ts +281 -0
  474. package/src/voice.ts +627 -0
  475. package/src/wait-session.ts +147 -0
  476. package/src/websockify.ts +101 -0
  477. package/src/worker-types.ts +64 -0
  478. package/src/worktree-lifecycle.e2e.test.ts +391 -0
  479. package/src/worktree-utils.ts +4 -0
  480. package/src/worktrees.test.ts +223 -0
  481. package/src/worktrees.ts +1294 -0
  482. package/src/xml.test.ts +38 -0
  483. package/src/xml.ts +121 -0
@@ -0,0 +1,554 @@
1
+ ---
2
+ name: x-articles
3
+ description: >
4
+ Edit x.com (Twitter) long-form article drafts reliably. Use this for
5
+ markdown imports, bulk formatting, code blocks, headings, lists, and
6
+ repeated inline styling. Inspect and validate with Playwriter, but prefer
7
+ x.com (Twitter) article GraphQL mutations for deterministic updates.
8
+ version: 0.1.0
9
+ ---
10
+
11
+ <!-- Skill for editing x.com (Twitter) article drafts through Playwriter plus content-state mutations. -->
12
+
13
+ Use this skill when editing long-form article drafts on `x.com/compose/articles`
14
+ (Twitter Articles).
15
+
16
+ ## Read Playwriter First
17
+
18
+ Before using this skill, read the `playwriter` skill and run:
19
+
20
+ ```bash
21
+ playwriter skill
22
+ ```
23
+
24
+ This skill assumes Playwriter is already set up and connected to the user's
25
+ existing Chrome session.
26
+
27
+ Read the full output. Do not pipe it through `head`, `tail`, or other
28
+ truncation commands.
29
+
30
+ ## Core idea
31
+
32
+ Use Playwriter for three things:
33
+
34
+ 1. connect to the already-open x.com (Twitter) article draft
35
+ 2. inspect the editor and capture one real network mutation
36
+ 3. validate the final rendered result after updates
37
+
38
+ For anything bigger than a tiny tweak, do **not** rely on manual typing inside
39
+ the editor. Generate the article `content_state` locally and send the same
40
+ GraphQL mutation x.com (Twitter) already uses.
41
+
42
+ ## Editor model
43
+
44
+ The article body is represented as a `content_state` object with two main
45
+ parts:
46
+
47
+ - `blocks`: ordered content blocks
48
+ - `entity_map`: supporting entities, especially code blocks
49
+
50
+ Important block types:
51
+
52
+ - `unstyled` — normal paragraph
53
+ - `header-two` — section subheading
54
+ - `ordered-list-item` — numbered list item
55
+ - `atomic` — embedded block like a markdown code block
56
+
57
+ Important entity type:
58
+
59
+ - `MARKDOWN` — used for code blocks, with the markdown fence stored in
60
+ `entity_map[*].value.data.markdown`
61
+
62
+ Longer example `content_state`:
63
+
64
+ ````json
65
+ {
66
+ "blocks": [
67
+ {
68
+ "key": "k0",
69
+ "text": "event sourcing for application state",
70
+ "type": "header-two",
71
+ "data": {},
72
+ "entity_ranges": [],
73
+ "inline_style_ranges": []
74
+ },
75
+ {
76
+ "key": "k1",
77
+ "text": "your clanker loves state",
78
+ "type": "unstyled",
79
+ "data": {},
80
+ "entity_ranges": [],
81
+ "inline_style_ranges": [
82
+ { "offset": 19, "length": 5, "style": "Bold" }
83
+ ]
84
+ },
85
+ {
86
+ "key": "k2",
87
+ "text": "doubles your final app state",
88
+ "type": "ordered-list-item",
89
+ "data": {},
90
+ "entity_ranges": [],
91
+ "inline_style_ranges": []
92
+ },
93
+ {
94
+ "key": "k3",
95
+ "text": "doubles your bugs",
96
+ "type": "ordered-list-item",
97
+ "data": {},
98
+ "entity_ranges": [],
99
+ "inline_style_ranges": []
100
+ },
101
+ {
102
+ "key": "k4",
103
+ "text": " ",
104
+ "type": "atomic",
105
+ "data": {},
106
+ "entity_ranges": [
107
+ { "key": 0, "offset": 0, "length": 1 }
108
+ ],
109
+ "inline_style_ranges": []
110
+ },
111
+ {
112
+ "key": "k5",
113
+ "text": "if you can derive it, don't store it.",
114
+ "type": "unstyled",
115
+ "data": {},
116
+ "entity_ranges": [],
117
+ "inline_style_ranges": [
118
+ { "offset": 7, "length": 6, "style": "Bold" }
119
+ ]
120
+ }
121
+ ],
122
+ "entity_map": [
123
+ {
124
+ "key": "0",
125
+ "value": {
126
+ "type": "MARKDOWN",
127
+ "mutability": "Mutable",
128
+ "data": {
129
+ "markdown": "```typescript\nfunction shouldShowFooter() {\n return true\n}\n```"
130
+ }
131
+ }
132
+ }
133
+ ]
134
+ }
135
+ ````
136
+
137
+ This is the minimum mental model:
138
+
139
+ - `blocks` is the article in order
140
+ - each paragraph, heading, and list item is a separate block
141
+ - code blocks are `atomic` blocks that point into `entity_map`
142
+ - inline bold lives in `inline_style_ranges`
143
+
144
+ ## Recommended workflow
145
+
146
+ ### 1. Open or locate the draft
147
+
148
+ Find the existing article editor page in the connected browser. The URL format
149
+ is:
150
+
151
+ ```text
152
+ https://x.com/compose/articles/edit/<article_id>
153
+ ```
154
+
155
+ Always parse and keep the numeric `article_id`. The content mutation needs it.
156
+
157
+ Example Playwriter check:
158
+
159
+ ```bash
160
+ playwriter session new
161
+ playwriter -s 1 -e '
162
+ state.page = context.pages().find((p) => {
163
+ return p.url().includes("/compose/articles/edit/")
164
+ })
165
+ if (!state.page) {
166
+ throw new Error("No article editor page found")
167
+ }
168
+ console.log(state.page.url())
169
+ '
170
+ ```
171
+
172
+ ### 2. Explore with small manual edits first
173
+
174
+ Use the UI to learn how the editor reacts before doing bulk updates. Good
175
+ exploration tasks:
176
+
177
+ - add one paragraph
178
+ - convert one block to `Sottotitolo`
179
+ - insert one code block
180
+ - bold one word in one paragraph
181
+
182
+ After each change, inspect the rendered HTML with `getCleanHTML()`.
183
+
184
+ Example validation command:
185
+
186
+ ```bash
187
+ playwriter -s 1 -e '
188
+ state.page = context.pages().find((p) => {
189
+ return p.url().includes("/compose/articles/edit/")
190
+ })
191
+ console.log(
192
+ await getCleanHTML({
193
+ locator: state.page.locator("[data-testid=\"composer\"]"),
194
+ showDiffSinceLastCall: false,
195
+ }),
196
+ )
197
+ '
198
+ ```
199
+
200
+ ### 3. Capture real network traffic
201
+
202
+ Watch GraphQL requests while making one tiny manual change. This gives you the
203
+ exact mutation names and payload shapes used by the current x.com (Twitter)
204
+ editor.
205
+
206
+ The two important mutations found in this session were:
207
+
208
+ - `ArticleEntityUpdateTitle`
209
+ - `ArticleEntityUpdateContent`
210
+
211
+ The content mutation URL looked like:
212
+
213
+ ```text
214
+ https://x.com/i/api/graphql/<queryId>/ArticleEntityUpdateContent
215
+ ```
216
+
217
+ The exact `queryId` can change over time. Do not hardcode it blindly without
218
+ first confirming it from a real request in the current session.
219
+
220
+ Example request logger:
221
+
222
+ ```bash
223
+ playwriter -s 1 -e '
224
+ state.page = context.pages().find((p) => {
225
+ return p.url().includes("/compose/articles/edit/")
226
+ })
227
+ state.requests = []
228
+ state.page.removeAllListeners("request")
229
+ state.page.on("request", (req) => {
230
+ if (req.url().includes("ArticleEntity") || req.url().includes("graphql")) {
231
+ state.requests.push({
232
+ url: req.url(),
233
+ method: req.method(),
234
+ postData: req.postData(),
235
+ })
236
+ }
237
+ })
238
+ console.log(
239
+ "Ready: now make one tiny manual edit in the page, then rerun this command to inspect state.requests",
240
+ )
241
+ '
242
+ ```
243
+
244
+ ### 4. Use direct content updates for bulk work
245
+
246
+ Once you know the current mutation shape, generate the full `content_state`
247
+ locally and send the content update directly.
248
+
249
+ This is the reliable path for:
250
+
251
+ - full markdown import
252
+ - replacing large sections
253
+ - converting paragraphs to ordered lists
254
+ - adding one bold keyword per paragraph
255
+ - fixing code block languages
256
+
257
+ Concrete pattern:
258
+
259
+ 1. build `content_state` in a local JSON file
260
+ 2. read `ct0` from `document.cookie`
261
+ 3. send `ArticleEntityUpdateContent` with the same `queryId` and feature flags
262
+ 4. reload the page
263
+
264
+ ### 5. Reload and validate
265
+
266
+ After every direct mutation:
267
+
268
+ 1. reload the article editor page
269
+ 2. inspect `getCleanHTML()`
270
+ 3. search for expected headings, list items, bold splits, and code labels
271
+
272
+ Do not trust the visual editor alone.
273
+
274
+ Example reload + search:
275
+
276
+ ```bash
277
+ playwriter -s 1 -e '
278
+ state.page = context.pages().find((p) => {
279
+ return p.url().includes("/compose/articles/edit/")
280
+ })
281
+ await state.page.reload({ waitUntil: "domcontentloaded" })
282
+ await waitForPageLoad({ page: state.page, timeout: 8000 })
283
+ console.log(
284
+ await getCleanHTML({
285
+ locator: state.page.locator("[data-testid=\"composer\"]"),
286
+ search: /debugging with event streams|typescript|ordered-list-item/i,
287
+ showDiffSinceLastCall: false,
288
+ }),
289
+ )
290
+ '
291
+ ```
292
+
293
+ ## Block type cheatsheet
294
+
295
+ ### Paragraphs
296
+
297
+ Use:
298
+
299
+ ```json
300
+ {
301
+ "type": "unstyled",
302
+ "text": "your paragraph text"
303
+ }
304
+ ```
305
+
306
+ ### Subheadings
307
+
308
+ Use:
309
+
310
+ ```json
311
+ {
312
+ "type": "header-two",
313
+ "text": "debugging with event streams"
314
+ }
315
+ ```
316
+
317
+ ### Numbered lists
318
+
319
+ Each item is its own block:
320
+
321
+ ```json
322
+ {
323
+ "type": "ordered-list-item",
324
+ "text": "doubles your bug surface"
325
+ }
326
+ ```
327
+
328
+ ### Code blocks
329
+
330
+ Code blocks are not plain text blocks. They are:
331
+
332
+ 1. one `atomic` block in `blocks`
333
+ 2. one `MARKDOWN` entity in `entity_map`
334
+
335
+ The atomic block points to the entity with `entity_ranges`.
336
+
337
+ The entity markdown should include the full fence, for example:
338
+
339
+ ````text
340
+ ```typescript
341
+ const x = 1
342
+ ```
343
+ ````
344
+
345
+ If you want the visible language label to say `typescript`, the stored fence
346
+ must be ` ```typescript `, not ` ```ts `.
347
+
348
+ ## Inline styles
349
+
350
+ Bold text is represented with `inlineStyleRanges` inside a block.
351
+
352
+ Important session learning:
353
+
354
+ - the style name is `Bold`
355
+ - not `BOLD`
356
+
357
+ Example:
358
+
359
+ ```json
360
+ {
361
+ "text": "your clanker loves state",
362
+ "inlineStyleRanges": [
363
+ { "offset": 19, "length": 5, "style": "Bold" }
364
+ ]
365
+ }
366
+ ```
367
+
368
+ Always calculate offsets against the raw block text exactly as stored.
369
+
370
+ ## Known UI pitfalls
371
+
372
+ The manual editor flow has several traps:
373
+
374
+ ### Heading inheritance
375
+
376
+ After creating a heading, pressing `Enter` once can keep the next block in the
377
+ same heading style. To reset to a paragraph, press `Enter` again.
378
+
379
+ ### Post-code-block cursor placement
380
+
381
+ Typing after a code block is unreliable. The editor can:
382
+
383
+ - append text to the wrong block
384
+ - split text unexpectedly
385
+ - create stray headings
386
+ - leave part of a sentence in one block and the rest in another
387
+
388
+ For anything more than a tiny manual tweak, use direct content updates instead.
389
+
390
+ ### Visual feedback is incomplete
391
+
392
+ The editor can look correct while the underlying block structure is wrong.
393
+ Always inspect the HTML or mutation payload.
394
+
395
+ ### Playwriter sessions can reset
396
+
397
+ If the relay server restarts or the extension reconnects, Playwriter sessions
398
+ can disappear. If that happens, create a new Playwriter session and reattach to
399
+ the already-open article page.
400
+
401
+ Recovery command:
402
+
403
+ ```bash
404
+ playwriter session new
405
+ playwriter -s 1 -e '
406
+ state.page = context.pages().find((p) => {
407
+ return p.url().includes("/compose/articles/edit/")
408
+ })
409
+ if (!state.page) {
410
+ throw new Error("No article editor page found")
411
+ }
412
+ console.log(state.page.url())
413
+ '
414
+ ```
415
+
416
+ ## Auth and request details
417
+
418
+ Direct content updates need proper auth headers. In this session, the direct
419
+ `fetch()` worked only after including:
420
+
421
+ - the X bearer token
422
+ - `x-csrf-token` from the `ct0` cookie
423
+ - the standard X active-user/auth/client-language headers
424
+
425
+ If you get `403`, inspect the successful browser request and match its headers.
426
+
427
+ In this session, the direct fetch succeeded only after matching:
428
+
429
+ - bearer token
430
+ - `x-csrf-token`
431
+ - `x-twitter-active-user`
432
+ - `x-twitter-auth-type`
433
+ - `x-twitter-client-language`
434
+
435
+ ## Validation checklist
436
+
437
+ After updating an article, verify all of these:
438
+
439
+ 1. correct title in the title field
440
+ 2. headings appear as `header-two`
441
+ 3. ordered lists appear as `ordered-list-item`
442
+ 4. code blocks render as `markdown-code-block`
443
+ 5. code block language labels say what you expect, for example `typescript`
444
+ 6. bold keywords are split into separate styled spans in the HTML
445
+ 7. no stray empty headings or broken split paragraphs remain
446
+
447
+ ## Useful recipes
448
+
449
+ ### Import a markdown article
450
+
451
+ 1. parse the markdown locally
452
+ 2. map paragraphs to `unstyled`
453
+ 3. map `##` headings to `header-two`
454
+ 4. map numbered list items to `ordered-list-item`
455
+ 5. map fenced code blocks to `atomic` + `MARKDOWN` entities
456
+ 6. send `ArticleEntityUpdateContent`
457
+ 7. reload and validate
458
+
459
+ The fastest implementation is usually:
460
+
461
+ 1. generate `./tmp/x-article-content-state.json`
462
+ 2. read it from a Playwriter command with `fs.readFileSync`
463
+ 3. push it with the direct content mutation
464
+
465
+ ### Bold one keyword per paragraph
466
+
467
+ 1. choose one keyword per paragraph
468
+ 2. compute exact `offset` and `length`
469
+ 3. add `inlineStyleRanges` with style `Bold`
470
+ 4. push the updated `content_state`
471
+ 5. reload and verify the HTML splits around the bold span
472
+
473
+ ### Fix code language labels
474
+
475
+ Update the markdown entity fences. Example:
476
+
477
+ - bad: ` ```ts `
478
+ - good: ` ```typescript `
479
+
480
+ Then resend the full `content_state` and reload the editor.
481
+
482
+ ## Minimal bulk update example
483
+
484
+ Use this pattern when you already have the right `queryId` and payload shape:
485
+
486
+ ```bash
487
+ playwriter -s 1 -e '
488
+ const fs = require("node:fs")
489
+ state.page = context.pages().find((p) => {
490
+ return p.url().includes("/compose/articles/edit/")
491
+ })
492
+ const articleId = state.page.url().match(/edit\/(\d+)/)?.[1]
493
+ const contentState = JSON.parse(
494
+ fs.readFileSync("./tmp/x-article-content-state.json", "utf8"),
495
+ )
496
+ const csrfToken = await state.page.evaluate(() => {
497
+ return document.cookie
498
+ .split("; ")
499
+ .find((x) => x.startsWith("ct0="))
500
+ ?.slice(4) || ""
501
+ })
502
+ const payload = {
503
+ variables: {
504
+ content_state: contentState,
505
+ article_entity: articleId,
506
+ },
507
+ features: {
508
+ profile_label_improvements_pcf_label_in_post_enabled: true,
509
+ responsive_web_profile_redirect_enabled: false,
510
+ rweb_tipjar_consumption_enabled: false,
511
+ verified_phone_label_enabled: false,
512
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
513
+ responsive_web_graphql_timeline_navigation_enabled: true,
514
+ },
515
+ queryId: "<capture-from-real-request>",
516
+ }
517
+ const response = await state.page.evaluate(async ({ payload, csrfToken }) => {
518
+ const res = await fetch(
519
+ `https://x.com/i/api/graphql/${payload.queryId}/ArticleEntityUpdateContent`,
520
+ {
521
+ method: "POST",
522
+ credentials: "include",
523
+ headers: {
524
+ authorization: "<capture-from-real-request>",
525
+ "content-type": "application/json",
526
+ "x-csrf-token": csrfToken,
527
+ "x-twitter-active-user": "yes",
528
+ "x-twitter-auth-type": "OAuth2Session",
529
+ "x-twitter-client-language": "it",
530
+ },
531
+ body: JSON.stringify(payload),
532
+ },
533
+ )
534
+ return { status: res.status, text: await res.text() }
535
+ }, { payload, csrfToken })
536
+ console.log(response.status)
537
+ console.log(response.text.slice(0, 1000))
538
+ '
539
+ ```
540
+
541
+ Replace the bearer token and `queryId` with values captured from a successful
542
+ browser request in the current session.
543
+
544
+ ## Default strategy
545
+
546
+ Use this default unless the task is tiny:
547
+
548
+ 1. inspect the current draft in the browser
549
+ 2. capture one real content mutation from X
550
+ 3. generate the final `content_state` locally
551
+ 4. update the draft with the same mutation shape
552
+ 5. validate the result in the live editor HTML
553
+
554
+ That is the fastest path and the most likely to work in one shot.
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: zele
3
+ description: >
4
+ Control Gmail and Google Calendar via CLI. Read, search, send, reply, and forward
5
+ emails. Create, update, and delete calendar events. Manage drafts, labels, and attachments.
6
+ Supports multiple Google accounts. Use this skill whenever the user asks to check email,
7
+ send messages, schedule meetings, or manage their calendar.
8
+ ---
9
+
10
+ # zele — Gmail & Google Calendar CLI
11
+
12
+ A multi-account Gmail and Google Calendar client. Output is YAML, pipe-friendly.
13
+
14
+ ## Setup
15
+
16
+ ```bash
17
+ # install (requires bun)
18
+ bun install -g zele
19
+
20
+ # show connected accounts
21
+ zele whoami
22
+
23
+ # authenticate (opens browser, supports multiple accounts)
24
+ zele login
25
+ ```
26
+
27
+ **Remote/headless login:** `zele login` is interactive — it prints an authorization URL and waits for a redirect URL to be pasted back. In agent/headless environments, run it inside tmux so the process persists:
28
+
29
+ ```bash
30
+ # start login in a tmux session
31
+ tmux new-session -d -s zele-login 'zele login'
32
+
33
+ # read the authorization URL from tmux output
34
+ tmux capture-pane -t zele-login -p
35
+
36
+ # after the user completes consent in their browser, paste the redirect URL
37
+ tmux send-keys -t zele-login 'http://localhost:...?code=...' Enter
38
+
39
+ # verify login succeeded
40
+ tmux capture-pane -t zele-login -p
41
+ tmux kill-session -t zele-login
42
+ ```
43
+
44
+ ## Important
45
+
46
+ **Always run `zele --help` before using.** The help output is the source of truth for all commands, options, and syntax. Run `zele <command> --help` for subcommand details (e.g. `zele mail send --help`). NEVER use head to truncate the output. read it fully.
47
+
48
+ Running `zele` with no subcommand launches a human-friendly TUI for browsing email. **Agents should not use the TUI** — always use the CLI subcommands (`zele mail list`, `zele cal events`, etc.) which output structured YAML.
49
+
50
+ ## Capabilities
51
+
52
+ - **Mail:** list, search, read, send, reply, forward, star, archive, trash, label, watch for new emails, manage filters
53
+ - **Drafts:** list, create, get, send, delete
54
+ - **Calendar:** list calendars, list/search events, create/update/delete events, RSVP, free/busy
55
+ - **Labels:** list, create, delete, unread counts
56
+ - **Attachments:** list per thread, download
57
+ - **Multi-account:** all commands support `--account <email>` to filter; list/search merge across accounts
58
+
59
+ ## Account discovery
60
+
61
+ When the user asks to check emails **for a specific account** (e.g. "check my work email", "what's new on my personal Gmail?"), always run `zele whoami` first to list the connected accounts and find the exact email address to pass to `--account`. Never guess the email — use the output of `zele whoami` to pick the right one.
62
+
63
+ ```bash
64
+ # list connected accounts
65
+ zele whoami
66
+
67
+ # then use the email from the output
68
+ zele mail list --account user@work.com
69
+ ```
70
+
71
+ ## Examples
72
+
73
+ ```bash
74
+ # list inbox
75
+ zele mail list
76
+
77
+ # list only unread emails
78
+ zele mail list --filter "is:unread"
79
+
80
+ # list unread emails with attachments in inbox
81
+ zele mail list --filter "is:unread has:attachment"
82
+
83
+ # combine filter with folder
84
+ zele mail list --filter "from:github" --folder sent
85
+
86
+ # search mail
87
+ zele mail search "from:github subject:review"
88
+
89
+ # read a thread (thread IDs come from list/search output)
90
+ zele mail read <threadId>
91
+
92
+ # send an email with attachment
93
+ zele mail send --to alice@example.com --subject "Report" --body "See attached" --attach report.pdf
94
+
95
+ # reply all
96
+ zele mail reply <threadId> --body "Thanks!" --all
97
+
98
+ # watch inbox for new mail (polls every 15s)
99
+ zele mail watch
100
+
101
+ # today's calendar events across all accounts
102
+ zele cal events --today --all
103
+
104
+ # create a meeting with Google Meet
105
+ zele cal create --summary "Standup" --from tomorrow --to +30m --meet --attendees bob@example.com
106
+
107
+ # check free/busy
108
+ zele cal freebusy --from today --to +8h
109
+
110
+ # list Gmail filters
111
+ zele mail filter list
112
+ ```