datanotes 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +1 -0
  2. package/SECURITY.md +12 -0
  3. package/dist/api/client.d.cts +2 -0
  4. package/dist/api/client.d.ts +2 -0
  5. package/dist/api/docs.d.cts +14 -4
  6. package/dist/api/docs.d.ts +14 -4
  7. package/dist/api/extension-files.d.cts +23 -0
  8. package/dist/api/extension-files.d.ts +23 -0
  9. package/dist/api/extension-host.d.cts +108 -0
  10. package/dist/api/extension-host.d.ts +108 -0
  11. package/dist/api/extension-manifest.d.cts +154 -0
  12. package/dist/api/extension-manifest.d.ts +154 -0
  13. package/dist/api/extension-plan.d.cts +174 -0
  14. package/dist/api/extension-plan.d.ts +174 -0
  15. package/dist/api/extension-record.d.cts +65 -0
  16. package/dist/api/extension-record.d.ts +65 -0
  17. package/dist/api/extension-sdk.d.cts +65 -0
  18. package/dist/api/extension-sdk.d.ts +65 -0
  19. package/dist/api/extensions.cjs +18472 -0
  20. package/dist/api/extensions.d.cts +11 -0
  21. package/dist/api/extensions.d.ts +11 -0
  22. package/dist/api/extensions.js +18409 -0
  23. package/dist/api/index.cjs +371 -366
  24. package/dist/api/index.js +371 -366
  25. package/dist/api/mcp.cjs +28 -5
  26. package/dist/api/mcp.js +28 -5
  27. package/dist/datanotes.cjs +6205 -3421
  28. package/dist/docs/administration/extensions.md +213 -0
  29. package/dist/docs/api/operations/extensions_delete.md +29 -0
  30. package/dist/docs/api/operations/extensions_list.md +20 -0
  31. package/dist/docs/api/operations/extensions_record.md +44 -0
  32. package/dist/docs/api/operations/tags/extensions.md +9 -0
  33. package/dist/docs/api.md +9 -1
  34. package/dist/docs/develop/write-an-extension.md +369 -0
  35. package/dist/docs/guides/data-quality/check-constraints.md +10 -10
  36. package/dist/docs/guides/data-quality/hand-edits.md +8 -8
  37. package/dist/docs/guides/database-objects/bases.md +11 -11
  38. package/dist/docs/guides/database-objects/catalogs-and-schemas.md +10 -10
  39. package/dist/docs/guides/database-objects/columns.md +38 -38
  40. package/dist/docs/guides/database-objects/relations.md +28 -28
  41. package/dist/docs/guides/database-objects/tables.md +28 -28
  42. package/dist/docs/guides/database-objects/views.md +44 -44
  43. package/dist/docs/guides/history/change-data-feed.md +34 -34
  44. package/dist/docs/guides/history/journal-and-undo.md +12 -12
  45. package/dist/docs/guides/history/restore.md +20 -20
  46. package/dist/docs/guides/history/table-history.md +31 -31
  47. package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
  48. package/dist/docs/guides/read-and-write/import-notes.md +20 -20
  49. package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
  50. package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
  51. package/dist/docs/guides/read-and-write/write-rows.md +10 -10
  52. package/dist/docs/guides/search/text.md +1 -1
  53. package/dist/docs/guides/security/security-model.md +12 -0
  54. package/dist/docs/reference/cli.md +32 -1
  55. package/dist/docs/reference/glossary.md +8 -0
  56. package/dist/docs/release-notes.md +33 -0
  57. package/dist/docs/start/connect-agents.md +11 -0
  58. package/package.json +11 -1
package/dist/api/index.js CHANGED
@@ -16867,125 +16867,397 @@ function classOf(cp) {
16867
16867
  return k;
16868
16868
  }
16869
16869
 
16870
- // src/api/otlp.ts
16871
- var SEVERITY_NUMBER = { DEBUG: 5, INFO: 9, WARN: 13, ERROR: 17 };
16872
- var SPAN_KIND = { internal: 1, server: 2, client: 3, producer: 4, consumer: 5 };
16873
- var STATUS_CODE = { unset: 0, ok: 1, error: 2 };
16874
- function attr(key, v) {
16875
- if (v === void 0 || v === null) return null;
16876
- if (typeof v === "boolean") return { key, value: { boolValue: v } };
16877
- if (typeof v === "number") return Number.isInteger(v) ? { key, value: { intValue: String(v) } } : { key, value: { doubleValue: v } };
16878
- return { key, value: { stringValue: v } };
16870
+ // src/api/tracing.ts
16871
+ var TRACEPARENT_HEADER = "traceparent";
16872
+ var TRACESTATE_HEADER = "tracestate";
16873
+ var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
16874
+ function parseTraceparent(traceparent, tracestate) {
16875
+ const m = TRACEPARENT.exec((typeof traceparent === "string" ? traceparent : "").trim().toLowerCase());
16876
+ if (!m) return null;
16877
+ const [, version, traceId, spanId, flags, rest] = m;
16878
+ if (version === "ff" || version === "00" && rest !== void 0) return null;
16879
+ if (/^0+$/.test(traceId) || /^0+$/.test(spanId)) return null;
16880
+ const state = (typeof tracestate === "string" ? tracestate : "").trim();
16881
+ return { traceId, spanId, sampled: (parseInt(flags, 16) & 1) === 1, ...state ? { traceState: state.slice(0, 512) } : {} };
16879
16882
  }
16880
- var attrs = (a) => Object.entries(a).map(([k, v]) => attr(k, v)).filter((x) => x !== null);
16881
- var fetchSend = async (url, body, headers) => {
16882
- const res = await fetch(url, { method: "POST", headers, body });
16883
- if (!res.ok) throw new Error(`OTLP HTTP ${res.status}`);
16884
- };
16885
- function unixNano(ms) {
16886
- const whole = Math.floor(ms);
16887
- const frac = Math.round((ms - whole) * 1e6);
16888
- return (BigInt(whole) * BigInt(1e6) + BigInt(frac)).toString();
16883
+ function formatTraceparent(ctx) {
16884
+ return `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
16889
16885
  }
16890
- var Pb = class {
16891
- constructor() {
16892
- this.parts = [];
16893
- }
16894
- varint(v) {
16895
- if (typeof v === "number" && v >= 0 && v < 2 ** 31) {
16896
- let x2 = v;
16897
- while (x2 >= 128) {
16898
- this.parts.push(x2 & 127 | 128);
16899
- x2 >>>= 7;
16900
- }
16901
- this.parts.push(x2);
16902
- return;
16903
- }
16904
- let x = BigInt.asUintN(64, BigInt(v));
16905
- const b128 = BigInt(128);
16906
- const low7 = BigInt(127);
16907
- const seven = BigInt(7);
16908
- while (x >= b128) {
16909
- this.parts.push(Number(x & low7) | 128);
16910
- x >>= seven;
16911
- }
16912
- this.parts.push(Number(x));
16913
- }
16914
- tag(field, wire) {
16915
- this.varint(field << 3 | wire);
16886
+ function traceHeaders(ctx) {
16887
+ return { [TRACEPARENT_HEADER]: formatTraceparent(ctx), ...ctx.traceState ? { [TRACESTATE_HEADER]: ctx.traceState } : {} };
16888
+ }
16889
+ function randomHex(bytes) {
16890
+ const b = new Uint8Array(bytes);
16891
+ const c = globalThis.crypto;
16892
+ if (c?.getRandomValues) c.getRandomValues(b);
16893
+ else for (let i = 0; i < bytes; i++) b[i] = Math.floor(Math.random() * 256);
16894
+ const hex = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
16895
+ return /^0+$/.test(hex) ? randomHex(bytes) : hex;
16896
+ }
16897
+ var newTraceId = () => randomHex(16);
16898
+ var newSpanId = () => randomHex(8);
16899
+ var perf = globalThis.performance;
16900
+ var defaultNow = perf ? () => perf.timeOrigin + perf.now() : () => Date.now();
16901
+ var TraceSpan = class {
16902
+ constructor(tracer, name, kind, parent, recording, attributes) {
16903
+ this.tracer = tracer;
16904
+ this.name = name;
16905
+ this.kind = kind;
16906
+ this.parent = parent;
16907
+ this.recording = recording;
16908
+ this.attributes = {};
16909
+ this.events = [];
16910
+ this.status = { code: "unset" };
16911
+ this.ended = false;
16912
+ this.context = {
16913
+ traceId: parent?.traceId ?? newTraceId(),
16914
+ spanId: newSpanId(),
16915
+ sampled: recording,
16916
+ ...parent?.traceState ? { traceState: parent.traceState } : {}
16917
+ };
16918
+ this.startMs = tracer.now();
16919
+ this.setAttributes(attributes);
16916
16920
  }
16917
- uint(field, v) {
16918
- this.tag(field, 0);
16919
- this.varint(v);
16921
+ setAttribute(key, value) {
16922
+ if (value !== void 0 && value !== null) this.attributes[key] = value;
16920
16923
  return this;
16921
16924
  }
16922
- fixed32(field, v) {
16923
- this.tag(field, 5);
16924
- for (let i = 0; i < 4; i++) this.parts.push(v >>> 8 * i & 255);
16925
+ setAttributes(attributes) {
16926
+ for (const k in attributes) this.setAttribute(k, attributes[k]);
16925
16927
  return this;
16926
16928
  }
16927
- fixed64(field, v) {
16928
- this.tag(field, 1);
16929
- for (let i = 0; i < 8; i++) this.parts.push(Number(v >> BigInt(8 * i) & BigInt(255)));
16929
+ addEvent(name, attributes = {}) {
16930
+ this.events.push({ name, timeMs: this.tracer.now(), attributes });
16930
16931
  return this;
16931
16932
  }
16932
- double(field, v) {
16933
- this.tag(field, 1);
16934
- const b = new DataView(new ArrayBuffer(8));
16935
- b.setFloat64(0, v, true);
16936
- for (let i = 0; i < 8; i++) this.parts.push(b.getUint8(i));
16937
- return this;
16933
+ /** An `exception` event, `error.type` and status ERROR. */
16934
+ recordException(e) {
16935
+ const type = e instanceof Error ? e.name : typeof e;
16936
+ const message = e instanceof Error ? e.message : String(e);
16937
+ this.addEvent("exception", { "exception.type": type, "exception.message": message, ...e instanceof Error && e.stack ? { "exception.stacktrace": e.stack.slice(0, 8192) } : {} });
16938
+ if (!("error.type" in this.attributes)) this.attributes["error.type"] = type;
16939
+ return this.setStatus("error", message);
16938
16940
  }
16939
- bytes(field, data) {
16940
- this.tag(field, 2);
16941
- this.varint(data.length);
16942
- for (const x of data) this.parts.push(x);
16941
+ setStatus(code, message) {
16942
+ if (this.status.code === "error" && code !== "error") return this;
16943
+ this.status = code === "error" && message ? { code, message } : { code };
16943
16944
  return this;
16944
16945
  }
16945
- /** An id given in hex (trace and span ids), as bytes. */
16946
- hex(field, hex) {
16947
- const out = [];
16948
- for (let i = 0; i < hex.length; i += 2) out.push(parseInt(hex.slice(i, i + 2), 16));
16949
- return this.bytes(field, out);
16946
+ end() {
16947
+ if (this.ended) return;
16948
+ this.ended = true;
16949
+ if (!this.recording) return;
16950
+ this.tracer.send({
16951
+ traceId: this.context.traceId,
16952
+ spanId: this.context.spanId,
16953
+ ...this.parent ? { parentSpanId: this.parent.spanId } : {},
16954
+ ...this.context.traceState ? { traceState: this.context.traceState } : {},
16955
+ name: this.name,
16956
+ kind: this.kind,
16957
+ startMs: this.startMs,
16958
+ endMs: this.tracer.now(),
16959
+ attributes: this.attributes,
16960
+ events: this.events,
16961
+ status: this.status
16962
+ });
16950
16963
  }
16951
- string(field, s) {
16952
- return this.bytes(field, new TextEncoder().encode(s));
16964
+ };
16965
+ var Tracer = class {
16966
+ constructor(o) {
16967
+ this.o = o;
16968
+ this.now = o.now ?? defaultNow;
16953
16969
  }
16954
- message(field, m) {
16955
- return this.bytes(field, m.finish());
16970
+ /** A new span: a child of `parent` (a context or a `traceparent` header), or a new trace. */
16971
+ startSpan(name, opts = {}) {
16972
+ const parent = typeof opts.parent === "string" ? parseTraceparent(opts.parent) : opts.parent ?? null;
16973
+ const ratio = this.o.sampleRatio ?? 1;
16974
+ const span = new TraceSpan(this, name, opts.kind ?? "internal", parent, true, opts.attributes ?? {});
16975
+ const recording = parent ? parent.sampled : ratio >= 1 || ratio > 0 && parseInt(span.context.traceId.slice(-13), 16) / 2 ** 52 < ratio;
16976
+ return recording ? span : new TraceSpan(this, name, opts.kind ?? "internal", parent ?? { ...span.context, sampled: false }, false, {});
16956
16977
  }
16957
- finish() {
16958
- return Uint8Array.from(this.parts);
16978
+ /** @internal */
16979
+ send(span) {
16980
+ try {
16981
+ this.o.export([span]);
16982
+ } catch {
16983
+ }
16959
16984
  }
16960
16985
  };
16961
- function pbValue(v) {
16962
- if (typeof v === "string") return new Pb().string(1, v);
16963
- if (typeof v === "boolean") return new Pb().uint(2, v ? 1 : 0);
16964
- return Number.isInteger(v) ? new Pb().uint(3, BigInt(v)) : new Pb().double(4, v);
16986
+
16987
+ // src/api/client.ts
16988
+ var ACTOR_HEADER = "X-Datanotes-Actor";
16989
+ var UNREACHABLE = {
16990
+ hint: "Start the engine (datanotes serve --database <folder>) or check its address; datanotes status --database <folder> shows whether it runs and where.",
16991
+ docs: `${DOCS_BASE}/start/connect-agents.md#how-the-mcp-server-reaches-the-engine`
16992
+ };
16993
+ var AUTH = {
16994
+ hint: "Send the engine's owner token (httpServerToken in settings.json in the engine's store: datanotes store path shows where) or a named token the owner made with POST /datanotes/tokens/create/, as Authorization: Bearer <token>.",
16995
+ docs: `${DOCS_BASE}/develop/http-api.md#authenticate-your-requests`
16996
+ };
16997
+ var DatanotesError = class extends Error {
16998
+ /** `unreachable`: the engine did not answer; `auth`: the token was refused. */
16999
+ constructor(message, kind = "http", status = 0, guidance = kind === "unreachable" ? UNREACHABLE : kind === "auth" ? AUTH : null) {
17000
+ super(guidedText(message, guidance));
17001
+ this.kind = kind;
17002
+ this.status = status;
17003
+ this.name = "DatanotesError";
17004
+ if (guidance) {
17005
+ this.hint = guidance.hint;
17006
+ this.docs = guidance.docs;
17007
+ }
17008
+ }
17009
+ };
17010
+ var fetchTransport = async (req) => {
17011
+ const res = await fetch(req.url, { method: req.method, headers: req.headers, ...req.body !== void 0 ? { body: req.body } : {} });
17012
+ return { status: res.status, text: await res.text() };
17013
+ };
17014
+ function isEngineAnswer(json) {
17015
+ if (json === null || typeof json !== "object" || Array.isArray(json)) return false;
17016
+ const o = json;
17017
+ return typeof o.ok === "boolean" || typeof o.error === "string";
16965
17018
  }
16966
- function pbAttrs(m, field, a) {
16967
- for (const [k, v] of Object.entries(a)) {
16968
- if (v === void 0 || v === null) continue;
16969
- m.message(field, new Pb().string(1, k).message(2, pbValue(v)));
17019
+ function clientSpan(tracer, method, url, parent) {
17020
+ let target;
17021
+ try {
17022
+ target = new URL(url);
17023
+ } catch {
17024
+ target = null;
16970
17025
  }
16971
- return m;
17026
+ return tracer.startSpan(target ? `${method} ${target.pathname}` : method, {
17027
+ kind: "client",
17028
+ parent,
17029
+ attributes: {
17030
+ "http.request.method": method,
17031
+ "url.full": target ? `${target.protocol}//${target.host}${target.pathname}` : void 0,
17032
+ "server.address": target?.hostname,
17033
+ "server.port": target ? Number(target.port || (target.protocol === "https:" ? 443 : 80)) : void 0
17034
+ }
17035
+ });
16972
17036
  }
16973
- var OtlpBatcher = class {
16974
- constructor(o, path, maxBatch) {
17037
+ function parse(text) {
17038
+ try {
17039
+ return text.trim() ? JSON.parse(text) : void 0;
17040
+ } catch {
17041
+ return void 0;
17042
+ }
17043
+ }
17044
+ function trimTrailingSlashes(s) {
17045
+ let end = s.length;
17046
+ while (end > 0 && s.charCodeAt(end - 1) === 47) end--;
17047
+ return end === s.length ? s : s.slice(0, end);
17048
+ }
17049
+ var DatanotesClient = class {
17050
+ constructor(o) {
16975
17051
  this.o = o;
16976
- this.path = path;
16977
- this.maxBatch = maxBatch;
16978
- this.buffer = [];
16979
- this.inflight = Promise.resolve();
16980
- this.timer = null;
16981
- /** Items sent, and items lost because the collector did not take them (or the buffer was full). */
16982
- this.sent = 0;
16983
- this.dropped = 0;
16984
- const every = o.flushMs ?? 5e3;
16985
- if (every > 0) {
16986
- this.timer = setInterval(() => void this.flush(), every);
16987
- this.timer.unref?.();
16988
- }
17052
+ this.url = trimTrailingSlashes(o.url);
17053
+ this.send = o.transport ?? fetchTransport;
17054
+ }
17055
+ /** The parent of a request: the call's own `trace`, else the client's. */
17056
+ parentOf(trace) {
17057
+ const given = trace ?? (typeof this.o.trace === "function" ? this.o.trace() : this.o.trace);
17058
+ return typeof given === "string" ? parseTraceparent(given) : given ?? null;
17059
+ }
17060
+ /**
17061
+ * Send a request; the answer's status, its JSON (when it is JSON) and its text. `trace`: the
17062
+ * trace this request continues (over the client's `trace` option).
17063
+ */
17064
+ async request(method, path, body, opts = {}) {
17065
+ if (!this.url) throw new DatanotesError("engine address not set", "unreachable");
17066
+ if (!this.o.token) throw new DatanotesError("token not set", "auth");
17067
+ const actor = opts.actor ?? this.o.actor;
17068
+ const parent = this.parentOf(opts.trace);
17069
+ const span = this.o.tracer ? clientSpan(this.o.tracer, method, `${this.url}${path}`, parent) : void 0;
17070
+ const sent = span?.context ?? parent;
17071
+ let res;
17072
+ try {
17073
+ res = await this.send({
17074
+ url: `${this.url}${path}`,
17075
+ method,
17076
+ headers: {
17077
+ Authorization: `Bearer ${this.o.token}`,
17078
+ ...body !== void 0 ? { "Content-Type": "application/json" } : {},
17079
+ ...opts.accept ? { Accept: opts.accept } : {},
17080
+ ...actor && Object.keys(actor).length ? { [ACTOR_HEADER]: JSON.stringify(actor) } : {},
17081
+ ...sent ? traceHeaders(sent) : {}
17082
+ },
17083
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
17084
+ });
17085
+ } catch (e) {
17086
+ span?.recordException(e);
17087
+ span?.end();
17088
+ throw new DatanotesError(`engine unreachable at ${this.url}: ${e instanceof Error ? e.message : String(e)}`, "unreachable");
17089
+ }
17090
+ span?.setAttribute("http.response.status_code", res.status);
17091
+ if (res.status >= 400) span?.setAttribute("error.type", String(res.status));
17092
+ if (res.status >= 500) span?.setStatus("error", `HTTP ${res.status}`);
17093
+ span?.end();
17094
+ if (res.status === 401) throw new DatanotesError("token refused by the engine", "auth", 401);
17095
+ const json = parse(res.text);
17096
+ const unreachable = res.status === 0 || res.status === 502 || res.status === 504 || res.status === 503 && !isEngineAnswer(json);
17097
+ if (unreachable) throw new DatanotesError(`engine unreachable at ${this.url} (HTTP ${res.status})`, "unreachable", res.status);
17098
+ return { status: res.status, json, text: res.text };
17099
+ }
17100
+ /** `POST /datanotes/<route>` and its JSON answer; throws on an error status. */
17101
+ async post(route, body = {}, actor) {
17102
+ const r = await this.request("POST", `/datanotes${route}`, body, actor ? { actor } : {});
17103
+ if (r.status >= 400) throw Object.assign(new DatanotesError(resultOf(r.status, r.json, r.text).value, "http", r.status), guidanceIn(r.json));
17104
+ return r.json;
17105
+ }
17106
+ /**
17107
+ * Run an operation of the catalogue (`select_rows`, `insert_row`, …) with an agent's arguments.
17108
+ * Arguments the operation does not take, or of the wrong type, are refused before anything is sent,
17109
+ * with the same message the engine gives.
17110
+ */
17111
+ async call(name, args = {}, actor, options = {}) {
17112
+ let req;
17113
+ try {
17114
+ req = operationRequest(name, args);
17115
+ } catch (e) {
17116
+ if (e instanceof OperationInputError) return { ok: false, value: e.message };
17117
+ throw e;
17118
+ }
17119
+ const problem = checkArguments(name, args);
17120
+ if (problem) return { ok: false, value: guidedText(problem.message, problem) };
17121
+ const r = await this.request(req.method, req.path, req.body, { ...actor ? { actor } : {}, ...options.trace ? { trace: options.trace } : {} });
17122
+ return resultOf(r.status, r.json, r.text);
17123
+ }
17124
+ /** True when the engine answers `GET /` (no token needed). */
17125
+ async ping() {
17126
+ try {
17127
+ const r = await this.send({ url: `${this.url}/`, method: "GET", headers: {} });
17128
+ return r.status === 200;
17129
+ } catch {
17130
+ return false;
17131
+ }
17132
+ }
17133
+ /**
17134
+ * Record an agent's tool call in the change feed (what MCP servers report). Answers what the
17135
+ * engine said: `takes_summary` when it records a `value` sent cut with its `summary`.
17136
+ */
17137
+ async recordToolCall(call, actor) {
17138
+ return this.post("/tool-calls/record/", call, actor);
17139
+ }
17140
+ };
17141
+
17142
+ // src/api/otlp.ts
17143
+ var SEVERITY_NUMBER = { DEBUG: 5, INFO: 9, WARN: 13, ERROR: 17 };
17144
+ var SPAN_KIND = { internal: 1, server: 2, client: 3, producer: 4, consumer: 5 };
17145
+ var STATUS_CODE = { unset: 0, ok: 1, error: 2 };
17146
+ function attr(key, v) {
17147
+ if (v === void 0 || v === null) return null;
17148
+ if (typeof v === "boolean") return { key, value: { boolValue: v } };
17149
+ if (typeof v === "number") return Number.isInteger(v) ? { key, value: { intValue: String(v) } } : { key, value: { doubleValue: v } };
17150
+ return { key, value: { stringValue: v } };
17151
+ }
17152
+ var attrs = (a) => Object.entries(a).map(([k, v]) => attr(k, v)).filter((x) => x !== null);
17153
+ var fetchSend = async (url, body, headers) => {
17154
+ const res = await fetch(url, { method: "POST", headers, body });
17155
+ if (!res.ok) throw new Error(`OTLP HTTP ${res.status}`);
17156
+ };
17157
+ function unixNano(ms) {
17158
+ const whole = Math.floor(ms);
17159
+ const frac = Math.round((ms - whole) * 1e6);
17160
+ return (BigInt(whole) * BigInt(1e6) + BigInt(frac)).toString();
17161
+ }
17162
+ var Pb = class {
17163
+ constructor() {
17164
+ this.parts = [];
17165
+ }
17166
+ varint(v) {
17167
+ if (typeof v === "number" && v >= 0 && v < 2 ** 31) {
17168
+ let x2 = v;
17169
+ while (x2 >= 128) {
17170
+ this.parts.push(x2 & 127 | 128);
17171
+ x2 >>>= 7;
17172
+ }
17173
+ this.parts.push(x2);
17174
+ return;
17175
+ }
17176
+ let x = BigInt.asUintN(64, BigInt(v));
17177
+ const b128 = BigInt(128);
17178
+ const low7 = BigInt(127);
17179
+ const seven = BigInt(7);
17180
+ while (x >= b128) {
17181
+ this.parts.push(Number(x & low7) | 128);
17182
+ x >>= seven;
17183
+ }
17184
+ this.parts.push(Number(x));
17185
+ }
17186
+ tag(field, wire) {
17187
+ this.varint(field << 3 | wire);
17188
+ }
17189
+ uint(field, v) {
17190
+ this.tag(field, 0);
17191
+ this.varint(v);
17192
+ return this;
17193
+ }
17194
+ fixed32(field, v) {
17195
+ this.tag(field, 5);
17196
+ for (let i = 0; i < 4; i++) this.parts.push(v >>> 8 * i & 255);
17197
+ return this;
17198
+ }
17199
+ fixed64(field, v) {
17200
+ this.tag(field, 1);
17201
+ for (let i = 0; i < 8; i++) this.parts.push(Number(v >> BigInt(8 * i) & BigInt(255)));
17202
+ return this;
17203
+ }
17204
+ double(field, v) {
17205
+ this.tag(field, 1);
17206
+ const b = new DataView(new ArrayBuffer(8));
17207
+ b.setFloat64(0, v, true);
17208
+ for (let i = 0; i < 8; i++) this.parts.push(b.getUint8(i));
17209
+ return this;
17210
+ }
17211
+ bytes(field, data) {
17212
+ this.tag(field, 2);
17213
+ this.varint(data.length);
17214
+ for (const x of data) this.parts.push(x);
17215
+ return this;
17216
+ }
17217
+ /** An id given in hex (trace and span ids), as bytes. */
17218
+ hex(field, hex) {
17219
+ const out = [];
17220
+ for (let i = 0; i < hex.length; i += 2) out.push(parseInt(hex.slice(i, i + 2), 16));
17221
+ return this.bytes(field, out);
17222
+ }
17223
+ string(field, s) {
17224
+ return this.bytes(field, new TextEncoder().encode(s));
17225
+ }
17226
+ message(field, m) {
17227
+ return this.bytes(field, m.finish());
17228
+ }
17229
+ finish() {
17230
+ return Uint8Array.from(this.parts);
17231
+ }
17232
+ };
17233
+ function pbValue(v) {
17234
+ if (typeof v === "string") return new Pb().string(1, v);
17235
+ if (typeof v === "boolean") return new Pb().uint(2, v ? 1 : 0);
17236
+ return Number.isInteger(v) ? new Pb().uint(3, BigInt(v)) : new Pb().double(4, v);
17237
+ }
17238
+ function pbAttrs(m, field, a) {
17239
+ for (const [k, v] of Object.entries(a)) {
17240
+ if (v === void 0 || v === null) continue;
17241
+ m.message(field, new Pb().string(1, k).message(2, pbValue(v)));
17242
+ }
17243
+ return m;
17244
+ }
17245
+ var OtlpBatcher = class {
17246
+ constructor(o, path, maxBatch) {
17247
+ this.o = o;
17248
+ this.path = path;
17249
+ this.maxBatch = maxBatch;
17250
+ this.buffer = [];
17251
+ this.inflight = Promise.resolve();
17252
+ this.timer = null;
17253
+ /** Items sent, and items lost because the collector did not take them (or the buffer was full). */
17254
+ this.sent = 0;
17255
+ this.dropped = 0;
17256
+ const every = o.flushMs ?? 5e3;
17257
+ if (every > 0) {
17258
+ this.timer = setInterval(() => void this.flush(), every);
17259
+ this.timer.unref?.();
17260
+ }
16989
17261
  }
16990
17262
  push(items) {
16991
17263
  const room = this.maxBatch * 8 - this.buffer.length;
@@ -17000,7 +17272,7 @@ var OtlpBatcher = class {
17000
17272
  flush() {
17001
17273
  if (this.buffer.length === 0) return this.inflight;
17002
17274
  const send = this.o.send ?? fetchSend;
17003
- const url = `${this.o.endpoint.replace(/\/+$/, "")}${this.path}`;
17275
+ const url = `${trimTrailingSlashes(this.o.endpoint)}${this.path}`;
17004
17276
  const protobuf = (this.o.protocol ?? "http/protobuf") === "http/protobuf";
17005
17277
  const headers = { "Content-Type": protobuf ? "application/x-protobuf" : "application/json", ...this.o.headers ?? {} };
17006
17278
  while (this.buffer.length > 0) {
@@ -17192,273 +17464,6 @@ function otlpProtocol(v) {
17192
17464
  const p = (v ?? "").trim().toLowerCase();
17193
17465
  return p === "http/protobuf" || p === "http/json" ? p : void 0;
17194
17466
  }
17195
-
17196
- // src/api/tracing.ts
17197
- var TRACEPARENT_HEADER = "traceparent";
17198
- var TRACESTATE_HEADER = "tracestate";
17199
- var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
17200
- function parseTraceparent(traceparent, tracestate) {
17201
- const m = TRACEPARENT.exec((typeof traceparent === "string" ? traceparent : "").trim().toLowerCase());
17202
- if (!m) return null;
17203
- const [, version, traceId, spanId, flags, rest] = m;
17204
- if (version === "ff" || version === "00" && rest !== void 0) return null;
17205
- if (/^0+$/.test(traceId) || /^0+$/.test(spanId)) return null;
17206
- const state = (typeof tracestate === "string" ? tracestate : "").trim();
17207
- return { traceId, spanId, sampled: (parseInt(flags, 16) & 1) === 1, ...state ? { traceState: state.slice(0, 512) } : {} };
17208
- }
17209
- function formatTraceparent(ctx) {
17210
- return `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
17211
- }
17212
- function traceHeaders(ctx) {
17213
- return { [TRACEPARENT_HEADER]: formatTraceparent(ctx), ...ctx.traceState ? { [TRACESTATE_HEADER]: ctx.traceState } : {} };
17214
- }
17215
- function randomHex(bytes) {
17216
- const b = new Uint8Array(bytes);
17217
- const c = globalThis.crypto;
17218
- if (c?.getRandomValues) c.getRandomValues(b);
17219
- else for (let i = 0; i < bytes; i++) b[i] = Math.floor(Math.random() * 256);
17220
- const hex = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
17221
- return /^0+$/.test(hex) ? randomHex(bytes) : hex;
17222
- }
17223
- var newTraceId = () => randomHex(16);
17224
- var newSpanId = () => randomHex(8);
17225
- var perf = globalThis.performance;
17226
- var defaultNow = perf ? () => perf.timeOrigin + perf.now() : () => Date.now();
17227
- var TraceSpan = class {
17228
- constructor(tracer, name, kind, parent, recording, attributes) {
17229
- this.tracer = tracer;
17230
- this.name = name;
17231
- this.kind = kind;
17232
- this.parent = parent;
17233
- this.recording = recording;
17234
- this.attributes = {};
17235
- this.events = [];
17236
- this.status = { code: "unset" };
17237
- this.ended = false;
17238
- this.context = {
17239
- traceId: parent?.traceId ?? newTraceId(),
17240
- spanId: newSpanId(),
17241
- sampled: recording,
17242
- ...parent?.traceState ? { traceState: parent.traceState } : {}
17243
- };
17244
- this.startMs = tracer.now();
17245
- this.setAttributes(attributes);
17246
- }
17247
- setAttribute(key, value) {
17248
- if (value !== void 0 && value !== null) this.attributes[key] = value;
17249
- return this;
17250
- }
17251
- setAttributes(attributes) {
17252
- for (const k in attributes) this.setAttribute(k, attributes[k]);
17253
- return this;
17254
- }
17255
- addEvent(name, attributes = {}) {
17256
- this.events.push({ name, timeMs: this.tracer.now(), attributes });
17257
- return this;
17258
- }
17259
- /** An `exception` event, `error.type` and status ERROR. */
17260
- recordException(e) {
17261
- const type = e instanceof Error ? e.name : typeof e;
17262
- const message = e instanceof Error ? e.message : String(e);
17263
- this.addEvent("exception", { "exception.type": type, "exception.message": message, ...e instanceof Error && e.stack ? { "exception.stacktrace": e.stack.slice(0, 8192) } : {} });
17264
- if (!("error.type" in this.attributes)) this.attributes["error.type"] = type;
17265
- return this.setStatus("error", message);
17266
- }
17267
- setStatus(code, message) {
17268
- if (this.status.code === "error" && code !== "error") return this;
17269
- this.status = code === "error" && message ? { code, message } : { code };
17270
- return this;
17271
- }
17272
- end() {
17273
- if (this.ended) return;
17274
- this.ended = true;
17275
- if (!this.recording) return;
17276
- this.tracer.send({
17277
- traceId: this.context.traceId,
17278
- spanId: this.context.spanId,
17279
- ...this.parent ? { parentSpanId: this.parent.spanId } : {},
17280
- ...this.context.traceState ? { traceState: this.context.traceState } : {},
17281
- name: this.name,
17282
- kind: this.kind,
17283
- startMs: this.startMs,
17284
- endMs: this.tracer.now(),
17285
- attributes: this.attributes,
17286
- events: this.events,
17287
- status: this.status
17288
- });
17289
- }
17290
- };
17291
- var Tracer = class {
17292
- constructor(o) {
17293
- this.o = o;
17294
- this.now = o.now ?? defaultNow;
17295
- }
17296
- /** A new span: a child of `parent` (a context or a `traceparent` header), or a new trace. */
17297
- startSpan(name, opts = {}) {
17298
- const parent = typeof opts.parent === "string" ? parseTraceparent(opts.parent) : opts.parent ?? null;
17299
- const ratio = this.o.sampleRatio ?? 1;
17300
- const span = new TraceSpan(this, name, opts.kind ?? "internal", parent, true, opts.attributes ?? {});
17301
- const recording = parent ? parent.sampled : ratio >= 1 || ratio > 0 && parseInt(span.context.traceId.slice(-13), 16) / 2 ** 52 < ratio;
17302
- return recording ? span : new TraceSpan(this, name, opts.kind ?? "internal", parent ?? { ...span.context, sampled: false }, false, {});
17303
- }
17304
- /** @internal */
17305
- send(span) {
17306
- try {
17307
- this.o.export([span]);
17308
- } catch {
17309
- }
17310
- }
17311
- };
17312
-
17313
- // src/api/client.ts
17314
- var ACTOR_HEADER = "X-Datanotes-Actor";
17315
- var UNREACHABLE = {
17316
- hint: "Start the engine (datanotes serve --database <folder>) or check its address; datanotes status --database <folder> shows whether it runs and where.",
17317
- docs: `${DOCS_BASE}/start/connect-agents.md#how-the-mcp-server-reaches-the-engine`
17318
- };
17319
- var AUTH = {
17320
- hint: "Send the engine's owner token (httpServerToken in settings.json in the engine's store: datanotes store path shows where) or a named token the owner made with POST /datanotes/tokens/create/, as Authorization: Bearer <token>.",
17321
- docs: `${DOCS_BASE}/develop/http-api.md#authenticate-your-requests`
17322
- };
17323
- var DatanotesError = class extends Error {
17324
- /** `unreachable`: the engine did not answer; `auth`: the token was refused. */
17325
- constructor(message, kind = "http", status = 0, guidance = kind === "unreachable" ? UNREACHABLE : kind === "auth" ? AUTH : null) {
17326
- super(guidedText(message, guidance));
17327
- this.kind = kind;
17328
- this.status = status;
17329
- this.name = "DatanotesError";
17330
- if (guidance) {
17331
- this.hint = guidance.hint;
17332
- this.docs = guidance.docs;
17333
- }
17334
- }
17335
- };
17336
- var fetchTransport = async (req) => {
17337
- const res = await fetch(req.url, { method: req.method, headers: req.headers, ...req.body !== void 0 ? { body: req.body } : {} });
17338
- return { status: res.status, text: await res.text() };
17339
- };
17340
- function isEngineAnswer(json) {
17341
- if (json === null || typeof json !== "object" || Array.isArray(json)) return false;
17342
- const o = json;
17343
- return typeof o.ok === "boolean" || typeof o.error === "string";
17344
- }
17345
- function clientSpan(tracer, method, url, parent) {
17346
- let target;
17347
- try {
17348
- target = new URL(url);
17349
- } catch {
17350
- target = null;
17351
- }
17352
- return tracer.startSpan(target ? `${method} ${target.pathname}` : method, {
17353
- kind: "client",
17354
- parent,
17355
- attributes: {
17356
- "http.request.method": method,
17357
- "url.full": target ? `${target.protocol}//${target.host}${target.pathname}` : void 0,
17358
- "server.address": target?.hostname,
17359
- "server.port": target ? Number(target.port || (target.protocol === "https:" ? 443 : 80)) : void 0
17360
- }
17361
- });
17362
- }
17363
- function parse(text) {
17364
- try {
17365
- return text.trim() ? JSON.parse(text) : void 0;
17366
- } catch {
17367
- return void 0;
17368
- }
17369
- }
17370
- var DatanotesClient = class {
17371
- constructor(o) {
17372
- this.o = o;
17373
- this.url = o.url.replace(/\/+$/, "");
17374
- this.send = o.transport ?? fetchTransport;
17375
- }
17376
- /** The parent of a request: the call's own `trace`, else the client's. */
17377
- parentOf(trace) {
17378
- const given = trace ?? (typeof this.o.trace === "function" ? this.o.trace() : this.o.trace);
17379
- return typeof given === "string" ? parseTraceparent(given) : given ?? null;
17380
- }
17381
- /**
17382
- * Send a request; the answer's status, its JSON (when it is JSON) and its text. `trace`: the
17383
- * trace this request continues (over the client's `trace` option).
17384
- */
17385
- async request(method, path, body, opts = {}) {
17386
- if (!this.url) throw new DatanotesError("engine address not set", "unreachable");
17387
- if (!this.o.token) throw new DatanotesError("token not set", "auth");
17388
- const actor = opts.actor ?? this.o.actor;
17389
- const parent = this.parentOf(opts.trace);
17390
- const span = this.o.tracer ? clientSpan(this.o.tracer, method, `${this.url}${path}`, parent) : void 0;
17391
- const sent = span?.context ?? parent;
17392
- let res;
17393
- try {
17394
- res = await this.send({
17395
- url: `${this.url}${path}`,
17396
- method,
17397
- headers: {
17398
- Authorization: `Bearer ${this.o.token}`,
17399
- ...body !== void 0 ? { "Content-Type": "application/json" } : {},
17400
- ...opts.accept ? { Accept: opts.accept } : {},
17401
- ...actor && Object.keys(actor).length ? { [ACTOR_HEADER]: JSON.stringify(actor) } : {},
17402
- ...sent ? traceHeaders(sent) : {}
17403
- },
17404
- ...body !== void 0 ? { body: JSON.stringify(body) } : {}
17405
- });
17406
- } catch (e) {
17407
- span?.recordException(e);
17408
- span?.end();
17409
- throw new DatanotesError(`engine unreachable at ${this.url}: ${e instanceof Error ? e.message : String(e)}`, "unreachable");
17410
- }
17411
- span?.setAttribute("http.response.status_code", res.status);
17412
- if (res.status >= 400) span?.setAttribute("error.type", String(res.status));
17413
- if (res.status >= 500) span?.setStatus("error", `HTTP ${res.status}`);
17414
- span?.end();
17415
- if (res.status === 401) throw new DatanotesError("token refused by the engine", "auth", 401);
17416
- const json = parse(res.text);
17417
- const unreachable = res.status === 0 || res.status === 502 || res.status === 504 || res.status === 503 && !isEngineAnswer(json);
17418
- if (unreachable) throw new DatanotesError(`engine unreachable at ${this.url} (HTTP ${res.status})`, "unreachable", res.status);
17419
- return { status: res.status, json, text: res.text };
17420
- }
17421
- /** `POST /datanotes/<route>` and its JSON answer; throws on an error status. */
17422
- async post(route, body = {}, actor) {
17423
- const r = await this.request("POST", `/datanotes${route}`, body, actor ? { actor } : {});
17424
- if (r.status >= 400) throw Object.assign(new DatanotesError(resultOf(r.status, r.json, r.text).value, "http", r.status), guidanceIn(r.json));
17425
- return r.json;
17426
- }
17427
- /**
17428
- * Run an operation of the catalogue (`select_rows`, `insert_row`, …) with an agent's arguments.
17429
- * Arguments the operation does not take, or of the wrong type, are refused before anything is sent,
17430
- * with the same message the engine gives.
17431
- */
17432
- async call(name, args = {}, actor, options = {}) {
17433
- let req;
17434
- try {
17435
- req = operationRequest(name, args);
17436
- } catch (e) {
17437
- if (e instanceof OperationInputError) return { ok: false, value: e.message };
17438
- throw e;
17439
- }
17440
- const problem = checkArguments(name, args);
17441
- if (problem) return { ok: false, value: guidedText(problem.message, problem) };
17442
- const r = await this.request(req.method, req.path, req.body, { ...actor ? { actor } : {}, ...options.trace ? { trace: options.trace } : {} });
17443
- return resultOf(r.status, r.json, r.text);
17444
- }
17445
- /** True when the engine answers `GET /` (no token needed). */
17446
- async ping() {
17447
- try {
17448
- const r = await this.send({ url: `${this.url}/`, method: "GET", headers: {} });
17449
- return r.status === 200;
17450
- } catch {
17451
- return false;
17452
- }
17453
- }
17454
- /**
17455
- * Record an agent's tool call in the change feed (what MCP servers report). Answers what the
17456
- * engine said: `takes_summary` when it records a `value` sent cut with its `summary`.
17457
- */
17458
- async recordToolCall(call, actor) {
17459
- return this.post("/tool-calls/record/", call, actor);
17460
- }
17461
- };
17462
17467
  export {
17463
17468
  ACTOR_HEADER,
17464
17469
  CALLABLE_OPERATIONS,