datanotes 0.0.0-stage → 1.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.
@@ -0,0 +1,3161 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/api/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ACTOR_HEADER: () => ACTOR_HEADER,
24
+ CALLABLE_OPERATIONS: () => CALLABLE_OPERATIONS,
25
+ DatanotesClient: () => DatanotesClient,
26
+ DatanotesError: () => DatanotesError,
27
+ OPERATIONS: () => OPERATIONS,
28
+ OperationInputError: () => OperationInputError,
29
+ ROUTE_PREFIX: () => ROUTE_PREFIX,
30
+ describeBatch: () => describeBatch,
31
+ describeRefusal: () => describeRefusal,
32
+ estimateTokens: () => estimateTokens,
33
+ fetchTransport: () => fetchTransport,
34
+ operationRequest: () => operationRequest,
35
+ operationRoute: () => operationRoute,
36
+ resultOf: () => resultOf
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+
40
+ // src/api/catalog.ts
41
+ var OPERATIONS = [
42
+ {
43
+ "name": "read_note",
44
+ "description": "Read a vault file (``GET /vault/{filename}``).\n\nDefault response is raw markdown. With ``as_json`` true, requests ``Accept: application/vnd.olrapi.note+json`` and returns ``NoteJson``: ``content``, ``frontmatter``, ``tags``, ``path``, and ``stat`` (file times and size), per the plugin OpenAPI schema.\n\nInputs:\n- ``path``: Vault-relative path to the file (forward slashes).\n- ``as_json``: If false (default), return markdown. If true, return ``NoteJson``.\n\nReturns:\n- ``str`` \u2014 markdown body, or\n- ``dict[str, Any]`` \u2014 parsed ``NoteJson`` when ``as_json`` is true.",
45
+ "inputSchema": {
46
+ "additionalProperties": false,
47
+ "properties": {
48
+ "path": {
49
+ "type": "string"
50
+ },
51
+ "as_json": {
52
+ "default": false,
53
+ "type": "boolean"
54
+ }
55
+ },
56
+ "required": [
57
+ "path"
58
+ ],
59
+ "type": "object"
60
+ },
61
+ "annotations": {
62
+ "title": "Read Note",
63
+ "readOnlyHint": true,
64
+ "destructiveHint": false,
65
+ "idempotentHint": true,
66
+ "openWorldHint": false
67
+ }
68
+ },
69
+ {
70
+ "name": "list_directory",
71
+ "description": 'List files under a vault directory (``GET /vault/`` or ``GET /vault/{pathToDirectory}/``).\n\nResponse JSON includes a ``files`` array. Names ending with ``/`` are subdirectories. Empty directories may not appear in listings (per API). Use ``""`` for the vault root.\n\nInputs:\n- ``path``: Vault-relative directory path; use ``""`` for the vault root.\n\nReturns:\n- ``dict[str, Any]`` \u2014 parsed JSON listing from the API.',
72
+ "inputSchema": {
73
+ "additionalProperties": false,
74
+ "properties": {
75
+ "path": {
76
+ "default": "",
77
+ "type": "string"
78
+ }
79
+ },
80
+ "type": "object"
81
+ },
82
+ "annotations": {
83
+ "title": "List Vault Directory",
84
+ "readOnlyHint": true,
85
+ "destructiveHint": false,
86
+ "idempotentHint": true,
87
+ "openWorldHint": false
88
+ }
89
+ },
90
+ {
91
+ "name": "search_simple",
92
+ "description": "Full-text search (``POST /search/simple/``).\n\nUses Obsidian\u2019s native search syntax (keywords, ``path:``, ``tag:``, ``file:``, etc.). Results include filenames, match positions, context snippets, and scores per the plugin OpenAPI.\n\nInputs:\n- ``query``: Obsidian search expression.\n- ``context_length``: Max characters of context around each match (default 100).\n\nReturns:\n- Parsed JSON from the API (matches per file, context, score).",
93
+ "inputSchema": {
94
+ "additionalProperties": false,
95
+ "properties": {
96
+ "query": {
97
+ "type": "string"
98
+ },
99
+ "context_length": {
100
+ "default": 100,
101
+ "type": "integer"
102
+ }
103
+ },
104
+ "required": [
105
+ "query"
106
+ ],
107
+ "type": "object"
108
+ },
109
+ "annotations": {
110
+ "title": "Search Vault",
111
+ "readOnlyHint": true,
112
+ "destructiveHint": false,
113
+ "idempotentHint": true,
114
+ "openWorldHint": false
115
+ }
116
+ },
117
+ {
118
+ "name": "list_tables",
119
+ "description": "List every table: `name`, `catalog`, `schema`, `qualified` (`personal.metrics.mood` \u2014 use it\nwherever a table is expected; `metrics.mood` or `mood` also work when unambiguous), `path` and,\nwhen declared, `description` and `aliases` (other words for what it records). Tables are\ndefined in `database.yaml` (catalog \u2192 schema \u2192 table); legacy schema-note tables have no\n`catalog` and a two-part `qualified` name. `views` lists the stored views (same fields, no\npath): select them like tables. `system.information_schema` is read with `select_rows`.\n\nCall this first to find the table for what the user reports (match their words against\nname, description and aliases), and before creating tables or columns so you reuse existing\nones instead of creating duplicates.",
120
+ "inputSchema": {
121
+ "additionalProperties": false,
122
+ "properties": {},
123
+ "type": "object"
124
+ },
125
+ "annotations": {
126
+ "title": "List Tables",
127
+ "readOnlyHint": true,
128
+ "destructiveHint": false,
129
+ "idempotentHint": true,
130
+ "openWorldHint": false
131
+ }
132
+ },
133
+ {
134
+ "name": "describe_table",
135
+ "description": "Describe a table (`catalog.schema.table` or a shorter unambiguous name): options (`path`/`filename` patterns, archive folder, `exclude` folders), typed columns with\nlabel/aliases/description, dense vs sparse flag, untyped fields, and row count.\n\nBefore adding a column (e.g. a new metric), read `columns` and match your concept against\n`name`, `label`, `aliases` and `description`; reuse an existing column when it means the same.",
136
+ "inputSchema": {
137
+ "additionalProperties": false,
138
+ "properties": {
139
+ "table": {
140
+ "type": "string"
141
+ }
142
+ },
143
+ "required": [
144
+ "table"
145
+ ],
146
+ "type": "object"
147
+ },
148
+ "annotations": {
149
+ "title": "Describe Table",
150
+ "readOnlyHint": true,
151
+ "destructiveHint": false,
152
+ "idempotentHint": true,
153
+ "openWorldHint": false
154
+ }
155
+ },
156
+ {
157
+ "name": "create_table",
158
+ "description": 'Create table `catalog.schema.name` (definition in database.yaml; rows in\n`<root>/<catalog>/<schema>/<name>/`). Names: lowercase letters, digits, `_`; catalog/schema default\nto the database defaults.\n- `columns`: specs like `{"name": "kind", "type": "enum", "values": ["a","b"], "required": true}`.\n Types: string, integer, number, boolean, date, datetime, enum, link, list (+ `items`), json.\n Attributes: required, default (`"{now}"`/`"{today}"`), min, max, step, values, `ordered` (enum in\n order: filters/avg use the position), ref (link target, full `catalog.schema.table` or "self"),\n unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`),\n `identity` ("filename" | "created"), `vocabulary` (allowed values = names of another table\'s rows),\n `hierarchy: true` (one parent link to its own table), `dense` (written on every row),\n `inverse` on a link column: the column of the `ref` table that links back (`friends` \u2194\n `friends`, `children` \u2194 `parents`, `partner` \u2194 `partner`); writes keep both sides in step.\n- `time_column`: rows named by that date/datetime; otherwise `options.filename` (e.g. `"{name}"`).\n- `options`: `description` and `aliases` (how agents find it), `filename`, `partition`, `exclude`.\n- `body`: markdown body of new rows (row_template). Shared columns come from bases: `set_table_bases`.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).',
159
+ "inputSchema": {
160
+ "additionalProperties": false,
161
+ "properties": {
162
+ "name": {
163
+ "type": "string"
164
+ },
165
+ "columns": {
166
+ "items": {
167
+ "additionalProperties": true,
168
+ "type": "object"
169
+ },
170
+ "type": "array"
171
+ },
172
+ "schema": {
173
+ "anyOf": [
174
+ {
175
+ "type": "string"
176
+ },
177
+ {
178
+ "type": "null"
179
+ }
180
+ ],
181
+ "default": null
182
+ },
183
+ "catalog": {
184
+ "anyOf": [
185
+ {
186
+ "type": "string"
187
+ },
188
+ {
189
+ "type": "null"
190
+ }
191
+ ],
192
+ "default": null
193
+ },
194
+ "time_column": {
195
+ "anyOf": [
196
+ {
197
+ "type": "string"
198
+ },
199
+ {
200
+ "type": "null"
201
+ }
202
+ ],
203
+ "default": null
204
+ },
205
+ "options": {
206
+ "anyOf": [
207
+ {
208
+ "additionalProperties": {
209
+ "anyOf": [
210
+ {
211
+ "type": "string"
212
+ },
213
+ {
214
+ "items": {
215
+ "type": "string"
216
+ },
217
+ "type": "array"
218
+ }
219
+ ]
220
+ },
221
+ "type": "object"
222
+ },
223
+ {
224
+ "type": "null"
225
+ }
226
+ ],
227
+ "default": null
228
+ },
229
+ "fields": {
230
+ "anyOf": [
231
+ {
232
+ "additionalProperties": true,
233
+ "type": "object"
234
+ },
235
+ {
236
+ "type": "null"
237
+ }
238
+ ],
239
+ "default": null
240
+ },
241
+ "body": {
242
+ "anyOf": [
243
+ {
244
+ "type": "string"
245
+ },
246
+ {
247
+ "type": "null"
248
+ }
249
+ ],
250
+ "default": null
251
+ },
252
+ "dry_run": {
253
+ "default": false,
254
+ "type": "boolean"
255
+ }
256
+ },
257
+ "required": [
258
+ "name",
259
+ "columns"
260
+ ],
261
+ "type": "object"
262
+ },
263
+ "annotations": {
264
+ "title": "Create Table",
265
+ "readOnlyHint": false,
266
+ "destructiveHint": false,
267
+ "idempotentHint": false,
268
+ "openWorldHint": false
269
+ }
270
+ },
271
+ {
272
+ "name": "drop_table",
273
+ "description": 'Drop a table. Refused while it has rows unless `cascade="archive"`, which removes the\ndefinition from `database.yaml` and moves all rows to the table\'s archive folder (nothing is\nhard-deleted; undo restores). The transaction log is kept: `restore_table` can bring it back.',
274
+ "inputSchema": {
275
+ "additionalProperties": false,
276
+ "properties": {
277
+ "table": {
278
+ "type": "string"
279
+ },
280
+ "cascade": {
281
+ "anyOf": [
282
+ {
283
+ "type": "string"
284
+ },
285
+ {
286
+ "type": "null"
287
+ }
288
+ ],
289
+ "default": null
290
+ },
291
+ "dry_run": {
292
+ "default": false,
293
+ "type": "boolean"
294
+ }
295
+ },
296
+ "required": [
297
+ "table"
298
+ ],
299
+ "type": "object"
300
+ },
301
+ "annotations": {
302
+ "title": "Drop Table",
303
+ "readOnlyHint": false,
304
+ "destructiveHint": true,
305
+ "idempotentHint": false,
306
+ "openWorldHint": false
307
+ }
308
+ },
309
+ {
310
+ "name": "add_column",
311
+ "description": 'Add a typed column. Sparse by default (written only on rows that have a value \u2014 use for\nmetrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label":\n"Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`).\n`dense=true` adds it to every row with its `default`. Call `describe_table` first: never add\na column whose meaning an existing column (name/label/aliases/description) already covers.\nColumn names are permanent identifiers; only `rename_column` changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).',
312
+ "inputSchema": {
313
+ "additionalProperties": false,
314
+ "properties": {
315
+ "table": {
316
+ "type": "string"
317
+ },
318
+ "column": {
319
+ "additionalProperties": true,
320
+ "type": "object"
321
+ },
322
+ "dense": {
323
+ "default": false,
324
+ "type": "boolean"
325
+ },
326
+ "dry_run": {
327
+ "default": false,
328
+ "type": "boolean"
329
+ }
330
+ },
331
+ "required": [
332
+ "table",
333
+ "column"
334
+ ],
335
+ "type": "object"
336
+ },
337
+ "annotations": {
338
+ "title": "Add Column",
339
+ "readOnlyHint": false,
340
+ "destructiveHint": false,
341
+ "idempotentHint": false,
342
+ "openWorldHint": false
343
+ }
344
+ },
345
+ {
346
+ "name": "rename_column",
347
+ "description": "Rename a column on the schema and every row, and rewrite the references to it in notes.\nAlso the way to merge a duplicate column into an existing compatible one. Refused (nothing\nwritten) if any row has both columns with different values.",
348
+ "inputSchema": {
349
+ "additionalProperties": false,
350
+ "properties": {
351
+ "table": {
352
+ "type": "string"
353
+ },
354
+ "from_column": {
355
+ "type": "string"
356
+ },
357
+ "to_column": {
358
+ "type": "string"
359
+ },
360
+ "dry_run": {
361
+ "default": false,
362
+ "type": "boolean"
363
+ }
364
+ },
365
+ "required": [
366
+ "table",
367
+ "from_column",
368
+ "to_column"
369
+ ],
370
+ "type": "object"
371
+ },
372
+ "annotations": {
373
+ "title": "Rename Column",
374
+ "readOnlyHint": false,
375
+ "destructiveHint": false,
376
+ "idempotentHint": true,
377
+ "openWorldHint": false
378
+ }
379
+ },
380
+ {
381
+ "name": "drop_column",
382
+ "description": "Remove a column from the schema and every row. Previous values are journaled; revert with\n`undo_migration`.",
383
+ "inputSchema": {
384
+ "additionalProperties": false,
385
+ "properties": {
386
+ "table": {
387
+ "type": "string"
388
+ },
389
+ "name": {
390
+ "type": "string"
391
+ },
392
+ "dry_run": {
393
+ "default": false,
394
+ "type": "boolean"
395
+ }
396
+ },
397
+ "required": [
398
+ "table",
399
+ "name"
400
+ ],
401
+ "type": "object"
402
+ },
403
+ "annotations": {
404
+ "title": "Drop Column",
405
+ "readOnlyHint": false,
406
+ "destructiveHint": true,
407
+ "idempotentHint": false,
408
+ "openWorldHint": false
409
+ }
410
+ },
411
+ {
412
+ "name": "alter_column",
413
+ "description": "Change a column's attributes (type, min/max/step, values, required, default, label,\naliases, description, note; `null` removes an attribute; `dense` true/false). Refused with\nthe list of violating rows when existing values do not satisfy the new definition. A\ndifferent scale means a different column: add a new one instead of rescaling. To rename one\nenum value use `rename_value`.",
414
+ "inputSchema": {
415
+ "additionalProperties": false,
416
+ "properties": {
417
+ "table": {
418
+ "type": "string"
419
+ },
420
+ "name": {
421
+ "type": "string"
422
+ },
423
+ "changes": {
424
+ "additionalProperties": true,
425
+ "type": "object"
426
+ },
427
+ "dry_run": {
428
+ "default": false,
429
+ "type": "boolean"
430
+ }
431
+ },
432
+ "required": [
433
+ "table",
434
+ "name",
435
+ "changes"
436
+ ],
437
+ "type": "object"
438
+ },
439
+ "annotations": {
440
+ "title": "Alter Column",
441
+ "readOnlyHint": false,
442
+ "destructiveHint": false,
443
+ "idempotentHint": false,
444
+ "openWorldHint": false
445
+ }
446
+ },
447
+ {
448
+ "name": "alter_table",
449
+ "description": 'Alter a table without paths: move it (`catalog`, `schema`), rename it (`name`), change\n`partition` / `filename` patterns, `description`, `aliases`, `exclude` folders, `row_template`\n(`clear_row_template=true` removes it) or `history` ("on" | "off" | "inherit"). Rows, archive and\ntransaction log follow; links are updated; renamed rows keep their old name in `aliases`. Refused\nwhen a row cannot fill a pattern. Use `dry_run` to see `plannedMoves`; undo with undo_migration.',
450
+ "inputSchema": {
451
+ "additionalProperties": false,
452
+ "properties": {
453
+ "table": {
454
+ "type": "string"
455
+ },
456
+ "catalog": {
457
+ "anyOf": [
458
+ {
459
+ "type": "string"
460
+ },
461
+ {
462
+ "type": "null"
463
+ }
464
+ ],
465
+ "default": null
466
+ },
467
+ "schema": {
468
+ "anyOf": [
469
+ {
470
+ "type": "string"
471
+ },
472
+ {
473
+ "type": "null"
474
+ }
475
+ ],
476
+ "default": null
477
+ },
478
+ "name": {
479
+ "anyOf": [
480
+ {
481
+ "type": "string"
482
+ },
483
+ {
484
+ "type": "null"
485
+ }
486
+ ],
487
+ "default": null
488
+ },
489
+ "partition": {
490
+ "anyOf": [
491
+ {
492
+ "type": "string"
493
+ },
494
+ {
495
+ "type": "null"
496
+ }
497
+ ],
498
+ "default": null
499
+ },
500
+ "filename": {
501
+ "anyOf": [
502
+ {
503
+ "type": "string"
504
+ },
505
+ {
506
+ "type": "null"
507
+ }
508
+ ],
509
+ "default": null
510
+ },
511
+ "description": {
512
+ "anyOf": [
513
+ {
514
+ "type": "string"
515
+ },
516
+ {
517
+ "type": "null"
518
+ }
519
+ ],
520
+ "default": null
521
+ },
522
+ "aliases": {
523
+ "anyOf": [
524
+ {
525
+ "items": {
526
+ "type": "string"
527
+ },
528
+ "type": "array"
529
+ },
530
+ {
531
+ "type": "null"
532
+ }
533
+ ],
534
+ "default": null
535
+ },
536
+ "history": {
537
+ "anyOf": [
538
+ {
539
+ "type": "string"
540
+ },
541
+ {
542
+ "type": "null"
543
+ }
544
+ ],
545
+ "default": null
546
+ },
547
+ "exclude": {
548
+ "anyOf": [
549
+ {
550
+ "items": {
551
+ "type": "string"
552
+ },
553
+ "type": "array"
554
+ },
555
+ {
556
+ "type": "null"
557
+ }
558
+ ],
559
+ "default": null
560
+ },
561
+ "row_template": {
562
+ "anyOf": [
563
+ {
564
+ "type": "string"
565
+ },
566
+ {
567
+ "type": "null"
568
+ }
569
+ ],
570
+ "default": null
571
+ },
572
+ "clear_row_template": {
573
+ "default": false,
574
+ "type": "boolean"
575
+ },
576
+ "dry_run": {
577
+ "default": false,
578
+ "type": "boolean"
579
+ }
580
+ },
581
+ "required": [
582
+ "table"
583
+ ],
584
+ "type": "object"
585
+ },
586
+ "annotations": {
587
+ "title": "Alter Table",
588
+ "readOnlyHint": false,
589
+ "destructiveHint": false,
590
+ "idempotentHint": false,
591
+ "openWorldHint": false
592
+ }
593
+ },
594
+ {
595
+ "name": "define_base",
596
+ "description": 'Create or replace a base: a named set of columns (same spec as `create_table`) that tables\ninherit, like a parent class (`bases` in `database.yaml`). Tables using it get the columns\nwith the same name and meaning; `ref: "self"` means the inheriting table (e.g. a `parent`\ncolumn with `hierarchy: true`). `extends` builds on other bases. Replacing a base changes\nevery inheriting table: `rename_columns` (`{"old": "new"}`) renames the column on their rows,\n`drop_columns` removes it from their rows; dropping a column without listing it is refused.\nAll affected rows are validated before any write.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.',
597
+ "inputSchema": {
598
+ "additionalProperties": false,
599
+ "properties": {
600
+ "name": {
601
+ "type": "string"
602
+ },
603
+ "columns": {
604
+ "items": {
605
+ "additionalProperties": true,
606
+ "type": "object"
607
+ },
608
+ "type": "array"
609
+ },
610
+ "extends": {
611
+ "anyOf": [
612
+ {
613
+ "items": {
614
+ "type": "string"
615
+ },
616
+ "type": "array"
617
+ },
618
+ {
619
+ "type": "null"
620
+ }
621
+ ],
622
+ "default": null
623
+ },
624
+ "comment": {
625
+ "anyOf": [
626
+ {
627
+ "type": "string"
628
+ },
629
+ {
630
+ "type": "null"
631
+ }
632
+ ],
633
+ "default": null
634
+ },
635
+ "rename_columns": {
636
+ "anyOf": [
637
+ {
638
+ "additionalProperties": {
639
+ "type": "string"
640
+ },
641
+ "type": "object"
642
+ },
643
+ {
644
+ "type": "null"
645
+ }
646
+ ],
647
+ "default": null
648
+ },
649
+ "drop_columns": {
650
+ "anyOf": [
651
+ {
652
+ "items": {
653
+ "type": "string"
654
+ },
655
+ "type": "array"
656
+ },
657
+ {
658
+ "type": "null"
659
+ }
660
+ ],
661
+ "default": null
662
+ },
663
+ "dry_run": {
664
+ "default": false,
665
+ "type": "boolean"
666
+ }
667
+ },
668
+ "required": [
669
+ "name",
670
+ "columns"
671
+ ],
672
+ "type": "object"
673
+ },
674
+ "annotations": {
675
+ "title": "Define Base",
676
+ "readOnlyHint": false,
677
+ "destructiveHint": false,
678
+ "idempotentHint": false,
679
+ "openWorldHint": false
680
+ }
681
+ },
682
+ {
683
+ "name": "set_table_bases",
684
+ "description": "Set the bases a table inherits from (`extends`, in order; `[]` removes them). Inherited\ncolumns come after `id` and before the table's own columns. An own column with the name of an\ninherited one is replaced by the inherited definition (rows must fit it); a table may only\nrestyle an inherited column (label, description, aliases, note, dense) with `alter_column`.\nDense and generated/identity columns are filled on existing rows.",
685
+ "inputSchema": {
686
+ "additionalProperties": false,
687
+ "properties": {
688
+ "table": {
689
+ "type": "string"
690
+ },
691
+ "bases": {
692
+ "items": {
693
+ "type": "string"
694
+ },
695
+ "type": "array"
696
+ },
697
+ "dry_run": {
698
+ "default": false,
699
+ "type": "boolean"
700
+ }
701
+ },
702
+ "required": [
703
+ "table",
704
+ "bases"
705
+ ],
706
+ "type": "object"
707
+ },
708
+ "annotations": {
709
+ "title": "Set Table Bases",
710
+ "readOnlyHint": false,
711
+ "destructiveHint": false,
712
+ "idempotentHint": true,
713
+ "openWorldHint": false
714
+ }
715
+ },
716
+ {
717
+ "name": "describe_database",
718
+ "description": "Describe the database: its folder (`root`), `metastore` (`database.yaml`), configuration\n(default catalog and schema, row partition and file-name formats, archive folder, time zone),\njournal folder, `bases` (shared column sets and the tables using them), `catalogs` \u2192 schemas \u2192 tables (row counts) and views, legacy schema-note\ntables (`schemas`) and tables outside the database (`outside`).",
719
+ "inputSchema": {
720
+ "additionalProperties": false,
721
+ "properties": {},
722
+ "type": "object"
723
+ },
724
+ "annotations": {
725
+ "title": "Describe Database",
726
+ "readOnlyHint": true,
727
+ "destructiveHint": false,
728
+ "idempotentHint": true,
729
+ "openWorldHint": false
730
+ }
731
+ },
732
+ {
733
+ "name": "configure_database",
734
+ "description": 'Configure the database (persisted in database.yaml `config:`): `root` (rename the database\nfolder; links follow; revert by renaming back), `default_catalog`, `default_schema`,\n`default_partition` ("" = flat) and `filename` (date formats for new time-based tables),\n`archive_folder`, `timezone` (IANA; completes date-times written without offset), `history`\n(transaction log for every table \u2014 only on the user\'s request). Returns describe_database;\nafter a root rename also `rewritten` and `mentions` (show them to the user).',
735
+ "inputSchema": {
736
+ "additionalProperties": false,
737
+ "properties": {
738
+ "root": {
739
+ "anyOf": [
740
+ {
741
+ "type": "string"
742
+ },
743
+ {
744
+ "type": "null"
745
+ }
746
+ ],
747
+ "default": null
748
+ },
749
+ "default_catalog": {
750
+ "anyOf": [
751
+ {
752
+ "type": "string"
753
+ },
754
+ {
755
+ "type": "null"
756
+ }
757
+ ],
758
+ "default": null
759
+ },
760
+ "default_schema": {
761
+ "anyOf": [
762
+ {
763
+ "type": "string"
764
+ },
765
+ {
766
+ "type": "null"
767
+ }
768
+ ],
769
+ "default": null
770
+ },
771
+ "default_partition": {
772
+ "anyOf": [
773
+ {
774
+ "type": "string"
775
+ },
776
+ {
777
+ "type": "null"
778
+ }
779
+ ],
780
+ "default": null
781
+ },
782
+ "filename": {
783
+ "anyOf": [
784
+ {
785
+ "type": "string"
786
+ },
787
+ {
788
+ "type": "null"
789
+ }
790
+ ],
791
+ "default": null
792
+ },
793
+ "archive_folder": {
794
+ "anyOf": [
795
+ {
796
+ "type": "string"
797
+ },
798
+ {
799
+ "type": "null"
800
+ }
801
+ ],
802
+ "default": null
803
+ },
804
+ "timezone": {
805
+ "anyOf": [
806
+ {
807
+ "type": "string"
808
+ },
809
+ {
810
+ "type": "null"
811
+ }
812
+ ],
813
+ "default": null
814
+ },
815
+ "history": {
816
+ "anyOf": [
817
+ {
818
+ "type": "boolean"
819
+ },
820
+ {
821
+ "type": "null"
822
+ }
823
+ ],
824
+ "default": null
825
+ }
826
+ },
827
+ "type": "object"
828
+ },
829
+ "annotations": {
830
+ "title": "Configure Database",
831
+ "readOnlyHint": false,
832
+ "destructiveHint": false,
833
+ "idempotentHint": true,
834
+ "openWorldHint": false
835
+ }
836
+ },
837
+ {
838
+ "name": "rename_value",
839
+ "description": "Rename one value of an enum column (e.g. `high` \u2192 `very high`) in database.yaml and every\nrow, keeping its position, so an ordered scale is unchanged. Note text (queries, prose) is not\nrewritten. Refused if `to_value` already exists. Undo with `undo_migration`. Adding or\nremoving classes changes the scale: create a new table instead.",
840
+ "inputSchema": {
841
+ "additionalProperties": false,
842
+ "properties": {
843
+ "table": {
844
+ "type": "string"
845
+ },
846
+ "column": {
847
+ "type": "string"
848
+ },
849
+ "from_value": {
850
+ "type": "string"
851
+ },
852
+ "to_value": {
853
+ "type": "string"
854
+ },
855
+ "dry_run": {
856
+ "default": false,
857
+ "type": "boolean"
858
+ }
859
+ },
860
+ "required": [
861
+ "table",
862
+ "column",
863
+ "from_value",
864
+ "to_value"
865
+ ],
866
+ "type": "object"
867
+ },
868
+ "annotations": {
869
+ "title": "Rename Value",
870
+ "readOnlyHint": false,
871
+ "destructiveHint": false,
872
+ "idempotentHint": false,
873
+ "openWorldHint": false
874
+ }
875
+ },
876
+ {
877
+ "name": "insert_row",
878
+ "description": "Insert a row (new note). Values are validated against the columns; the note path comes from\nthe table's `path`/`filename` patterns (e.g. an event logged today about last night lands in\nlast night's day folder when you set `occurred_at` to last night). `body` is the note text.\nGenerated / identity columns are computed (do not pass them); CHECK constraints are enforced.\nReturns `migrationId` (undo) and the created path in `plannedCreates`.",
879
+ "inputSchema": {
880
+ "additionalProperties": false,
881
+ "properties": {
882
+ "table": {
883
+ "type": "string"
884
+ },
885
+ "values": {
886
+ "additionalProperties": true,
887
+ "type": "object"
888
+ },
889
+ "body": {
890
+ "anyOf": [
891
+ {
892
+ "type": "string"
893
+ },
894
+ {
895
+ "type": "null"
896
+ }
897
+ ],
898
+ "default": null
899
+ },
900
+ "path": {
901
+ "anyOf": [
902
+ {
903
+ "type": "string"
904
+ },
905
+ {
906
+ "type": "null"
907
+ }
908
+ ],
909
+ "default": null
910
+ },
911
+ "dry_run": {
912
+ "default": false,
913
+ "type": "boolean"
914
+ }
915
+ },
916
+ "required": [
917
+ "table",
918
+ "values"
919
+ ],
920
+ "type": "object"
921
+ },
922
+ "annotations": {
923
+ "title": "Insert Row",
924
+ "readOnlyHint": false,
925
+ "destructiveHint": false,
926
+ "idempotentHint": false,
927
+ "openWorldHint": false
928
+ }
929
+ },
930
+ {
931
+ "name": "update_rows",
932
+ "description": 'Update every row matching `where`. `where`: keys AND-ed; values are equality or operators\neq, ne, gt, gte, lt, lte, in, contains, icontains (case/accent-insensitive, also inside lists \u2014\nuse it for names and aliases), exists, within (a hierarchy link: that row and everything below);\ncombine with `or` / `and` / `not` (nestable); `path` is a pseudo-column. A dotted key follows a\nlink column: `{"project.area": "[[Work]]"}` matches rows whose `project` links a row with that `area`. `set_values` sets, `unset`\nremoves; all rows are validated first. `body` replaces the note body (only when one row matches).\n`expect_rows`: refuse unless exactly that many match. One row: prefer update_row.',
933
+ "inputSchema": {
934
+ "additionalProperties": false,
935
+ "properties": {
936
+ "table": {
937
+ "type": "string"
938
+ },
939
+ "where": {
940
+ "anyOf": [
941
+ {
942
+ "additionalProperties": true,
943
+ "type": "object"
944
+ },
945
+ {
946
+ "type": "null"
947
+ }
948
+ ],
949
+ "default": null
950
+ },
951
+ "set_values": {
952
+ "anyOf": [
953
+ {
954
+ "additionalProperties": true,
955
+ "type": "object"
956
+ },
957
+ {
958
+ "type": "null"
959
+ }
960
+ ],
961
+ "default": null
962
+ },
963
+ "unset": {
964
+ "anyOf": [
965
+ {
966
+ "items": {
967
+ "type": "string"
968
+ },
969
+ "type": "array"
970
+ },
971
+ {
972
+ "type": "null"
973
+ }
974
+ ],
975
+ "default": null
976
+ },
977
+ "dry_run": {
978
+ "default": false,
979
+ "type": "boolean"
980
+ },
981
+ "body": {
982
+ "anyOf": [
983
+ {
984
+ "type": "string"
985
+ },
986
+ {
987
+ "type": "null"
988
+ }
989
+ ],
990
+ "default": null
991
+ },
992
+ "expect_rows": {
993
+ "anyOf": [
994
+ {
995
+ "type": "integer"
996
+ },
997
+ {
998
+ "type": "null"
999
+ }
1000
+ ],
1001
+ "default": null
1002
+ }
1003
+ },
1004
+ "required": [
1005
+ "table"
1006
+ ],
1007
+ "type": "object"
1008
+ },
1009
+ "annotations": {
1010
+ "title": "Update Rows",
1011
+ "readOnlyHint": false,
1012
+ "destructiveHint": false,
1013
+ "idempotentHint": true,
1014
+ "openWorldHint": false
1015
+ }
1016
+ },
1017
+ {
1018
+ "name": "update_row",
1019
+ "description": 'Update exactly ONE row, addressed by its `id` (the system UUID) or its `path`; refused when\nthe row does not exist (or id and path disagree). Same validation, journal and history as\n`update_rows`.\n\n- `set_values` / `unset`: columns to set or remove.\n- `body`: replace the whole note body; or edit it keeping the rest:\n `body_sections` `{"Storia": "\u2026"}` replaces the text under that heading (any level, up to the\n next heading of the same level; added as `## Storia` when missing), `body_prepend` /\n `body_append` add text before / after.\n- `expect`: compare-and-set \u2014 `{"status": "open"}` writes only if the row still has those\n values (a person may have changed it since you read it); otherwise refused, nothing written.',
1020
+ "inputSchema": {
1021
+ "additionalProperties": false,
1022
+ "properties": {
1023
+ "table": {
1024
+ "type": "string"
1025
+ },
1026
+ "id": {
1027
+ "anyOf": [
1028
+ {
1029
+ "type": "string"
1030
+ },
1031
+ {
1032
+ "type": "null"
1033
+ }
1034
+ ],
1035
+ "default": null
1036
+ },
1037
+ "path": {
1038
+ "anyOf": [
1039
+ {
1040
+ "type": "string"
1041
+ },
1042
+ {
1043
+ "type": "null"
1044
+ }
1045
+ ],
1046
+ "default": null
1047
+ },
1048
+ "set_values": {
1049
+ "anyOf": [
1050
+ {
1051
+ "additionalProperties": true,
1052
+ "type": "object"
1053
+ },
1054
+ {
1055
+ "type": "null"
1056
+ }
1057
+ ],
1058
+ "default": null
1059
+ },
1060
+ "unset": {
1061
+ "anyOf": [
1062
+ {
1063
+ "items": {
1064
+ "type": "string"
1065
+ },
1066
+ "type": "array"
1067
+ },
1068
+ {
1069
+ "type": "null"
1070
+ }
1071
+ ],
1072
+ "default": null
1073
+ },
1074
+ "body": {
1075
+ "anyOf": [
1076
+ {
1077
+ "type": "string"
1078
+ },
1079
+ {
1080
+ "type": "null"
1081
+ }
1082
+ ],
1083
+ "default": null
1084
+ },
1085
+ "body_sections": {
1086
+ "anyOf": [
1087
+ {
1088
+ "additionalProperties": {
1089
+ "type": "string"
1090
+ },
1091
+ "type": "object"
1092
+ },
1093
+ {
1094
+ "type": "null"
1095
+ }
1096
+ ],
1097
+ "default": null
1098
+ },
1099
+ "body_prepend": {
1100
+ "anyOf": [
1101
+ {
1102
+ "type": "string"
1103
+ },
1104
+ {
1105
+ "type": "null"
1106
+ }
1107
+ ],
1108
+ "default": null
1109
+ },
1110
+ "expect": {
1111
+ "anyOf": [
1112
+ {
1113
+ "additionalProperties": true,
1114
+ "type": "object"
1115
+ },
1116
+ {
1117
+ "type": "null"
1118
+ }
1119
+ ],
1120
+ "default": null
1121
+ },
1122
+ "body_append": {
1123
+ "anyOf": [
1124
+ {
1125
+ "type": "string"
1126
+ },
1127
+ {
1128
+ "type": "null"
1129
+ }
1130
+ ],
1131
+ "default": null
1132
+ },
1133
+ "dry_run": {
1134
+ "default": false,
1135
+ "type": "boolean"
1136
+ }
1137
+ },
1138
+ "required": [
1139
+ "table"
1140
+ ],
1141
+ "type": "object"
1142
+ },
1143
+ "annotations": {
1144
+ "title": "Update Row",
1145
+ "readOnlyHint": false,
1146
+ "destructiveHint": false,
1147
+ "idempotentHint": true,
1148
+ "openWorldHint": false
1149
+ }
1150
+ },
1151
+ {
1152
+ "name": "delete_rows",
1153
+ "description": 'Delete rows matching `where`. `mode`: "archive" (default, move to the table\'s archive\nfolder) or "delete" (trash; content journaled for undo). `on_referenced`: "restrict"\n(default, refuse rows other notes link to), "set_null" (clear frontmatter links to them) or\n"ignore". Omitting `where` targets every row: always pass `where` unless you mean all.',
1154
+ "inputSchema": {
1155
+ "additionalProperties": false,
1156
+ "properties": {
1157
+ "table": {
1158
+ "type": "string"
1159
+ },
1160
+ "where": {
1161
+ "anyOf": [
1162
+ {
1163
+ "additionalProperties": true,
1164
+ "type": "object"
1165
+ },
1166
+ {
1167
+ "type": "null"
1168
+ }
1169
+ ],
1170
+ "default": null
1171
+ },
1172
+ "mode": {
1173
+ "anyOf": [
1174
+ {
1175
+ "type": "string"
1176
+ },
1177
+ {
1178
+ "type": "null"
1179
+ }
1180
+ ],
1181
+ "default": null
1182
+ },
1183
+ "on_referenced": {
1184
+ "anyOf": [
1185
+ {
1186
+ "type": "string"
1187
+ },
1188
+ {
1189
+ "type": "null"
1190
+ }
1191
+ ],
1192
+ "default": null
1193
+ },
1194
+ "dry_run": {
1195
+ "default": false,
1196
+ "type": "boolean"
1197
+ }
1198
+ },
1199
+ "required": [
1200
+ "table"
1201
+ ],
1202
+ "type": "object"
1203
+ },
1204
+ "annotations": {
1205
+ "title": "Delete Rows",
1206
+ "readOnlyHint": false,
1207
+ "destructiveHint": true,
1208
+ "idempotentHint": false,
1209
+ "openWorldHint": false
1210
+ }
1211
+ },
1212
+ {
1213
+ "name": "move_rows",
1214
+ "description": 'Move rows matching `where` to another table (e.g. split a domain out of `log` into its own\ntable): sets each row\'s `table` to the destination, applies `rename` (`{"metric_distance_km":\n"distance_km"}`), `set_values` and `drop`, adds the destination\'s missing dense fields, and\nvalidates every row against the destination first. Keys unknown to the destination are\nreported, never dropped silently \u2014 rename or drop them explicitly. `relocate=true` also moves\nthe files to the destination table\'s folder (named by its filename pattern). Undo with\n`undo_migration`.',
1215
+ "inputSchema": {
1216
+ "additionalProperties": false,
1217
+ "properties": {
1218
+ "table": {
1219
+ "type": "string"
1220
+ },
1221
+ "to_table": {
1222
+ "type": "string"
1223
+ },
1224
+ "where": {
1225
+ "anyOf": [
1226
+ {
1227
+ "additionalProperties": true,
1228
+ "type": "object"
1229
+ },
1230
+ {
1231
+ "type": "null"
1232
+ }
1233
+ ],
1234
+ "default": null
1235
+ },
1236
+ "rename": {
1237
+ "anyOf": [
1238
+ {
1239
+ "additionalProperties": {
1240
+ "type": "string"
1241
+ },
1242
+ "type": "object"
1243
+ },
1244
+ {
1245
+ "type": "null"
1246
+ }
1247
+ ],
1248
+ "default": null
1249
+ },
1250
+ "set_values": {
1251
+ "anyOf": [
1252
+ {
1253
+ "additionalProperties": true,
1254
+ "type": "object"
1255
+ },
1256
+ {
1257
+ "type": "null"
1258
+ }
1259
+ ],
1260
+ "default": null
1261
+ },
1262
+ "drop": {
1263
+ "anyOf": [
1264
+ {
1265
+ "items": {
1266
+ "type": "string"
1267
+ },
1268
+ "type": "array"
1269
+ },
1270
+ {
1271
+ "type": "null"
1272
+ }
1273
+ ],
1274
+ "default": null
1275
+ },
1276
+ "relocate": {
1277
+ "default": false,
1278
+ "type": "boolean"
1279
+ },
1280
+ "dry_run": {
1281
+ "default": false,
1282
+ "type": "boolean"
1283
+ }
1284
+ },
1285
+ "required": [
1286
+ "table",
1287
+ "to_table"
1288
+ ],
1289
+ "type": "object"
1290
+ },
1291
+ "annotations": {
1292
+ "title": "Move Rows",
1293
+ "readOnlyHint": false,
1294
+ "destructiveHint": false,
1295
+ "idempotentHint": true,
1296
+ "openWorldHint": false
1297
+ }
1298
+ },
1299
+ {
1300
+ "name": "adopt_rows",
1301
+ "description": 'Turn existing notes (not rows of any table yet) into rows of `table`, keeping their body and\nlinks: `rename` keys (`{"data": "occurred_at"}`), `set_values` for all, `per_row` values by\nnote path (`{"Home/x.md": {"zone": "[[Kitchen]]"}}`), `drop` keys the table does not have.\nEvery note gets `table` and a system `id`; with `relocate` (default) it moves to the table\'s\nfolder, named by its filename pattern (Obsidian updates links). All notes are validated first:\nunknown keys and bad values are listed and nothing is written. Run with `dry_run` first; undo\nwith `undo_migration`.',
1302
+ "inputSchema": {
1303
+ "additionalProperties": false,
1304
+ "properties": {
1305
+ "table": {
1306
+ "type": "string"
1307
+ },
1308
+ "paths": {
1309
+ "items": {
1310
+ "type": "string"
1311
+ },
1312
+ "type": "array"
1313
+ },
1314
+ "rename": {
1315
+ "anyOf": [
1316
+ {
1317
+ "additionalProperties": {
1318
+ "type": "string"
1319
+ },
1320
+ "type": "object"
1321
+ },
1322
+ {
1323
+ "type": "null"
1324
+ }
1325
+ ],
1326
+ "default": null
1327
+ },
1328
+ "set_values": {
1329
+ "anyOf": [
1330
+ {
1331
+ "additionalProperties": true,
1332
+ "type": "object"
1333
+ },
1334
+ {
1335
+ "type": "null"
1336
+ }
1337
+ ],
1338
+ "default": null
1339
+ },
1340
+ "per_row": {
1341
+ "anyOf": [
1342
+ {
1343
+ "additionalProperties": {
1344
+ "additionalProperties": true,
1345
+ "type": "object"
1346
+ },
1347
+ "type": "object"
1348
+ },
1349
+ {
1350
+ "type": "null"
1351
+ }
1352
+ ],
1353
+ "default": null
1354
+ },
1355
+ "drop": {
1356
+ "anyOf": [
1357
+ {
1358
+ "items": {
1359
+ "type": "string"
1360
+ },
1361
+ "type": "array"
1362
+ },
1363
+ {
1364
+ "type": "null"
1365
+ }
1366
+ ],
1367
+ "default": null
1368
+ },
1369
+ "relocate": {
1370
+ "default": true,
1371
+ "type": "boolean"
1372
+ },
1373
+ "dry_run": {
1374
+ "default": false,
1375
+ "type": "boolean"
1376
+ }
1377
+ },
1378
+ "required": [
1379
+ "table",
1380
+ "paths"
1381
+ ],
1382
+ "type": "object"
1383
+ },
1384
+ "annotations": {
1385
+ "title": "Adopt Rows",
1386
+ "readOnlyHint": false,
1387
+ "destructiveHint": false,
1388
+ "idempotentHint": false,
1389
+ "openWorldHint": false
1390
+ }
1391
+ },
1392
+ {
1393
+ "name": "select_rows",
1394
+ "description": 'Query rows: `{table, total, rows: [{path, ...}]}`. `table` may be a view,\n`system.information_schema.<catalogs|schemata|tables|columns|views|check_constraints>`, or\n`base:<name>` \u2014 every table that extends that base (e.g. `base:record`: all event-like tables),\non the base\'s columns, each row tagged `_source` with its table.\n- `where`: as in update_rows; relative dates `"{today}"`, `"{today-7d}"`, `"{now-24h}"`; file columns\n `file_name`, `file_link`, `file_modified`, `file_backlinks`.\n- `columns`, `order_by` (`-col` descending), `limit` (default 100, max 1000), `offset`,\n `expand` (inline linked rows\' frontmatter), `include_body` (the note body as `body`).\n- `join`: `{"table", "on": {"date(occurred_at)+1": "date(timestamp)"}, "as", "type": "inner"|"left",\n "columns", "where"}` \u2014 matches attached under `as`.\n- `group_by` (column, `path` or `date(col)\xB1n`; a list column counts once per item) + `aggregates`\n `{"n": "count", "kcal": "sum:meal.kcal"}` (count, count:col, sum, avg, min, max).\n- Ordered enums compare by position. Time travel: `version` or `timestamp`.',
1395
+ "inputSchema": {
1396
+ "additionalProperties": false,
1397
+ "properties": {
1398
+ "table": {
1399
+ "type": "string"
1400
+ },
1401
+ "columns": {
1402
+ "anyOf": [
1403
+ {
1404
+ "items": {
1405
+ "type": "string"
1406
+ },
1407
+ "type": "array"
1408
+ },
1409
+ {
1410
+ "type": "null"
1411
+ }
1412
+ ],
1413
+ "default": null
1414
+ },
1415
+ "where": {
1416
+ "anyOf": [
1417
+ {
1418
+ "additionalProperties": true,
1419
+ "type": "object"
1420
+ },
1421
+ {
1422
+ "type": "null"
1423
+ }
1424
+ ],
1425
+ "default": null
1426
+ },
1427
+ "order_by": {
1428
+ "anyOf": [
1429
+ {
1430
+ "type": "string"
1431
+ },
1432
+ {
1433
+ "items": {
1434
+ "type": "string"
1435
+ },
1436
+ "type": "array"
1437
+ },
1438
+ {
1439
+ "type": "null"
1440
+ }
1441
+ ],
1442
+ "default": null
1443
+ },
1444
+ "limit": {
1445
+ "anyOf": [
1446
+ {
1447
+ "type": "integer"
1448
+ },
1449
+ {
1450
+ "type": "null"
1451
+ }
1452
+ ],
1453
+ "default": null
1454
+ },
1455
+ "offset": {
1456
+ "anyOf": [
1457
+ {
1458
+ "type": "integer"
1459
+ },
1460
+ {
1461
+ "type": "null"
1462
+ }
1463
+ ],
1464
+ "default": null
1465
+ },
1466
+ "expand": {
1467
+ "anyOf": [
1468
+ {
1469
+ "items": {
1470
+ "type": "string"
1471
+ },
1472
+ "type": "array"
1473
+ },
1474
+ {
1475
+ "type": "null"
1476
+ }
1477
+ ],
1478
+ "default": null
1479
+ },
1480
+ "join": {
1481
+ "anyOf": [
1482
+ {
1483
+ "additionalProperties": true,
1484
+ "type": "object"
1485
+ },
1486
+ {
1487
+ "type": "null"
1488
+ }
1489
+ ],
1490
+ "default": null
1491
+ },
1492
+ "group_by": {
1493
+ "anyOf": [
1494
+ {
1495
+ "type": "string"
1496
+ },
1497
+ {
1498
+ "items": {
1499
+ "type": "string"
1500
+ },
1501
+ "type": "array"
1502
+ },
1503
+ {
1504
+ "type": "null"
1505
+ }
1506
+ ],
1507
+ "default": null
1508
+ },
1509
+ "aggregates": {
1510
+ "anyOf": [
1511
+ {
1512
+ "additionalProperties": {
1513
+ "type": "string"
1514
+ },
1515
+ "type": "object"
1516
+ },
1517
+ {
1518
+ "type": "null"
1519
+ }
1520
+ ],
1521
+ "default": null
1522
+ },
1523
+ "include_body": {
1524
+ "default": false,
1525
+ "type": "boolean"
1526
+ },
1527
+ "version": {
1528
+ "anyOf": [
1529
+ {
1530
+ "type": "integer"
1531
+ },
1532
+ {
1533
+ "type": "null"
1534
+ }
1535
+ ],
1536
+ "default": null
1537
+ },
1538
+ "timestamp": {
1539
+ "anyOf": [
1540
+ {
1541
+ "type": "string"
1542
+ },
1543
+ {
1544
+ "type": "null"
1545
+ }
1546
+ ],
1547
+ "default": null
1548
+ }
1549
+ },
1550
+ "required": [
1551
+ "table"
1552
+ ],
1553
+ "type": "object"
1554
+ },
1555
+ "annotations": {
1556
+ "title": "Select Rows",
1557
+ "readOnlyHint": true,
1558
+ "destructiveHint": false,
1559
+ "idempotentHint": true,
1560
+ "openWorldHint": false
1561
+ }
1562
+ },
1563
+ {
1564
+ "name": "check_table",
1565
+ "description": "Validate every row against the table (required, types, ranges, enums, links, unknown\ncolumns, CHECK constraints, stale generated/identity values). Use it to find rows edited by hand that break the schema.",
1566
+ "inputSchema": {
1567
+ "additionalProperties": false,
1568
+ "properties": {
1569
+ "table": {
1570
+ "type": "string"
1571
+ }
1572
+ },
1573
+ "required": [
1574
+ "table"
1575
+ ],
1576
+ "type": "object"
1577
+ },
1578
+ "annotations": {
1579
+ "title": "Check Table",
1580
+ "readOnlyHint": true,
1581
+ "destructiveHint": false,
1582
+ "idempotentHint": true,
1583
+ "openWorldHint": false
1584
+ }
1585
+ },
1586
+ {
1587
+ "name": "undo_migration",
1588
+ "description": "Revert a journaled table operation by its `migrationId`. Refused (nothing written) when any\ntouched note changed since; the conflicts are listed. The revert is a new version (`UNDO`) in\nthe transaction log.",
1589
+ "inputSchema": {
1590
+ "additionalProperties": false,
1591
+ "properties": {
1592
+ "migration_id": {
1593
+ "type": "string"
1594
+ }
1595
+ },
1596
+ "required": [
1597
+ "migration_id"
1598
+ ],
1599
+ "type": "object"
1600
+ },
1601
+ "annotations": {
1602
+ "title": "Undo Migration",
1603
+ "readOnlyHint": false,
1604
+ "destructiveHint": false,
1605
+ "idempotentHint": false,
1606
+ "openWorldHint": false
1607
+ }
1608
+ },
1609
+ {
1610
+ "name": "batch",
1611
+ "description": 'Several writes that succeed or fail together. `operations`: `[{"op": ..., ...arguments}]` where\n`op` is a row operation (`insert_row`, `update_row`, `update_rows`, `delete_rows`, `merge_rows`,\n`move_rows`, `adopt_rows`, `recompute_columns`, `align_relations`, `restore_table`) or a DDL op\n(`create_table`, `add_column`, `alter_column`, \u2026), with the same arguments as its tool (e.g.\n`values` for insert_row, `set_values` for update_row / update_rows). They run in order, each seeing the previous ones; if one is\nrefused, the ones already applied are undone (`rolledBack`). Returns `steps` (per operation) and\n`migrationId`: undo_migration on it reverts the whole batch. Use it when a change spans several\nrows (create an event and update the people in it). `dry_run` checks each operation against the\ncurrent data only.',
1612
+ "inputSchema": {
1613
+ "additionalProperties": false,
1614
+ "properties": {
1615
+ "operations": {
1616
+ "items": {
1617
+ "additionalProperties": true,
1618
+ "type": "object"
1619
+ },
1620
+ "type": "array"
1621
+ },
1622
+ "summary": {
1623
+ "anyOf": [
1624
+ {
1625
+ "type": "string"
1626
+ },
1627
+ {
1628
+ "type": "null"
1629
+ }
1630
+ ],
1631
+ "default": null
1632
+ },
1633
+ "dry_run": {
1634
+ "default": false,
1635
+ "type": "boolean"
1636
+ }
1637
+ },
1638
+ "required": [
1639
+ "operations"
1640
+ ],
1641
+ "type": "object"
1642
+ },
1643
+ "annotations": {
1644
+ "title": "Batch",
1645
+ "readOnlyHint": false,
1646
+ "destructiveHint": true,
1647
+ "idempotentHint": false,
1648
+ "openWorldHint": false
1649
+ }
1650
+ },
1651
+ {
1652
+ "name": "align_relations",
1653
+ "description": "Add the reciprocal links missing on a table's `inverse` link columns (e.g. Alice lists Carol\nin `friends` but Carol does not list Alice). Run it after declaring `inverse` on existing data;\ncheck_table reports such rows (code `inverse`). Single-value links already pointing elsewhere\nare conflicts (nothing written). Writes through the tools already keep both sides in step.",
1654
+ "inputSchema": {
1655
+ "additionalProperties": false,
1656
+ "properties": {
1657
+ "table": {
1658
+ "type": "string"
1659
+ },
1660
+ "paths": {
1661
+ "anyOf": [
1662
+ {
1663
+ "items": {
1664
+ "type": "string"
1665
+ },
1666
+ "type": "array"
1667
+ },
1668
+ {
1669
+ "type": "null"
1670
+ }
1671
+ ],
1672
+ "default": null
1673
+ },
1674
+ "dry_run": {
1675
+ "default": false,
1676
+ "type": "boolean"
1677
+ }
1678
+ },
1679
+ "required": [
1680
+ "table"
1681
+ ],
1682
+ "type": "object"
1683
+ },
1684
+ "annotations": {
1685
+ "title": "Align Relations",
1686
+ "readOnlyHint": false,
1687
+ "destructiveHint": false,
1688
+ "idempotentHint": true,
1689
+ "openWorldHint": false
1690
+ }
1691
+ },
1692
+ {
1693
+ "name": "infer_table",
1694
+ "description": "Read-only schema inference from notes' frontmatter.\n- `folder` (recursive; \"\" = whole vault) and/or `paths`: notes not yet in a table. Returns\n `columns` (type, enum `values`, link `ref` to the table most targets belong to, `required`,\n `unique`, `dense`, `from` when the property name is not a valid column name, `stats`),\n `proposal` ready for create_table (`name`, `options.filename` or `timeColumn`, `columns`) and\n `adopt` ready for adopt_rows (`paths`, `rename`, `relocate: false`), plus `notes` to read.\n Review the proposal (names, enums, required) before creating; ask the user when unsure.\n- `table`: keys the table's rows use but the table does not declare (candidates for add_column,\n or keys to drop from rows).\nA string column becomes an enum with at most `max_enum_values` distinct values (default 12).",
1695
+ "inputSchema": {
1696
+ "additionalProperties": false,
1697
+ "properties": {
1698
+ "folder": {
1699
+ "anyOf": [
1700
+ {
1701
+ "type": "string"
1702
+ },
1703
+ {
1704
+ "type": "null"
1705
+ }
1706
+ ],
1707
+ "default": null
1708
+ },
1709
+ "paths": {
1710
+ "anyOf": [
1711
+ {
1712
+ "items": {
1713
+ "type": "string"
1714
+ },
1715
+ "type": "array"
1716
+ },
1717
+ {
1718
+ "type": "null"
1719
+ }
1720
+ ],
1721
+ "default": null
1722
+ },
1723
+ "table": {
1724
+ "anyOf": [
1725
+ {
1726
+ "type": "string"
1727
+ },
1728
+ {
1729
+ "type": "null"
1730
+ }
1731
+ ],
1732
+ "default": null
1733
+ },
1734
+ "name": {
1735
+ "anyOf": [
1736
+ {
1737
+ "type": "string"
1738
+ },
1739
+ {
1740
+ "type": "null"
1741
+ }
1742
+ ],
1743
+ "default": null
1744
+ },
1745
+ "max_enum_values": {
1746
+ "anyOf": [
1747
+ {
1748
+ "type": "integer"
1749
+ },
1750
+ {
1751
+ "type": "null"
1752
+ }
1753
+ ],
1754
+ "default": null
1755
+ }
1756
+ },
1757
+ "type": "object"
1758
+ },
1759
+ "annotations": {
1760
+ "title": "Infer Table",
1761
+ "readOnlyHint": true,
1762
+ "destructiveHint": false,
1763
+ "idempotentHint": true,
1764
+ "openWorldHint": false
1765
+ }
1766
+ },
1767
+ {
1768
+ "name": "semantic_search",
1769
+ "description": 'Find notes by meaning, not exact words: `{query, results: [{path, score, heading, snippet,\ntable?}]}`, one result per note (its best passage), best first. Use it for vague questions\n("the dinner where we talked about moving", "what did I decide about the car") and to find the\nrows to read or update; then read_note / select_rows for the details. Filters: `tables`\n(qualified or short names), `folder`, `min_score` (cosine 0\u20131; ~0.5+ is usually relevant).\nFails with a clear message when semantic search is off in the plugin settings.',
1770
+ "inputSchema": {
1771
+ "additionalProperties": false,
1772
+ "properties": {
1773
+ "query": {
1774
+ "type": "string"
1775
+ },
1776
+ "limit": {
1777
+ "default": 10,
1778
+ "type": "integer"
1779
+ },
1780
+ "tables": {
1781
+ "anyOf": [
1782
+ {
1783
+ "items": {
1784
+ "type": "string"
1785
+ },
1786
+ "type": "array"
1787
+ },
1788
+ {
1789
+ "type": "null"
1790
+ }
1791
+ ],
1792
+ "default": null
1793
+ },
1794
+ "folder": {
1795
+ "anyOf": [
1796
+ {
1797
+ "type": "string"
1798
+ },
1799
+ {
1800
+ "type": "null"
1801
+ }
1802
+ ],
1803
+ "default": null
1804
+ },
1805
+ "min_score": {
1806
+ "anyOf": [
1807
+ {
1808
+ "type": "number"
1809
+ },
1810
+ {
1811
+ "type": "null"
1812
+ }
1813
+ ],
1814
+ "default": null
1815
+ }
1816
+ },
1817
+ "required": [
1818
+ "query"
1819
+ ],
1820
+ "type": "object"
1821
+ },
1822
+ "annotations": {
1823
+ "title": "Semantic Search",
1824
+ "readOnlyHint": true,
1825
+ "destructiveHint": false,
1826
+ "idempotentHint": true,
1827
+ "openWorldHint": false
1828
+ }
1829
+ },
1830
+ {
1831
+ "name": "semantic_index",
1832
+ "description": "Semantic search index: `status` (provider, model, notes, passages, last error), `update`\n(embed notes changed since the last run; the plugin also does it on its own a few seconds after\nedits) or `rebuild` (re-embed everything: slow, and costs money with a paid provider \u2014 ask\nfirst).",
1833
+ "inputSchema": {
1834
+ "additionalProperties": false,
1835
+ "properties": {
1836
+ "action": {
1837
+ "default": "status",
1838
+ "type": "string"
1839
+ }
1840
+ },
1841
+ "type": "object"
1842
+ },
1843
+ "annotations": {
1844
+ "title": "Semantic Index",
1845
+ "readOnlyHint": false,
1846
+ "destructiveHint": false,
1847
+ "idempotentHint": true,
1848
+ "openWorldHint": false
1849
+ }
1850
+ },
1851
+ {
1852
+ "name": "list_migrations",
1853
+ "description": 'The operation journal, newest first: `migration_id` (for undo_migration), `op`, `summary`,\n`schema` (table), `executed_at`, `notes_changed`, `files`, `undone`, `undoes`, `failed`.\nFilters: `op` (e.g. "update_rows"), `table` (substring of the table name, e.g.\n"personal.tasks.task"), `since` (ISO date). `limit` default 50. The journal is kept in the\nvault\'s hidden `.datanotes/journal/` (not notes); entries older than 90 days are dropped.',
1854
+ "inputSchema": {
1855
+ "additionalProperties": false,
1856
+ "properties": {
1857
+ "limit": {
1858
+ "anyOf": [
1859
+ {
1860
+ "type": "integer"
1861
+ },
1862
+ {
1863
+ "type": "null"
1864
+ }
1865
+ ],
1866
+ "default": null
1867
+ },
1868
+ "op": {
1869
+ "anyOf": [
1870
+ {
1871
+ "type": "string"
1872
+ },
1873
+ {
1874
+ "type": "null"
1875
+ }
1876
+ ],
1877
+ "default": null
1878
+ },
1879
+ "table": {
1880
+ "anyOf": [
1881
+ {
1882
+ "type": "string"
1883
+ },
1884
+ {
1885
+ "type": "null"
1886
+ }
1887
+ ],
1888
+ "default": null
1889
+ },
1890
+ "since": {
1891
+ "anyOf": [
1892
+ {
1893
+ "type": "string"
1894
+ },
1895
+ {
1896
+ "type": "null"
1897
+ }
1898
+ ],
1899
+ "default": null
1900
+ }
1901
+ },
1902
+ "type": "object"
1903
+ },
1904
+ "annotations": {
1905
+ "title": "List Migrations",
1906
+ "readOnlyHint": true,
1907
+ "destructiveHint": false,
1908
+ "idempotentHint": true,
1909
+ "openWorldHint": false
1910
+ }
1911
+ },
1912
+ {
1913
+ "name": "merge_rows",
1914
+ "description": 'MERGE (upsert) `rows` into `table` by the key columns `on` (e.g. `["occurred_at"]` or\n`["id"]`): a row matching an existing one updates it (`when_matched`: "update" default or\n"ignore"), the others are inserted (`when_not_matched`: "insert" default or "ignore").\nDate-times are compared after completion with the database time zone. A source key matching\nseveral rows, or repeated, is a conflict. One journaled, undoable operation.',
1915
+ "inputSchema": {
1916
+ "additionalProperties": false,
1917
+ "properties": {
1918
+ "table": {
1919
+ "type": "string"
1920
+ },
1921
+ "on": {
1922
+ "items": {
1923
+ "type": "string"
1924
+ },
1925
+ "type": "array"
1926
+ },
1927
+ "rows": {
1928
+ "items": {
1929
+ "additionalProperties": true,
1930
+ "type": "object"
1931
+ },
1932
+ "type": "array"
1933
+ },
1934
+ "when_matched": {
1935
+ "anyOf": [
1936
+ {
1937
+ "type": "string"
1938
+ },
1939
+ {
1940
+ "type": "null"
1941
+ }
1942
+ ],
1943
+ "default": null
1944
+ },
1945
+ "when_not_matched": {
1946
+ "anyOf": [
1947
+ {
1948
+ "type": "string"
1949
+ },
1950
+ {
1951
+ "type": "null"
1952
+ }
1953
+ ],
1954
+ "default": null
1955
+ },
1956
+ "dry_run": {
1957
+ "default": false,
1958
+ "type": "boolean"
1959
+ }
1960
+ },
1961
+ "required": [
1962
+ "table",
1963
+ "on",
1964
+ "rows"
1965
+ ],
1966
+ "type": "object"
1967
+ },
1968
+ "annotations": {
1969
+ "title": "Merge Rows",
1970
+ "readOnlyHint": false,
1971
+ "destructiveHint": false,
1972
+ "idempotentHint": true,
1973
+ "openWorldHint": false
1974
+ }
1975
+ },
1976
+ {
1977
+ "name": "describe_history",
1978
+ "description": "DESCRIBE HISTORY: the table's versions, newest first \u2014 `version`, `timestamp`, `operation`\n(CREATE TABLE, WRITE, UPDATE, DELETE, MERGE, ALTER TABLE, ADD COLUMNS, RESTORE, UNDO, \u2026;\n`EXTERNAL_EDIT` = changed by hand in Obsidian), `operationMetrics` and `migrationId` (undo).\nWorks for dropped tables too (full `catalog.schema.table`). Use a version with `select_rows`\n(time travel), `table_changes` or `restore_table`.",
1979
+ "inputSchema": {
1980
+ "additionalProperties": false,
1981
+ "properties": {
1982
+ "table": {
1983
+ "type": "string"
1984
+ },
1985
+ "limit": {
1986
+ "anyOf": [
1987
+ {
1988
+ "type": "integer"
1989
+ },
1990
+ {
1991
+ "type": "null"
1992
+ }
1993
+ ],
1994
+ "default": null
1995
+ }
1996
+ },
1997
+ "required": [
1998
+ "table"
1999
+ ],
2000
+ "type": "object"
2001
+ },
2002
+ "annotations": {
2003
+ "title": "Describe History",
2004
+ "readOnlyHint": true,
2005
+ "destructiveHint": false,
2006
+ "idempotentHint": true,
2007
+ "openWorldHint": false
2008
+ }
2009
+ },
2010
+ {
2011
+ "name": "table_changes",
2012
+ "description": 'Change data feed between two versions (both included, end defaults to latest): one entry\nper row change with its values plus `_change_type` (insert, delete, update_preimage,\nupdate_postimage, metadata), `_commit_version`, `_commit_timestamp`, `_operation`, `path`.\nUse it to answer "what changed since \u2026" without diffing full tables.',
2013
+ "inputSchema": {
2014
+ "additionalProperties": false,
2015
+ "properties": {
2016
+ "table": {
2017
+ "type": "string"
2018
+ },
2019
+ "start_version": {
2020
+ "type": "integer"
2021
+ },
2022
+ "end_version": {
2023
+ "anyOf": [
2024
+ {
2025
+ "type": "integer"
2026
+ },
2027
+ {
2028
+ "type": "null"
2029
+ }
2030
+ ],
2031
+ "default": null
2032
+ }
2033
+ },
2034
+ "required": [
2035
+ "table",
2036
+ "start_version"
2037
+ ],
2038
+ "type": "object"
2039
+ },
2040
+ "annotations": {
2041
+ "title": "Table Changes",
2042
+ "readOnlyHint": true,
2043
+ "destructiveHint": false,
2044
+ "idempotentHint": true,
2045
+ "openWorldHint": false
2046
+ }
2047
+ },
2048
+ {
2049
+ "name": "list_changes",
2050
+ "description": "Change feed across all tables: numbered row changes (`seq`), oldest first, from engine writes\nand from hand edits (`source: external`). Each has `table`, `op` (insert, update, delete, move,\nschema), `path`, `changes` ({column: {before, after}}), `actor`, `migration`. MCP tool calls are `op: tool_call` events (`call`: tool, args, ok, value, servedBy), returned only when `ops` includes tool_call. Pass the returned\n`last` as `since` next time (`head` is the newest number); `wait_ms` waits for a new change (long poll). `gap: true` means\nolder changes were dropped: re-read the tables. `where` filters rows as in select_rows (on the values after the change). Per-table versions: `table_changes`.",
2051
+ "inputSchema": {
2052
+ "additionalProperties": false,
2053
+ "properties": {
2054
+ "since": {
2055
+ "type": "integer",
2056
+ "default": 0
2057
+ },
2058
+ "tables": {
2059
+ "anyOf": [
2060
+ {
2061
+ "items": {
2062
+ "type": "string"
2063
+ },
2064
+ "type": "array"
2065
+ },
2066
+ {
2067
+ "type": "null"
2068
+ }
2069
+ ],
2070
+ "default": null
2071
+ },
2072
+ "ops": {
2073
+ "anyOf": [
2074
+ {
2075
+ "items": {
2076
+ "enum": [
2077
+ "insert",
2078
+ "update",
2079
+ "delete",
2080
+ "move",
2081
+ "schema",
2082
+ "tool_call"
2083
+ ],
2084
+ "type": "string"
2085
+ },
2086
+ "type": "array"
2087
+ },
2088
+ {
2089
+ "type": "null"
2090
+ }
2091
+ ],
2092
+ "default": null
2093
+ },
2094
+ "columns": {
2095
+ "anyOf": [
2096
+ {
2097
+ "items": {
2098
+ "type": "string"
2099
+ },
2100
+ "type": "array"
2101
+ },
2102
+ {
2103
+ "type": "null"
2104
+ }
2105
+ ],
2106
+ "default": null
2107
+ },
2108
+ "where": {
2109
+ "anyOf": [
2110
+ {
2111
+ "additionalProperties": true,
2112
+ "type": "object"
2113
+ },
2114
+ {
2115
+ "type": "null"
2116
+ }
2117
+ ],
2118
+ "default": null
2119
+ },
2120
+ "exclude_actor": {
2121
+ "anyOf": [
2122
+ {
2123
+ "type": "string"
2124
+ },
2125
+ {
2126
+ "type": "null"
2127
+ }
2128
+ ],
2129
+ "default": null
2130
+ },
2131
+ "limit": {
2132
+ "type": "integer",
2133
+ "default": 500
2134
+ },
2135
+ "wait_ms": {
2136
+ "type": "integer",
2137
+ "default": 0
2138
+ }
2139
+ },
2140
+ "type": "object"
2141
+ },
2142
+ "annotations": {
2143
+ "title": "List Changes",
2144
+ "readOnlyHint": true,
2145
+ "destructiveHint": false,
2146
+ "idempotentHint": true,
2147
+ "openWorldHint": false
2148
+ }
2149
+ },
2150
+ {
2151
+ "name": "list_webhooks",
2152
+ "description": "Webhooks of the change feed: id, url, filter (tables, ops, columns, exclude_actor), `cursor` (last change delivered), `status` (ok, failing, disabled), `lastDelivery`, `lastError`. Secrets are not shown.",
2153
+ "inputSchema": {
2154
+ "additionalProperties": false,
2155
+ "properties": {},
2156
+ "type": "object"
2157
+ },
2158
+ "annotations": {
2159
+ "title": "List Webhooks",
2160
+ "readOnlyHint": true,
2161
+ "destructiveHint": false,
2162
+ "idempotentHint": true,
2163
+ "openWorldHint": false
2164
+ }
2165
+ },
2166
+ {
2167
+ "name": "create_webhook",
2168
+ "description": "Push row changes to a URL (a service that would rather be called than poll `list_changes`): batches of up to 100 events POSTed as `{webhook, events, last}`, signed with `X-Datanotes-Signature: sha256=<HMAC of the body>`, retried with backoff until a 2xx. Starts from now unless `since`. Returns the webhook with its `secret` \u2014 shown only here: give it to the receiver.",
2169
+ "inputSchema": {
2170
+ "additionalProperties": false,
2171
+ "properties": {
2172
+ "url": {
2173
+ "type": "string"
2174
+ },
2175
+ "tables": {
2176
+ "anyOf": [
2177
+ {
2178
+ "items": {
2179
+ "type": "string"
2180
+ },
2181
+ "type": "array"
2182
+ },
2183
+ {
2184
+ "type": "null"
2185
+ }
2186
+ ],
2187
+ "default": null
2188
+ },
2189
+ "ops": {
2190
+ "anyOf": [
2191
+ {
2192
+ "items": {
2193
+ "enum": [
2194
+ "insert",
2195
+ "update",
2196
+ "delete",
2197
+ "move",
2198
+ "schema",
2199
+ "tool_call"
2200
+ ],
2201
+ "type": "string"
2202
+ },
2203
+ "type": "array"
2204
+ },
2205
+ {
2206
+ "type": "null"
2207
+ }
2208
+ ],
2209
+ "default": null
2210
+ },
2211
+ "columns": {
2212
+ "anyOf": [
2213
+ {
2214
+ "items": {
2215
+ "type": "string"
2216
+ },
2217
+ "type": "array"
2218
+ },
2219
+ {
2220
+ "type": "null"
2221
+ }
2222
+ ],
2223
+ "default": null
2224
+ },
2225
+ "exclude_actor": {
2226
+ "anyOf": [
2227
+ {
2228
+ "type": "string"
2229
+ },
2230
+ {
2231
+ "type": "null"
2232
+ }
2233
+ ],
2234
+ "default": null
2235
+ },
2236
+ "where": {
2237
+ "anyOf": [
2238
+ {
2239
+ "additionalProperties": true,
2240
+ "type": "object"
2241
+ },
2242
+ {
2243
+ "type": "null"
2244
+ }
2245
+ ],
2246
+ "default": null
2247
+ },
2248
+ "since": {
2249
+ "anyOf": [
2250
+ {
2251
+ "type": "integer"
2252
+ },
2253
+ {
2254
+ "type": "null"
2255
+ }
2256
+ ],
2257
+ "default": null
2258
+ }
2259
+ },
2260
+ "required": [
2261
+ "url"
2262
+ ],
2263
+ "type": "object"
2264
+ },
2265
+ "annotations": {
2266
+ "title": "Create Webhook",
2267
+ "readOnlyHint": false,
2268
+ "destructiveHint": false,
2269
+ "idempotentHint": false,
2270
+ "openWorldHint": true
2271
+ }
2272
+ },
2273
+ {
2274
+ "name": "delete_webhook",
2275
+ "description": "Stop and remove a webhook (by `id` from list_webhooks).",
2276
+ "inputSchema": {
2277
+ "additionalProperties": false,
2278
+ "properties": {
2279
+ "id": {
2280
+ "type": "string"
2281
+ }
2282
+ },
2283
+ "required": [
2284
+ "id"
2285
+ ],
2286
+ "type": "object"
2287
+ },
2288
+ "annotations": {
2289
+ "title": "Delete Webhook",
2290
+ "readOnlyHint": false,
2291
+ "destructiveHint": true,
2292
+ "idempotentHint": true,
2293
+ "openWorldHint": false
2294
+ }
2295
+ },
2296
+ {
2297
+ "name": "restore_table",
2298
+ "description": "RESTORE TABLE to a `version` or `timestamp`: rows and definition return to that state \u2014\nrows added since are deleted, changed rows get their old content, removed rows come back (a\ndropped table is re-created). History is not rewritten: the restore is a new version, and\n`undo_migration` reverts it. Run with `dry_run` first and show the user what changes.",
2299
+ "inputSchema": {
2300
+ "additionalProperties": false,
2301
+ "properties": {
2302
+ "table": {
2303
+ "type": "string"
2304
+ },
2305
+ "version": {
2306
+ "anyOf": [
2307
+ {
2308
+ "type": "integer"
2309
+ },
2310
+ {
2311
+ "type": "null"
2312
+ }
2313
+ ],
2314
+ "default": null
2315
+ },
2316
+ "timestamp": {
2317
+ "anyOf": [
2318
+ {
2319
+ "type": "string"
2320
+ },
2321
+ {
2322
+ "type": "null"
2323
+ }
2324
+ ],
2325
+ "default": null
2326
+ },
2327
+ "dry_run": {
2328
+ "default": false,
2329
+ "type": "boolean"
2330
+ }
2331
+ },
2332
+ "required": [
2333
+ "table"
2334
+ ],
2335
+ "type": "object"
2336
+ },
2337
+ "annotations": {
2338
+ "title": "Restore Table",
2339
+ "readOnlyHint": false,
2340
+ "destructiveHint": true,
2341
+ "idempotentHint": false,
2342
+ "openWorldHint": false
2343
+ }
2344
+ },
2345
+ {
2346
+ "name": "vacuum_table",
2347
+ "description": "Delete transaction-log history older than `retain_from_version` (default: keep only the\nlatest version); time travel before it becomes impossible. Rows are not touched. `dry_run`\ndefaults to true: it lists the log files that would go. Only on the user's explicit request.",
2348
+ "inputSchema": {
2349
+ "additionalProperties": false,
2350
+ "properties": {
2351
+ "table": {
2352
+ "type": "string"
2353
+ },
2354
+ "retain_from_version": {
2355
+ "anyOf": [
2356
+ {
2357
+ "type": "integer"
2358
+ },
2359
+ {
2360
+ "type": "null"
2361
+ }
2362
+ ],
2363
+ "default": null
2364
+ },
2365
+ "dry_run": {
2366
+ "default": true,
2367
+ "type": "boolean"
2368
+ }
2369
+ },
2370
+ "required": [
2371
+ "table"
2372
+ ],
2373
+ "type": "object"
2374
+ },
2375
+ "annotations": {
2376
+ "title": "Vacuum Table",
2377
+ "readOnlyHint": false,
2378
+ "destructiveHint": true,
2379
+ "idempotentHint": true,
2380
+ "openWorldHint": false
2381
+ }
2382
+ },
2383
+ {
2384
+ "name": "add_constraint",
2385
+ "description": 'ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match,\ne.g. `{"value": {"gte": 1, "lte": 5}}` (a condition on an empty value passes, like SQL).\nRefused while existing rows violate it (they are listed); then enforced on every write.',
2386
+ "inputSchema": {
2387
+ "additionalProperties": false,
2388
+ "properties": {
2389
+ "table": {
2390
+ "type": "string"
2391
+ },
2392
+ "name": {
2393
+ "type": "string"
2394
+ },
2395
+ "check": {
2396
+ "additionalProperties": true,
2397
+ "type": "object"
2398
+ },
2399
+ "dry_run": {
2400
+ "default": false,
2401
+ "type": "boolean"
2402
+ }
2403
+ },
2404
+ "required": [
2405
+ "table",
2406
+ "name",
2407
+ "check"
2408
+ ],
2409
+ "type": "object"
2410
+ },
2411
+ "annotations": {
2412
+ "title": "Add Constraint",
2413
+ "readOnlyHint": false,
2414
+ "destructiveHint": false,
2415
+ "idempotentHint": false,
2416
+ "openWorldHint": false
2417
+ }
2418
+ },
2419
+ {
2420
+ "name": "drop_constraint",
2421
+ "description": "Remove the CHECK constraint `name` from `table`.",
2422
+ "inputSchema": {
2423
+ "additionalProperties": false,
2424
+ "properties": {
2425
+ "table": {
2426
+ "type": "string"
2427
+ },
2428
+ "name": {
2429
+ "type": "string"
2430
+ },
2431
+ "dry_run": {
2432
+ "default": false,
2433
+ "type": "boolean"
2434
+ }
2435
+ },
2436
+ "required": [
2437
+ "table",
2438
+ "name"
2439
+ ],
2440
+ "type": "object"
2441
+ },
2442
+ "annotations": {
2443
+ "title": "Drop Constraint",
2444
+ "readOnlyHint": false,
2445
+ "destructiveHint": false,
2446
+ "idempotentHint": false,
2447
+ "openWorldHint": false
2448
+ }
2449
+ },
2450
+ {
2451
+ "name": "create_view",
2452
+ "description": "Create (or `replace`) a view: a named select stored in database.yaml. Name it with the prefix\n`vw_` (e.g. `vw_open_tasks`): views share names and folders with tables. `query` takes the\nselect_rows parameters (table, columns, where, order_by, limit, join, group_by, aggregates, expand;\nrelative dates keep it current) and must run now. `comment` and `aliases` let agents find it;\n`labels` are column headings. Read it with select_rows(table=<view>). A note shows it with a\n```datanotes block containing `view: <name>` (drawn live by the client; nothing is written into\nthe note). Filters may read the note that shows the view: `{this.date}`, `{this.date+1d}` (a\nfrontmatter value, date arithmetic), `{this.link}` (a link to that note), `{this.name}`. The view\nalso gets a note in its schema folder.",
2453
+ "inputSchema": {
2454
+ "additionalProperties": false,
2455
+ "properties": {
2456
+ "name": {
2457
+ "type": "string"
2458
+ },
2459
+ "query": {
2460
+ "additionalProperties": true,
2461
+ "type": "object"
2462
+ },
2463
+ "catalog": {
2464
+ "anyOf": [
2465
+ {
2466
+ "type": "string"
2467
+ },
2468
+ {
2469
+ "type": "null"
2470
+ }
2471
+ ],
2472
+ "default": null
2473
+ },
2474
+ "schema": {
2475
+ "anyOf": [
2476
+ {
2477
+ "type": "string"
2478
+ },
2479
+ {
2480
+ "type": "null"
2481
+ }
2482
+ ],
2483
+ "default": null
2484
+ },
2485
+ "comment": {
2486
+ "anyOf": [
2487
+ {
2488
+ "type": "string"
2489
+ },
2490
+ {
2491
+ "type": "null"
2492
+ }
2493
+ ],
2494
+ "default": null
2495
+ },
2496
+ "aliases": {
2497
+ "anyOf": [
2498
+ {
2499
+ "items": {
2500
+ "type": "string"
2501
+ },
2502
+ "type": "array"
2503
+ },
2504
+ {
2505
+ "type": "null"
2506
+ }
2507
+ ],
2508
+ "default": null
2509
+ },
2510
+ "labels": {
2511
+ "anyOf": [
2512
+ {
2513
+ "additionalProperties": {
2514
+ "type": "string"
2515
+ },
2516
+ "type": "object"
2517
+ },
2518
+ {
2519
+ "type": "null"
2520
+ }
2521
+ ],
2522
+ "default": null
2523
+ },
2524
+ "replace": {
2525
+ "default": false,
2526
+ "type": "boolean"
2527
+ },
2528
+ "dry_run": {
2529
+ "default": false,
2530
+ "type": "boolean"
2531
+ }
2532
+ },
2533
+ "required": [
2534
+ "name",
2535
+ "query"
2536
+ ],
2537
+ "type": "object"
2538
+ },
2539
+ "annotations": {
2540
+ "title": "Create View",
2541
+ "readOnlyHint": false,
2542
+ "destructiveHint": false,
2543
+ "idempotentHint": false,
2544
+ "openWorldHint": false
2545
+ }
2546
+ },
2547
+ {
2548
+ "name": "drop_view",
2549
+ "description": "Remove a view from `database.yaml` (undo with `undo_migration`).",
2550
+ "inputSchema": {
2551
+ "additionalProperties": false,
2552
+ "properties": {
2553
+ "view": {
2554
+ "type": "string"
2555
+ },
2556
+ "dry_run": {
2557
+ "default": false,
2558
+ "type": "boolean"
2559
+ }
2560
+ },
2561
+ "required": [
2562
+ "view"
2563
+ ],
2564
+ "type": "object"
2565
+ },
2566
+ "annotations": {
2567
+ "title": "Drop View",
2568
+ "readOnlyHint": false,
2569
+ "destructiveHint": true,
2570
+ "idempotentHint": false,
2571
+ "openWorldHint": false
2572
+ }
2573
+ },
2574
+ {
2575
+ "name": "clone_table",
2576
+ "description": "CREATE TABLE `target` CLONE `source`: same definition plus independent copies of its rows\n(deep clone), optionally as of a `version` / `timestamp`. `shallow=true` copies the\ndefinition only (CREATE TABLE LIKE). `target`: `catalog.schema.table`, `schema.table` (default\ncatalog) or a name (source's catalog and schema). Useful for experiments, e.g. a sandbox copy\nin the `agent` catalog.",
2577
+ "inputSchema": {
2578
+ "additionalProperties": false,
2579
+ "properties": {
2580
+ "source": {
2581
+ "type": "string"
2582
+ },
2583
+ "target": {
2584
+ "type": "string"
2585
+ },
2586
+ "version": {
2587
+ "anyOf": [
2588
+ {
2589
+ "type": "integer"
2590
+ },
2591
+ {
2592
+ "type": "null"
2593
+ }
2594
+ ],
2595
+ "default": null
2596
+ },
2597
+ "timestamp": {
2598
+ "anyOf": [
2599
+ {
2600
+ "type": "string"
2601
+ },
2602
+ {
2603
+ "type": "null"
2604
+ }
2605
+ ],
2606
+ "default": null
2607
+ },
2608
+ "shallow": {
2609
+ "default": false,
2610
+ "type": "boolean"
2611
+ },
2612
+ "dry_run": {
2613
+ "default": false,
2614
+ "type": "boolean"
2615
+ }
2616
+ },
2617
+ "required": [
2618
+ "source",
2619
+ "target"
2620
+ ],
2621
+ "type": "object"
2622
+ },
2623
+ "annotations": {
2624
+ "title": "Clone Table",
2625
+ "readOnlyHint": false,
2626
+ "destructiveHint": false,
2627
+ "idempotentHint": false,
2628
+ "openWorldHint": false
2629
+ }
2630
+ },
2631
+ {
2632
+ "name": "recompute_columns",
2633
+ "description": "Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after\nrows were edited outside the plugin or a generated expression changed with `alter_column`.\nAlso gives rows without an `id` a new one, and a duplicated note (same `id` as an older row)\na new id. `new_ids=true` regenerates every id in scope: only on the user's explicit request.\n`check_table` reports stale values with code `generated`. No-op when nothing is stale;\notherwise journaled (undo_migration) and a RECOMPUTE version in the table's history.",
2634
+ "inputSchema": {
2635
+ "additionalProperties": false,
2636
+ "properties": {
2637
+ "table": {
2638
+ "type": "string"
2639
+ },
2640
+ "paths": {
2641
+ "anyOf": [
2642
+ {
2643
+ "items": {
2644
+ "type": "string"
2645
+ },
2646
+ "type": "array"
2647
+ },
2648
+ {
2649
+ "type": "null"
2650
+ }
2651
+ ],
2652
+ "default": null
2653
+ },
2654
+ "new_ids": {
2655
+ "default": false,
2656
+ "type": "boolean"
2657
+ },
2658
+ "dry_run": {
2659
+ "default": false,
2660
+ "type": "boolean"
2661
+ }
2662
+ },
2663
+ "required": [
2664
+ "table"
2665
+ ],
2666
+ "type": "object"
2667
+ },
2668
+ "annotations": {
2669
+ "title": "Recompute Columns",
2670
+ "readOnlyHint": false,
2671
+ "destructiveHint": false,
2672
+ "idempotentHint": true,
2673
+ "openWorldHint": false
2674
+ }
2675
+ },
2676
+ {
2677
+ "name": "graph_neighbors",
2678
+ "description": 'Direct neighbours of notes: what they link to (`out`) and what links to them (`in`,\nbacklinks), with counts per edge label. `direction`: out, in or both (default).\n\n`from_nodes` selects the notes: `{"paths": [...]}` and/or `{"table": ..., "where": {...}}`.\nEdges are labelled with their link column (`people`, `event`, \u2026) or `link` for other links.',
2679
+ "inputSchema": {
2680
+ "additionalProperties": false,
2681
+ "properties": {
2682
+ "from_nodes": {
2683
+ "additionalProperties": true,
2684
+ "type": "object"
2685
+ },
2686
+ "direction": {
2687
+ "anyOf": [
2688
+ {
2689
+ "type": "string"
2690
+ },
2691
+ {
2692
+ "type": "null"
2693
+ }
2694
+ ],
2695
+ "default": null
2696
+ },
2697
+ "edges": {
2698
+ "anyOf": [
2699
+ {
2700
+ "items": {
2701
+ "type": "string"
2702
+ },
2703
+ "type": "array"
2704
+ },
2705
+ {
2706
+ "type": "null"
2707
+ }
2708
+ ],
2709
+ "default": null
2710
+ }
2711
+ },
2712
+ "required": [
2713
+ "from_nodes"
2714
+ ],
2715
+ "type": "object"
2716
+ },
2717
+ "annotations": {
2718
+ "title": "Graph Neighbors",
2719
+ "readOnlyHint": true,
2720
+ "destructiveHint": false,
2721
+ "idempotentHint": true,
2722
+ "openWorldHint": false
2723
+ }
2724
+ },
2725
+ {
2726
+ "name": "graph_traverse",
2727
+ "description": 'Breadth-first walk over links from `from_nodes` (`{"paths": [...]}` and/or `{"table", "where"}`).\n\n- `direction`: out (default, follow links), in (follow backlinks) or both.\n- `edges`: edge labels to follow (link columns such as `people`, `event`, or `link`).\n- `tables`: return only notes of these tables; `through`: only walk on through these tables.\n- `min_depth` (default 1) / `max_depth` (default 2, max 10), `limit` (default 500).\n\nEach node comes with `depth` and `via` (one shortest route). Example \u2014 moods tied to events\nwith Alice: from `{"table": "person", "where": {"name": "Alice"}}`, direction `in`, edges\n`["people", "event"]`, tables `["mood"]`, max_depth 2. Feed the paths to `select_rows` with\n`where: {"path": {"in": [...]}}` to aggregate them.',
2728
+ "inputSchema": {
2729
+ "additionalProperties": false,
2730
+ "properties": {
2731
+ "from_nodes": {
2732
+ "additionalProperties": true,
2733
+ "type": "object"
2734
+ },
2735
+ "direction": {
2736
+ "anyOf": [
2737
+ {
2738
+ "type": "string"
2739
+ },
2740
+ {
2741
+ "type": "null"
2742
+ }
2743
+ ],
2744
+ "default": null
2745
+ },
2746
+ "edges": {
2747
+ "anyOf": [
2748
+ {
2749
+ "items": {
2750
+ "type": "string"
2751
+ },
2752
+ "type": "array"
2753
+ },
2754
+ {
2755
+ "type": "null"
2756
+ }
2757
+ ],
2758
+ "default": null
2759
+ },
2760
+ "tables": {
2761
+ "anyOf": [
2762
+ {
2763
+ "items": {
2764
+ "type": "string"
2765
+ },
2766
+ "type": "array"
2767
+ },
2768
+ {
2769
+ "type": "null"
2770
+ }
2771
+ ],
2772
+ "default": null
2773
+ },
2774
+ "through": {
2775
+ "anyOf": [
2776
+ {
2777
+ "items": {
2778
+ "type": "string"
2779
+ },
2780
+ "type": "array"
2781
+ },
2782
+ {
2783
+ "type": "null"
2784
+ }
2785
+ ],
2786
+ "default": null
2787
+ },
2788
+ "min_depth": {
2789
+ "anyOf": [
2790
+ {
2791
+ "type": "integer"
2792
+ },
2793
+ {
2794
+ "type": "null"
2795
+ }
2796
+ ],
2797
+ "default": null
2798
+ },
2799
+ "max_depth": {
2800
+ "anyOf": [
2801
+ {
2802
+ "type": "integer"
2803
+ },
2804
+ {
2805
+ "type": "null"
2806
+ }
2807
+ ],
2808
+ "default": null
2809
+ },
2810
+ "limit": {
2811
+ "anyOf": [
2812
+ {
2813
+ "type": "integer"
2814
+ },
2815
+ {
2816
+ "type": "null"
2817
+ }
2818
+ ],
2819
+ "default": null
2820
+ }
2821
+ },
2822
+ "required": [
2823
+ "from_nodes"
2824
+ ],
2825
+ "type": "object"
2826
+ },
2827
+ "annotations": {
2828
+ "title": "Graph Traverse",
2829
+ "readOnlyHint": true,
2830
+ "destructiveHint": false,
2831
+ "idempotentHint": true,
2832
+ "openWorldHint": false
2833
+ }
2834
+ },
2835
+ {
2836
+ "name": "graph_path",
2837
+ "description": 'Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or\n`{"table", "where"}`): `found`, `length` and the steps (`from`, `label`, `direction`, `to`).\n`direction` both by default; `max_depth` default 6 (max 10).',
2838
+ "inputSchema": {
2839
+ "additionalProperties": false,
2840
+ "properties": {
2841
+ "from_nodes": {
2842
+ "additionalProperties": true,
2843
+ "type": "object"
2844
+ },
2845
+ "to_nodes": {
2846
+ "additionalProperties": true,
2847
+ "type": "object"
2848
+ },
2849
+ "direction": {
2850
+ "anyOf": [
2851
+ {
2852
+ "type": "string"
2853
+ },
2854
+ {
2855
+ "type": "null"
2856
+ }
2857
+ ],
2858
+ "default": null
2859
+ },
2860
+ "edges": {
2861
+ "anyOf": [
2862
+ {
2863
+ "items": {
2864
+ "type": "string"
2865
+ },
2866
+ "type": "array"
2867
+ },
2868
+ {
2869
+ "type": "null"
2870
+ }
2871
+ ],
2872
+ "default": null
2873
+ },
2874
+ "max_depth": {
2875
+ "anyOf": [
2876
+ {
2877
+ "type": "integer"
2878
+ },
2879
+ {
2880
+ "type": "null"
2881
+ }
2882
+ ],
2883
+ "default": null
2884
+ }
2885
+ },
2886
+ "required": [
2887
+ "from_nodes",
2888
+ "to_nodes"
2889
+ ],
2890
+ "type": "object"
2891
+ },
2892
+ "annotations": {
2893
+ "title": "Graph Path",
2894
+ "readOnlyHint": true,
2895
+ "destructiveHint": false,
2896
+ "idempotentHint": true,
2897
+ "openWorldHint": false
2898
+ }
2899
+ }
2900
+ ];
2901
+
2902
+ // src/api/requests.ts
2903
+ var OperationInputError = class extends Error {
2904
+ constructor() {
2905
+ super(...arguments);
2906
+ this.name = "OperationInputError";
2907
+ }
2908
+ };
2909
+ function compact(o) {
2910
+ return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0 && v !== null));
2911
+ }
2912
+ function pick(a, keys) {
2913
+ return compact(Object.fromEntries(keys.map((k) => [k, a[k]])));
2914
+ }
2915
+ var dry = (a) => a.dry_run === true ? { dry_run: true } : {};
2916
+ var ROUTES = {
2917
+ list_tables: () => ["/tables/", {}],
2918
+ describe_table: (a) => ["/tables/describe/", pick(a, ["table"])],
2919
+ describe_database: () => ["/database/", {}],
2920
+ configure_database: (a) => ["/database/configure/", pick(a, ["root", "default_catalog", "default_schema", "default_partition", "filename", "archive_folder", "timezone", "history"])],
2921
+ create_table: (a) => ["/ddl/", { op: "create_table", ...pick(a, ["name", "schema", "catalog", "time_column", "columns", "options", "fields", "body"]), ...dry(a) }],
2922
+ drop_table: (a) => ["/ddl/", { op: "drop_table", ...pick(a, ["table", "cascade"]), ...dry(a) }],
2923
+ add_column: (a) => ["/ddl/", { op: "add_column", ...pick(a, ["table", "column"]), ...a.dense === true ? { dense: true } : {}, ...dry(a) }],
2924
+ rename_column: (a) => ["/ddl/", { op: "rename_column", ...pick(a, ["table"]), ...compact({ from: a.from_column, to: a.to_column }), ...dry(a) }],
2925
+ drop_column: (a) => ["/ddl/", { op: "drop_column", ...pick(a, ["table", "name"]), ...dry(a) }],
2926
+ alter_column: (a) => ["/ddl/", { op: "alter_column", ...pick(a, ["table", "name", "changes"]), ...dry(a) }],
2927
+ alter_table: (a) => {
2928
+ const extra = {};
2929
+ if (a.clear_row_template === true) extra.row_template = "";
2930
+ else if (typeof a.row_template === "string") extra.row_template = a.row_template;
2931
+ if (a.history !== void 0 && a.history !== null) {
2932
+ const h = { on: true, off: false, inherit: "inherit" }[String(a.history)];
2933
+ if (h === void 0) throw new OperationInputError(`history must be "on", "off" or "inherit"`);
2934
+ extra.history = h;
2935
+ }
2936
+ return ["/ddl/", { op: "alter_table", ...pick(a, ["table", "catalog", "schema", "name", "partition", "filename", "description", "aliases", "exclude"]), ...extra, ...dry(a) }];
2937
+ },
2938
+ define_base: (a) => ["/ddl/", { op: "define_base", ...pick(a, ["name", "columns", "extends", "comment", "rename_columns", "drop_columns"]), ...dry(a) }],
2939
+ set_table_bases: (a) => ["/ddl/", { op: "set_table_bases", ...pick(a, ["table", "bases"]), ...dry(a) }],
2940
+ rename_value: (a) => ["/ddl/", { op: "rename_value", ...pick(a, ["table", "column"]), ...compact({ from: a.from_value, to: a.to_value }), ...dry(a) }],
2941
+ add_constraint: (a) => ["/ddl/", { op: "add_constraint", ...pick(a, ["table", "name", "check"]), ...dry(a) }],
2942
+ drop_constraint: (a) => ["/ddl/", { op: "drop_constraint", ...pick(a, ["table", "name"]), ...dry(a) }],
2943
+ create_view: (a) => ["/ddl/", { op: "create_view", ...pick(a, ["name", "query", "catalog", "schema", "comment", "aliases", "labels"]), ...a.replace === true ? { replace: true } : {}, ...dry(a) }],
2944
+ drop_view: (a) => ["/ddl/", { op: "drop_view", ...pick(a, ["view"]), ...dry(a) }],
2945
+ clone_table: (a) => ["/ddl/", { op: "clone_table", ...pick(a, ["source", "target", "version", "timestamp"]), ...a.shallow === true ? { shallow: true } : {}, ...dry(a) }],
2946
+ insert_row: (a) => ["/rows/insert/", { ...pick(a, ["table", "values", "body", "path"]), ...dry(a) }],
2947
+ update_rows: (a) => ["/rows/update/", { ...pick(a, ["table", "where", "unset", "body", "expect_rows"]), ...compact({ set: a.set_values }), ...dry(a) }],
2948
+ update_row: (a) => ["/rows/update-one/", { ...pick(a, ["table", "id", "path", "unset", "body", "body_sections", "body_prepend", "body_append", "expect"]), ...compact({ set: a.set_values }), ...dry(a) }],
2949
+ delete_rows: (a) => ["/rows/delete/", { ...pick(a, ["table", "where", "mode", "on_referenced"]), ...dry(a) }],
2950
+ move_rows: (a) => ["/rows/move/", { ...pick(a, ["table", "to_table", "where", "rename", "drop"]), ...compact({ set: a.set_values }), ...a.relocate === true ? { relocate: true } : {}, ...dry(a) }],
2951
+ adopt_rows: (a) => ["/rows/adopt/", { ...pick(a, ["table", "paths", "rename", "per_row", "drop"]), ...compact({ set: a.set_values }), ...a.relocate === false ? { relocate: false } : {}, ...dry(a) }],
2952
+ merge_rows: (a) => ["/rows/merge/", { ...pick(a, ["table", "on", "rows", "when_matched", "when_not_matched"]), ...dry(a) }],
2953
+ recompute_columns: (a) => ["/rows/recompute/", { ...pick(a, ["table", "paths"]), ...a.new_ids === true ? { new_ids: true } : {}, ...dry(a) }],
2954
+ align_relations: (a) => ["/rows/align-relations/", { ...pick(a, ["table", "paths"]), ...dry(a) }],
2955
+ select_rows: (a) => ["/select/", { ...pick(a, ["table", "columns", "where", "order_by", "limit", "offset", "expand", "join", "group_by", "aggregates", "version", "timestamp"]), ...a.include_body === true ? { include_body: true } : {} }],
2956
+ check_table: (a) => ["/check/", pick(a, ["table"])],
2957
+ undo_migration: (a) => ["/migrations/undo/", pick(a, ["migration_id"])],
2958
+ list_migrations: (a) => ["/migrations/list/", pick(a, ["limit", "op", "table", "since"])],
2959
+ batch: (a) => ["/batch/", { ...pick(a, ["operations", "summary"]), ...dry(a) }],
2960
+ infer_table: (a) => ["/tables/infer/", pick(a, ["folder", "paths", "table", "name", "max_enum_values"])],
2961
+ semantic_search: (a) => ["/search/semantic/", pick(a, ["query", "limit", "tables", "folder", "min_score"])],
2962
+ semantic_index: (a) => {
2963
+ const action = String(a.action ?? "status");
2964
+ if (action === "status") return ["/search/semantic/status/", {}];
2965
+ if (action !== "update" && action !== "rebuild") throw new OperationInputError(`action must be "status", "update" or "rebuild"`);
2966
+ return ["/search/semantic/sync/", { rebuild: action === "rebuild" }];
2967
+ },
2968
+ describe_history: (a) => ["/history/", pick(a, ["table", "limit"])],
2969
+ table_changes: (a) => ["/history/changes/", pick(a, ["table", "start_version", "end_version"])],
2970
+ list_changes: (a) => ["/changes/", pick(a, ["since", "tables", "ops", "columns", "exclude_actor", "where", "limit", "wait_ms"])],
2971
+ list_webhooks: () => ["/webhooks/", {}],
2972
+ create_webhook: (a) => ["/webhooks/create/", pick(a, ["url", "tables", "ops", "columns", "exclude_actor", "where", "since"])],
2973
+ delete_webhook: (a) => ["/webhooks/delete/", pick(a, ["id"])],
2974
+ restore_table: (a) => ["/history/restore/", { ...pick(a, ["table", "version", "timestamp"]), ...dry(a) }],
2975
+ vacuum_table: (a) => ["/history/vacuum/", { ...pick(a, ["table", "retain_from_version"]), ...dry(a) }],
2976
+ graph_neighbors: (a) => ["/graph/neighbors/", compact({ from: a.from_nodes, direction: a.direction, edges: a.edges })],
2977
+ graph_traverse: (a) => [
2978
+ "/graph/traverse/",
2979
+ compact({ from: a.from_nodes, direction: a.direction, edges: a.edges, tables: a.tables, through: a.through, min_depth: a.min_depth, max_depth: a.max_depth, limit: a.limit })
2980
+ ],
2981
+ graph_path: (a) => ["/graph/path/", compact({ from: a.from_nodes, to: a.to_nodes, direction: a.direction, edges: a.edges, max_depth: a.max_depth })]
2982
+ };
2983
+ var ROUTE_PREFIX = "/datanotes";
2984
+ var NOTE_JSON = "application/vnd.olrapi.note+json";
2985
+ var encodePath = (p) => p.split("/").map(encodeURIComponent).join("/");
2986
+ function operationRequest(name, args = {}) {
2987
+ if (name === "read_note") {
2988
+ const path2 = String(args.path ?? "").replace(/^\/+/, "");
2989
+ if (!path2 || path2.endsWith("/")) throw new OperationInputError("path must name a file");
2990
+ return { method: "GET", path: `/vault/${encodePath(path2)}`, ...args.as_json === true ? { accept: NOTE_JSON } : {} };
2991
+ }
2992
+ if (name === "list_directory") {
2993
+ const dir = String(args.path ?? "").replace(/^\/+|\/+$/g, "");
2994
+ return { method: "GET", path: dir ? `/vault/${encodePath(dir)}/` : "/vault/" };
2995
+ }
2996
+ if (name === "search_simple") {
2997
+ const ctx = typeof args.context_length === "number" ? args.context_length : 100;
2998
+ return { method: "POST", path: `/search/simple/?query=${encodeURIComponent(String(args.query ?? ""))}&contextLength=${ctx}` };
2999
+ }
3000
+ const route = ROUTES[name];
3001
+ if (!route) throw new OperationInputError(`unknown operation: ${name}`);
3002
+ const [path, body] = route(args);
3003
+ return { method: "POST", path: `${ROUTE_PREFIX}${path}`, body };
3004
+ }
3005
+ var CALLABLE_OPERATIONS = /* @__PURE__ */ new Set([...Object.keys(ROUTES), "read_note", "list_directory", "search_simple"]);
3006
+ function operationRoute(name) {
3007
+ const route = ROUTES[name];
3008
+ if (!route) return null;
3009
+ try {
3010
+ const [path, fixed] = route({});
3011
+ return { path, fixed };
3012
+ } catch {
3013
+ return null;
3014
+ }
3015
+ }
3016
+
3017
+ // src/api/results.ts
3018
+ var MAX_DETAIL_ROWS = 20;
3019
+ function describeRefusal(data) {
3020
+ const lines = [];
3021
+ for (const c of data.conflicts ?? []) lines.push(`conflict ${c.path}: ${c.message}`);
3022
+ for (const rv of data.violations ?? []) {
3023
+ for (const v of rv.violations ?? []) lines.push(`invalid ${rv.path}: ${v.column} ${v.message}`);
3024
+ }
3025
+ for (const f of data.failed ?? []) lines.push(`failed ${f.path}: ${f.error}`);
3026
+ const shown = lines.slice(0, MAX_DETAIL_ROWS);
3027
+ if (lines.length > shown.length) shown.push(`... and ${lines.length - shown.length} more`);
3028
+ const op = data.op ?? "operation";
3029
+ const failed = (data.failed ?? []).length > 0;
3030
+ let head = failed ? `${op} failed` : `${op} refused \u2014 nothing was written`;
3031
+ if (data.migrationId) head += ` (journal ${String(data.migrationId)}; use undo_migration to revert what was applied)`;
3032
+ return head + (shown.length ? `:
3033
+ ${shown.join("\n")}` : "");
3034
+ }
3035
+ function describeBatch(data) {
3036
+ const steps = data.steps ?? [];
3037
+ const lines = steps.filter((st) => !st.ok).map((st) => `operation ${st.index} (${st.op}): ${st.error ?? (st.result ? describeRefusal(st.result) : "refused")}`);
3038
+ const head = data.dryRun ? "batch dry run: some operations would be refused" : data.rolledBack === false ? `batch failed at operation ${String(data.failedAt)} and could NOT be fully rolled back: ${JSON.stringify(data.rollback)}` : `batch refused at operation ${String(data.failedAt)} \u2014 the operations before it were undone, nothing is left written`;
3039
+ return head + (lines.length ? `:
3040
+ ${lines.join("\n")}` : "");
3041
+ }
3042
+ function resultOf(status, json, text) {
3043
+ if (status >= 200 && status < 300) return { ok: true, value: json !== void 0 ? json : text };
3044
+ const data = json && typeof json === "object" ? json : {};
3045
+ if ("steps" in data) return { ok: false, value: describeBatch(data) };
3046
+ if ("conflicts" in data || "violations" in data || "failed" in data) return { ok: false, value: describeRefusal(data) };
3047
+ return { ok: false, value: typeof data.error === "string" ? data.error : text.trim() || `HTTP ${status}` };
3048
+ }
3049
+
3050
+ // src/api/tokens.ts
3051
+ function estimateTokens(text) {
3052
+ let n = 0;
3053
+ for (const m of text.matchAll(/\p{L}+|\p{N}+|[^\s\p{L}\p{N}]/gu)) {
3054
+ const s = m[0];
3055
+ if (/^\p{L}/u.test(s)) n += Math.ceil(s.length / 4);
3056
+ else if (/^\p{N}/u.test(s)) n += Math.ceil(s.length / 3);
3057
+ else n += 1;
3058
+ }
3059
+ return n;
3060
+ }
3061
+
3062
+ // src/api/client.ts
3063
+ var ACTOR_HEADER = "X-Datanotes-Actor";
3064
+ var DatanotesError = class extends Error {
3065
+ /** `unreachable`: the engine did not answer; `auth`: the token was refused. */
3066
+ constructor(message, kind = "http", status = 0) {
3067
+ super(message);
3068
+ this.kind = kind;
3069
+ this.status = status;
3070
+ this.name = "DatanotesError";
3071
+ }
3072
+ };
3073
+ var fetchTransport = async (req) => {
3074
+ const res = await fetch(req.url, { method: req.method, headers: req.headers, ...req.body !== void 0 ? { body: req.body } : {} });
3075
+ return { status: res.status, text: await res.text() };
3076
+ };
3077
+ function parse(text) {
3078
+ try {
3079
+ return text.trim() ? JSON.parse(text) : void 0;
3080
+ } catch {
3081
+ return void 0;
3082
+ }
3083
+ }
3084
+ var DatanotesClient = class {
3085
+ constructor(o) {
3086
+ this.o = o;
3087
+ this.url = o.url.replace(/\/+$/, "");
3088
+ this.send = o.transport ?? fetchTransport;
3089
+ }
3090
+ /** Send a request; the answer's status, its JSON (when it is JSON) and its text. */
3091
+ async request(method, path, body, opts = {}) {
3092
+ if (!this.url) throw new DatanotesError("engine address not set", "unreachable");
3093
+ if (!this.o.token) throw new DatanotesError("token not set", "auth");
3094
+ const actor = opts.actor ?? this.o.actor;
3095
+ let res;
3096
+ try {
3097
+ res = await this.send({
3098
+ url: `${this.url}${path}`,
3099
+ method,
3100
+ headers: {
3101
+ Authorization: `Bearer ${this.o.token}`,
3102
+ ...body !== void 0 ? { "Content-Type": "application/json" } : {},
3103
+ ...opts.accept ? { Accept: opts.accept } : {},
3104
+ ...actor && Object.keys(actor).length ? { [ACTOR_HEADER]: JSON.stringify(actor) } : {}
3105
+ },
3106
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
3107
+ });
3108
+ } catch (e) {
3109
+ throw new DatanotesError(`engine unreachable at ${this.url}: ${e instanceof Error ? e.message : String(e)}`, "unreachable");
3110
+ }
3111
+ if (res.status === 401) throw new DatanotesError("token refused by the engine", "auth", 401);
3112
+ if (res.status === 0 || res.status === 502 || res.status === 503 || res.status === 504) throw new DatanotesError(`engine unreachable at ${this.url} (HTTP ${res.status})`, "unreachable", res.status);
3113
+ return { status: res.status, json: parse(res.text), text: res.text };
3114
+ }
3115
+ /** `POST /datanotes/<route>` and its JSON answer; throws on an error status. */
3116
+ async post(route, body = {}, actor) {
3117
+ const r = await this.request("POST", `/datanotes${route}`, body, actor ? { actor } : {});
3118
+ if (r.status >= 400) throw new DatanotesError(resultOf(r.status, r.json, r.text).value, "http", r.status);
3119
+ return r.json;
3120
+ }
3121
+ /** Run an operation of the catalogue (`select_rows`, `insert_row`, …) with an agent's arguments. */
3122
+ async call(name, args = {}, actor) {
3123
+ let req;
3124
+ try {
3125
+ req = operationRequest(name, args);
3126
+ } catch (e) {
3127
+ if (e instanceof OperationInputError) return { ok: false, value: e.message };
3128
+ throw e;
3129
+ }
3130
+ const r = await this.request(req.method, req.path, req.body, { ...actor ? { actor } : {}, ...req.accept ? { accept: req.accept } : {} });
3131
+ return resultOf(r.status, r.json, r.text);
3132
+ }
3133
+ /** Run an operation of the engine, or else a registered app's tool of that name. */
3134
+ async invoke(name, args = {}, actor) {
3135
+ if (CALLABLE_OPERATIONS.has(name)) return { ...await this.call(name, args, actor), servedBy: "engine" };
3136
+ return this.callAppTool(name, args, actor);
3137
+ }
3138
+ /** True when the engine answers `GET /` (no token needed). */
3139
+ async ping() {
3140
+ try {
3141
+ const r = await this.send({ url: `${this.url}/`, method: "GET", headers: {} });
3142
+ return r.status === 200;
3143
+ } catch {
3144
+ return false;
3145
+ }
3146
+ }
3147
+ /** The tools of the registered apps and the apps' instructions for agents. */
3148
+ appTools() {
3149
+ return this.post("/apps/tools/");
3150
+ }
3151
+ /** Call an app's tool through the engine (which holds the app's credentials). */
3152
+ async callAppTool(name, args, actor) {
3153
+ const r = await this.request("POST", "/datanotes/apps/call/", { tool: name, arguments: args }, actor ? { actor } : {});
3154
+ if (r.status >= 400) return { ...resultOf(r.status, r.json, r.text), servedBy: "engine" };
3155
+ return r.json;
3156
+ }
3157
+ /** Record an agent's tool call in the change feed (what MCP servers report). */
3158
+ async recordToolCall(call, actor) {
3159
+ await this.post("/tool-calls/record/", call, actor);
3160
+ }
3161
+ };