@aitne-sh/aitne 0.1.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 (249) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +464 -0
  3. package/agent-assets/agent-profiles/_safety.md +26 -0
  4. package/agent-assets/agent-profiles/conversational.md +33 -0
  5. package/agent-assets/agent-profiles/docs-qa.md +24 -0
  6. package/agent-assets/agent-profiles/observer.md +28 -0
  7. package/agent-assets/agent-profiles/profile-importer.md +63 -0
  8. package/agent-assets/agent-profiles/proxy.md +28 -0
  9. package/agent-assets/agent-profiles/routine.md +16 -0
  10. package/agent-assets/agent-profiles/task.md +18 -0
  11. package/agent-assets/docs/concepts/agent-day.md +88 -0
  12. package/agent-assets/docs/concepts/auth-health.md +75 -0
  13. package/agent-assets/docs/concepts/backends-and-tiers.md +126 -0
  14. package/agent-assets/docs/concepts/costs-and-quotas.md +103 -0
  15. package/agent-assets/docs/concepts/delegated-mode.md +223 -0
  16. package/agent-assets/docs/concepts/memory-model.md +118 -0
  17. package/agent-assets/docs/concepts/observations.md +80 -0
  18. package/agent-assets/docs/concepts/process-keys.md +89 -0
  19. package/agent-assets/docs/concepts/routines.md +108 -0
  20. package/agent-assets/docs/concepts/safety-and-execution.md +109 -0
  21. package/agent-assets/docs/concepts/safety-model.md +279 -0
  22. package/agent-assets/docs/concepts/skills.md +100 -0
  23. package/agent-assets/docs/features/integrations/calendar.md +92 -0
  24. package/agent-assets/docs/features/integrations/git.md +95 -0
  25. package/agent-assets/docs/features/integrations/github.md +170 -0
  26. package/agent-assets/docs/features/integrations/mail.md +106 -0
  27. package/agent-assets/docs/features/integrations/notion.md +69 -0
  28. package/agent-assets/docs/features/integrations/obsidian.md +71 -0
  29. package/agent-assets/docs/features/lifestyle/git.md +178 -0
  30. package/agent-assets/docs/features/lifestyle/reading.md +93 -0
  31. package/agent-assets/docs/features/lifestyle/receipts.md +71 -0
  32. package/agent-assets/docs/features/lifestyle/travel-bookings.md +44 -0
  33. package/agent-assets/docs/features/lifestyle/travel-time.md +52 -0
  34. package/agent-assets/docs/features/memory-files/agent-journal.md +105 -0
  35. package/agent-assets/docs/features/memory-files/projects.md +56 -0
  36. package/agent-assets/docs/features/memory-files/roadmap.md +61 -0
  37. package/agent-assets/docs/features/memory-files/schedule.md +112 -0
  38. package/agent-assets/docs/features/memory-files/today.md +73 -0
  39. package/agent-assets/docs/features/memory-files/user-profile.md +81 -0
  40. package/agent-assets/docs/features/messaging/dashboard-chat.md +93 -0
  41. package/agent-assets/docs/features/messaging/discord.md +50 -0
  42. package/agent-assets/docs/features/messaging/overview.md +111 -0
  43. package/agent-assets/docs/features/messaging/pairing-and-magic-phrase.md +69 -0
  44. package/agent-assets/docs/features/messaging/slack.md +51 -0
  45. package/agent-assets/docs/features/messaging/telegram.md +63 -0
  46. package/agent-assets/docs/features/messaging/whatsapp.md +48 -0
  47. package/agent-assets/docs/features/operations/activity-and-conversations.md +105 -0
  48. package/agent-assets/docs/features/operations/approvals.md +58 -0
  49. package/agent-assets/docs/features/operations/backend-routing.md +62 -0
  50. package/agent-assets/docs/features/operations/cost-tracking.md +59 -0
  51. package/agent-assets/docs/features/operations/notifications.md +69 -0
  52. package/agent-assets/docs/features/operations/quiet-hours.md +106 -0
  53. package/agent-assets/docs/features/operations/schedule-approaching.md +60 -0
  54. package/agent-assets/docs/features/routines/custom-routines.md +101 -0
  55. package/agent-assets/docs/features/routines/evening-review.md +81 -0
  56. package/agent-assets/docs/features/routines/hourly-check.md +85 -0
  57. package/agent-assets/docs/features/routines/monthly-review.md +65 -0
  58. package/agent-assets/docs/features/routines/morning-routine.md +123 -0
  59. package/agent-assets/docs/features/routines/weekly-review.md +70 -0
  60. package/agent-assets/docs/getting-started/01-what-is-this.md +192 -0
  61. package/agent-assets/docs/getting-started/02-first-steps.md +80 -0
  62. package/agent-assets/docs/getting-started/03-what-can-this-do.md +110 -0
  63. package/agent-assets/docs/getting-started/04-first-day.md +287 -0
  64. package/agent-assets/docs/glossary.md +116 -0
  65. package/agent-assets/docs/guides/add-a-custom-routine.md +71 -0
  66. package/agent-assets/docs/guides/backup-and-restore.md +54 -0
  67. package/agent-assets/docs/guides/change-which-model-handles-x.md +47 -0
  68. package/agent-assets/docs/guides/connect-a-new-mail-account.md +59 -0
  69. package/agent-assets/docs/guides/import-knowledge-file.md +275 -0
  70. package/agent-assets/docs/guides/install-and-run.md +72 -0
  71. package/agent-assets/docs/guides/migrate-machines.md +52 -0
  72. package/agent-assets/docs/guides/pause-the-agent.md +65 -0
  73. package/agent-assets/docs/guides/reinstall-cleanly.md +52 -0
  74. package/agent-assets/docs/guides/setup-wizard.md +107 -0
  75. package/agent-assets/docs/guides/switch-default-backend.md +60 -0
  76. package/agent-assets/docs/reference/api.md +51 -0
  77. package/agent-assets/docs/reference/cli-commands.md +121 -0
  78. package/agent-assets/docs/reference/config.md +74 -0
  79. package/agent-assets/docs/reference/disallowed-tools.md +76 -0
  80. package/agent-assets/docs/reference/keyboard-shortcuts.md +39 -0
  81. package/agent-assets/docs/reference/process-keys.md +59 -0
  82. package/agent-assets/docs/reference/skills.md +50 -0
  83. package/agent-assets/docs/troubleshooting/auth-failed.md +57 -0
  84. package/agent-assets/docs/troubleshooting/dashboard-shows-degraded.md +55 -0
  85. package/agent-assets/docs/troubleshooting/fallback-keeps-firing.md +54 -0
  86. package/agent-assets/docs/troubleshooting/messaging-not-pairing.md +53 -0
  87. package/agent-assets/docs/troubleshooting/morning-routine-didnt-run.md +75 -0
  88. package/agent-assets/docs/troubleshooting/observation-not-detected.md +57 -0
  89. package/agent-assets/docs/troubleshooting/quota-exhausted.md +57 -0
  90. package/agent-assets/optimizer-skills/drift-analysis/SKILL.md +75 -0
  91. package/agent-assets/optimizer-skills/knowledge-map/SKILL.md +71 -0
  92. package/agent-assets/optimizer-skills/skill-curation/SKILL.md +108 -0
  93. package/agent-assets/project-doc-templates/git-repo.md +21 -0
  94. package/agent-assets/project-doc-templates/project.md +38 -0
  95. package/agent-assets/skills/attach/SKILL.md +104 -0
  96. package/agent-assets/skills/context/SKILL.md +257 -0
  97. package/agent-assets/skills/context/curation.json +37 -0
  98. package/agent-assets/skills/context/seeds/file-responsibilities.seed.json +13 -0
  99. package/agent-assets/skills/context/seeds/frontmatter-requirements.seed.json +40 -0
  100. package/agent-assets/skills/docs-search/SKILL.md +176 -0
  101. package/agent-assets/skills/external-services/SKILL.delegated.claude.md +369 -0
  102. package/agent-assets/skills/external-services/SKILL.delegated.codex.md +349 -0
  103. package/agent-assets/skills/external-services/SKILL.delegated.gemini.md +347 -0
  104. package/agent-assets/skills/external-services/SKILL.md +371 -0
  105. package/agent-assets/skills/mail/SKILL.delegated.claude.md +284 -0
  106. package/agent-assets/skills/mail/SKILL.delegated.codex.md +261 -0
  107. package/agent-assets/skills/mail/SKILL.delegated.gemini.md +255 -0
  108. package/agent-assets/skills/mail/SKILL.md +313 -0
  109. package/agent-assets/skills/mail/references/errors.md +17 -0
  110. package/agent-assets/skills/mail/references/providers.md +40 -0
  111. package/agent-assets/skills/mail/references/query-grammar.md +24 -0
  112. package/agent-assets/skills/management-policy/SKILL.md +307 -0
  113. package/agent-assets/skills/management-policy/curation.json +13 -0
  114. package/agent-assets/skills/management-policy/seeds/policy-file-shape.seed.json +16 -0
  115. package/agent-assets/skills/management-task-modify/SKILL.md +202 -0
  116. package/agent-assets/skills/management-task-register/SKILL.md +330 -0
  117. package/agent-assets/skills/management-task-stop/SKILL.md +166 -0
  118. package/agent-assets/skills/notify/SKILL.md +196 -0
  119. package/agent-assets/skills/notion/SKILL.delegated.claude.md +254 -0
  120. package/agent-assets/skills/notion/SKILL.delegated.codex.md +195 -0
  121. package/agent-assets/skills/notion/SKILL.delegated.gemini.md +194 -0
  122. package/agent-assets/skills/notion/SKILL.md +86 -0
  123. package/agent-assets/skills/observations/SKILL.md +234 -0
  124. package/agent-assets/skills/observations/curation.json +13 -0
  125. package/agent-assets/skills/observations/seeds/source-namespacing.seed.json +20 -0
  126. package/agent-assets/skills/project-doc/SKILL.md +86 -0
  127. package/agent-assets/skills/project-doc/curation.json +21 -0
  128. package/agent-assets/skills/project-doc/seeds/project-shape.seed.json +25 -0
  129. package/agent-assets/skills/project-doc/seeds/slug-grammar.seed.json +20 -0
  130. package/agent-assets/skills/reading/SKILL.md +198 -0
  131. package/agent-assets/skills/reading/references/reading-taste.md +197 -0
  132. package/agent-assets/skills/receipts/SKILL.md +134 -0
  133. package/agent-assets/skills/roadmap/SKILL.md +276 -0
  134. package/agent-assets/skills/roadmap/curation.json +13 -0
  135. package/agent-assets/skills/roadmap/references/horizon-tags.md +40 -0
  136. package/agent-assets/skills/roadmap/references/preparation-timeline.md +47 -0
  137. package/agent-assets/skills/roadmap/seeds/entry-types.seed.json +16 -0
  138. package/agent-assets/skills/schedule/SKILL.md +228 -0
  139. package/agent-assets/skills/scheduled-managed-task/SKILL.md +392 -0
  140. package/agent-assets/skills/today/SKILL.md +198 -0
  141. package/agent-assets/skills/today/curation.json +21 -0
  142. package/agent-assets/skills/today/seeds/agent-notes-flavors.seed.json +17 -0
  143. package/agent-assets/skills/today/seeds/section-shape.seed.json +17 -0
  144. package/agent-assets/skills/travel/SKILL.md +132 -0
  145. package/agent-assets/skills/travel-time/SKILL.md +149 -0
  146. package/agent-assets/skills/user-interview/SKILL.md +323 -0
  147. package/agent-assets/skills/user-interview/references/sweep-and-fallback.md +94 -0
  148. package/agent-assets/skills/user-profile/SKILL.md +210 -0
  149. package/agent-assets/skills/user-profile/curation.json +29 -0
  150. package/agent-assets/skills/user-profile/seeds/learned-context-format.seed.json +14 -0
  151. package/agent-assets/skills/user-profile/seeds/routing-table.seed.json +53 -0
  152. package/agent-assets/skills/user-profile/seeds/topic-files.seed.json +27 -0
  153. package/agent-assets/task-flows/dashboard.docs_qa.md +43 -0
  154. package/agent-assets/task-flows/default.md +11 -0
  155. package/agent-assets/task-flows/git.branch.created.md +25 -0
  156. package/agent-assets/task-flows/git.lifecycle.poll.md +52 -0
  157. package/agent-assets/task-flows/git.local_ahead.stale.md +34 -0
  158. package/agent-assets/task-flows/git.merge_to_default.md +30 -0
  159. package/agent-assets/task-flows/git.project.refresh_architecture.md +100 -0
  160. package/agent-assets/task-flows/git.project.retemplate.md +73 -0
  161. package/agent-assets/task-flows/git.push.detected.md +32 -0
  162. package/agent-assets/task-flows/git.push.force_pushed.md +36 -0
  163. package/agent-assets/task-flows/git.tag.created.md +24 -0
  164. package/agent-assets/task-flows/github.assigned.md +43 -0
  165. package/agent-assets/task-flows/github.pull_request.review_requested.md +57 -0
  166. package/agent-assets/task-flows/github.security_alert.md +45 -0
  167. package/agent-assets/task-flows/github.workflow_run.failed.md +57 -0
  168. package/agent-assets/task-flows/knowledge.import.md +161 -0
  169. package/agent-assets/task-flows/message.received.dm.md +142 -0
  170. package/agent-assets/task-flows/message.received.dm_first.md +117 -0
  171. package/agent-assets/task-flows/message.received.md +14 -0
  172. package/agent-assets/task-flows/routine.custom.md +38 -0
  173. package/agent-assets/task-flows/routine.evening_review.md +323 -0
  174. package/agent-assets/task-flows/routine.hourly_check.delegated.claude.md +405 -0
  175. package/agent-assets/task-flows/routine.hourly_check.delegated.codex.md +400 -0
  176. package/agent-assets/task-flows/routine.hourly_check.delegated.gemini.md +404 -0
  177. package/agent-assets/task-flows/routine.hourly_check.md +184 -0
  178. package/agent-assets/task-flows/routine.hourly_check.triage.md +93 -0
  179. package/agent-assets/task-flows/routine.monthly_review.md +250 -0
  180. package/agent-assets/task-flows/routine.morning_routine.md +300 -0
  181. package/agent-assets/task-flows/routine.morning_routine_initial.md +184 -0
  182. package/agent-assets/task-flows/routine.roadmap_refresh.md +275 -0
  183. package/agent-assets/task-flows/routine.today_refresh.md +172 -0
  184. package/agent-assets/task-flows/routine.user_profile_sweep.md +242 -0
  185. package/agent-assets/task-flows/routine.weekly_review.md +247 -0
  186. package/agent-assets/task-flows/schedule.approaching.md +124 -0
  187. package/agent-assets/task-flows/scheduled.dm.md +391 -0
  188. package/agent-assets/task-flows/scheduled.task.md +141 -0
  189. package/agent-assets/task-flows/setup.initial.md +277 -0
  190. package/agent-assets/task-flows/setup.update.md +53 -0
  191. package/agent-assets/templates/README.md +85 -0
  192. package/agent-assets/templates/_index.md +39 -0
  193. package/agent-assets/templates/_manifest.json +103 -0
  194. package/agent-assets/templates/agent/journal.md +10 -0
  195. package/agent-assets/templates/agent/profile-questions.md +74 -0
  196. package/agent-assets/templates/context-index.md +42 -0
  197. package/agent-assets/templates/dossiers/_index.md +22 -0
  198. package/agent-assets/templates/dossiers/evening.md +23 -0
  199. package/agent-assets/templates/dossiers/hourly.md +23 -0
  200. package/agent-assets/templates/dossiers/monthly.md +23 -0
  201. package/agent-assets/templates/dossiers/morning.md +23 -0
  202. package/agent-assets/templates/dossiers/roadmap.md +23 -0
  203. package/agent-assets/templates/dossiers/weekly.md +23 -0
  204. package/agent-assets/templates/projects/_active.base +14 -0
  205. package/agent-assets/templates/projects/_index.md +29 -0
  206. package/agent-assets/templates/roadmap.md +15 -0
  207. package/agent-assets/templates/routines/_index.md +20 -0
  208. package/agent-assets/templates/routines/evening.md +22 -0
  209. package/agent-assets/templates/routines/hourly.md +30 -0
  210. package/agent-assets/templates/routines/monthly.md +25 -0
  211. package/agent-assets/templates/routines/morning.md +26 -0
  212. package/agent-assets/templates/routines/weekly.md +23 -0
  213. package/agent-assets/templates/rules/_index.md +19 -0
  214. package/agent-assets/templates/rules/journal-export.md +41 -0
  215. package/agent-assets/templates/rules/journal-format.md +61 -0
  216. package/agent-assets/templates/rules/management.md +48 -0
  217. package/agent-assets/templates/rules/mcp.md +40 -0
  218. package/agent-assets/templates/rules/policies/_index.md +22 -0
  219. package/agent-assets/templates/rules/redaction.md +30 -0
  220. package/agent-assets/templates/today.md +13 -0
  221. package/agent-assets/templates/user/_index.md +16 -0
  222. package/agent-assets/templates/user/expertise.md +7 -0
  223. package/agent-assets/templates/user/goals.md +7 -0
  224. package/agent-assets/templates/user/people.md +7 -0
  225. package/agent-assets/templates/user/personal.md +7 -0
  226. package/agent-assets/templates/user/profile.md +28 -0
  227. package/agent-assets/templates/user/work.md +7 -0
  228. package/bin/aitne.mjs +1096 -0
  229. package/package.json +78 -0
  230. package/personal-agent.mjs +39 -0
  231. package/scripts/browser.mjs +99 -0
  232. package/scripts/check-redaction-coverage.mjs +109 -0
  233. package/scripts/commands/audit.mjs +309 -0
  234. package/scripts/commands/doctor.mjs +437 -0
  235. package/scripts/commands/open.mjs +40 -0
  236. package/scripts/commands/setup.mjs +21 -0
  237. package/scripts/commands/uninstall.mjs +114 -0
  238. package/scripts/commands/update.mjs +96 -0
  239. package/scripts/commands/version.mjs +62 -0
  240. package/scripts/commands.md +0 -0
  241. package/scripts/lib/sqlite-loader.mjs +49 -0
  242. package/scripts/message-discipline-digest.mjs +535 -0
  243. package/scripts/poc/google-connector-inheritance/REPORT.md +197 -0
  244. package/scripts/poc/google-connector-inheritance/claude-sdk-probe.mjs +79 -0
  245. package/scripts/remint-roadmap-ids.mjs +257 -0
  246. package/scripts/rm-paths.mjs +22 -0
  247. package/scripts/run-node.mjs +223 -0
  248. package/scripts/smoke-obsidian-api.mjs +166 -0
  249. package/scripts/start.mjs +160 -0
@@ -0,0 +1,313 @@
1
+ ---
2
+ name: mail
3
+ description: Load when reading, searching, sending, drafting, replying, tagging, or filing email — Gmail, Outlook, Yahoo, and iCloud accounts share one route surface, with provider-native translation at the daemon.
4
+ allowed-tools:
5
+ - Bash(curl *)
6
+ - Read
7
+ ---
8
+
9
+ # Mail Operations Guide (multi-provider)
10
+
11
+ All mail work goes through `/api/mail/*`. Gmail, Outlook, Yahoo, iCloud —
12
+ same route surface, per-account routing, provider-native translation at the
13
+ daemon.
14
+
15
+ ## 0. Delegation-aware routing (read before §1)
16
+
17
+ This body is materialized only in direct mode and same-backend Gmail
18
+ delegation. (Cross-backend Gmail delegation pulls
19
+ `SKILL.delegated.<backend>.md` instead — that variant has its own
20
+ routing prose.) Read the `<integration_modes>` block injected above:
21
+
22
+ - **Non-Gmail accounts (iCloud, Outlook, Yahoo, IMAP):** unaffected —
23
+ use the `/api/mail/:acct/*` endpoints documented below regardless of
24
+ Gmail's mode.
25
+ - **Gmail accounts AND `gmail="delegated"` (same-backend):** the
26
+ per-account gate inside the mail handler returns
27
+ `410 {"error": "integration_delegated"}`. Do NOT retry through
28
+ `/api/mail/*`. Use the connector tools your session already holds
29
+ natively — `mcp__claude_ai_Gmail__*` (Claude session),
30
+ `mcp__codex_apps__gmail._*` (Codex session), or
31
+ `mcp_google-workspace_gmail.*` (Gemini session, via the
32
+ `google-workspace` extension).
33
+
34
+ Account-resolution (§1) is unchanged: `accounts.md` lists every active
35
+ account regardless of mode. The branch above only affects the wire call
36
+ once an account is selected.
37
+
38
+ ## 1. Account resolution (do this first)
39
+
40
+ `accounts.md` (next to this file) lists the active accounts available this
41
+ session — scope-gated to `enabled provider ∧ account.active ∧ healthy`. If
42
+ the file is absent or empty, there are no active mail accounts: tell the
43
+ user and stop. Account setup is outside this skill's scope — do NOT
44
+ speculate about how to add one.
45
+
46
+ There is **no global "primary" account**. Pick one from conversation
47
+ context, in this order:
48
+
49
+ 1. **User named it.** `"email from my work gmail"` / `"reply from my
50
+ icloud"` → match against the `email` / `label` columns in `accounts.md`.
51
+ 2. **Replying to a thread.** The reply MUST go from the account that
52
+ received the original. Find it by the `accountId` attached to the
53
+ message/thread you fetched.
54
+ 3. **Exactly one active account.** No ambiguity — use it.
55
+ 4. **Multiple active, no context clue.** Ask the user which account to
56
+ use. Do NOT pick arbitrarily.
57
+
58
+ If an API call returns `404 not_found` on an id you resolved from
59
+ `accounts.md`, the file may be stale. Re-fetch the scope-gated set:
60
+
61
+ ```bash
62
+ curl -s "http://localhost:8321/api/mail/accounts?active=1"
63
+ ```
64
+
65
+ This returns the same filtered view `accounts.md` was materialized from.
66
+ Do NOT call `GET /api/mail/accounts` without `?active=1` for recovery — it
67
+ includes dormant and unhealthy rows that every operation will reject.
68
+
69
+ ## 2. Decision rules
70
+
71
+ ### Send vs draft
72
+ - **Prefer drafts.** Create via `POST /mail/:acct/drafts`. The user sends
73
+ from the provider's web UI.
74
+ - Direct send (`POST /mail/:acct/messages/send`) succeeds autonomously —
75
+ the daemon does not DM the owner before sending. (The user's
76
+ `deniedTools` list applies to **delegated-mode connector tools** —
77
+ e.g. Codex's `send_email` — and is enforced at the
78
+ `/api/integrations/:key/exec` task-mode chokepoint via the per-task
79
+ allowed-tools envelope. In direct mode, the `/api/mail/*` route
80
+ handler has no equivalent deny check today, so a send call is what
81
+ it appears to be: a send.) When you judge the user would want to
82
+ know about a send immediately (e.g. a reply to a stranger), call
83
+ `POST /api/notify` yourself.
84
+ - Never include `bcc` unless the user explicitly asks for it.
85
+
86
+ ### Replies — RFC-2822 headers are the source of truth
87
+ Provider thread ids (Gmail `threadId`, Graph `conversationId`) differ;
88
+ RFC-2822 `Message-Id` + `References` is the one chain that works across
89
+ all four kinds.
90
+
91
+ 1. Fetch the thread metadata: `GET /api/mail/:acct/threads/:threadId?body=none`
92
+ (returns `messages[]` in chronological order without raw HTML bodies).
93
+ 2. From the last message, pull `rfc822MsgId` and `references`.
94
+ 3. Build the `reply` block:
95
+ ```json
96
+ {
97
+ "inReplyToRfc822Id": "<last.rfc822MsgId>",
98
+ "references": ["<A>", "<B>", "<last.rfc822MsgId>"],
99
+ "providerThreadId": "<last.threadId>",
100
+ "parentProviderMsgId": "<last.providerMsgId>"
101
+ }
102
+ ```
103
+ `providerThreadId` is Gmail's `threadId` / Graph's `conversationId`. On
104
+ IMAP (Yahoo / iCloud) threads are client-walked — omit it there.
105
+ 4. For reply-all, build `to` from the original `from` + existing `to`, and
106
+ `cc` from the original `cc`, excluding the sender account's own email
107
+ (resolve from `accounts.md`).
108
+
109
+ If the thread endpoint returns `status: "partial"` with `missingAncestors
110
+ > 0`, reply is still safe (the chain you have is headers-valid), but
111
+ acknowledge to the user that older context wasn't indexed locally.
112
+
113
+ ### Searching — prefer the local index
114
+ For "find emails about X / from Y / last month" queries, start with the
115
+ daemon's local FTS5 index — zero provider round-trips, cross-account:
116
+
117
+ ```bash
118
+ curl -s "http://localhost:8321/api/mail/search?q=invoice+acme&limit=20"
119
+ # Scope to one account: &accountId=<id>
120
+ # Shape: { results: [{ accountId, providerMsgId, subject, snippet,
121
+ # receivedAtUtc, from: { email }, isRead }], count, query }
122
+ ```
123
+
124
+ Only fall back to per-account provider search (`/mail/:acct/messages?q=`)
125
+ when you need provider-fresh results or the index doesn't cover the time
126
+ range (fresh installs).
127
+
128
+ ### Reading message bodies — use extracted chunks
129
+ Do not dump full raw HTML mail into a file for `Read`. Large airline,
130
+ receipt, and marketing emails often arrive as one-line compressed HTML and
131
+ can exceed the tool's token/line limits.
132
+
133
+ For headers/snippet/attachment metadata only, use:
134
+
135
+ ```bash
136
+ curl -s "http://localhost:8321/api/mail/ACCT/messages/MSG?body=none"
137
+ ```
138
+
139
+ For body understanding, fetch the extracted body endpoint first:
140
+
141
+ ```bash
142
+ curl -s "http://localhost:8321/api/mail/ACCT/messages/MSG/body?format=extracted&maxChars=12000"
143
+ ```
144
+
145
+ Shape: `{ content, source, links, images, chunk, hasMore, nextChunk,
146
+ totalChars, rawHtmlAvailable, linkCount, imageCount, nextMetadataOffset }`.
147
+ `content` contains visible body text plus link URLs and image alt/title
148
+ metadata. If `hasMore` is true, request the next content chunk:
149
+
150
+ ```bash
151
+ curl -s "http://localhost:8321/api/mail/ACCT/messages/MSG/body?format=extracted&chunk=1&maxChars=12000"
152
+ ```
153
+
154
+ The structured `links` / `images` arrays are paginated separately so a
155
+ marketing email with thousands of links cannot blow up a response. If
156
+ `nextMetadataOffset` is non-null and you need structured metadata beyond
157
+ what is already rendered in `content`, pass `metadataOffset=<value>`.
158
+
159
+ Only use `format=raw` when exact markup is required; it is still chunked:
160
+
161
+ ```bash
162
+ curl -s "http://localhost:8321/api/mail/ACCT/messages/MSG/body?format=raw&chunk=0&maxChars=12000"
163
+ ```
164
+
165
+ ### When NOT to act
166
+ - During `routine.hourly_check` this skill is **read-only** — no sending,
167
+ no draft edits, no tag changes, no trash / untrash / archive.
168
+ - No bulk operations without user confirmation.
169
+ - Trash / untrash / archive run autonomously when not on the user's
170
+ deny list. The daemon does not DM the owner before the call. Single
171
+ ops only; if you're about to trash 3+ messages at once, stop and ask
172
+ the user — the agent's own judgment is the gate, not the daemon.
173
+ - **Delegated mode**: this skill body is loaded only when `gmail.mode ===
174
+ "direct"`. When Gmail is delegated, the materializer picks
175
+ `SKILL.delegated.<sessionBackend>.md` (cross-backend) or skips the
176
+ skill entirely (same-backend, native MCP). If you somehow reach
177
+ `/api/mail/*` from this body while Gmail is delegated, the route
178
+ returns `410 integration_delegated` — re-read `integrations.md` and
179
+ use `POST /api/integrations/gmail/exec` (task mode) instead.
180
+
181
+ ## 3. Provider capability matrix
182
+
183
+ {{> ref:providers }}
184
+
185
+ ## 4. Query grammar
186
+
187
+ {{> ref:query-grammar }}
188
+
189
+ ## 5. Error handling
190
+
191
+ {{> ref:errors }}
192
+
193
+ ## 6. Worked examples
194
+
195
+ ### Reply with context
196
+ ```bash
197
+ # 1. Find the thread — start local.
198
+ curl -s "http://localhost:8321/api/mail/search?q=from:alice+proposal&limit=5"
199
+ # → pick the hit, note accountId + providerMsgId.
200
+
201
+ # 2. Fetch the thread.
202
+ curl -s "http://localhost:8321/api/mail/acct-1/threads/THREAD_ID"
203
+ # → last message has rfc822MsgId, references[], providerMsgId.
204
+
205
+ # 3. Create a draft threaded to it. Drafts are Autonomous tier.
206
+ curl -sX POST "http://localhost:8321/api/mail/acct-1/drafts" \
207
+ -H "Content-Type: application/json" \
208
+ -d '{
209
+ "to": ["alice@example.com"],
210
+ "subject": "Re: Proposal",
211
+ "textBody": "Thanks Alice — ...",
212
+ "reply": {
213
+ "inReplyToRfc822Id": "<abc@mail.example.com>",
214
+ "references": ["<root@mail.example.com>", "<abc@mail.example.com>"],
215
+ "providerThreadId": "THREAD_ID",
216
+ "parentProviderMsgId": "PARENT_MSG_ID"
217
+ }
218
+ }'
219
+ ```
220
+
221
+ ### File a message (read + tag + archive)
222
+ ```bash
223
+ curl -sX POST "http://localhost:8321/api/mail/acct-1/messages/MSG/read" \
224
+ -d '{"read": true}'
225
+ curl -sX POST "http://localhost:8321/api/mail/acct-1/messages/MSG/tags" \
226
+ -d '{"add": ["followup"], "remove": []}'
227
+ curl -sX POST "http://localhost:8321/api/mail/acct-1/messages/MSG/archive"
228
+ ```
229
+ On IMAP, confirm `followup` is in `GET /mail/:acct/tags` `.userDefined`
230
+ first — unknown keywords get dropped.
231
+
232
+ ### Cross-account search → pick account → send
233
+ ```bash
234
+ # Find recipient's earlier emails across all accounts.
235
+ curl -s "http://localhost:8321/api/mail/search?q=from:bob@acme.com&limit=10"
236
+ # → hits carry accountId. Use whichever account received the earlier thread
237
+ # so the reply comes from a familiar address.
238
+
239
+ curl -sX POST "http://localhost:8321/api/mail/acct-2/messages/send" \
240
+ -H "Content-Type: application/json" \
241
+ -d '{"to": ["bob@acme.com"], "subject": "...", "textBody": "..."}'
242
+ ```
243
+
244
+ ## 7. API reference
245
+
246
+ Base URL `http://localhost:8321`. `ACCT` = accountId from `accounts.md`.
247
+
248
+ ### Accounts
249
+ ```bash
250
+ curl -s "http://localhost:8321/api/mail/accounts?active=1"
251
+ # → { accounts: [{ id, kind, email, label?, authStatus, idleEnabled, active, createdAt }, ...] }
252
+ ```
253
+
254
+ ### Search (local FTS5, cross-account)
255
+ ```bash
256
+ curl -s "http://localhost:8321/api/mail/search?q=...&limit=50&accountId=ACCT"
257
+ # → { results: [{ accountId, providerMsgId, subject, snippet, receivedAtUtc,
258
+ # from: { email } | null, isRead }], count, query }
259
+ ```
260
+
261
+ ### Read
262
+ ```bash
263
+ # List / search via the provider.
264
+ curl -s "http://localhost:8321/api/mail/ACCT/messages?q=is:unread&limit=20"
265
+ # → { messages: [{ providerMsgId, threadId, from, subject, snippet,
266
+ # receivedAtUtc, isRead, flags, hasAttachment }] }
267
+
268
+ curl -s "http://localhost:8321/api/mail/ACCT/messages/MSG_ID"
269
+ # → { message: { ..., body: { text, html }, attachments: [...] } }
270
+
271
+ curl -s "http://localhost:8321/api/mail/ACCT/threads/THREAD_ID"
272
+ # → { thread: { threadId, messages: [...], status: "full"|"partial", missingAncestors? } }
273
+
274
+ curl -s "http://localhost:8321/api/mail/ACCT/folders"
275
+ curl -s "http://localhost:8321/api/mail/ACCT/tags"
276
+ ```
277
+
278
+ ### Send / draft
279
+ ```bash
280
+ # Direct send — Autonomous; rejected with 403 when the user has denied
281
+ # the send tool. Call /api/notify yourself if the user should know.
282
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/messages/send" \
283
+ -H "Content-Type: application/json" \
284
+ -d '{"to": [...], "subject": "...", "textBody": "...", "reply"?: {...}}'
285
+ # → { result: { id, isDraft: false, rfc822MsgId?, warnings? } }
286
+
287
+ # Draft CRUD — Autonomous tier.
288
+ curl -s "http://localhost:8321/api/mail/ACCT/drafts"
289
+ curl -s "http://localhost:8321/api/mail/ACCT/drafts/DRAFT_ID"
290
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/drafts" -d '{...}'
291
+ curl -sX PATCH "http://localhost:8321/api/mail/ACCT/drafts/DRAFT_ID" -d '{...}'
292
+ # PATCH response: { status, id, warnings? }
293
+ # - On Outlook, `warnings: ["reply_threading_immutable_after_create"]` if
294
+ # `reply` was supplied — reply headers are fixed at createDraft time.
295
+ curl -sX DELETE "http://localhost:8321/api/mail/ACCT/drafts/DRAFT_ID"
296
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/drafts/DRAFT_ID/send"
297
+ ```
298
+
299
+ ### Modify / move
300
+ ```bash
301
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/messages/MSG_ID/read" -d '{"read": true}'
302
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/messages/MSG_ID/tags" -d '{"add": ["Starred"], "remove": []}'
303
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/messages/MSG_ID/trash"
304
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/messages/MSG_ID/untrash"
305
+ curl -sX POST "http://localhost:8321/api/mail/ACCT/messages/MSG_ID/archive"
306
+ ```
307
+
308
+ ### Health
309
+ ```bash
310
+ curl -s "http://localhost:8321/api/mail/ACCT/health"
311
+ # → { accountId, lastPollAtUtc, lastError, lastErrorAtUtc,
312
+ # consecutiveErrorCount, idleFallbackUntilUtc }
313
+ ```
@@ -0,0 +1,17 @@
1
+ ---
2
+ kind: reference
3
+ parent_skill: mail
4
+ ---
5
+
6
+ Direct-mode write routes share `{ error: string, message: string, detail?: string }`. Map by the `error` code first, then `detail` for richer disambiguation.
7
+
8
+ | HTTP | `error` | `detail` | What it means / what to do |
9
+ |---|---|---|---|
10
+ | 400 | `provider_not_enabled` | `kind_not_enabled` | The provider is authenticated but the user disabled that provider in settings. Tell the user and stop. |
11
+ | 400 | `provider_not_enabled` | `account_inactive` | This specific account is paused. Tell the user to re-enable it in the dashboard. Stop. |
12
+ | 400 | `provider_not_enabled` | `account_unhealthy` | **Credentials broken** (refresh rejected / app password expired). Tell the user to re-authenticate at `/connections/mail#<accountId>`. Stop. Do NOT treat as "provider disabled." |
13
+ | 404 | `not_found` | — | Account id unknown or message/thread id gone. First retry: re-resolve via `?active=1` (§1). If still 404, surface to user. |
14
+ | 410 | `integration_delegated` | — | Gmail flipped to delegated mode mid-session. This skill body is direct-only — re-read `integrations.md` and use `POST /api/integrations/gmail/exec` (cross-backend task mode) or your session backend's native Gmail MCP (the same-backend variant) instead. |
15
+ | 501 | `not_implemented` | — | Operation unavailable on this provider kind (e.g. IMAP draft writes, Outlook attachment download). Fall back to the provider's native UI and tell the user. |
16
+ | 502 | `provider_auth_error` | — | Upstream rejected the credentials mid-call. Re-consent needed. Do NOT retry; tell the user. |
17
+ | other 5xx | — | — | Transient. Backoff, one retry, then surface the error text. |
@@ -0,0 +1,40 @@
1
+ ---
2
+ kind: reference
3
+ parent_skill: mail
4
+ ---
5
+
6
+ Each provider supports the unified surface but with differing semantics.
7
+ Routes return **HTTP 501 `not_implemented`** when a method isn't available
8
+ on this kind — do NOT retry; tell the user and fall back.
9
+
10
+ | Operation | Gmail | Outlook | Yahoo / iCloud (IMAP) |
11
+ |---|---|---|---|
12
+ | Read, search, list folders | ✅ | ✅ | ✅ (ASCII; non-ASCII degrades — see §4) |
13
+ | Direct send (`POST /messages/send`) | ✅ | ✅ | ✅ |
14
+ | `markRead` / `tags` / `trash` | ✅ | ✅ | ✅ |
15
+ | `archive` / `untrash` | ✅ | ✅ | ✅ |
16
+ | Thread read (`GET /threads/:id`) | ✅ | ✅ | ⚠️ client-walked; `status: "partial"` possible |
17
+ | Draft read (`GET /drafts`, `GET /drafts/:id`) | ✅ | ✅ | ✅ |
18
+ | Draft write (`POST`/`PATCH`/`DELETE /drafts`, `POST /drafts/:id/send`) | ✅ | ✅ | ❌ **501** — direct `/messages/send` only |
19
+ | Attachment download (via `/receipts/:id/file`) | ✅ | ❌ 501 | ❌ 501 |
20
+
21
+ **IMAP drafts** (Yahoo / iCloud): every draft *write* returns 501. To
22
+ queue outbound mail for a non-Gmail IMAP user, send directly via
23
+ `POST /messages/send` (agent composes body) or ask the user to compose in
24
+ their native client. MIME-constructed drafts ship in a later phase.
25
+
26
+ **Attachments beyond Gmail**: receipts / attachment download currently
27
+ work only for Gmail messages. If the user asks you to save an attachment
28
+ off an Outlook or IMAP message, say so and point them to the provider's
29
+ web UI.
30
+
31
+ ### Provider-specific quirks
32
+
33
+ | Concern | Gmail / Outlook | Yahoo / iCloud (IMAP) |
34
+ |---|---|---|
35
+ | Tag semantics | Gmail: label ids. Outlook: category names. Free-form. | System flags only (`\Seen \Flagged \Answered`) + server-advertised `PERMANENTFLAGS` keywords. Unknown tags silently dropped. |
36
+ | Threads | Provider-authoritative | Client-walked from `In-Reply-To` + `References`. `status: "partial"` when local index lacks older ancestors. `404 not_found` if the rfc822 id can't be reached. |
37
+ | `PATCH /drafts/:id` with `reply` | Gmail: threading is editable. Outlook: silently ignores `reply`; response includes `warnings: ["reply_threading_immutable_after_create"]` — create a fresh draft to reshape threading. | N/A (draft writes 501) |
38
+
39
+ Call `GET /api/mail/:acct/tags` before tagging on IMAP — `userDefined` is
40
+ often empty on servers that don't advertise keywords.
@@ -0,0 +1,24 @@
1
+ ---
2
+ kind: reference
3
+ parent_skill: mail
4
+ ---
5
+
6
+ One grammar, translated per-provider:
7
+
8
+ | Token | Meaning |
9
+ |---|---|
10
+ | `from:<email>` | sender match |
11
+ | `to:<email>` | recipient match |
12
+ | `subject:"..."` | substring of subject |
13
+ | `has:attachment` | ≥ 1 attachment |
14
+ | `is:unread` | unread only |
15
+ | `newer_than:<N>d` | received in last N days |
16
+ | `older_than:<N>d` | received before N days |
17
+ | `<free text>` | subject / body / from |
18
+
19
+ **Non-ASCII and IMAP.** Before running a non-ASCII free-text query
20
+ against an IMAP account, check `accounts.md` `kind` column. For `yahoo`
21
+ / `icloud`, the route downgrades to client-side filtering over recent
22
+ UIDs — historic ranges will be **incomplete**. Either (a) keep the
23
+ window short with `newer_than:30d`, (b) use the local FTS5 endpoint
24
+ instead, or (c) tell the user results may miss older matches.