@dbx-tools/appkit-mastra 0.1.111 → 0.3.1
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 +309 -344
- package/index.ts +46 -0
- package/package.json +50 -28
- package/src/agents.ts +858 -0
- package/src/chart.ts +695 -0
- package/src/config.ts +443 -0
- package/src/filesystems.ts +1090 -0
- package/src/genie.ts +1091 -0
- package/src/history.ts +297 -0
- package/src/mcp.ts +105 -0
- package/src/memory.ts +300 -0
- package/src/mlflow.ts +149 -0
- package/src/model.ts +163 -0
- package/src/observability.ts +144 -0
- package/src/pagination.ts +34 -0
- package/src/plugin.ts +804 -0
- package/src/processors.ts +168 -0
- package/src/rest.ts +67 -0
- package/src/server.ts +343 -0
- package/src/serving-sanitize.ts +167 -0
- package/src/serving.ts +97 -0
- package/src/statement.ts +89 -0
- package/src/storage-schema.ts +41 -0
- package/src/summarize.ts +176 -0
- package/src/threads.ts +338 -0
- package/src/workspaces.ts +346 -0
- package/src/writer.ts +44 -0
- package/tsconfig.json +41 -0
- package/dist/index.d.ts +0 -1676
- package/dist/index.js +0 -5337
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mastra observability wired through the same OTel pipeline AppKit's
|
|
3
|
+
* built-in plugins (e.g. `agents`) use, via `@mastra/otel-bridge`.
|
|
4
|
+
*
|
|
5
|
+
* How traces flow:
|
|
6
|
+
*
|
|
7
|
+
* 1. `@databricks/appkit` boots a global `NodeSDK` in
|
|
8
|
+
* `TelemetryManager.initialize()` (during `createApp`) when
|
|
9
|
+
* `OTEL_EXPORTER_OTLP_ENDPOINT` is set in the process env.
|
|
10
|
+
* 2. Every AppKit plugin span (e.g. the `agents` plugin's
|
|
11
|
+
* `executeStream`) is created via the global OTel tracer
|
|
12
|
+
* (`trace.getTracer(<plugin>)`), so it lands on that NodeSDK and
|
|
13
|
+
* is shipped through its OTLP exporter.
|
|
14
|
+
* 3. The Mastra `OtelBridge` ALSO creates real OTel spans on the same
|
|
15
|
+
* global tracer for every Mastra operation (agent runs, model
|
|
16
|
+
* calls, tool invocations, workflow steps). They inherit the
|
|
17
|
+
* ambient OTel context, so when Mastra is invoked from inside an
|
|
18
|
+
* AppKit HTTP span the trace stays connected.
|
|
19
|
+
*
|
|
20
|
+
* Net effect: Mastra spans get exactly the treatment AppKit's
|
|
21
|
+
* `agents` plugin gets. No custom OTLP pipeline lives in this
|
|
22
|
+
* package; the OTLP endpoint, headers, and resource attributes are
|
|
23
|
+
* driven by the standard OTel env vars
|
|
24
|
+
* (`OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_HEADERS`,
|
|
25
|
+
* `OTEL_SERVICE_NAME`, `OTEL_RESOURCE_ATTRIBUTES`, ...) and consumed
|
|
26
|
+
* by AppKit's `TelemetryManager`. Set those once and both AppKit and
|
|
27
|
+
* Mastra spans end up at the same backend.
|
|
28
|
+
*
|
|
29
|
+
* When `OTEL_EXPORTER_OTLP_ENDPOINT` is unset the bridge is not
|
|
30
|
+
* registered at all (unless `observability: true` forces it on), so
|
|
31
|
+
* Mastra does not emit `[OtelBridge] No OTEL span found` warnings.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { Observability } from "@mastra/observability";
|
|
35
|
+
import { OtelBridge } from "@mastra/otel-bridge";
|
|
36
|
+
|
|
37
|
+
import { TRACE_REQUEST_CONTEXT_KEYS } from "./config";
|
|
38
|
+
import { log } from "@dbx-tools/shared-core";
|
|
39
|
+
import { project } from "@dbx-tools/core";
|
|
40
|
+
|
|
41
|
+
const logger = log.logger("mastra/observability");
|
|
42
|
+
|
|
43
|
+
const DEFAULT_SERVICE_NAME = "mastra";
|
|
44
|
+
|
|
45
|
+
export interface BuildObservabilityOptions {
|
|
46
|
+
/**
|
|
47
|
+
* Whether to wire the Mastra `OtelBridge`. Mirrors
|
|
48
|
+
* {@link MastraPluginConfig.observability}:
|
|
49
|
+
*
|
|
50
|
+
* - `undefined` (auto): on only when `OTEL_EXPORTER_OTLP_ENDPOINT` or
|
|
51
|
+
* `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` is set (same signal AppKit's
|
|
52
|
+
* `TelemetryManager` uses to register a real tracer). When unset,
|
|
53
|
+
* skip the bridge entirely so Mastra does not emit
|
|
54
|
+
* `[OtelBridge] No OTEL span found` warnings on the noop tracer.
|
|
55
|
+
* - `true`: force on even without an OTLP endpoint.
|
|
56
|
+
* - `false`: force off.
|
|
57
|
+
*/
|
|
58
|
+
enabled?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Service name attached to the Mastra `Observability` config. Used
|
|
61
|
+
* as the tracer scope name on bridged OTel spans (the `service.name`
|
|
62
|
+
* resource attribute is owned by AppKit's `TelemetryManager` instead
|
|
63
|
+
* - it reads `OTEL_SERVICE_NAME` / `DATABRICKS_APP_NAME` at
|
|
64
|
+
* `createApp` time).
|
|
65
|
+
*
|
|
66
|
+
* Defaults to project name then `"mastra"`.
|
|
67
|
+
*/
|
|
68
|
+
serviceName?: string;
|
|
69
|
+
/**
|
|
70
|
+
* `RequestContext` keys to extract as span metadata on every Mastra
|
|
71
|
+
* trace. Defaults to {@link TRACE_REQUEST_CONTEXT_KEYS} (user id,
|
|
72
|
+
* thread id, request id, environment, model override, ...).
|
|
73
|
+
*
|
|
74
|
+
* Supports dot notation for nested values per the Mastra docs.
|
|
75
|
+
*/
|
|
76
|
+
requestContextKeys?: readonly string[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** True when AppKit's global OTel pipeline is configured to export traces. */
|
|
80
|
+
export function isOtlpTracingConfigured(): boolean {
|
|
81
|
+
return Boolean(
|
|
82
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT || process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Build a Mastra `Observability` whose spans ride AppKit's global
|
|
88
|
+
* OTel pipeline via `@mastra/otel-bridge`.
|
|
89
|
+
*
|
|
90
|
+
* Returns `undefined` when tracing is off: either the caller passed
|
|
91
|
+
* `enabled: false`, or auto mode finds no OTLP endpoint (the default).
|
|
92
|
+
* Skipping the bridge in that case avoids `[OtelBridge] No OTEL span
|
|
93
|
+
* found` log spam from Mastra spans that have no parent on the noop
|
|
94
|
+
* tracer.
|
|
95
|
+
*/
|
|
96
|
+
export async function buildObservability(
|
|
97
|
+
options?: BuildObservabilityOptions,
|
|
98
|
+
): Promise<Observability | undefined> {
|
|
99
|
+
const otelBase = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
100
|
+
const otelTracesOverride = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT;
|
|
101
|
+
const otlpConfigured = isOtlpTracingConfigured();
|
|
102
|
+
|
|
103
|
+
if (options?.enabled === false || (options?.enabled !== true && !otlpConfigured)) {
|
|
104
|
+
logger.info("Mastra observability off", {
|
|
105
|
+
reason:
|
|
106
|
+
options?.enabled === false
|
|
107
|
+
? "disabled in plugin config"
|
|
108
|
+
: "OTEL_EXPORTER_OTLP_ENDPOINT unset",
|
|
109
|
+
});
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const serviceName = options?.serviceName ?? (await project.name()) ?? DEFAULT_SERVICE_NAME;
|
|
114
|
+
const requestContextKeys = [...(options?.requestContextKeys ?? TRACE_REQUEST_CONTEXT_KEYS)];
|
|
115
|
+
|
|
116
|
+
// The OTel HTTP exporter treats `OTEL_EXPORTER_OTLP_ENDPOINT` as a
|
|
117
|
+
// *base* URL and appends the signal path itself (e.g.
|
|
118
|
+
// `http://localhost:6006` -> `http://localhost:6006/v1/traces`). Log
|
|
119
|
+
// the resolved POST URL so misconfigurations (e.g. accidentally
|
|
120
|
+
// setting the base var to a `/v1/traces`-suffixed URL, which makes
|
|
121
|
+
// the SDK POST to `.../v1/traces/v1/traces` and Phoenix 404s) are
|
|
122
|
+
// obvious in startup output.
|
|
123
|
+
const resolvedTracesUrl = otelTracesOverride
|
|
124
|
+
? otelTracesOverride
|
|
125
|
+
: otelBase
|
|
126
|
+
? `${otelBase.replace(/\/+$/, "")}/v1/traces`
|
|
127
|
+
: undefined;
|
|
128
|
+
logger.info("Mastra observability wired through OTel bridge", {
|
|
129
|
+
serviceName,
|
|
130
|
+
requestContextKeys,
|
|
131
|
+
otelBase: otelBase ?? "<unset>",
|
|
132
|
+
resolvedTracesUrl: resolvedTracesUrl ?? "<unset>",
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return new Observability({
|
|
136
|
+
configs: {
|
|
137
|
+
serviceName: {
|
|
138
|
+
serviceName,
|
|
139
|
+
bridge: new OtelBridge(),
|
|
140
|
+
requestContextKeys,
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query-parameter coercion shared by the paginated custom routes
|
|
3
|
+
* (`history` / `threads`). Each route keeps its own page-size default
|
|
4
|
+
* and hard cap and passes them in, so the coercion rules stay in one
|
|
5
|
+
* place without collapsing the routes' distinct sizing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Bounds for {@link clampPerPage}. */
|
|
9
|
+
export interface PerPageBounds {
|
|
10
|
+
/** Page size used for empty / non-positive / non-numeric inputs. */
|
|
11
|
+
fallback: number;
|
|
12
|
+
/** Hard cap so a misbehaving client can't fetch everything at once. */
|
|
13
|
+
max: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Coerce / clamp a `perPage` value, falling back to `bounds.fallback`. */
|
|
17
|
+
export function clampPerPage(value: number | undefined, bounds: PerPageBounds): number {
|
|
18
|
+
if (value === undefined || Number.isNaN(value)) return bounds.fallback;
|
|
19
|
+
const n = Math.trunc(value);
|
|
20
|
+
if (n <= 0) return bounds.fallback;
|
|
21
|
+
return Math.min(n, bounds.max);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Coerce a Hono query value into a non-negative integer. Returns
|
|
26
|
+
* `undefined` for empty / non-numeric / negative inputs so the caller
|
|
27
|
+
* can apply its built-in defaults.
|
|
28
|
+
*/
|
|
29
|
+
export function parseIntParam(value: string | undefined): number | undefined {
|
|
30
|
+
if (!value) return undefined;
|
|
31
|
+
const n = Number(value);
|
|
32
|
+
if (!Number.isFinite(n) || n < 0) return undefined;
|
|
33
|
+
return Math.trunc(n);
|
|
34
|
+
}
|