@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.
- package/LICENSE +201 -0
- package/NOTICE +21 -0
- package/README.md +48 -0
- package/agent/channels/notion-acting-identity.ts +88 -0
- package/agent/channels/notion-ancestry-trust.ts +458 -0
- package/agent/channels/notion-api.ts +1290 -0
- package/agent/channels/notion-bot-user.ts +250 -0
- package/agent/channels/notion-catch-up.ts +339 -0
- package/agent/channels/notion-credentials.ts +417 -0
- package/agent/channels/notion-engagement.ts +372 -0
- package/agent/channels/notion-event-normalizer.ts +587 -0
- package/agent/channels/notion-identity.ts +271 -0
- package/agent/channels/notion-ingress-drain.ts +289 -0
- package/agent/channels/notion-ingress.ts +182 -0
- package/agent/channels/notion-message-ops.ts +140 -0
- package/agent/channels/notion-origin-codec.ts +38 -0
- package/agent/channels/notion-post-arm.ts +189 -0
- package/agent/channels/notion-question-return.ts +223 -0
- package/agent/channels/notion-read.ts +283 -0
- package/agent/channels/notion-scope.ts +560 -0
- package/agent/channels/notion-stop.ts +169 -0
- package/agent/channels/notion-supervisor.ts +856 -0
- package/agent/channels/notion-webhook-timing.ts +131 -0
- package/agent/channels/notion-webhook-verifier.ts +55 -0
- package/agent/channels/notion-webhook.ts +963 -0
- package/agent/channels/notion-work-search.ts +74 -0
- package/agent/channels/notion-work.ts +144 -0
- package/agent/channels/notion.ts +1242 -0
- package/agent/contributions.ts +39 -0
- package/agent/docs-generated.ts +15 -0
- package/agent/memory/blocks.ts +295 -0
- package/agent/memory/memory.ts +622 -0
- package/agent/provider-events.ts +198 -0
- package/agent/register.ts +144 -0
- package/agent/schedules/notion-ingress.ts +20 -0
- package/agent/surface-parity.ts +105 -0
- package/agent/tools/notion_search.ts +110 -0
- package/agent/tools/read_notion_comments.ts +250 -0
- package/agent/tools/read_notion_page.ts +351 -0
- package/dist/agent/channels/notion-acting-identity.d.ts +23 -0
- package/dist/agent/channels/notion-acting-identity.d.ts.map +1 -0
- package/dist/agent/channels/notion-acting-identity.js +85 -0
- package/dist/agent/channels/notion-acting-identity.js.map +1 -0
- package/dist/agent/channels/notion-ancestry-trust.d.ts +208 -0
- package/dist/agent/channels/notion-ancestry-trust.d.ts.map +1 -0
- package/dist/agent/channels/notion-ancestry-trust.js +331 -0
- package/dist/agent/channels/notion-ancestry-trust.js.map +1 -0
- package/dist/agent/channels/notion-api.d.ts +655 -0
- package/dist/agent/channels/notion-api.d.ts.map +1 -0
- package/dist/agent/channels/notion-api.js +938 -0
- package/dist/agent/channels/notion-api.js.map +1 -0
- package/dist/agent/channels/notion-bot-user.d.ts +107 -0
- package/dist/agent/channels/notion-bot-user.d.ts.map +1 -0
- package/dist/agent/channels/notion-bot-user.js +192 -0
- package/dist/agent/channels/notion-bot-user.js.map +1 -0
- package/dist/agent/channels/notion-catch-up.d.ts +64 -0
- package/dist/agent/channels/notion-catch-up.d.ts.map +1 -0
- package/dist/agent/channels/notion-catch-up.js +289 -0
- package/dist/agent/channels/notion-catch-up.js.map +1 -0
- package/dist/agent/channels/notion-credentials.d.ts +210 -0
- package/dist/agent/channels/notion-credentials.d.ts.map +1 -0
- package/dist/agent/channels/notion-credentials.js +360 -0
- package/dist/agent/channels/notion-credentials.js.map +1 -0
- package/dist/agent/channels/notion-engagement.d.ts +219 -0
- package/dist/agent/channels/notion-engagement.d.ts.map +1 -0
- package/dist/agent/channels/notion-engagement.js +283 -0
- package/dist/agent/channels/notion-engagement.js.map +1 -0
- package/dist/agent/channels/notion-event-normalizer.d.ts +194 -0
- package/dist/agent/channels/notion-event-normalizer.d.ts.map +1 -0
- package/dist/agent/channels/notion-event-normalizer.js +542 -0
- package/dist/agent/channels/notion-event-normalizer.js.map +1 -0
- package/dist/agent/channels/notion-identity.d.ts +119 -0
- package/dist/agent/channels/notion-identity.d.ts.map +1 -0
- package/dist/agent/channels/notion-identity.js +205 -0
- package/dist/agent/channels/notion-identity.js.map +1 -0
- package/dist/agent/channels/notion-ingress-drain.d.ts +66 -0
- package/dist/agent/channels/notion-ingress-drain.d.ts.map +1 -0
- package/dist/agent/channels/notion-ingress-drain.js +185 -0
- package/dist/agent/channels/notion-ingress-drain.js.map +1 -0
- package/dist/agent/channels/notion-ingress.d.ts +64 -0
- package/dist/agent/channels/notion-ingress.d.ts.map +1 -0
- package/dist/agent/channels/notion-ingress.js +130 -0
- package/dist/agent/channels/notion-ingress.js.map +1 -0
- package/dist/agent/channels/notion-message-ops.d.ts +3 -0
- package/dist/agent/channels/notion-message-ops.d.ts.map +1 -0
- package/dist/agent/channels/notion-message-ops.js +126 -0
- package/dist/agent/channels/notion-message-ops.js.map +1 -0
- package/dist/agent/channels/notion-origin-codec.d.ts +7 -0
- package/dist/agent/channels/notion-origin-codec.d.ts.map +1 -0
- package/dist/agent/channels/notion-origin-codec.js +32 -0
- package/dist/agent/channels/notion-origin-codec.js.map +1 -0
- package/dist/agent/channels/notion-post-arm.d.ts +3 -0
- package/dist/agent/channels/notion-post-arm.d.ts.map +1 -0
- package/dist/agent/channels/notion-post-arm.js +185 -0
- package/dist/agent/channels/notion-post-arm.js.map +1 -0
- package/dist/agent/channels/notion-question-return.d.ts +77 -0
- package/dist/agent/channels/notion-question-return.d.ts.map +1 -0
- package/dist/agent/channels/notion-question-return.js +183 -0
- package/dist/agent/channels/notion-question-return.js.map +1 -0
- package/dist/agent/channels/notion-read.d.ts +62 -0
- package/dist/agent/channels/notion-read.d.ts.map +1 -0
- package/dist/agent/channels/notion-read.js +257 -0
- package/dist/agent/channels/notion-read.js.map +1 -0
- package/dist/agent/channels/notion-scope.d.ts +188 -0
- package/dist/agent/channels/notion-scope.d.ts.map +1 -0
- package/dist/agent/channels/notion-scope.js +433 -0
- package/dist/agent/channels/notion-scope.js.map +1 -0
- package/dist/agent/channels/notion-stop.d.ts +48 -0
- package/dist/agent/channels/notion-stop.d.ts.map +1 -0
- package/dist/agent/channels/notion-stop.js +141 -0
- package/dist/agent/channels/notion-stop.js.map +1 -0
- package/dist/agent/channels/notion-supervisor.d.ts +462 -0
- package/dist/agent/channels/notion-supervisor.d.ts.map +1 -0
- package/dist/agent/channels/notion-supervisor.js +482 -0
- package/dist/agent/channels/notion-supervisor.js.map +1 -0
- package/dist/agent/channels/notion-webhook-timing.d.ts +35 -0
- package/dist/agent/channels/notion-webhook-timing.d.ts.map +1 -0
- package/dist/agent/channels/notion-webhook-timing.js +99 -0
- package/dist/agent/channels/notion-webhook-timing.js.map +1 -0
- package/dist/agent/channels/notion-webhook-verifier.d.ts +5 -0
- package/dist/agent/channels/notion-webhook-verifier.d.ts.map +1 -0
- package/dist/agent/channels/notion-webhook-verifier.js +53 -0
- package/dist/agent/channels/notion-webhook-verifier.js.map +1 -0
- package/dist/agent/channels/notion-webhook.d.ts +242 -0
- package/dist/agent/channels/notion-webhook.d.ts.map +1 -0
- package/dist/agent/channels/notion-webhook.js +675 -0
- package/dist/agent/channels/notion-webhook.js.map +1 -0
- package/dist/agent/channels/notion-work-search.d.ts +9 -0
- package/dist/agent/channels/notion-work-search.d.ts.map +1 -0
- package/dist/agent/channels/notion-work-search.js +69 -0
- package/dist/agent/channels/notion-work-search.js.map +1 -0
- package/dist/agent/channels/notion-work.d.ts +68 -0
- package/dist/agent/channels/notion-work.d.ts.map +1 -0
- package/dist/agent/channels/notion-work.js +126 -0
- package/dist/agent/channels/notion-work.js.map +1 -0
- package/dist/agent/channels/notion.d.ts +95 -0
- package/dist/agent/channels/notion.d.ts.map +1 -0
- package/dist/agent/channels/notion.js +1081 -0
- package/dist/agent/channels/notion.js.map +1 -0
- package/dist/agent/contributions.d.ts +32 -0
- package/dist/agent/contributions.d.ts.map +1 -0
- package/dist/agent/contributions.js +37 -0
- package/dist/agent/contributions.js.map +1 -0
- package/dist/agent/docs-generated.d.ts +3 -0
- package/dist/agent/docs-generated.d.ts.map +1 -0
- package/dist/agent/docs-generated.js +13 -0
- package/dist/agent/docs-generated.js.map +1 -0
- package/dist/agent/memory/blocks.d.ts +58 -0
- package/dist/agent/memory/blocks.d.ts.map +1 -0
- package/dist/agent/memory/blocks.js +264 -0
- package/dist/agent/memory/blocks.js.map +1 -0
- package/dist/agent/memory/memory.d.ts +157 -0
- package/dist/agent/memory/memory.d.ts.map +1 -0
- package/dist/agent/memory/memory.js +471 -0
- package/dist/agent/memory/memory.js.map +1 -0
- package/dist/agent/provider-events.d.ts +3 -0
- package/dist/agent/provider-events.d.ts.map +1 -0
- package/dist/agent/provider-events.js +196 -0
- package/dist/agent/provider-events.js.map +1 -0
- package/dist/agent/register.d.ts +5 -0
- package/dist/agent/register.d.ts.map +1 -0
- package/dist/agent/register.js +128 -0
- package/dist/agent/register.js.map +1 -0
- package/dist/agent/schedules/notion-ingress.d.ts +6 -0
- package/dist/agent/schedules/notion-ingress.d.ts.map +1 -0
- package/dist/agent/schedules/notion-ingress.js +16 -0
- package/dist/agent/schedules/notion-ingress.js.map +1 -0
- package/dist/agent/surface-parity.d.ts +3 -0
- package/dist/agent/surface-parity.d.ts.map +1 -0
- package/dist/agent/surface-parity.js +99 -0
- package/dist/agent/surface-parity.js.map +1 -0
- package/dist/agent/tools/notion_search.d.ts +56 -0
- package/dist/agent/tools/notion_search.d.ts.map +1 -0
- package/dist/agent/tools/notion_search.js +100 -0
- package/dist/agent/tools/notion_search.js.map +1 -0
- package/dist/agent/tools/read_notion_comments.d.ts +57 -0
- package/dist/agent/tools/read_notion_comments.d.ts.map +1 -0
- package/dist/agent/tools/read_notion_comments.js +236 -0
- package/dist/agent/tools/read_notion_comments.js.map +1 -0
- package/dist/agent/tools/read_notion_page.d.ts +53 -0
- package/dist/agent/tools/read_notion_page.d.ts.map +1 -0
- package/dist/agent/tools/read_notion_page.js +327 -0
- package/dist/agent/tools/read_notion_page.js.map +1 -0
- package/package.json +231 -0
- package/tsconfig.build.json +22 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// THE WORK-PLANE SEARCH (OPE-913) — Notion's own cross-container read, under a domain work grant.
|
|
2
|
+
//
|
|
3
|
+
// WHY IT IS WORK AND NOT CHAT (OPE-928's container line): a read INSIDE the wake container is chat —
|
|
4
|
+
// the envelope already renders it. A read ACROSS containers is work: it reaches pages nobody in this
|
|
5
|
+
// conversation named, which is an exfiltration surface, so it lives behind the domain's work grant
|
|
6
|
+
// and runs on the work credential.
|
|
7
|
+
//
|
|
8
|
+
// MOUNT: the domain's work grant, and nothing else. No grant ⇒ the tool is ABSENT, not refusing.
|
|
9
|
+
// That is the OPE-927 class closed structurally: a worker that never mounts this cannot tell a
|
|
10
|
+
// member it "searched Notion and found nothing".
|
|
11
|
+
//
|
|
12
|
+
// 🔴 NO RESULT FILTER, EVER. Tommy ruled on 2026-08-21 that search's reach IS the credential's
|
|
13
|
+
// reach: "OE never filters search results as a boundary (a post-hoc filter is not enforcement)."
|
|
14
|
+
// Notion enforces the boundary for real — an internal integration sees only the page trees a human
|
|
15
|
+
// shared with it — so an organisation narrows search by sharing a narrow integration, and OE ships
|
|
16
|
+
// the legible seam rather than a filter that would look like one. If you are about to add a
|
|
17
|
+
// domain-scoped filter here, read that ruling first.
|
|
18
|
+
//
|
|
19
|
+
// WHAT COMES BACK: ids and titles. No page body ever crosses this tool, so the model has to take the
|
|
20
|
+
// second, FENCED step (read_notion_page, which admits only pages the caller's own domain owns) to
|
|
21
|
+
// read anything. Search widens what the agent can FIND; it does not widen what it can READ.
|
|
22
|
+
//
|
|
23
|
+
// Output is wrapped untrusted: a page title is written by arbitrary workspace members, so the model
|
|
24
|
+
// must treat it as DATA, not instructions.
|
|
25
|
+
import { defineDynamic, defineTool } from "eve/tools";
|
|
26
|
+
import { z } from "zod";
|
|
27
|
+
import { resolveNotionCredential, searchNotion } from "../channels/notion-api.js";
|
|
28
|
+
import { notionWorkGrant, notionWorkMount } from "../channels/notion-work.js";
|
|
29
|
+
import { assertNotionActingIdentity } from "../channels/notion-acting-identity.js";
|
|
30
|
+
import { ingestUntrustedModelOutput, getConfig, preRegisterDynamicEntry, } from "@open-everywhere/core/agent/adapter-api.js";
|
|
31
|
+
const MAX_RESULTS = 25;
|
|
32
|
+
// FACTORED (see read_notion_page.ts's REPLAY DOCTRINE note): a top-level defineTool const, never an
|
|
33
|
+
// inline literal in the handler. Exported so the work-grant test can drive execute() and prove the
|
|
34
|
+
// grant is actually WIRED here — a mount gate the handler forgets to honour is worth nothing.
|
|
35
|
+
export const notionSearchEntry = defineTool({
|
|
36
|
+
description: "Search this domain's Notion workspace by title and text, and get back page ids + titles. " +
|
|
37
|
+
"Use it to FIND the page you need — a spec, a runbook, a notes page — then read it with " +
|
|
38
|
+
"read_notion_page. It returns no page content, so a result is a pointer, not an answer.",
|
|
39
|
+
inputSchema: z.object({
|
|
40
|
+
query: z.string().min(1).describe("Words to search for in page titles and text."),
|
|
41
|
+
limit: z.number().int().min(1).max(MAX_RESULTS).optional().describe(`How many results to return (default 10, max ${MAX_RESULTS}).`),
|
|
42
|
+
kind: z.enum(["page", "database"]).optional().describe("Restrict results to pages or to databases. Omit for both."),
|
|
43
|
+
}),
|
|
44
|
+
outputSchema: z.object({
|
|
45
|
+
query: z.string(),
|
|
46
|
+
hits: z.array(z.object({ id: z.string(), object: z.string(), title: z.string(), url: z.string().optional() })),
|
|
47
|
+
}),
|
|
48
|
+
// NO `approval:` — a dynamic-tool approval fn only registers at session.started resolve time, so a
|
|
49
|
+
// resumed session's replay lookup fails and eve kills the turn (the pin read_notion_page carries).
|
|
50
|
+
// Read-only, so absent approval === never() is correct.
|
|
51
|
+
async execute(input, ctx) {
|
|
52
|
+
const domains = getConfig().loadDomains();
|
|
53
|
+
// THE GRANT IS RE-CHECKED IN EXECUTE, not trusted from the mount. A session resolves its tools
|
|
54
|
+
// once at session.started and can then run for hours; the config it mounted under is a
|
|
55
|
+
// deployment away from changing. Re-reading it here costs one pure lookup and means a revoked
|
|
56
|
+
// grant stops working on the next call rather than on the next rotation.
|
|
57
|
+
const grant = notionWorkGrant(ctx, domains);
|
|
58
|
+
if (!grant) {
|
|
59
|
+
throw new Error("This domain holds no Notion work grant, so Notion search is unavailable here. " +
|
|
60
|
+
"An operator grants it by declaring the domain's Notion work credential in agent/memory/config/domains.ts.");
|
|
61
|
+
}
|
|
62
|
+
// 🔴 OPE-1525 — THE OWN-ACCOUNT GATE, on the line below's behalf. `grant.credential` is a TEAM
|
|
63
|
+
// key by construction (channels/notion-work.ts NOTION_WORK_CREDENTIAL), so a member who asked to
|
|
64
|
+
// act with THEIR OWN Notion account has no answer here. The gate refuses that turn and writes the
|
|
65
|
+
// `connector.acting_identity` row either way — see channels/notion-acting-identity.ts.
|
|
66
|
+
await assertNotionActingIdentity(ctx, "notion_search");
|
|
67
|
+
const cred = await resolveNotionCredential(grant.credential);
|
|
68
|
+
if (!cred)
|
|
69
|
+
throw new Error(`no value stored for this domain's Notion work credential "${grant.credential}" — cannot search.`);
|
|
70
|
+
const hits = await searchNotion(input.query, {
|
|
71
|
+
...cred,
|
|
72
|
+
pageSize: input.limit ?? 10,
|
|
73
|
+
...(input.kind ? { filter: input.kind } : {}),
|
|
74
|
+
});
|
|
75
|
+
return { query: input.query, hits: hits.slice(0, input.limit ?? 10).map((h) => ({ ...h })) };
|
|
76
|
+
},
|
|
77
|
+
toModelOutput(output) {
|
|
78
|
+
const body = output.hits.length === 0
|
|
79
|
+
? `Notion search for "${output.query}" matched nothing the work integration can see.`
|
|
80
|
+
: `Notion search for "${output.query}" — ${output.hits.length} result(s):\n` +
|
|
81
|
+
output.hits.map((h) => `- ${h.object} ${h.id}: ${h.title || "(untitled)"}`).join("\n");
|
|
82
|
+
return ingestUntrustedModelOutput(body, {
|
|
83
|
+
source: "notion search",
|
|
84
|
+
ingestion: { kind: "notion", label: "notion_search" },
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
preRegisterDynamicEntry("notion_search", "_single", notionSearchEntry);
|
|
89
|
+
export default defineDynamic({
|
|
90
|
+
events: {
|
|
91
|
+
// session.started ONLY: a session's domain cannot change mid-session, so resolving the grant
|
|
92
|
+
// once is correct and cheaper (the same reasoning read_notion_page's resolver carries).
|
|
93
|
+
"session.started": (_event, ctx) => {
|
|
94
|
+
if (!notionWorkMount(ctx, () => getConfig().loadDomains()))
|
|
95
|
+
return null; // no work grant ⇒ absent
|
|
96
|
+
return notionSearchEntry;
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=notion_search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notion_search.js","sourceRoot":"","sources":["../../../agent/tools/notion_search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type SurfaceTrust } from "@open-everywhere/core/agent/adapter-api.js";
|
|
2
|
+
export declare const readNotionCommentsEntry: import("eve/tools").ToolDefinition<{
|
|
3
|
+
page?: string | undefined;
|
|
4
|
+
block?: string | undefined;
|
|
5
|
+
}, {
|
|
6
|
+
page: string;
|
|
7
|
+
discussions: number;
|
|
8
|
+
comments: number;
|
|
9
|
+
blocksScanned: number;
|
|
10
|
+
truncated: boolean;
|
|
11
|
+
text: string;
|
|
12
|
+
readAt?: string | undefined;
|
|
13
|
+
workspaceTrust?: "internal" | "public" | undefined;
|
|
14
|
+
}> & {
|
|
15
|
+
execute(input: {
|
|
16
|
+
page?: string | undefined;
|
|
17
|
+
block?: string | undefined;
|
|
18
|
+
}, ctx: import("eve/tools").ToolContext): Promise<{
|
|
19
|
+
page: string;
|
|
20
|
+
discussions: number;
|
|
21
|
+
comments: number;
|
|
22
|
+
blocksScanned: number;
|
|
23
|
+
truncated: boolean;
|
|
24
|
+
text: string;
|
|
25
|
+
readAt: string;
|
|
26
|
+
workspaceTrust?: SurfaceTrust | undefined;
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
29
|
+
declare const _default: import("eve/tools").DynamicSentinel<(import("eve/tools").ToolDefinition<{
|
|
30
|
+
page?: string | undefined;
|
|
31
|
+
block?: string | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
page: string;
|
|
34
|
+
discussions: number;
|
|
35
|
+
comments: number;
|
|
36
|
+
blocksScanned: number;
|
|
37
|
+
truncated: boolean;
|
|
38
|
+
text: string;
|
|
39
|
+
readAt?: string | undefined;
|
|
40
|
+
workspaceTrust?: "internal" | "public" | undefined;
|
|
41
|
+
}> & {
|
|
42
|
+
execute(input: {
|
|
43
|
+
page?: string | undefined;
|
|
44
|
+
block?: string | undefined;
|
|
45
|
+
}, ctx: import("eve/tools").ToolContext): Promise<{
|
|
46
|
+
page: string;
|
|
47
|
+
discussions: number;
|
|
48
|
+
comments: number;
|
|
49
|
+
blocksScanned: number;
|
|
50
|
+
truncated: boolean;
|
|
51
|
+
text: string;
|
|
52
|
+
readAt: string;
|
|
53
|
+
workspaceTrust?: SurfaceTrust | undefined;
|
|
54
|
+
}>;
|
|
55
|
+
}) | null>;
|
|
56
|
+
export default _default;
|
|
57
|
+
//# sourceMappingURL=read_notion_comments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read_notion_comments.d.ts","sourceRoot":"","sources":["../../../agent/tools/read_notion_comments.ts"],"names":[],"mappings":"AA8CA,OAAO,EAYL,KAAK,YAAY,EAElB,MAAM,4CAA4C,CAAC;AA2CpD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;CAmIlC,CAAC"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// The comments/inline-discussion read tool for the ambient Notion surface — the SIBLING of
|
|
2
|
+
// read_notion_page (which returns the page BODY). The comment thread you were WOKEN on is already in
|
|
3
|
+
// context; this pulls the OTHER discussions on the page (a second commenter on another block, an
|
|
4
|
+
// older resolved argument the reply needs to reconcile) BY REFERENCE — fetched on demand, never
|
|
5
|
+
// inlined into the wake, so a heavily-annotated page can't blow the backscroll budget.
|
|
6
|
+
//
|
|
7
|
+
// SURFACE GATE + REPLAY DOCTRINE + UNTRUSTED WRAP: identical to read_notion_page.ts — a per-session
|
|
8
|
+
// dynamic resolver gated on `notion ∈ sources` (workerChatArmMount) with a per-turn origin fence
|
|
9
|
+
// (assertTurnSurface), a top-level factored defineTool (never an inline literal — the bundler's
|
|
10
|
+
// build-time transform hoists one under a build-order-counter name that shifts across deploys; eve
|
|
11
|
+
// derives a session-scoped step id for a factored, unstamped entry and self-heals it on cold resume,
|
|
12
|
+
// OPE-867), and NO `approval:` (read-only).
|
|
13
|
+
//
|
|
14
|
+
// DOMAIN FENCE (channels/notion-scope.ts, OPE-236): BOTH caller-supplied ids are gated — `page`, and
|
|
15
|
+
// `block`, which addresses a block directly and never touches `page` at all. Fail closed on either,
|
|
16
|
+
// and audit the refusal; the one deployment-wide credential fences the workspace, never the domain.
|
|
17
|
+
//
|
|
18
|
+
// Comment bodies are EXTERNAL, UNTRUSTED content (commenters include workspace guests / externals),
|
|
19
|
+
// so the whole rendered listing is wrapped through ingestUntrusted (toModelOutput) — the model must
|
|
20
|
+
// treat comment text as DATA, not instructions. Author ids are surfaced as DATA too, never as a
|
|
21
|
+
// trust signal.
|
|
22
|
+
//
|
|
23
|
+
// 🔴 THIS TOOL IS THE DELEGATED WORKER'S ONLY (OPE-1014). It has ONE mount arm — the chat arm — and
|
|
24
|
+
// that arm now mounts on the `task` grain alone (access/source-scoped-mount.ts `workerChatArmMount`).
|
|
25
|
+
// A conversational Notion seat reads the same comment layer through `read_channel` (channels/
|
|
26
|
+
// notion-read.ts), which sweeps every discussion on the page headed by its anchor block, a SUPERSET
|
|
27
|
+
// of what this tool returns, and `read_thread`, which reads the one discussion the turn is in. Since
|
|
28
|
+
// OPE-1039 the generic pair carries the OPE-1026 dated-read framing too — the `readAt` stamp, the
|
|
29
|
+
// per-line age and the HISTORY marker that stops the model reading a stale comment's claim as the
|
|
30
|
+
// page's present state — so the seat loses no safety framing by taking the generic route.
|
|
31
|
+
//
|
|
32
|
+
// The worker kept it because it had no substitute: access/worker-seat.ts withholds `read_channel` /
|
|
33
|
+
// `read_thread` from every delegated worker. That is no longer the whole story (OPE-1064): `WORK_ROLES`
|
|
34
|
+
// now gives Notion a CONTAINER row too, so a work-granted domain's delegated worker also holds the
|
|
35
|
+
// generic `read_work_channel` / `read_work_thread` pair, which the paragraph above already says
|
|
36
|
+
// SUPERSEDES this tool's own read (a superset via `read_channel`'s discussion sweep). This tool has
|
|
37
|
+
// no work arm of its own to fall back on, so the `task` grain is still its whole mount — it stays
|
|
38
|
+
// live for now because retiring a shipped tool is its own reviewed change (filed on OPE-1064), not
|
|
39
|
+
// a side effect of adding the neutral path beside it.
|
|
40
|
+
import { defineDynamic, defineTool } from "eve/tools";
|
|
41
|
+
import { z } from "zod";
|
|
42
|
+
import { readNotionComments, resolveBlockOwningPage, resolveNotionCredential } from "../channels/notion-api.js";
|
|
43
|
+
import { notionCallerCredential } from "../channels/notion-credentials.js";
|
|
44
|
+
import { assertNotionActingIdentity } from "../channels/notion-acting-identity.js";
|
|
45
|
+
import { assertNotionBlockAllowed, assertNotionPageAllowed } from "../channels/notion-scope.js";
|
|
46
|
+
import { ingestUntrustedModelOutput, assertTurnSurface, TurnOriginFenceError, auditOriginFenceRefusal, bindFrom, workerChatArmMount, getConfig, preRegisterDynamicEntry, resolvePartition, declaredWorkspaceTrust, ageAtRead, } from "@open-everywhere/core/agent/adapter-api.js";
|
|
47
|
+
const MAX_COMMENTS = 100;
|
|
48
|
+
const MAX_BLOCK_SCANS = 80;
|
|
49
|
+
/** Render the flattened comments into a human-readable, per-discussion listing. The WHOLE string is
|
|
50
|
+
* wrapped untrusted by toModelOutput, so bodies + author ids inside it are DATA.
|
|
51
|
+
*
|
|
52
|
+
* OPE-1026 — each line carries its age at the moment of the read (see {@link ageAtRead}), the same
|
|
53
|
+
* fact `read_linear_issue.ts` renders for Linear comments: the discriminator between "an old comment
|
|
54
|
+
* said X" and "X is true now". `readAt` is optional so a stored output from before this field
|
|
55
|
+
* existed still renders — with no invented age. */
|
|
56
|
+
function renderComments(comments, readAt) {
|
|
57
|
+
if (comments.length === 0)
|
|
58
|
+
return "";
|
|
59
|
+
// Group by anchor (block/page) → each anchor is a distinct inline discussion.
|
|
60
|
+
const byAnchor = new Map();
|
|
61
|
+
for (const c of comments) {
|
|
62
|
+
const key = c.anchorId ?? "(unknown)";
|
|
63
|
+
let list = byAnchor.get(key);
|
|
64
|
+
if (!list) {
|
|
65
|
+
list = [];
|
|
66
|
+
byAnchor.set(key, list);
|
|
67
|
+
}
|
|
68
|
+
list.push(c);
|
|
69
|
+
}
|
|
70
|
+
const sections = [];
|
|
71
|
+
for (const [anchor, list] of byAnchor) {
|
|
72
|
+
const disc = list.find((c) => c.discussionId)?.discussionId;
|
|
73
|
+
const head = `discussion on block ${anchor}${disc ? ` (discussion_id ${disc})` : ""}:`;
|
|
74
|
+
const lines = list.map((c) => {
|
|
75
|
+
const who = c.authorId ? `${c.authorKind ?? "user"} ${c.authorId}` : "unknown author";
|
|
76
|
+
const when = c.createdTime ? ` at ${c.createdTime}` : "";
|
|
77
|
+
const age = ageAtRead(c.createdTime, readAt);
|
|
78
|
+
const old = age ? ` (${age} before this read)` : "";
|
|
79
|
+
return ` - ${who}${when}${old}: ${c.text}`;
|
|
80
|
+
});
|
|
81
|
+
sections.push([head, ...lines].join("\n"));
|
|
82
|
+
}
|
|
83
|
+
return sections.join("\n\n");
|
|
84
|
+
}
|
|
85
|
+
// FACTORED + PRE-REGISTERED (see read_notion_page.ts / access/window-gated.ts REPLAY DOCTRINE).
|
|
86
|
+
// Exported for the unit test (its toModelOutput = the untrusted-wrap assertion).
|
|
87
|
+
export const readNotionCommentsEntry = defineTool({
|
|
88
|
+
description: "Read the comments / inline discussions on a Notion page (this doc, or another page shared with " +
|
|
89
|
+
"the integration). Use it when a reply needs OTHER discussions on the page — a comment on a " +
|
|
90
|
+
"different block, or an older thread — beyond the one you were woken on (already in context). " +
|
|
91
|
+
"Pass `block` to read just one block's inline discussion. Bounded; truncates a heavily-commented page.",
|
|
92
|
+
inputSchema: z.object({
|
|
93
|
+
page: z
|
|
94
|
+
.string()
|
|
95
|
+
.min(1)
|
|
96
|
+
.optional()
|
|
97
|
+
.describe("The Notion page id whose comments to read. Defaults to THIS doc — the page the comment you're on lives in."),
|
|
98
|
+
block: z
|
|
99
|
+
.string()
|
|
100
|
+
.min(1)
|
|
101
|
+
.optional()
|
|
102
|
+
.describe("Read ONLY this block's inline discussion (a block/page id), instead of sweeping the whole page."),
|
|
103
|
+
}),
|
|
104
|
+
outputSchema: z.object({
|
|
105
|
+
page: z.string(),
|
|
106
|
+
discussions: z.number(),
|
|
107
|
+
comments: z.number(),
|
|
108
|
+
blocksScanned: z.number(),
|
|
109
|
+
truncated: z.boolean(),
|
|
110
|
+
text: z.string(),
|
|
111
|
+
// OPE-1026 — the moment the comments below were fetched, stamped by `execute` and carried to
|
|
112
|
+
// `toModelOutput`. Optional because `toModelOutput` also runs over outputs stored before this
|
|
113
|
+
// field existed; the render drops the read-time line rather than inventing one (see
|
|
114
|
+
// read_linear_issue.ts's `readAt`, the pattern this copies).
|
|
115
|
+
readAt: z.string().optional(),
|
|
116
|
+
// OPE-331 — the bound workspace's declared tier, carried execute → toModelOutput. Same shape and
|
|
117
|
+
// same reasoning as read_notion_page's field; model-invisible behind the authored projection.
|
|
118
|
+
workspaceTrust: z.enum(["internal", "public"]).optional(),
|
|
119
|
+
}),
|
|
120
|
+
// NO `approval:` — read-only; a dynamic-tool approval fn fails a resumed session's replay lookup
|
|
121
|
+
// (same pin read_notion_page / access/window-gated.ts document). Absent approval === never() is correct.
|
|
122
|
+
async execute(input, ctx2) {
|
|
123
|
+
// Per-turn surface fence (finding 1b): a non-Notion-origin turn on a unified window must not read
|
|
124
|
+
// Notion comments even though the tool is armed for the session.
|
|
125
|
+
// OPE-732: the fence's refusal is audited here (see read_notion_page.ts's note).
|
|
126
|
+
try {
|
|
127
|
+
assertTurnSurface(ctx2, "notion");
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
if (err instanceof TurnOriginFenceError)
|
|
131
|
+
await auditOriginFenceRefusal(ctx2, "notion");
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
// Default to THIS session's page (bindFrom(ctx).surface = the page id for Notion).
|
|
135
|
+
const page = input.page ?? bindFrom(ctx2).surface;
|
|
136
|
+
if (!page)
|
|
137
|
+
throw new Error("No Notion page id available for this session — pass `page` explicitly.");
|
|
138
|
+
// DOMAIN FENCE (OPE-236) — see read_notion_page.ts and channels/notion-scope.ts. The one
|
|
139
|
+
// deployment-wide integration key bounds the WORKSPACE, not the domain, so the domain allowlist
|
|
140
|
+
// is ours to enforce: fail closed on an unresolvable page, audit every refusal.
|
|
141
|
+
const domains = getConfig().loadDomains();
|
|
142
|
+
await assertNotionPageAllowed(ctx2, page, domains);
|
|
143
|
+
// OPE-467 / OPE-499 — the carried delivery credential decides, when one is present; the CALLING
|
|
144
|
+
// domain's own binding is the fallback (see read_notion_page.ts / notion-credentials.ts).
|
|
145
|
+
// OPE-505: `cred` is the key AND its endpoint rules; spreading it carries the fence into every
|
|
146
|
+
// REST call below (notion-api.ts funnels them all through one guarded fetch).
|
|
147
|
+
// 🔴 OPE-1525 — THE OWN-ACCOUNT GATE, on the line below's behalf. `notionCallerCredential`
|
|
148
|
+
// resolves an `install`-family key, so a member who asked to act with THEIR OWN Notion account
|
|
149
|
+
// has no answer here. This tool is the DELEGATED WORKER's own arm — the grain the live
|
|
150
|
+
// substitution ran in — so leaving it ungated while `read_notion_page` is gated would move the
|
|
151
|
+
// defect one verb along. The gate refuses that turn and writes the `connector.acting_identity`
|
|
152
|
+
// row either way; see channels/notion-acting-identity.ts.
|
|
153
|
+
await assertNotionActingIdentity(ctx2, "read_notion_comments");
|
|
154
|
+
const cred = await resolveNotionCredential(notionCallerCredential(ctx2, domains));
|
|
155
|
+
if (!cred)
|
|
156
|
+
throw new Error("no value stored under db:notion:channel-key — cannot read the comments.");
|
|
157
|
+
// `block` NEEDS ITS OWN GATE: the drill-in addresses the block directly and never touches `page`
|
|
158
|
+
// (notion-api.ts readNotionComments returns early on it), so fencing `page` alone would leave the
|
|
159
|
+
// whole fence bypassable in one argument. Costs one `GET /v1/blocks/{id}` only when the block
|
|
160
|
+
// isn't already in scope by id — the common case (a top-level block of this very page) still
|
|
161
|
+
// pays it, which is the honest price of not trusting a caller-supplied id.
|
|
162
|
+
if (input.block) {
|
|
163
|
+
await assertNotionBlockAllowed(ctx2, input.block, domains, (id) => resolveBlockOwningPage(id, { ...cred }));
|
|
164
|
+
}
|
|
165
|
+
const res = await readNotionComments(page, {
|
|
166
|
+
...cred,
|
|
167
|
+
block: input.block,
|
|
168
|
+
maxComments: MAX_COMMENTS,
|
|
169
|
+
maxBlockScans: MAX_BLOCK_SCANS,
|
|
170
|
+
});
|
|
171
|
+
// OPE-1026 — the moment the fetch above returned. Stamped AFTER the fetch, so it never claims a
|
|
172
|
+
// read is fresher than it is (see read_linear_issue.ts's `readAt`).
|
|
173
|
+
const readAt = new Date().toISOString();
|
|
174
|
+
// OPE-331 — resolve the workspace tier where a ctx exists; fail-soft to absent (the table's
|
|
175
|
+
// pre-existing fail-closed answer).
|
|
176
|
+
let workspaceTrust;
|
|
177
|
+
try {
|
|
178
|
+
workspaceTrust = declaredWorkspaceTrust(resolvePartition(ctx2).workspaceKey);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
workspaceTrust = undefined;
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
page,
|
|
185
|
+
discussions: res.discussionCount,
|
|
186
|
+
comments: res.comments.length,
|
|
187
|
+
blocksScanned: res.blocksScanned,
|
|
188
|
+
truncated: res.truncated,
|
|
189
|
+
text: renderComments(res.comments, readAt),
|
|
190
|
+
readAt,
|
|
191
|
+
...(workspaceTrust !== undefined ? { workspaceTrust } : {}),
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
toModelOutput(output) {
|
|
195
|
+
const header = output.comments === 0
|
|
196
|
+
? `Notion page ${output.page} has no readable comments.`
|
|
197
|
+
: `Notion page ${output.page} — ${output.comments} comment(s) across ${output.discussions} discussion(s):`;
|
|
198
|
+
const suffix = output.truncated ? "\n\n[truncated — the page has more comments/blocks than shown]" : "";
|
|
199
|
+
// OPE-1026 — THE PROVENANCE LINE, only when there is comment text to date (Linear's pattern,
|
|
200
|
+
// §OPE-1012): the comments above are dated against THIS read, and a comment's claim about status
|
|
201
|
+
// or approval is HISTORY, not the page's current state. `read_notion_page` is the tool that reads
|
|
202
|
+
// the page's current content — this one never claims to.
|
|
203
|
+
const asOf = output.comments > 0 && output.readAt
|
|
204
|
+
? `\n\nRead live at ${output.readAt}: the comments above are HISTORY, each dated against this read. A comment's claim about status, approval or progress is not the page's current state — read the page itself (read_notion_page) for that.`
|
|
205
|
+
: "";
|
|
206
|
+
const body = output.comments === 0 ? header : `${header}\n${output.text}${suffix}${asOf}`;
|
|
207
|
+
// OPE-324 — `workspaceTrust` (plumbed OPE-331) is the DECISION here, same route and same meaning
|
|
208
|
+
// as read_notion_page's (see its note): a vouched-internal workspace fences without tainting, an
|
|
209
|
+
// unvouched one falls closed and taints, and the `assumed` flag says the operator never vouched
|
|
210
|
+
// it rather than that OE could not look.
|
|
211
|
+
return ingestUntrustedModelOutput(body, {
|
|
212
|
+
source: `notion comments ${output.page}`,
|
|
213
|
+
ingestion: {
|
|
214
|
+
kind: "notion",
|
|
215
|
+
label: "read_notion_comments",
|
|
216
|
+
...(output.workspaceTrust !== undefined ? { workspaceTrust: output.workspaceTrust } : {}),
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
preRegisterDynamicEntry("read_notion_comments", "_single", readNotionCommentsEntry);
|
|
222
|
+
export default defineDynamic({
|
|
223
|
+
events: {
|
|
224
|
+
// session.started ONLY: a session runs on exactly one surface (see read_notion_page.ts).
|
|
225
|
+
"session.started": (_event, ctx) => {
|
|
226
|
+
// THE CHAT ARM (§A5), narrowed to the DELEGATED-WORKER grain by OPE-1014: mount iff `notion ∈`
|
|
227
|
+
// this window's sources AND the grain is `task`. This tool has NO work arm, so `task` is its whole
|
|
228
|
+
// mount: a conversational Notion seat reads the same comment layer through the generic
|
|
229
|
+
// `read_channel` / `read_thread`, which sweep a superset of what this tool returns.
|
|
230
|
+
if (!workerChatArmMount(ctx, "notion", () => getConfig().loadDomains()))
|
|
231
|
+
return null;
|
|
232
|
+
return readNotionCommentsEntry;
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
//# sourceMappingURL=read_notion_comments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read_notion_comments.js","sourceRoot":"","sources":["../../../agent/tools/read_notion_comments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type SurfaceTrust } from "@open-everywhere/core/agent/adapter-api.js";
|
|
2
|
+
export declare const readNotionPageEntry: import("eve/tools").ToolDefinition<{
|
|
3
|
+
page?: string | undefined;
|
|
4
|
+
}, {
|
|
5
|
+
page: string;
|
|
6
|
+
title?: string | undefined;
|
|
7
|
+
url?: string | undefined;
|
|
8
|
+
blocks: number;
|
|
9
|
+
truncated: boolean;
|
|
10
|
+
text: string;
|
|
11
|
+
readAt?: string | undefined;
|
|
12
|
+
workspaceTrust?: "internal" | "public" | undefined;
|
|
13
|
+
}> & {
|
|
14
|
+
execute(input: {
|
|
15
|
+
page?: string | undefined;
|
|
16
|
+
}, ctx: import("eve/tools").ToolContext): Promise<{
|
|
17
|
+
page: string;
|
|
18
|
+
title?: string | undefined;
|
|
19
|
+
url?: string | undefined;
|
|
20
|
+
blocks: number;
|
|
21
|
+
truncated: boolean;
|
|
22
|
+
text: string;
|
|
23
|
+
readAt: string;
|
|
24
|
+
workspaceTrust?: SurfaceTrust | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
};
|
|
27
|
+
declare const _default: import("eve/tools").DynamicSentinel<(import("eve/tools").ToolDefinition<{
|
|
28
|
+
page?: string | undefined;
|
|
29
|
+
}, {
|
|
30
|
+
page: string;
|
|
31
|
+
title?: string | undefined;
|
|
32
|
+
url?: string | undefined;
|
|
33
|
+
blocks: number;
|
|
34
|
+
truncated: boolean;
|
|
35
|
+
text: string;
|
|
36
|
+
readAt?: string | undefined;
|
|
37
|
+
workspaceTrust?: "internal" | "public" | undefined;
|
|
38
|
+
}> & {
|
|
39
|
+
execute(input: {
|
|
40
|
+
page?: string | undefined;
|
|
41
|
+
}, ctx: import("eve/tools").ToolContext): Promise<{
|
|
42
|
+
page: string;
|
|
43
|
+
title?: string | undefined;
|
|
44
|
+
url?: string | undefined;
|
|
45
|
+
blocks: number;
|
|
46
|
+
truncated: boolean;
|
|
47
|
+
text: string;
|
|
48
|
+
readAt: string;
|
|
49
|
+
workspaceTrust?: SurfaceTrust | undefined;
|
|
50
|
+
}>;
|
|
51
|
+
}) | null>;
|
|
52
|
+
export default _default;
|
|
53
|
+
//# sourceMappingURL=read_notion_page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read_notion_page.d.ts","sourceRoot":"","sources":["../../../agent/tools/read_notion_page.ts"],"names":[],"mappings":"AAsDA,OAAO,EAYL,KAAK,YAAY,EAElB,MAAM,4CAA4C,CAAC;AAYpD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;CAqP9B,CAAC"}
|