datanotes 3.1.0 → 3.3.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.
Files changed (72) hide show
  1. package/README.md +1 -0
  2. package/SECURITY.md +12 -0
  3. package/dist/api/client.d.cts +2 -0
  4. package/dist/api/client.d.ts +2 -0
  5. package/dist/api/docs.d.cts +14 -4
  6. package/dist/api/docs.d.ts +14 -4
  7. package/dist/api/extension-files.d.cts +23 -0
  8. package/dist/api/extension-files.d.ts +23 -0
  9. package/dist/api/extension-host.d.cts +108 -0
  10. package/dist/api/extension-host.d.ts +108 -0
  11. package/dist/api/extension-manifest.d.cts +154 -0
  12. package/dist/api/extension-manifest.d.ts +154 -0
  13. package/dist/api/extension-plan.d.cts +174 -0
  14. package/dist/api/extension-plan.d.ts +174 -0
  15. package/dist/api/extension-record.d.cts +65 -0
  16. package/dist/api/extension-record.d.ts +65 -0
  17. package/dist/api/extension-sdk.d.cts +65 -0
  18. package/dist/api/extension-sdk.d.ts +65 -0
  19. package/dist/api/extensions.cjs +18472 -0
  20. package/dist/api/extensions.d.cts +11 -0
  21. package/dist/api/extensions.d.ts +11 -0
  22. package/dist/api/extensions.js +18409 -0
  23. package/dist/api/index.cjs +675 -503
  24. package/dist/api/index.js +675 -503
  25. package/dist/api/mcp.cjs +203 -13
  26. package/dist/api/mcp.js +203 -13
  27. package/dist/datanotes.cjs +7903 -4667
  28. package/dist/docs/administration/extensions.md +213 -0
  29. package/dist/docs/api/operations/add_column.md +1 -0
  30. package/dist/docs/api/operations/add_constraint.md +2 -0
  31. package/dist/docs/api/operations/alter_column.md +1 -1
  32. package/dist/docs/api/operations/alter_table.md +3 -2
  33. package/dist/docs/api/operations/check_table.md +1 -1
  34. package/dist/docs/api/operations/create_table.md +3 -1
  35. package/dist/docs/api/operations/describe_table.md +1 -1
  36. package/dist/docs/api/operations/extensions_delete.md +29 -0
  37. package/dist/docs/api/operations/extensions_list.md +20 -0
  38. package/dist/docs/api/operations/extensions_record.md +44 -0
  39. package/dist/docs/api/operations/insert_row.md +2 -2
  40. package/dist/docs/api/operations/tags/extensions.md +9 -0
  41. package/dist/docs/api/operations/tags/rows-dml.md +1 -1
  42. package/dist/docs/api.md +10 -2
  43. package/dist/docs/develop/write-an-extension.md +369 -0
  44. package/dist/docs/guides/data-quality/check-constraints.md +14 -13
  45. package/dist/docs/guides/data-quality/hand-edits.md +10 -10
  46. package/dist/docs/guides/database-objects/bases.md +11 -11
  47. package/dist/docs/guides/database-objects/catalogs-and-schemas.md +16 -10
  48. package/dist/docs/guides/database-objects/columns.md +38 -38
  49. package/dist/docs/guides/database-objects/relations.md +173 -36
  50. package/dist/docs/guides/database-objects/tables.md +80 -35
  51. package/dist/docs/guides/database-objects/views.md +44 -44
  52. package/dist/docs/guides/history/change-data-feed.md +34 -34
  53. package/dist/docs/guides/history/journal-and-undo.md +12 -12
  54. package/dist/docs/guides/history/restore.md +20 -20
  55. package/dist/docs/guides/history/table-history.md +31 -31
  56. package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
  57. package/dist/docs/guides/read-and-write/import-notes.md +21 -21
  58. package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
  59. package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
  60. package/dist/docs/guides/read-and-write/write-rows.md +10 -10
  61. package/dist/docs/guides/search/text.md +1 -1
  62. package/dist/docs/guides/security/security-model.md +12 -0
  63. package/dist/docs/reference/cli.md +32 -1
  64. package/dist/docs/reference/errors.md +1 -1
  65. package/dist/docs/reference/glossary.md +8 -0
  66. package/dist/docs/reference/operations/auxiliary.md +2 -2
  67. package/dist/docs/reference/operations/rows.md +1 -1
  68. package/dist/docs/reference/operations/schema.md +15 -11
  69. package/dist/docs/reference/operations.md +28 -28
  70. package/dist/docs/release-notes.md +57 -0
  71. package/dist/docs/start/connect-agents.md +11 -0
  72. package/package.json +11 -1
@@ -0,0 +1,154 @@
1
+ /**
2
+ * The manifest of a Datanotes extension (`datanotes-extension.json`, format version 1): parsing, validation
3
+ * with errors that teach (every problem at once, each as `<path>: <text>`), version comparison and the
4
+ * binding of table roles to real tables. The installer reads only this file before the user confirms, so
5
+ * everything an extension can do is declared here. No dependency but ./guidance.js.
6
+ */
7
+ /** The manifest's file name at the root of the extension's repository. */
8
+ export declare const MANIFEST_FILE = "datanotes-extension.json";
9
+ /** Docs pages and headings that the errors of extensions point to (the pages are in docs/). */
10
+ export declare const EXT_DOCS: {
11
+ readonly install: "https://datanotes.dev/administration/extensions.md#install-an-extension";
12
+ readonly tables: "https://datanotes.dev/administration/extensions.md#choose-the-tables-an-extension-uses";
13
+ readonly permissions: "https://datanotes.dev/administration/extensions.md#what-an-extension-can-do";
14
+ readonly update: "https://datanotes.dev/administration/extensions.md#update-an-extension";
15
+ readonly rollback: "https://datanotes.dev/administration/extensions.md#undo-an-install-or-an-update";
16
+ readonly remove: "https://datanotes.dev/administration/extensions.md#remove-an-extension";
17
+ readonly skipped: "https://datanotes.dev/administration/extensions.md#when-the-mcp-server-skips-an-extension";
18
+ readonly where: "https://datanotes.dev/administration/extensions.md#where-extensions-live";
19
+ readonly layout: "https://datanotes.dev/develop/write-an-extension.md#lay-out-the-repository";
20
+ readonly manifest: "https://datanotes.dev/develop/write-an-extension.md#write-the-manifest";
21
+ readonly declare: "https://datanotes.dev/develop/write-an-extension.md#declare-the-tables";
22
+ readonly tools: "https://datanotes.dev/develop/write-an-extension.md#write-the-tools";
23
+ readonly migrations: "https://datanotes.dev/develop/write-an-extension.md#migrate-the-schema-between-versions";
24
+ readonly publish: "https://datanotes.dev/develop/write-an-extension.md#check-and-publish-an-extension";
25
+ };
26
+ /** An extension's name (its token is `ext-<name>`). */
27
+ export declare const EXTENSION_NAME: RegExp;
28
+ /** A role, a table, a schema, a column, a base. */
29
+ export declare const IDENT: RegExp;
30
+ /** A tool's name. */
31
+ export declare const TOOL_NAME: RegExp;
32
+ /** The column types of the engine (a test checks the list against src/core). */
33
+ export declare const COLUMN_TYPES: readonly string[];
34
+ /** The attributes of a column spec in the engine (src/core/table-loader.ts; a test checks the list). */
35
+ export declare const COLUMN_ATTRS: readonly string[];
36
+ /** The operations a batch takes (src/server/rest.ts; a test checks the list). */
37
+ export declare const BATCH_OPERATIONS: readonly string[];
38
+ /** The operations that write rows. */
39
+ export declare const DATA_OPERATIONS: readonly string[];
40
+ /** An extension's own error: what is wrong, how to fix it, where to read more. */
41
+ export declare class ExtensionError extends Error {
42
+ readonly hint: string;
43
+ readonly docs: string;
44
+ readonly code: string;
45
+ readonly name: string;
46
+ constructor(message: string, hint: string, docs: string, code?: string);
47
+ }
48
+ /** A manifest that is not valid: every problem, in the order of the walk. */
49
+ export declare class ExtensionManifestError extends ExtensionError {
50
+ readonly problems: string[];
51
+ readonly name = "ExtensionManifestError";
52
+ constructor(problems: string[], file?: string);
53
+ }
54
+ /** Whether a table the extension depends on must have the column. */
55
+ export type ColumnNeed = "required" | "optional";
56
+ /** A column spec as the engine's operations take it, plus `need`. */
57
+ export interface ManifestColumn {
58
+ name: string;
59
+ type: string;
60
+ description: string;
61
+ need: ColumnNeed;
62
+ [attribute: string]: unknown;
63
+ }
64
+ export interface ManifestConstraint {
65
+ name: string;
66
+ check: Record<string, unknown>;
67
+ hint: string;
68
+ }
69
+ export interface ManifestTable {
70
+ owned: boolean;
71
+ /** The table's name when created; the role when missing. */
72
+ name?: string;
73
+ schema?: string;
74
+ names?: string[];
75
+ description: string;
76
+ aliases?: string[];
77
+ filename?: string;
78
+ columns: ManifestColumn[];
79
+ constraints?: ManifestConstraint[];
80
+ instructions?: string;
81
+ bases?: string[];
82
+ }
83
+ export interface ManifestBase {
84
+ description: string;
85
+ columns: ManifestColumn[];
86
+ }
87
+ export interface ManifestView {
88
+ description: string;
89
+ query: Record<string, unknown>;
90
+ aliases?: string[];
91
+ labels?: Record<string, unknown>;
92
+ }
93
+ export interface ManifestTool {
94
+ name: string;
95
+ description: string;
96
+ inputSchema: Record<string, unknown>;
97
+ annotations: Record<string, unknown>;
98
+ /** Roles the tool reads or writes. */
99
+ tables: string[];
100
+ /** Roles the tool writes. */
101
+ writes: string[];
102
+ }
103
+ export interface ManifestMigration {
104
+ version: string;
105
+ description: string;
106
+ operations: ({
107
+ op: string;
108
+ } & Record<string, unknown>)[];
109
+ }
110
+ export interface ExtensionManifest {
111
+ manifest_version: 1;
112
+ name: string;
113
+ version: string;
114
+ description: string;
115
+ datanotes: string;
116
+ api: 1;
117
+ entry: string;
118
+ default_schema: string;
119
+ instructions?: string;
120
+ tables: Record<string, ManifestTable>;
121
+ /** The keys of `tables`, in order. */
122
+ roles: string[];
123
+ bases: Record<string, ManifestBase>;
124
+ views: Record<string, ManifestView>;
125
+ permissions: {
126
+ write: string[];
127
+ };
128
+ tools: ManifestTool[];
129
+ migrations: ManifestMigration[];
130
+ }
131
+ export interface SemVer {
132
+ major: number;
133
+ minor: number;
134
+ patch: number;
135
+ pre: string | null;
136
+ }
137
+ /** MAJOR.MINOR.PATCH[-pre] (no leading `v`); null when it is not a version. */
138
+ export declare function parseVersion(v: string): SemVer | null;
139
+ /** Negative when a is older than b, 0 when equal, positive when newer. Throws for text that is not a version. */
140
+ export declare function compareVersions(a: string, b: string): number;
141
+ /** Whether an engine version meets a manifest's `">=X.Y.Z"`. A source run ("dev", "") meets every range. */
142
+ export declare function satisfiesEngine(range: string, engineVersion: string): boolean;
143
+ /** A string that is exactly a role: `@task`. */
144
+ export declare const ROLE_REF: RegExp;
145
+ /** A role inside a text: `@{task}`. */
146
+ export declare const ROLE_TEXT: RegExp;
147
+ /** A deep copy of `value` with every `@role` string and every `@{role}` in a string replaced by the role's table. Keys stay. */
148
+ export declare function bindRoles<T>(value: T, tables: Readonly<Record<string, string>>): T;
149
+ /** The roles a value names, in order of first appearance (both forms). */
150
+ export declare function rolesNamed(value: unknown): string[];
151
+ /** Read a manifest's text (a leading BOM is fine) and validate it. */
152
+ export declare function parseManifest(text: string, file?: string): ExtensionManifest;
153
+ /** Check a parsed manifest, collecting every problem; returns the typed manifest (a deep copy) or throws ExtensionManifestError. */
154
+ export declare function validateManifest(raw: unknown, file?: string): ExtensionManifest;
@@ -0,0 +1,174 @@
1
+ /**
2
+ * The install plan of a Datanotes extension: which table each role of the manifest uses, how the
3
+ * existing tables differ from what the manifest declares, the migrations between two versions, and
4
+ * the one batch that brings the database to the new version, with the token change, the tools, the
5
+ * problems and the record to write. Pure: the CLI reads the database (list_tables, describe_table,
6
+ * describe_database) and passes what it read; nothing here reads or writes anything.
7
+ */
8
+ import type { ExtensionManifest } from "./extension-manifest.cjs";
9
+ import type { ExtensionSourceRecord, InstalledExtension } from "./extension-record.cjs";
10
+ /** What list_tables answered, with the database's default catalog. */
11
+ export interface TablesListing {
12
+ default_catalog: string;
13
+ tables: {
14
+ qualified: string;
15
+ name: string;
16
+ catalog: string;
17
+ schema: string;
18
+ aliases?: string[];
19
+ tags?: Record<string, string>;
20
+ }[];
21
+ views: {
22
+ qualified: string;
23
+ }[];
24
+ }
25
+ /** The user's choices, from the options of the command. */
26
+ export interface InstallChoices {
27
+ /** role → qualified table (`--map role=catalog.schema.table`). */
28
+ map: Record<string, string>;
29
+ /** role → (manifest column → the user's column) (`--map role.column=column`). */
30
+ columns: Record<string, Record<string, string>>;
31
+ /** Dependency roles to create (`--create`). */
32
+ create: string[];
33
+ /** role → manifest columns to add to the matched dependency table (`--add role.column`). */
34
+ add: Record<string, string[]>;
35
+ /** Catalog of created tables and views (`--catalog`; default: the database's default catalog). */
36
+ catalog?: string;
37
+ /** Schema of created owned tables and views (`--schema`; default: the manifest's default_schema). */
38
+ schema?: string;
39
+ }
40
+ export type TableDecision = "create" | "adopt" | "match" | "unresolved";
41
+ /** The table chosen for one role. */
42
+ export interface TableChoice {
43
+ role: string;
44
+ owned: boolean;
45
+ table: string | null;
46
+ decision: TableDecision;
47
+ /** True when the installer chose it, not the user: the agent must confirm it with the user. */
48
+ proposed: boolean;
49
+ candidates: string[];
50
+ }
51
+ export type ProblemCode = "engine_too_old" | "unknown_role" | "table_not_found" | "table_missing" | "table_exists" | "owned_create" | "ambiguous_dependency" | "missing_column" | "column_differs" | "owned_column_map" | "migration_conflict" | "base_differs" | "view_exists" | "tool_name_taken" | "token_exists" | "too_many_operations" | "already_installed" | "downgrade" | "same_version";
52
+ /** Something that keeps the plan from being written: what is wrong, how to fix it, where to read more. */
53
+ export interface PlanProblem {
54
+ code: ProblemCode;
55
+ role?: string;
56
+ table?: string;
57
+ column?: string;
58
+ detail: string;
59
+ hint: string;
60
+ docs: string;
61
+ }
62
+ /** What describe_table answered for an existing table. */
63
+ export interface DescribedTable {
64
+ qualified: string;
65
+ columns: Record<string, unknown>[];
66
+ constraints?: Record<string, Record<string, unknown>>;
67
+ constraint_hints?: Record<string, string>;
68
+ instructions?: string;
69
+ bases?: string[];
70
+ tags?: Record<string, string>;
71
+ }
72
+ export interface PlanInput {
73
+ manifest: ExtensionManifest;
74
+ /** What was fetched: the label the user reads, the source record, the commit and the hashes. */
75
+ source: {
76
+ label: string;
77
+ record: ExtensionSourceRecord;
78
+ commit: string;
79
+ manifest_sha256: string;
80
+ entry_sha256: string;
81
+ };
82
+ engineVersion: string;
83
+ listing: TablesListing;
84
+ chosen: TableChoice[];
85
+ choiceProblems: PlanProblem[];
86
+ /** describe_table answers, by qualified name, for every bound existing table. */
87
+ described: Record<string, DescribedTable>;
88
+ /** describe_database bases. */
89
+ bases: {
90
+ name: string;
91
+ columns: string[];
92
+ }[];
93
+ choices: InstallChoices;
94
+ /** Names of the named tokens (/tokens/). */
95
+ tokens: string[];
96
+ /** The record of this extension, when installed. */
97
+ installed: InstalledExtension | null;
98
+ /** install: null; a repair: the fetched manifest itself (null is read as it); update: the installed version's manifest. */
99
+ oldManifest: ExtensionManifest | null;
100
+ /** The other installed extensions (their tool names). */
101
+ others: InstalledExtension[];
102
+ /** Engine operations and docs tools (the CLI passes OPERATIONS names + DOCS_TOOL_NAMES). */
103
+ reservedTools: string[];
104
+ /** Whether this machine holds the extension's token file. */
105
+ localTokenPresent: boolean;
106
+ /** ISO time for the record's dates. */
107
+ now: string;
108
+ }
109
+ export interface PlanTable {
110
+ role: string;
111
+ owned: boolean;
112
+ table: string | null;
113
+ decision: TableDecision;
114
+ proposed: boolean;
115
+ candidates: string[];
116
+ /** Human lines: "create", "add column repo", "replace CHECK run_has_executor", "set instructions", "add tags". */
117
+ changes: string[];
118
+ columns: Record<string, string>;
119
+ absent: string[];
120
+ }
121
+ export interface PlanTool {
122
+ name: string;
123
+ read_only: boolean;
124
+ /** Qualified names of the tables it writes. */
125
+ writes: string[];
126
+ change: "added" | "removed" | "changed" | "same";
127
+ }
128
+ export interface ExtensionPlan {
129
+ action: "install" | "repair" | "update";
130
+ extension: {
131
+ name: string;
132
+ version: string;
133
+ description: string;
134
+ from_version: string | null;
135
+ source: string;
136
+ commit: string;
137
+ };
138
+ tables: PlanTable[];
139
+ /** The batch, each `{ op, ...arguments }`, in order (empty: nothing to write). */
140
+ operations: Record<string, unknown>[];
141
+ token: {
142
+ name: string;
143
+ action: "create" | "rotate" | "update" | "keep";
144
+ write: string[];
145
+ previous_write: string[] | null;
146
+ };
147
+ tools: PlanTool[];
148
+ problems: PlanProblem[];
149
+ notes: string[];
150
+ ready: boolean;
151
+ agent_message: string;
152
+ summary: string;
153
+ /** The record to write after the batch (`migration_id` filled by the CLI); null when not ready. */
154
+ record: InstalledExtension | null;
155
+ }
156
+ /** The text every plan ends with, for the agent that runs the installer. */
157
+ export declare const AGENT_MESSAGE = "For the agent installing this extension: show this plan to the user before anything is written. Where a table says \"proposed\", the installer chose it: ask the user to confirm it, to pick another table (--map <role>=<catalog.schema.table>, --map <role>.<column>=<column>), or to create it (--create <role>). Add a missing column only after the user agrees (--add <role>.<column>). Solve each problem the same way. Then run the same command again with the user's choices and --yes, only once the user approved the tables it creates or changes, the tools and the token's permissions.";
158
+ /** The most operations one batch takes. */
159
+ export declare const MAX_OPERATIONS = 200;
160
+ /**
161
+ * How an existing column differs from what the manifest expects, in a few words (null: it fits).
162
+ * `ref: "self"` means `ownTable` on both sides. `strict` also compares hierarchy, acyclic and inverse
163
+ * (the extension's own tables); other attributes never count.
164
+ */
165
+ export declare function columnDifference(expected: Record<string, unknown>, actual: Record<string, unknown>, ownTable: string, strict: boolean): string | null;
166
+ /** The table of every role of the manifest, from the user's choices, the installed record and the listing. */
167
+ export declare function chooseTables(m: ExtensionManifest, listing: TablesListing, choices: InstallChoices, installed: InstalledExtension | null): {
168
+ chosen: TableChoice[];
169
+ problems: PlanProblem[];
170
+ };
171
+ /** Compute the plan of an install, a repair or an update from what the CLI read. */
172
+ export declare function planChanges(input: PlanInput): ExtensionPlan;
173
+ /** The plan as the user reads it in a terminal. */
174
+ export declare function renderPlan(plan: ExtensionPlan): string;
@@ -0,0 +1,174 @@
1
+ /**
2
+ * The install plan of a Datanotes extension: which table each role of the manifest uses, how the
3
+ * existing tables differ from what the manifest declares, the migrations between two versions, and
4
+ * the one batch that brings the database to the new version, with the token change, the tools, the
5
+ * problems and the record to write. Pure: the CLI reads the database (list_tables, describe_table,
6
+ * describe_database) and passes what it read; nothing here reads or writes anything.
7
+ */
8
+ import type { ExtensionManifest } from "./extension-manifest.js";
9
+ import type { ExtensionSourceRecord, InstalledExtension } from "./extension-record.js";
10
+ /** What list_tables answered, with the database's default catalog. */
11
+ export interface TablesListing {
12
+ default_catalog: string;
13
+ tables: {
14
+ qualified: string;
15
+ name: string;
16
+ catalog: string;
17
+ schema: string;
18
+ aliases?: string[];
19
+ tags?: Record<string, string>;
20
+ }[];
21
+ views: {
22
+ qualified: string;
23
+ }[];
24
+ }
25
+ /** The user's choices, from the options of the command. */
26
+ export interface InstallChoices {
27
+ /** role → qualified table (`--map role=catalog.schema.table`). */
28
+ map: Record<string, string>;
29
+ /** role → (manifest column → the user's column) (`--map role.column=column`). */
30
+ columns: Record<string, Record<string, string>>;
31
+ /** Dependency roles to create (`--create`). */
32
+ create: string[];
33
+ /** role → manifest columns to add to the matched dependency table (`--add role.column`). */
34
+ add: Record<string, string[]>;
35
+ /** Catalog of created tables and views (`--catalog`; default: the database's default catalog). */
36
+ catalog?: string;
37
+ /** Schema of created owned tables and views (`--schema`; default: the manifest's default_schema). */
38
+ schema?: string;
39
+ }
40
+ export type TableDecision = "create" | "adopt" | "match" | "unresolved";
41
+ /** The table chosen for one role. */
42
+ export interface TableChoice {
43
+ role: string;
44
+ owned: boolean;
45
+ table: string | null;
46
+ decision: TableDecision;
47
+ /** True when the installer chose it, not the user: the agent must confirm it with the user. */
48
+ proposed: boolean;
49
+ candidates: string[];
50
+ }
51
+ export type ProblemCode = "engine_too_old" | "unknown_role" | "table_not_found" | "table_missing" | "table_exists" | "owned_create" | "ambiguous_dependency" | "missing_column" | "column_differs" | "owned_column_map" | "migration_conflict" | "base_differs" | "view_exists" | "tool_name_taken" | "token_exists" | "too_many_operations" | "already_installed" | "downgrade" | "same_version";
52
+ /** Something that keeps the plan from being written: what is wrong, how to fix it, where to read more. */
53
+ export interface PlanProblem {
54
+ code: ProblemCode;
55
+ role?: string;
56
+ table?: string;
57
+ column?: string;
58
+ detail: string;
59
+ hint: string;
60
+ docs: string;
61
+ }
62
+ /** What describe_table answered for an existing table. */
63
+ export interface DescribedTable {
64
+ qualified: string;
65
+ columns: Record<string, unknown>[];
66
+ constraints?: Record<string, Record<string, unknown>>;
67
+ constraint_hints?: Record<string, string>;
68
+ instructions?: string;
69
+ bases?: string[];
70
+ tags?: Record<string, string>;
71
+ }
72
+ export interface PlanInput {
73
+ manifest: ExtensionManifest;
74
+ /** What was fetched: the label the user reads, the source record, the commit and the hashes. */
75
+ source: {
76
+ label: string;
77
+ record: ExtensionSourceRecord;
78
+ commit: string;
79
+ manifest_sha256: string;
80
+ entry_sha256: string;
81
+ };
82
+ engineVersion: string;
83
+ listing: TablesListing;
84
+ chosen: TableChoice[];
85
+ choiceProblems: PlanProblem[];
86
+ /** describe_table answers, by qualified name, for every bound existing table. */
87
+ described: Record<string, DescribedTable>;
88
+ /** describe_database bases. */
89
+ bases: {
90
+ name: string;
91
+ columns: string[];
92
+ }[];
93
+ choices: InstallChoices;
94
+ /** Names of the named tokens (/tokens/). */
95
+ tokens: string[];
96
+ /** The record of this extension, when installed. */
97
+ installed: InstalledExtension | null;
98
+ /** install: null; a repair: the fetched manifest itself (null is read as it); update: the installed version's manifest. */
99
+ oldManifest: ExtensionManifest | null;
100
+ /** The other installed extensions (their tool names). */
101
+ others: InstalledExtension[];
102
+ /** Engine operations and docs tools (the CLI passes OPERATIONS names + DOCS_TOOL_NAMES). */
103
+ reservedTools: string[];
104
+ /** Whether this machine holds the extension's token file. */
105
+ localTokenPresent: boolean;
106
+ /** ISO time for the record's dates. */
107
+ now: string;
108
+ }
109
+ export interface PlanTable {
110
+ role: string;
111
+ owned: boolean;
112
+ table: string | null;
113
+ decision: TableDecision;
114
+ proposed: boolean;
115
+ candidates: string[];
116
+ /** Human lines: "create", "add column repo", "replace CHECK run_has_executor", "set instructions", "add tags". */
117
+ changes: string[];
118
+ columns: Record<string, string>;
119
+ absent: string[];
120
+ }
121
+ export interface PlanTool {
122
+ name: string;
123
+ read_only: boolean;
124
+ /** Qualified names of the tables it writes. */
125
+ writes: string[];
126
+ change: "added" | "removed" | "changed" | "same";
127
+ }
128
+ export interface ExtensionPlan {
129
+ action: "install" | "repair" | "update";
130
+ extension: {
131
+ name: string;
132
+ version: string;
133
+ description: string;
134
+ from_version: string | null;
135
+ source: string;
136
+ commit: string;
137
+ };
138
+ tables: PlanTable[];
139
+ /** The batch, each `{ op, ...arguments }`, in order (empty: nothing to write). */
140
+ operations: Record<string, unknown>[];
141
+ token: {
142
+ name: string;
143
+ action: "create" | "rotate" | "update" | "keep";
144
+ write: string[];
145
+ previous_write: string[] | null;
146
+ };
147
+ tools: PlanTool[];
148
+ problems: PlanProblem[];
149
+ notes: string[];
150
+ ready: boolean;
151
+ agent_message: string;
152
+ summary: string;
153
+ /** The record to write after the batch (`migration_id` filled by the CLI); null when not ready. */
154
+ record: InstalledExtension | null;
155
+ }
156
+ /** The text every plan ends with, for the agent that runs the installer. */
157
+ export declare const AGENT_MESSAGE = "For the agent installing this extension: show this plan to the user before anything is written. Where a table says \"proposed\", the installer chose it: ask the user to confirm it, to pick another table (--map <role>=<catalog.schema.table>, --map <role>.<column>=<column>), or to create it (--create <role>). Add a missing column only after the user agrees (--add <role>.<column>). Solve each problem the same way. Then run the same command again with the user's choices and --yes, only once the user approved the tables it creates or changes, the tools and the token's permissions.";
158
+ /** The most operations one batch takes. */
159
+ export declare const MAX_OPERATIONS = 200;
160
+ /**
161
+ * How an existing column differs from what the manifest expects, in a few words (null: it fits).
162
+ * `ref: "self"` means `ownTable` on both sides. `strict` also compares hierarchy, acyclic and inverse
163
+ * (the extension's own tables); other attributes never count.
164
+ */
165
+ export declare function columnDifference(expected: Record<string, unknown>, actual: Record<string, unknown>, ownTable: string, strict: boolean): string | null;
166
+ /** The table of every role of the manifest, from the user's choices, the installed record and the listing. */
167
+ export declare function chooseTables(m: ExtensionManifest, listing: TablesListing, choices: InstallChoices, installed: InstalledExtension | null): {
168
+ chosen: TableChoice[];
169
+ problems: PlanProblem[];
170
+ };
171
+ /** Compute the plan of an install, a repair or an update from what the CLI read. */
172
+ export declare function planChanges(input: PlanInput): ExtensionPlan;
173
+ /** The plan as the user reads it in a terminal. */
174
+ export declare function renderPlan(plan: ExtensionPlan): string;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The record of an installed extension: what `datanotes extension install` writes to the engine's
3
+ * registry (`POST /datanotes/extensions/record/`) and every MCP host reads back
4
+ * (`POST /datanotes/extensions/`). Shape only: this file imports nothing.
5
+ */
6
+ export interface RecordTable {
7
+ /** The qualified table bound to the role. */
8
+ table: string;
9
+ /** True for a role the extension owns. */
10
+ owned: boolean;
11
+ /** Dependency roles: manifest column → the user's column, only where they differ. */
12
+ columns?: Record<string, string>;
13
+ /** Dependency roles: optional manifest columns the bound table does not have. */
14
+ absent?: string[];
15
+ }
16
+ export interface ExtensionSourceRecord {
17
+ kind: "git" | "local";
18
+ /** git: the URL as given (https://…, git@…, ssh://…, file://…). */
19
+ url?: string;
20
+ /** git: the tag or commit id given (or the newest tag chosen). */
21
+ ref?: string;
22
+ /** local: the absolute folder, with "/" separators. */
23
+ path?: string;
24
+ }
25
+ export interface InstalledExtension {
26
+ name: string;
27
+ version: string;
28
+ description: string;
29
+ api: number;
30
+ source: ExtensionSourceRecord;
31
+ /** The git commit id (40 hex), or "local-<12 hex>" for a folder. */
32
+ commit: string;
33
+ manifest_sha256: string;
34
+ entry_sha256: string;
35
+ /** The extension's named token: "ext-<name>". */
36
+ token: string;
37
+ tables: Record<string, RecordTable>;
38
+ tools: string[];
39
+ /** The token's write patterns (qualified table names). */
40
+ write: string[];
41
+ /** The batch that brought the database from `previous` to this record (null: nothing was written). */
42
+ migration_id: string | null;
43
+ installed_at: string;
44
+ updated_at: string;
45
+ /** The record before the last install, repair or update (null after a first install). */
46
+ previous: InstalledExtension | null;
47
+ }
48
+ export interface ExtensionList {
49
+ database_id: string | null;
50
+ extensions: InstalledExtension[];
51
+ }
52
+ /** The rule of extension names (the same as EXTENSION_NAME in extension-manifest.ts). */
53
+ export declare const RECORD_NAME: RegExp;
54
+ /**
55
+ * The rule of a record's commit: a git commit id (40 hex) or a folder's content id ("local-" and lowercase letters,
56
+ * digits, "." or "-"). The registry checks only shape; the extension host and the commands check this before they
57
+ * build a path from a record.
58
+ */
59
+ export declare const RECORD_COMMIT: RegExp;
60
+ /** The rule of a database id: a UUID, as src/api/local.ts reads it. It names a folder of the token files. */
61
+ export declare const DATABASE_ID: RegExp;
62
+ /** The largest record the registry keeps (JSON characters). */
63
+ export declare const MAX_RECORD_CHARS = 1000000;
64
+ /** The problems of a record (empty: valid), each a short sentence naming the field. Unknown keys are kept. */
65
+ export declare function recordProblems(v: unknown, prefix?: string): string[];
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The record of an installed extension: what `datanotes extension install` writes to the engine's
3
+ * registry (`POST /datanotes/extensions/record/`) and every MCP host reads back
4
+ * (`POST /datanotes/extensions/`). Shape only: this file imports nothing.
5
+ */
6
+ export interface RecordTable {
7
+ /** The qualified table bound to the role. */
8
+ table: string;
9
+ /** True for a role the extension owns. */
10
+ owned: boolean;
11
+ /** Dependency roles: manifest column → the user's column, only where they differ. */
12
+ columns?: Record<string, string>;
13
+ /** Dependency roles: optional manifest columns the bound table does not have. */
14
+ absent?: string[];
15
+ }
16
+ export interface ExtensionSourceRecord {
17
+ kind: "git" | "local";
18
+ /** git: the URL as given (https://…, git@…, ssh://…, file://…). */
19
+ url?: string;
20
+ /** git: the tag or commit id given (or the newest tag chosen). */
21
+ ref?: string;
22
+ /** local: the absolute folder, with "/" separators. */
23
+ path?: string;
24
+ }
25
+ export interface InstalledExtension {
26
+ name: string;
27
+ version: string;
28
+ description: string;
29
+ api: number;
30
+ source: ExtensionSourceRecord;
31
+ /** The git commit id (40 hex), or "local-<12 hex>" for a folder. */
32
+ commit: string;
33
+ manifest_sha256: string;
34
+ entry_sha256: string;
35
+ /** The extension's named token: "ext-<name>". */
36
+ token: string;
37
+ tables: Record<string, RecordTable>;
38
+ tools: string[];
39
+ /** The token's write patterns (qualified table names). */
40
+ write: string[];
41
+ /** The batch that brought the database from `previous` to this record (null: nothing was written). */
42
+ migration_id: string | null;
43
+ installed_at: string;
44
+ updated_at: string;
45
+ /** The record before the last install, repair or update (null after a first install). */
46
+ previous: InstalledExtension | null;
47
+ }
48
+ export interface ExtensionList {
49
+ database_id: string | null;
50
+ extensions: InstalledExtension[];
51
+ }
52
+ /** The rule of extension names (the same as EXTENSION_NAME in extension-manifest.ts). */
53
+ export declare const RECORD_NAME: RegExp;
54
+ /**
55
+ * The rule of a record's commit: a git commit id (40 hex) or a folder's content id ("local-" and lowercase letters,
56
+ * digits, "." or "-"). The registry checks only shape; the extension host and the commands check this before they
57
+ * build a path from a record.
58
+ */
59
+ export declare const RECORD_COMMIT: RegExp;
60
+ /** The rule of a database id: a UUID, as src/api/local.ts reads it. It names a folder of the token files. */
61
+ export declare const DATABASE_ID: RegExp;
62
+ /** The largest record the registry keeps (JSON characters). */
63
+ export declare const MAX_RECORD_CHARS = 1000000;
64
+ /** The problems of a record (empty: valid), each a short sentence naming the field. Unknown keys are kept. */
65
+ export declare function recordProblems(v: unknown, prefix?: string): string[];