datanotes 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +1 -5
  2. package/dist/api/client.d.cts +37 -4
  3. package/dist/api/client.d.ts +37 -4
  4. package/dist/api/index.cjs +388 -52
  5. package/dist/api/index.d.cts +3 -2
  6. package/dist/api/index.d.ts +3 -2
  7. package/dist/api/index.js +388 -52
  8. package/dist/api/mcp.cjs +6 -3
  9. package/dist/api/mcp.js +6 -3
  10. package/dist/api/otlp.d.cts +63 -15
  11. package/dist/api/otlp.d.ts +63 -15
  12. package/dist/api/redact.d.cts +25 -0
  13. package/dist/api/redact.d.ts +25 -0
  14. package/dist/api/tokens.d.cts +5 -0
  15. package/dist/api/tokens.d.ts +5 -0
  16. package/dist/api/tracing.d.cts +107 -0
  17. package/dist/api/tracing.d.ts +107 -0
  18. package/dist/datanotes.cjs +9380 -2554
  19. package/dist/docs/administration/limits.md +96 -12
  20. package/dist/docs/administration/run-the-service.md +18 -0
  21. package/dist/docs/api/operations/graph_neighbors.md +4 -2
  22. package/dist/docs/api/operations/graph_path.md +3 -3
  23. package/dist/docs/api/operations/graph_traverse.md +2 -2
  24. package/dist/docs/api/operations/record_tool_call.md +1 -0
  25. package/dist/docs/api/operations/tags/queries.md +2 -2
  26. package/dist/docs/api.md +3 -3
  27. package/dist/docs/develop/concurrency.md +36 -1
  28. package/dist/docs/develop/http-api.md +11 -1
  29. package/dist/docs/develop/telemetry.md +224 -25
  30. package/dist/docs/guides/data-quality/check-constraints.md +10 -10
  31. package/dist/docs/guides/data-quality/hand-edits.md +8 -8
  32. package/dist/docs/guides/database-objects/bases.md +11 -11
  33. package/dist/docs/guides/database-objects/catalogs-and-schemas.md +10 -10
  34. package/dist/docs/guides/database-objects/columns.md +38 -38
  35. package/dist/docs/guides/database-objects/relations.md +27 -27
  36. package/dist/docs/guides/database-objects/tables.md +37 -101
  37. package/dist/docs/guides/database-objects/views.md +44 -44
  38. package/dist/docs/guides/history/back-up.md +12 -4
  39. package/dist/docs/guides/history/change-data-feed.md +34 -34
  40. package/dist/docs/guides/history/journal-and-undo.md +12 -12
  41. package/dist/docs/guides/history/restore.md +20 -20
  42. package/dist/docs/guides/history/table-history.md +31 -31
  43. package/dist/docs/guides/history/vacuum.md +1 -10
  44. package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
  45. package/dist/docs/guides/read-and-write/import-notes.md +20 -20
  46. package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
  47. package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
  48. package/dist/docs/guides/read-and-write/write-rows.md +10 -10
  49. package/dist/docs/guides/search/link-graph.md +95 -0
  50. package/dist/docs/guides/search/text.md +1 -1
  51. package/dist/docs/guides/security/who-did-what.md +2 -0
  52. package/dist/docs/reference/cli.md +10 -3
  53. package/dist/docs/reference/compatibility.md +33 -13
  54. package/dist/docs/reference/operations/queries.md +3 -3
  55. package/dist/docs/reference/operations.md +11 -11
  56. package/dist/docs/reference/settings.md +37 -25
  57. package/dist/docs/release-notes.md +121 -0
  58. package/dist/docs/start/how-it-works.md +35 -3
  59. package/dist/docs/start/quick-start.md +2 -0
  60. package/package.json +3 -2
package/dist/api/index.js CHANGED
@@ -15955,7 +15955,7 @@ var OPERATIONS = [
15955
15955
  },
15956
15956
  {
15957
15957
  "name": "graph_neighbors",
15958
- "description": 'Direct neighbours of notes: what they link to (`out`) and what links to them (`in`,\nbacklinks), with counts per edge label. `direction`: out, in or both (default).\n\n`from_nodes` selects the notes: `{"paths": [...]}` and/or `{"table": ..., "where": {...}}`.\nEdges are labelled with their link column (`people`, `event`, \u2026) or `link` for other links.',
15958
+ "description": 'Direct neighbours of notes: what they link to (`out`) and what links to them (`in`,\nbacklinks), with counts per edge label. `direction`: out, in or both (default).\n\n`from_nodes` selects the notes: `{"paths": [...]}`, `{"table": ..., "where": {...}}` and/or\n`{"tables": [...]}`: the rows of several tables, by name or pattern (`["*"]` every table, `["personal.*"]` a\ncatalog\'s). The whole vault\'s graph in one call: `{"tables": ["*"]}` with direction `out` (at most 5000\nstart notes). Edges are labelled with their link column (`people`, `event`, \u2026) or `link` for other links.',
15959
15959
  "inputSchema": {
15960
15960
  "additionalProperties": false,
15961
15961
  "properties": {
@@ -16074,7 +16074,7 @@ var OPERATIONS = [
16074
16074
  },
16075
16075
  {
16076
16076
  "name": "graph_traverse",
16077
- "description": 'Breadth-first walk over links from `from_nodes` (`{"paths": [...]}` and/or `{"table", "where"}`).\n\n- `direction`: out (default, follow links), in (follow backlinks) or both.\n- `edges`: edge labels to follow (link columns such as `people`, `event`, or `link`).\n- `tables`: return only notes of these tables; `through`: only walk on through these tables.\n- `min_depth` (default 1) / `max_depth` (default 2, max 10), `limit` (default 500).\n\nEach node comes with `depth` and `via` (one shortest route). Example \u2014 moods tied to events\nwith Alice: from `{"table": "person", "where": {"name": "Alice"}}`, direction `in`, edges\n`["people", "event"]`, tables `["mood"]`, max_depth 2. Feed the paths to `select_rows` with\n`where: {"path": {"in": [...]}}` to aggregate them.',
16077
+ "description": 'Breadth-first walk over links from `from_nodes` (`{"paths": [...]}`, `{"table", "where"}` and/or `{"tables": [...]}`).\n\n- `direction`: out (default, follow links), in (follow backlinks) or both.\n- `edges`: edge labels to follow (link columns such as `people`, `event`, or `link`).\n- `tables`: return only notes of these tables; `through`: only walk on through these tables.\n- `min_depth` (default 1) / `max_depth` (default 2, max 10), `limit` (default 500).\n\nEach node comes with `depth` and `via` (one shortest route). Example \u2014 moods tied to events\nwith Alice: from `{"table": "person", "where": {"name": "Alice"}}`, direction `in`, edges\n`["people", "event"]`, tables `["mood"]`, max_depth 2. Feed the paths to `select_rows` with\n`where: {"path": {"in": [...]}}` to aggregate them.',
16078
16078
  "inputSchema": {
16079
16079
  "additionalProperties": false,
16080
16080
  "properties": {
@@ -16270,7 +16270,7 @@ var OPERATIONS = [
16270
16270
  },
16271
16271
  {
16272
16272
  "name": "graph_path",
16273
- "description": 'Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or\n`{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`).\n`direction` both by default; `max_depth` default 6 (max 10).',
16273
+ "description": 'Shortest chain of links between two sets of notes (each `{"paths": [...]}`, `{"table", "where"}`\nand/or `{"tables": [...]}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`).\n`direction` both by default; `max_depth` default 6 (max 10).',
16274
16274
  "inputSchema": {
16275
16275
  "additionalProperties": false,
16276
16276
  "properties": {
@@ -16658,17 +16658,52 @@ function resultOf(status, json, text) {
16658
16658
  // src/api/tokens.ts
16659
16659
  function estimateTokens(text) {
16660
16660
  let n = 0;
16661
- for (const m of text.matchAll(/\p{L}+|\p{N}+|[^\s\p{L}\p{N}]/gu)) {
16662
- const s = m[0];
16663
- if (/^\p{L}/u.test(s)) n += Math.ceil(s.length / 4);
16664
- else if (/^\p{N}/u.test(s)) n += Math.ceil(s.length / 3);
16665
- else n += 1;
16661
+ let run = 0;
16662
+ for (let i = 0; i < text.length; ) {
16663
+ const c = text.charCodeAt(i);
16664
+ const cp = c >= 55296 && c <= 56319 ? text.codePointAt(i) : c;
16665
+ const width = cp > 65535 ? 2 : 1;
16666
+ const kind = classOf(cp);
16667
+ if (kind === LETTER && run >= 0) run += width;
16668
+ else if (kind === DIGIT && run <= 0) run -= width;
16669
+ else {
16670
+ n += run > 0 ? Math.ceil(run / 4) : Math.ceil(-run / 3);
16671
+ run = kind === LETTER ? width : kind === DIGIT ? -width : 0;
16672
+ if (kind === OTHER) n += 1;
16673
+ }
16674
+ i += width;
16675
+ }
16676
+ return n + (run > 0 ? Math.ceil(run / 4) : Math.ceil(-run / 3));
16677
+ }
16678
+ var LETTER = 0;
16679
+ var DIGIT = 1;
16680
+ var SPACE = 2;
16681
+ var OTHER = 3;
16682
+ function test(cp) {
16683
+ const ch = String.fromCodePoint(cp);
16684
+ return /\p{L}/u.test(ch) ? LETTER : /\p{N}/u.test(ch) ? DIGIT : /\s/u.test(ch) ? SPACE : OTHER;
16685
+ }
16686
+ var BMP = new Uint8Array(65536).fill(255);
16687
+ var ASTRAL = /* @__PURE__ */ new Map();
16688
+ var ASTRAL_KEPT = 4096;
16689
+ function classOf(cp) {
16690
+ if (cp <= 65535) {
16691
+ let k2 = BMP[cp];
16692
+ if (k2 === 255) BMP[cp] = k2 = test(cp);
16693
+ return k2;
16694
+ }
16695
+ let k = ASTRAL.get(cp);
16696
+ if (k === void 0) {
16697
+ k = test(cp);
16698
+ if (ASTRAL.size < ASTRAL_KEPT) ASTRAL.set(cp, k);
16666
16699
  }
16667
- return n;
16700
+ return k;
16668
16701
  }
16669
16702
 
16670
16703
  // src/api/otlp.ts
16671
16704
  var SEVERITY_NUMBER = { DEBUG: 5, INFO: 9, WARN: 13, ERROR: 17 };
16705
+ var SPAN_KIND = { internal: 1, server: 2, client: 3, producer: 4, consumer: 5 };
16706
+ var STATUS_CODE = { unset: 0, ok: 1, error: 2 };
16672
16707
  function attr(key, v) {
16673
16708
  if (v === void 0 || v === null) return null;
16674
16709
  if (typeof v === "boolean") return { key, value: { boolValue: v } };
@@ -16680,12 +16715,26 @@ var fetchSend = async (url, body, headers) => {
16680
16715
  const res = await fetch(url, { method: "POST", headers, body });
16681
16716
  if (!res.ok) throw new Error(`OTLP HTTP ${res.status}`);
16682
16717
  };
16718
+ function unixNano(ms) {
16719
+ const whole = Math.floor(ms);
16720
+ const frac = Math.round((ms - whole) * 1e6);
16721
+ return (BigInt(whole) * BigInt(1e6) + BigInt(frac)).toString();
16722
+ }
16683
16723
  var Pb = class {
16684
16724
  constructor() {
16685
16725
  this.parts = [];
16686
16726
  }
16687
16727
  varint(v) {
16688
- let x = BigInt.asUintN(64, v);
16728
+ if (typeof v === "number" && v >= 0 && v < 2 ** 31) {
16729
+ let x2 = v;
16730
+ while (x2 >= 128) {
16731
+ this.parts.push(x2 & 127 | 128);
16732
+ x2 >>>= 7;
16733
+ }
16734
+ this.parts.push(x2);
16735
+ return;
16736
+ }
16737
+ let x = BigInt.asUintN(64, BigInt(v));
16689
16738
  const b128 = BigInt(128);
16690
16739
  const low7 = BigInt(127);
16691
16740
  const seven = BigInt(7);
@@ -16696,11 +16745,16 @@ var Pb = class {
16696
16745
  this.parts.push(Number(x));
16697
16746
  }
16698
16747
  tag(field, wire) {
16699
- this.varint(BigInt(field << 3 | wire));
16748
+ this.varint(field << 3 | wire);
16700
16749
  }
16701
16750
  uint(field, v) {
16702
16751
  this.tag(field, 0);
16703
- this.varint(BigInt(v));
16752
+ this.varint(v);
16753
+ return this;
16754
+ }
16755
+ fixed32(field, v) {
16756
+ this.tag(field, 5);
16757
+ for (let i = 0; i < 4; i++) this.parts.push(v >>> 8 * i & 255);
16704
16758
  return this;
16705
16759
  }
16706
16760
  fixed64(field, v) {
@@ -16717,10 +16771,16 @@ var Pb = class {
16717
16771
  }
16718
16772
  bytes(field, data) {
16719
16773
  this.tag(field, 2);
16720
- this.varint(BigInt(data.length));
16774
+ this.varint(data.length);
16721
16775
  for (const x of data) this.parts.push(x);
16722
16776
  return this;
16723
16777
  }
16778
+ /** An id given in hex (trace and span ids), as bytes. */
16779
+ hex(field, hex) {
16780
+ const out = [];
16781
+ for (let i = 0; i < hex.length; i += 2) out.push(parseInt(hex.slice(i, i + 2), 16));
16782
+ return this.bytes(field, out);
16783
+ }
16724
16784
  string(field, s) {
16725
16785
  return this.bytes(field, new TextEncoder().encode(s));
16726
16786
  }
@@ -16743,13 +16803,15 @@ function pbAttrs(m, field, a) {
16743
16803
  }
16744
16804
  return m;
16745
16805
  }
16746
- var OtlpLogExporter = class {
16747
- constructor(o) {
16806
+ var OtlpBatcher = class {
16807
+ constructor(o, path, maxBatch) {
16748
16808
  this.o = o;
16809
+ this.path = path;
16810
+ this.maxBatch = maxBatch;
16749
16811
  this.buffer = [];
16750
16812
  this.inflight = Promise.resolve();
16751
16813
  this.timer = null;
16752
- /** Records sent, and records lost because the collector did not take them. */
16814
+ /** Items sent, and items lost because the collector did not take them (or the buffer was full). */
16753
16815
  this.sent = 0;
16754
16816
  this.dropped = 0;
16755
16817
  const every = o.flushMs ?? 5e3;
@@ -16758,19 +16820,60 @@ var OtlpLogExporter = class {
16758
16820
  this.timer.unref?.();
16759
16821
  }
16760
16822
  }
16761
- log(severity, body, attributes = {}) {
16762
- const ms = (this.o.now ?? Date.now)();
16763
- this.buffer.push({ timeUnixNano: `${Math.round(ms)}000000`, severity, body, attributes });
16764
- if (this.buffer.length >= (this.o.maxBatch ?? 50)) void this.flush();
16823
+ push(items) {
16824
+ const room = this.maxBatch * 8 - this.buffer.length;
16825
+ if (room < items.length) this.dropped += items.length - Math.max(room, 0);
16826
+ for (let i = 0; i < Math.min(items.length, Math.max(room, 0)); i++) this.buffer.push(items[i]);
16827
+ if (this.buffer.length >= this.maxBatch) void this.flush();
16828
+ }
16829
+ resource() {
16830
+ return { "service.name": this.o.serviceName, "service.version": this.o.serviceVersion, ...this.o.resource };
16765
16831
  }
16766
16832
  /** Send what is buffered. Never rejects. */
16767
16833
  flush() {
16768
16834
  if (this.buffer.length === 0) return this.inflight;
16769
- const batch = this.buffer;
16770
- this.buffer = [];
16771
- const resource = { "service.name": this.o.serviceName, "service.version": this.o.serviceVersion, ...this.o.resource };
16835
+ const send = this.o.send ?? fetchSend;
16836
+ const url = `${this.o.endpoint.replace(/\/+$/, "")}${this.path}`;
16772
16837
  const protobuf = (this.o.protocol ?? "http/protobuf") === "http/protobuf";
16773
- const body = protobuf ? this.protobuf(resource, batch) : JSON.stringify({
16838
+ const headers = { "Content-Type": protobuf ? "application/x-protobuf" : "application/json", ...this.o.headers ?? {} };
16839
+ while (this.buffer.length > 0) {
16840
+ const batch = this.buffer.splice(0, this.maxBatch);
16841
+ let body;
16842
+ try {
16843
+ body = this.encode(batch, protobuf);
16844
+ } catch {
16845
+ this.dropped += batch.length;
16846
+ continue;
16847
+ }
16848
+ this.inflight = this.inflight.then(
16849
+ () => send(url, body, headers).then(
16850
+ () => void (this.sent += batch.length),
16851
+ () => void (this.dropped += batch.length)
16852
+ )
16853
+ );
16854
+ }
16855
+ return this.inflight;
16856
+ }
16857
+ /** Stop the timer and send what is left. */
16858
+ async close() {
16859
+ if (this.timer) clearInterval(this.timer);
16860
+ this.timer = null;
16861
+ await this.flush();
16862
+ }
16863
+ };
16864
+ var OtlpLogExporter = class extends OtlpBatcher {
16865
+ constructor(o) {
16866
+ super(o, "/v1/logs", o.maxBatch ?? 50);
16867
+ }
16868
+ /** Buffer a record; `context`: the span it was made in (its trace and span id go with it). */
16869
+ log(severity, body, attributes = {}, context) {
16870
+ const ms = (this.o.now ?? Date.now)();
16871
+ this.push([{ timeUnixNano: `${Math.round(ms)}000000`, severity, body, attributes, ...context ? { context } : {} }]);
16872
+ }
16873
+ encode(batch, protobuf) {
16874
+ const resource = this.resource();
16875
+ if (protobuf) return this.protobuf(resource, batch);
16876
+ return JSON.stringify({
16774
16877
  resourceLogs: [
16775
16878
  {
16776
16879
  resource: { attributes: attrs(resource) },
@@ -16783,39 +16886,90 @@ var OtlpLogExporter = class {
16783
16886
  severityNumber: SEVERITY_NUMBER[r.severity],
16784
16887
  severityText: r.severity,
16785
16888
  body: { stringValue: r.body },
16786
- attributes: attrs(r.attributes)
16889
+ attributes: attrs(r.attributes),
16890
+ ...r.context ? { traceId: r.context.traceId, spanId: r.context.spanId, flags: r.context.sampled ? 1 : 0 } : {}
16787
16891
  }))
16788
16892
  }
16789
16893
  ]
16790
16894
  }
16791
16895
  ]
16792
16896
  });
16793
- const url = `${this.o.endpoint.replace(/\/+$/, "")}/v1/logs`;
16794
- const send = this.o.send ?? fetchSend;
16795
- this.inflight = this.inflight.then(
16796
- () => send(url, body, { "Content-Type": protobuf ? "application/x-protobuf" : "application/json", ...this.o.headers ?? {} }).then(
16797
- () => void (this.sent += batch.length),
16798
- () => void (this.dropped += batch.length)
16799
- )
16800
- );
16801
- return this.inflight;
16802
16897
  }
16803
16898
  protobuf(resource, batch) {
16804
16899
  const scope = new Pb().message(1, new Pb().string(1, this.o.serviceName));
16805
16900
  for (const r of batch) {
16806
16901
  const t = BigInt(r.timeUnixNano);
16807
16902
  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));
16808
- pbAttrs(rec, 6, r.attributes).fixed64(11, t);
16903
+ pbAttrs(rec, 6, r.attributes);
16904
+ if (r.context) rec.fixed32(8, r.context.sampled ? 1 : 0).hex(9, r.context.traceId).hex(10, r.context.spanId);
16905
+ rec.fixed64(11, t);
16809
16906
  scope.message(2, rec);
16810
16907
  }
16811
16908
  const resourceLogs = new Pb().message(1, pbAttrs(new Pb(), 1, resource)).message(2, scope);
16812
16909
  return new Pb().message(1, resourceLogs).finish();
16813
16910
  }
16814
- /** Stop the timer and send what is left. */
16815
- async close() {
16816
- if (this.timer) clearInterval(this.timer);
16817
- this.timer = null;
16818
- await this.flush();
16911
+ };
16912
+ var OtlpTraceExporter = class extends OtlpBatcher {
16913
+ constructor(o) {
16914
+ super(o, "/v1/traces", o.maxBatch ?? 512);
16915
+ }
16916
+ /** Buffer finished spans (sent with the next batch). Never throws. */
16917
+ export(spans) {
16918
+ this.push(Array.isArray(spans) ? spans : [spans]);
16919
+ }
16920
+ encode(batch, protobuf) {
16921
+ const resource = this.resource();
16922
+ if (protobuf) return this.protobuf(resource, batch);
16923
+ return JSON.stringify({
16924
+ resourceSpans: [
16925
+ {
16926
+ resource: { attributes: attrs(resource) },
16927
+ scopeSpans: [
16928
+ {
16929
+ scope: { name: this.o.serviceName, ...this.o.serviceVersion ? { version: this.o.serviceVersion } : {} },
16930
+ spans: batch.map((s) => ({
16931
+ traceId: s.traceId,
16932
+ spanId: s.spanId,
16933
+ ...s.parentSpanId ? { parentSpanId: s.parentSpanId } : {},
16934
+ ...s.traceState ? { traceState: s.traceState } : {},
16935
+ flags: 1,
16936
+ name: s.name,
16937
+ kind: SPAN_KIND[s.kind],
16938
+ startTimeUnixNano: unixNano(s.startMs),
16939
+ endTimeUnixNano: unixNano(s.endMs),
16940
+ attributes: attrs(s.attributes),
16941
+ ...s.droppedAttributes ? { droppedAttributesCount: s.droppedAttributes } : {},
16942
+ events: s.events.map((e) => ({ timeUnixNano: unixNano(e.timeMs), name: e.name, attributes: attrs(e.attributes) })),
16943
+ ...s.droppedEvents ? { droppedEventsCount: s.droppedEvents } : {},
16944
+ status: { code: STATUS_CODE[s.status.code], ...s.status.message ? { message: s.status.message } : {} }
16945
+ }))
16946
+ }
16947
+ ]
16948
+ }
16949
+ ]
16950
+ });
16951
+ }
16952
+ protobuf(resource, batch) {
16953
+ const scopeInfo = new Pb().string(1, this.o.serviceName);
16954
+ if (this.o.serviceVersion) scopeInfo.string(2, this.o.serviceVersion);
16955
+ const scope = new Pb().message(1, scopeInfo);
16956
+ for (const s of batch) {
16957
+ const span = new Pb().hex(1, s.traceId).hex(2, s.spanId);
16958
+ if (s.traceState) span.string(3, s.traceState);
16959
+ if (s.parentSpanId) span.hex(4, s.parentSpanId);
16960
+ span.string(5, s.name).uint(6, SPAN_KIND[s.kind]).fixed64(7, BigInt(unixNano(s.startMs))).fixed64(8, BigInt(unixNano(s.endMs)));
16961
+ pbAttrs(span, 9, s.attributes);
16962
+ if (s.droppedAttributes) span.uint(10, s.droppedAttributes);
16963
+ 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));
16964
+ if (s.droppedEvents) span.uint(12, s.droppedEvents);
16965
+ const status = new Pb();
16966
+ if (s.status.message) status.string(2, s.status.message);
16967
+ if (s.status.code !== "unset") status.uint(3, STATUS_CODE[s.status.code]);
16968
+ span.message(15, status).fixed32(16, 1);
16969
+ scope.message(2, span);
16970
+ }
16971
+ const resourceSpans = new Pb().message(1, pbAttrs(new Pb(), 1, resource)).message(2, scope);
16972
+ return new Pb().message(1, resourceSpans).finish();
16819
16973
  }
16820
16974
  };
16821
16975
  function parseOtlpHeaders(text) {
@@ -16837,12 +16991,18 @@ function parseOtlpHeaders(text) {
16837
16991
  var parseResourceAttributes = parseOtlpHeaders;
16838
16992
  var truthy = (v) => (v ?? "").trim().toLowerCase() === "true";
16839
16993
  function otlpFromEnv(env, defaults) {
16840
- if (truthy(env.OTEL_SDK_DISABLED) || (env.OTEL_LOGS_EXPORTER ?? "").trim().toLowerCase() === "none") return null;
16841
- const logs = env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT?.trim();
16994
+ return fromEnv(env, defaults, "LOGS", "logs");
16995
+ }
16996
+ function otlpTracesFromEnv(env, defaults) {
16997
+ return fromEnv(env, defaults, "TRACES", "traces");
16998
+ }
16999
+ function fromEnv(env, defaults, signal, path) {
17000
+ if (truthy(env.OTEL_SDK_DISABLED) || (env[`OTEL_${signal}_EXPORTER`] ?? "").trim().toLowerCase() === "none") return null;
17001
+ const own = env[`OTEL_EXPORTER_OTLP_${signal}_ENDPOINT`]?.trim();
16842
17002
  const base = env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim();
16843
- const endpoint = logs ? logs.replace(/\/v1\/logs\/?$/, "") : base;
17003
+ const endpoint = own ? own.replace(new RegExp(`/v1/${path}/?$`), "") : base;
16844
17004
  if (!endpoint) return null;
16845
- const protocol = otlpProtocol(env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL ?? env.OTEL_EXPORTER_OTLP_PROTOCOL);
17005
+ const protocol = otlpProtocol(env[`OTEL_EXPORTER_OTLP_${signal}_PROTOCOL`] ?? env.OTEL_EXPORTER_OTLP_PROTOCOL);
16846
17006
  const resource = parseResourceAttributes(env.OTEL_RESOURCE_ATTRIBUTES);
16847
17007
  return {
16848
17008
  endpoint,
@@ -16850,14 +17010,139 @@ function otlpFromEnv(env, defaults) {
16850
17010
  ...defaults.serviceVersion ? { serviceVersion: defaults.serviceVersion } : {},
16851
17011
  ...protocol ? { protocol } : {},
16852
17012
  ...Object.keys(resource).length ? { resource } : {},
16853
- headers: { ...parseOtlpHeaders(env.OTEL_EXPORTER_OTLP_HEADERS), ...parseOtlpHeaders(env.OTEL_EXPORTER_OTLP_LOGS_HEADERS) }
17013
+ headers: { ...parseOtlpHeaders(env.OTEL_EXPORTER_OTLP_HEADERS), ...parseOtlpHeaders(env[`OTEL_EXPORTER_OTLP_${signal}_HEADERS`]) }
16854
17014
  };
16855
17015
  }
17016
+ function samplerRatioFromEnv(env) {
17017
+ const sampler = (env.OTEL_TRACES_SAMPLER ?? "").trim().toLowerCase().replace(/^parentbased_/, "");
17018
+ if (sampler === "always_on") return 1;
17019
+ if (sampler === "always_off") return 0;
17020
+ if (sampler !== "traceidratio") return void 0;
17021
+ const arg = Number((env.OTEL_TRACES_SAMPLER_ARG ?? "").trim() || "1");
17022
+ return Number.isFinite(arg) && arg >= 0 && arg <= 1 ? arg : 1;
17023
+ }
16856
17024
  function otlpProtocol(v) {
16857
17025
  const p = (v ?? "").trim().toLowerCase();
16858
17026
  return p === "http/protobuf" || p === "http/json" ? p : void 0;
16859
17027
  }
16860
17028
 
17029
+ // src/api/tracing.ts
17030
+ var TRACEPARENT_HEADER = "traceparent";
17031
+ var TRACESTATE_HEADER = "tracestate";
17032
+ var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
17033
+ function parseTraceparent(traceparent, tracestate) {
17034
+ const m = TRACEPARENT.exec((typeof traceparent === "string" ? traceparent : "").trim().toLowerCase());
17035
+ if (!m) return null;
17036
+ const [, version, traceId, spanId, flags, rest] = m;
17037
+ if (version === "ff" || version === "00" && rest !== void 0) return null;
17038
+ if (/^0+$/.test(traceId) || /^0+$/.test(spanId)) return null;
17039
+ const state = (typeof tracestate === "string" ? tracestate : "").trim();
17040
+ return { traceId, spanId, sampled: (parseInt(flags, 16) & 1) === 1, ...state ? { traceState: state.slice(0, 512) } : {} };
17041
+ }
17042
+ function formatTraceparent(ctx) {
17043
+ return `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
17044
+ }
17045
+ function traceHeaders(ctx) {
17046
+ return { [TRACEPARENT_HEADER]: formatTraceparent(ctx), ...ctx.traceState ? { [TRACESTATE_HEADER]: ctx.traceState } : {} };
17047
+ }
17048
+ function randomHex(bytes) {
17049
+ const b = new Uint8Array(bytes);
17050
+ const c = globalThis.crypto;
17051
+ if (c?.getRandomValues) c.getRandomValues(b);
17052
+ else for (let i = 0; i < bytes; i++) b[i] = Math.floor(Math.random() * 256);
17053
+ const hex = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
17054
+ return /^0+$/.test(hex) ? randomHex(bytes) : hex;
17055
+ }
17056
+ var newTraceId = () => randomHex(16);
17057
+ var newSpanId = () => randomHex(8);
17058
+ var perf = globalThis.performance;
17059
+ var defaultNow = perf ? () => perf.timeOrigin + perf.now() : () => Date.now();
17060
+ var TraceSpan = class {
17061
+ constructor(tracer, name, kind, parent, recording, attributes) {
17062
+ this.tracer = tracer;
17063
+ this.name = name;
17064
+ this.kind = kind;
17065
+ this.parent = parent;
17066
+ this.recording = recording;
17067
+ this.attributes = {};
17068
+ this.events = [];
17069
+ this.status = { code: "unset" };
17070
+ this.ended = false;
17071
+ this.context = {
17072
+ traceId: parent?.traceId ?? newTraceId(),
17073
+ spanId: newSpanId(),
17074
+ sampled: recording,
17075
+ ...parent?.traceState ? { traceState: parent.traceState } : {}
17076
+ };
17077
+ this.startMs = tracer.now();
17078
+ this.setAttributes(attributes);
17079
+ }
17080
+ setAttribute(key, value) {
17081
+ if (value !== void 0 && value !== null) this.attributes[key] = value;
17082
+ return this;
17083
+ }
17084
+ setAttributes(attributes) {
17085
+ for (const k in attributes) this.setAttribute(k, attributes[k]);
17086
+ return this;
17087
+ }
17088
+ addEvent(name, attributes = {}) {
17089
+ this.events.push({ name, timeMs: this.tracer.now(), attributes });
17090
+ return this;
17091
+ }
17092
+ /** An `exception` event, `error.type` and status ERROR. */
17093
+ recordException(e) {
17094
+ const type = e instanceof Error ? e.name : typeof e;
17095
+ const message = e instanceof Error ? e.message : String(e);
17096
+ this.addEvent("exception", { "exception.type": type, "exception.message": message, ...e instanceof Error && e.stack ? { "exception.stacktrace": e.stack.slice(0, 8192) } : {} });
17097
+ if (!("error.type" in this.attributes)) this.attributes["error.type"] = type;
17098
+ return this.setStatus("error", message);
17099
+ }
17100
+ setStatus(code, message) {
17101
+ if (this.status.code === "error" && code !== "error") return this;
17102
+ this.status = code === "error" && message ? { code, message } : { code };
17103
+ return this;
17104
+ }
17105
+ end() {
17106
+ if (this.ended) return;
17107
+ this.ended = true;
17108
+ if (!this.recording) return;
17109
+ this.tracer.send({
17110
+ traceId: this.context.traceId,
17111
+ spanId: this.context.spanId,
17112
+ ...this.parent ? { parentSpanId: this.parent.spanId } : {},
17113
+ ...this.context.traceState ? { traceState: this.context.traceState } : {},
17114
+ name: this.name,
17115
+ kind: this.kind,
17116
+ startMs: this.startMs,
17117
+ endMs: this.tracer.now(),
17118
+ attributes: this.attributes,
17119
+ events: this.events,
17120
+ status: this.status
17121
+ });
17122
+ }
17123
+ };
17124
+ var Tracer = class {
17125
+ constructor(o) {
17126
+ this.o = o;
17127
+ this.now = o.now ?? defaultNow;
17128
+ }
17129
+ /** A new span: a child of `parent` (a context or a `traceparent` header), or a new trace. */
17130
+ startSpan(name, opts = {}) {
17131
+ const parent = typeof opts.parent === "string" ? parseTraceparent(opts.parent) : opts.parent ?? null;
17132
+ const ratio = this.o.sampleRatio ?? 1;
17133
+ const span = new TraceSpan(this, name, opts.kind ?? "internal", parent, true, opts.attributes ?? {});
17134
+ const recording = parent ? parent.sampled : ratio >= 1 || ratio > 0 && parseInt(span.context.traceId.slice(-13), 16) / 2 ** 52 < ratio;
17135
+ return recording ? span : new TraceSpan(this, name, opts.kind ?? "internal", parent ?? { ...span.context, sampled: false }, false, {});
17136
+ }
17137
+ /** @internal */
17138
+ send(span) {
17139
+ try {
17140
+ this.o.export([span]);
17141
+ } catch {
17142
+ }
17143
+ }
17144
+ };
17145
+
16861
17146
  // src/api/client.ts
16862
17147
  var ACTOR_HEADER = "X-Datanotes-Actor";
16863
17148
  var UNREACHABLE = {
@@ -16890,6 +17175,24 @@ function isEngineAnswer(json) {
16890
17175
  const o = json;
16891
17176
  return typeof o.ok === "boolean" || typeof o.error === "string";
16892
17177
  }
17178
+ function clientSpan(tracer, method, url, parent) {
17179
+ let target;
17180
+ try {
17181
+ target = new URL(url);
17182
+ } catch {
17183
+ target = null;
17184
+ }
17185
+ return tracer.startSpan(target ? `${method} ${target.pathname}` : method, {
17186
+ kind: "client",
17187
+ parent,
17188
+ attributes: {
17189
+ "http.request.method": method,
17190
+ "url.full": target ? `${target.protocol}//${target.host}${target.pathname}` : void 0,
17191
+ "server.address": target?.hostname,
17192
+ "server.port": target ? Number(target.port || (target.protocol === "https:" ? 443 : 80)) : void 0
17193
+ }
17194
+ });
17195
+ }
16893
17196
  function parse(text) {
16894
17197
  try {
16895
17198
  return text.trim() ? JSON.parse(text) : void 0;
@@ -16903,11 +17206,22 @@ var DatanotesClient = class {
16903
17206
  this.url = o.url.replace(/\/+$/, "");
16904
17207
  this.send = o.transport ?? fetchTransport;
16905
17208
  }
16906
- /** Send a request; the answer's status, its JSON (when it is JSON) and its text. */
17209
+ /** The parent of a request: the call's own `trace`, else the client's. */
17210
+ parentOf(trace) {
17211
+ const given = trace ?? (typeof this.o.trace === "function" ? this.o.trace() : this.o.trace);
17212
+ return typeof given === "string" ? parseTraceparent(given) : given ?? null;
17213
+ }
17214
+ /**
17215
+ * Send a request; the answer's status, its JSON (when it is JSON) and its text. `trace`: the
17216
+ * trace this request continues (over the client's `trace` option).
17217
+ */
16907
17218
  async request(method, path, body, opts = {}) {
16908
17219
  if (!this.url) throw new DatanotesError("engine address not set", "unreachable");
16909
17220
  if (!this.o.token) throw new DatanotesError("token not set", "auth");
16910
17221
  const actor = opts.actor ?? this.o.actor;
17222
+ const parent = this.parentOf(opts.trace);
17223
+ const span = this.o.tracer ? clientSpan(this.o.tracer, method, `${this.url}${path}`, parent) : void 0;
17224
+ const sent = span?.context ?? parent;
16911
17225
  let res;
16912
17226
  try {
16913
17227
  res = await this.send({
@@ -16917,13 +17231,20 @@ var DatanotesClient = class {
16917
17231
  Authorization: `Bearer ${this.o.token}`,
16918
17232
  ...body !== void 0 ? { "Content-Type": "application/json" } : {},
16919
17233
  ...opts.accept ? { Accept: opts.accept } : {},
16920
- ...actor && Object.keys(actor).length ? { [ACTOR_HEADER]: JSON.stringify(actor) } : {}
17234
+ ...actor && Object.keys(actor).length ? { [ACTOR_HEADER]: JSON.stringify(actor) } : {},
17235
+ ...sent ? traceHeaders(sent) : {}
16921
17236
  },
16922
17237
  ...body !== void 0 ? { body: JSON.stringify(body) } : {}
16923
17238
  });
16924
17239
  } catch (e) {
17240
+ span?.recordException(e);
17241
+ span?.end();
16925
17242
  throw new DatanotesError(`engine unreachable at ${this.url}: ${e instanceof Error ? e.message : String(e)}`, "unreachable");
16926
17243
  }
17244
+ span?.setAttribute("http.response.status_code", res.status);
17245
+ if (res.status >= 400) span?.setAttribute("error.type", String(res.status));
17246
+ if (res.status >= 500) span?.setStatus("error", `HTTP ${res.status}`);
17247
+ span?.end();
16927
17248
  if (res.status === 401) throw new DatanotesError("token refused by the engine", "auth", 401);
16928
17249
  const json = parse(res.text);
16929
17250
  const unreachable = res.status === 0 || res.status === 502 || res.status === 504 || res.status === 503 && !isEngineAnswer(json);
@@ -16941,7 +17262,7 @@ var DatanotesClient = class {
16941
17262
  * Arguments the operation does not take, or of the wrong type, are refused before anything is sent,
16942
17263
  * with the same message the engine gives.
16943
17264
  */
16944
- async call(name, args = {}, actor) {
17265
+ async call(name, args = {}, actor, options = {}) {
16945
17266
  let req;
16946
17267
  try {
16947
17268
  req = operationRequest(name, args);
@@ -16951,7 +17272,7 @@ var DatanotesClient = class {
16951
17272
  }
16952
17273
  const problem = checkArguments(name, args);
16953
17274
  if (problem) return { ok: false, value: guidedText(problem.message, problem) };
16954
- const r = await this.request(req.method, req.path, req.body, actor ? { actor } : {});
17275
+ const r = await this.request(req.method, req.path, req.body, { ...actor ? { actor } : {}, ...options.trace ? { trace: options.trace } : {} });
16955
17276
  return resultOf(r.status, r.json, r.text);
16956
17277
  }
16957
17278
  /** True when the engine answers `GET /` (no token needed). */
@@ -16963,9 +17284,12 @@ var DatanotesClient = class {
16963
17284
  return false;
16964
17285
  }
16965
17286
  }
16966
- /** Record an agent's tool call in the change feed (what MCP servers report). */
17287
+ /**
17288
+ * Record an agent's tool call in the change feed (what MCP servers report). Answers what the
17289
+ * engine said: `takes_summary` when it records a `value` sent cut with its `summary`.
17290
+ */
16967
17291
  async recordToolCall(call, actor) {
16968
- await this.post("/tool-calls/record/", call, actor);
17292
+ return this.post("/tool-calls/record/", call, actor);
16969
17293
  }
16970
17294
  };
16971
17295
  export {
@@ -16977,19 +17301,31 @@ export {
16977
17301
  OPERATIONS,
16978
17302
  OperationInputError,
16979
17303
  OtlpLogExporter,
17304
+ OtlpTraceExporter,
16980
17305
  ROUTE_PREFIX,
17306
+ TRACEPARENT_HEADER,
17307
+ TRACESTATE_HEADER,
17308
+ TraceSpan,
17309
+ Tracer,
16981
17310
  argumentsOf,
16982
17311
  checkArguments,
16983
17312
  describeBatch,
16984
17313
  describeRefusal,
16985
17314
  estimateTokens,
16986
17315
  fetchTransport,
17316
+ formatTraceparent,
16987
17317
  guidanceIn,
16988
17318
  guidedText,
17319
+ newSpanId,
17320
+ newTraceId,
16989
17321
  operationRequest,
16990
17322
  operationRoute,
16991
17323
  otlpFromEnv,
17324
+ otlpTracesFromEnv,
16992
17325
  parseOtlpHeaders,
17326
+ parseTraceparent,
16993
17327
  resultOf,
16994
- toolDocs
17328
+ samplerRatioFromEnv,
17329
+ toolDocs,
17330
+ traceHeaders
16995
17331
  };