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