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.
- 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 +371 -366
- package/dist/api/index.js +371 -366
- package/dist/api/mcp.cjs +28 -5
- package/dist/api/mcp.js +28 -5
- package/dist/datanotes.cjs +6205 -3421
- package/dist/docs/administration/extensions.md +213 -0
- 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/tags/extensions.md +9 -0
- package/dist/docs/api.md +9 -1
- package/dist/docs/develop/write-an-extension.md +369 -0
- package/dist/docs/guides/data-quality/check-constraints.md +10 -10
- package/dist/docs/guides/data-quality/hand-edits.md +8 -8
- package/dist/docs/guides/database-objects/bases.md +11 -11
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +10 -10
- package/dist/docs/guides/database-objects/columns.md +38 -38
- package/dist/docs/guides/database-objects/relations.md +28 -28
- package/dist/docs/guides/database-objects/tables.md +28 -28
- 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 +20 -20
- 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/glossary.md +8 -0
- package/dist/docs/release-notes.md +33 -0
- package/dist/docs/start/connect-agents.md +11 -0
- package/package.json +11 -1
package/dist/api/index.cjs
CHANGED
|
@@ -16927,125 +16927,397 @@ function classOf(cp) {
|
|
|
16927
16927
|
return k;
|
|
16928
16928
|
}
|
|
16929
16929
|
|
|
16930
|
-
// src/api/
|
|
16931
|
-
var
|
|
16932
|
-
var
|
|
16933
|
-
var
|
|
16934
|
-
function
|
|
16935
|
-
|
|
16936
|
-
if (
|
|
16937
|
-
|
|
16938
|
-
|
|
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) } : {} };
|
|
16939
16942
|
}
|
|
16940
|
-
|
|
16941
|
-
|
|
16942
|
-
const res = await fetch(url, { method: "POST", headers, body });
|
|
16943
|
-
if (!res.ok) throw new Error(`OTLP HTTP ${res.status}`);
|
|
16944
|
-
};
|
|
16945
|
-
function unixNano(ms) {
|
|
16946
|
-
const whole = Math.floor(ms);
|
|
16947
|
-
const frac = Math.round((ms - whole) * 1e6);
|
|
16948
|
-
return (BigInt(whole) * BigInt(1e6) + BigInt(frac)).toString();
|
|
16943
|
+
function formatTraceparent(ctx) {
|
|
16944
|
+
return `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
|
|
16949
16945
|
}
|
|
16950
|
-
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
this.
|
|
16973
|
-
|
|
16974
|
-
|
|
16975
|
-
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);
|
|
16976
16980
|
}
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
this.varint(v);
|
|
16981
|
+
setAttribute(key, value) {
|
|
16982
|
+
if (value !== void 0 && value !== null) this.attributes[key] = value;
|
|
16980
16983
|
return this;
|
|
16981
16984
|
}
|
|
16982
|
-
|
|
16983
|
-
this.
|
|
16984
|
-
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]);
|
|
16985
16987
|
return this;
|
|
16986
16988
|
}
|
|
16987
|
-
|
|
16988
|
-
this.
|
|
16989
|
-
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 });
|
|
16990
16991
|
return this;
|
|
16991
16992
|
}
|
|
16992
|
-
|
|
16993
|
-
|
|
16994
|
-
const
|
|
16995
|
-
|
|
16996
|
-
|
|
16997
|
-
|
|
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);
|
|
16998
17000
|
}
|
|
16999
|
-
|
|
17000
|
-
this.
|
|
17001
|
-
this.
|
|
17002
|
-
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 };
|
|
17003
17004
|
return this;
|
|
17004
17005
|
}
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
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
|
+
});
|
|
17010
17023
|
}
|
|
17011
|
-
|
|
17012
|
-
|
|
17024
|
+
};
|
|
17025
|
+
var Tracer = class {
|
|
17026
|
+
constructor(o) {
|
|
17027
|
+
this.o = o;
|
|
17028
|
+
this.now = o.now ?? defaultNow;
|
|
17013
17029
|
}
|
|
17014
|
-
|
|
17015
|
-
|
|
17030
|
+
/** A new span: a child of `parent` (a context or a `traceparent` header), or a new trace. */
|
|
17031
|
+
startSpan(name, opts = {}) {
|
|
17032
|
+
const parent = typeof opts.parent === "string" ? parseTraceparent(opts.parent) : opts.parent ?? null;
|
|
17033
|
+
const ratio = this.o.sampleRatio ?? 1;
|
|
17034
|
+
const span = new TraceSpan(this, name, opts.kind ?? "internal", parent, true, opts.attributes ?? {});
|
|
17035
|
+
const recording = parent ? parent.sampled : ratio >= 1 || ratio > 0 && parseInt(span.context.traceId.slice(-13), 16) / 2 ** 52 < ratio;
|
|
17036
|
+
return recording ? span : new TraceSpan(this, name, opts.kind ?? "internal", parent ?? { ...span.context, sampled: false }, false, {});
|
|
17016
17037
|
}
|
|
17017
|
-
|
|
17018
|
-
|
|
17038
|
+
/** @internal */
|
|
17039
|
+
send(span) {
|
|
17040
|
+
try {
|
|
17041
|
+
this.o.export([span]);
|
|
17042
|
+
} catch {
|
|
17043
|
+
}
|
|
17019
17044
|
}
|
|
17020
17045
|
};
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
|
|
17024
|
-
|
|
17046
|
+
|
|
17047
|
+
// src/api/client.ts
|
|
17048
|
+
var ACTOR_HEADER = "X-Datanotes-Actor";
|
|
17049
|
+
var UNREACHABLE = {
|
|
17050
|
+
hint: "Start the engine (datanotes serve --database <folder>) or check its address; datanotes status --database <folder> shows whether it runs and where.",
|
|
17051
|
+
docs: `${DOCS_BASE}/start/connect-agents.md#how-the-mcp-server-reaches-the-engine`
|
|
17052
|
+
};
|
|
17053
|
+
var AUTH = {
|
|
17054
|
+
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>.",
|
|
17055
|
+
docs: `${DOCS_BASE}/develop/http-api.md#authenticate-your-requests`
|
|
17056
|
+
};
|
|
17057
|
+
var DatanotesError = class extends Error {
|
|
17058
|
+
/** `unreachable`: the engine did not answer; `auth`: the token was refused. */
|
|
17059
|
+
constructor(message, kind = "http", status = 0, guidance = kind === "unreachable" ? UNREACHABLE : kind === "auth" ? AUTH : null) {
|
|
17060
|
+
super(guidedText(message, guidance));
|
|
17061
|
+
this.kind = kind;
|
|
17062
|
+
this.status = status;
|
|
17063
|
+
this.name = "DatanotesError";
|
|
17064
|
+
if (guidance) {
|
|
17065
|
+
this.hint = guidance.hint;
|
|
17066
|
+
this.docs = guidance.docs;
|
|
17067
|
+
}
|
|
17068
|
+
}
|
|
17069
|
+
};
|
|
17070
|
+
var fetchTransport = async (req) => {
|
|
17071
|
+
const res = await fetch(req.url, { method: req.method, headers: req.headers, ...req.body !== void 0 ? { body: req.body } : {} });
|
|
17072
|
+
return { status: res.status, text: await res.text() };
|
|
17073
|
+
};
|
|
17074
|
+
function isEngineAnswer(json) {
|
|
17075
|
+
if (json === null || typeof json !== "object" || Array.isArray(json)) return false;
|
|
17076
|
+
const o = json;
|
|
17077
|
+
return typeof o.ok === "boolean" || typeof o.error === "string";
|
|
17025
17078
|
}
|
|
17026
|
-
function
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
17079
|
+
function clientSpan(tracer, method, url, parent) {
|
|
17080
|
+
let target;
|
|
17081
|
+
try {
|
|
17082
|
+
target = new URL(url);
|
|
17083
|
+
} catch {
|
|
17084
|
+
target = null;
|
|
17030
17085
|
}
|
|
17031
|
-
return
|
|
17086
|
+
return tracer.startSpan(target ? `${method} ${target.pathname}` : method, {
|
|
17087
|
+
kind: "client",
|
|
17088
|
+
parent,
|
|
17089
|
+
attributes: {
|
|
17090
|
+
"http.request.method": method,
|
|
17091
|
+
"url.full": target ? `${target.protocol}//${target.host}${target.pathname}` : void 0,
|
|
17092
|
+
"server.address": target?.hostname,
|
|
17093
|
+
"server.port": target ? Number(target.port || (target.protocol === "https:" ? 443 : 80)) : void 0
|
|
17094
|
+
}
|
|
17095
|
+
});
|
|
17032
17096
|
}
|
|
17033
|
-
|
|
17034
|
-
|
|
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) {
|
|
17035
17111
|
this.o = o;
|
|
17036
|
-
this.
|
|
17037
|
-
this.
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
|
|
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
|
+
}
|
|
17049
17321
|
}
|
|
17050
17322
|
push(items) {
|
|
17051
17323
|
const room = this.maxBatch * 8 - this.buffer.length;
|
|
@@ -17060,7 +17332,7 @@ var OtlpBatcher = class {
|
|
|
17060
17332
|
flush() {
|
|
17061
17333
|
if (this.buffer.length === 0) return this.inflight;
|
|
17062
17334
|
const send = this.o.send ?? fetchSend;
|
|
17063
|
-
const url = `${this.o.endpoint
|
|
17335
|
+
const url = `${trimTrailingSlashes(this.o.endpoint)}${this.path}`;
|
|
17064
17336
|
const protobuf = (this.o.protocol ?? "http/protobuf") === "http/protobuf";
|
|
17065
17337
|
const headers = { "Content-Type": protobuf ? "application/x-protobuf" : "application/json", ...this.o.headers ?? {} };
|
|
17066
17338
|
while (this.buffer.length > 0) {
|
|
@@ -17252,270 +17524,3 @@ function otlpProtocol(v) {
|
|
|
17252
17524
|
const p = (v ?? "").trim().toLowerCase();
|
|
17253
17525
|
return p === "http/protobuf" || p === "http/json" ? p : void 0;
|
|
17254
17526
|
}
|
|
17255
|
-
|
|
17256
|
-
// src/api/tracing.ts
|
|
17257
|
-
var TRACEPARENT_HEADER = "traceparent";
|
|
17258
|
-
var TRACESTATE_HEADER = "tracestate";
|
|
17259
|
-
var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
|
|
17260
|
-
function parseTraceparent(traceparent, tracestate) {
|
|
17261
|
-
const m = TRACEPARENT.exec((typeof traceparent === "string" ? traceparent : "").trim().toLowerCase());
|
|
17262
|
-
if (!m) return null;
|
|
17263
|
-
const [, version, traceId, spanId, flags, rest] = m;
|
|
17264
|
-
if (version === "ff" || version === "00" && rest !== void 0) return null;
|
|
17265
|
-
if (/^0+$/.test(traceId) || /^0+$/.test(spanId)) return null;
|
|
17266
|
-
const state = (typeof tracestate === "string" ? tracestate : "").trim();
|
|
17267
|
-
return { traceId, spanId, sampled: (parseInt(flags, 16) & 1) === 1, ...state ? { traceState: state.slice(0, 512) } : {} };
|
|
17268
|
-
}
|
|
17269
|
-
function formatTraceparent(ctx) {
|
|
17270
|
-
return `00-${ctx.traceId}-${ctx.spanId}-${ctx.sampled ? "01" : "00"}`;
|
|
17271
|
-
}
|
|
17272
|
-
function traceHeaders(ctx) {
|
|
17273
|
-
return { [TRACEPARENT_HEADER]: formatTraceparent(ctx), ...ctx.traceState ? { [TRACESTATE_HEADER]: ctx.traceState } : {} };
|
|
17274
|
-
}
|
|
17275
|
-
function randomHex(bytes) {
|
|
17276
|
-
const b = new Uint8Array(bytes);
|
|
17277
|
-
const c = globalThis.crypto;
|
|
17278
|
-
if (c?.getRandomValues) c.getRandomValues(b);
|
|
17279
|
-
else for (let i = 0; i < bytes; i++) b[i] = Math.floor(Math.random() * 256);
|
|
17280
|
-
const hex = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
17281
|
-
return /^0+$/.test(hex) ? randomHex(bytes) : hex;
|
|
17282
|
-
}
|
|
17283
|
-
var newTraceId = () => randomHex(16);
|
|
17284
|
-
var newSpanId = () => randomHex(8);
|
|
17285
|
-
var perf = globalThis.performance;
|
|
17286
|
-
var defaultNow = perf ? () => perf.timeOrigin + perf.now() : () => Date.now();
|
|
17287
|
-
var TraceSpan = class {
|
|
17288
|
-
constructor(tracer, name, kind, parent, recording, attributes) {
|
|
17289
|
-
this.tracer = tracer;
|
|
17290
|
-
this.name = name;
|
|
17291
|
-
this.kind = kind;
|
|
17292
|
-
this.parent = parent;
|
|
17293
|
-
this.recording = recording;
|
|
17294
|
-
this.attributes = {};
|
|
17295
|
-
this.events = [];
|
|
17296
|
-
this.status = { code: "unset" };
|
|
17297
|
-
this.ended = false;
|
|
17298
|
-
this.context = {
|
|
17299
|
-
traceId: parent?.traceId ?? newTraceId(),
|
|
17300
|
-
spanId: newSpanId(),
|
|
17301
|
-
sampled: recording,
|
|
17302
|
-
...parent?.traceState ? { traceState: parent.traceState } : {}
|
|
17303
|
-
};
|
|
17304
|
-
this.startMs = tracer.now();
|
|
17305
|
-
this.setAttributes(attributes);
|
|
17306
|
-
}
|
|
17307
|
-
setAttribute(key, value) {
|
|
17308
|
-
if (value !== void 0 && value !== null) this.attributes[key] = value;
|
|
17309
|
-
return this;
|
|
17310
|
-
}
|
|
17311
|
-
setAttributes(attributes) {
|
|
17312
|
-
for (const k in attributes) this.setAttribute(k, attributes[k]);
|
|
17313
|
-
return this;
|
|
17314
|
-
}
|
|
17315
|
-
addEvent(name, attributes = {}) {
|
|
17316
|
-
this.events.push({ name, timeMs: this.tracer.now(), attributes });
|
|
17317
|
-
return this;
|
|
17318
|
-
}
|
|
17319
|
-
/** An `exception` event, `error.type` and status ERROR. */
|
|
17320
|
-
recordException(e) {
|
|
17321
|
-
const type = e instanceof Error ? e.name : typeof e;
|
|
17322
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
17323
|
-
this.addEvent("exception", { "exception.type": type, "exception.message": message, ...e instanceof Error && e.stack ? { "exception.stacktrace": e.stack.slice(0, 8192) } : {} });
|
|
17324
|
-
if (!("error.type" in this.attributes)) this.attributes["error.type"] = type;
|
|
17325
|
-
return this.setStatus("error", message);
|
|
17326
|
-
}
|
|
17327
|
-
setStatus(code, message) {
|
|
17328
|
-
if (this.status.code === "error" && code !== "error") return this;
|
|
17329
|
-
this.status = code === "error" && message ? { code, message } : { code };
|
|
17330
|
-
return this;
|
|
17331
|
-
}
|
|
17332
|
-
end() {
|
|
17333
|
-
if (this.ended) return;
|
|
17334
|
-
this.ended = true;
|
|
17335
|
-
if (!this.recording) return;
|
|
17336
|
-
this.tracer.send({
|
|
17337
|
-
traceId: this.context.traceId,
|
|
17338
|
-
spanId: this.context.spanId,
|
|
17339
|
-
...this.parent ? { parentSpanId: this.parent.spanId } : {},
|
|
17340
|
-
...this.context.traceState ? { traceState: this.context.traceState } : {},
|
|
17341
|
-
name: this.name,
|
|
17342
|
-
kind: this.kind,
|
|
17343
|
-
startMs: this.startMs,
|
|
17344
|
-
endMs: this.tracer.now(),
|
|
17345
|
-
attributes: this.attributes,
|
|
17346
|
-
events: this.events,
|
|
17347
|
-
status: this.status
|
|
17348
|
-
});
|
|
17349
|
-
}
|
|
17350
|
-
};
|
|
17351
|
-
var Tracer = class {
|
|
17352
|
-
constructor(o) {
|
|
17353
|
-
this.o = o;
|
|
17354
|
-
this.now = o.now ?? defaultNow;
|
|
17355
|
-
}
|
|
17356
|
-
/** A new span: a child of `parent` (a context or a `traceparent` header), or a new trace. */
|
|
17357
|
-
startSpan(name, opts = {}) {
|
|
17358
|
-
const parent = typeof opts.parent === "string" ? parseTraceparent(opts.parent) : opts.parent ?? null;
|
|
17359
|
-
const ratio = this.o.sampleRatio ?? 1;
|
|
17360
|
-
const span = new TraceSpan(this, name, opts.kind ?? "internal", parent, true, opts.attributes ?? {});
|
|
17361
|
-
const recording = parent ? parent.sampled : ratio >= 1 || ratio > 0 && parseInt(span.context.traceId.slice(-13), 16) / 2 ** 52 < ratio;
|
|
17362
|
-
return recording ? span : new TraceSpan(this, name, opts.kind ?? "internal", parent ?? { ...span.context, sampled: false }, false, {});
|
|
17363
|
-
}
|
|
17364
|
-
/** @internal */
|
|
17365
|
-
send(span) {
|
|
17366
|
-
try {
|
|
17367
|
-
this.o.export([span]);
|
|
17368
|
-
} catch {
|
|
17369
|
-
}
|
|
17370
|
-
}
|
|
17371
|
-
};
|
|
17372
|
-
|
|
17373
|
-
// src/api/client.ts
|
|
17374
|
-
var ACTOR_HEADER = "X-Datanotes-Actor";
|
|
17375
|
-
var UNREACHABLE = {
|
|
17376
|
-
hint: "Start the engine (datanotes serve --database <folder>) or check its address; datanotes status --database <folder> shows whether it runs and where.",
|
|
17377
|
-
docs: `${DOCS_BASE}/start/connect-agents.md#how-the-mcp-server-reaches-the-engine`
|
|
17378
|
-
};
|
|
17379
|
-
var AUTH = {
|
|
17380
|
-
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>.",
|
|
17381
|
-
docs: `${DOCS_BASE}/develop/http-api.md#authenticate-your-requests`
|
|
17382
|
-
};
|
|
17383
|
-
var DatanotesError = class extends Error {
|
|
17384
|
-
/** `unreachable`: the engine did not answer; `auth`: the token was refused. */
|
|
17385
|
-
constructor(message, kind = "http", status = 0, guidance = kind === "unreachable" ? UNREACHABLE : kind === "auth" ? AUTH : null) {
|
|
17386
|
-
super(guidedText(message, guidance));
|
|
17387
|
-
this.kind = kind;
|
|
17388
|
-
this.status = status;
|
|
17389
|
-
this.name = "DatanotesError";
|
|
17390
|
-
if (guidance) {
|
|
17391
|
-
this.hint = guidance.hint;
|
|
17392
|
-
this.docs = guidance.docs;
|
|
17393
|
-
}
|
|
17394
|
-
}
|
|
17395
|
-
};
|
|
17396
|
-
var fetchTransport = async (req) => {
|
|
17397
|
-
const res = await fetch(req.url, { method: req.method, headers: req.headers, ...req.body !== void 0 ? { body: req.body } : {} });
|
|
17398
|
-
return { status: res.status, text: await res.text() };
|
|
17399
|
-
};
|
|
17400
|
-
function isEngineAnswer(json) {
|
|
17401
|
-
if (json === null || typeof json !== "object" || Array.isArray(json)) return false;
|
|
17402
|
-
const o = json;
|
|
17403
|
-
return typeof o.ok === "boolean" || typeof o.error === "string";
|
|
17404
|
-
}
|
|
17405
|
-
function clientSpan(tracer, method, url, parent) {
|
|
17406
|
-
let target;
|
|
17407
|
-
try {
|
|
17408
|
-
target = new URL(url);
|
|
17409
|
-
} catch {
|
|
17410
|
-
target = null;
|
|
17411
|
-
}
|
|
17412
|
-
return tracer.startSpan(target ? `${method} ${target.pathname}` : method, {
|
|
17413
|
-
kind: "client",
|
|
17414
|
-
parent,
|
|
17415
|
-
attributes: {
|
|
17416
|
-
"http.request.method": method,
|
|
17417
|
-
"url.full": target ? `${target.protocol}//${target.host}${target.pathname}` : void 0,
|
|
17418
|
-
"server.address": target?.hostname,
|
|
17419
|
-
"server.port": target ? Number(target.port || (target.protocol === "https:" ? 443 : 80)) : void 0
|
|
17420
|
-
}
|
|
17421
|
-
});
|
|
17422
|
-
}
|
|
17423
|
-
function parse(text) {
|
|
17424
|
-
try {
|
|
17425
|
-
return text.trim() ? JSON.parse(text) : void 0;
|
|
17426
|
-
} catch {
|
|
17427
|
-
return void 0;
|
|
17428
|
-
}
|
|
17429
|
-
}
|
|
17430
|
-
var DatanotesClient = class {
|
|
17431
|
-
constructor(o) {
|
|
17432
|
-
this.o = o;
|
|
17433
|
-
this.url = o.url.replace(/\/+$/, "");
|
|
17434
|
-
this.send = o.transport ?? fetchTransport;
|
|
17435
|
-
}
|
|
17436
|
-
/** The parent of a request: the call's own `trace`, else the client's. */
|
|
17437
|
-
parentOf(trace) {
|
|
17438
|
-
const given = trace ?? (typeof this.o.trace === "function" ? this.o.trace() : this.o.trace);
|
|
17439
|
-
return typeof given === "string" ? parseTraceparent(given) : given ?? null;
|
|
17440
|
-
}
|
|
17441
|
-
/**
|
|
17442
|
-
* Send a request; the answer's status, its JSON (when it is JSON) and its text. `trace`: the
|
|
17443
|
-
* trace this request continues (over the client's `trace` option).
|
|
17444
|
-
*/
|
|
17445
|
-
async request(method, path, body, opts = {}) {
|
|
17446
|
-
if (!this.url) throw new DatanotesError("engine address not set", "unreachable");
|
|
17447
|
-
if (!this.o.token) throw new DatanotesError("token not set", "auth");
|
|
17448
|
-
const actor = opts.actor ?? this.o.actor;
|
|
17449
|
-
const parent = this.parentOf(opts.trace);
|
|
17450
|
-
const span = this.o.tracer ? clientSpan(this.o.tracer, method, `${this.url}${path}`, parent) : void 0;
|
|
17451
|
-
const sent = span?.context ?? parent;
|
|
17452
|
-
let res;
|
|
17453
|
-
try {
|
|
17454
|
-
res = await this.send({
|
|
17455
|
-
url: `${this.url}${path}`,
|
|
17456
|
-
method,
|
|
17457
|
-
headers: {
|
|
17458
|
-
Authorization: `Bearer ${this.o.token}`,
|
|
17459
|
-
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
17460
|
-
...opts.accept ? { Accept: opts.accept } : {},
|
|
17461
|
-
...actor && Object.keys(actor).length ? { [ACTOR_HEADER]: JSON.stringify(actor) } : {},
|
|
17462
|
-
...sent ? traceHeaders(sent) : {}
|
|
17463
|
-
},
|
|
17464
|
-
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
17465
|
-
});
|
|
17466
|
-
} catch (e) {
|
|
17467
|
-
span?.recordException(e);
|
|
17468
|
-
span?.end();
|
|
17469
|
-
throw new DatanotesError(`engine unreachable at ${this.url}: ${e instanceof Error ? e.message : String(e)}`, "unreachable");
|
|
17470
|
-
}
|
|
17471
|
-
span?.setAttribute("http.response.status_code", res.status);
|
|
17472
|
-
if (res.status >= 400) span?.setAttribute("error.type", String(res.status));
|
|
17473
|
-
if (res.status >= 500) span?.setStatus("error", `HTTP ${res.status}`);
|
|
17474
|
-
span?.end();
|
|
17475
|
-
if (res.status === 401) throw new DatanotesError("token refused by the engine", "auth", 401);
|
|
17476
|
-
const json = parse(res.text);
|
|
17477
|
-
const unreachable = res.status === 0 || res.status === 502 || res.status === 504 || res.status === 503 && !isEngineAnswer(json);
|
|
17478
|
-
if (unreachable) throw new DatanotesError(`engine unreachable at ${this.url} (HTTP ${res.status})`, "unreachable", res.status);
|
|
17479
|
-
return { status: res.status, json, text: res.text };
|
|
17480
|
-
}
|
|
17481
|
-
/** `POST /datanotes/<route>` and its JSON answer; throws on an error status. */
|
|
17482
|
-
async post(route, body = {}, actor) {
|
|
17483
|
-
const r = await this.request("POST", `/datanotes${route}`, body, actor ? { actor } : {});
|
|
17484
|
-
if (r.status >= 400) throw Object.assign(new DatanotesError(resultOf(r.status, r.json, r.text).value, "http", r.status), guidanceIn(r.json));
|
|
17485
|
-
return r.json;
|
|
17486
|
-
}
|
|
17487
|
-
/**
|
|
17488
|
-
* Run an operation of the catalogue (`select_rows`, `insert_row`, …) with an agent's arguments.
|
|
17489
|
-
* Arguments the operation does not take, or of the wrong type, are refused before anything is sent,
|
|
17490
|
-
* with the same message the engine gives.
|
|
17491
|
-
*/
|
|
17492
|
-
async call(name, args = {}, actor, options = {}) {
|
|
17493
|
-
let req;
|
|
17494
|
-
try {
|
|
17495
|
-
req = operationRequest(name, args);
|
|
17496
|
-
} catch (e) {
|
|
17497
|
-
if (e instanceof OperationInputError) return { ok: false, value: e.message };
|
|
17498
|
-
throw e;
|
|
17499
|
-
}
|
|
17500
|
-
const problem = checkArguments(name, args);
|
|
17501
|
-
if (problem) return { ok: false, value: guidedText(problem.message, problem) };
|
|
17502
|
-
const r = await this.request(req.method, req.path, req.body, { ...actor ? { actor } : {}, ...options.trace ? { trace: options.trace } : {} });
|
|
17503
|
-
return resultOf(r.status, r.json, r.text);
|
|
17504
|
-
}
|
|
17505
|
-
/** True when the engine answers `GET /` (no token needed). */
|
|
17506
|
-
async ping() {
|
|
17507
|
-
try {
|
|
17508
|
-
const r = await this.send({ url: `${this.url}/`, method: "GET", headers: {} });
|
|
17509
|
-
return r.status === 200;
|
|
17510
|
-
} catch {
|
|
17511
|
-
return false;
|
|
17512
|
-
}
|
|
17513
|
-
}
|
|
17514
|
-
/**
|
|
17515
|
-
* Record an agent's tool call in the change feed (what MCP servers report). Answers what the
|
|
17516
|
-
* engine said: `takes_summary` when it records a `value` sent cut with its `summary`.
|
|
17517
|
-
*/
|
|
17518
|
-
async recordToolCall(call, actor) {
|
|
17519
|
-
return this.post("/tool-calls/record/", call, actor);
|
|
17520
|
-
}
|
|
17521
|
-
};
|