datanotes 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/SECURITY.md +6 -3
- package/dist/api/index.cjs +24 -21
- package/dist/api/index.js +24 -21
- package/dist/datanotes.cjs +47 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
The engine of your second brain: Markdown notes as database tables, for you and your AI agents.
|
|
4
4
|
|
|
5
5
|
A row is any note whose `table` property names a table; tables are defined in
|
|
6
|
-
`Database/database.yaml`. Every write is checked against its table, journaled and undoable.
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
`Database/database.yaml`. Every write is checked against its table, journaled and undoable.
|
|
7
|
+
Programs use its HTTP API or the `datanotes/client` library; agents use the separate MCP server
|
|
8
|
+
`datanotes-mcp`.
|
|
9
9
|
|
|
10
10
|
**Documentation: [datanotes.dev](https://datanotes.dev)**
|
|
11
11
|
|
|
@@ -17,7 +17,8 @@ Requires Node.js 20 or newer. Start the engine on a vault:
|
|
|
17
17
|
npx -y datanotes serve --vault /path/to/vault
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
It serves the HTTP API on `http://127.0.0.1:27150
|
|
20
|
+
It serves the HTTP API on `http://127.0.0.1:27150` (routes under `/datanotes/*`, plus the
|
|
21
|
+
Local-REST-API-style `/vault/*` and `/search/simple/`), with the owner's token in
|
|
21
22
|
`<vault>/.datanotes/service.json`. From code:
|
|
22
23
|
|
|
23
24
|
```js
|
package/SECURITY.md
CHANGED
|
@@ -25,7 +25,7 @@ run on your own machine, for you and the agents you choose.
|
|
|
25
25
|
| Credential | Where | What it can do |
|
|
26
26
|
| --- | --- | --- |
|
|
27
27
|
| Owner token | `httpServerToken` in the settings | Everything: data, schema, apps, webhooks, undo. Keep it on the machine. |
|
|
28
|
-
| App token | created with `POST /datanotes/apps/create/` (owner only), stored hashed | Read everything; write only the tables in its `write` patterns; change the schema only with `ddl`. It cannot create webhooks, manage apps or undo; with `maintain` it may also undo, restore, vacuum and
|
|
28
|
+
| App token | created with `POST /datanotes/apps/create/` (owner only), stored hashed | Read everything; write only the tables in its `write` patterns; change the schema only with `ddl`. It cannot create webhooks, manage apps or undo; with `maintain` it may also undo, restore, vacuum, configure and rebuild the semantic index (an agent's own token). |
|
|
29
29
|
|
|
30
30
|
Prefer an **app token per device or agent**: it has only the permissions it needs and the journal
|
|
31
31
|
names it. MCP clients use the same tokens: the MCP server passes them to the engine.
|
|
@@ -44,8 +44,11 @@ followed: do not link to folders you would not give the engine.
|
|
|
44
44
|
|
|
45
45
|
Nothing leaves the machine unless you turn it on:
|
|
46
46
|
|
|
47
|
-
- **Semantic search** sends note text to the embedding provider you configure (`
|
|
48
|
-
off by default). A local provider (Ollama
|
|
47
|
+
- **Semantic search** sends note text to the embedding provider you configure (`semanticEnabled`,
|
|
48
|
+
off by default; provider `semanticProvider` / `semanticBaseUrl`). A local provider (Ollama,
|
|
49
|
+
LM Studio) keeps it on the machine.
|
|
49
50
|
- **Telemetry** sends logs to the OTLP endpoint you configure (`telemetryEnabled`, off by default).
|
|
50
51
|
- **Webhooks** (created by the owner) post change events to the URLs they name.
|
|
52
|
+
- **Apps' MCP endpoints** (registered by the owner): the engine sends each app's `mcp_token`, and
|
|
53
|
+
the arguments and caller of every call of its tools, to the app's `mcp_url`, which may be remote.
|
|
51
54
|
- **Git sync** (`--git-sync`) pushes the vault to its git remote.
|
package/dist/api/index.cjs
CHANGED
|
@@ -41,7 +41,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
41
41
|
var OPERATIONS = [
|
|
42
42
|
{
|
|
43
43
|
"name": "read_note",
|
|
44
|
-
"description": "Read a vault file (
|
|
44
|
+
"description": "Read a vault file (`GET /vault/{path}`). Default: the raw markdown. With `as_json`:\n`{content, frontmatter, tags, path, stat}` (`tags` without `#`, from the text and the\nfrontmatter; `stat`: `{ctime, mtime, size}` or null). A missing file is an error.\n`path`: vault-relative, forward slashes.",
|
|
45
45
|
"inputSchema": {
|
|
46
46
|
"additionalProperties": false,
|
|
47
47
|
"properties": {
|
|
@@ -68,7 +68,7 @@ var OPERATIONS = [
|
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
"name": "list_directory",
|
|
71
|
-
"description": '
|
|
71
|
+
"description": 'Direct children of a vault folder (`GET /vault/{folder}/`): `{files: [...]}`. Folders end with\n`/`, names are sorted, dot-files are hidden. `""` is the vault root. A missing folder is an\nerror.',
|
|
72
72
|
"inputSchema": {
|
|
73
73
|
"additionalProperties": false,
|
|
74
74
|
"properties": {
|
|
@@ -89,7 +89,7 @@ var OPERATIONS = [
|
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
"name": "search_simple",
|
|
92
|
-
"description": "
|
|
92
|
+
"description": "Plain-text search (`POST /search/simple/`): every word of `query` must occur, case- and\naccent-insensitive, in the note's path or text; there are no operators. Returns up to 200\nfiles, best first: `[{filename, score, matches: [{match: {start, end}, context}]}]`, at most 20\nmatches per file. `context_length`: characters of context on each side (default 100, max 1000).",
|
|
93
93
|
"inputSchema": {
|
|
94
94
|
"additionalProperties": false,
|
|
95
95
|
"properties": {
|
|
@@ -116,7 +116,7 @@ var OPERATIONS = [
|
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
"name": "list_tables",
|
|
119
|
-
"description": "List every table: `name`, `catalog`, `schema`, `qualified` (`personal.metrics.mood` \u2014 use it\nwherever a table is expected; `metrics.mood` or `mood` also work when unambiguous), `path` and,\nwhen declared, `description` and `aliases` (other words for what it records). Tables are\ndefined in `database.yaml` (catalog \u2192 schema \u2192 table)
|
|
119
|
+
"description": "List every table: `name`, `catalog`, `schema`, `qualified` (`personal.metrics.mood` \u2014 use it\nwherever a table is expected; `metrics.mood` or `mood` also work when unambiguous), `path` and,\nwhen declared, `description` and `aliases` (other words for what it records). Tables are\ndefined in `database.yaml` (catalog \u2192 schema \u2192 table). Returns `{tables, views}`: `views` lists the stored views (same fields, no\npath): select them like tables. `system.information_schema` is read with `select_rows`.\n\nCall this first to find the table for what the user reports (match their words against\nname, description and aliases), and before creating tables or columns so you reuse existing\nones instead of creating duplicates.",
|
|
120
120
|
"inputSchema": {
|
|
121
121
|
"additionalProperties": false,
|
|
122
122
|
"properties": {},
|
|
@@ -236,7 +236,8 @@ var OPERATIONS = [
|
|
|
236
236
|
"type": "null"
|
|
237
237
|
}
|
|
238
238
|
],
|
|
239
|
-
"default": null
|
|
239
|
+
"default": null,
|
|
240
|
+
"description": "Untyped fields of the table (name \u2192 default), kept on every row; a field cannot share a name with a column."
|
|
240
241
|
},
|
|
241
242
|
"body": {
|
|
242
243
|
"anyOf": [
|
|
@@ -344,7 +345,7 @@ var OPERATIONS = [
|
|
|
344
345
|
},
|
|
345
346
|
{
|
|
346
347
|
"name": "rename_column",
|
|
347
|
-
"description": "Rename a column
|
|
348
|
+
"description": "Rename a column in database.yaml and on every row. Refused if `to_column` is already a column\nof the table; a row that has a stray `to_column` key with a different value is a conflict, and\nnothing is written. Views and note text that mention the old name are not rewritten.",
|
|
348
349
|
"inputSchema": {
|
|
349
350
|
"additionalProperties": false,
|
|
350
351
|
"properties": {
|
|
@@ -715,7 +716,7 @@ var OPERATIONS = [
|
|
|
715
716
|
},
|
|
716
717
|
{
|
|
717
718
|
"name": "describe_database",
|
|
718
|
-
"description": "Describe the database: its folder (`root`), `metastore` (`database.yaml`), configuration\n(default catalog and schema, row partition and file-name formats, archive folder, time zone),\njournal folder, `bases` (shared column sets and the tables using them), `catalogs` \u2192 schemas \u2192 tables (
|
|
719
|
+
"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` (with `rows` counts) and `views`.",
|
|
719
720
|
"inputSchema": {
|
|
720
721
|
"additionalProperties": false,
|
|
721
722
|
"properties": {},
|
|
@@ -731,7 +732,7 @@ var OPERATIONS = [
|
|
|
731
732
|
},
|
|
732
733
|
{
|
|
733
734
|
"name": "configure_database",
|
|
734
|
-
"description": 'Configure the database (persisted in database.yaml `config:`): `root` (rename the database\nfolder; links follow; revert by renaming back), `default_catalog`, `default_schema`,\n`default_partition` ("" = flat) and `filename` (date formats for new time-based tables),\n`archive_folder`, `timezone` (IANA; completes date-times written without offset), `history`\n(transaction log for every table \u2014 only on the user\'s request). Returns describe_database
|
|
735
|
+
"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.\nRenaming `root` moves the folder (links to its notes are rewritten); it is not journaled: to\nrevert, call it again with the old value.',
|
|
735
736
|
"inputSchema": {
|
|
736
737
|
"additionalProperties": false,
|
|
737
738
|
"properties": {
|
|
@@ -906,7 +907,8 @@ var OPERATIONS = [
|
|
|
906
907
|
"type": "null"
|
|
907
908
|
}
|
|
908
909
|
],
|
|
909
|
-
"default": null
|
|
910
|
+
"default": null,
|
|
911
|
+
"description": "Optional note path (vault-relative), instead of the table's file-name pattern; `.md` is added if missing; it must stay inside the vault."
|
|
910
912
|
},
|
|
911
913
|
"dry_run": {
|
|
912
914
|
"default": false,
|
|
@@ -1144,7 +1146,7 @@ var OPERATIONS = [
|
|
|
1144
1146
|
"title": "Update Row",
|
|
1145
1147
|
"readOnlyHint": false,
|
|
1146
1148
|
"destructiveHint": false,
|
|
1147
|
-
"idempotentHint":
|
|
1149
|
+
"idempotentHint": false,
|
|
1148
1150
|
"openWorldHint": false
|
|
1149
1151
|
}
|
|
1150
1152
|
},
|
|
@@ -1298,7 +1300,7 @@ var OPERATIONS = [
|
|
|
1298
1300
|
},
|
|
1299
1301
|
{
|
|
1300
1302
|
"name": "adopt_rows",
|
|
1301
|
-
"description": 'Turn existing notes (not rows of any table yet) into rows of `table`, keeping their body and\nlinks: `rename` keys (`{"data": "occurred_at"}`), `set_values` for all, `per_row` values by\nnote path (`{"Home/x.md": {"zone": "[[Kitchen]]"}}`), `drop` keys the table does not have.\nEvery note gets `table` and a system `id`; with `relocate` (default) it moves to the table\'s\nfolder, named by its filename pattern (
|
|
1303
|
+
"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 (links to it are rewritten). All notes are validated first:\nunknown keys and bad values are listed and nothing is written. Run with `dry_run` first; undo\nwith `undo_migration`.',
|
|
1302
1304
|
"inputSchema": {
|
|
1303
1305
|
"additionalProperties": false,
|
|
1304
1306
|
"properties": {
|
|
@@ -1601,7 +1603,7 @@ var OPERATIONS = [
|
|
|
1601
1603
|
"annotations": {
|
|
1602
1604
|
"title": "Undo Migration",
|
|
1603
1605
|
"readOnlyHint": false,
|
|
1604
|
-
"destructiveHint":
|
|
1606
|
+
"destructiveHint": true,
|
|
1605
1607
|
"idempotentHint": false,
|
|
1606
1608
|
"openWorldHint": false
|
|
1607
1609
|
}
|
|
@@ -1766,7 +1768,7 @@ var OPERATIONS = [
|
|
|
1766
1768
|
},
|
|
1767
1769
|
{
|
|
1768
1770
|
"name": "semantic_search",
|
|
1769
|
-
"description": 'Find notes by meaning, not exact words: `{query, results: [{path, score, heading, snippet,\ntable?}]}`, one result per note (its best passage), best first. Use it for vague questions\n("the dinner where we talked about moving", "what did I decide about the car") and to find the\nrows to read or update; then read_note / select_rows for the details. Filters: `tables`\n(qualified or short names), `folder`, `min_score` (cosine 0\u20131; ~0.5+ is usually relevant).\
|
|
1771
|
+
"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).\n`limit`: default 10, max 100. Fails with a clear message when semantic search is not enabled in\nthe engine settings.',
|
|
1770
1772
|
"inputSchema": {
|
|
1771
1773
|
"additionalProperties": false,
|
|
1772
1774
|
"properties": {
|
|
@@ -1829,7 +1831,7 @@ var OPERATIONS = [
|
|
|
1829
1831
|
},
|
|
1830
1832
|
{
|
|
1831
1833
|
"name": "semantic_index",
|
|
1832
|
-
"description": "Semantic search index: `status` (provider
|
|
1834
|
+
"description": "Semantic search index: `status` (`enabled`, `provider`, `model`, `files`, `passages`, `pending`,\n`running`, `lastSync`, `lastError`), `update` (embed notes changed since the last run; the\nengine also does it on its own about ten seconds after edits) or `rebuild` (re-embed\neverything: slow, and costs money with a paid provider \u2014 ask first).",
|
|
1833
1835
|
"inputSchema": {
|
|
1834
1836
|
"additionalProperties": false,
|
|
1835
1837
|
"properties": {
|
|
@@ -1975,7 +1977,7 @@ var OPERATIONS = [
|
|
|
1975
1977
|
},
|
|
1976
1978
|
{
|
|
1977
1979
|
"name": "describe_history",
|
|
1978
|
-
"description": "DESCRIBE HISTORY: the table's versions, newest first \u2014 `version`, `timestamp`, `operation`\n(CREATE TABLE, WRITE, UPDATE, DELETE, MERGE, ALTER TABLE, ADD COLUMNS, RESTORE, UNDO, \u2026;\n`EXTERNAL_EDIT` = changed
|
|
1980
|
+
"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 outside the engine: an editor, git, sync), `operationMetrics` and `migrationId` (undo).\nWorks for dropped tables too (full `catalog.schema.table`). Use a version with `select_rows`\n(time travel), `table_changes` or `restore_table`.",
|
|
1979
1981
|
"inputSchema": {
|
|
1980
1982
|
"additionalProperties": false,
|
|
1981
1983
|
"properties": {
|
|
@@ -2047,7 +2049,7 @@ var OPERATIONS = [
|
|
|
2047
2049
|
},
|
|
2048
2050
|
{
|
|
2049
2051
|
"name": "list_changes",
|
|
2050
|
-
"description": "Change feed across all tables: numbered row changes (`seq`), oldest first, from engine writes\nand from hand edits (`source: external`). Each has `table`, `op` (insert, update, delete, move,\nschema), `path`, `changes` ({column: {before, after}}), `actor`, `migration`.
|
|
2052
|
+
"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`. Agents' tool calls (reported by MCP servers) 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` (max 60000) waits for a new change (long poll); `limit` max 5000. `gap: true` means\nolder changes were dropped: re-read the tables. `where` filters rows as in select_rows (on the values after the change). Per-table versions: `table_changes`.",
|
|
2051
2053
|
"inputSchema": {
|
|
2052
2054
|
"additionalProperties": false,
|
|
2053
2055
|
"properties": {
|
|
@@ -2573,7 +2575,7 @@ var OPERATIONS = [
|
|
|
2573
2575
|
},
|
|
2574
2576
|
{
|
|
2575
2577
|
"name": "clone_table",
|
|
2576
|
-
"description": "CREATE TABLE `target` CLONE `source`: same definition plus independent copies of its rows\n(deep clone), optionally as of a `version` / `timestamp`. `shallow=true` copies the\ndefinition only (CREATE TABLE LIKE). `target`: `catalog.schema.table`, `schema.table` (
|
|
2578
|
+
"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` (in the\nsource's catalog) or a name (source's catalog and schema). Useful for experiments, e.g. a sandbox copy\nin the `agent` catalog.",
|
|
2577
2579
|
"inputSchema": {
|
|
2578
2580
|
"additionalProperties": false,
|
|
2579
2581
|
"properties": {
|
|
@@ -2630,7 +2632,7 @@ var OPERATIONS = [
|
|
|
2630
2632
|
},
|
|
2631
2633
|
{
|
|
2632
2634
|
"name": "recompute_columns",
|
|
2633
|
-
"description": "Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after\nrows were edited
|
|
2635
|
+
"description": "Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after\nrows were edited by hand (an editor, git, sync) 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 (new ones on every call): only on the user's\nexplicit request.\n`check_table` reports stale values with code `generated`. No-op when nothing is stale;\notherwise journaled (undo_migration) and a RECOMPUTE version in the table's history.",
|
|
2634
2636
|
"inputSchema": {
|
|
2635
2637
|
"additionalProperties": false,
|
|
2636
2638
|
"properties": {
|
|
@@ -2669,7 +2671,7 @@ var OPERATIONS = [
|
|
|
2669
2671
|
"title": "Recompute Columns",
|
|
2670
2672
|
"readOnlyHint": false,
|
|
2671
2673
|
"destructiveHint": false,
|
|
2672
|
-
"idempotentHint":
|
|
2674
|
+
"idempotentHint": false,
|
|
2673
2675
|
"openWorldHint": false
|
|
2674
2676
|
}
|
|
2675
2677
|
},
|
|
@@ -2834,7 +2836,7 @@ var OPERATIONS = [
|
|
|
2834
2836
|
},
|
|
2835
2837
|
{
|
|
2836
2838
|
"name": "graph_path",
|
|
2837
|
-
"description": 'Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or\n`{"table", "where"}`): `found`, `length` and the steps (`from`, `label`, `direction`, `to`).\n`direction` both by default; `max_depth` default 6 (max 10).',
|
|
2839
|
+
"description": 'Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or\n`{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`).\n`direction` both by default; `max_depth` default 6 (max 10).',
|
|
2838
2840
|
"inputSchema": {
|
|
2839
2841
|
"additionalProperties": false,
|
|
2840
2842
|
"properties": {
|
|
@@ -2972,7 +2974,8 @@ var ROUTES = {
|
|
|
2972
2974
|
create_webhook: (a) => ["/webhooks/create/", pick(a, ["url", "tables", "ops", "columns", "exclude_actor", "where", "since"])],
|
|
2973
2975
|
delete_webhook: (a) => ["/webhooks/delete/", pick(a, ["id"])],
|
|
2974
2976
|
restore_table: (a) => ["/history/restore/", { ...pick(a, ["table", "version", "timestamp"]), ...dry(a) }],
|
|
2975
|
-
|
|
2977
|
+
// vacuum deletes history for good: a dry run unless the caller says `dry_run: false`
|
|
2978
|
+
vacuum_table: (a) => ["/history/vacuum/", { ...pick(a, ["table", "retain_from_version"]), dry_run: a.dry_run !== false }],
|
|
2976
2979
|
graph_neighbors: (a) => ["/graph/neighbors/", compact({ from: a.from_nodes, direction: a.direction, edges: a.edges })],
|
|
2977
2980
|
graph_traverse: (a) => [
|
|
2978
2981
|
"/graph/traverse/",
|
package/dist/api/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var OPERATIONS = [
|
|
3
3
|
{
|
|
4
4
|
"name": "read_note",
|
|
5
|
-
"description": "Read a vault file (
|
|
5
|
+
"description": "Read a vault file (`GET /vault/{path}`). Default: the raw markdown. With `as_json`:\n`{content, frontmatter, tags, path, stat}` (`tags` without `#`, from the text and the\nfrontmatter; `stat`: `{ctime, mtime, size}` or null). A missing file is an error.\n`path`: vault-relative, forward slashes.",
|
|
6
6
|
"inputSchema": {
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"properties": {
|
|
@@ -29,7 +29,7 @@ var OPERATIONS = [
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"name": "list_directory",
|
|
32
|
-
"description": '
|
|
32
|
+
"description": 'Direct children of a vault folder (`GET /vault/{folder}/`): `{files: [...]}`. Folders end with\n`/`, names are sorted, dot-files are hidden. `""` is the vault root. A missing folder is an\nerror.',
|
|
33
33
|
"inputSchema": {
|
|
34
34
|
"additionalProperties": false,
|
|
35
35
|
"properties": {
|
|
@@ -50,7 +50,7 @@ var OPERATIONS = [
|
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"name": "search_simple",
|
|
53
|
-
"description": "
|
|
53
|
+
"description": "Plain-text search (`POST /search/simple/`): every word of `query` must occur, case- and\naccent-insensitive, in the note's path or text; there are no operators. Returns up to 200\nfiles, best first: `[{filename, score, matches: [{match: {start, end}, context}]}]`, at most 20\nmatches per file. `context_length`: characters of context on each side (default 100, max 1000).",
|
|
54
54
|
"inputSchema": {
|
|
55
55
|
"additionalProperties": false,
|
|
56
56
|
"properties": {
|
|
@@ -77,7 +77,7 @@ var OPERATIONS = [
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
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)
|
|
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). Returns `{tables, views}`: `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
81
|
"inputSchema": {
|
|
82
82
|
"additionalProperties": false,
|
|
83
83
|
"properties": {},
|
|
@@ -197,7 +197,8 @@ var OPERATIONS = [
|
|
|
197
197
|
"type": "null"
|
|
198
198
|
}
|
|
199
199
|
],
|
|
200
|
-
"default": null
|
|
200
|
+
"default": null,
|
|
201
|
+
"description": "Untyped fields of the table (name \u2192 default), kept on every row; a field cannot share a name with a column."
|
|
201
202
|
},
|
|
202
203
|
"body": {
|
|
203
204
|
"anyOf": [
|
|
@@ -305,7 +306,7 @@ var OPERATIONS = [
|
|
|
305
306
|
},
|
|
306
307
|
{
|
|
307
308
|
"name": "rename_column",
|
|
308
|
-
"description": "Rename a column
|
|
309
|
+
"description": "Rename a column in database.yaml and on every row. Refused if `to_column` is already a column\nof the table; a row that has a stray `to_column` key with a different value is a conflict, and\nnothing is written. Views and note text that mention the old name are not rewritten.",
|
|
309
310
|
"inputSchema": {
|
|
310
311
|
"additionalProperties": false,
|
|
311
312
|
"properties": {
|
|
@@ -676,7 +677,7 @@ var OPERATIONS = [
|
|
|
676
677
|
},
|
|
677
678
|
{
|
|
678
679
|
"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 (
|
|
680
|
+
"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` (with `rows` counts) and `views`.",
|
|
680
681
|
"inputSchema": {
|
|
681
682
|
"additionalProperties": false,
|
|
682
683
|
"properties": {},
|
|
@@ -692,7 +693,7 @@ var OPERATIONS = [
|
|
|
692
693
|
},
|
|
693
694
|
{
|
|
694
695
|
"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
|
|
696
|
+
"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.\nRenaming `root` moves the folder (links to its notes are rewritten); it is not journaled: to\nrevert, call it again with the old value.',
|
|
696
697
|
"inputSchema": {
|
|
697
698
|
"additionalProperties": false,
|
|
698
699
|
"properties": {
|
|
@@ -867,7 +868,8 @@ var OPERATIONS = [
|
|
|
867
868
|
"type": "null"
|
|
868
869
|
}
|
|
869
870
|
],
|
|
870
|
-
"default": null
|
|
871
|
+
"default": null,
|
|
872
|
+
"description": "Optional note path (vault-relative), instead of the table's file-name pattern; `.md` is added if missing; it must stay inside the vault."
|
|
871
873
|
},
|
|
872
874
|
"dry_run": {
|
|
873
875
|
"default": false,
|
|
@@ -1105,7 +1107,7 @@ var OPERATIONS = [
|
|
|
1105
1107
|
"title": "Update Row",
|
|
1106
1108
|
"readOnlyHint": false,
|
|
1107
1109
|
"destructiveHint": false,
|
|
1108
|
-
"idempotentHint":
|
|
1110
|
+
"idempotentHint": false,
|
|
1109
1111
|
"openWorldHint": false
|
|
1110
1112
|
}
|
|
1111
1113
|
},
|
|
@@ -1259,7 +1261,7 @@ var OPERATIONS = [
|
|
|
1259
1261
|
},
|
|
1260
1262
|
{
|
|
1261
1263
|
"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 (
|
|
1264
|
+
"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 (links to it are rewritten). 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
1265
|
"inputSchema": {
|
|
1264
1266
|
"additionalProperties": false,
|
|
1265
1267
|
"properties": {
|
|
@@ -1562,7 +1564,7 @@ var OPERATIONS = [
|
|
|
1562
1564
|
"annotations": {
|
|
1563
1565
|
"title": "Undo Migration",
|
|
1564
1566
|
"readOnlyHint": false,
|
|
1565
|
-
"destructiveHint":
|
|
1567
|
+
"destructiveHint": true,
|
|
1566
1568
|
"idempotentHint": false,
|
|
1567
1569
|
"openWorldHint": false
|
|
1568
1570
|
}
|
|
@@ -1727,7 +1729,7 @@ var OPERATIONS = [
|
|
|
1727
1729
|
},
|
|
1728
1730
|
{
|
|
1729
1731
|
"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).\
|
|
1732
|
+
"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).\n`limit`: default 10, max 100. Fails with a clear message when semantic search is not enabled in\nthe engine settings.',
|
|
1731
1733
|
"inputSchema": {
|
|
1732
1734
|
"additionalProperties": false,
|
|
1733
1735
|
"properties": {
|
|
@@ -1790,7 +1792,7 @@ var OPERATIONS = [
|
|
|
1790
1792
|
},
|
|
1791
1793
|
{
|
|
1792
1794
|
"name": "semantic_index",
|
|
1793
|
-
"description": "Semantic search index: `status` (provider
|
|
1795
|
+
"description": "Semantic search index: `status` (`enabled`, `provider`, `model`, `files`, `passages`, `pending`,\n`running`, `lastSync`, `lastError`), `update` (embed notes changed since the last run; the\nengine also does it on its own about ten seconds after edits) or `rebuild` (re-embed\neverything: slow, and costs money with a paid provider \u2014 ask first).",
|
|
1794
1796
|
"inputSchema": {
|
|
1795
1797
|
"additionalProperties": false,
|
|
1796
1798
|
"properties": {
|
|
@@ -1936,7 +1938,7 @@ var OPERATIONS = [
|
|
|
1936
1938
|
},
|
|
1937
1939
|
{
|
|
1938
1940
|
"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
|
|
1941
|
+
"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 outside the engine: an editor, git, sync), `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
1942
|
"inputSchema": {
|
|
1941
1943
|
"additionalProperties": false,
|
|
1942
1944
|
"properties": {
|
|
@@ -2008,7 +2010,7 @@ var OPERATIONS = [
|
|
|
2008
2010
|
},
|
|
2009
2011
|
{
|
|
2010
2012
|
"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`.
|
|
2013
|
+
"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`. Agents' tool calls (reported by MCP servers) 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` (max 60000) waits for a new change (long poll); `limit` max 5000. `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
2014
|
"inputSchema": {
|
|
2013
2015
|
"additionalProperties": false,
|
|
2014
2016
|
"properties": {
|
|
@@ -2534,7 +2536,7 @@ var OPERATIONS = [
|
|
|
2534
2536
|
},
|
|
2535
2537
|
{
|
|
2536
2538
|
"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` (
|
|
2539
|
+
"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` (in the\nsource's catalog) or a name (source's catalog and schema). Useful for experiments, e.g. a sandbox copy\nin the `agent` catalog.",
|
|
2538
2540
|
"inputSchema": {
|
|
2539
2541
|
"additionalProperties": false,
|
|
2540
2542
|
"properties": {
|
|
@@ -2591,7 +2593,7 @@ var OPERATIONS = [
|
|
|
2591
2593
|
},
|
|
2592
2594
|
{
|
|
2593
2595
|
"name": "recompute_columns",
|
|
2594
|
-
"description": "Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after\nrows were edited
|
|
2596
|
+
"description": "Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after\nrows were edited by hand (an editor, git, sync) 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 (new ones on every call): only on the user's\nexplicit 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
2597
|
"inputSchema": {
|
|
2596
2598
|
"additionalProperties": false,
|
|
2597
2599
|
"properties": {
|
|
@@ -2630,7 +2632,7 @@ var OPERATIONS = [
|
|
|
2630
2632
|
"title": "Recompute Columns",
|
|
2631
2633
|
"readOnlyHint": false,
|
|
2632
2634
|
"destructiveHint": false,
|
|
2633
|
-
"idempotentHint":
|
|
2635
|
+
"idempotentHint": false,
|
|
2634
2636
|
"openWorldHint": false
|
|
2635
2637
|
}
|
|
2636
2638
|
},
|
|
@@ -2795,7 +2797,7 @@ var OPERATIONS = [
|
|
|
2795
2797
|
},
|
|
2796
2798
|
{
|
|
2797
2799
|
"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).',
|
|
2800
|
+
"description": 'Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or\n`{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`).\n`direction` both by default; `max_depth` default 6 (max 10).',
|
|
2799
2801
|
"inputSchema": {
|
|
2800
2802
|
"additionalProperties": false,
|
|
2801
2803
|
"properties": {
|
|
@@ -2933,7 +2935,8 @@ var ROUTES = {
|
|
|
2933
2935
|
create_webhook: (a) => ["/webhooks/create/", pick(a, ["url", "tables", "ops", "columns", "exclude_actor", "where", "since"])],
|
|
2934
2936
|
delete_webhook: (a) => ["/webhooks/delete/", pick(a, ["id"])],
|
|
2935
2937
|
restore_table: (a) => ["/history/restore/", { ...pick(a, ["table", "version", "timestamp"]), ...dry(a) }],
|
|
2936
|
-
|
|
2938
|
+
// vacuum deletes history for good: a dry run unless the caller says `dry_run: false`
|
|
2939
|
+
vacuum_table: (a) => ["/history/vacuum/", { ...pick(a, ["table", "retain_from_version"]), dry_run: a.dry_run !== false }],
|
|
2937
2940
|
graph_neighbors: (a) => ["/graph/neighbors/", compact({ from: a.from_nodes, direction: a.direction, edges: a.edges })],
|
|
2938
2941
|
graph_traverse: (a) => [
|
|
2939
2942
|
"/graph/traverse/",
|
package/dist/datanotes.cjs
CHANGED
|
@@ -7793,6 +7793,7 @@ var TeeTelemetry = class {
|
|
|
7793
7793
|
|
|
7794
7794
|
// src/server/engine-lock.ts
|
|
7795
7795
|
var LOCK_PATH_SUFFIX = "engine.lock";
|
|
7796
|
+
var LOCK_STALE_MS = 3e4;
|
|
7796
7797
|
var LOCK_HEARTBEAT_MS = 1e4;
|
|
7797
7798
|
function lockPath(storeFolder) {
|
|
7798
7799
|
return `${storeFolder.replace(/\/+$/, "")}/${LOCK_PATH_SUFFIX}`;
|
|
@@ -7805,6 +7806,9 @@ async function readLock(adapter2, storeFolder) {
|
|
|
7805
7806
|
return null;
|
|
7806
7807
|
}
|
|
7807
7808
|
}
|
|
7809
|
+
function isFresh(lock, now = Date.now()) {
|
|
7810
|
+
return !!lock && now - Date.parse(lock.heartbeat) < LOCK_STALE_MS;
|
|
7811
|
+
}
|
|
7808
7812
|
var LockHolder = class {
|
|
7809
7813
|
constructor(adapter2, storeFolder, info) {
|
|
7810
7814
|
this.adapter = adapter2;
|
|
@@ -10087,7 +10091,7 @@ async function tableStateAt(app, settings, full, asOf2 = {}) {
|
|
|
10087
10091
|
if (versions.length === 0) {
|
|
10088
10092
|
if (asOf2.version !== void 0 || asOf2.timestamp !== void 0) {
|
|
10089
10093
|
throw new HistoryError(
|
|
10090
|
-
`${full} has no history: time travel is off for it (turn it on with configure_database(history=true) or alter_table(history=
|
|
10094
|
+
`${full} has no history: time travel is off for it (turn it on with configure_database(history=true) or alter_table(history="on"))`
|
|
10091
10095
|
);
|
|
10092
10096
|
}
|
|
10093
10097
|
return emptyState(full);
|
|
@@ -15006,7 +15010,7 @@ var SemanticIndex = class {
|
|
|
15006
15010
|
}
|
|
15007
15011
|
requireEnabled() {
|
|
15008
15012
|
if (!this.getSettings().semanticEnabled) {
|
|
15009
|
-
throw new OperationInputError("semantic search is off:
|
|
15013
|
+
throw new OperationInputError("semantic search is off: set semanticEnabled, semanticProvider and semanticModel in the engine settings");
|
|
15010
15014
|
}
|
|
15011
15015
|
}
|
|
15012
15016
|
async load() {
|
|
@@ -15054,7 +15058,7 @@ var SemanticIndex = class {
|
|
|
15054
15058
|
/** Notes in scope: every markdown note, or only table rows; minus excluded folders and archives. */
|
|
15055
15059
|
inScope(f, table) {
|
|
15056
15060
|
const s = this.getSettings();
|
|
15057
|
-
if (f.path.includes("/_archive/")) return false;
|
|
15061
|
+
if (f.path.startsWith("_archive/") || f.path.includes("/_archive/")) return false;
|
|
15058
15062
|
if (s.semanticExclude.some((dir) => f.path === dir || f.path.startsWith(`${dir.replace(/\/+$/, "")}/`))) return false;
|
|
15059
15063
|
if (s.semanticScope === "tables" && !table) return false;
|
|
15060
15064
|
return true;
|
|
@@ -16206,7 +16210,7 @@ var HttpApiServer = class {
|
|
|
16206
16210
|
}
|
|
16207
16211
|
/**
|
|
16208
16212
|
* Resolves with the bound port once listening. A busy port is retried a few times: when the
|
|
16209
|
-
*
|
|
16213
|
+
* engine restarts, the previous instance may still be closing.
|
|
16210
16214
|
*/
|
|
16211
16215
|
async start(retries = 6, delayMs = 500) {
|
|
16212
16216
|
for (let i = 0; ; i++) {
|
|
@@ -17533,7 +17537,7 @@ function checkPatterns(patterns) {
|
|
|
17533
17537
|
var OPERATIONS = [
|
|
17534
17538
|
{
|
|
17535
17539
|
"name": "read_note",
|
|
17536
|
-
"description": "Read a vault file (
|
|
17540
|
+
"description": "Read a vault file (`GET /vault/{path}`). Default: the raw markdown. With `as_json`:\n`{content, frontmatter, tags, path, stat}` (`tags` without `#`, from the text and the\nfrontmatter; `stat`: `{ctime, mtime, size}` or null). A missing file is an error.\n`path`: vault-relative, forward slashes.",
|
|
17537
17541
|
"inputSchema": {
|
|
17538
17542
|
"additionalProperties": false,
|
|
17539
17543
|
"properties": {
|
|
@@ -17560,7 +17564,7 @@ var OPERATIONS = [
|
|
|
17560
17564
|
},
|
|
17561
17565
|
{
|
|
17562
17566
|
"name": "list_directory",
|
|
17563
|
-
"description": '
|
|
17567
|
+
"description": 'Direct children of a vault folder (`GET /vault/{folder}/`): `{files: [...]}`. Folders end with\n`/`, names are sorted, dot-files are hidden. `""` is the vault root. A missing folder is an\nerror.',
|
|
17564
17568
|
"inputSchema": {
|
|
17565
17569
|
"additionalProperties": false,
|
|
17566
17570
|
"properties": {
|
|
@@ -17581,7 +17585,7 @@ var OPERATIONS = [
|
|
|
17581
17585
|
},
|
|
17582
17586
|
{
|
|
17583
17587
|
"name": "search_simple",
|
|
17584
|
-
"description": "
|
|
17588
|
+
"description": "Plain-text search (`POST /search/simple/`): every word of `query` must occur, case- and\naccent-insensitive, in the note's path or text; there are no operators. Returns up to 200\nfiles, best first: `[{filename, score, matches: [{match: {start, end}, context}]}]`, at most 20\nmatches per file. `context_length`: characters of context on each side (default 100, max 1000).",
|
|
17585
17589
|
"inputSchema": {
|
|
17586
17590
|
"additionalProperties": false,
|
|
17587
17591
|
"properties": {
|
|
@@ -17608,7 +17612,7 @@ var OPERATIONS = [
|
|
|
17608
17612
|
},
|
|
17609
17613
|
{
|
|
17610
17614
|
"name": "list_tables",
|
|
17611
|
-
"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)
|
|
17615
|
+
"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). Returns `{tables, views}`: `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.",
|
|
17612
17616
|
"inputSchema": {
|
|
17613
17617
|
"additionalProperties": false,
|
|
17614
17618
|
"properties": {},
|
|
@@ -17728,7 +17732,8 @@ var OPERATIONS = [
|
|
|
17728
17732
|
"type": "null"
|
|
17729
17733
|
}
|
|
17730
17734
|
],
|
|
17731
|
-
"default": null
|
|
17735
|
+
"default": null,
|
|
17736
|
+
"description": "Untyped fields of the table (name \u2192 default), kept on every row; a field cannot share a name with a column."
|
|
17732
17737
|
},
|
|
17733
17738
|
"body": {
|
|
17734
17739
|
"anyOf": [
|
|
@@ -17836,7 +17841,7 @@ var OPERATIONS = [
|
|
|
17836
17841
|
},
|
|
17837
17842
|
{
|
|
17838
17843
|
"name": "rename_column",
|
|
17839
|
-
"description": "Rename a column
|
|
17844
|
+
"description": "Rename a column in database.yaml and on every row. Refused if `to_column` is already a column\nof the table; a row that has a stray `to_column` key with a different value is a conflict, and\nnothing is written. Views and note text that mention the old name are not rewritten.",
|
|
17840
17845
|
"inputSchema": {
|
|
17841
17846
|
"additionalProperties": false,
|
|
17842
17847
|
"properties": {
|
|
@@ -18207,7 +18212,7 @@ var OPERATIONS = [
|
|
|
18207
18212
|
},
|
|
18208
18213
|
{
|
|
18209
18214
|
"name": "describe_database",
|
|
18210
|
-
"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 (
|
|
18215
|
+
"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` (with `rows` counts) and `views`.",
|
|
18211
18216
|
"inputSchema": {
|
|
18212
18217
|
"additionalProperties": false,
|
|
18213
18218
|
"properties": {},
|
|
@@ -18223,7 +18228,7 @@ var OPERATIONS = [
|
|
|
18223
18228
|
},
|
|
18224
18229
|
{
|
|
18225
18230
|
"name": "configure_database",
|
|
18226
|
-
"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
|
|
18231
|
+
"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.\nRenaming `root` moves the folder (links to its notes are rewritten); it is not journaled: to\nrevert, call it again with the old value.',
|
|
18227
18232
|
"inputSchema": {
|
|
18228
18233
|
"additionalProperties": false,
|
|
18229
18234
|
"properties": {
|
|
@@ -18398,7 +18403,8 @@ var OPERATIONS = [
|
|
|
18398
18403
|
"type": "null"
|
|
18399
18404
|
}
|
|
18400
18405
|
],
|
|
18401
|
-
"default": null
|
|
18406
|
+
"default": null,
|
|
18407
|
+
"description": "Optional note path (vault-relative), instead of the table's file-name pattern; `.md` is added if missing; it must stay inside the vault."
|
|
18402
18408
|
},
|
|
18403
18409
|
"dry_run": {
|
|
18404
18410
|
"default": false,
|
|
@@ -18636,7 +18642,7 @@ var OPERATIONS = [
|
|
|
18636
18642
|
"title": "Update Row",
|
|
18637
18643
|
"readOnlyHint": false,
|
|
18638
18644
|
"destructiveHint": false,
|
|
18639
|
-
"idempotentHint":
|
|
18645
|
+
"idempotentHint": false,
|
|
18640
18646
|
"openWorldHint": false
|
|
18641
18647
|
}
|
|
18642
18648
|
},
|
|
@@ -18790,7 +18796,7 @@ var OPERATIONS = [
|
|
|
18790
18796
|
},
|
|
18791
18797
|
{
|
|
18792
18798
|
"name": "adopt_rows",
|
|
18793
|
-
"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 (
|
|
18799
|
+
"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 (links to it are rewritten). 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`.',
|
|
18794
18800
|
"inputSchema": {
|
|
18795
18801
|
"additionalProperties": false,
|
|
18796
18802
|
"properties": {
|
|
@@ -19093,7 +19099,7 @@ var OPERATIONS = [
|
|
|
19093
19099
|
"annotations": {
|
|
19094
19100
|
"title": "Undo Migration",
|
|
19095
19101
|
"readOnlyHint": false,
|
|
19096
|
-
"destructiveHint":
|
|
19102
|
+
"destructiveHint": true,
|
|
19097
19103
|
"idempotentHint": false,
|
|
19098
19104
|
"openWorldHint": false
|
|
19099
19105
|
}
|
|
@@ -19258,7 +19264,7 @@ var OPERATIONS = [
|
|
|
19258
19264
|
},
|
|
19259
19265
|
{
|
|
19260
19266
|
"name": "semantic_search",
|
|
19261
|
-
"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).\
|
|
19267
|
+
"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).\n`limit`: default 10, max 100. Fails with a clear message when semantic search is not enabled in\nthe engine settings.',
|
|
19262
19268
|
"inputSchema": {
|
|
19263
19269
|
"additionalProperties": false,
|
|
19264
19270
|
"properties": {
|
|
@@ -19321,7 +19327,7 @@ var OPERATIONS = [
|
|
|
19321
19327
|
},
|
|
19322
19328
|
{
|
|
19323
19329
|
"name": "semantic_index",
|
|
19324
|
-
"description": "Semantic search index: `status` (provider
|
|
19330
|
+
"description": "Semantic search index: `status` (`enabled`, `provider`, `model`, `files`, `passages`, `pending`,\n`running`, `lastSync`, `lastError`), `update` (embed notes changed since the last run; the\nengine also does it on its own about ten seconds after edits) or `rebuild` (re-embed\neverything: slow, and costs money with a paid provider \u2014 ask first).",
|
|
19325
19331
|
"inputSchema": {
|
|
19326
19332
|
"additionalProperties": false,
|
|
19327
19333
|
"properties": {
|
|
@@ -19467,7 +19473,7 @@ var OPERATIONS = [
|
|
|
19467
19473
|
},
|
|
19468
19474
|
{
|
|
19469
19475
|
"name": "describe_history",
|
|
19470
|
-
"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
|
|
19476
|
+
"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 outside the engine: an editor, git, sync), `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`.",
|
|
19471
19477
|
"inputSchema": {
|
|
19472
19478
|
"additionalProperties": false,
|
|
19473
19479
|
"properties": {
|
|
@@ -19539,7 +19545,7 @@ var OPERATIONS = [
|
|
|
19539
19545
|
},
|
|
19540
19546
|
{
|
|
19541
19547
|
"name": "list_changes",
|
|
19542
|
-
"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`.
|
|
19548
|
+
"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`. Agents' tool calls (reported by MCP servers) 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` (max 60000) waits for a new change (long poll); `limit` max 5000. `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`.",
|
|
19543
19549
|
"inputSchema": {
|
|
19544
19550
|
"additionalProperties": false,
|
|
19545
19551
|
"properties": {
|
|
@@ -20065,7 +20071,7 @@ var OPERATIONS = [
|
|
|
20065
20071
|
},
|
|
20066
20072
|
{
|
|
20067
20073
|
"name": "clone_table",
|
|
20068
|
-
"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` (
|
|
20074
|
+
"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` (in the\nsource's catalog) or a name (source's catalog and schema). Useful for experiments, e.g. a sandbox copy\nin the `agent` catalog.",
|
|
20069
20075
|
"inputSchema": {
|
|
20070
20076
|
"additionalProperties": false,
|
|
20071
20077
|
"properties": {
|
|
@@ -20122,7 +20128,7 @@ var OPERATIONS = [
|
|
|
20122
20128
|
},
|
|
20123
20129
|
{
|
|
20124
20130
|
"name": "recompute_columns",
|
|
20125
|
-
"description": "Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after\nrows were edited
|
|
20131
|
+
"description": "Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after\nrows were edited by hand (an editor, git, sync) 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 (new ones on every call): only on the user's\nexplicit 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.",
|
|
20126
20132
|
"inputSchema": {
|
|
20127
20133
|
"additionalProperties": false,
|
|
20128
20134
|
"properties": {
|
|
@@ -20161,7 +20167,7 @@ var OPERATIONS = [
|
|
|
20161
20167
|
"title": "Recompute Columns",
|
|
20162
20168
|
"readOnlyHint": false,
|
|
20163
20169
|
"destructiveHint": false,
|
|
20164
|
-
"idempotentHint":
|
|
20170
|
+
"idempotentHint": false,
|
|
20165
20171
|
"openWorldHint": false
|
|
20166
20172
|
}
|
|
20167
20173
|
},
|
|
@@ -20326,7 +20332,7 @@ var OPERATIONS = [
|
|
|
20326
20332
|
},
|
|
20327
20333
|
{
|
|
20328
20334
|
"name": "graph_path",
|
|
20329
|
-
"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).',
|
|
20335
|
+
"description": 'Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or\n`{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`).\n`direction` both by default; `max_depth` default 6 (max 10).',
|
|
20330
20336
|
"inputSchema": {
|
|
20331
20337
|
"additionalProperties": false,
|
|
20332
20338
|
"properties": {
|
|
@@ -20464,7 +20470,8 @@ var ROUTES = {
|
|
|
20464
20470
|
create_webhook: (a) => ["/webhooks/create/", pick(a, ["url", "tables", "ops", "columns", "exclude_actor", "where", "since"])],
|
|
20465
20471
|
delete_webhook: (a) => ["/webhooks/delete/", pick(a, ["id"])],
|
|
20466
20472
|
restore_table: (a) => ["/history/restore/", { ...pick(a, ["table", "version", "timestamp"]), ...dry(a) }],
|
|
20467
|
-
|
|
20473
|
+
// vacuum deletes history for good: a dry run unless the caller says `dry_run: false`
|
|
20474
|
+
vacuum_table: (a) => ["/history/vacuum/", { ...pick(a, ["table", "retain_from_version"]), dry_run: a.dry_run !== false }],
|
|
20468
20475
|
graph_neighbors: (a) => ["/graph/neighbors/", compact({ from: a.from_nodes, direction: a.direction, edges: a.edges })],
|
|
20469
20476
|
graph_traverse: (a) => [
|
|
20470
20477
|
"/graph/traverse/",
|
|
@@ -22062,7 +22069,7 @@ var NodeWatcher = class {
|
|
|
22062
22069
|
};
|
|
22063
22070
|
|
|
22064
22071
|
// src/node/service.ts
|
|
22065
|
-
var VERSION = true ? "1.2.
|
|
22072
|
+
var VERSION = true ? "1.2.1" : "dev";
|
|
22066
22073
|
function parseArgs(argv, env = process.env) {
|
|
22067
22074
|
const get = (name) => {
|
|
22068
22075
|
const i = argv.indexOf(`--${name}`);
|
|
@@ -22107,6 +22114,11 @@ async function startService(o, env = process.env) {
|
|
|
22107
22114
|
import_node_fs5.default.writeFileSync(file, JSON.stringify({ ...current2, ...settings }, null, 2));
|
|
22108
22115
|
};
|
|
22109
22116
|
const host = openNodeVault(o.vault);
|
|
22117
|
+
const held = await readLock(host.vault.adapter, storeRoot(settings));
|
|
22118
|
+
if (isFresh(held) && held.pid !== process.pid && (held.host !== import_node_os.default.hostname() || processAlive(held.pid))) {
|
|
22119
|
+
host.metadataCache.dispose();
|
|
22120
|
+
throw new Error(`another engine holds the vault (pid ${held.pid} on ${held.host}, port ${held.port}): stop it first`);
|
|
22121
|
+
}
|
|
22110
22122
|
const watcher = new NodeWatcher(host.vault, { mode: o.watch, intervalMs: o.pollMs });
|
|
22111
22123
|
const keyFromFile = () => {
|
|
22112
22124
|
if (!o.embeddingKeyFile) return void 0;
|
|
@@ -22184,6 +22196,14 @@ async function startService(o, env = process.env) {
|
|
|
22184
22196
|
}
|
|
22185
22197
|
};
|
|
22186
22198
|
}
|
|
22199
|
+
function processAlive(pid) {
|
|
22200
|
+
try {
|
|
22201
|
+
process.kill(pid, 0);
|
|
22202
|
+
return true;
|
|
22203
|
+
} catch (e) {
|
|
22204
|
+
return e.code === "EPERM";
|
|
22205
|
+
}
|
|
22206
|
+
}
|
|
22187
22207
|
async function main(argv = process.argv.slice(2)) {
|
|
22188
22208
|
const li = argv.indexOf("--log");
|
|
22189
22209
|
if (li >= 0 && argv[li + 1]) {
|
|
@@ -22227,7 +22247,7 @@ Docs: https://datanotes.dev`;
|
|
|
22227
22247
|
}
|
|
22228
22248
|
|
|
22229
22249
|
// src/node/cli.ts
|
|
22230
|
-
var VERSION2 = true ? "1.2.
|
|
22250
|
+
var VERSION2 = true ? "1.2.1" : "dev";
|
|
22231
22251
|
async function main2(argv = process.argv.slice(2)) {
|
|
22232
22252
|
const [command, ...rest] = argv;
|
|
22233
22253
|
if (command === "--version" || command === "-v" || command === "version") return void process.stdout.write(`${VERSION2}
|