@notis_ai/cli 0.2.0-beta.191.1 → 0.2.0-beta.196.1
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/README.md +479 -80
- package/config/portal-route-roots.json +48 -0
- package/dist/agent-hooks/notis-agent-hook.mjs +29072 -2784
- package/dist/base-skills/notis-apps/SKILL.md +88 -67
- package/dist/base-skills/notis-apps/references/architecture.md +114 -167
- package/dist/base-skills/notis-apps/references/design.md +26 -107
- package/dist/base-skills/notis-apps/references/memory.md +58 -0
- package/dist/base-skills/notis-apps/references/reading.md +52 -74
- package/dist/base-skills/notis-apps/references/release.md +104 -142
- package/dist/base-skills/notis-apps/references/sdk.md +113 -60
- package/dist/base-skills/notis-apps/references/troubleshooting.md +22 -21
- package/dist/base-skills/notis-apps/references/views.md +142 -0
- package/dist/base-skills/notis-cli/SKILL.md +4 -4
- package/dist/base-skills/notis-cli/references/app-delivery.md +12 -11
- package/dist/base-skills/notis-cli/references/native-databases.md +6 -6
- package/dist/base-skills/notis-cli/references/tool-examples.md +4 -4
- package/dist/base-skills/notis-query/SKILL.md +34 -60
- package/dist/base-skills/notis-query/references/database-discovery.md +59 -69
- package/dist/base-skills/notis-query/references/documents.md +63 -50
- package/dist/base-skills/notis-query/references/query.md +57 -524
- package/dist/sdk/src/bundleModule.ts +79 -0
- package/dist/sdk/src/components/DocumentEditor.tsx +6 -3
- package/dist/sdk/src/components/DocumentPage.tsx +141 -0
- package/dist/sdk/src/components/RecordComponents.tsx +33 -0
- package/dist/sdk/src/components/RenderChartData.tsx +19 -0
- package/dist/sdk/src/config.ts +4 -26
- package/dist/sdk/src/documents.ts +2 -0
- package/dist/sdk/src/hooks/useAction.ts +28 -0
- package/dist/sdk/src/hooks/useCloudComputer.ts +35 -4
- package/dist/sdk/src/hooks/useCloudComputerShell.ts +114 -0
- package/dist/sdk/src/hooks/useHandover.ts +5 -4
- package/dist/sdk/src/hooks/useNativeDocumentBody.ts +50 -0
- package/dist/sdk/src/hooks/useNativeDocuments.ts +83 -0
- package/dist/sdk/src/hooks/useNotis.ts +3 -0
- package/dist/sdk/src/hooks/useNotisNavigation.ts +26 -11
- package/dist/sdk/src/hooks/useQuery.ts +7 -4
- package/dist/sdk/src/hooks/useViewParams.ts +121 -0
- package/dist/sdk/src/hooks/useViewerReads.ts +129 -0
- package/dist/sdk/src/index.ts +36 -0
- package/dist/sdk/src/interactions/shortcuts.tsx +17 -3
- package/dist/sdk/src/nativeData.ts +39 -0
- package/dist/sdk/src/presentation.tsx +82 -0
- package/dist/sdk/src/provider.tsx +9 -4
- package/dist/sdk/src/queryCache.ts +5 -3
- package/dist/sdk/src/queryErrors.ts +51 -0
- package/dist/sdk/src/runtime.ts +146 -8
- package/dist/sdk/src/space.ts +425 -0
- package/dist/sdk/src/styles.css +96 -72
- package/dist/sdk/src/vite.ts +11 -1
- package/dist/skill-sync/index.js +458 -68
- package/dist/skill-sync/index.js.map +4 -4
- package/dist/skill-sync-worker.mjs +451 -77
- package/dist/space-harness/host.js +66 -0
- package/dist/view-renderer/dist/host.css +1 -0
- package/dist/view-renderer/dist/host.js +1042 -0
- package/dist/view-renderer/dist/theme.css +73 -0
- package/dist/view-renderer/src/dom.js +180 -0
- package/dist/view-renderer/src/errors.js +8 -0
- package/dist/view-renderer/src/host.tsx +173 -0
- package/dist/view-renderer/src/index.js +4 -0
- package/dist/view-renderer/src/pool.js +76 -0
- package/dist/view-renderer/src/remote-broker.js +59 -0
- package/dist/view-renderer/src/renderer.js +201 -0
- package/package.json +11 -5
- package/skills/notis-apps/cli.md +270 -163
- package/skills/notis-cli/AGENT_INSTRUCTIONS.md +2 -2
- package/skills/notis-onboarding/BRIEF.md +7 -3
- package/src/command-specs/apps.js +1 -8
- package/src/command-specs/files.js +29 -0
- package/src/command-specs/helpers.js +1 -0
- package/src/command-specs/index.js +10 -4
- package/src/command-specs/skills.js +229 -0
- package/src/command-specs/spaces.js +572 -0
- package/src/command-specs/views.js +69 -0
- package/src/runtime/agent-browser.js +30 -7
- package/src/runtime/app-boundary-validator.js +7 -4
- package/src/runtime/app-data-literals.js +82 -0
- package/src/runtime/app-platform.js +321 -253
- package/src/runtime/confined-space-build.js +74 -0
- package/src/runtime/confined-space-verify.js +49 -0
- package/src/runtime/native-record-files.js +47 -0
- package/src/runtime/retired-sdk-files.js +20 -0
- package/src/runtime/skill-sync/cloud-client.ts +26 -4
- package/src/runtime/skill-sync/index.ts +154 -35
- package/src/runtime/skill-sync/local-scanner.ts +125 -17
- package/src/runtime/skill-sync/native-identity.ts +102 -0
- package/src/runtime/skill-sync/native-plan.ts +59 -0
- package/src/runtime/skill-sync/sync-plan.ts +16 -9
- package/src/runtime/skill-sync/types.ts +32 -6
- package/src/runtime/source-root.js +32 -0
- package/src/runtime/space-collection-scaffold.js +66 -0
- package/src/runtime/space-database-structures.js +229 -0
- package/src/runtime/space-fixture-broker.js +50 -0
- package/src/runtime/space-lock.js +337 -0
- package/src/runtime/space-platform.js +105 -0
- package/src/runtime/space-source.js +281 -0
- package/src/runtime/space-test-server.js +327 -0
- package/src/runtime/space-verification.js +89 -0
- package/src/runtime/space-verify-browser-worker.js +51 -0
- package/src/runtime/space-view-manifest.js +254 -0
- package/src/runtime/sync-skills.js +1 -1
- package/src/runtime/transport.js +8 -1
- package/src/runtime/view-render.js +49 -0
- package/src/space-harness-host.ts +103 -0
- package/template/app/globals.css +1 -0
- package/src/command-specs/reports.js +0 -97
|
@@ -1,543 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
# Structured native query grammar
|
|
2
2
|
|
|
3
|
-
`LOCAL_NOTIS_DATABASE_QUERY
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Request shape
|
|
8
|
-
|
|
9
|
-
```json
|
|
10
|
-
{
|
|
11
|
-
"database_id": "tasks-db-id",
|
|
12
|
-
"database_slug": "tasks",
|
|
13
|
-
"query": {
|
|
14
|
-
"filter": {
|
|
15
|
-
"operator": "and",
|
|
16
|
-
"conditions": [
|
|
17
|
-
{
|
|
18
|
-
"property": "Status",
|
|
19
|
-
"type": "status",
|
|
20
|
-
"operator": "equals",
|
|
21
|
-
"value": "In Progress"
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
},
|
|
25
|
-
"sorts": [
|
|
26
|
-
{
|
|
27
|
-
"property": "Due Date",
|
|
28
|
-
"direction": "ascending"
|
|
29
|
-
}
|
|
30
|
-
],
|
|
31
|
-
"page_size": 20
|
|
32
|
-
},
|
|
33
|
-
"offset": 0
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Top-level fields:
|
|
38
|
-
|
|
39
|
-
- One of `database_id` or `database_slug` is required.
|
|
40
|
-
- `database_id`: stable native database ID. Prefer this when it is available from database context, `list_databases`, or `get_database`.
|
|
41
|
-
- `database_slug`: native database slug. Use this when `database_id` is not available, or pass it alongside `database_id` as a fallback.
|
|
42
|
-
- `query`: required object
|
|
43
|
-
- `offset`: optional numeric pagination offset
|
|
44
|
-
|
|
45
|
-
When both `database_id` and `database_slug` are provided, they must identify the same database. If the ID is stale and no database is found by ID, the runtime may fall back to the slug.
|
|
46
|
-
|
|
47
|
-
`query` fields:
|
|
48
|
-
|
|
49
|
-
- `filter`: optional rule tree
|
|
50
|
-
- `sorts`: optional array of sort definitions
|
|
51
|
-
- `page_size`: optional integer page size
|
|
52
|
-
|
|
53
|
-
## Filter shape
|
|
54
|
-
|
|
55
|
-
```json
|
|
56
|
-
{
|
|
57
|
-
"operator": "and",
|
|
58
|
-
"conditions": [
|
|
59
|
-
{
|
|
60
|
-
"property": "Status",
|
|
61
|
-
"type": "status",
|
|
62
|
-
"operator": "equals",
|
|
63
|
-
"value": "In Progress"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"property": "Priority",
|
|
67
|
-
"type": "select",
|
|
68
|
-
"operator": "equals",
|
|
69
|
-
"value": "High"
|
|
70
|
-
}
|
|
71
|
-
]
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Use nested groups when needed:
|
|
76
|
-
|
|
77
|
-
```json
|
|
78
|
-
{
|
|
79
|
-
"operator": "or",
|
|
80
|
-
"conditions": [
|
|
81
|
-
{
|
|
82
|
-
"property": "Status",
|
|
83
|
-
"type": "status",
|
|
84
|
-
"operator": "equals",
|
|
85
|
-
"value": "Todo"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"operator": "and",
|
|
89
|
-
"conditions": [
|
|
90
|
-
{
|
|
91
|
-
"property": "Priority",
|
|
92
|
-
"type": "select",
|
|
93
|
-
"operator": "equals",
|
|
94
|
-
"value": "High"
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
"property": "Archived",
|
|
98
|
-
"type": "checkbox",
|
|
99
|
-
"operator": "equals",
|
|
100
|
-
"value": false
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
]
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Supported property semantics
|
|
109
|
-
|
|
110
|
-
Use the real Notis property name and the correct property type.
|
|
111
|
-
|
|
112
|
-
### Title and rich text
|
|
113
|
-
|
|
114
|
-
Recommended operators:
|
|
115
|
-
|
|
116
|
-
- `contains`
|
|
117
|
-
- `equals`
|
|
118
|
-
- `not_equals`
|
|
119
|
-
|
|
120
|
-
Example:
|
|
121
|
-
|
|
122
|
-
```json
|
|
123
|
-
{
|
|
124
|
-
"property": "Title",
|
|
125
|
-
"type": "title",
|
|
126
|
-
"operator": "contains",
|
|
127
|
-
"value": "launch"
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Select and status
|
|
132
|
-
|
|
133
|
-
Recommended operators:
|
|
134
|
-
|
|
135
|
-
- `equals`
|
|
136
|
-
- `not_equals`
|
|
137
|
-
- `in`
|
|
138
|
-
|
|
139
|
-
Example:
|
|
140
|
-
|
|
141
|
-
```json
|
|
142
|
-
{
|
|
143
|
-
"property": "Status",
|
|
144
|
-
"type": "status",
|
|
145
|
-
"operator": "equals",
|
|
146
|
-
"value": "Done"
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Multi-select
|
|
151
|
-
|
|
152
|
-
Recommended operators:
|
|
153
|
-
|
|
154
|
-
- `contains`
|
|
155
|
-
- `not_contains`
|
|
156
|
-
|
|
157
|
-
Example:
|
|
158
|
-
|
|
159
|
-
```json
|
|
160
|
-
{
|
|
161
|
-
"property": "Tags",
|
|
162
|
-
"type": "multi_select",
|
|
163
|
-
"operator": "contains",
|
|
164
|
-
"value": "Urgent"
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Checkbox
|
|
169
|
-
|
|
170
|
-
Recommended operator:
|
|
171
|
-
|
|
172
|
-
- `equals`
|
|
173
|
-
|
|
174
|
-
Example:
|
|
175
|
-
|
|
176
|
-
```json
|
|
177
|
-
{
|
|
178
|
-
"property": "Archived",
|
|
179
|
-
"type": "checkbox",
|
|
180
|
-
"operator": "equals",
|
|
181
|
-
"value": false
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Number
|
|
186
|
-
|
|
187
|
-
Recommended operators:
|
|
188
|
-
|
|
189
|
-
- `equals`
|
|
190
|
-
- `not_equals`
|
|
191
|
-
- `greater_than`
|
|
192
|
-
- `greater_than_or_equal`
|
|
193
|
-
- `less_than`
|
|
194
|
-
- `less_than_or_equal`
|
|
195
|
-
|
|
196
|
-
Example:
|
|
197
|
-
|
|
198
|
-
```json
|
|
199
|
-
{
|
|
200
|
-
"property": "Score",
|
|
201
|
-
"type": "number",
|
|
202
|
-
"operator": "greater_than_or_equal",
|
|
203
|
-
"value": 80
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Date
|
|
208
|
-
|
|
209
|
-
Recommended operators:
|
|
210
|
-
|
|
211
|
-
- `equals`
|
|
212
|
-
- `before`
|
|
213
|
-
- `after`
|
|
214
|
-
- `on_or_before`
|
|
215
|
-
- `on_or_after`
|
|
216
|
-
|
|
217
|
-
Use ISO dates or timestamps depending on the property precision.
|
|
218
|
-
|
|
219
|
-
Example:
|
|
3
|
+
Discover and inspect `LOCAL_NOTIS_DATABASE_QUERY`; use its current input schema.
|
|
4
|
+
For native Spaces use `protocol: 1`, the exact discovery `target`, and `input`.
|
|
5
|
+
The native query lives directly inside `input`, without another request/query wrapper.
|
|
220
6
|
|
|
221
7
|
```json
|
|
222
8
|
{
|
|
223
|
-
"
|
|
224
|
-
"
|
|
225
|
-
"
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
Recommended operators:
|
|
233
|
-
|
|
234
|
-
- `contains`
|
|
235
|
-
- `not_contains`
|
|
236
|
-
|
|
237
|
-
Pass the related `document_id`, not the display title.
|
|
238
|
-
|
|
239
|
-
Example:
|
|
240
|
-
|
|
241
|
-
```json
|
|
242
|
-
{
|
|
243
|
-
"property": "Project",
|
|
244
|
-
"type": "relation",
|
|
245
|
-
"operator": "contains",
|
|
246
|
-
"value": "doc_project_123"
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### Formula
|
|
251
|
-
|
|
252
|
-
Treat formula values according to the returned data type. In practice, use the matching operator family for the computed result:
|
|
253
|
-
|
|
254
|
-
- text-like formula: `contains` or `equals`
|
|
255
|
-
- number-like formula: numeric comparison operators
|
|
256
|
-
- boolean-like formula: `equals`
|
|
257
|
-
|
|
258
|
-
Only use formula filters when the formula property already exists in the schema.
|
|
259
|
-
|
|
260
|
-
## Sorts
|
|
261
|
-
|
|
262
|
-
Sort objects look like this:
|
|
263
|
-
|
|
264
|
-
```json
|
|
265
|
-
{
|
|
266
|
-
"property": "Created At",
|
|
267
|
-
"direction": "descending"
|
|
268
|
-
}
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
Recommended directions:
|
|
272
|
-
|
|
273
|
-
- `ascending`
|
|
274
|
-
- `descending`
|
|
275
|
-
|
|
276
|
-
Common sorts:
|
|
277
|
-
|
|
278
|
-
- title sorts for alphabetical browsing
|
|
279
|
-
- status then date sorts for workflow queues
|
|
280
|
-
- timestamp sorts such as `Created At`, `Updated At`, or `Last Edited Time`
|
|
281
|
-
|
|
282
|
-
Example:
|
|
283
|
-
|
|
284
|
-
```json
|
|
285
|
-
[
|
|
286
|
-
{
|
|
287
|
-
"property": "Last Edited Time",
|
|
288
|
-
"direction": "descending"
|
|
9
|
+
"protocol": 1,
|
|
10
|
+
"target": {"space_id": "<exact-discovered-space-id>", "binding": "<exact-discovered-binding-id>"},
|
|
11
|
+
"input": {
|
|
12
|
+
"mode": "rows",
|
|
13
|
+
"filter": {"field": {"property": "Status"}, "op": "equals", "value": "Done"},
|
|
14
|
+
"sorts": [{"field": {"column": "updated_at"}, "direction": "desc"}],
|
|
15
|
+
"page_size": 20,
|
|
16
|
+
"offset": 0,
|
|
17
|
+
"include_content": false
|
|
289
18
|
}
|
|
290
|
-
]
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Pagination
|
|
294
|
-
|
|
295
|
-
Use `page_size` to cap the number of results per call.
|
|
296
|
-
|
|
297
|
-
The response returns:
|
|
298
|
-
|
|
299
|
-
- `documents`
|
|
300
|
-
- `results_count`
|
|
301
|
-
- `has_more`
|
|
302
|
-
- `next_offset`
|
|
303
|
-
- `query`
|
|
304
|
-
- `complementary_instructions`
|
|
305
|
-
|
|
306
|
-
Pagination rules:
|
|
307
|
-
|
|
308
|
-
- start with `offset: 0` or omit it
|
|
309
|
-
- if `has_more` is true, call again with `offset: next_offset`
|
|
310
|
-
|
|
311
|
-
Example follow-up call:
|
|
312
|
-
|
|
313
|
-
```json
|
|
314
|
-
{
|
|
315
|
-
"database_id": "tasks-db-id",
|
|
316
|
-
"query": {
|
|
317
|
-
"page_size": 25
|
|
318
|
-
},
|
|
319
|
-
"offset": 25
|
|
320
19
|
}
|
|
321
20
|
```
|
|
322
21
|
|
|
323
|
-
|
|
22
|
+
Use the complete Space binding target returned by schema discovery. Every
|
|
23
|
+
database lives in a Space: a bare `database_id` gets `resolved_target` from
|
|
24
|
+
`LOCAL_NOTIS_DATABASE_GET_DATABASE`, and a bare-id query answers
|
|
25
|
+
`database_in_spaces` with its links. Never remove its record context or substitute
|
|
26
|
+
another database/owner after a denial. `action_id`, when present, retains the
|
|
27
|
+
saved action's narrower authority rather than granting direct Editor access.
|
|
324
28
|
|
|
325
|
-
|
|
29
|
+
## Fields and filters
|
|
326
30
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
31
|
+
Choose one field reference: `{property_id}`, an unambiguous `{property}` label,
|
|
32
|
+
or a supported `{column}` such as `record_key`, `id`, `title`, `created_at`,
|
|
33
|
+
`updated_at`, `last_edited_time`, `content_type`, `file_type`. Current property
|
|
34
|
+
names take precedence; use stable IDs when names are ambiguous.
|
|
331
35
|
|
|
332
|
-
|
|
36
|
+
A condition is `{field, op, value}`. Empty checks (`is_empty`, `is_not_empty`)
|
|
37
|
+
omit `value`. Combine with `{and: [conditions]}` or `{or: [conditions]}`; groups
|
|
38
|
+
must be nonempty. Invalid conditions fail—they never become an unrestricted query.
|
|
333
39
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
40
|
+
| Type | Operators |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| Record identity | `equals`, `not_equals`, `in` |
|
|
43
|
+
| Text/title/URL | `equals`, `not_equals`, `contains`, `not_contains`, `starts_with`, `ends_with`, empty checks |
|
|
44
|
+
| Number | `equals`, `not_equals`, `greater_than`, `less_than`, inclusive variants, empty checks |
|
|
45
|
+
| Checkbox | `equals`, `not_equals` with real booleans |
|
|
46
|
+
| Select/status | `equals`, `not_equals`, empty checks; use a current option ID or unambiguous label |
|
|
47
|
+
| Multi-select/relation | `contains`, `does_not_contain`, empty checks |
|
|
48
|
+
| Date | `equals`, `before`, `after`, `on_or_before`, `on_or_after`, empty checks; use ISO dates/timestamps |
|
|
337
49
|
|
|
338
|
-
|
|
50
|
+
A relation filter uses the related record identity returned by its native read,
|
|
51
|
+
not a guessed title. Do not encode a relation as a scalar text equality. Avoid
|
|
52
|
+
assuming every application uses the same status labels or Inbox semantics.
|
|
339
53
|
|
|
340
|
-
|
|
54
|
+
## Pagination and projection
|
|
341
55
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
"filter": {
|
|
347
|
-
"operator": "and",
|
|
348
|
-
"conditions": [
|
|
349
|
-
{
|
|
350
|
-
"property": "Title",
|
|
351
|
-
"type": "title",
|
|
352
|
-
"operator": "contains",
|
|
353
|
-
"value": "pricing"
|
|
354
|
-
}
|
|
355
|
-
]
|
|
356
|
-
},
|
|
357
|
-
"page_size": 10
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
```
|
|
56
|
+
Use bounded pages (1–500) and the returned continuation/offset until complete.
|
|
57
|
+
Native row results expose `rows`, stable `record_key`, revision and schema
|
|
58
|
+
metadata; do not assume the older `documents` result shape. Sorts use
|
|
59
|
+
`{field, direction: 'asc'|'desc'}`. Multi-select/relation fields cannot be sorted.
|
|
361
60
|
|
|
362
|
-
|
|
61
|
+
Use `include_content: false` for lists. Include bodies only when needed.
|
|
62
|
+
Archived rows are excluded unless `include_archived: true`; binned/inaccessible
|
|
63
|
+
rows remain excluded by authority. Do not turn a missing page into a zero count.
|
|
363
64
|
|
|
364
|
-
|
|
365
|
-
{
|
|
366
|
-
"database_id": "tasks-db-id",
|
|
367
|
-
"query": {
|
|
368
|
-
"filter": {
|
|
369
|
-
"operator": "and",
|
|
370
|
-
"conditions": [
|
|
371
|
-
{
|
|
372
|
-
"property": "Status",
|
|
373
|
-
"type": "status",
|
|
374
|
-
"operator": "equals",
|
|
375
|
-
"value": "In Progress"
|
|
376
|
-
}
|
|
377
|
-
]
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
### Multi-select contains
|
|
384
|
-
|
|
385
|
-
```json
|
|
386
|
-
{
|
|
387
|
-
"database_id": "content-db-id",
|
|
388
|
-
"query": {
|
|
389
|
-
"filter": {
|
|
390
|
-
"operator": "and",
|
|
391
|
-
"conditions": [
|
|
392
|
-
{
|
|
393
|
-
"property": "Tags",
|
|
394
|
-
"type": "multi_select",
|
|
395
|
-
"operator": "contains",
|
|
396
|
-
"value": "Newsletter"
|
|
397
|
-
}
|
|
398
|
-
]
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
### Checkbox equals
|
|
405
|
-
|
|
406
|
-
```json
|
|
407
|
-
{
|
|
408
|
-
"database_id": "tasks-db-id",
|
|
409
|
-
"query": {
|
|
410
|
-
"filter": {
|
|
411
|
-
"operator": "and",
|
|
412
|
-
"conditions": [
|
|
413
|
-
{
|
|
414
|
-
"property": "Completed",
|
|
415
|
-
"type": "checkbox",
|
|
416
|
-
"operator": "equals",
|
|
417
|
-
"value": true
|
|
418
|
-
}
|
|
419
|
-
]
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
### Number comparison
|
|
426
|
-
|
|
427
|
-
```json
|
|
428
|
-
{
|
|
429
|
-
"database_id": "deals-db-id",
|
|
430
|
-
"query": {
|
|
431
|
-
"filter": {
|
|
432
|
-
"operator": "and",
|
|
433
|
-
"conditions": [
|
|
434
|
-
{
|
|
435
|
-
"property": "Amount",
|
|
436
|
-
"type": "number",
|
|
437
|
-
"operator": "greater_than",
|
|
438
|
-
"value": 10000
|
|
439
|
-
}
|
|
440
|
-
]
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
### Date comparison
|
|
447
|
-
|
|
448
|
-
```json
|
|
449
|
-
{
|
|
450
|
-
"database_id": "tasks-db-id",
|
|
451
|
-
"query": {
|
|
452
|
-
"filter": {
|
|
453
|
-
"operator": "and",
|
|
454
|
-
"conditions": [
|
|
455
|
-
{
|
|
456
|
-
"property": "Due Date",
|
|
457
|
-
"type": "date",
|
|
458
|
-
"operator": "on_or_after",
|
|
459
|
-
"value": "2026-03-01"
|
|
460
|
-
}
|
|
461
|
-
]
|
|
462
|
-
},
|
|
463
|
-
"sorts": [
|
|
464
|
-
{
|
|
465
|
-
"property": "Due Date",
|
|
466
|
-
"direction": "ascending"
|
|
467
|
-
}
|
|
468
|
-
]
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
### Relation contains
|
|
474
|
-
|
|
475
|
-
```json
|
|
476
|
-
{
|
|
477
|
-
"database_id": "tasks-db-id",
|
|
478
|
-
"query": {
|
|
479
|
-
"filter": {
|
|
480
|
-
"operator": "and",
|
|
481
|
-
"conditions": [
|
|
482
|
-
{
|
|
483
|
-
"property": "Project",
|
|
484
|
-
"type": "relation",
|
|
485
|
-
"operator": "contains",
|
|
486
|
-
"value": "doc_project_123"
|
|
487
|
-
}
|
|
488
|
-
]
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
### Timestamp sort
|
|
495
|
-
|
|
496
|
-
```json
|
|
497
|
-
{
|
|
498
|
-
"database_id": "tasks-db-id",
|
|
499
|
-
"query": {
|
|
500
|
-
"sorts": [
|
|
501
|
-
{
|
|
502
|
-
"property": "Last Edited Time",
|
|
503
|
-
"direction": "descending"
|
|
504
|
-
}
|
|
505
|
-
],
|
|
506
|
-
"page_size": 20
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
### Pagination follow-up
|
|
512
|
-
|
|
513
|
-
First call:
|
|
514
|
-
|
|
515
|
-
```json
|
|
516
|
-
{
|
|
517
|
-
"database_id": "tasks-db-id",
|
|
518
|
-
"query": {
|
|
519
|
-
"page_size": 20
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
Second call after a response with `has_more: true` and `next_offset: 20`:
|
|
525
|
-
|
|
526
|
-
```json
|
|
527
|
-
{
|
|
528
|
-
"database_id": "tasks-db-id",
|
|
529
|
-
"query": {
|
|
530
|
-
"page_size": 20
|
|
531
|
-
},
|
|
532
|
-
"offset": 20
|
|
533
|
-
}
|
|
534
|
-
```
|
|
65
|
+
## Count, aggregate and search
|
|
535
66
|
|
|
536
|
-
|
|
67
|
+
- `mode: 'count'` applies the same authorized filter and returns its count.
|
|
68
|
+
- `mode: 'aggregate'` adds `aggregate: {op: 'sum'|'avg'|'min'|'max', field}` over
|
|
69
|
+
a numeric field. It is computed within the same native scope.
|
|
70
|
+
- `mode: 'search'` adds `search: {text, fields: [field, ...]}` over supported text
|
|
71
|
+
fields; this is structured native search, not semantic memory retrieval.
|
|
72
|
+
- For one current body, use `input: {mode: 'document_body', record_key}` with the
|
|
73
|
+
exact body-capable target. The response includes Markdown and current revisions.
|
|
537
74
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
3. Call `LOCAL_NOTIS_DATABASE_QUERY` with `database_id` plus structured filters and sorts. Use `database_slug` only when the ID is not available.
|
|
541
|
-
4. If you need the full body of one row, call `LOCAL_NOTIS_DATABASE_GET_DOCUMENT` with the returned `document_id`.
|
|
542
|
-
5. If you need to update one of the matched rows, call the relevant generated database upsert tool with that `document_id`.
|
|
543
|
-
6. If you need a relation value, query the related database first and pass the resulting `document_id` into the upsert.
|
|
75
|
+
For visual dashboards or a link's selected params, resolve/render the view rather
|
|
76
|
+
than guessing that an independent query recreates its presentation or period.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Framework-neutral ESM loading shared by Portal and credentialless verification. */
|
|
2
|
+
import type React from 'react';
|
|
3
|
+
|
|
4
|
+
export function rewriteReactImports(source: string): string {
|
|
5
|
+
// Create inline data URLs that re-export from window globals.
|
|
6
|
+
// This avoids the "Cannot find module" error with blob URL imports.
|
|
7
|
+
const reactShim = `data:text/javascript,${encodeURIComponent(
|
|
8
|
+
'const R = window.React; export default R; export const { createContext, createRef, useState, useEffect, useContext, useCallback, useMemo, useRef, useReducer, useLayoutEffect, useId, memo, forwardRef, createElement, Fragment, Children, cloneElement, isValidElement, lazy, Suspense, startTransition, useTransition, useDeferredValue, useSyncExternalStore, useInsertionEffect, useDebugValue, useImperativeHandle, Component, PureComponent } = R;'
|
|
9
|
+
)}`;
|
|
10
|
+
const jsxShim = `data:text/javascript,${encodeURIComponent(
|
|
11
|
+
'const J = window.__ReactJSXRuntime || {}; const R = window.React; export const jsx = J.jsx || R.createElement; export const jsxs = J.jsxs || R.createElement; export const jsxDEV = J.jsxDEV || R.createElement; export const Fragment = J.Fragment || R.Fragment;'
|
|
12
|
+
)}`;
|
|
13
|
+
const reactDomShim = `data:text/javascript,${encodeURIComponent(
|
|
14
|
+
'const RD = window.ReactDOM; export default RD; export const { createPortal, flushSync, unstable_batchedUpdates } = RD;'
|
|
15
|
+
)}`;
|
|
16
|
+
const reactDomClientShim = `data:text/javascript,${encodeURIComponent(
|
|
17
|
+
'const RDC = window.ReactDOMClient; export default RDC; export const { createRoot, hydrateRoot } = RDC;'
|
|
18
|
+
)}`;
|
|
19
|
+
|
|
20
|
+
let result = source;
|
|
21
|
+
// Replace bare side-effect imports
|
|
22
|
+
result = result.replace(/import\s*["']react-dom\/client["'];?/g, `import "${reactDomClientShim}";`);
|
|
23
|
+
result = result.replace(/import\s*["']react-dom["'];?/g, `import "${reactDomShim}";`);
|
|
24
|
+
result = result.replace(/import\s*["']react\/jsx-runtime["'];?/g, `import "${jsxShim}";`);
|
|
25
|
+
result = result.replace(/import\s*["']react\/jsx-dev-runtime["'];?/g, `import "${jsxShim}";`);
|
|
26
|
+
result = result.replace(/import\s*["']react["'];?/g, `import "${reactShim}";`);
|
|
27
|
+
|
|
28
|
+
// Replace import statements with data URL shims
|
|
29
|
+
// Handle: import { ... } from "react/jsx-runtime"
|
|
30
|
+
result = result.replace(/from\s*["']react\/jsx-runtime["']/g, `from "${jsxShim}"`);
|
|
31
|
+
result = result.replace(/from\s*["']react\/jsx-dev-runtime["']/g, `from "${jsxShim}"`);
|
|
32
|
+
// Handle react-dom/client before react-dom
|
|
33
|
+
result = result.replace(/from\s*["']react-dom\/client["']/g, `from "${reactDomClientShim}"`);
|
|
34
|
+
// Handle: import ... from "react-dom"
|
|
35
|
+
result = result.replace(/from\s*["']react-dom["']/g, `from "${reactDomShim}"`);
|
|
36
|
+
// Handle: import ... from "react" (must come after react-dom and react/jsx-runtime)
|
|
37
|
+
result = result.replace(/from\s*["']react["']/g, `from "${reactShim}"`);
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function resolveBundleRouteExport(
|
|
43
|
+
moduleExports: Record<string, React.ComponentType>,
|
|
44
|
+
exportCandidates: string[],
|
|
45
|
+
strict = false,
|
|
46
|
+
): { name: string; component: React.ComponentType } | null {
|
|
47
|
+
const namedExport = exportCandidates.find((name) => Boolean(moduleExports[name]));
|
|
48
|
+
if (namedExport) {
|
|
49
|
+
return { name: namedExport, component: moduleExports[namedExport] };
|
|
50
|
+
}
|
|
51
|
+
if (strict) return null;
|
|
52
|
+
if (moduleExports.default) {
|
|
53
|
+
return { name: 'default', component: moduleExports.default };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Vite may minify an entry export even though the manifest still carries
|
|
57
|
+
// its source name. A bundle with one non-shell component is unambiguous, so
|
|
58
|
+
// keep Dev usable instead of showing "View not available" for that route.
|
|
59
|
+
const componentExports = Object.entries(moduleExports).filter(
|
|
60
|
+
([name, value]) => name !== '__AppShell' && Boolean(value),
|
|
61
|
+
);
|
|
62
|
+
if (componentExports.length !== 1) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const [name, component] = componentExports[0];
|
|
66
|
+
return { name, component };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function importRewrittenBundleSource(source: string): Promise<Record<string, React.ComponentType>> {
|
|
70
|
+
const blob = new Blob([source], { type: 'text/javascript' });
|
|
71
|
+
const url = URL.createObjectURL(blob);
|
|
72
|
+
try {
|
|
73
|
+
return await import(/* webpackIgnore: true */ url) as Record<string, React.ComponentType>;
|
|
74
|
+
} finally { URL.revokeObjectURL(url); }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function importBundleSource(source: string) {
|
|
78
|
+
return importRewrittenBundleSource(rewriteReactImports(source));
|
|
79
|
+
}
|