@pome-sh/cli 0.7.0 → 0.9.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/dist/build-info.json +3 -3
- package/dist/src/cli/agent-identity.js +7 -2
- package/dist/src/cli/compile-seeds.js +51 -5
- package/dist/src/cli/docs-topics.js +5 -3
- package/dist/src/cli/main.js +21 -11
- package/dist/src/cli/project-config.d.ts +8 -0
- package/dist/src/cli/project-config.js +18 -0
- package/dist/src/cli/register.d.ts +15 -0
- package/dist/src/cli/register.js +26 -3
- package/dist/src/cli/session.d.ts +10 -0
- package/dist/src/cli/session.js +28 -2
- package/dist/src/fix-prompt/index.d.ts +1 -1
- package/dist/src/fix-prompt/index.js +2 -2
- package/dist/src/fix-prompt/prompt.d.ts +2 -2
- package/dist/src/fix-prompt/prompt.js +9 -9
- package/dist/src/hosted/client.d.ts +8 -2
- package/dist/src/hosted/client.js +108 -26
- package/dist/src/hosted/errors.d.ts +14 -0
- package/dist/src/hosted/errors.js +22 -0
- package/dist/src/hosted/evalResultCache.d.ts +4 -4
- package/dist/src/hosted/evalResultCache.js +10 -3
- package/dist/src/recorder/artifacts.d.ts +1 -1
- package/dist/src/recorder/artifacts.js +8 -1
- package/dist/src/runner/runTask.d.ts +14 -0
- package/dist/src/runner/runTaskHosted.js +9 -2
- package/dist/src/runner/runTrialGroup.js +4 -1
- package/dist/src/task/taskSchema.d.ts +52 -16
- package/node_modules/@pome-sh/shared-types/dist/seed-state.d.ts +27 -0
- package/node_modules/@pome-sh/shared-types/dist/seed-state.js +12 -0
- package/node_modules/@pome-sh/shared-types/dist/seed-state.js.map +1 -1
- package/node_modules/@pome-sh/shared-types/dist/task.d.ts +18 -0
- package/node_modules/@pome-sh/shared-types/package.json +1 -1
- package/node_modules/@pome-sh/shared-types/trace-contract.json +1 -1
- package/node_modules/@pome-sh/twin-gmail/CHANGELOG.md +21 -0
- package/node_modules/@pome-sh/twin-gmail/HOSTED.md +37 -15
- package/node_modules/@pome-sh/twin-gmail/LIMITS.md +10 -0
- package/node_modules/@pome-sh/twin-gmail/README.md +52 -11
- package/node_modules/@pome-sh/twin-gmail/dist/fixtures/mcp-tools-list.canonical.json +242 -7
- package/node_modules/@pome-sh/twin-gmail/dist/src/db.js +6 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/db.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.d.ts +41 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.js +138 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/drafts.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/filters.d.ts +10 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/{domain-search.js → domain/filters.js} +52 -36
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/filters.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/{domain.d.ts → domain/gmail-domain.d.ts} +45 -34
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/gmail-domain.js +174 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/gmail-domain.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.d.ts +8 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.js +122 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/hydrate.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.d.ts +4 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.js +5 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/index.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.d.ts +40 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.js +122 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/labels.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.d.ts +49 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.js +276 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/messages.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.d.ts +19 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.js +179 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/search-sql.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.d.ts +27 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.js +98 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain/settings.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/errors.js +2 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/errors.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/faults.d.ts +21 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/faults.js +52 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/faults.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/identity.d.ts +1 -6
- package/node_modules/@pome-sh/twin-gmail/dist/src/identity.js +0 -11
- package/node_modules/@pome-sh/twin-gmail/dist/src/identity.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/index.d.ts +4 -3
- package/node_modules/@pome-sh/twin-gmail/dist/src/index.js +3 -3
- package/node_modules/@pome-sh/twin-gmail/dist/src/index.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.d.ts +48 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.js +23 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/mcp-schemas.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.d.ts +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.js +39 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/mcp.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-drafts.js +4 -5
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-drafts.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.d.ts +2 -3
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.js +4 -4
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-kit.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-messages.js +7 -8
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-messages.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-resources.js +20 -21
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes-resources.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-routes.d.ts +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.d.ts +2 -4
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.js +4 -6
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-serializers.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.d.ts +4 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.js +179 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/search-match.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.d.ts +61 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.js +318 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/search-parse.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/search.d.ts +3 -61
- package/node_modules/@pome-sh/twin-gmail/dist/src/search.js +2 -503
- package/node_modules/@pome-sh/twin-gmail/dist/src/search.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/seed.d.ts +13 -4
- package/node_modules/@pome-sh/twin-gmail/dist/src/seed.js +3 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/seed.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/server.js +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/server.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/storage.js +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/storage.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/twin.d.ts +2 -3
- package/node_modules/@pome-sh/twin-gmail/dist/src/twin.js +1 -4
- package/node_modules/@pome-sh/twin-gmail/dist/src/twin.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/types.d.ts +1 -0
- package/node_modules/@pome-sh/twin-gmail/fidelity.inventory.json +42 -435
- package/node_modules/@pome-sh/twin-gmail/fixtures/README.md +4 -4
- package/node_modules/@pome-sh/twin-gmail/fixtures/mcp-tools-list.canonical.json +242 -7
- package/node_modules/@pome-sh/twin-gmail/fixtures/mcp-tools-list.meta.json +3 -3
- package/node_modules/@pome-sh/twin-gmail/package.json +3 -2
- package/node_modules/hono/dist/cjs/client/utils.js +1 -1
- package/node_modules/hono/dist/cjs/helper/streaming/sse.js +5 -4
- package/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/compress/index.js +2 -1
- package/node_modules/hono/dist/cjs/middleware/method-override/index.js +5 -3
- package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +10 -4
- package/node_modules/hono/dist/cjs/request.js +8 -3
- package/node_modules/hono/dist/cjs/utils/accept.js +1 -1
- package/node_modules/hono/dist/cjs/utils/body.js +6 -0
- package/node_modules/hono/dist/cjs/utils/url.js +1 -1
- package/node_modules/hono/dist/client/utils.js +1 -1
- package/node_modules/hono/dist/helper/streaming/sse.js +5 -4
- package/node_modules/hono/dist/middleware/cache/index.js +1 -1
- package/node_modules/hono/dist/middleware/compress/index.js +2 -1
- package/node_modules/hono/dist/middleware/method-override/index.js +5 -3
- package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +10 -4
- package/node_modules/hono/dist/request.js +8 -3
- package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
- package/node_modules/hono/dist/types/helper/websocket/index.d.ts +1 -1
- package/node_modules/hono/dist/types/middleware/combine/index.d.ts +1 -1
- package/node_modules/hono/dist/utils/accept.js +1 -1
- package/node_modules/hono/dist/utils/body.js +6 -0
- package/node_modules/hono/dist/utils/url.js +1 -1
- package/node_modules/hono/package.json +3 -3
- package/package.json +3 -3
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain-search.d.ts +0 -5
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain-search.js.map +0 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain.js +0 -407
- package/node_modules/@pome-sh/twin-gmail/dist/src/domain.js.map +0 -1
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.d.ts +0 -75
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.js +0 -282
- package/node_modules/@pome-sh/twin-gmail/dist/src/rest-store.js.map +0 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { invalidArgument } from "./errors.js";
|
|
3
|
+
import { assertHasOperator, CATEGORY_LABELS, KNOWN_FIELDS, parseDate, parseDuration, parseSize, } from "./search-parse.js";
|
|
4
|
+
export function matchesSearch(node, document, nowMs = Date.now()) {
|
|
5
|
+
switch (node.type) {
|
|
6
|
+
case "and":
|
|
7
|
+
return node.children.every((child) => matchesSearch(child, document, nowMs));
|
|
8
|
+
case "or":
|
|
9
|
+
return node.children.some((child) => matchesSearch(child, document, nowMs));
|
|
10
|
+
case "not":
|
|
11
|
+
return !matchesSearch(node.child, document, nowMs);
|
|
12
|
+
case "around":
|
|
13
|
+
return matchesAround(searchable(document), node.left, node.right, node.distance);
|
|
14
|
+
case "term":
|
|
15
|
+
return matchesTerm(node.field, node.value, node.exact === true, document, nowMs);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function matchesTerm(field, rawValue, exact, document, nowMs) {
|
|
19
|
+
const value = rawValue.toLocaleLowerCase("en-US");
|
|
20
|
+
const contains = (candidate) => matchText(candidate, value, exact);
|
|
21
|
+
if (!field)
|
|
22
|
+
return contains(searchable(document));
|
|
23
|
+
if (!KNOWN_FIELDS.has(field)) {
|
|
24
|
+
invalidArgument(`Unsupported search operator: ${field}`);
|
|
25
|
+
}
|
|
26
|
+
if (field === "from")
|
|
27
|
+
return contains(document.from);
|
|
28
|
+
if (field === "to")
|
|
29
|
+
return document.to.some(contains);
|
|
30
|
+
if (field === "cc")
|
|
31
|
+
return document.cc.some(contains);
|
|
32
|
+
if (field === "bcc")
|
|
33
|
+
return document.bcc.some(contains);
|
|
34
|
+
if (field === "deliveredto")
|
|
35
|
+
return contains(document.deliveredTo);
|
|
36
|
+
if (field === "list") {
|
|
37
|
+
return document.headers.some((header) => header.name.toLowerCase() === "list-id" && contains(header.value));
|
|
38
|
+
}
|
|
39
|
+
if (field === "subject")
|
|
40
|
+
return contains(document.subject);
|
|
41
|
+
if (field === "rfc822msgid")
|
|
42
|
+
return normalizeMessageId(document.rfcMessageId) === normalizeMessageId(value);
|
|
43
|
+
if (field === "filename") {
|
|
44
|
+
return document.attachmentNames.some(contains) || document.attachmentMimeTypes.some(contains);
|
|
45
|
+
}
|
|
46
|
+
if (field === "after" || field === "newer")
|
|
47
|
+
return document.dateMs > parseDate(value);
|
|
48
|
+
if (field === "before" || field === "older")
|
|
49
|
+
return document.dateMs < parseDate(value);
|
|
50
|
+
if (field === "newer_than")
|
|
51
|
+
return document.dateMs > nowMs - parseDuration(value);
|
|
52
|
+
if (field === "older_than")
|
|
53
|
+
return document.dateMs < nowMs - parseDuration(value);
|
|
54
|
+
if (field === "size")
|
|
55
|
+
return document.size === parseSize(value);
|
|
56
|
+
if (field === "larger")
|
|
57
|
+
return document.size > parseSize(value);
|
|
58
|
+
if (field === "smaller")
|
|
59
|
+
return document.size < parseSize(value);
|
|
60
|
+
if (field === "label")
|
|
61
|
+
return hasLabel(document, value);
|
|
62
|
+
if (field === "category")
|
|
63
|
+
return matchesCategory(value, document);
|
|
64
|
+
if (field === "in")
|
|
65
|
+
return matchesFolder(value, document);
|
|
66
|
+
if (field === "is")
|
|
67
|
+
return matchesStatus(value, document);
|
|
68
|
+
if (field === "has")
|
|
69
|
+
return matchesHas(value, document);
|
|
70
|
+
invalidArgument(`Unsupported search operator: ${field}`);
|
|
71
|
+
}
|
|
72
|
+
function matchesCategory(value, document) {
|
|
73
|
+
const mapped = CATEGORY_LABELS[value.toLocaleLowerCase("en-US")];
|
|
74
|
+
if (!mapped)
|
|
75
|
+
invalidArgument(`Unsupported search category: ${value}`);
|
|
76
|
+
return hasLabel(document, mapped);
|
|
77
|
+
}
|
|
78
|
+
function matchesFolder(value, document) {
|
|
79
|
+
if (value === "anywhere")
|
|
80
|
+
return true;
|
|
81
|
+
if (value === "archive")
|
|
82
|
+
return !hasLabel(document, "inbox");
|
|
83
|
+
if (value === "draft")
|
|
84
|
+
return hasLabel(document, "draft");
|
|
85
|
+
return hasLabel(document, value);
|
|
86
|
+
}
|
|
87
|
+
function matchesStatus(value, document) {
|
|
88
|
+
if (value === "read")
|
|
89
|
+
return !hasLabel(document, "unread");
|
|
90
|
+
if (value === "unread")
|
|
91
|
+
return hasLabel(document, "unread");
|
|
92
|
+
if (value === "starred")
|
|
93
|
+
return hasLabel(document, "starred");
|
|
94
|
+
if (value === "important")
|
|
95
|
+
return hasLabel(document, "important");
|
|
96
|
+
if (value === "muted")
|
|
97
|
+
return hasLabel(document, "muted");
|
|
98
|
+
return hasLabel(document, value);
|
|
99
|
+
}
|
|
100
|
+
function matchesHas(value, document) {
|
|
101
|
+
const normalized = value.toLocaleLowerCase("en-US");
|
|
102
|
+
assertHasOperator(normalized);
|
|
103
|
+
if (normalized === "attachment")
|
|
104
|
+
return document.attachmentNames.length > 0;
|
|
105
|
+
if (normalized === "userlabels")
|
|
106
|
+
return document.userLabelCount > 0;
|
|
107
|
+
if (normalized === "nouserlabels")
|
|
108
|
+
return document.userLabelCount === 0;
|
|
109
|
+
if (normalized === "youtube")
|
|
110
|
+
return /youtube\.com|youtu\.be/i.test(searchable(document));
|
|
111
|
+
if (["drive", "document"].includes(normalized)) {
|
|
112
|
+
return /drive\.google\.com|docs\.google\.com/i.test(searchable(document));
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
function hasLabel(document, value) {
|
|
117
|
+
const normalized = value.toLocaleLowerCase("en-US");
|
|
118
|
+
return document.labels.some((label) => label.toLocaleLowerCase("en-US") === normalized);
|
|
119
|
+
}
|
|
120
|
+
function searchable(document) {
|
|
121
|
+
// Strip tags with a linear scan — avoid backtracking regex on hostile HTML.
|
|
122
|
+
const htmlText = stripHtmlTags(document.html);
|
|
123
|
+
return [
|
|
124
|
+
document.from,
|
|
125
|
+
...document.to,
|
|
126
|
+
...document.cc,
|
|
127
|
+
...document.bcc,
|
|
128
|
+
document.subject,
|
|
129
|
+
document.text,
|
|
130
|
+
htmlText,
|
|
131
|
+
...document.attachmentNames,
|
|
132
|
+
].join(" ");
|
|
133
|
+
}
|
|
134
|
+
/** Linear HTML tag strip — safe for untrusted MIME (no ReDoS). */
|
|
135
|
+
export function stripHtmlTags(value) {
|
|
136
|
+
let out = "";
|
|
137
|
+
let inTag = false;
|
|
138
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
139
|
+
const char = value[index];
|
|
140
|
+
if (char === "<") {
|
|
141
|
+
inTag = true;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (char === ">" && inTag) {
|
|
145
|
+
inTag = false;
|
|
146
|
+
out += " ";
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (!inTag)
|
|
150
|
+
out += char;
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
function matchText(candidate, value, exact) {
|
|
155
|
+
const haystack = candidate.toLocaleLowerCase("en-US");
|
|
156
|
+
if (!exact)
|
|
157
|
+
return haystack.includes(value);
|
|
158
|
+
const pattern = new RegExp(`(?:^|[^\\p{L}\\p{N}])${escapeRegExp(value)}(?:$|[^\\p{L}\\p{N}])`, "iu");
|
|
159
|
+
return value.includes(" ") ? haystack.includes(value) : pattern.test(haystack);
|
|
160
|
+
}
|
|
161
|
+
function matchesAround(text, left, right, distance) {
|
|
162
|
+
const words = text.toLocaleLowerCase("en-US").split(/[^\p{L}\p{N}@._+-]+/u);
|
|
163
|
+
const leftValue = left.toLocaleLowerCase("en-US");
|
|
164
|
+
const rightValue = right.toLocaleLowerCase("en-US");
|
|
165
|
+
const leftIndexes = words.flatMap((word, index) => (word === leftValue ? [index] : []));
|
|
166
|
+
return leftIndexes.some((index) => words.slice(Math.max(0, index - distance), index + distance + 1).includes(rightValue));
|
|
167
|
+
}
|
|
168
|
+
function normalizeMessageId(value) {
|
|
169
|
+
let normalized = value.trim();
|
|
170
|
+
if (normalized.startsWith("<"))
|
|
171
|
+
normalized = normalized.slice(1);
|
|
172
|
+
if (normalized.endsWith(">"))
|
|
173
|
+
normalized = normalized.slice(0, -1);
|
|
174
|
+
return normalized.toLowerCase();
|
|
175
|
+
}
|
|
176
|
+
function escapeRegExp(value) {
|
|
177
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=search-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-match.js","sourceRoot":"","sources":["../../src/search-match.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type SearchNode = {
|
|
2
|
+
type: "and";
|
|
3
|
+
children: SearchNode[];
|
|
4
|
+
} | {
|
|
5
|
+
type: "or";
|
|
6
|
+
children: SearchNode[];
|
|
7
|
+
} | {
|
|
8
|
+
type: "not";
|
|
9
|
+
child: SearchNode;
|
|
10
|
+
} | {
|
|
11
|
+
type: "term";
|
|
12
|
+
field?: string;
|
|
13
|
+
value: string;
|
|
14
|
+
exact?: boolean;
|
|
15
|
+
} | {
|
|
16
|
+
type: "around";
|
|
17
|
+
left: string;
|
|
18
|
+
right: string;
|
|
19
|
+
distance: number;
|
|
20
|
+
};
|
|
21
|
+
export type SearchDocument = {
|
|
22
|
+
from: string;
|
|
23
|
+
to: string[];
|
|
24
|
+
cc: string[];
|
|
25
|
+
bcc: string[];
|
|
26
|
+
deliveredTo: string;
|
|
27
|
+
subject: string;
|
|
28
|
+
text: string;
|
|
29
|
+
html: string;
|
|
30
|
+
dateMs: number;
|
|
31
|
+
rfcMessageId: string;
|
|
32
|
+
size: number;
|
|
33
|
+
labels: string[];
|
|
34
|
+
userLabelCount: number;
|
|
35
|
+
attachmentNames: string[];
|
|
36
|
+
attachmentMimeTypes: string[];
|
|
37
|
+
headers: Array<{
|
|
38
|
+
name: string;
|
|
39
|
+
value: string;
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Hard mailbox-size budget for the intentional in-memory search evaluator.
|
|
44
|
+
* Search hydrates semantic rows in process; exceeding this fails loudly before OOM.
|
|
45
|
+
*/
|
|
46
|
+
export declare const SEARCH_MAILBOX_MESSAGE_BUDGET = 10000;
|
|
47
|
+
/** Operators supported by the twin search grammar (unknowns are rejected). */
|
|
48
|
+
export declare const KNOWN_FIELDS: Set<string>;
|
|
49
|
+
/** Gmail `category:` aliases → system label ids. */
|
|
50
|
+
export declare const CATEGORY_LABELS: Record<string, string>;
|
|
51
|
+
/**
|
|
52
|
+
* Parse a Gmail query and reject operators/values that would throw at match time
|
|
53
|
+
* (unknown fields, categories, and invalid date/size/duration literals).
|
|
54
|
+
*/
|
|
55
|
+
export declare function validateSearchQuery(query: string): SearchNode;
|
|
56
|
+
export declare function assertSearchTerm(field: string | undefined, value: string): void;
|
|
57
|
+
export declare function parseSearchQuery(query: string): SearchNode;
|
|
58
|
+
export declare function assertHasOperator(value: string): void;
|
|
59
|
+
export declare function parseDate(value: string): number;
|
|
60
|
+
export declare function parseDuration(value: string): number;
|
|
61
|
+
export declare function parseSize(value: string): number;
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { invalidArgument } from "./errors.js";
|
|
3
|
+
const MAX_QUERY_BYTES = 4096;
|
|
4
|
+
const MAX_TOKENS = 256;
|
|
5
|
+
const MAX_DEPTH = 20;
|
|
6
|
+
const MAX_BRANCHES = 256;
|
|
7
|
+
/**
|
|
8
|
+
* Hard mailbox-size budget for the intentional in-memory search evaluator.
|
|
9
|
+
* Search hydrates semantic rows in process; exceeding this fails loudly before OOM.
|
|
10
|
+
*/
|
|
11
|
+
export const SEARCH_MAILBOX_MESSAGE_BUDGET = 10_000;
|
|
12
|
+
/** Operators supported by the twin search grammar (unknowns are rejected). */
|
|
13
|
+
export const KNOWN_FIELDS = new Set([
|
|
14
|
+
"from",
|
|
15
|
+
"to",
|
|
16
|
+
"cc",
|
|
17
|
+
"bcc",
|
|
18
|
+
"deliveredto",
|
|
19
|
+
"list",
|
|
20
|
+
"subject",
|
|
21
|
+
"rfc822msgid",
|
|
22
|
+
"filename",
|
|
23
|
+
"after",
|
|
24
|
+
"newer",
|
|
25
|
+
"before",
|
|
26
|
+
"older",
|
|
27
|
+
"newer_than",
|
|
28
|
+
"older_than",
|
|
29
|
+
"size",
|
|
30
|
+
"larger",
|
|
31
|
+
"smaller",
|
|
32
|
+
"label",
|
|
33
|
+
"category",
|
|
34
|
+
"in",
|
|
35
|
+
"is",
|
|
36
|
+
"has",
|
|
37
|
+
]);
|
|
38
|
+
/** Gmail `category:` aliases → system label ids. */
|
|
39
|
+
export const CATEGORY_LABELS = {
|
|
40
|
+
primary: "CATEGORY_PERSONAL",
|
|
41
|
+
personal: "CATEGORY_PERSONAL",
|
|
42
|
+
social: "CATEGORY_SOCIAL",
|
|
43
|
+
promotions: "CATEGORY_PROMOTIONS",
|
|
44
|
+
updates: "CATEGORY_UPDATES",
|
|
45
|
+
forums: "CATEGORY_FORUMS",
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Parse a Gmail query and reject operators/values that would throw at match time
|
|
49
|
+
* (unknown fields, categories, and invalid date/size/duration literals).
|
|
50
|
+
*/
|
|
51
|
+
export function validateSearchQuery(query) {
|
|
52
|
+
const node = parseSearchQuery(query);
|
|
53
|
+
const walk = (current) => {
|
|
54
|
+
switch (current.type) {
|
|
55
|
+
case "and":
|
|
56
|
+
case "or":
|
|
57
|
+
for (const child of current.children)
|
|
58
|
+
walk(child);
|
|
59
|
+
return;
|
|
60
|
+
case "not":
|
|
61
|
+
walk(current.child);
|
|
62
|
+
return;
|
|
63
|
+
case "around":
|
|
64
|
+
return;
|
|
65
|
+
case "term":
|
|
66
|
+
assertSearchTerm(current.field, current.value);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
walk(node);
|
|
71
|
+
return node;
|
|
72
|
+
}
|
|
73
|
+
export function assertSearchTerm(field, value) {
|
|
74
|
+
if (!field)
|
|
75
|
+
return;
|
|
76
|
+
if (!KNOWN_FIELDS.has(field)) {
|
|
77
|
+
invalidArgument(`Unsupported search operator: ${field}`);
|
|
78
|
+
}
|
|
79
|
+
if (field === "category") {
|
|
80
|
+
if (!CATEGORY_LABELS[value.toLocaleLowerCase("en-US")]) {
|
|
81
|
+
invalidArgument(`Unsupported search category: ${value}`);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (field === "after" || field === "newer" || field === "before" || field === "older") {
|
|
86
|
+
parseDate(value);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (field === "newer_than" || field === "older_than") {
|
|
90
|
+
parseDuration(value);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (field === "size" || field === "larger" || field === "smaller") {
|
|
94
|
+
parseSize(value);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (field === "has") {
|
|
98
|
+
assertHasOperator(value);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function parseSearchQuery(query) {
|
|
102
|
+
if (Buffer.byteLength(query) > MAX_QUERY_BYTES)
|
|
103
|
+
invalidArgument("Search query exceeds limit");
|
|
104
|
+
const tokens = tokenize(query);
|
|
105
|
+
if (tokens.length > MAX_TOKENS)
|
|
106
|
+
invalidArgument("Search query has too many tokens");
|
|
107
|
+
if (tokens.length === 0)
|
|
108
|
+
return { type: "and", children: [] };
|
|
109
|
+
let position = 0;
|
|
110
|
+
const parseExpression = (depth, stop) => {
|
|
111
|
+
if (depth > MAX_DEPTH)
|
|
112
|
+
invalidArgument("Search query nesting exceeds limit");
|
|
113
|
+
const alternatives = [];
|
|
114
|
+
let conjunction = [];
|
|
115
|
+
const flush = () => {
|
|
116
|
+
alternatives.push(conjunction.length === 1 ? conjunction[0] : { type: "and", children: conjunction });
|
|
117
|
+
conjunction = [];
|
|
118
|
+
};
|
|
119
|
+
while (position < tokens.length) {
|
|
120
|
+
const token = tokens[position];
|
|
121
|
+
if (stop && token.value === stop)
|
|
122
|
+
break;
|
|
123
|
+
if (token.value.toUpperCase() === "OR") {
|
|
124
|
+
position++;
|
|
125
|
+
if (!conjunction.length)
|
|
126
|
+
invalidArgument("OR requires a left expression");
|
|
127
|
+
flush();
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (token.value.toUpperCase() === "AND") {
|
|
131
|
+
position++;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
conjunction.push(parsePrimary(depth + 1));
|
|
135
|
+
}
|
|
136
|
+
if (conjunction.length)
|
|
137
|
+
flush();
|
|
138
|
+
if (!alternatives.length)
|
|
139
|
+
return { type: "and", children: [] };
|
|
140
|
+
return alternatives.length === 1 ? alternatives[0] : { type: "or", children: alternatives };
|
|
141
|
+
};
|
|
142
|
+
const parsePrimary = (depth) => {
|
|
143
|
+
const token = tokens[position++];
|
|
144
|
+
if (token.value === "(" || token.value === "{") {
|
|
145
|
+
const end = token.value === "(" ? ")" : "}";
|
|
146
|
+
const child = parseExpression(depth, end);
|
|
147
|
+
if (tokens[position]?.value !== end)
|
|
148
|
+
invalidArgument(`Unclosed ${token.value}`);
|
|
149
|
+
position++;
|
|
150
|
+
return token.value === "{" ? makeImplicitOr(child) : child;
|
|
151
|
+
}
|
|
152
|
+
if (token.value === ")" || token.value === "}")
|
|
153
|
+
invalidArgument(`Unexpected ${token.value}`);
|
|
154
|
+
let value = token.value;
|
|
155
|
+
let negate = false;
|
|
156
|
+
if (value === "-") {
|
|
157
|
+
negate = true;
|
|
158
|
+
const next = tokens[position++];
|
|
159
|
+
if (!next)
|
|
160
|
+
invalidArgument("Negation requires an expression");
|
|
161
|
+
position--;
|
|
162
|
+
const child = parsePrimary(depth + 1);
|
|
163
|
+
return { type: "not", child };
|
|
164
|
+
}
|
|
165
|
+
if (value.startsWith("-") && value.length > 1) {
|
|
166
|
+
negate = true;
|
|
167
|
+
value = value.slice(1);
|
|
168
|
+
}
|
|
169
|
+
const around = tokens[position]?.value.toUpperCase() === "AROUND";
|
|
170
|
+
if (around) {
|
|
171
|
+
position++;
|
|
172
|
+
const distance = Number(tokens[position++]?.value);
|
|
173
|
+
const right = tokens[position++]?.value;
|
|
174
|
+
if (!Number.isInteger(distance) || distance < 1 || distance > 100 || !right) {
|
|
175
|
+
invalidArgument("AROUND requires a distance and right term");
|
|
176
|
+
}
|
|
177
|
+
const node = { type: "around", left: value, right, distance };
|
|
178
|
+
return negate ? { type: "not", child: node } : node;
|
|
179
|
+
}
|
|
180
|
+
const colon = value.indexOf(":");
|
|
181
|
+
let node;
|
|
182
|
+
if (colon > 0) {
|
|
183
|
+
const field = value.slice(0, colon).toLowerCase();
|
|
184
|
+
let fieldValue = value.slice(colon + 1);
|
|
185
|
+
if (!fieldValue && (tokens[position]?.value === "(" || tokens[position]?.value === "{")) {
|
|
186
|
+
node = parseFieldGroup(field, depth + 1);
|
|
187
|
+
return negate ? { type: "not", child: node } : node;
|
|
188
|
+
}
|
|
189
|
+
if (!fieldValue && tokens[position] && !["AND", "OR", ")", "}"].includes(tokens[position].value.toUpperCase())) {
|
|
190
|
+
fieldValue = tokens[position++].value;
|
|
191
|
+
}
|
|
192
|
+
node = { type: "term", field, value: fieldValue, exact: token.quoted };
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
node = { type: "term", value: value.startsWith("+") ? value.slice(1) : value, exact: token.quoted || value.startsWith("+") };
|
|
196
|
+
}
|
|
197
|
+
return negate ? { type: "not", child: node } : node;
|
|
198
|
+
};
|
|
199
|
+
const parseFieldGroup = (field, depth) => {
|
|
200
|
+
if (depth > MAX_DEPTH)
|
|
201
|
+
invalidArgument("Search query nesting exceeds limit");
|
|
202
|
+
const opening = tokens[position++].value;
|
|
203
|
+
const end = opening === "(" ? ")" : "}";
|
|
204
|
+
const groups = [[]];
|
|
205
|
+
while (position < tokens.length && tokens[position].value !== end) {
|
|
206
|
+
const token = tokens[position++];
|
|
207
|
+
if (token.value.toUpperCase() === "OR") {
|
|
208
|
+
groups.push([]);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (token.value.toUpperCase() === "AND")
|
|
212
|
+
continue;
|
|
213
|
+
if (["(", "{", ")", "}"].includes(token.value))
|
|
214
|
+
invalidArgument("Nested field groups are unsupported");
|
|
215
|
+
let value = token.value;
|
|
216
|
+
let negate = false;
|
|
217
|
+
if (value.startsWith("-")) {
|
|
218
|
+
negate = true;
|
|
219
|
+
value = value.slice(1);
|
|
220
|
+
}
|
|
221
|
+
const term = { type: "term", field, value, exact: token.quoted };
|
|
222
|
+
groups.at(-1).push(negate ? { type: "not", child: term } : term);
|
|
223
|
+
}
|
|
224
|
+
if (tokens[position]?.value !== end)
|
|
225
|
+
invalidArgument(`Unclosed ${opening}`);
|
|
226
|
+
position++;
|
|
227
|
+
const nodes = groups.map((children) => children.length === 1 ? children[0] : { type: "and", children });
|
|
228
|
+
const useOr = opening === "{" || nodes.length > 1;
|
|
229
|
+
return useOr ? { type: "or", children: nodes } : nodes[0] ?? { type: "and", children: [] };
|
|
230
|
+
};
|
|
231
|
+
const root = parseExpression(0);
|
|
232
|
+
if (position !== tokens.length)
|
|
233
|
+
invalidArgument("Unexpected search token");
|
|
234
|
+
if (countBranches(root) > MAX_BRANCHES)
|
|
235
|
+
invalidArgument("Search query has too many branches");
|
|
236
|
+
return root;
|
|
237
|
+
}
|
|
238
|
+
export function assertHasOperator(value) {
|
|
239
|
+
const normalized = value.toLocaleLowerCase("en-US");
|
|
240
|
+
if (normalized.endsWith("-star")) {
|
|
241
|
+
invalidArgument(`Unsupported colored-star operator: has:${value}; twin maps only STARRED via is:starred`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
export function parseDate(value) {
|
|
245
|
+
const normalized = /^\d{4}\/\d{1,2}\/\d{1,2}$/.test(value) ? value.replaceAll("/", "-") : value;
|
|
246
|
+
const date = Date.parse(`${normalized}${/^\d{4}-\d/.test(normalized) ? "T00:00:00Z" : ""}`);
|
|
247
|
+
if (Number.isNaN(date))
|
|
248
|
+
invalidArgument(`Invalid search date: ${value}`);
|
|
249
|
+
return date;
|
|
250
|
+
}
|
|
251
|
+
export function parseDuration(value) {
|
|
252
|
+
const match = value.match(/^(\d+)([dmy])$/i);
|
|
253
|
+
if (!match)
|
|
254
|
+
invalidArgument(`Invalid search duration: ${value}`);
|
|
255
|
+
const units = { d: 86_400_000, m: 30 * 86_400_000, y: 365 * 86_400_000 };
|
|
256
|
+
return Number(match[1]) * units[match[2].toLowerCase()];
|
|
257
|
+
}
|
|
258
|
+
export function parseSize(value) {
|
|
259
|
+
const match = value.match(/^(\d+(?:\.\d+)?)([kmg])?$/i);
|
|
260
|
+
if (!match)
|
|
261
|
+
invalidArgument(`Invalid search size: ${value}`);
|
|
262
|
+
const scale = { k: 1024, m: 1024 ** 2, g: 1024 ** 3 };
|
|
263
|
+
return Math.floor(Number(match[1]) * (match[2] ? scale[match[2].toLowerCase()] : 1));
|
|
264
|
+
}
|
|
265
|
+
function countBranches(node) {
|
|
266
|
+
switch (node.type) {
|
|
267
|
+
case "and":
|
|
268
|
+
case "or":
|
|
269
|
+
return node.children.reduce((sum, child) => sum + countBranches(child), 0);
|
|
270
|
+
case "not":
|
|
271
|
+
return countBranches(node.child);
|
|
272
|
+
case "around":
|
|
273
|
+
case "term":
|
|
274
|
+
return 1;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function tokenize(query) {
|
|
278
|
+
const out = [];
|
|
279
|
+
let index = 0;
|
|
280
|
+
while (index < query.length) {
|
|
281
|
+
if (/\s/.test(query[index])) {
|
|
282
|
+
index++;
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
const char = query[index];
|
|
286
|
+
if ("(){}".includes(char)) {
|
|
287
|
+
out.push({ value: char });
|
|
288
|
+
index++;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
let value = "";
|
|
292
|
+
let quoted = false;
|
|
293
|
+
while (index < query.length && !/\s/.test(query[index]) && !"(){}".includes(query[index])) {
|
|
294
|
+
if (query[index] === '"') {
|
|
295
|
+
quoted = true;
|
|
296
|
+
index++;
|
|
297
|
+
while (index < query.length && query[index] !== '"') {
|
|
298
|
+
if (query[index] === "\\" && index + 1 < query.length)
|
|
299
|
+
index++;
|
|
300
|
+
value += query[index++];
|
|
301
|
+
}
|
|
302
|
+
if (query[index] !== '"')
|
|
303
|
+
invalidArgument("Unclosed search quote");
|
|
304
|
+
index++;
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
value += query[index++];
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (value)
|
|
311
|
+
out.push({ value, quoted });
|
|
312
|
+
}
|
|
313
|
+
return out;
|
|
314
|
+
}
|
|
315
|
+
function makeImplicitOr(node) {
|
|
316
|
+
return node.type === "and" ? { type: "or", children: node.children } : node;
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=search-parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-parse.js","sourceRoot":"","sources":["../../src/search-parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,61 +1,3 @@
|
|
|
1
|
-
export type SearchNode
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} | {
|
|
5
|
-
type: "or";
|
|
6
|
-
children: SearchNode[];
|
|
7
|
-
} | {
|
|
8
|
-
type: "not";
|
|
9
|
-
child: SearchNode;
|
|
10
|
-
} | {
|
|
11
|
-
type: "term";
|
|
12
|
-
field?: string;
|
|
13
|
-
value: string;
|
|
14
|
-
exact?: boolean;
|
|
15
|
-
} | {
|
|
16
|
-
type: "around";
|
|
17
|
-
left: string;
|
|
18
|
-
right: string;
|
|
19
|
-
distance: number;
|
|
20
|
-
};
|
|
21
|
-
export type SearchDocument = {
|
|
22
|
-
from: string;
|
|
23
|
-
to: string[];
|
|
24
|
-
cc: string[];
|
|
25
|
-
bcc: string[];
|
|
26
|
-
deliveredTo: string;
|
|
27
|
-
subject: string;
|
|
28
|
-
text: string;
|
|
29
|
-
html: string;
|
|
30
|
-
dateMs: number;
|
|
31
|
-
rfcMessageId: string;
|
|
32
|
-
size: number;
|
|
33
|
-
labels: string[];
|
|
34
|
-
userLabelCount: number;
|
|
35
|
-
attachmentNames: string[];
|
|
36
|
-
attachmentMimeTypes: string[];
|
|
37
|
-
headers: Array<{
|
|
38
|
-
name: string;
|
|
39
|
-
value: string;
|
|
40
|
-
}>;
|
|
41
|
-
};
|
|
42
|
-
/**
|
|
43
|
-
* Hard mailbox-size budget for the intentional in-memory search evaluator.
|
|
44
|
-
* Search hydrates semantic rows in process; exceeding this fails loudly before OOM.
|
|
45
|
-
* Parameterized SQL compile of the AST remains a dedicated follow-up.
|
|
46
|
-
*/
|
|
47
|
-
export declare const SEARCH_MAILBOX_MESSAGE_BUDGET = 10000;
|
|
48
|
-
/**
|
|
49
|
-
* Parse a Gmail query and reject operators/values that would throw at match time
|
|
50
|
-
* (unknown fields, categories, and invalid date/size/duration literals).
|
|
51
|
-
*/
|
|
52
|
-
export declare function validateSearchQuery(query: string): SearchNode;
|
|
53
|
-
export declare function parseSearchQuery(query: string): SearchNode;
|
|
54
|
-
export declare function matchesSearch(node: SearchNode, document: SearchDocument, nowMs?: number): boolean;
|
|
55
|
-
export declare function compileSearchToSql(mailboxId: number, node: SearchNode): {
|
|
56
|
-
sql: string;
|
|
57
|
-
params: unknown[];
|
|
58
|
-
predicate: (document: SearchDocument) => boolean;
|
|
59
|
-
};
|
|
60
|
-
/** Linear HTML tag strip — safe for untrusted MIME (no ReDoS). */
|
|
61
|
-
export declare function stripHtmlTags(value: string): string;
|
|
1
|
+
export type { SearchDocument, SearchNode } from "./search-parse.js";
|
|
2
|
+
export { CATEGORY_LABELS, KNOWN_FIELDS, SEARCH_MAILBOX_MESSAGE_BUDGET, assertHasOperator, assertSearchTerm, parseDate, parseDuration, parseSearchQuery, parseSize, validateSearchQuery, } from "./search-parse.js";
|
|
3
|
+
export { matchesSearch, stripHtmlTags } from "./search-match.js";
|