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.
- package/README.md +1 -0
- package/SECURITY.md +12 -0
- package/dist/api/client.d.cts +2 -0
- package/dist/api/client.d.ts +2 -0
- package/dist/api/docs.d.cts +14 -4
- package/dist/api/docs.d.ts +14 -4
- package/dist/api/extension-files.d.cts +23 -0
- package/dist/api/extension-files.d.ts +23 -0
- package/dist/api/extension-host.d.cts +108 -0
- package/dist/api/extension-host.d.ts +108 -0
- package/dist/api/extension-manifest.d.cts +154 -0
- package/dist/api/extension-manifest.d.ts +154 -0
- package/dist/api/extension-plan.d.cts +174 -0
- package/dist/api/extension-plan.d.ts +174 -0
- package/dist/api/extension-record.d.cts +65 -0
- package/dist/api/extension-record.d.ts +65 -0
- package/dist/api/extension-sdk.d.cts +65 -0
- package/dist/api/extension-sdk.d.ts +65 -0
- package/dist/api/extensions.cjs +18472 -0
- package/dist/api/extensions.d.cts +11 -0
- package/dist/api/extensions.d.ts +11 -0
- package/dist/api/extensions.js +18409 -0
- package/dist/api/index.cjs +675 -503
- package/dist/api/index.js +675 -503
- package/dist/api/mcp.cjs +203 -13
- package/dist/api/mcp.js +203 -13
- package/dist/datanotes.cjs +7903 -4667
- package/dist/docs/administration/extensions.md +213 -0
- package/dist/docs/api/operations/add_column.md +1 -0
- package/dist/docs/api/operations/add_constraint.md +2 -0
- package/dist/docs/api/operations/alter_column.md +1 -1
- package/dist/docs/api/operations/alter_table.md +3 -2
- package/dist/docs/api/operations/check_table.md +1 -1
- package/dist/docs/api/operations/create_table.md +3 -1
- package/dist/docs/api/operations/describe_table.md +1 -1
- package/dist/docs/api/operations/extensions_delete.md +29 -0
- package/dist/docs/api/operations/extensions_list.md +20 -0
- package/dist/docs/api/operations/extensions_record.md +44 -0
- package/dist/docs/api/operations/insert_row.md +2 -2
- package/dist/docs/api/operations/tags/extensions.md +9 -0
- package/dist/docs/api/operations/tags/rows-dml.md +1 -1
- package/dist/docs/api.md +10 -2
- package/dist/docs/develop/write-an-extension.md +369 -0
- package/dist/docs/guides/data-quality/check-constraints.md +14 -13
- package/dist/docs/guides/data-quality/hand-edits.md +10 -10
- package/dist/docs/guides/database-objects/bases.md +11 -11
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +16 -10
- package/dist/docs/guides/database-objects/columns.md +38 -38
- package/dist/docs/guides/database-objects/relations.md +173 -36
- package/dist/docs/guides/database-objects/tables.md +80 -35
- package/dist/docs/guides/database-objects/views.md +44 -44
- package/dist/docs/guides/history/change-data-feed.md +34 -34
- package/dist/docs/guides/history/journal-and-undo.md +12 -12
- package/dist/docs/guides/history/restore.md +20 -20
- package/dist/docs/guides/history/table-history.md +31 -31
- package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
- package/dist/docs/guides/read-and-write/import-notes.md +21 -21
- package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
- package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
- package/dist/docs/guides/read-and-write/write-rows.md +10 -10
- package/dist/docs/guides/search/text.md +1 -1
- package/dist/docs/guides/security/security-model.md +12 -0
- package/dist/docs/reference/cli.md +32 -1
- package/dist/docs/reference/errors.md +1 -1
- package/dist/docs/reference/glossary.md +8 -0
- package/dist/docs/reference/operations/auxiliary.md +2 -2
- package/dist/docs/reference/operations/rows.md +1 -1
- package/dist/docs/reference/operations/schema.md +15 -11
- package/dist/docs/reference/operations.md +28 -28
- package/dist/docs/release-notes.md +57 -0
- package/dist/docs/start/connect-agents.md +11 -0
- package/package.json +11 -1
package/dist/api/index.cjs
CHANGED
|
@@ -390,7 +390,7 @@ var OPERATIONS = [
|
|
|
390
390
|
},
|
|
391
391
|
{
|
|
392
392
|
"name": "describe_table",
|
|
393
|
-
"description": "Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualified`, `name`,\n`catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern\nof new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns`\nwith label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set:\n`tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name \u2192 where), `row_template`, `history`,\n`autolink_target`, `fields` (their values).\n\nBefore adding a column (e.g. a new metric), read `columns` and match your concept against\n`name`, `label`, `aliases` and `description`; reuse an existing column when it means the same.\n\n`missing_descriptions` (`{table, columns}`), present only when something has no description (a table\ndefined before descriptions were required), names what lacks one: write them with alter_table\n`description` and alter_column `changes.description`, asking the user when the meaning is unclear.",
|
|
393
|
+
"description": "Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualified`, `name`,\n`catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern\nof new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns`\nwith label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set:\n`tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name \u2192 where), `constraint_hints` (their own hints, name \u2192 hint), `instructions` (how to fill a row: follow them before you write one), `row_template`, `history`,\n`autolink_target`, `fields` (their values).\n\nBefore adding a column (e.g. a new metric), read `columns` and match your concept against\n`name`, `label`, `aliases` and `description`; reuse an existing column when it means the same.\n\n`missing_descriptions` (`{table, columns}`), present only when something has no description (a table\ndefined before descriptions were required), names what lacks one: write them with alter_table\n`description` and alter_column `changes.description`, asking the user when the meaning is unclear.",
|
|
394
394
|
"inputSchema": {
|
|
395
395
|
"additionalProperties": false,
|
|
396
396
|
"properties": {
|
|
@@ -513,6 +513,10 @@ var OPERATIONS = [
|
|
|
513
513
|
"inverse": {
|
|
514
514
|
"type": "string"
|
|
515
515
|
},
|
|
516
|
+
"acyclic": {
|
|
517
|
+
"type": "boolean",
|
|
518
|
+
"description": "Link column to its own table whose links never form a cycle (a write that closes one is refused)."
|
|
519
|
+
},
|
|
516
520
|
"ref_where": {
|
|
517
521
|
"type": "object",
|
|
518
522
|
"description": "Link column: the where filter every linked row must match.",
|
|
@@ -622,6 +626,17 @@ var OPERATIONS = [
|
|
|
622
626
|
},
|
|
623
627
|
"description": "Its CHECK constraints: name \u2192 the where every row must match."
|
|
624
628
|
},
|
|
629
|
+
"constraint_hints": {
|
|
630
|
+
"type": "object",
|
|
631
|
+
"additionalProperties": {
|
|
632
|
+
"type": "string"
|
|
633
|
+
},
|
|
634
|
+
"description": "The hint of each CHECK that has one: name \u2192 what to do when a row breaks it."
|
|
635
|
+
},
|
|
636
|
+
"instructions": {
|
|
637
|
+
"type": "string",
|
|
638
|
+
"description": "How to fill a row of the table (alter_table instructions): follow them before you write one."
|
|
639
|
+
},
|
|
625
640
|
"row_template": {
|
|
626
641
|
"type": "string",
|
|
627
642
|
"description": "The text of every new row's note."
|
|
@@ -655,7 +670,7 @@ var OPERATIONS = [
|
|
|
655
670
|
},
|
|
656
671
|
{
|
|
657
672
|
"name": "create_table",
|
|
658
|
-
"description": 'Create a table: `name`, in `catalog` and `schema` (default: the database\'s defaults); the definition\ngoes in metastore.yaml, the rows in `<root>/<catalog>/<schema>/<name>/`. Names: lowercase letters,\ndigits, `_` (no dots: pass the catalog and the schema as their own arguments).\n- `description` (required): what a row of the table records. Every column needs its own `description`\n too, what it holds: the table is refused otherwise, with every missing one listed. Descriptions are how\n agents and people understand the schema, so write them for a reader who never saw the notes. The\n engine writes those of `id` and of `identity` "uuid" / "created" columns.\n- `columns`: specs like `{"name": "kind", "type": "enum", "values": ["a","b"], "required": true,\n "description": "What kind of entry the row is"}`.\n Types: string, integer, number, boolean, date, datetime, enum, link, list (+ `items`), json.\n Attributes: required, default (`"{now}"`/`"{today}"`), min, max, step, values, `ordered` (enum in\n order: filters/avg use the position), ref (link target, full `catalog.schema.table` or "self"),\n unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`),\n `identity` ("filename" | "created"), `vocabulary` (allowed values = names of another table\'s rows),\n `hierarchy: true` (one parent link to its own table), `dense` (written on every row),\n `inverse` on a link column: the column of the `ref` table that links back (`friends` \u2194\n `friends`, `children` \u2194 `parents`, `partner` \u2194 `partner`); writes keep both sides in step.\n- `time_column`: rows named by that date/datetime; otherwise `filename` (e.g. `"{name}"`).\n- The table\'s options, as alter_table names them: `aliases` (how agents find it, with the\n description), `partition`, `exclude`, `archive`, `history` (keep its versions; default: the\n database\'s setting), `autolink_target` (true / false: may automatic links link its rows? default:\n yes, unless its rows are named by a date or a time, as with `time_column`).\n- `row_template`: markdown body of new rows. Shared columns come from bases: `set_table_bases`.\n- `tags`: key/value labels of the table, strings (`{"domain": "health"}`); list_tables and\n describe_table return them, alter_table changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
673
|
+
"description": 'Create a table: `name`, in `catalog` and `schema` (default: the database\'s defaults); the definition\ngoes in metastore.yaml, the rows in `<root>/<catalog>/<schema>/<name>/`. Names: lowercase letters,\ndigits, `_` (no dots: pass the catalog and the schema as their own arguments).\n- `description` (required): what a row of the table records. Every column needs its own `description`\n too, what it holds: the table is refused otherwise, with every missing one listed. Descriptions are how\n agents and people understand the schema, so write them for a reader who never saw the notes. The\n engine writes those of `id` and of `identity` "uuid" / "created" columns.\n- `columns`: specs like `{"name": "kind", "type": "enum", "values": ["a","b"], "required": true,\n "description": "What kind of entry the row is"}`.\n Types: string, integer, number, boolean, date, datetime, enum, link, list (+ `items`), json.\n Attributes: required, default (`"{now}"`/`"{today}"`), min, max, step, values, `ordered` (enum in\n order: filters/avg use the position), ref (link target, full `catalog.schema.table` or "self"),\n unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`),\n `identity` ("filename" | "created"), `vocabulary` (allowed values = names of another table\'s rows),\n `hierarchy: true` (one parent link to its own table), `acyclic: true` (links to rows of its own table that never loop back, such as tasks blocked by tasks; with `inverse`, the rule holds on both sides), `dense` (written on every row),\n `inverse` on a link column: the column of the `ref` table that links back (`friends` \u2194\n `friends`, `children` \u2194 `parents`, `partner` \u2194 `partner`); writes keep both sides in step.\n- `time_column`: rows named by that date/datetime; otherwise `filename` (e.g. `"{name}"`).\n- The table\'s options, as alter_table names them: `aliases` (how agents find it, with the\n description), `partition`, `exclude`, `archive`, `history` (keep its versions; default: the\n database\'s setting), `autolink_target` (true / false: may automatic links link its rows? default:\n yes, unless its rows are named by a date or a time, as with `time_column`).\n- `row_template`: markdown body of new rows. Shared columns come from bases: `set_table_bases`.\n- `instructions`: how to fill a row, for agents (Markdown); describe_table returns them.\n- `tags`: key/value labels of the table, strings (`{"domain": "health"}`); list_tables and\n describe_table return them, alter_table changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
659
674
|
"inputSchema": {
|
|
660
675
|
"additionalProperties": false,
|
|
661
676
|
"properties": {
|
|
@@ -816,6 +831,18 @@ var OPERATIONS = [
|
|
|
816
831
|
"default": null,
|
|
817
832
|
"description": "Markdown body of new rows; {column} placeholders are filled from the row."
|
|
818
833
|
},
|
|
834
|
+
"instructions": {
|
|
835
|
+
"anyOf": [
|
|
836
|
+
{
|
|
837
|
+
"type": "string"
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
"type": "null"
|
|
841
|
+
}
|
|
842
|
+
],
|
|
843
|
+
"default": null,
|
|
844
|
+
"description": "How to fill a row, for agents (Markdown): which columns first, what to ask the user. describe_table returns them."
|
|
845
|
+
},
|
|
819
846
|
"fields": {
|
|
820
847
|
"anyOf": [
|
|
821
848
|
{
|
|
@@ -953,6 +980,10 @@ var OPERATIONS = [
|
|
|
953
980
|
"type": "string",
|
|
954
981
|
"description": "The CHECK's name (code check)."
|
|
955
982
|
},
|
|
983
|
+
"hint": {
|
|
984
|
+
"type": "string",
|
|
985
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
986
|
+
},
|
|
956
987
|
"code": {
|
|
957
988
|
"type": "string",
|
|
958
989
|
"enum": [
|
|
@@ -1362,6 +1393,10 @@ var OPERATIONS = [
|
|
|
1362
1393
|
"type": "string",
|
|
1363
1394
|
"description": "The CHECK's name (code check)."
|
|
1364
1395
|
},
|
|
1396
|
+
"hint": {
|
|
1397
|
+
"type": "string",
|
|
1398
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
1399
|
+
},
|
|
1365
1400
|
"code": {
|
|
1366
1401
|
"type": "string",
|
|
1367
1402
|
"enum": [
|
|
@@ -1641,7 +1676,7 @@ var OPERATIONS = [
|
|
|
1641
1676
|
},
|
|
1642
1677
|
{
|
|
1643
1678
|
"name": "add_column",
|
|
1644
|
-
"description": 'Add a typed column. Sparse by default (written only on rows that have a value \u2014 use for\nmetrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label":\n"Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`).\n`description` is required: what the column holds, for the agents and people who read the schema\n(the engine writes it for `identity` "uuid" / "created" columns).\n`dense: true` in the spec adds it to every row with its `default`. Call `describe_table` first: never add\na column whose meaning an existing column (name/label/aliases/description) already covers.\nColumn names are permanent identifiers; only `rename_column` changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
1679
|
+
"description": 'Add a typed column. Sparse by default (written only on rows that have a value \u2014 use for\nmetrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label":\n"Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`).\n`description` is required: what the column holds, for the agents and people who read the schema\n(the engine writes it for `identity` "uuid" / "created" columns).\n`dense: true` in the spec adds it to every row with its `default`. Call `describe_table` first: never add\na column whose meaning an existing column (name/label/aliases/description) already covers.\nColumn names are permanent identifiers; only `rename_column` changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\nAcyclic links: `acyclic: true` on a link (or list of links) to the table itself refuses every write that closes a cycle, on either side of an `inverse`; refused while existing rows form one (they are listed).\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
1645
1680
|
"inputSchema": {
|
|
1646
1681
|
"additionalProperties": false,
|
|
1647
1682
|
"properties": {
|
|
@@ -1762,6 +1797,10 @@ var OPERATIONS = [
|
|
|
1762
1797
|
"type": "string",
|
|
1763
1798
|
"description": "The CHECK's name (code check)."
|
|
1764
1799
|
},
|
|
1800
|
+
"hint": {
|
|
1801
|
+
"type": "string",
|
|
1802
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
1803
|
+
},
|
|
1765
1804
|
"code": {
|
|
1766
1805
|
"type": "string",
|
|
1767
1806
|
"enum": [
|
|
@@ -2164,6 +2203,10 @@ var OPERATIONS = [
|
|
|
2164
2203
|
"type": "string",
|
|
2165
2204
|
"description": "The CHECK's name (code check)."
|
|
2166
2205
|
},
|
|
2206
|
+
"hint": {
|
|
2207
|
+
"type": "string",
|
|
2208
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
2209
|
+
},
|
|
2167
2210
|
"code": {
|
|
2168
2211
|
"type": "string",
|
|
2169
2212
|
"enum": [
|
|
@@ -2563,6 +2606,10 @@ var OPERATIONS = [
|
|
|
2563
2606
|
"type": "string",
|
|
2564
2607
|
"description": "The CHECK's name (code check)."
|
|
2565
2608
|
},
|
|
2609
|
+
"hint": {
|
|
2610
|
+
"type": "string",
|
|
2611
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
2612
|
+
},
|
|
2566
2613
|
"code": {
|
|
2567
2614
|
"type": "string",
|
|
2568
2615
|
"enum": [
|
|
@@ -2842,7 +2889,7 @@ var OPERATIONS = [
|
|
|
2842
2889
|
},
|
|
2843
2890
|
{
|
|
2844
2891
|
"name": "alter_column",
|
|
2845
|
-
"description": 'Change a column\'s attributes (type, min/max/step, values, required, default, label,\naliases, description, note, `ref_where`, `ref_by` (see list_link_targets); `null` removes an attribute, except\n`description`, which changes but never goes (null or "" is refused); `dense` true/false). Refused with\nthe list of violating rows when existing values do not satisfy the new definition. A\ndifferent scale means a different column: add a new one instead of rescaling. To rename one\nenum value use `rename_value`. Dropping an enum value that a `ref_by` (of any table) allows as a\ntarget level is refused, naming it.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
2892
|
+
"description": 'Change a column\'s attributes (type, min/max/step, values, required, default, label,\naliases, description, note, `ref_where`, `ref_by` (see list_link_targets), `acyclic` (refused while the rows already form a cycle: they are listed); `null` removes an attribute, except\n`description`, which changes but never goes (null or "" is refused); `dense` true/false). Refused with\nthe list of violating rows when existing values do not satisfy the new definition. A\ndifferent scale means a different column: add a new one instead of rescaling. To rename one\nenum value use `rename_value`. Dropping an enum value that a `ref_by` (of any table) allows as a\ntarget level is refused, naming it.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
2846
2893
|
"inputSchema": {
|
|
2847
2894
|
"additionalProperties": false,
|
|
2848
2895
|
"properties": {
|
|
@@ -2967,6 +3014,10 @@ var OPERATIONS = [
|
|
|
2967
3014
|
"type": "string",
|
|
2968
3015
|
"description": "The CHECK's name (code check)."
|
|
2969
3016
|
},
|
|
3017
|
+
"hint": {
|
|
3018
|
+
"type": "string",
|
|
3019
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
3020
|
+
},
|
|
2970
3021
|
"code": {
|
|
2971
3022
|
"type": "string",
|
|
2972
3023
|
"enum": [
|
|
@@ -3246,7 +3297,7 @@ var OPERATIONS = [
|
|
|
3246
3297
|
},
|
|
3247
3298
|
{
|
|
3248
3299
|
"name": "alter_table",
|
|
3249
|
-
"description": 'Alter a table: move it (`catalog`, `schema`), rename it (`name`), change\n`partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`,\n`exclude` folders, `row_template`\n("" removes it), `history` (true | false | "default"), `autolink_target`\n(true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by\na date or a time) or `tags` (key/value\nlabels merged into the table\'s, e.g. `{"domain": "health"}`; a `null` value removes that tag;\n`clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those),\n`archive` (folder name inside the table folder) or `fields` (untyped fields, name \u2192 default; a\n`null` value removes one). Rows, archive and transaction log follow; links are updated; renamed\nrows keep their old name in `aliases`. A change of metadata only (tags, description, aliases,\nhistory, autolink_target, row_template, fields) rewrites the table entry alone: no row is moved or rewritten. Refused\nwhen a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows\nlinks, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not\nrewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
3300
|
+
"description": 'Alter a table: move it (`catalog`, `schema`), rename it (`name`), change\n`partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`,\n`exclude` folders, `row_template`\n("" removes it), `instructions` (how to fill a row, for agents; "" removes them), `history` (true | false | "default"), `autolink_target`\n(true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by\na date or a time) or `tags` (key/value\nlabels merged into the table\'s, e.g. `{"domain": "health"}`; a `null` value removes that tag;\n`clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those),\n`archive` (folder name inside the table folder) or `fields` (untyped fields, name \u2192 default; a\n`null` value removes one). Rows, archive and transaction log follow; links are updated; renamed\nrows keep their old name in `aliases`. A change of metadata only (tags, description, aliases,\nhistory, autolink_target, row_template, instructions, fields) rewrites the table entry alone: no row is moved or rewritten. Refused\nwhen a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows\nlinks, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not\nrewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
3250
3301
|
"inputSchema": {
|
|
3251
3302
|
"additionalProperties": false,
|
|
3252
3303
|
"properties": {
|
|
@@ -3396,6 +3447,18 @@ var OPERATIONS = [
|
|
|
3396
3447
|
"default": null,
|
|
3397
3448
|
"description": 'Markdown body of new rows; "" removes it.'
|
|
3398
3449
|
},
|
|
3450
|
+
"instructions": {
|
|
3451
|
+
"anyOf": [
|
|
3452
|
+
{
|
|
3453
|
+
"type": "string"
|
|
3454
|
+
},
|
|
3455
|
+
{
|
|
3456
|
+
"type": "null"
|
|
3457
|
+
}
|
|
3458
|
+
],
|
|
3459
|
+
"default": null,
|
|
3460
|
+
"description": 'How to fill a row, for agents (Markdown); "" removes them.'
|
|
3461
|
+
},
|
|
3399
3462
|
"tags": {
|
|
3400
3463
|
"anyOf": [
|
|
3401
3464
|
{
|
|
@@ -3556,6 +3619,10 @@ var OPERATIONS = [
|
|
|
3556
3619
|
"type": "string",
|
|
3557
3620
|
"description": "The CHECK's name (code check)."
|
|
3558
3621
|
},
|
|
3622
|
+
"hint": {
|
|
3623
|
+
"type": "string",
|
|
3624
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
3625
|
+
},
|
|
3559
3626
|
"code": {
|
|
3560
3627
|
"type": "string",
|
|
3561
3628
|
"enum": [
|
|
@@ -4012,6 +4079,10 @@ var OPERATIONS = [
|
|
|
4012
4079
|
"type": "string",
|
|
4013
4080
|
"description": "The CHECK's name (code check)."
|
|
4014
4081
|
},
|
|
4082
|
+
"hint": {
|
|
4083
|
+
"type": "string",
|
|
4084
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
4085
|
+
},
|
|
4015
4086
|
"code": {
|
|
4016
4087
|
"type": "string",
|
|
4017
4088
|
"enum": [
|
|
@@ -4413,6 +4484,10 @@ var OPERATIONS = [
|
|
|
4413
4484
|
"type": "string",
|
|
4414
4485
|
"description": "The CHECK's name (code check)."
|
|
4415
4486
|
},
|
|
4487
|
+
"hint": {
|
|
4488
|
+
"type": "string",
|
|
4489
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
4490
|
+
},
|
|
4416
4491
|
"code": {
|
|
4417
4492
|
"type": "string",
|
|
4418
4493
|
"enum": [
|
|
@@ -5475,6 +5550,10 @@ var OPERATIONS = [
|
|
|
5475
5550
|
"type": "string",
|
|
5476
5551
|
"description": "The CHECK's name (code check)."
|
|
5477
5552
|
},
|
|
5553
|
+
"hint": {
|
|
5554
|
+
"type": "string",
|
|
5555
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
5556
|
+
},
|
|
5478
5557
|
"code": {
|
|
5479
5558
|
"type": "string",
|
|
5480
5559
|
"enum": [
|
|
@@ -5881,6 +5960,10 @@ var OPERATIONS = [
|
|
|
5881
5960
|
"type": "string",
|
|
5882
5961
|
"description": "The CHECK's name (code check)."
|
|
5883
5962
|
},
|
|
5963
|
+
"hint": {
|
|
5964
|
+
"type": "string",
|
|
5965
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
5966
|
+
},
|
|
5884
5967
|
"code": {
|
|
5885
5968
|
"type": "string",
|
|
5886
5969
|
"enum": [
|
|
@@ -6160,7 +6243,7 @@ var OPERATIONS = [
|
|
|
6160
6243
|
},
|
|
6161
6244
|
{
|
|
6162
6245
|
"name": "insert_row",
|
|
6163
|
-
"description": "Insert a row (new note). Values are validated against the columns; the note path comes from\nthe table's `path`/`filename` patterns (e.g. an event logged today about last night lands in\nlast night's day folder when you set `occurred_at` to last night). `body` is the note text.\nGenerated / identity columns are computed (do not pass them); CHECK constraints are enforced.\nReturns `migration_id` (undo) and the created path in `planned_creates`.\n`body` links the notes it mentions by name, at their first mention (automatic links; off with\n`autolink: false` or the database's `autolink` setting). `links_added` lists the links made;\n`ambiguous_mentions` lists the mentions left as text with the notes they may name: read those,\nthen link the right one with update_row and `autolink: false`, or leave the text.",
|
|
6246
|
+
"description": "Insert a row (new note). When describe_table gives the table's `instructions`, fill the row as they say. Values are validated against the columns; the note path comes from\nthe table's `path`/`filename` patterns (e.g. an event logged today about last night lands in\nlast night's day folder when you set `occurred_at` to last night). `body` is the note text.\nGenerated / identity columns are computed (do not pass them); CHECK constraints are enforced.\nReturns `migration_id` (undo) and the created path in `planned_creates`.\n`body` links the notes it mentions by name, at their first mention (automatic links; off with\n`autolink: false` or the database's `autolink` setting). `links_added` lists the links made;\n`ambiguous_mentions` lists the mentions left as text with the notes they may name: read those,\nthen link the right one with update_row and `autolink: false`, or leave the text.",
|
|
6164
6247
|
"inputSchema": {
|
|
6165
6248
|
"additionalProperties": false,
|
|
6166
6249
|
"properties": {
|
|
@@ -6315,6 +6398,10 @@ var OPERATIONS = [
|
|
|
6315
6398
|
"type": "string",
|
|
6316
6399
|
"description": "The CHECK's name (code check)."
|
|
6317
6400
|
},
|
|
6401
|
+
"hint": {
|
|
6402
|
+
"type": "string",
|
|
6403
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
6404
|
+
},
|
|
6318
6405
|
"code": {
|
|
6319
6406
|
"type": "string",
|
|
6320
6407
|
"enum": [
|
|
@@ -6753,6 +6840,10 @@ var OPERATIONS = [
|
|
|
6753
6840
|
"type": "string",
|
|
6754
6841
|
"description": "The CHECK's name (code check)."
|
|
6755
6842
|
},
|
|
6843
|
+
"hint": {
|
|
6844
|
+
"type": "string",
|
|
6845
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
6846
|
+
},
|
|
6756
6847
|
"code": {
|
|
6757
6848
|
"type": "string",
|
|
6758
6849
|
"enum": [
|
|
@@ -7266,6 +7357,10 @@ var OPERATIONS = [
|
|
|
7266
7357
|
"type": "string",
|
|
7267
7358
|
"description": "The CHECK's name (code check)."
|
|
7268
7359
|
},
|
|
7360
|
+
"hint": {
|
|
7361
|
+
"type": "string",
|
|
7362
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
7363
|
+
},
|
|
7269
7364
|
"code": {
|
|
7270
7365
|
"type": "string",
|
|
7271
7366
|
"enum": [
|
|
@@ -7697,6 +7792,10 @@ var OPERATIONS = [
|
|
|
7697
7792
|
"type": "string",
|
|
7698
7793
|
"description": "The CHECK's name (code check)."
|
|
7699
7794
|
},
|
|
7795
|
+
"hint": {
|
|
7796
|
+
"type": "string",
|
|
7797
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
7798
|
+
},
|
|
7700
7799
|
"code": {
|
|
7701
7800
|
"type": "string",
|
|
7702
7801
|
"enum": [
|
|
@@ -8145,6 +8244,10 @@ var OPERATIONS = [
|
|
|
8145
8244
|
"type": "string",
|
|
8146
8245
|
"description": "The CHECK's name (code check)."
|
|
8147
8246
|
},
|
|
8247
|
+
"hint": {
|
|
8248
|
+
"type": "string",
|
|
8249
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
8250
|
+
},
|
|
8148
8251
|
"code": {
|
|
8149
8252
|
"type": "string",
|
|
8150
8253
|
"enum": [
|
|
@@ -8605,6 +8708,10 @@ var OPERATIONS = [
|
|
|
8605
8708
|
"type": "string",
|
|
8606
8709
|
"description": "The CHECK's name (code check)."
|
|
8607
8710
|
},
|
|
8711
|
+
"hint": {
|
|
8712
|
+
"type": "string",
|
|
8713
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
8714
|
+
},
|
|
8608
8715
|
"code": {
|
|
8609
8716
|
"type": "string",
|
|
8610
8717
|
"enum": [
|
|
@@ -9113,7 +9220,7 @@ var OPERATIONS = [
|
|
|
9113
9220
|
},
|
|
9114
9221
|
{
|
|
9115
9222
|
"name": "check_table",
|
|
9116
|
-
"description": "Validate every row against the table (required, types, ranges, enums, links, unknown\ncolumns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK's name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)",
|
|
9223
|
+
"description": "Validate every row against the table (required, types, ranges, enums, links, unknown\ncolumns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, cycles of hierarchy and acyclic columns, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK's name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)",
|
|
9117
9224
|
"inputSchema": {
|
|
9118
9225
|
"additionalProperties": false,
|
|
9119
9226
|
"properties": {
|
|
@@ -9226,6 +9333,10 @@ var OPERATIONS = [
|
|
|
9226
9333
|
"type": "string",
|
|
9227
9334
|
"description": "The CHECK's name (code check)."
|
|
9228
9335
|
},
|
|
9336
|
+
"hint": {
|
|
9337
|
+
"type": "string",
|
|
9338
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
9339
|
+
},
|
|
9229
9340
|
"code": {
|
|
9230
9341
|
"type": "string",
|
|
9231
9342
|
"enum": [
|
|
@@ -9679,6 +9790,10 @@ var OPERATIONS = [
|
|
|
9679
9790
|
"type": "string",
|
|
9680
9791
|
"description": "The CHECK's name (code check)."
|
|
9681
9792
|
},
|
|
9793
|
+
"hint": {
|
|
9794
|
+
"type": "string",
|
|
9795
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
9796
|
+
},
|
|
9682
9797
|
"code": {
|
|
9683
9798
|
"type": "string",
|
|
9684
9799
|
"enum": [
|
|
@@ -10122,6 +10237,10 @@ var OPERATIONS = [
|
|
|
10122
10237
|
"type": "string",
|
|
10123
10238
|
"description": "The CHECK's name (code check)."
|
|
10124
10239
|
},
|
|
10240
|
+
"hint": {
|
|
10241
|
+
"type": "string",
|
|
10242
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
10243
|
+
},
|
|
10125
10244
|
"code": {
|
|
10126
10245
|
"type": "string",
|
|
10127
10246
|
"enum": [
|
|
@@ -11205,6 +11324,10 @@ var OPERATIONS = [
|
|
|
11205
11324
|
"type": "string",
|
|
11206
11325
|
"description": "The CHECK's name (code check)."
|
|
11207
11326
|
},
|
|
11327
|
+
"hint": {
|
|
11328
|
+
"type": "string",
|
|
11329
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
11330
|
+
},
|
|
11208
11331
|
"code": {
|
|
11209
11332
|
"type": "string",
|
|
11210
11333
|
"enum": [
|
|
@@ -12642,6 +12765,10 @@ var OPERATIONS = [
|
|
|
12642
12765
|
"type": "string",
|
|
12643
12766
|
"description": "The CHECK's name (code check)."
|
|
12644
12767
|
},
|
|
12768
|
+
"hint": {
|
|
12769
|
+
"type": "string",
|
|
12770
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
12771
|
+
},
|
|
12645
12772
|
"code": {
|
|
12646
12773
|
"type": "string",
|
|
12647
12774
|
"enum": [
|
|
@@ -13052,6 +13179,10 @@ var OPERATIONS = [
|
|
|
13052
13179
|
"type": "string",
|
|
13053
13180
|
"description": "The CHECK's name (code check)."
|
|
13054
13181
|
},
|
|
13182
|
+
"hint": {
|
|
13183
|
+
"type": "string",
|
|
13184
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
13185
|
+
},
|
|
13055
13186
|
"code": {
|
|
13056
13187
|
"type": "string",
|
|
13057
13188
|
"enum": [
|
|
@@ -13518,7 +13649,7 @@ var OPERATIONS = [
|
|
|
13518
13649
|
},
|
|
13519
13650
|
{
|
|
13520
13651
|
"name": "add_constraint",
|
|
13521
|
-
"description": 'ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match,\ne.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL;\ninside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails).\nA key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}`\n(further dots follow further links). An empty link passes at the top level and fails inside `or` / `and` /\n`not`; only the first link of a longer path is skipped when empty (`parent.parent.kind` fails for a row\nwhose parent has no parent). A link to a row that does not exist fails; on a list of links every linked\nrow must match. `not` turns that into a pass: `{"not": {"parent.kind": "area"}}` passes a link to a\nmissing row, so add `"parent.kind": {"exists": true}` to require a real one. Links resolve as in the\nvault (by path, from the row\'s note: same-named rows in two folders stay apart); renaming or moving a\nlinked row keeps them (they follow it).\nRefused while existing rows violate it (they are listed); then enforced on every write, by the same rule.\nA write that changes a linked row re-checks the rows that link to it and is refused, listing them, when\nit breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault\nthe earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too.\nrename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
13652
|
+
"description": 'ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match,\ne.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL;\ninside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails).\nA key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}`\n(further dots follow further links). An empty link passes at the top level and fails inside `or` / `and` /\n`not`; only the first link of a longer path is skipped when empty (`parent.parent.kind` fails for a row\nwhose parent has no parent). A link to a row that does not exist fails; on a list of links every linked\nrow must match. `not` turns that into a pass: `{"not": {"parent.kind": "area"}}` passes a link to a\nmissing row, so add `"parent.kind": {"exists": true}` to require a real one. Links resolve as in the\nvault (by path, from the row\'s note: same-named rows in two folders stay apart); renaming or moving a\nlinked row keeps them (they follow it).\nRefused while existing rows violate it (they are listed); then enforced on every write, by the same rule.\nA write that changes a linked row re-checks the rows that link to it and is refused, listing them, when\nit breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault\nthe earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too.\nrename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused.\n`hint`: what to do when a row breaks the rule, in your words; a refused write puts it first in its hint, and each violation of the CHECK carries it.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
13522
13653
|
"inputSchema": {
|
|
13523
13654
|
"additionalProperties": false,
|
|
13524
13655
|
"properties": {
|
|
@@ -13532,6 +13663,18 @@ var OPERATIONS = [
|
|
|
13532
13663
|
"additionalProperties": true,
|
|
13533
13664
|
"type": "object"
|
|
13534
13665
|
},
|
|
13666
|
+
"hint": {
|
|
13667
|
+
"anyOf": [
|
|
13668
|
+
{
|
|
13669
|
+
"type": "string"
|
|
13670
|
+
},
|
|
13671
|
+
{
|
|
13672
|
+
"type": "null"
|
|
13673
|
+
}
|
|
13674
|
+
],
|
|
13675
|
+
"default": null,
|
|
13676
|
+
"description": "What a refused write tells the agent when a row breaks this CHECK: how to fix the row. It comes first in the refusal's hint; describe_table lists it in constraint_hints."
|
|
13677
|
+
},
|
|
13535
13678
|
"dry_run": {
|
|
13536
13679
|
"default": false,
|
|
13537
13680
|
"type": "boolean"
|
|
@@ -13642,6 +13785,10 @@ var OPERATIONS = [
|
|
|
13642
13785
|
"type": "string",
|
|
13643
13786
|
"description": "The CHECK's name (code check)."
|
|
13644
13787
|
},
|
|
13788
|
+
"hint": {
|
|
13789
|
+
"type": "string",
|
|
13790
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
13791
|
+
},
|
|
13645
13792
|
"code": {
|
|
13646
13793
|
"type": "string",
|
|
13647
13794
|
"enum": [
|
|
@@ -14040,6 +14187,10 @@ var OPERATIONS = [
|
|
|
14040
14187
|
"type": "string",
|
|
14041
14188
|
"description": "The CHECK's name (code check)."
|
|
14042
14189
|
},
|
|
14190
|
+
"hint": {
|
|
14191
|
+
"type": "string",
|
|
14192
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
14193
|
+
},
|
|
14043
14194
|
"code": {
|
|
14044
14195
|
"type": "string",
|
|
14045
14196
|
"enum": [
|
|
@@ -14505,6 +14656,10 @@ var OPERATIONS = [
|
|
|
14505
14656
|
"type": "string",
|
|
14506
14657
|
"description": "The CHECK's name (code check)."
|
|
14507
14658
|
},
|
|
14659
|
+
"hint": {
|
|
14660
|
+
"type": "string",
|
|
14661
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
14662
|
+
},
|
|
14508
14663
|
"code": {
|
|
14509
14664
|
"type": "string",
|
|
14510
14665
|
"enum": [
|
|
@@ -14899,6 +15054,10 @@ var OPERATIONS = [
|
|
|
14899
15054
|
"type": "string",
|
|
14900
15055
|
"description": "The CHECK's name (code check)."
|
|
14901
15056
|
},
|
|
15057
|
+
"hint": {
|
|
15058
|
+
"type": "string",
|
|
15059
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
15060
|
+
},
|
|
14902
15061
|
"code": {
|
|
14903
15062
|
"type": "string",
|
|
14904
15063
|
"enum": [
|
|
@@ -15324,6 +15483,10 @@ var OPERATIONS = [
|
|
|
15324
15483
|
"type": "string",
|
|
15325
15484
|
"description": "The CHECK's name (code check)."
|
|
15326
15485
|
},
|
|
15486
|
+
"hint": {
|
|
15487
|
+
"type": "string",
|
|
15488
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
15489
|
+
},
|
|
15327
15490
|
"code": {
|
|
15328
15491
|
"type": "string",
|
|
15329
15492
|
"enum": [
|
|
@@ -15736,6 +15899,10 @@ var OPERATIONS = [
|
|
|
15736
15899
|
"type": "string",
|
|
15737
15900
|
"description": "The CHECK's name (code check)."
|
|
15738
15901
|
},
|
|
15902
|
+
"hint": {
|
|
15903
|
+
"type": "string",
|
|
15904
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
15905
|
+
},
|
|
15739
15906
|
"code": {
|
|
15740
15907
|
"type": "string",
|
|
15741
15908
|
"enum": [
|
|
@@ -16760,425 +16927,99 @@ function classOf(cp) {
|
|
|
16760
16927
|
return k;
|
|
16761
16928
|
}
|
|
16762
16929
|
|
|
16763
|
-
// src/api/
|
|
16764
|
-
var
|
|
16765
|
-
var
|
|
16766
|
-
var
|
|
16767
|
-
function
|
|
16768
|
-
|
|
16769
|
-
if (
|
|
16770
|
-
|
|
16771
|
-
|
|
16930
|
+
// src/api/tracing.ts
|
|
16931
|
+
var TRACEPARENT_HEADER = "traceparent";
|
|
16932
|
+
var TRACESTATE_HEADER = "tracestate";
|
|
16933
|
+
var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
|
|
16934
|
+
function parseTraceparent(traceparent, tracestate) {
|
|
16935
|
+
const m = TRACEPARENT.exec((typeof traceparent === "string" ? traceparent : "").trim().toLowerCase());
|
|
16936
|
+
if (!m) return null;
|
|
16937
|
+
const [, version, traceId, spanId, flags, rest] = m;
|
|
16938
|
+
if (version === "ff" || version === "00" && rest !== void 0) return null;
|
|
16939
|
+
if (/^0+$/.test(traceId) || /^0+$/.test(spanId)) return null;
|
|
16940
|
+
const state = (typeof tracestate === "string" ? tracestate : "").trim();
|
|
16941
|
+
return { traceId, spanId, sampled: (parseInt(flags, 16) & 1) === 1, ...state ? { traceState: state.slice(0, 512) } : {} };
|
|
16772
16942
|
}
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
const res = await fetch(url, { method: "POST", headers, body });
|
|
16776
|
-
if (!res.ok) throw new Error(`OTLP HTTP ${res.status}`);
|
|
16777
|
-
};
|
|
16778
|
-
function unixNano(ms) {
|
|
16779
|
-
const whole = Math.floor(ms);
|
|
16780
|
-
const frac = Math.round((ms - whole) * 1e6);
|
|
16781
|
-
return (BigInt(whole) * BigInt(1e6) + BigInt(frac)).toString();
|
|
16943
|
+
function formatTraceparent(ctx) {
|
|
16944
|
+
return `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
|
|
16782
16945
|
}
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
|
|
16789
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
16792
|
-
|
|
16793
|
-
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
|
|
16804
|
-
|
|
16805
|
-
this.
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
this.
|
|
16946
|
+
function traceHeaders(ctx) {
|
|
16947
|
+
return { [TRACEPARENT_HEADER]: formatTraceparent(ctx), ...ctx.traceState ? { [TRACESTATE_HEADER]: ctx.traceState } : {} };
|
|
16948
|
+
}
|
|
16949
|
+
function randomHex(bytes) {
|
|
16950
|
+
const b = new Uint8Array(bytes);
|
|
16951
|
+
const c = globalThis.crypto;
|
|
16952
|
+
if (c?.getRandomValues) c.getRandomValues(b);
|
|
16953
|
+
else for (let i = 0; i < bytes; i++) b[i] = Math.floor(Math.random() * 256);
|
|
16954
|
+
const hex = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
16955
|
+
return /^0+$/.test(hex) ? randomHex(bytes) : hex;
|
|
16956
|
+
}
|
|
16957
|
+
var newTraceId = () => randomHex(16);
|
|
16958
|
+
var newSpanId = () => randomHex(8);
|
|
16959
|
+
var perf = globalThis.performance;
|
|
16960
|
+
var defaultNow = perf ? () => perf.timeOrigin + perf.now() : () => Date.now();
|
|
16961
|
+
var TraceSpan = class {
|
|
16962
|
+
constructor(tracer, name, kind, parent, recording, attributes) {
|
|
16963
|
+
this.tracer = tracer;
|
|
16964
|
+
this.name = name;
|
|
16965
|
+
this.kind = kind;
|
|
16966
|
+
this.parent = parent;
|
|
16967
|
+
this.recording = recording;
|
|
16968
|
+
this.attributes = {};
|
|
16969
|
+
this.events = [];
|
|
16970
|
+
this.status = { code: "unset" };
|
|
16971
|
+
this.ended = false;
|
|
16972
|
+
this.context = {
|
|
16973
|
+
traceId: parent?.traceId ?? newTraceId(),
|
|
16974
|
+
spanId: newSpanId(),
|
|
16975
|
+
sampled: recording,
|
|
16976
|
+
...parent?.traceState ? { traceState: parent.traceState } : {}
|
|
16977
|
+
};
|
|
16978
|
+
this.startMs = tracer.now();
|
|
16979
|
+
this.setAttributes(attributes);
|
|
16809
16980
|
}
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
this.varint(v);
|
|
16981
|
+
setAttribute(key, value) {
|
|
16982
|
+
if (value !== void 0 && value !== null) this.attributes[key] = value;
|
|
16813
16983
|
return this;
|
|
16814
16984
|
}
|
|
16815
|
-
|
|
16816
|
-
this.
|
|
16817
|
-
for (let i = 0; i < 4; i++) this.parts.push(v >>> 8 * i & 255);
|
|
16985
|
+
setAttributes(attributes) {
|
|
16986
|
+
for (const k in attributes) this.setAttribute(k, attributes[k]);
|
|
16818
16987
|
return this;
|
|
16819
16988
|
}
|
|
16820
|
-
|
|
16821
|
-
this.
|
|
16822
|
-
for (let i = 0; i < 8; i++) this.parts.push(Number(v >> BigInt(8 * i) & BigInt(255)));
|
|
16989
|
+
addEvent(name, attributes = {}) {
|
|
16990
|
+
this.events.push({ name, timeMs: this.tracer.now(), attributes });
|
|
16823
16991
|
return this;
|
|
16824
16992
|
}
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
const
|
|
16828
|
-
|
|
16829
|
-
|
|
16830
|
-
|
|
16993
|
+
/** An `exception` event, `error.type` and status ERROR. */
|
|
16994
|
+
recordException(e) {
|
|
16995
|
+
const type = e instanceof Error ? e.name : typeof e;
|
|
16996
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
16997
|
+
this.addEvent("exception", { "exception.type": type, "exception.message": message, ...e instanceof Error && e.stack ? { "exception.stacktrace": e.stack.slice(0, 8192) } : {} });
|
|
16998
|
+
if (!("error.type" in this.attributes)) this.attributes["error.type"] = type;
|
|
16999
|
+
return this.setStatus("error", message);
|
|
16831
17000
|
}
|
|
16832
|
-
|
|
16833
|
-
this.
|
|
16834
|
-
this.
|
|
16835
|
-
for (const x of data) this.parts.push(x);
|
|
17001
|
+
setStatus(code, message) {
|
|
17002
|
+
if (this.status.code === "error" && code !== "error") return this;
|
|
17003
|
+
this.status = code === "error" && message ? { code, message } : { code };
|
|
16836
17004
|
return this;
|
|
16837
17005
|
}
|
|
16838
|
-
|
|
16839
|
-
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
-
|
|
16843
|
-
|
|
16844
|
-
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16851
|
-
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
if (typeof v === "string") return new Pb().string(1, v);
|
|
16856
|
-
if (typeof v === "boolean") return new Pb().uint(2, v ? 1 : 0);
|
|
16857
|
-
return Number.isInteger(v) ? new Pb().uint(3, BigInt(v)) : new Pb().double(4, v);
|
|
16858
|
-
}
|
|
16859
|
-
function pbAttrs(m, field, a) {
|
|
16860
|
-
for (const [k, v] of Object.entries(a)) {
|
|
16861
|
-
if (v === void 0 || v === null) continue;
|
|
16862
|
-
m.message(field, new Pb().string(1, k).message(2, pbValue(v)));
|
|
16863
|
-
}
|
|
16864
|
-
return m;
|
|
16865
|
-
}
|
|
16866
|
-
var OtlpBatcher = class {
|
|
16867
|
-
constructor(o, path, maxBatch) {
|
|
16868
|
-
this.o = o;
|
|
16869
|
-
this.path = path;
|
|
16870
|
-
this.maxBatch = maxBatch;
|
|
16871
|
-
this.buffer = [];
|
|
16872
|
-
this.inflight = Promise.resolve();
|
|
16873
|
-
this.timer = null;
|
|
16874
|
-
/** Items sent, and items lost because the collector did not take them (or the buffer was full). */
|
|
16875
|
-
this.sent = 0;
|
|
16876
|
-
this.dropped = 0;
|
|
16877
|
-
const every = o.flushMs ?? 5e3;
|
|
16878
|
-
if (every > 0) {
|
|
16879
|
-
this.timer = setInterval(() => void this.flush(), every);
|
|
16880
|
-
this.timer.unref?.();
|
|
16881
|
-
}
|
|
16882
|
-
}
|
|
16883
|
-
push(items) {
|
|
16884
|
-
const room = this.maxBatch * 8 - this.buffer.length;
|
|
16885
|
-
if (room < items.length) this.dropped += items.length - Math.max(room, 0);
|
|
16886
|
-
for (let i = 0; i < Math.min(items.length, Math.max(room, 0)); i++) this.buffer.push(items[i]);
|
|
16887
|
-
if (this.buffer.length >= this.maxBatch) void this.flush();
|
|
16888
|
-
}
|
|
16889
|
-
resource() {
|
|
16890
|
-
return { "service.name": this.o.serviceName, "service.version": this.o.serviceVersion, ...this.o.resource };
|
|
16891
|
-
}
|
|
16892
|
-
/** Send what is buffered. Never rejects. */
|
|
16893
|
-
flush() {
|
|
16894
|
-
if (this.buffer.length === 0) return this.inflight;
|
|
16895
|
-
const send = this.o.send ?? fetchSend;
|
|
16896
|
-
const url = `${this.o.endpoint.replace(/\/+$/, "")}${this.path}`;
|
|
16897
|
-
const protobuf = (this.o.protocol ?? "http/protobuf") === "http/protobuf";
|
|
16898
|
-
const headers = { "Content-Type": protobuf ? "application/x-protobuf" : "application/json", ...this.o.headers ?? {} };
|
|
16899
|
-
while (this.buffer.length > 0) {
|
|
16900
|
-
const batch = this.buffer.splice(0, this.maxBatch);
|
|
16901
|
-
let body;
|
|
16902
|
-
try {
|
|
16903
|
-
body = this.encode(batch, protobuf);
|
|
16904
|
-
} catch {
|
|
16905
|
-
this.dropped += batch.length;
|
|
16906
|
-
continue;
|
|
16907
|
-
}
|
|
16908
|
-
this.inflight = this.inflight.then(
|
|
16909
|
-
() => send(url, body, headers).then(
|
|
16910
|
-
() => void (this.sent += batch.length),
|
|
16911
|
-
() => void (this.dropped += batch.length)
|
|
16912
|
-
)
|
|
16913
|
-
);
|
|
16914
|
-
}
|
|
16915
|
-
return this.inflight;
|
|
16916
|
-
}
|
|
16917
|
-
/** Stop the timer and send what is left. */
|
|
16918
|
-
async close() {
|
|
16919
|
-
if (this.timer) clearInterval(this.timer);
|
|
16920
|
-
this.timer = null;
|
|
16921
|
-
await this.flush();
|
|
16922
|
-
}
|
|
16923
|
-
};
|
|
16924
|
-
var OtlpLogExporter = class extends OtlpBatcher {
|
|
16925
|
-
constructor(o) {
|
|
16926
|
-
super(o, "/v1/logs", o.maxBatch ?? 50);
|
|
16927
|
-
}
|
|
16928
|
-
/** Buffer a record; `context`: the span it was made in (its trace and span id go with it). */
|
|
16929
|
-
log(severity, body, attributes = {}, context) {
|
|
16930
|
-
const ms = (this.o.now ?? Date.now)();
|
|
16931
|
-
this.push([{ timeUnixNano: `${Math.round(ms)}000000`, severity, body, attributes, ...context ? { context } : {} }]);
|
|
16932
|
-
}
|
|
16933
|
-
encode(batch, protobuf) {
|
|
16934
|
-
const resource = this.resource();
|
|
16935
|
-
if (protobuf) return this.protobuf(resource, batch);
|
|
16936
|
-
return JSON.stringify({
|
|
16937
|
-
resourceLogs: [
|
|
16938
|
-
{
|
|
16939
|
-
resource: { attributes: attrs(resource) },
|
|
16940
|
-
scopeLogs: [
|
|
16941
|
-
{
|
|
16942
|
-
scope: { name: this.o.serviceName },
|
|
16943
|
-
logRecords: batch.map((r) => ({
|
|
16944
|
-
timeUnixNano: r.timeUnixNano,
|
|
16945
|
-
observedTimeUnixNano: r.timeUnixNano,
|
|
16946
|
-
severityNumber: SEVERITY_NUMBER[r.severity],
|
|
16947
|
-
severityText: r.severity,
|
|
16948
|
-
body: { stringValue: r.body },
|
|
16949
|
-
attributes: attrs(r.attributes),
|
|
16950
|
-
...r.context ? { traceId: r.context.traceId, spanId: r.context.spanId, flags: r.context.sampled ? 1 : 0 } : {}
|
|
16951
|
-
}))
|
|
16952
|
-
}
|
|
16953
|
-
]
|
|
16954
|
-
}
|
|
16955
|
-
]
|
|
16956
|
-
});
|
|
16957
|
-
}
|
|
16958
|
-
protobuf(resource, batch) {
|
|
16959
|
-
const scope = new Pb().message(1, new Pb().string(1, this.o.serviceName));
|
|
16960
|
-
for (const r of batch) {
|
|
16961
|
-
const t = BigInt(r.timeUnixNano);
|
|
16962
|
-
const rec = new Pb().fixed64(1, t).uint(2, SEVERITY_NUMBER[r.severity]).string(3, r.severity).message(5, new Pb().string(1, r.body));
|
|
16963
|
-
pbAttrs(rec, 6, r.attributes);
|
|
16964
|
-
if (r.context) rec.fixed32(8, r.context.sampled ? 1 : 0).hex(9, r.context.traceId).hex(10, r.context.spanId);
|
|
16965
|
-
rec.fixed64(11, t);
|
|
16966
|
-
scope.message(2, rec);
|
|
16967
|
-
}
|
|
16968
|
-
const resourceLogs = new Pb().message(1, pbAttrs(new Pb(), 1, resource)).message(2, scope);
|
|
16969
|
-
return new Pb().message(1, resourceLogs).finish();
|
|
16970
|
-
}
|
|
16971
|
-
};
|
|
16972
|
-
var OtlpTraceExporter = class extends OtlpBatcher {
|
|
16973
|
-
constructor(o) {
|
|
16974
|
-
super(o, "/v1/traces", o.maxBatch ?? 512);
|
|
16975
|
-
}
|
|
16976
|
-
/** Buffer finished spans (sent with the next batch). Never throws. */
|
|
16977
|
-
export(spans) {
|
|
16978
|
-
this.push(Array.isArray(spans) ? spans : [spans]);
|
|
16979
|
-
}
|
|
16980
|
-
encode(batch, protobuf) {
|
|
16981
|
-
const resource = this.resource();
|
|
16982
|
-
if (protobuf) return this.protobuf(resource, batch);
|
|
16983
|
-
return JSON.stringify({
|
|
16984
|
-
resourceSpans: [
|
|
16985
|
-
{
|
|
16986
|
-
resource: { attributes: attrs(resource) },
|
|
16987
|
-
scopeSpans: [
|
|
16988
|
-
{
|
|
16989
|
-
scope: { name: this.o.serviceName, ...this.o.serviceVersion ? { version: this.o.serviceVersion } : {} },
|
|
16990
|
-
spans: batch.map((s) => ({
|
|
16991
|
-
traceId: s.traceId,
|
|
16992
|
-
spanId: s.spanId,
|
|
16993
|
-
...s.parentSpanId ? { parentSpanId: s.parentSpanId } : {},
|
|
16994
|
-
...s.traceState ? { traceState: s.traceState } : {},
|
|
16995
|
-
flags: 1,
|
|
16996
|
-
name: s.name,
|
|
16997
|
-
kind: SPAN_KIND[s.kind],
|
|
16998
|
-
startTimeUnixNano: unixNano(s.startMs),
|
|
16999
|
-
endTimeUnixNano: unixNano(s.endMs),
|
|
17000
|
-
attributes: attrs(s.attributes),
|
|
17001
|
-
...s.droppedAttributes ? { droppedAttributesCount: s.droppedAttributes } : {},
|
|
17002
|
-
events: s.events.map((e) => ({ timeUnixNano: unixNano(e.timeMs), name: e.name, attributes: attrs(e.attributes) })),
|
|
17003
|
-
...s.droppedEvents ? { droppedEventsCount: s.droppedEvents } : {},
|
|
17004
|
-
status: { code: STATUS_CODE[s.status.code], ...s.status.message ? { message: s.status.message } : {} }
|
|
17005
|
-
}))
|
|
17006
|
-
}
|
|
17007
|
-
]
|
|
17008
|
-
}
|
|
17009
|
-
]
|
|
17010
|
-
});
|
|
17011
|
-
}
|
|
17012
|
-
protobuf(resource, batch) {
|
|
17013
|
-
const scopeInfo = new Pb().string(1, this.o.serviceName);
|
|
17014
|
-
if (this.o.serviceVersion) scopeInfo.string(2, this.o.serviceVersion);
|
|
17015
|
-
const scope = new Pb().message(1, scopeInfo);
|
|
17016
|
-
for (const s of batch) {
|
|
17017
|
-
const span = new Pb().hex(1, s.traceId).hex(2, s.spanId);
|
|
17018
|
-
if (s.traceState) span.string(3, s.traceState);
|
|
17019
|
-
if (s.parentSpanId) span.hex(4, s.parentSpanId);
|
|
17020
|
-
span.string(5, s.name).uint(6, SPAN_KIND[s.kind]).fixed64(7, BigInt(unixNano(s.startMs))).fixed64(8, BigInt(unixNano(s.endMs)));
|
|
17021
|
-
pbAttrs(span, 9, s.attributes);
|
|
17022
|
-
if (s.droppedAttributes) span.uint(10, s.droppedAttributes);
|
|
17023
|
-
for (const e of s.events) span.message(11, pbAttrs(new Pb().fixed64(1, BigInt(unixNano(e.timeMs))).string(2, e.name), 3, e.attributes));
|
|
17024
|
-
if (s.droppedEvents) span.uint(12, s.droppedEvents);
|
|
17025
|
-
const status = new Pb();
|
|
17026
|
-
if (s.status.message) status.string(2, s.status.message);
|
|
17027
|
-
if (s.status.code !== "unset") status.uint(3, STATUS_CODE[s.status.code]);
|
|
17028
|
-
span.message(15, status).fixed32(16, 1);
|
|
17029
|
-
scope.message(2, span);
|
|
17030
|
-
}
|
|
17031
|
-
const resourceSpans = new Pb().message(1, pbAttrs(new Pb(), 1, resource)).message(2, scope);
|
|
17032
|
-
return new Pb().message(1, resourceSpans).finish();
|
|
17033
|
-
}
|
|
17034
|
-
};
|
|
17035
|
-
function parseOtlpHeaders(text) {
|
|
17036
|
-
const out = {};
|
|
17037
|
-
for (const part of (text ?? "").split(",")) {
|
|
17038
|
-
const i = part.indexOf("=");
|
|
17039
|
-
if (i <= 0) continue;
|
|
17040
|
-
const key = part.slice(0, i).trim();
|
|
17041
|
-
const value = part.slice(i + 1).trim();
|
|
17042
|
-
if (!key) continue;
|
|
17043
|
-
try {
|
|
17044
|
-
out[key] = decodeURIComponent(value);
|
|
17045
|
-
} catch {
|
|
17046
|
-
out[key] = value;
|
|
17047
|
-
}
|
|
17048
|
-
}
|
|
17049
|
-
return out;
|
|
17050
|
-
}
|
|
17051
|
-
var parseResourceAttributes = parseOtlpHeaders;
|
|
17052
|
-
var truthy = (v) => (v ?? "").trim().toLowerCase() === "true";
|
|
17053
|
-
function otlpFromEnv(env, defaults) {
|
|
17054
|
-
return fromEnv(env, defaults, "LOGS", "logs");
|
|
17055
|
-
}
|
|
17056
|
-
function otlpTracesFromEnv(env, defaults) {
|
|
17057
|
-
return fromEnv(env, defaults, "TRACES", "traces");
|
|
17058
|
-
}
|
|
17059
|
-
function fromEnv(env, defaults, signal, path) {
|
|
17060
|
-
if (truthy(env.OTEL_SDK_DISABLED) || (env[`OTEL_${signal}_EXPORTER`] ?? "").trim().toLowerCase() === "none") return null;
|
|
17061
|
-
const own = env[`OTEL_EXPORTER_OTLP_${signal}_ENDPOINT`]?.trim();
|
|
17062
|
-
const base = env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim();
|
|
17063
|
-
const endpoint = own ? own.replace(new RegExp(`/v1/${path}/?$`), "") : base;
|
|
17064
|
-
if (!endpoint) return null;
|
|
17065
|
-
const protocol = otlpProtocol(env[`OTEL_EXPORTER_OTLP_${signal}_PROTOCOL`] ?? env.OTEL_EXPORTER_OTLP_PROTOCOL);
|
|
17066
|
-
const resource = parseResourceAttributes(env.OTEL_RESOURCE_ATTRIBUTES);
|
|
17067
|
-
return {
|
|
17068
|
-
endpoint,
|
|
17069
|
-
serviceName: env.OTEL_SERVICE_NAME?.trim() || resource["service.name"] || defaults.serviceName,
|
|
17070
|
-
...defaults.serviceVersion ? { serviceVersion: defaults.serviceVersion } : {},
|
|
17071
|
-
...protocol ? { protocol } : {},
|
|
17072
|
-
...Object.keys(resource).length ? { resource } : {},
|
|
17073
|
-
headers: { ...parseOtlpHeaders(env.OTEL_EXPORTER_OTLP_HEADERS), ...parseOtlpHeaders(env[`OTEL_EXPORTER_OTLP_${signal}_HEADERS`]) }
|
|
17074
|
-
};
|
|
17075
|
-
}
|
|
17076
|
-
function samplerRatioFromEnv(env) {
|
|
17077
|
-
const sampler = (env.OTEL_TRACES_SAMPLER ?? "").trim().toLowerCase().replace(/^parentbased_/, "");
|
|
17078
|
-
if (sampler === "always_on") return 1;
|
|
17079
|
-
if (sampler === "always_off") return 0;
|
|
17080
|
-
if (sampler !== "traceidratio") return void 0;
|
|
17081
|
-
const arg = Number((env.OTEL_TRACES_SAMPLER_ARG ?? "").trim() || "1");
|
|
17082
|
-
return Number.isFinite(arg) && arg >= 0 && arg <= 1 ? arg : 1;
|
|
17083
|
-
}
|
|
17084
|
-
function otlpProtocol(v) {
|
|
17085
|
-
const p = (v ?? "").trim().toLowerCase();
|
|
17086
|
-
return p === "http/protobuf" || p === "http/json" ? p : void 0;
|
|
17087
|
-
}
|
|
17088
|
-
|
|
17089
|
-
// src/api/tracing.ts
|
|
17090
|
-
var TRACEPARENT_HEADER = "traceparent";
|
|
17091
|
-
var TRACESTATE_HEADER = "tracestate";
|
|
17092
|
-
var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
|
|
17093
|
-
function parseTraceparent(traceparent, tracestate) {
|
|
17094
|
-
const m = TRACEPARENT.exec((typeof traceparent === "string" ? traceparent : "").trim().toLowerCase());
|
|
17095
|
-
if (!m) return null;
|
|
17096
|
-
const [, version, traceId, spanId, flags, rest] = m;
|
|
17097
|
-
if (version === "ff" || version === "00" && rest !== void 0) return null;
|
|
17098
|
-
if (/^0+$/.test(traceId) || /^0+$/.test(spanId)) return null;
|
|
17099
|
-
const state = (typeof tracestate === "string" ? tracestate : "").trim();
|
|
17100
|
-
return { traceId, spanId, sampled: (parseInt(flags, 16) & 1) === 1, ...state ? { traceState: state.slice(0, 512) } : {} };
|
|
17101
|
-
}
|
|
17102
|
-
function formatTraceparent(ctx) {
|
|
17103
|
-
return `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
|
|
17104
|
-
}
|
|
17105
|
-
function traceHeaders(ctx) {
|
|
17106
|
-
return { [TRACEPARENT_HEADER]: formatTraceparent(ctx), ...ctx.traceState ? { [TRACESTATE_HEADER]: ctx.traceState } : {} };
|
|
17107
|
-
}
|
|
17108
|
-
function randomHex(bytes) {
|
|
17109
|
-
const b = new Uint8Array(bytes);
|
|
17110
|
-
const c = globalThis.crypto;
|
|
17111
|
-
if (c?.getRandomValues) c.getRandomValues(b);
|
|
17112
|
-
else for (let i = 0; i < bytes; i++) b[i] = Math.floor(Math.random() * 256);
|
|
17113
|
-
const hex = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
17114
|
-
return /^0+$/.test(hex) ? randomHex(bytes) : hex;
|
|
17115
|
-
}
|
|
17116
|
-
var newTraceId = () => randomHex(16);
|
|
17117
|
-
var newSpanId = () => randomHex(8);
|
|
17118
|
-
var perf = globalThis.performance;
|
|
17119
|
-
var defaultNow = perf ? () => perf.timeOrigin + perf.now() : () => Date.now();
|
|
17120
|
-
var TraceSpan = class {
|
|
17121
|
-
constructor(tracer, name, kind, parent, recording, attributes) {
|
|
17122
|
-
this.tracer = tracer;
|
|
17123
|
-
this.name = name;
|
|
17124
|
-
this.kind = kind;
|
|
17125
|
-
this.parent = parent;
|
|
17126
|
-
this.recording = recording;
|
|
17127
|
-
this.attributes = {};
|
|
17128
|
-
this.events = [];
|
|
17129
|
-
this.status = { code: "unset" };
|
|
17130
|
-
this.ended = false;
|
|
17131
|
-
this.context = {
|
|
17132
|
-
traceId: parent?.traceId ?? newTraceId(),
|
|
17133
|
-
spanId: newSpanId(),
|
|
17134
|
-
sampled: recording,
|
|
17135
|
-
...parent?.traceState ? { traceState: parent.traceState } : {}
|
|
17136
|
-
};
|
|
17137
|
-
this.startMs = tracer.now();
|
|
17138
|
-
this.setAttributes(attributes);
|
|
17139
|
-
}
|
|
17140
|
-
setAttribute(key, value) {
|
|
17141
|
-
if (value !== void 0 && value !== null) this.attributes[key] = value;
|
|
17142
|
-
return this;
|
|
17143
|
-
}
|
|
17144
|
-
setAttributes(attributes) {
|
|
17145
|
-
for (const k in attributes) this.setAttribute(k, attributes[k]);
|
|
17146
|
-
return this;
|
|
17147
|
-
}
|
|
17148
|
-
addEvent(name, attributes = {}) {
|
|
17149
|
-
this.events.push({ name, timeMs: this.tracer.now(), attributes });
|
|
17150
|
-
return this;
|
|
17151
|
-
}
|
|
17152
|
-
/** An `exception` event, `error.type` and status ERROR. */
|
|
17153
|
-
recordException(e) {
|
|
17154
|
-
const type = e instanceof Error ? e.name : typeof e;
|
|
17155
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
17156
|
-
this.addEvent("exception", { "exception.type": type, "exception.message": message, ...e instanceof Error && e.stack ? { "exception.stacktrace": e.stack.slice(0, 8192) } : {} });
|
|
17157
|
-
if (!("error.type" in this.attributes)) this.attributes["error.type"] = type;
|
|
17158
|
-
return this.setStatus("error", message);
|
|
17159
|
-
}
|
|
17160
|
-
setStatus(code, message) {
|
|
17161
|
-
if (this.status.code === "error" && code !== "error") return this;
|
|
17162
|
-
this.status = code === "error" && message ? { code, message } : { code };
|
|
17163
|
-
return this;
|
|
17164
|
-
}
|
|
17165
|
-
end() {
|
|
17166
|
-
if (this.ended) return;
|
|
17167
|
-
this.ended = true;
|
|
17168
|
-
if (!this.recording) return;
|
|
17169
|
-
this.tracer.send({
|
|
17170
|
-
traceId: this.context.traceId,
|
|
17171
|
-
spanId: this.context.spanId,
|
|
17172
|
-
...this.parent ? { parentSpanId: this.parent.spanId } : {},
|
|
17173
|
-
...this.context.traceState ? { traceState: this.context.traceState } : {},
|
|
17174
|
-
name: this.name,
|
|
17175
|
-
kind: this.kind,
|
|
17176
|
-
startMs: this.startMs,
|
|
17177
|
-
endMs: this.tracer.now(),
|
|
17178
|
-
attributes: this.attributes,
|
|
17179
|
-
events: this.events,
|
|
17180
|
-
status: this.status
|
|
17181
|
-
});
|
|
17006
|
+
end() {
|
|
17007
|
+
if (this.ended) return;
|
|
17008
|
+
this.ended = true;
|
|
17009
|
+
if (!this.recording) return;
|
|
17010
|
+
this.tracer.send({
|
|
17011
|
+
traceId: this.context.traceId,
|
|
17012
|
+
spanId: this.context.spanId,
|
|
17013
|
+
...this.parent ? { parentSpanId: this.parent.spanId } : {},
|
|
17014
|
+
...this.context.traceState ? { traceState: this.context.traceState } : {},
|
|
17015
|
+
name: this.name,
|
|
17016
|
+
kind: this.kind,
|
|
17017
|
+
startMs: this.startMs,
|
|
17018
|
+
endMs: this.tracer.now(),
|
|
17019
|
+
attributes: this.attributes,
|
|
17020
|
+
events: this.events,
|
|
17021
|
+
status: this.status
|
|
17022
|
+
});
|
|
17182
17023
|
}
|
|
17183
17024
|
};
|
|
17184
17025
|
var Tracer = class {
|
|
@@ -17251,104 +17092,435 @@ function clientSpan(tracer, method, url, parent) {
|
|
|
17251
17092
|
"server.address": target?.hostname,
|
|
17252
17093
|
"server.port": target ? Number(target.port || (target.protocol === "https:" ? 443 : 80)) : void 0
|
|
17253
17094
|
}
|
|
17254
|
-
});
|
|
17255
|
-
}
|
|
17256
|
-
function parse(text) {
|
|
17257
|
-
try {
|
|
17258
|
-
return text.trim() ? JSON.parse(text) : void 0;
|
|
17259
|
-
} catch {
|
|
17260
|
-
return void 0;
|
|
17095
|
+
});
|
|
17096
|
+
}
|
|
17097
|
+
function parse(text) {
|
|
17098
|
+
try {
|
|
17099
|
+
return text.trim() ? JSON.parse(text) : void 0;
|
|
17100
|
+
} catch {
|
|
17101
|
+
return void 0;
|
|
17102
|
+
}
|
|
17103
|
+
}
|
|
17104
|
+
function trimTrailingSlashes(s) {
|
|
17105
|
+
let end = s.length;
|
|
17106
|
+
while (end > 0 && s.charCodeAt(end - 1) === 47) end--;
|
|
17107
|
+
return end === s.length ? s : s.slice(0, end);
|
|
17108
|
+
}
|
|
17109
|
+
var DatanotesClient = class {
|
|
17110
|
+
constructor(o) {
|
|
17111
|
+
this.o = o;
|
|
17112
|
+
this.url = trimTrailingSlashes(o.url);
|
|
17113
|
+
this.send = o.transport ?? fetchTransport;
|
|
17114
|
+
}
|
|
17115
|
+
/** The parent of a request: the call's own `trace`, else the client's. */
|
|
17116
|
+
parentOf(trace) {
|
|
17117
|
+
const given = trace ?? (typeof this.o.trace === "function" ? this.o.trace() : this.o.trace);
|
|
17118
|
+
return typeof given === "string" ? parseTraceparent(given) : given ?? null;
|
|
17119
|
+
}
|
|
17120
|
+
/**
|
|
17121
|
+
* Send a request; the answer's status, its JSON (when it is JSON) and its text. `trace`: the
|
|
17122
|
+
* trace this request continues (over the client's `trace` option).
|
|
17123
|
+
*/
|
|
17124
|
+
async request(method, path, body, opts = {}) {
|
|
17125
|
+
if (!this.url) throw new DatanotesError("engine address not set", "unreachable");
|
|
17126
|
+
if (!this.o.token) throw new DatanotesError("token not set", "auth");
|
|
17127
|
+
const actor = opts.actor ?? this.o.actor;
|
|
17128
|
+
const parent = this.parentOf(opts.trace);
|
|
17129
|
+
const span = this.o.tracer ? clientSpan(this.o.tracer, method, `${this.url}${path}`, parent) : void 0;
|
|
17130
|
+
const sent = span?.context ?? parent;
|
|
17131
|
+
let res;
|
|
17132
|
+
try {
|
|
17133
|
+
res = await this.send({
|
|
17134
|
+
url: `${this.url}${path}`,
|
|
17135
|
+
method,
|
|
17136
|
+
headers: {
|
|
17137
|
+
Authorization: `Bearer ${this.o.token}`,
|
|
17138
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
17139
|
+
...opts.accept ? { Accept: opts.accept } : {},
|
|
17140
|
+
...actor && Object.keys(actor).length ? { [ACTOR_HEADER]: JSON.stringify(actor) } : {},
|
|
17141
|
+
...sent ? traceHeaders(sent) : {}
|
|
17142
|
+
},
|
|
17143
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
17144
|
+
});
|
|
17145
|
+
} catch (e) {
|
|
17146
|
+
span?.recordException(e);
|
|
17147
|
+
span?.end();
|
|
17148
|
+
throw new DatanotesError(`engine unreachable at ${this.url}: ${e instanceof Error ? e.message : String(e)}`, "unreachable");
|
|
17149
|
+
}
|
|
17150
|
+
span?.setAttribute("http.response.status_code", res.status);
|
|
17151
|
+
if (res.status >= 400) span?.setAttribute("error.type", String(res.status));
|
|
17152
|
+
if (res.status >= 500) span?.setStatus("error", `HTTP ${res.status}`);
|
|
17153
|
+
span?.end();
|
|
17154
|
+
if (res.status === 401) throw new DatanotesError("token refused by the engine", "auth", 401);
|
|
17155
|
+
const json = parse(res.text);
|
|
17156
|
+
const unreachable = res.status === 0 || res.status === 502 || res.status === 504 || res.status === 503 && !isEngineAnswer(json);
|
|
17157
|
+
if (unreachable) throw new DatanotesError(`engine unreachable at ${this.url} (HTTP ${res.status})`, "unreachable", res.status);
|
|
17158
|
+
return { status: res.status, json, text: res.text };
|
|
17159
|
+
}
|
|
17160
|
+
/** `POST /datanotes/<route>` and its JSON answer; throws on an error status. */
|
|
17161
|
+
async post(route, body = {}, actor) {
|
|
17162
|
+
const r = await this.request("POST", `/datanotes${route}`, body, actor ? { actor } : {});
|
|
17163
|
+
if (r.status >= 400) throw Object.assign(new DatanotesError(resultOf(r.status, r.json, r.text).value, "http", r.status), guidanceIn(r.json));
|
|
17164
|
+
return r.json;
|
|
17165
|
+
}
|
|
17166
|
+
/**
|
|
17167
|
+
* Run an operation of the catalogue (`select_rows`, `insert_row`, …) with an agent's arguments.
|
|
17168
|
+
* Arguments the operation does not take, or of the wrong type, are refused before anything is sent,
|
|
17169
|
+
* with the same message the engine gives.
|
|
17170
|
+
*/
|
|
17171
|
+
async call(name, args = {}, actor, options = {}) {
|
|
17172
|
+
let req;
|
|
17173
|
+
try {
|
|
17174
|
+
req = operationRequest(name, args);
|
|
17175
|
+
} catch (e) {
|
|
17176
|
+
if (e instanceof OperationInputError) return { ok: false, value: e.message };
|
|
17177
|
+
throw e;
|
|
17178
|
+
}
|
|
17179
|
+
const problem = checkArguments(name, args);
|
|
17180
|
+
if (problem) return { ok: false, value: guidedText(problem.message, problem) };
|
|
17181
|
+
const r = await this.request(req.method, req.path, req.body, { ...actor ? { actor } : {}, ...options.trace ? { trace: options.trace } : {} });
|
|
17182
|
+
return resultOf(r.status, r.json, r.text);
|
|
17183
|
+
}
|
|
17184
|
+
/** True when the engine answers `GET /` (no token needed). */
|
|
17185
|
+
async ping() {
|
|
17186
|
+
try {
|
|
17187
|
+
const r = await this.send({ url: `${this.url}/`, method: "GET", headers: {} });
|
|
17188
|
+
return r.status === 200;
|
|
17189
|
+
} catch {
|
|
17190
|
+
return false;
|
|
17191
|
+
}
|
|
17192
|
+
}
|
|
17193
|
+
/**
|
|
17194
|
+
* Record an agent's tool call in the change feed (what MCP servers report). Answers what the
|
|
17195
|
+
* engine said: `takes_summary` when it records a `value` sent cut with its `summary`.
|
|
17196
|
+
*/
|
|
17197
|
+
async recordToolCall(call, actor) {
|
|
17198
|
+
return this.post("/tool-calls/record/", call, actor);
|
|
17199
|
+
}
|
|
17200
|
+
};
|
|
17201
|
+
|
|
17202
|
+
// src/api/otlp.ts
|
|
17203
|
+
var SEVERITY_NUMBER = { DEBUG: 5, INFO: 9, WARN: 13, ERROR: 17 };
|
|
17204
|
+
var SPAN_KIND = { internal: 1, server: 2, client: 3, producer: 4, consumer: 5 };
|
|
17205
|
+
var STATUS_CODE = { unset: 0, ok: 1, error: 2 };
|
|
17206
|
+
function attr(key, v) {
|
|
17207
|
+
if (v === void 0 || v === null) return null;
|
|
17208
|
+
if (typeof v === "boolean") return { key, value: { boolValue: v } };
|
|
17209
|
+
if (typeof v === "number") return Number.isInteger(v) ? { key, value: { intValue: String(v) } } : { key, value: { doubleValue: v } };
|
|
17210
|
+
return { key, value: { stringValue: v } };
|
|
17211
|
+
}
|
|
17212
|
+
var attrs = (a) => Object.entries(a).map(([k, v]) => attr(k, v)).filter((x) => x !== null);
|
|
17213
|
+
var fetchSend = async (url, body, headers) => {
|
|
17214
|
+
const res = await fetch(url, { method: "POST", headers, body });
|
|
17215
|
+
if (!res.ok) throw new Error(`OTLP HTTP ${res.status}`);
|
|
17216
|
+
};
|
|
17217
|
+
function unixNano(ms) {
|
|
17218
|
+
const whole = Math.floor(ms);
|
|
17219
|
+
const frac = Math.round((ms - whole) * 1e6);
|
|
17220
|
+
return (BigInt(whole) * BigInt(1e6) + BigInt(frac)).toString();
|
|
17221
|
+
}
|
|
17222
|
+
var Pb = class {
|
|
17223
|
+
constructor() {
|
|
17224
|
+
this.parts = [];
|
|
17225
|
+
}
|
|
17226
|
+
varint(v) {
|
|
17227
|
+
if (typeof v === "number" && v >= 0 && v < 2 ** 31) {
|
|
17228
|
+
let x2 = v;
|
|
17229
|
+
while (x2 >= 128) {
|
|
17230
|
+
this.parts.push(x2 & 127 | 128);
|
|
17231
|
+
x2 >>>= 7;
|
|
17232
|
+
}
|
|
17233
|
+
this.parts.push(x2);
|
|
17234
|
+
return;
|
|
17235
|
+
}
|
|
17236
|
+
let x = BigInt.asUintN(64, BigInt(v));
|
|
17237
|
+
const b128 = BigInt(128);
|
|
17238
|
+
const low7 = BigInt(127);
|
|
17239
|
+
const seven = BigInt(7);
|
|
17240
|
+
while (x >= b128) {
|
|
17241
|
+
this.parts.push(Number(x & low7) | 128);
|
|
17242
|
+
x >>= seven;
|
|
17243
|
+
}
|
|
17244
|
+
this.parts.push(Number(x));
|
|
17245
|
+
}
|
|
17246
|
+
tag(field, wire) {
|
|
17247
|
+
this.varint(field << 3 | wire);
|
|
17248
|
+
}
|
|
17249
|
+
uint(field, v) {
|
|
17250
|
+
this.tag(field, 0);
|
|
17251
|
+
this.varint(v);
|
|
17252
|
+
return this;
|
|
17253
|
+
}
|
|
17254
|
+
fixed32(field, v) {
|
|
17255
|
+
this.tag(field, 5);
|
|
17256
|
+
for (let i = 0; i < 4; i++) this.parts.push(v >>> 8 * i & 255);
|
|
17257
|
+
return this;
|
|
17258
|
+
}
|
|
17259
|
+
fixed64(field, v) {
|
|
17260
|
+
this.tag(field, 1);
|
|
17261
|
+
for (let i = 0; i < 8; i++) this.parts.push(Number(v >> BigInt(8 * i) & BigInt(255)));
|
|
17262
|
+
return this;
|
|
17263
|
+
}
|
|
17264
|
+
double(field, v) {
|
|
17265
|
+
this.tag(field, 1);
|
|
17266
|
+
const b = new DataView(new ArrayBuffer(8));
|
|
17267
|
+
b.setFloat64(0, v, true);
|
|
17268
|
+
for (let i = 0; i < 8; i++) this.parts.push(b.getUint8(i));
|
|
17269
|
+
return this;
|
|
17270
|
+
}
|
|
17271
|
+
bytes(field, data) {
|
|
17272
|
+
this.tag(field, 2);
|
|
17273
|
+
this.varint(data.length);
|
|
17274
|
+
for (const x of data) this.parts.push(x);
|
|
17275
|
+
return this;
|
|
17276
|
+
}
|
|
17277
|
+
/** An id given in hex (trace and span ids), as bytes. */
|
|
17278
|
+
hex(field, hex) {
|
|
17279
|
+
const out = [];
|
|
17280
|
+
for (let i = 0; i < hex.length; i += 2) out.push(parseInt(hex.slice(i, i + 2), 16));
|
|
17281
|
+
return this.bytes(field, out);
|
|
17282
|
+
}
|
|
17283
|
+
string(field, s) {
|
|
17284
|
+
return this.bytes(field, new TextEncoder().encode(s));
|
|
17285
|
+
}
|
|
17286
|
+
message(field, m) {
|
|
17287
|
+
return this.bytes(field, m.finish());
|
|
17288
|
+
}
|
|
17289
|
+
finish() {
|
|
17290
|
+
return Uint8Array.from(this.parts);
|
|
17291
|
+
}
|
|
17292
|
+
};
|
|
17293
|
+
function pbValue(v) {
|
|
17294
|
+
if (typeof v === "string") return new Pb().string(1, v);
|
|
17295
|
+
if (typeof v === "boolean") return new Pb().uint(2, v ? 1 : 0);
|
|
17296
|
+
return Number.isInteger(v) ? new Pb().uint(3, BigInt(v)) : new Pb().double(4, v);
|
|
17297
|
+
}
|
|
17298
|
+
function pbAttrs(m, field, a) {
|
|
17299
|
+
for (const [k, v] of Object.entries(a)) {
|
|
17300
|
+
if (v === void 0 || v === null) continue;
|
|
17301
|
+
m.message(field, new Pb().string(1, k).message(2, pbValue(v)));
|
|
17302
|
+
}
|
|
17303
|
+
return m;
|
|
17304
|
+
}
|
|
17305
|
+
var OtlpBatcher = class {
|
|
17306
|
+
constructor(o, path, maxBatch) {
|
|
17307
|
+
this.o = o;
|
|
17308
|
+
this.path = path;
|
|
17309
|
+
this.maxBatch = maxBatch;
|
|
17310
|
+
this.buffer = [];
|
|
17311
|
+
this.inflight = Promise.resolve();
|
|
17312
|
+
this.timer = null;
|
|
17313
|
+
/** Items sent, and items lost because the collector did not take them (or the buffer was full). */
|
|
17314
|
+
this.sent = 0;
|
|
17315
|
+
this.dropped = 0;
|
|
17316
|
+
const every = o.flushMs ?? 5e3;
|
|
17317
|
+
if (every > 0) {
|
|
17318
|
+
this.timer = setInterval(() => void this.flush(), every);
|
|
17319
|
+
this.timer.unref?.();
|
|
17320
|
+
}
|
|
17321
|
+
}
|
|
17322
|
+
push(items) {
|
|
17323
|
+
const room = this.maxBatch * 8 - this.buffer.length;
|
|
17324
|
+
if (room < items.length) this.dropped += items.length - Math.max(room, 0);
|
|
17325
|
+
for (let i = 0; i < Math.min(items.length, Math.max(room, 0)); i++) this.buffer.push(items[i]);
|
|
17326
|
+
if (this.buffer.length >= this.maxBatch) void this.flush();
|
|
17327
|
+
}
|
|
17328
|
+
resource() {
|
|
17329
|
+
return { "service.name": this.o.serviceName, "service.version": this.o.serviceVersion, ...this.o.resource };
|
|
17330
|
+
}
|
|
17331
|
+
/** Send what is buffered. Never rejects. */
|
|
17332
|
+
flush() {
|
|
17333
|
+
if (this.buffer.length === 0) return this.inflight;
|
|
17334
|
+
const send = this.o.send ?? fetchSend;
|
|
17335
|
+
const url = `${trimTrailingSlashes(this.o.endpoint)}${this.path}`;
|
|
17336
|
+
const protobuf = (this.o.protocol ?? "http/protobuf") === "http/protobuf";
|
|
17337
|
+
const headers = { "Content-Type": protobuf ? "application/x-protobuf" : "application/json", ...this.o.headers ?? {} };
|
|
17338
|
+
while (this.buffer.length > 0) {
|
|
17339
|
+
const batch = this.buffer.splice(0, this.maxBatch);
|
|
17340
|
+
let body;
|
|
17341
|
+
try {
|
|
17342
|
+
body = this.encode(batch, protobuf);
|
|
17343
|
+
} catch {
|
|
17344
|
+
this.dropped += batch.length;
|
|
17345
|
+
continue;
|
|
17346
|
+
}
|
|
17347
|
+
this.inflight = this.inflight.then(
|
|
17348
|
+
() => send(url, body, headers).then(
|
|
17349
|
+
() => void (this.sent += batch.length),
|
|
17350
|
+
() => void (this.dropped += batch.length)
|
|
17351
|
+
)
|
|
17352
|
+
);
|
|
17353
|
+
}
|
|
17354
|
+
return this.inflight;
|
|
17261
17355
|
}
|
|
17262
|
-
|
|
17263
|
-
|
|
17356
|
+
/** Stop the timer and send what is left. */
|
|
17357
|
+
async close() {
|
|
17358
|
+
if (this.timer) clearInterval(this.timer);
|
|
17359
|
+
this.timer = null;
|
|
17360
|
+
await this.flush();
|
|
17361
|
+
}
|
|
17362
|
+
};
|
|
17363
|
+
var OtlpLogExporter = class extends OtlpBatcher {
|
|
17264
17364
|
constructor(o) {
|
|
17265
|
-
|
|
17266
|
-
this.url = o.url.replace(/\/+$/, "");
|
|
17267
|
-
this.send = o.transport ?? fetchTransport;
|
|
17365
|
+
super(o, "/v1/logs", o.maxBatch ?? 50);
|
|
17268
17366
|
}
|
|
17269
|
-
/**
|
|
17270
|
-
|
|
17271
|
-
const
|
|
17272
|
-
|
|
17367
|
+
/** Buffer a record; `context`: the span it was made in (its trace and span id go with it). */
|
|
17368
|
+
log(severity, body, attributes = {}, context) {
|
|
17369
|
+
const ms = (this.o.now ?? Date.now)();
|
|
17370
|
+
this.push([{ timeUnixNano: `${Math.round(ms)}000000`, severity, body, attributes, ...context ? { context } : {} }]);
|
|
17273
17371
|
}
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
17278
|
-
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
17282
|
-
|
|
17283
|
-
|
|
17284
|
-
|
|
17285
|
-
|
|
17286
|
-
|
|
17287
|
-
|
|
17288
|
-
|
|
17289
|
-
|
|
17290
|
-
|
|
17291
|
-
|
|
17292
|
-
|
|
17293
|
-
|
|
17294
|
-
|
|
17295
|
-
|
|
17296
|
-
|
|
17297
|
-
|
|
17298
|
-
|
|
17299
|
-
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17372
|
+
encode(batch, protobuf) {
|
|
17373
|
+
const resource = this.resource();
|
|
17374
|
+
if (protobuf) return this.protobuf(resource, batch);
|
|
17375
|
+
return JSON.stringify({
|
|
17376
|
+
resourceLogs: [
|
|
17377
|
+
{
|
|
17378
|
+
resource: { attributes: attrs(resource) },
|
|
17379
|
+
scopeLogs: [
|
|
17380
|
+
{
|
|
17381
|
+
scope: { name: this.o.serviceName },
|
|
17382
|
+
logRecords: batch.map((r) => ({
|
|
17383
|
+
timeUnixNano: r.timeUnixNano,
|
|
17384
|
+
observedTimeUnixNano: r.timeUnixNano,
|
|
17385
|
+
severityNumber: SEVERITY_NUMBER[r.severity],
|
|
17386
|
+
severityText: r.severity,
|
|
17387
|
+
body: { stringValue: r.body },
|
|
17388
|
+
attributes: attrs(r.attributes),
|
|
17389
|
+
...r.context ? { traceId: r.context.traceId, spanId: r.context.spanId, flags: r.context.sampled ? 1 : 0 } : {}
|
|
17390
|
+
}))
|
|
17391
|
+
}
|
|
17392
|
+
]
|
|
17393
|
+
}
|
|
17394
|
+
]
|
|
17395
|
+
});
|
|
17396
|
+
}
|
|
17397
|
+
protobuf(resource, batch) {
|
|
17398
|
+
const scope = new Pb().message(1, new Pb().string(1, this.o.serviceName));
|
|
17399
|
+
for (const r of batch) {
|
|
17400
|
+
const t = BigInt(r.timeUnixNano);
|
|
17401
|
+
const rec = new Pb().fixed64(1, t).uint(2, SEVERITY_NUMBER[r.severity]).string(3, r.severity).message(5, new Pb().string(1, r.body));
|
|
17402
|
+
pbAttrs(rec, 6, r.attributes);
|
|
17403
|
+
if (r.context) rec.fixed32(8, r.context.sampled ? 1 : 0).hex(9, r.context.traceId).hex(10, r.context.spanId);
|
|
17404
|
+
rec.fixed64(11, t);
|
|
17405
|
+
scope.message(2, rec);
|
|
17303
17406
|
}
|
|
17304
|
-
|
|
17305
|
-
|
|
17306
|
-
if (res.status >= 500) span?.setStatus("error", `HTTP ${res.status}`);
|
|
17307
|
-
span?.end();
|
|
17308
|
-
if (res.status === 401) throw new DatanotesError("token refused by the engine", "auth", 401);
|
|
17309
|
-
const json = parse(res.text);
|
|
17310
|
-
const unreachable = res.status === 0 || res.status === 502 || res.status === 504 || res.status === 503 && !isEngineAnswer(json);
|
|
17311
|
-
if (unreachable) throw new DatanotesError(`engine unreachable at ${this.url} (HTTP ${res.status})`, "unreachable", res.status);
|
|
17312
|
-
return { status: res.status, json, text: res.text };
|
|
17407
|
+
const resourceLogs = new Pb().message(1, pbAttrs(new Pb(), 1, resource)).message(2, scope);
|
|
17408
|
+
return new Pb().message(1, resourceLogs).finish();
|
|
17313
17409
|
}
|
|
17314
|
-
|
|
17315
|
-
|
|
17316
|
-
|
|
17317
|
-
|
|
17318
|
-
return r.json;
|
|
17410
|
+
};
|
|
17411
|
+
var OtlpTraceExporter = class extends OtlpBatcher {
|
|
17412
|
+
constructor(o) {
|
|
17413
|
+
super(o, "/v1/traces", o.maxBatch ?? 512);
|
|
17319
17414
|
}
|
|
17320
|
-
/**
|
|
17321
|
-
|
|
17322
|
-
|
|
17323
|
-
|
|
17324
|
-
|
|
17325
|
-
|
|
17326
|
-
|
|
17327
|
-
|
|
17328
|
-
|
|
17329
|
-
|
|
17330
|
-
|
|
17331
|
-
|
|
17415
|
+
/** Buffer finished spans (sent with the next batch). Never throws. */
|
|
17416
|
+
export(spans) {
|
|
17417
|
+
this.push(Array.isArray(spans) ? spans : [spans]);
|
|
17418
|
+
}
|
|
17419
|
+
encode(batch, protobuf) {
|
|
17420
|
+
const resource = this.resource();
|
|
17421
|
+
if (protobuf) return this.protobuf(resource, batch);
|
|
17422
|
+
return JSON.stringify({
|
|
17423
|
+
resourceSpans: [
|
|
17424
|
+
{
|
|
17425
|
+
resource: { attributes: attrs(resource) },
|
|
17426
|
+
scopeSpans: [
|
|
17427
|
+
{
|
|
17428
|
+
scope: { name: this.o.serviceName, ...this.o.serviceVersion ? { version: this.o.serviceVersion } : {} },
|
|
17429
|
+
spans: batch.map((s) => ({
|
|
17430
|
+
traceId: s.traceId,
|
|
17431
|
+
spanId: s.spanId,
|
|
17432
|
+
...s.parentSpanId ? { parentSpanId: s.parentSpanId } : {},
|
|
17433
|
+
...s.traceState ? { traceState: s.traceState } : {},
|
|
17434
|
+
flags: 1,
|
|
17435
|
+
name: s.name,
|
|
17436
|
+
kind: SPAN_KIND[s.kind],
|
|
17437
|
+
startTimeUnixNano: unixNano(s.startMs),
|
|
17438
|
+
endTimeUnixNano: unixNano(s.endMs),
|
|
17439
|
+
attributes: attrs(s.attributes),
|
|
17440
|
+
...s.droppedAttributes ? { droppedAttributesCount: s.droppedAttributes } : {},
|
|
17441
|
+
events: s.events.map((e) => ({ timeUnixNano: unixNano(e.timeMs), name: e.name, attributes: attrs(e.attributes) })),
|
|
17442
|
+
...s.droppedEvents ? { droppedEventsCount: s.droppedEvents } : {},
|
|
17443
|
+
status: { code: STATUS_CODE[s.status.code], ...s.status.message ? { message: s.status.message } : {} }
|
|
17444
|
+
}))
|
|
17445
|
+
}
|
|
17446
|
+
]
|
|
17447
|
+
}
|
|
17448
|
+
]
|
|
17449
|
+
});
|
|
17450
|
+
}
|
|
17451
|
+
protobuf(resource, batch) {
|
|
17452
|
+
const scopeInfo = new Pb().string(1, this.o.serviceName);
|
|
17453
|
+
if (this.o.serviceVersion) scopeInfo.string(2, this.o.serviceVersion);
|
|
17454
|
+
const scope = new Pb().message(1, scopeInfo);
|
|
17455
|
+
for (const s of batch) {
|
|
17456
|
+
const span = new Pb().hex(1, s.traceId).hex(2, s.spanId);
|
|
17457
|
+
if (s.traceState) span.string(3, s.traceState);
|
|
17458
|
+
if (s.parentSpanId) span.hex(4, s.parentSpanId);
|
|
17459
|
+
span.string(5, s.name).uint(6, SPAN_KIND[s.kind]).fixed64(7, BigInt(unixNano(s.startMs))).fixed64(8, BigInt(unixNano(s.endMs)));
|
|
17460
|
+
pbAttrs(span, 9, s.attributes);
|
|
17461
|
+
if (s.droppedAttributes) span.uint(10, s.droppedAttributes);
|
|
17462
|
+
for (const e of s.events) span.message(11, pbAttrs(new Pb().fixed64(1, BigInt(unixNano(e.timeMs))).string(2, e.name), 3, e.attributes));
|
|
17463
|
+
if (s.droppedEvents) span.uint(12, s.droppedEvents);
|
|
17464
|
+
const status = new Pb();
|
|
17465
|
+
if (s.status.message) status.string(2, s.status.message);
|
|
17466
|
+
if (s.status.code !== "unset") status.uint(3, STATUS_CODE[s.status.code]);
|
|
17467
|
+
span.message(15, status).fixed32(16, 1);
|
|
17468
|
+
scope.message(2, span);
|
|
17332
17469
|
}
|
|
17333
|
-
const
|
|
17334
|
-
|
|
17335
|
-
const r = await this.request(req.method, req.path, req.body, { ...actor ? { actor } : {}, ...options.trace ? { trace: options.trace } : {} });
|
|
17336
|
-
return resultOf(r.status, r.json, r.text);
|
|
17470
|
+
const resourceSpans = new Pb().message(1, pbAttrs(new Pb(), 1, resource)).message(2, scope);
|
|
17471
|
+
return new Pb().message(1, resourceSpans).finish();
|
|
17337
17472
|
}
|
|
17338
|
-
|
|
17339
|
-
|
|
17473
|
+
};
|
|
17474
|
+
function parseOtlpHeaders(text) {
|
|
17475
|
+
const out = {};
|
|
17476
|
+
for (const part of (text ?? "").split(",")) {
|
|
17477
|
+
const i = part.indexOf("=");
|
|
17478
|
+
if (i <= 0) continue;
|
|
17479
|
+
const key = part.slice(0, i).trim();
|
|
17480
|
+
const value = part.slice(i + 1).trim();
|
|
17481
|
+
if (!key) continue;
|
|
17340
17482
|
try {
|
|
17341
|
-
|
|
17342
|
-
return r.status === 200;
|
|
17483
|
+
out[key] = decodeURIComponent(value);
|
|
17343
17484
|
} catch {
|
|
17344
|
-
|
|
17485
|
+
out[key] = value;
|
|
17345
17486
|
}
|
|
17346
17487
|
}
|
|
17347
|
-
|
|
17348
|
-
|
|
17349
|
-
|
|
17350
|
-
|
|
17351
|
-
|
|
17352
|
-
|
|
17353
|
-
|
|
17354
|
-
|
|
17488
|
+
return out;
|
|
17489
|
+
}
|
|
17490
|
+
var parseResourceAttributes = parseOtlpHeaders;
|
|
17491
|
+
var truthy = (v) => (v ?? "").trim().toLowerCase() === "true";
|
|
17492
|
+
function otlpFromEnv(env, defaults) {
|
|
17493
|
+
return fromEnv(env, defaults, "LOGS", "logs");
|
|
17494
|
+
}
|
|
17495
|
+
function otlpTracesFromEnv(env, defaults) {
|
|
17496
|
+
return fromEnv(env, defaults, "TRACES", "traces");
|
|
17497
|
+
}
|
|
17498
|
+
function fromEnv(env, defaults, signal, path) {
|
|
17499
|
+
if (truthy(env.OTEL_SDK_DISABLED) || (env[`OTEL_${signal}_EXPORTER`] ?? "").trim().toLowerCase() === "none") return null;
|
|
17500
|
+
const own = env[`OTEL_EXPORTER_OTLP_${signal}_ENDPOINT`]?.trim();
|
|
17501
|
+
const base = env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim();
|
|
17502
|
+
const endpoint = own ? own.replace(new RegExp(`/v1/${path}/?$`), "") : base;
|
|
17503
|
+
if (!endpoint) return null;
|
|
17504
|
+
const protocol = otlpProtocol(env[`OTEL_EXPORTER_OTLP_${signal}_PROTOCOL`] ?? env.OTEL_EXPORTER_OTLP_PROTOCOL);
|
|
17505
|
+
const resource = parseResourceAttributes(env.OTEL_RESOURCE_ATTRIBUTES);
|
|
17506
|
+
return {
|
|
17507
|
+
endpoint,
|
|
17508
|
+
serviceName: env.OTEL_SERVICE_NAME?.trim() || resource["service.name"] || defaults.serviceName,
|
|
17509
|
+
...defaults.serviceVersion ? { serviceVersion: defaults.serviceVersion } : {},
|
|
17510
|
+
...protocol ? { protocol } : {},
|
|
17511
|
+
...Object.keys(resource).length ? { resource } : {},
|
|
17512
|
+
headers: { ...parseOtlpHeaders(env.OTEL_EXPORTER_OTLP_HEADERS), ...parseOtlpHeaders(env[`OTEL_EXPORTER_OTLP_${signal}_HEADERS`]) }
|
|
17513
|
+
};
|
|
17514
|
+
}
|
|
17515
|
+
function samplerRatioFromEnv(env) {
|
|
17516
|
+
const sampler = (env.OTEL_TRACES_SAMPLER ?? "").trim().toLowerCase().replace(/^parentbased_/, "");
|
|
17517
|
+
if (sampler === "always_on") return 1;
|
|
17518
|
+
if (sampler === "always_off") return 0;
|
|
17519
|
+
if (sampler !== "traceidratio") return void 0;
|
|
17520
|
+
const arg = Number((env.OTEL_TRACES_SAMPLER_ARG ?? "").trim() || "1");
|
|
17521
|
+
return Number.isFinite(arg) && arg >= 0 && arg <= 1 ? arg : 1;
|
|
17522
|
+
}
|
|
17523
|
+
function otlpProtocol(v) {
|
|
17524
|
+
const p = (v ?? "").trim().toLowerCase();
|
|
17525
|
+
return p === "http/protobuf" || p === "http/json" ? p : void 0;
|
|
17526
|
+
}
|