@pome-sh/cli 0.7.0 → 0.8.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 (131) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/src/cli/docs-topics.js +5 -3
  3. package/dist/src/runner/runTask.d.ts +14 -0
  4. package/dist/src/task/taskSchema.d.ts +52 -16
  5. package/node_modules/@pome-sh/shared-types/dist/seed-state.d.ts +27 -0
  6. package/node_modules/@pome-sh/shared-types/dist/seed-state.js +12 -0
  7. package/node_modules/@pome-sh/shared-types/dist/seed-state.js.map +1 -1
  8. package/node_modules/@pome-sh/shared-types/dist/task.d.ts +18 -0
  9. package/node_modules/@pome-sh/shared-types/package.json +1 -1
  10. package/node_modules/@pome-sh/shared-types/trace-contract.json +1 -1
  11. package/node_modules/@pome-sh/twin-gmail/CHANGELOG.md +21 -0
  12. package/node_modules/@pome-sh/twin-gmail/HOSTED.md +37 -15
  13. package/node_modules/@pome-sh/twin-gmail/LIMITS.md +10 -0
  14. package/node_modules/@pome-sh/twin-gmail/README.md +52 -11
  15. package/node_modules/@pome-sh/twin-gmail/dist/fixtures/mcp-tools-list.canonical.json +242 -7
  16. package/node_modules/@pome-sh/twin-gmail/dist/src/db.js +6 -0
  17. package/node_modules/@pome-sh/twin-gmail/dist/src/db.js.map +1 -1
  18. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.d.ts +41 -0
  19. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.js +138 -0
  20. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.js.map +1 -0
  21. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/filters.d.ts +10 -0
  22. package/node_modules/@pome-sh/twin-gmail/dist/src/{domain-search.js → domain/filters.js} +52 -36
  23. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/filters.js.map +1 -0
  24. package/node_modules/@pome-sh/twin-gmail/dist/src/{domain.d.ts → domain/gmail-domain.d.ts} +45 -34
  25. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/gmail-domain.js +174 -0
  26. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/gmail-domain.js.map +1 -0
  27. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.d.ts +8 -0
  28. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.js +122 -0
  29. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.js.map +1 -0
  30. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.d.ts +4 -0
  31. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.js +5 -0
  32. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.js.map +1 -0
  33. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.d.ts +40 -0
  34. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.js +122 -0
  35. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.js.map +1 -0
  36. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.d.ts +49 -0
  37. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.js +276 -0
  38. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.js.map +1 -0
  39. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.d.ts +19 -0
  40. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.js +179 -0
  41. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.js.map +1 -0
  42. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.d.ts +27 -0
  43. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.js +98 -0
  44. package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.js.map +1 -0
  45. package/node_modules/@pome-sh/twin-gmail/dist/src/errors.js +2 -0
  46. package/node_modules/@pome-sh/twin-gmail/dist/src/errors.js.map +1 -1
  47. package/node_modules/@pome-sh/twin-gmail/dist/src/faults.d.ts +21 -0
  48. package/node_modules/@pome-sh/twin-gmail/dist/src/faults.js +52 -0
  49. package/node_modules/@pome-sh/twin-gmail/dist/src/faults.js.map +1 -0
  50. package/node_modules/@pome-sh/twin-gmail/dist/src/identity.d.ts +1 -6
  51. package/node_modules/@pome-sh/twin-gmail/dist/src/identity.js +0 -11
  52. package/node_modules/@pome-sh/twin-gmail/dist/src/identity.js.map +1 -1
  53. package/node_modules/@pome-sh/twin-gmail/dist/src/index.d.ts +4 -3
  54. package/node_modules/@pome-sh/twin-gmail/dist/src/index.js +3 -3
  55. package/node_modules/@pome-sh/twin-gmail/dist/src/index.js.map +1 -1
  56. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.d.ts +48 -0
  57. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.js +23 -0
  58. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.js.map +1 -1
  59. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.d.ts +1 -1
  60. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.js +39 -1
  61. package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.js.map +1 -1
  62. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-drafts.js +4 -5
  63. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-drafts.js.map +1 -1
  64. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.d.ts +2 -3
  65. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.js +4 -4
  66. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.js.map +1 -1
  67. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-messages.js +7 -8
  68. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-messages.js.map +1 -1
  69. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-resources.js +20 -21
  70. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-resources.js.map +1 -1
  71. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes.d.ts +1 -1
  72. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.d.ts +2 -4
  73. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.js +4 -6
  74. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.js.map +1 -1
  75. package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.d.ts +4 -0
  76. package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.js +179 -0
  77. package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.js.map +1 -0
  78. package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.d.ts +61 -0
  79. package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.js +318 -0
  80. package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.js.map +1 -0
  81. package/node_modules/@pome-sh/twin-gmail/dist/src/search.d.ts +3 -61
  82. package/node_modules/@pome-sh/twin-gmail/dist/src/search.js +2 -503
  83. package/node_modules/@pome-sh/twin-gmail/dist/src/search.js.map +1 -1
  84. package/node_modules/@pome-sh/twin-gmail/dist/src/seed.d.ts +13 -4
  85. package/node_modules/@pome-sh/twin-gmail/dist/src/seed.js +3 -1
  86. package/node_modules/@pome-sh/twin-gmail/dist/src/seed.js.map +1 -1
  87. package/node_modules/@pome-sh/twin-gmail/dist/src/server.js +1 -1
  88. package/node_modules/@pome-sh/twin-gmail/dist/src/server.js.map +1 -1
  89. package/node_modules/@pome-sh/twin-gmail/dist/src/storage.js +1 -1
  90. package/node_modules/@pome-sh/twin-gmail/dist/src/storage.js.map +1 -1
  91. package/node_modules/@pome-sh/twin-gmail/dist/src/twin.d.ts +2 -3
  92. package/node_modules/@pome-sh/twin-gmail/dist/src/twin.js +1 -4
  93. package/node_modules/@pome-sh/twin-gmail/dist/src/twin.js.map +1 -1
  94. package/node_modules/@pome-sh/twin-gmail/dist/src/types.d.ts +1 -0
  95. package/node_modules/@pome-sh/twin-gmail/fidelity.inventory.json +42 -435
  96. package/node_modules/@pome-sh/twin-gmail/fixtures/README.md +4 -4
  97. package/node_modules/@pome-sh/twin-gmail/fixtures/mcp-tools-list.canonical.json +242 -7
  98. package/node_modules/@pome-sh/twin-gmail/fixtures/mcp-tools-list.meta.json +3 -3
  99. package/node_modules/@pome-sh/twin-gmail/package.json +3 -2
  100. package/node_modules/hono/dist/cjs/client/utils.js +1 -1
  101. package/node_modules/hono/dist/cjs/helper/streaming/sse.js +5 -4
  102. package/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
  103. package/node_modules/hono/dist/cjs/middleware/compress/index.js +2 -1
  104. package/node_modules/hono/dist/cjs/middleware/method-override/index.js +5 -3
  105. package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +10 -4
  106. package/node_modules/hono/dist/cjs/request.js +8 -3
  107. package/node_modules/hono/dist/cjs/utils/accept.js +1 -1
  108. package/node_modules/hono/dist/cjs/utils/body.js +6 -0
  109. package/node_modules/hono/dist/cjs/utils/url.js +1 -1
  110. package/node_modules/hono/dist/client/utils.js +1 -1
  111. package/node_modules/hono/dist/helper/streaming/sse.js +5 -4
  112. package/node_modules/hono/dist/middleware/cache/index.js +1 -1
  113. package/node_modules/hono/dist/middleware/compress/index.js +2 -1
  114. package/node_modules/hono/dist/middleware/method-override/index.js +5 -3
  115. package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +10 -4
  116. package/node_modules/hono/dist/request.js +8 -3
  117. package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
  118. package/node_modules/hono/dist/types/helper/websocket/index.d.ts +1 -1
  119. package/node_modules/hono/dist/types/middleware/combine/index.d.ts +1 -1
  120. package/node_modules/hono/dist/utils/accept.js +1 -1
  121. package/node_modules/hono/dist/utils/body.js +6 -0
  122. package/node_modules/hono/dist/utils/url.js +1 -1
  123. package/node_modules/hono/package.json +3 -3
  124. package/package.json +3 -3
  125. package/node_modules/@pome-sh/twin-gmail/dist/src/domain-search.d.ts +0 -5
  126. package/node_modules/@pome-sh/twin-gmail/dist/src/domain-search.js.map +0 -1
  127. package/node_modules/@pome-sh/twin-gmail/dist/src/domain.js +0 -407
  128. package/node_modules/@pome-sh/twin-gmail/dist/src/domain.js.map +0 -1
  129. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.d.ts +0 -75
  130. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.js +0 -282
  131. package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.js.map +0 -1
@@ -6,7 +6,7 @@ Deterministic Gmail-shaped twin for agent testing (Pome).
6
6
  SQLite mailbox model, strict seed/reset APIs, canonical MIME storage, identity,
7
7
  delivery, drafts, labels/history/search, bounded semantic state export,
8
8
  recording projection, the frozen Gmail REST/upload surface, and the captured
9
- ten-tool first-party MCP contract.
9
+ thirteen-tool first-party MCP contract (Gate 1).
10
10
 
11
11
  ## Auth identity (frozen)
12
12
 
@@ -29,22 +29,24 @@ revealing mailbox existence.
29
29
  | Path | Role |
30
30
  | --- | --- |
31
31
  | [`fixtures/rest-surface.json`](fixtures/rest-surface.json) | Frozen launch REST method/parameter/media matrix from Gmail v1 discovery |
32
- | [`fixtures/mcp-tools-list.*.json`](fixtures/) | Official Gmail MCP `tools/list` raw + canonical (10-tool launch set) |
32
+ | [`fixtures/mcp-tools-list.*.json`](fixtures/) | Official Gmail MCP `tools/list` raw + canonical (13-tool Gate-1 launch set) |
33
33
  | [`fidelity.inventory.json`](fidelity.inventory.json) | Heat × fidelity × evidence for every launch REST/MCP row |
34
+ | [`FIDELITY.md`](FIDELITY.md) | Human-readable heat × fidelity tables (linted against inventory) |
34
35
  | [`REFERENCE-DIVERGENCES.md`](REFERENCE-DIVERGENCES.md) | Emulate rejected; never an oracle |
35
36
  | [`LIMITS.md`](LIMITS.md) | Limit placeholders (discovery maxima + TBD local caps) |
36
37
 
37
38
  See [`fixtures/README.md`](fixtures/README.md) for capture provenance and SHA-256.
38
39
 
39
- ## Launch MCP tools (exactly 10)
40
+ ## Launch MCP tools (exactly 13)
40
41
 
41
- `create_draft`, `list_drafts`, `get_thread`, `search_threads`, `label_thread`,
42
- `unlabel_thread`, `list_labels`, `label_message`, `unlabel_message`,
42
+ `create_draft`, `list_drafts`, `get_thread`, `get_message`, `search_threads`,
43
+ `label_thread`, `unlabel_thread`, `apply_sensitive_thread_label`, `list_labels`,
44
+ `label_message`, `unlabel_message`, `apply_sensitive_message_label`,
43
45
  `create_label`.
44
46
 
45
- Order and schemas are frozen from the live listing capture (relative order among
46
- the launch set). Three extra preview tools seen live are **out of launch scope**
47
- (named cold in the inventory).
47
+ Order and schemas are frozen from the live Developer Preview listing capture.
48
+ Gate 1 promotes `get_message` and the two `apply_sensitive_*` tools that were
49
+ previously named cold preview drift under the Gate 0 ten-tool freeze.
48
50
 
49
51
  ## Named 501 gaps (not fake success)
50
52
 
@@ -61,7 +63,7 @@ the launch set). Three extra preview tools seen live are **out of launch scope**
61
63
  - Calendar, Drive, Contacts, client UI, CSE, delegates, S/MIME, admin controls
62
64
  - HTTP batch API
63
65
  - Resumable upload
64
- - Expanding MCP beyond the frozen 10-tool launch set without a new Gate 0 ruling
66
+ - Expanding MCP beyond the frozen Gate-1 13-tool launch set without a new ruling
65
67
 
66
68
  ## Limits
67
69
 
@@ -84,6 +86,45 @@ Gmail follows the same SDK chassis as GitHub / Slack / Stripe:
84
86
 
85
87
  Intentional differences: no Google OAuth (Pome JWT only); watch/stop 501; Stripe-style idempotency/failure-injection middleware is Stripe-only.
86
88
 
89
+ ## Runtime contract (for snapshot consumers)
90
+
91
+ `pome-cloud` builds a Vercel Sandbox snapshot from this package's signed source
92
+ artifact. The following constraints must hold for that build to succeed and for
93
+ the resulting snapshot to boot. Changing any of these is a breaking change for
94
+ hosted; land the producer change here first, then open the cloud consumer PR
95
+ that pins and verifies the new signed digest.
96
+
97
+ ### Build
98
+
99
+ - Package is `npm install`-able from `package.json` alone (no `workspace:*`
100
+ protocols, no package-manager-specific deps; no committed lockfile is required, the snapshot
101
+ build regenerates one on each rebuild)
102
+ - `npm run build` exits 0 and emits `dist/src/server.js`
103
+ - Built output is loadable under Node 24 — the snapshot runs `runtime: "node24"`.
104
+ SQLite is the built-in `node:sqlite` (via the sdk's `openTwinDatabase()`) —
105
+ no native modules, no compiler toolchain.
106
+
107
+ ### Runtime
108
+
109
+ - Server entry: `node dist/src/server.js` (cwd = package root)
110
+ - Listens on `:3336` by default (`GMAIL_TWIN_PORT`, then the native default)
111
+ - **Hosted normalizes the port to `PORT=3333`.** The server honors the `PORT`
112
+ env var first (`PORT` → `GMAIL_TWIN_PORT` → `3336`); the pome-cloud
113
+ control-plane sets `PORT=3333` at spawn for every twin, so the native `3336`
114
+ default is only used for standalone local runs.
115
+ - Honors `GMAIL_TWIN_HOST=0.0.0.0` env (default `127.0.0.1` is unreachable via
116
+ Vercel Sandbox port forwarding)
117
+ - `GET /healthz` returns 200 within ~3s of process start (the snapshot build
118
+ sleeps 3s after `node dist/src/server.js` before probing)
119
+ - Seed via `POME_SEED_JSON` (strict Gmail seed schema)
120
+ - Bearer auth at `Authorization: Bearer <jwt>` — Pome session JWT, not a Google
121
+ OAuth access token
122
+
123
+ ### Cloud consumer coordination
124
+
125
+ - Bumping any of the above = publish a signed twin digest and open the matching
126
+ `pome-cloud` consumer PR.
127
+
87
128
  ## Development
88
129
 
89
130
  ```bash
@@ -104,6 +145,6 @@ npx @pome-sh/cli twin start gmail
104
145
  # and the identical POME_GMAIL_TOKEN alias
105
146
  ```
106
147
 
107
- Use `pome scenarios gmail --copy` for the inbox-triage and captured first-party
108
- MCP parity scenarios. Hosted rollout is gated separately; see
148
+ Use `pome tasks gmail --copy` for the inbox-triage and captured first-party
149
+ MCP parity tasks. Hosted rollout is gated separately; see
109
150
  [`HOSTED.md`](HOSTED.md).
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "meta": {
3
- "source": "live_unauthenticated_tools_list_filtered_to_launch_set",
3
+ "source": "live_unauthenticated_tools_list_gate1_launch_set",
4
4
  "endpoint": "https://gmailmcp.googleapis.com/mcp/v1",
5
5
  "method": "tools/list",
6
6
  "protocol": "JSON-RPC 2.0 over HTTP (accept: application/json, text/event-stream)",
7
7
  "protocolVersion": "2025-03-26",
8
8
  "captureDate": "2026-07-20",
9
9
  "rawFileSha256": "6ef35bad568967015c101f89e995148c4eb2131b3a6dd244f7237058abae8e7a",
10
- "launchToolCount": 10,
10
+ "launchToolCount": 13,
11
11
  "liveToolCount": 13,
12
12
  "liveToolOrder": [
13
13
  "create_draft",
@@ -28,28 +28,43 @@
28
28
  "create_draft",
29
29
  "list_drafts",
30
30
  "get_thread",
31
+ "get_message",
31
32
  "search_threads",
32
33
  "label_thread",
33
34
  "unlabel_thread",
35
+ "apply_sensitive_thread_label",
34
36
  "list_labels",
35
37
  "label_message",
36
38
  "unlabel_message",
39
+ "apply_sensitive_message_label",
37
40
  "create_label"
38
41
  ],
39
- "excludedFromLaunch": [
42
+ "gate0LaunchToolOrder": [
43
+ "create_draft",
44
+ "list_drafts",
45
+ "get_thread",
46
+ "search_threads",
47
+ "label_thread",
48
+ "unlabel_thread",
49
+ "list_labels",
50
+ "label_message",
51
+ "unlabel_message",
52
+ "create_label"
53
+ ],
54
+ "gate1PromotedFromPreview": [
40
55
  "get_message",
41
56
  "apply_sensitive_thread_label",
42
57
  "apply_sensitive_message_label"
43
58
  ],
44
59
  "notes": [
45
60
  "Raw live tools/list returned 13 tools without auth (Developer Preview).",
46
- "Gate 0 launch set is exactly the 10 tools named in the Gmail twin plan / public tool reference.",
47
- "Schemas/annotations/descriptions for launch tools are copied verbatim from the live capture.",
48
- "Excluded live tools (get_message, apply_sensitive_thread_label, apply_sensitive_message_label) are preview drift vs the documented 10-tool launch set — not served by the twin while claiming official listing parity.",
61
+ "Gate 1 expands the OSS launch set from the Gate 0 ten-tool freeze to the full live 13-tool listing.",
62
+ "Schemas/annotations/descriptions for all launch tools are copied verbatim from the live capture.",
63
+ "Promoted Gate-1 tools: get_message, apply_sensitive_thread_label, apply_sensitive_message_label.",
49
64
  "Authenticated tools/call success envelopes were unavailable; see mcp-tools-call.representative.json and mcp-tools-call-unauth-error.raw.json.",
50
65
  "initialize returned protocolVersion=2025-03-26 (see mcp-initialize.raw.json)."
51
66
  ],
52
- "canonicalSha256": "8771e967b1c8d5c364de2a05c890aaddd27fb9eba45fde68e18d767b1dfc7ac3"
67
+ "canonicalSha256": "56b5e86181c13ead63fdc8ea0d4bedc6860c1a3fdb17372fdca76591e48a4eed"
53
68
  },
54
69
  "jsonrpc": "2.0",
55
70
  "id": 1,
@@ -463,6 +478,138 @@
463
478
  "type": "object"
464
479
  }
465
480
  },
481
+ {
482
+ "annotations": {
483
+ "destructiveHint": false,
484
+ "idempotentHint": true,
485
+ "openWorldHint": false,
486
+ "readOnlyHint": true,
487
+ "title": "Retrieves a specific email message from the authenticated user's Gmail account."
488
+ },
489
+ "description": "Retrieves a specific email message from the authenticated user's Gmail account by its unique message ID.\n\nUse this tool to inspect a single, individual email when you already know its message ID. If the user wants to read a specific email in detail, check the exact wording of a message, or examine attachment metadata for a single email, this is the right tool. It is not suitable for retrieving entire conversations or viewing back-and-forth discussion threads; use the 'get_thread' tool instead.\nKey indicators include if the user asks for the full content of a specific message ID returned by a previous search, or if the query asks to inspect a specific individual email rather than an entire thread.\nExample user prompts are: \"Get the full text of message ID 18f123456789abcd.\", \"Read the latest message in that thread from Alice.\", and \"What are the attachment names in the email I just received from HR?\" \n\nThe optional `messageFormat` parameter controls the format of the message returned. By default (or with `FULL_CONTENT`), it returns the full content of the message. Use `MINIMAL` to include only subject and snippet (excluding body). Use `METADATA_ONLY` to include only basic metadata (message ID, thread ID, labels, timestamp, and size estimate). \n",
490
+ "inputSchema": {
491
+ "description": "Request message for GetMessage RPC.",
492
+ "properties": {
493
+ "messageFormat": {
494
+ "description": "Optional. Specifies the format of the message returned. Defaults to FULL_CONTENT.",
495
+ "enum": [
496
+ "MESSAGE_FORMAT_UNSPECIFIED",
497
+ "MINIMAL",
498
+ "FULL_CONTENT",
499
+ "METADATA_ONLY"
500
+ ],
501
+ "type": "string",
502
+ "x-google-enum-descriptions": [
503
+ "Defaults to FULL_CONTENT.",
504
+ "Returns message snippets and key headers (Subject, From, To, Cc, Date).",
505
+ "Returns all information in \"MINIMAL\" plus the full body content of each message.",
506
+ "Metadata only: does not include subject, snippet, body, attachment filenames."
507
+ ]
508
+ },
509
+ "messageId": {
510
+ "description": "Required. The unique identifier of the message to fetch.",
511
+ "type": "string"
512
+ }
513
+ },
514
+ "required": [
515
+ "messageId"
516
+ ],
517
+ "type": "object"
518
+ },
519
+ "name": "get_message",
520
+ "outputSchema": {
521
+ "$defs": {
522
+ "AttachmentMetadata": {
523
+ "description": "Represents an attachment associated with a message.",
524
+ "properties": {
525
+ "filename": {
526
+ "description": "The filename of the attachment.",
527
+ "type": "string"
528
+ },
529
+ "id": {
530
+ "description": "Output only. The ID of the attachment.",
531
+ "readOnly": true,
532
+ "type": "string"
533
+ },
534
+ "mimeType": {
535
+ "description": "The MIME type of the attachment.",
536
+ "type": "string"
537
+ }
538
+ },
539
+ "type": "object"
540
+ }
541
+ },
542
+ "description": "Message within a thread.",
543
+ "properties": {
544
+ "attachmentIds": {
545
+ "description": "Output only. The attachment ids, only populated if MessageFormat was FULL_CONTENT.",
546
+ "items": {
547
+ "type": "string"
548
+ },
549
+ "readOnly": true,
550
+ "type": "array"
551
+ },
552
+ "attachments": {
553
+ "description": "Output only. The attachments, only populated if MessageFormat was FULL_CONTENT.",
554
+ "items": {
555
+ "$ref": "#/$defs/AttachmentMetadata"
556
+ },
557
+ "readOnly": true,
558
+ "type": "array"
559
+ },
560
+ "ccRecipients": {
561
+ "description": "CC recipient email addresses.",
562
+ "items": {
563
+ "type": "string"
564
+ },
565
+ "type": "array"
566
+ },
567
+ "date": {
568
+ "description": "Date of the message in ISO 8601 format (YYYY-MM-DD).",
569
+ "type": "string"
570
+ },
571
+ "htmlBody": {
572
+ "description": "The HTML content of the email, only populated if MessageFormat was FULL_CONTENT.",
573
+ "type": "string"
574
+ },
575
+ "id": {
576
+ "description": "The unique identifier of the message.",
577
+ "type": "string"
578
+ },
579
+ "labelIds": {
580
+ "description": "The ids of the labels attached to the message. Includes ids of user labels and standard system labels limited to \"INBOX\", \"SPAM\", \"TRASH\", \"UNREAD\", \"STARRED\", \"IMPORTANT\", \"SENT\", \"DRAFT\", \"CHAT\".",
581
+ "items": {
582
+ "type": "string"
583
+ },
584
+ "type": "array"
585
+ },
586
+ "plaintextBody": {
587
+ "description": "Full body content, only populated if MessageFormat was FULL_CONTENT.",
588
+ "type": "string"
589
+ },
590
+ "sender": {
591
+ "description": "Sender email address.",
592
+ "type": "string"
593
+ },
594
+ "snippet": {
595
+ "description": "Snippet of the message body.",
596
+ "type": "string"
597
+ },
598
+ "subject": {
599
+ "description": "The message subject extracted from headers:",
600
+ "type": "string"
601
+ },
602
+ "toRecipients": {
603
+ "description": "To recipient email addresses.",
604
+ "items": {
605
+ "type": "string"
606
+ },
607
+ "type": "array"
608
+ }
609
+ },
610
+ "type": "object"
611
+ }
612
+ },
466
613
  {
467
614
  "annotations": {
468
615
  "destructiveHint": false,
@@ -716,6 +863,50 @@
716
863
  "type": "object"
717
864
  }
718
865
  },
866
+ {
867
+ "annotations": {
868
+ "destructiveHint": true,
869
+ "idempotentHint": true,
870
+ "openWorldHint": false,
871
+ "readOnlyHint": false,
872
+ "title": "Adds a sensitive label (Trash or Spam) to a thread."
873
+ },
874
+ "description": "Adds a sensitive label (Trash or Spam) to an entire thread in the authenticated user's Gmail account. This operation affects all messages currently in the thread and any future messages added to it.\n\nUse this tool to trash or mark a thread as spam. If unsure of the thread ID, use the `search_threads` tool first.\n",
875
+ "inputSchema": {
876
+ "description": "Request message for ApplySensitiveThreadLabel RPC.",
877
+ "properties": {
878
+ "labelOption": {
879
+ "description": "Required. The sensitive label option to add.",
880
+ "enum": [
881
+ "LABEL_OPTION_UNSPECIFIED",
882
+ "TRASH",
883
+ "SPAM"
884
+ ],
885
+ "type": "string",
886
+ "x-google-enum-descriptions": [
887
+ "Unspecified label option.",
888
+ "Trash label.",
889
+ "Spam label."
890
+ ]
891
+ },
892
+ "threadId": {
893
+ "description": "Required. The ID of the thread to add the label to.",
894
+ "type": "string"
895
+ }
896
+ },
897
+ "required": [
898
+ "threadId",
899
+ "labelOption"
900
+ ],
901
+ "type": "object"
902
+ },
903
+ "name": "apply_sensitive_thread_label",
904
+ "outputSchema": {
905
+ "description": "Response message for ApplySensitiveThreadLabel RPC.",
906
+ "properties": {},
907
+ "type": "object"
908
+ }
909
+ },
719
910
  {
720
911
  "annotations": {
721
912
  "destructiveHint": false,
@@ -877,6 +1068,50 @@
877
1068
  "type": "object"
878
1069
  }
879
1070
  },
1071
+ {
1072
+ "annotations": {
1073
+ "destructiveHint": true,
1074
+ "idempotentHint": true,
1075
+ "openWorldHint": false,
1076
+ "readOnlyHint": false,
1077
+ "title": "Adds a sensitive label (Trash or Spam) to a message."
1078
+ },
1079
+ "description": "Adds a sensitive label (Trash or Spam) to a specific message in the authenticated user's Gmail account.\n\nUse this tool to trash or mark a message as spam. To find the message ID, use tools like `search_threads` or `get_thread`.\n",
1080
+ "inputSchema": {
1081
+ "description": "Request message for ApplySensitiveMessageLabel RPC.",
1082
+ "properties": {
1083
+ "labelOption": {
1084
+ "description": "Required. The sensitive label option to add.",
1085
+ "enum": [
1086
+ "LABEL_OPTION_UNSPECIFIED",
1087
+ "TRASH",
1088
+ "SPAM"
1089
+ ],
1090
+ "type": "string",
1091
+ "x-google-enum-descriptions": [
1092
+ "Unspecified label option.",
1093
+ "Trash label.",
1094
+ "Spam label."
1095
+ ]
1096
+ },
1097
+ "messageId": {
1098
+ "description": "Required. The ID of the message to add the label to.",
1099
+ "type": "string"
1100
+ }
1101
+ },
1102
+ "required": [
1103
+ "messageId",
1104
+ "labelOption"
1105
+ ],
1106
+ "type": "object"
1107
+ },
1108
+ "name": "apply_sensitive_message_label",
1109
+ "outputSchema": {
1110
+ "description": "Response message for ApplySensitiveMessageLabel RPC.",
1111
+ "properties": {},
1112
+ "type": "object"
1113
+ }
1114
+ },
880
1115
  {
881
1116
  "annotations": {
882
1117
  "destructiveHint": false,
@@ -6,6 +6,11 @@ CREATE TABLE IF NOT EXISTS gmail_config (
6
6
  value TEXT NOT NULL
7
7
  );
8
8
 
9
+ CREATE TABLE IF NOT EXISTS fault_counters (
10
+ operation TEXT PRIMARY KEY,
11
+ calls INTEGER NOT NULL DEFAULT 0
12
+ );
13
+
9
14
  CREATE TABLE IF NOT EXISTS mailboxes (
10
15
  id INTEGER PRIMARY KEY AUTOINCREMENT,
11
16
  email TEXT NOT NULL COLLATE NOCASE UNIQUE,
@@ -180,6 +185,7 @@ CREATE INDEX IF NOT EXISTS idx_filters_mailbox
180
185
  `;
181
186
  const RESET_SQL = `
182
187
  DELETE FROM gmail_config;
188
+ DELETE FROM fault_counters;
183
189
  DELETE FROM send_as;
184
190
  DELETE FROM forwarding_addresses;
185
191
  DELETE FROM filters;
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiLrB,CAAC;AAEF,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;CAejB,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;IAClF,OAAO,gBAAgB,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAqB;IAC3C,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAqB;IACjD,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsLrB,CAAC;AAEF,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;CAgBjB,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;IAClF,OAAO,gBAAgB,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAqB;IAC3C,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAqB;IACjD,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { SeedAttachment, SemanticMessage } from "../types.js";
2
+ import type { GmailDomain } from "./gmail-domain.js";
3
+ import { sendMessage } from "./messages.js";
4
+ export type DraftResource = {
5
+ id: string;
6
+ message: SemanticMessage;
7
+ updatedAt: string;
8
+ };
9
+ export declare function createDraft(domain: GmailDomain, email: string, raw: Uint8Array | string, options?: {
10
+ threadId?: string;
11
+ }): {
12
+ id: string;
13
+ message: SemanticMessage;
14
+ };
15
+ export declare function createComposedDraft(domain: GmailDomain, email: string, input: {
16
+ to?: string[];
17
+ cc?: string[];
18
+ bcc?: string[];
19
+ subject?: string;
20
+ text?: string;
21
+ html?: string;
22
+ replyToMessageId?: string;
23
+ attachments?: SeedAttachment[];
24
+ }): {
25
+ id: string;
26
+ message: SemanticMessage;
27
+ };
28
+ export declare function listDrafts(domain: GmailDomain, email: string, query?: string): Array<{
29
+ id: string;
30
+ message: SemanticMessage;
31
+ }>;
32
+ export declare function drafts(domain: GmailDomain, email: string, query?: string, includeTrash?: boolean): DraftResource[];
33
+ export declare function draft(domain: GmailDomain, email: string, draftId: string): DraftResource;
34
+ export declare function updateDraft(domain: GmailDomain, email: string, draftId: string, raw: Uint8Array | string, options?: {
35
+ threadId?: string;
36
+ }): {
37
+ id: string;
38
+ message: SemanticMessage;
39
+ };
40
+ export declare function sendDraft(domain: GmailDomain, email: string, draftId: string): ReturnType<typeof sendMessage>;
41
+ export declare function deleteDraft(domain: GmailDomain, email: string, draftId: string): void;
@@ -0,0 +1,138 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { notFound } from "../errors.js";
3
+ import { composeMime } from "../mime.js";
4
+ import { addHistory, insertStoredMessage, nextId, nextTimestamp, rawMessage, semanticMessage } from "../storage.js";
5
+ import { acceptedRaw, removeEmptyThread, searchMessages, sendMessage } from "./messages.js";
6
+ export function createDraft(domain, email, raw, options = {}) {
7
+ const mailboxId = domain.mailboxId(email);
8
+ const bytes = acceptedRaw(raw);
9
+ return domain.db.transaction(() => {
10
+ const message = insertStoredMessage(domain.db, mailboxId, bytes, {
11
+ threadId: options.threadId,
12
+ draft: true,
13
+ });
14
+ const draftId = nextId(domain.db, mailboxId, "draft_counter", "draft");
15
+ const now = nextTimestamp(domain.db, mailboxId);
16
+ domain.db
17
+ .prepare("INSERT INTO drafts(mailbox_id, id, message_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?)")
18
+ .run(mailboxId, draftId, message.id, now, now);
19
+ addHistory(domain.db, mailboxId, message.id, message.threadId, "draftCreated", ["DRAFT"]);
20
+ return { id: draftId, message };
21
+ }).immediate();
22
+ }
23
+ export function createComposedDraft(domain, email, input) {
24
+ const mailboxId = domain.mailboxId(email);
25
+ return domain.db.transaction(() => {
26
+ const reply = input.replyToMessageId
27
+ ? semanticMessage(domain.db, mailboxId, input.replyToMessageId)
28
+ : undefined;
29
+ const raw = composeMime({
30
+ from: email,
31
+ to: input.to,
32
+ cc: input.cc,
33
+ bcc: input.bcc,
34
+ subject: input.subject ?? (reply ? `Re: ${reply.subject}` : ""),
35
+ text: reply ? [input.text ?? "", reply.text].filter(Boolean).join("\r\n\r\n") : input.text,
36
+ html: reply ? [input.html ?? "", reply.html].filter(Boolean).join("<br><br>") : input.html,
37
+ date: nextTimestamp(domain.db, mailboxId),
38
+ messageId: `${nextId(domain.db, mailboxId, "message_counter", "rfc")}@pome-twin.test`,
39
+ inReplyTo: reply?.rfcMessageId,
40
+ references: reply ? [reply.rfcMessageId] : undefined,
41
+ attachments: input.attachments,
42
+ });
43
+ return createDraft(domain, email, raw, { threadId: reply?.threadId });
44
+ }).immediate();
45
+ }
46
+ export function listDrafts(domain, email, query = "") {
47
+ const mailboxId = domain.mailboxId(email);
48
+ const rows = domain.db
49
+ .prepare(`SELECT d.id, d.message_id
50
+ FROM drafts d JOIN messages m ON m.mailbox_id = d.mailbox_id AND m.id = d.message_id
51
+ WHERE d.mailbox_id = ? ORDER BY d.updated_at DESC, d.id DESC`)
52
+ .all(mailboxId);
53
+ const matchingIds = query
54
+ ? new Set(searchMessages(domain, email, `in:draft ${query}`, { includeTrash: true }).map((message) => message.id))
55
+ : undefined;
56
+ return rows
57
+ .filter((row) => matchingIds?.has(row.message_id) ?? true)
58
+ .map((row) => ({ id: row.id, message: semanticMessage(domain.db, mailboxId, row.message_id) }));
59
+ }
60
+ export function drafts(domain, email, query = "", includeTrash = false) {
61
+ const mailboxId = domain.mailboxId(email);
62
+ const matching = query
63
+ ? new Set(searchMessages(domain, email, query, { includeTrash }).map((message) => message.id))
64
+ : null;
65
+ const rows = domain.db
66
+ .prepare("SELECT id, message_id, updated_at FROM drafts WHERE mailbox_id = ? ORDER BY updated_at DESC, id DESC")
67
+ .all(mailboxId);
68
+ return rows
69
+ .filter((row) => !matching || matching.has(row.message_id))
70
+ .map((row) => ({
71
+ id: row.id,
72
+ message: semanticMessage(domain.db, mailboxId, row.message_id),
73
+ updatedAt: row.updated_at,
74
+ }));
75
+ }
76
+ export function draft(domain, email, draftId) {
77
+ const mailboxId = domain.mailboxId(email);
78
+ const row = domain.db
79
+ .prepare("SELECT id, message_id, updated_at FROM drafts WHERE mailbox_id = ? AND id = ?")
80
+ .get(mailboxId, draftId);
81
+ if (!row)
82
+ notFound("Draft");
83
+ return { id: row.id, message: semanticMessage(domain.db, mailboxId, row.message_id), updatedAt: row.updated_at };
84
+ }
85
+ export function updateDraft(domain, email, draftId, raw, options = {}) {
86
+ const mailboxId = domain.mailboxId(email);
87
+ const bytes = acceptedRaw(raw);
88
+ return domain.db.transaction(() => {
89
+ const draftRow = requireDraft(domain, mailboxId, draftId);
90
+ const old = semanticMessage(domain.db, mailboxId, draftRow.message_id);
91
+ const replacement = insertStoredMessage(domain.db, mailboxId, bytes, {
92
+ threadId: options.threadId,
93
+ draft: true,
94
+ });
95
+ const now = nextTimestamp(domain.db, mailboxId);
96
+ domain.db
97
+ .prepare("UPDATE drafts SET message_id = ?, updated_at = ? WHERE mailbox_id = ? AND id = ?")
98
+ .run(replacement.id, now, mailboxId, draftId);
99
+ domain.db.prepare("DELETE FROM messages WHERE mailbox_id = ? AND id = ?").run(mailboxId, draftRow.message_id);
100
+ removeEmptyThread(domain, mailboxId, old.threadId);
101
+ addHistory(domain.db, mailboxId, draftRow.message_id, old.threadId, "draftReplaced");
102
+ return { id: draftId, message: replacement };
103
+ }).immediate();
104
+ }
105
+ export function sendDraft(domain, email, draftId) {
106
+ const mailboxId = domain.mailboxId(email);
107
+ return domain.db.transaction(() => {
108
+ const draftRow = requireDraft(domain, mailboxId, draftId);
109
+ const raw = rawMessage(domain.db, mailboxId, draftRow.message_id);
110
+ const old = semanticMessage(domain.db, mailboxId, draftRow.message_id);
111
+ domain.db.prepare("DELETE FROM drafts WHERE mailbox_id = ? AND id = ?").run(mailboxId, draftId);
112
+ domain.db.prepare("DELETE FROM messages WHERE mailbox_id = ? AND id = ?").run(mailboxId, draftRow.message_id);
113
+ // Keep the draft's thread row even when it becomes empty — send reuses
114
+ // old.threadId (Gmail draft send identity). removeEmptyThread here would
115
+ // drop solo-draft threads and force a new thread id on send.
116
+ addHistory(domain.db, mailboxId, draftRow.message_id, old.threadId, "draftSent");
117
+ return sendMessage(domain, email, raw, { threadId: old.threadId });
118
+ }).immediate();
119
+ }
120
+ export function deleteDraft(domain, email, draftId) {
121
+ const mailboxId = domain.mailboxId(email);
122
+ domain.db.transaction(() => {
123
+ const draftRow = requireDraft(domain, mailboxId, draftId);
124
+ const message = semanticMessage(domain.db, mailboxId, draftRow.message_id);
125
+ domain.db.prepare("DELETE FROM messages WHERE mailbox_id = ? AND id = ?").run(mailboxId, draftRow.message_id);
126
+ removeEmptyThread(domain, mailboxId, message.threadId);
127
+ addHistory(domain.db, mailboxId, draftRow.message_id, message.threadId, "draftDeleted");
128
+ }).immediate();
129
+ }
130
+ function requireDraft(domain, mailboxId, draftId) {
131
+ const row = domain.db
132
+ .prepare("SELECT * FROM drafts WHERE mailbox_id = ? AND id = ?")
133
+ .get(mailboxId, draftId);
134
+ if (!row)
135
+ notFound("Draft");
136
+ return row;
137
+ }
138
+ //# sourceMappingURL=drafts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drafts.js","sourceRoot":"","sources":["../../../src/domain/drafts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { GmailTwinDatabase, SeedFilter } from "../types.js";
2
+ import type { GmailDomain } from "./gmail-domain.js";
3
+ export type FilterResource = Required<Pick<SeedFilter, "criteria" | "action">> & {
4
+ id: string;
5
+ };
6
+ export declare function applyInboundFilters(db: GmailTwinDatabase, mailboxId: number, messageId: string): void;
7
+ export declare function filters(domain: GmailDomain, email: string): FilterResource[];
8
+ export declare function filter(domain: GmailDomain, email: string, filterId: string): FilterResource;
9
+ export declare function createFilter(domain: GmailDomain, email: string, criteria?: SeedFilter["criteria"], action?: SeedFilter["action"]): FilterResource;
10
+ export declare function deleteFilter(domain: GmailDomain, email: string, filterId: string): void;