@open-everywhere/provider-notion 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 (186) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +48 -0
  4. package/agent/channels/notion-acting-identity.ts +88 -0
  5. package/agent/channels/notion-ancestry-trust.ts +458 -0
  6. package/agent/channels/notion-api.ts +1290 -0
  7. package/agent/channels/notion-bot-user.ts +250 -0
  8. package/agent/channels/notion-catch-up.ts +339 -0
  9. package/agent/channels/notion-credentials.ts +417 -0
  10. package/agent/channels/notion-engagement.ts +372 -0
  11. package/agent/channels/notion-event-normalizer.ts +587 -0
  12. package/agent/channels/notion-identity.ts +271 -0
  13. package/agent/channels/notion-ingress-drain.ts +289 -0
  14. package/agent/channels/notion-ingress.ts +182 -0
  15. package/agent/channels/notion-message-ops.ts +140 -0
  16. package/agent/channels/notion-origin-codec.ts +38 -0
  17. package/agent/channels/notion-post-arm.ts +189 -0
  18. package/agent/channels/notion-question-return.ts +223 -0
  19. package/agent/channels/notion-read.ts +283 -0
  20. package/agent/channels/notion-scope.ts +560 -0
  21. package/agent/channels/notion-stop.ts +169 -0
  22. package/agent/channels/notion-supervisor.ts +856 -0
  23. package/agent/channels/notion-webhook-timing.ts +131 -0
  24. package/agent/channels/notion-webhook-verifier.ts +55 -0
  25. package/agent/channels/notion-webhook.ts +963 -0
  26. package/agent/channels/notion-work-search.ts +74 -0
  27. package/agent/channels/notion-work.ts +144 -0
  28. package/agent/channels/notion.ts +1242 -0
  29. package/agent/contributions.ts +39 -0
  30. package/agent/docs-generated.ts +15 -0
  31. package/agent/memory/blocks.ts +295 -0
  32. package/agent/memory/memory.ts +622 -0
  33. package/agent/provider-events.ts +198 -0
  34. package/agent/register.ts +144 -0
  35. package/agent/schedules/notion-ingress.ts +20 -0
  36. package/agent/surface-parity.ts +105 -0
  37. package/agent/tools/notion_search.ts +110 -0
  38. package/agent/tools/read_notion_comments.ts +250 -0
  39. package/agent/tools/read_notion_page.ts +351 -0
  40. package/dist/agent/channels/notion-acting-identity.d.ts +23 -0
  41. package/dist/agent/channels/notion-acting-identity.d.ts.map +1 -0
  42. package/dist/agent/channels/notion-acting-identity.js +85 -0
  43. package/dist/agent/channels/notion-acting-identity.js.map +1 -0
  44. package/dist/agent/channels/notion-ancestry-trust.d.ts +208 -0
  45. package/dist/agent/channels/notion-ancestry-trust.d.ts.map +1 -0
  46. package/dist/agent/channels/notion-ancestry-trust.js +331 -0
  47. package/dist/agent/channels/notion-ancestry-trust.js.map +1 -0
  48. package/dist/agent/channels/notion-api.d.ts +655 -0
  49. package/dist/agent/channels/notion-api.d.ts.map +1 -0
  50. package/dist/agent/channels/notion-api.js +938 -0
  51. package/dist/agent/channels/notion-api.js.map +1 -0
  52. package/dist/agent/channels/notion-bot-user.d.ts +107 -0
  53. package/dist/agent/channels/notion-bot-user.d.ts.map +1 -0
  54. package/dist/agent/channels/notion-bot-user.js +192 -0
  55. package/dist/agent/channels/notion-bot-user.js.map +1 -0
  56. package/dist/agent/channels/notion-catch-up.d.ts +64 -0
  57. package/dist/agent/channels/notion-catch-up.d.ts.map +1 -0
  58. package/dist/agent/channels/notion-catch-up.js +289 -0
  59. package/dist/agent/channels/notion-catch-up.js.map +1 -0
  60. package/dist/agent/channels/notion-credentials.d.ts +210 -0
  61. package/dist/agent/channels/notion-credentials.d.ts.map +1 -0
  62. package/dist/agent/channels/notion-credentials.js +360 -0
  63. package/dist/agent/channels/notion-credentials.js.map +1 -0
  64. package/dist/agent/channels/notion-engagement.d.ts +219 -0
  65. package/dist/agent/channels/notion-engagement.d.ts.map +1 -0
  66. package/dist/agent/channels/notion-engagement.js +283 -0
  67. package/dist/agent/channels/notion-engagement.js.map +1 -0
  68. package/dist/agent/channels/notion-event-normalizer.d.ts +194 -0
  69. package/dist/agent/channels/notion-event-normalizer.d.ts.map +1 -0
  70. package/dist/agent/channels/notion-event-normalizer.js +542 -0
  71. package/dist/agent/channels/notion-event-normalizer.js.map +1 -0
  72. package/dist/agent/channels/notion-identity.d.ts +119 -0
  73. package/dist/agent/channels/notion-identity.d.ts.map +1 -0
  74. package/dist/agent/channels/notion-identity.js +205 -0
  75. package/dist/agent/channels/notion-identity.js.map +1 -0
  76. package/dist/agent/channels/notion-ingress-drain.d.ts +66 -0
  77. package/dist/agent/channels/notion-ingress-drain.d.ts.map +1 -0
  78. package/dist/agent/channels/notion-ingress-drain.js +185 -0
  79. package/dist/agent/channels/notion-ingress-drain.js.map +1 -0
  80. package/dist/agent/channels/notion-ingress.d.ts +64 -0
  81. package/dist/agent/channels/notion-ingress.d.ts.map +1 -0
  82. package/dist/agent/channels/notion-ingress.js +130 -0
  83. package/dist/agent/channels/notion-ingress.js.map +1 -0
  84. package/dist/agent/channels/notion-message-ops.d.ts +3 -0
  85. package/dist/agent/channels/notion-message-ops.d.ts.map +1 -0
  86. package/dist/agent/channels/notion-message-ops.js +126 -0
  87. package/dist/agent/channels/notion-message-ops.js.map +1 -0
  88. package/dist/agent/channels/notion-origin-codec.d.ts +7 -0
  89. package/dist/agent/channels/notion-origin-codec.d.ts.map +1 -0
  90. package/dist/agent/channels/notion-origin-codec.js +32 -0
  91. package/dist/agent/channels/notion-origin-codec.js.map +1 -0
  92. package/dist/agent/channels/notion-post-arm.d.ts +3 -0
  93. package/dist/agent/channels/notion-post-arm.d.ts.map +1 -0
  94. package/dist/agent/channels/notion-post-arm.js +185 -0
  95. package/dist/agent/channels/notion-post-arm.js.map +1 -0
  96. package/dist/agent/channels/notion-question-return.d.ts +77 -0
  97. package/dist/agent/channels/notion-question-return.d.ts.map +1 -0
  98. package/dist/agent/channels/notion-question-return.js +183 -0
  99. package/dist/agent/channels/notion-question-return.js.map +1 -0
  100. package/dist/agent/channels/notion-read.d.ts +62 -0
  101. package/dist/agent/channels/notion-read.d.ts.map +1 -0
  102. package/dist/agent/channels/notion-read.js +257 -0
  103. package/dist/agent/channels/notion-read.js.map +1 -0
  104. package/dist/agent/channels/notion-scope.d.ts +188 -0
  105. package/dist/agent/channels/notion-scope.d.ts.map +1 -0
  106. package/dist/agent/channels/notion-scope.js +433 -0
  107. package/dist/agent/channels/notion-scope.js.map +1 -0
  108. package/dist/agent/channels/notion-stop.d.ts +48 -0
  109. package/dist/agent/channels/notion-stop.d.ts.map +1 -0
  110. package/dist/agent/channels/notion-stop.js +141 -0
  111. package/dist/agent/channels/notion-stop.js.map +1 -0
  112. package/dist/agent/channels/notion-supervisor.d.ts +462 -0
  113. package/dist/agent/channels/notion-supervisor.d.ts.map +1 -0
  114. package/dist/agent/channels/notion-supervisor.js +482 -0
  115. package/dist/agent/channels/notion-supervisor.js.map +1 -0
  116. package/dist/agent/channels/notion-webhook-timing.d.ts +35 -0
  117. package/dist/agent/channels/notion-webhook-timing.d.ts.map +1 -0
  118. package/dist/agent/channels/notion-webhook-timing.js +99 -0
  119. package/dist/agent/channels/notion-webhook-timing.js.map +1 -0
  120. package/dist/agent/channels/notion-webhook-verifier.d.ts +5 -0
  121. package/dist/agent/channels/notion-webhook-verifier.d.ts.map +1 -0
  122. package/dist/agent/channels/notion-webhook-verifier.js +53 -0
  123. package/dist/agent/channels/notion-webhook-verifier.js.map +1 -0
  124. package/dist/agent/channels/notion-webhook.d.ts +242 -0
  125. package/dist/agent/channels/notion-webhook.d.ts.map +1 -0
  126. package/dist/agent/channels/notion-webhook.js +675 -0
  127. package/dist/agent/channels/notion-webhook.js.map +1 -0
  128. package/dist/agent/channels/notion-work-search.d.ts +9 -0
  129. package/dist/agent/channels/notion-work-search.d.ts.map +1 -0
  130. package/dist/agent/channels/notion-work-search.js +69 -0
  131. package/dist/agent/channels/notion-work-search.js.map +1 -0
  132. package/dist/agent/channels/notion-work.d.ts +68 -0
  133. package/dist/agent/channels/notion-work.d.ts.map +1 -0
  134. package/dist/agent/channels/notion-work.js +126 -0
  135. package/dist/agent/channels/notion-work.js.map +1 -0
  136. package/dist/agent/channels/notion.d.ts +95 -0
  137. package/dist/agent/channels/notion.d.ts.map +1 -0
  138. package/dist/agent/channels/notion.js +1081 -0
  139. package/dist/agent/channels/notion.js.map +1 -0
  140. package/dist/agent/contributions.d.ts +32 -0
  141. package/dist/agent/contributions.d.ts.map +1 -0
  142. package/dist/agent/contributions.js +37 -0
  143. package/dist/agent/contributions.js.map +1 -0
  144. package/dist/agent/docs-generated.d.ts +3 -0
  145. package/dist/agent/docs-generated.d.ts.map +1 -0
  146. package/dist/agent/docs-generated.js +13 -0
  147. package/dist/agent/docs-generated.js.map +1 -0
  148. package/dist/agent/memory/blocks.d.ts +58 -0
  149. package/dist/agent/memory/blocks.d.ts.map +1 -0
  150. package/dist/agent/memory/blocks.js +264 -0
  151. package/dist/agent/memory/blocks.js.map +1 -0
  152. package/dist/agent/memory/memory.d.ts +157 -0
  153. package/dist/agent/memory/memory.d.ts.map +1 -0
  154. package/dist/agent/memory/memory.js +471 -0
  155. package/dist/agent/memory/memory.js.map +1 -0
  156. package/dist/agent/provider-events.d.ts +3 -0
  157. package/dist/agent/provider-events.d.ts.map +1 -0
  158. package/dist/agent/provider-events.js +196 -0
  159. package/dist/agent/provider-events.js.map +1 -0
  160. package/dist/agent/register.d.ts +5 -0
  161. package/dist/agent/register.d.ts.map +1 -0
  162. package/dist/agent/register.js +128 -0
  163. package/dist/agent/register.js.map +1 -0
  164. package/dist/agent/schedules/notion-ingress.d.ts +6 -0
  165. package/dist/agent/schedules/notion-ingress.d.ts.map +1 -0
  166. package/dist/agent/schedules/notion-ingress.js +16 -0
  167. package/dist/agent/schedules/notion-ingress.js.map +1 -0
  168. package/dist/agent/surface-parity.d.ts +3 -0
  169. package/dist/agent/surface-parity.d.ts.map +1 -0
  170. package/dist/agent/surface-parity.js +99 -0
  171. package/dist/agent/surface-parity.js.map +1 -0
  172. package/dist/agent/tools/notion_search.d.ts +56 -0
  173. package/dist/agent/tools/notion_search.d.ts.map +1 -0
  174. package/dist/agent/tools/notion_search.js +100 -0
  175. package/dist/agent/tools/notion_search.js.map +1 -0
  176. package/dist/agent/tools/read_notion_comments.d.ts +57 -0
  177. package/dist/agent/tools/read_notion_comments.d.ts.map +1 -0
  178. package/dist/agent/tools/read_notion_comments.js +236 -0
  179. package/dist/agent/tools/read_notion_comments.js.map +1 -0
  180. package/dist/agent/tools/read_notion_page.d.ts +53 -0
  181. package/dist/agent/tools/read_notion_page.d.ts.map +1 -0
  182. package/dist/agent/tools/read_notion_page.js +327 -0
  183. package/dist/agent/tools/read_notion_page.js.map +1 -0
  184. package/package.json +231 -0
  185. package/tsconfig.build.json +22 -0
  186. package/tsconfig.json +15 -0
@@ -0,0 +1,471 @@
1
+ // The Notion memory backing — a domain's (or the org default's) memory living
2
+ // in a Notion page subtree (docs/capabilities/memory.md "Notion backing"). The silo points at a
3
+ // ROOT page (`container` = the page id). By default it pulls that page AND ALL its child
4
+ // pages RECURSIVELY (containment only — child pages, never @-mentions/links, which would
5
+ // explode), rendering each page's blocks to one markdown file keyed by its page-path, so
6
+ // the Notion hierarchy becomes the memory file hierarchy. Set the silo's `recursive: false`
7
+ // to pull JUST the one page (a single curated page whose sub-pages are noise).
8
+ //
9
+ // THE DEFAULT USE IS READ-ONLY: a curated, human-maintained baseline the agent READS as context
10
+ // (the read-only org default / a read-only domain silo). Sharing the ROOT page with the integration
11
+ // grants the whole subtree, matching the recursive pull.
12
+ //
13
+ // WRITE-BACK IS OPT-IN AND APPEND-ONLY (OPE-70). A silo the author declares WRITABLE (`readOnly`
14
+ // unset) persists the session's added lines to the matching page through Notion's own block-append
15
+ // API. Every other outcome THROWS: a read-only silo, a file with no page, an edit above the tail,
16
+ // and a line the codec cannot store unchanged. Nothing here ever returns "saved" over bytes that
17
+ // went nowhere — that silent loss is the defect this backing used to have.
18
+ //
19
+ // 🔴 THE OPT-IN HAS TWO HALVES, AND THE SECOND IS NOT IN THIS PACKAGE. The silo declares itself
20
+ // writable, AND the deployment's notion `memory` credential must admit `PATCH` on `/v1/blocks/`.
21
+ // The shipped entry (`agent/access/connector-credentials.ts`) admits GET ONLY, so on an unchanged
22
+ // deployment the endpoint fence refuses every append BEFORE dispatch and the persist fails loud.
23
+ // That is deliberate: widening a credential's method set is a capability expansion, which belongs
24
+ // to the operator's own access config and never to a provider package. `write` below turns the
25
+ // fence's bare refusal into an error that names the file to change.
26
+ //
27
+ // 🔴 WHAT A WRITABLE NOTION SILO CANNOT HOLD. Three host-minted file shapes have no Notion page and
28
+ // therefore refuse the whole tier's write: `RECURRING.md` (the dream cycle's enrichment),
29
+ // `<file>.conflict-<session>.md` (the merge's parked concurrent write) and
30
+ // `<file>.rejected-<session>.md` (the write guard's parked destructive overwrite). A deployment that
31
+ // runs the dream cycle, or that shares one silo across concurrent sessions, must keep its writable
32
+ // memory on a backing that owns its files.
33
+ //
34
+ // Lives in @open-everywhere/adapters (Notion is a vendor integration). Uses the raw Notion
35
+ // REST API via an injectable fetch (no SDK dependency needed; offline-testable). Core
36
+ // stays vendor-free; this registers itself under the "notion" provider id.
37
+ import { registerProvider, registerConnectorMemory, domainCredentialId, findConnectorCredential, getSecretVia, safeName, makeSelector, normalizeSelection, assertCredentialEndpointAllowed, withRetryAfterLoose, } from "@open-everywhere/core/agent/adapter-api.js";
38
+ import { createHash } from "node:crypto";
39
+ import { posix } from "node:path";
40
+ import { renderBlocks, pageTitle, contentLines, blocksFromMarkdown, PAGE_BLOCK_TYPES, } from "./blocks.js";
41
+ // The provider name has ONE definition, beside the channel role that shares it. `notion-credentials.ts`
42
+ // imports nothing but the core adapter-api, so this costs the memory plane no channel machinery.
43
+ import { NOTION_PROVIDER } from "../channels/notion-credentials.js";
44
+ const API = "https://api.notion.com";
45
+ const NOTION_VERSION = "2022-06-28";
46
+ /**
47
+ * The ORG-DEFAULT memory credential id — the ROLE a domain override replaces, and the role name a
48
+ * `credentials` binding must name (`{ connector: "notion", credential: "memory", use: "<id>" }`).
49
+ *
50
+ * It is a SEPARATE role from the channel plumbing key on purpose. An operator may share a domain's
51
+ * BRAIN page tree with one integration and its WORK pages with another, and `Domain.credentials` is
52
+ * keyed on the role exactly so that stays expressible.
53
+ */
54
+ export const NOTION_MEMORY_CREDENTIAL = "memory";
55
+ // Bounds (the subtree is paginated + rate-limited; cap to avoid runaway pulls).
56
+ const MAX_PAGES = Number(process.env.OE_NOTION_MAX_PAGES) || 200;
57
+ const MAX_PAGE_DEPTH = Number(process.env.OE_NOTION_MAX_DEPTH) || 6;
58
+ const MAX_BLOCK_DEPTH = 4;
59
+ const TTL_MS = Number(process.env.OE_NOTION_TTL_MS) || 5 * 60_000;
60
+ /** Notion's per-request cap on `children` for the block-append API. Longer appends are batched. */
61
+ const MAX_APPEND_CHILDREN = 100;
62
+ /**
63
+ * Wrap an {@link HttpFetch} so every call is checked against a credential's endpoint rules
64
+ * (OPE-505) BEFORE it is dispatched — this backing's own funnel, the same shape as
65
+ * `channels/notion-api.ts`'s `notionFetch`/`guardCredentialFetch`, adapted to `HttpFetch`'s
66
+ * (non-`Response`) return shape so the two can't be interchanged by accident.
67
+ *
68
+ * `endpoints` undefined returns `base` UNCHANGED, not a wrapper that always allows — an
69
+ * unnarrowed credential stays byte-identical to the pre-fence path, including object identity.
70
+ */
71
+ function guardHttpFetch(endpoints, base) {
72
+ if (endpoints === undefined)
73
+ return base;
74
+ return async (url, init) => {
75
+ assertCredentialEndpointAllowed(endpoints, url, init.method, "notion memory credential");
76
+ return base(url, init);
77
+ };
78
+ }
79
+ /** Minimal Notion REST client — lists a block's children (paginated) and appends new ones.
80
+ *
81
+ * `endpoints` (OPE-505) is the credential's declared endpoint narrowing, carried alongside the
82
+ * token so the fence travels with it — see {@link resolveNotionMemoryCredential}, the ONLY
83
+ * resolver, which returns the pair rather than a bare token for exactly this reason.
84
+ *
85
+ * 429/`Retry-After` BACKOFF (OPE-1255): `children` honours a 429 through `withRetryAfterLoose` —
86
+ * the same shared primitive `channels/notion-api.ts`'s `notionFetch` uses, adapted for `HttpFetch`'s
87
+ * response shape, which carries no `headers` accessor of its own. This was the ONE Notion transport
88
+ * OPE-1233 left uncovered — see `docs/extending/provider-rate-limits.md`. */
89
+ export class NotionClient {
90
+ token;
91
+ apiBase;
92
+ retry;
93
+ fetchFn;
94
+ constructor(token, fetchFn = globalThis.fetch, apiBase = API, endpoints,
95
+ /** Tightens or drives the 429 backoff (OPE-1255) — a test injects a stub `sleep`; omitted
96
+ * takes the shared defaults from `channels/rate-limit-retry.ts`. */
97
+ retry) {
98
+ this.token = token;
99
+ this.apiBase = apiBase;
100
+ this.retry = retry;
101
+ this.fetchFn = guardHttpFetch(endpoints, fetchFn);
102
+ }
103
+ async children(blockId) {
104
+ const out = [];
105
+ let cursor;
106
+ do {
107
+ const qs = new URLSearchParams({ page_size: "100", ...(cursor ? { start_cursor: cursor } : {}) });
108
+ const res = await withRetryAfterLoose(() => this.fetchFn(`${this.apiBase}/v1/blocks/${blockId}/children?${qs}`, {
109
+ method: "GET",
110
+ headers: {
111
+ authorization: `Bearer ${this.token}`,
112
+ "Notion-Version": NOTION_VERSION,
113
+ accept: "application/json",
114
+ },
115
+ }), { ...this.retry, surface: "notion", operation: "blocks.children.list" });
116
+ if (!res.ok)
117
+ throw new Error(`notion children ${blockId}: ${res.status} ${await res.text()}`);
118
+ const body = (await res.json());
119
+ out.push(...(body.results ?? []));
120
+ cursor = body.has_more && body.next_cursor ? body.next_cursor : undefined;
121
+ } while (cursor);
122
+ return out;
123
+ }
124
+ /**
125
+ * APPEND blocks to the end of a page (or of any block that takes children) — Notion's own
126
+ * `PATCH /v1/blocks/{id}/children`, the write half of this backing (OPE-70).
127
+ *
128
+ * It rides the SAME guarded fetch the read does, so a credential narrowed to `GET` refuses the
129
+ * append before it is dispatched, and it carries the same 429 backoff. Batched at Notion's
130
+ * 100-children cap; a batch that fails THROWS, so a partial append surfaces as a failed persist
131
+ * rather than a success line over lost bytes.
132
+ */
133
+ async appendChildren(blockId, children) {
134
+ for (let i = 0; i < children.length; i += MAX_APPEND_CHILDREN) {
135
+ const batch = children.slice(i, i + MAX_APPEND_CHILDREN);
136
+ const res = await withRetryAfterLoose(() => this.fetchFn(`${this.apiBase}/v1/blocks/${blockId}/children`, {
137
+ method: "PATCH",
138
+ headers: {
139
+ authorization: `Bearer ${this.token}`,
140
+ "Notion-Version": NOTION_VERSION,
141
+ accept: "application/json",
142
+ "content-type": "application/json",
143
+ },
144
+ body: JSON.stringify({ children: batch }),
145
+ }), { ...this.retry, surface: "notion", operation: "blocks.children.append" });
146
+ if (!res.ok)
147
+ throw new Error(`notion append ${blockId}: ${res.status} ${await res.text()}`);
148
+ }
149
+ }
150
+ }
151
+ /** Recursively fetch a block's content children (excluding sub-pages), bounded by depth. */
152
+ async function loadBlockTree(client, blockId, depth) {
153
+ const blocks = await client.children(blockId);
154
+ if (depth >= MAX_BLOCK_DEPTH)
155
+ return blocks;
156
+ for (const b of blocks) {
157
+ if (b.has_children && b.id && !PAGE_BLOCK_TYPES.has(b.type)) {
158
+ b.children = await loadBlockTree(client, b.id, depth + 1);
159
+ }
160
+ }
161
+ return blocks;
162
+ }
163
+ /**
164
+ * PASS 1 — walk the page tree, loading each page's blocks and recording its on-disk file
165
+ * key (so PASS 2 can rewrite inter-page links). The root's title isn't known from a parent
166
+ * block, so it falls back to "index".
167
+ */
168
+ async function collect(client, pageId, title, segs, stats, out, selector) {
169
+ if (stats.pages >= MAX_PAGES || segs.length > MAX_PAGE_DEPTH) {
170
+ stats.capped = true;
171
+ return;
172
+ }
173
+ stats.pages++;
174
+ // Blocks are loaded regardless (we need them to find child pages even when this page is
175
+ // a non-included pass-through on the way to a deeper selected page).
176
+ const blocks = await loadBlockTree(client, pageId, 0);
177
+ if (selector.includes(segs, pageId)) {
178
+ const key = segs.length === 0 ? "MEMORY.md" : `${segs.join("/")}.md`;
179
+ out.push({ key, id: pageId, title, blocks });
180
+ }
181
+ if (!selector.descends(segs, pageId))
182
+ return; // selection says don't walk child pages
183
+ for (const b of blocks) {
184
+ if (PAGE_BLOCK_TYPES.has(b.type) && b.id) {
185
+ await collect(client, b.id, pageTitle(b), [...segs, safeName(pageTitle(b))], stats, out, selector);
186
+ }
187
+ }
188
+ }
189
+ /**
190
+ * PASS 2 — render each collected page, rewriting page mentions / link_to_page blocks to
191
+ * the RELATIVE on-disk path of the target file (when the target is in this subtree).
192
+ */
193
+ function renderCollected(pages) {
194
+ const byId = new Map();
195
+ for (const pg of pages)
196
+ byId.set(pg.id, { path: pg.key, title: pg.title });
197
+ const files = {};
198
+ for (const pg of pages) {
199
+ const fromDir = posix.dirname(pg.key);
200
+ const resolve = (id) => {
201
+ const t = byId.get(id);
202
+ if (!t)
203
+ return undefined; // outside this silo's subtree → plain text
204
+ const rel = posix.relative(fromDir, t.path);
205
+ return { path: rel.length > 0 ? rel : t.path, title: t.title };
206
+ };
207
+ files[pg.key] = renderBlocks(pg.blocks, resolve);
208
+ }
209
+ return files;
210
+ }
211
+ /**
212
+ * Build the Notion memory provider. `deps.client(silo, credentialId)` yields a client for a silo
213
+ * under one integration's token. Reads are cached for TTL_MS — a curated baseline changes rarely,
214
+ * and the subtree pull is several API calls.
215
+ *
216
+ * 🔴 THE CACHE KEY CARRIES THE CREDENTIAL AND THE SELECTION, never the root page alone. Two
217
+ * integrations may both be shared a page and see DIFFERENT subtrees of it, because Notion shares per
218
+ * page tree; and two silos may name one page under one integration and select different subsets of
219
+ * it. Keying on the page alone let the first reader's files serve the second — the cross-domain read
220
+ * the per-domain credential exists to prevent, and the subset leak `recursive`/`select` exists to
221
+ * prevent. See {@link cacheKeyFor}.
222
+ */
223
+ export function makeNotionProvider(deps) {
224
+ const cache = new Map();
225
+ /**
226
+ * The cache key. 🔴 IT CARRIES THE SELECTION, not just (credential, root page). Two silos may
227
+ * name the SAME root page under the SAME integration and select different subsets of it
228
+ * (`recursive: false`, or a `select` set) — keying on the page alone served the first reader's
229
+ * subset to the second, which is a silo reading files its own config excluded.
230
+ */
231
+ function cacheKeyFor(silo, credentialId) {
232
+ return `${credentialId} ${silo.container} ${JSON.stringify(normalizeSelection(silo))}`;
233
+ }
234
+ function requireContainer(silo) {
235
+ if (!silo?.container) {
236
+ throw new Error("notion memory backing needs a silo with container = the root page id (memory/silo.ts).");
237
+ }
238
+ return silo;
239
+ }
240
+ /** Pull the subtree, serving a cache hit unless `fresh` is set. The WRITE path always asks for
241
+ * `fresh`: it diffs against the page's CURRENT content, and a five-minute-old copy would make it
242
+ * append lines the page already carries. */
243
+ async function pull(silo, access, fresh) {
244
+ const root = silo.container;
245
+ const credentialId = deps.credentialFor?.(access) ?? NOTION_MEMORY_CREDENTIAL;
246
+ const cacheKey = cacheKeyFor(silo, credentialId);
247
+ const hit = cache.get(cacheKey);
248
+ if (!fresh && hit && Date.now() - hit.atMs < TTL_MS)
249
+ return hit.pull;
250
+ const pages = [];
251
+ const stats = { pages: 0, capped: false };
252
+ const selector = makeSelector(normalizeSelection(silo)); // recursive/select → which pages
253
+ await collect(await deps.client(silo, credentialId), root, "index", [], stats, pages, selector);
254
+ if (stats.capped) {
255
+ console.warn(`[open-everywhere:notion] page "${root}" pull hit the cap (${MAX_PAGES} pages / depth ${MAX_PAGE_DEPTH}); some pages omitted.`);
256
+ }
257
+ const result = { files: renderCollected(pages), pageIds: new Map(pages.map((pg) => [pg.key, pg.id])) };
258
+ cache.set(cacheKey, { pull: result, atMs: Date.now() });
259
+ return result;
260
+ }
261
+ async function read(_p, _tier, silo, access) {
262
+ return (await pull(requireContainer(silo), access, false)).files;
263
+ }
264
+ /**
265
+ * WRITE ONE TIER BACK TO NOTION (OPE-70) — an APPEND of the lines the session added, through
266
+ * Notion's own block-append API, for a silo the author declared WRITABLE.
267
+ *
268
+ * 🔴 THE DEFECT THIS CLOSES IS SILENT LOSS. `writeTier` used to return `null` for every silo. A
269
+ * silo declared writable on provider `notion` is in the session's WRITE plan (memory/resolve.ts:
270
+ * `writes = reads.filter(!readOnly)`), so the write fence ALLOWS the sandbox edit, the persist
271
+ * logs a normal success line, and the bytes reach nothing. `null` also means the `memory.write`
272
+ * audit row never fires, so the write left no trace anywhere.
273
+ *
274
+ * THE THREE RULES, and each one throws rather than dropping bytes:
275
+ * 1. A READ-ONLY silo is REFUSED. It is a projection of Notion, and its update route is the
276
+ * Notion tools — see the banner in core's `memory/readonly.ts`.
277
+ * 2. A file key with no page in the pulled subtree is REFUSED. Creating pages is a different
278
+ * API and a different decision (where in the tree? under what title?), so v1 appends to
279
+ * pages that already exist.
280
+ * 3. The backing is APPEND-ONLY. A page's current content must still be a PREFIX of the new
281
+ * content; an edit or a deletion above the tail cannot be expressed as an append, so it is
282
+ * refused rather than half-applied.
283
+ */
284
+ async function write(_p, _tier, files, _message, siloArg, access) {
285
+ const silo = requireContainer(siloArg);
286
+ if (silo.readOnly === true) {
287
+ const via = silo.skill ? `the \`${silo.skill}\` skill` : "the Notion tools";
288
+ throw new Error(`notion memory: silo "${silo.name}" is READ-ONLY (memory/silo.ts \`readOnly\`), so this write of ` +
289
+ `${Object.keys(files).length} file(s) was REFUSED and NOTHING was saved. Update the Notion source with ` +
290
+ `${via} and the projection refreshes from it, or declare the silo writable to let memory append to its pages.`);
291
+ }
292
+ const credentialId = deps.credentialFor?.(access) ?? NOTION_MEMORY_CREDENTIAL;
293
+ const current = await pull(silo, access, true);
294
+ const appends = [];
295
+ for (const [key, content] of Object.entries(files)) {
296
+ const pageId = current.pageIds.get(key);
297
+ if (pageId === undefined) {
298
+ throw new Error(`notion memory: silo "${silo.name}" has no Notion page for "${key}", and this backing appends to ` +
299
+ `EXISTING pages only — it does not create them. NOTHING was saved, including the other file(s) in ` +
300
+ `this write: the whole tier is refused together so no half-written state reaches Notion. Add the ` +
301
+ `page under root page "${silo.container}" in Notion (it becomes writable on the next pull), or move ` +
302
+ `this silo to a backing that owns its files (github/postgres/sqlite). 🔴 THREE FILE SHAPES ARE ` +
303
+ `HOST-MINTED and can never map to a page: "RECURRING.md" (the dream cycle's enrichment), ` +
304
+ `"<file>.conflict-<session>.md" (a concurrent write parked by the merge) and ` +
305
+ `"<file>.rejected-<session>.md" (a destructive overwrite parked by the write guard). A deployment ` +
306
+ `that runs any of those must not hold its writable memory on this backing.`);
307
+ }
308
+ const cur = contentLines(current.files[key] ?? "");
309
+ const next = contentLines(content);
310
+ // The page's current lines must still be a PREFIX of the new ones. A DELETION lands here too:
311
+ // the shorter `next` has `undefined` where a current line was, so it diverges at that index.
312
+ const diverges = cur.findIndex((line, i) => line !== next[i]);
313
+ if (diverges !== -1) {
314
+ throw new Error(`notion memory: "${key}" in silo "${silo.name}" changed at line ${diverges + 1}, and this backing is ` +
315
+ `APPEND-ONLY — it adds blocks to the end of a page and cannot edit or remove one. Nothing was saved. ` +
316
+ `Change that content in Notion itself, or move this silo to a backing that owns its files ` +
317
+ `(github/postgres/sqlite).`);
318
+ }
319
+ const added = next.slice(cur.length);
320
+ if (added.length > 0)
321
+ appends.push({ pageId, key, lines: added });
322
+ }
323
+ if (appends.length === 0)
324
+ return null; // nothing changed — the provider contract's null
325
+ // Every batch is BUILT and round-trip-proven before ANY of them is dispatched, so a line this
326
+ // codec cannot store leaves the page untouched rather than half-appended.
327
+ const batches = appends.map((a) => ({ ...a, blocks: blocksFromMarkdown(a.lines) }));
328
+ const client = await deps.client(silo, credentialId);
329
+ // 🔴 DROP THE CACHE BEFORE THE FIRST APPEND, never after the last. The fresh pull above put the
330
+ // PRE-append snapshot in the cache. A batch that throws part-way leaves earlier batches' blocks
331
+ // in Notion, and a cache dropped only on success would then serve that stale snapshot for the
332
+ // rest of the TTL — a reader seeing memory Notion already holds.
333
+ cache.delete(cacheKeyFor(silo, credentialId));
334
+ const version = createHash("sha256");
335
+ for (const batch of batches) {
336
+ try {
337
+ await client.appendChildren(batch.pageId, batch.blocks);
338
+ }
339
+ catch (err) {
340
+ // The likeliest cause is the credential's own endpoint narrowing: the shipped `memory`
341
+ // credential admits GET only, and the fence refuses the PATCH before dispatch. That refusal
342
+ // reads as a bare "BLOCKED PATCH …", which does not tell an operator where the fix lives.
343
+ throw new Error(`notion memory: appending to silo "${silo.name}" failed for "${batch.key}" — ${String(err)}. ` +
344
+ `Nothing further was written. If this is an endpoint refusal, the notion "memory" credential ` +
345
+ `must admit PATCH on /v1/blocks/ (agent/access/connector-credentials.ts): write-back is a ` +
346
+ `deliberate capability expansion, so a deployment opts into it in that file, not here.`, { cause: err });
347
+ }
348
+ version.update(`${batch.key}\n${batch.lines.join("\n")}\n`);
349
+ }
350
+ return version.digest("hex");
351
+ }
352
+ return {
353
+ id: "notion",
354
+ readTier: read,
355
+ // Never seeds: a Notion page tree is authored in Notion, so "ensure" is just the pull. A silo
356
+ // whose root page is empty materialises empty rather than having a seed written into someone's
357
+ // Notion workspace.
358
+ ensureTier: read,
359
+ writeTier: write,
360
+ deleteTier: async (_p, _tier, silo) => {
361
+ // A read-only projection has nothing of ours to erase — the source is authored in Notion.
362
+ if (silo?.readOnly === true)
363
+ return;
364
+ // A WRITABLE silo does hold bytes this backing appended, and v1 cannot remove them: block
365
+ // deletion is a separate API and a separate decision. Refuse rather than report an erasure
366
+ // that did not happen — a purge that silently no-ops is the worst version of this defect.
367
+ throw new Error(`notion memory: silo "${silo?.name ?? "(unnamed)"}" is writable, and this backing cannot erase a tier — ` +
368
+ `it appends blocks and never deletes them. NOTHING was erased. Remove the content in Notion itself, or ` +
369
+ `hold erasable memory in a backing with real deletion (postgres/sqlite).`);
370
+ },
371
+ };
372
+ }
373
+ /**
374
+ * The Notion credential ONE memory read runs under — the org default, or a bound domain's own
375
+ * integration — together with its endpoint rules. THE ONLY way to resolve a Notion memory
376
+ * credential.
377
+ *
378
+ * TWO PATHS, and the difference is the whole rule (OPE-467, applied to memory by OPE-485):
379
+ * • `credentialId` IS the org-default role ⇒ the deployment key, resolved through the explicit
380
+ * broker + ref stamp `registerNotionMemory` carries. Unchanged behaviour for every deployment
381
+ * that binds nothing, which is nearly all of them. Its endpoint rules come from the SAME-named
382
+ * `"memory"` entry in the registered provider set (agent/access/providers.ts) — that entry's
383
+ * `secretRef` is not what this path reads (see the comment there), but its `endpoints` is, so
384
+ * the org-default read is narrowed exactly as the entry declares.
385
+ * • `credentialId` is a BOUND domain's own credential ⇒ that `ConnectorCredential`'s own
386
+ * `secretRef` + `broker` + `endpoints`, resolved through the same seam `channels/notion-api.ts`
387
+ * uses.
388
+ *
389
+ * 🔴 A BOUND DOMAIN NEVER FALLS BACK TO THE ORG KEY. When the named credential is absent from the
390
+ * provider set, or carries no `secretRef`, this THROWS. Quietly serving the deployment key there
391
+ * would hand the domain the exact integration it was bound away from, which is the isolation the
392
+ * binding was created to buy. `assertDomainCredentialsResolvable` already refuses such a config at
393
+ * boot, so this throw is the second line, not the first.
394
+ */
395
+ export async function resolveNotionMemoryCredential(credentialId, broker, secretRef) {
396
+ if (credentialId === NOTION_MEMORY_CREDENTIAL) {
397
+ const token = await getSecretVia(broker, secretRef);
398
+ return { token, endpoints: findConnectorCredential(NOTION_PROVIDER, NOTION_MEMORY_CREDENTIAL)?.endpoints };
399
+ }
400
+ const cred = findConnectorCredential(NOTION_PROVIDER, credentialId);
401
+ if (!cred?.secretRef) {
402
+ throw new Error(`notion memory backing: domain credential "${credentialId}" is not a declared notion credential with a secretRef ` +
403
+ `(agent/access/providers.ts). A bound domain never falls back to the org default "${NOTION_MEMORY_CREDENTIAL}" key.`);
404
+ }
405
+ const token = await getSecretVia(cred.broker, cred.secretRef);
406
+ return { token, endpoints: cred.endpoints };
407
+ }
408
+ /**
409
+ * THE PRODUCTION WIRING of the credential seam, as a value — the deps {@link registerNotionMemory}
410
+ * registers. It is exported so a test drives the REAL wiring with only the HTTP call replaced,
411
+ * rather than restating `credentialFor` and getting a green from its own copy of the rule.
412
+ *
413
+ * `fetchFn` is the ONLY injected part. Leave it undefined in production and `NotionClient` uses
414
+ * `globalThis.fetch`.
415
+ */
416
+ export function notionMemoryDeps(secretRef, broker, fetchFn) {
417
+ return {
418
+ credentialFor: (access) => domainCredentialId(access?.domain, NOTION_PROVIDER, NOTION_MEMORY_CREDENTIAL),
419
+ client: async (_silo, credentialId) => {
420
+ const { token, endpoints } = await resolveNotionMemoryCredential(credentialId, broker, secretRef);
421
+ return new NotionClient(token, fetchFn, API, endpoints);
422
+ },
423
+ };
424
+ }
425
+ /**
426
+ * Register the Notion memory backing, and DECLARE it as a connector-owned memory capability
427
+ * (OPE-390) so the prefetch invariant applies: a domain may only project a Notion subtree if it
428
+ * holds the `notion` connector grant. Memory rides the same route as connector access.
429
+ *
430
+ * MODE `"materialise"` — the DEFAULT posture: the files are a read-only PROJECTION, not the source
431
+ * of truth. The subtree is pulled to Markdown, chmod-locked in the sandbox, and the banner routes
432
+ * writes to Notion's own connector ops. A silo the author declares WRITABLE opts out of that
433
+ * posture per silo and persists through the append path above (OPE-70); the mode names what a
434
+ * Notion silo is unless its author says otherwise, and it stays the recommended shape.
435
+ *
436
+ * SUBJECT `"app-principal"` — structurally pinned (memory/connector-memory.ts). Materialisation is
437
+ * host-side at session.started, outside any session and any approval flow, and a shared domain
438
+ * brain must never be projected through one person's user-subject OAuth token: doing so would bake
439
+ * their personal access into a cache every session in the domain then reads.
440
+ *
441
+ * CREDENTIAL (OPE-485, completing the symmetry ruling's credential half). The domain that OWNS the
442
+ * silo picks the integration, and a domain that binds none uses the org default — the same one rule
443
+ * `channels/notion-credentials.ts` states for the channel plane. The seam that carries the domain is
444
+ * `MemoryAccess` (core `memory/provider.ts`); this backing turns it into a credential id with
445
+ * `domainCredentialId(access.domain, "notion", "memory")`.
446
+ *
447
+ * The ORG DEFAULT still resolves through its explicit home credential BROKER (`getSecretVia`) —
448
+ * `"db"` + `db:notion:memory` (OPE-408 step 2, re-stamped from `"env"` + `NOTION_TOKEN`),
449
+ * overridable via `OE_NOTION_SECRET_BROKER`/`OE_NOTION_SECRET_REF`. A BOUND domain resolves its own
450
+ * `ConnectorCredential` instead, through the same `findConnectorCredential` → `getSecretVia` seam the
451
+ * channel key uses, and FAILS CLOSED — see {@link resolveNotionMemoryCredential}.
452
+ *
453
+ * Resolution stays LAZY (per read, inside makeNotionProvider's client factory): registering is cheap
454
+ * and side-effect-free, and a missing secret fails loud at read time only when a `notion` silo is
455
+ * actually used.
456
+ */
457
+ export function registerNotionMemory(secretRef = process.env.OE_NOTION_SECRET_REF ?? "db:notion:memory", broker = process.env.OE_NOTION_SECRET_BROKER ?? "db") {
458
+ registerProvider(makeNotionProvider(notionMemoryDeps(secretRef, broker)));
459
+ registerConnectorMemory({
460
+ provider: "notion",
461
+ connector: "notion",
462
+ mode: "materialise",
463
+ subject: "app-principal",
464
+ containerLabel: "the root page id",
465
+ // No container-level grant check: a Notion page id is not a member of any grant plane the
466
+ // access resolver models (unlike a GitHub repo, which the `repos` grant enumerates). The
467
+ // connector grant IS the whole invariant here — deliberately, rather than inventing a
468
+ // page-level grant vocabulary with no evidence behind it.
469
+ });
470
+ }
471
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../agent/memory/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProviderEventDeclaration } from "@open-everywhere/core/agent/adapter-api.js";
2
+ export declare const NOTION_PROVIDER_EVENTS: ProviderEventDeclaration;
3
+ //# sourceMappingURL=provider-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-events.d.ts","sourceRoot":"","sources":["../../agent/provider-events.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F,eAAO,MAAM,sBAAsB,EAAE,wBAsKpC,CAAC"}