melchizedek-agents 0.9.0 → 0.9.3

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 (36) hide show
  1. package/AGENT_SETUP.md +14 -2
  2. package/DOCUMENTATION.md +13 -22
  3. package/QUICKSTART.md +35 -6
  4. package/README.md +22 -19
  5. package/config/agents/examples/ares.yaml +0 -2
  6. package/config/agents/examples/augustin.yaml +248 -0
  7. package/config/agents/examples/cartographers.yaml +0 -3
  8. package/config/agents/examples/council.yaml +1 -1
  9. package/config/agents/examples/image_production.yaml +0 -1
  10. package/config/agents/examples/librarian.yaml +0 -2
  11. package/config/agents/examples/patient_advocate.yaml +0 -2
  12. package/config/agents/examples/scriptorium.yaml +0 -3
  13. package/config/agents/examples/style_council.yaml +1 -5
  14. package/config/agents/examples/syndicate.yaml +0 -3
  15. package/config/agents/examples/tutor.yaml +1 -1
  16. package/config/agents/syndicateSchema.yaml +4 -2
  17. package/dist/lib/compile.d.ts +64 -0
  18. package/dist/lib/compile.js +105 -0
  19. package/dist/lib/models/claudeLlm.js +25 -1
  20. package/dist/lib/models/gptLlm.js +5 -2
  21. package/dist/lib/models/ollamaLlm.d.ts +2 -0
  22. package/dist/lib/models/ollamaLlm.js +4 -0
  23. package/dist/lib/models/openAiCompatibleLlm.d.ts +2 -0
  24. package/dist/lib/models/openAiCompatibleLlm.js +14 -5
  25. package/dist/lib/models/schemaNormalize.d.ts +9 -0
  26. package/dist/lib/models/schemaNormalize.js +34 -0
  27. package/dist/lib/observability/embeddings.d.ts +21 -0
  28. package/dist/lib/observability/embeddings.js +47 -0
  29. package/dist/lib/observability/lineage.d.ts +35 -0
  30. package/dist/lib/observability/lineage.js +96 -0
  31. package/dist/lib/observability/supabaseSpanExporter.d.ts +186 -18
  32. package/dist/lib/observability/supabaseSpanExporter.js +377 -80
  33. package/dist/lib/observability/tracer.d.ts +74 -0
  34. package/dist/lib/observability/tracer.js +282 -1
  35. package/dist/scripts/a2a_server.js +85 -75
  36. package/package.json +9 -4
@@ -1,35 +1,203 @@
1
1
  /**
2
- * lib/observability/supabaseSpanExporter.ts — optional OpenTelemetry sink
3
- * that persists model-request telemetry to Supabase.
2
+ * lib/observability/supabaseSpanExporter.ts — the observability ledger sink.
4
3
  *
5
4
  * WHY this file exists:
6
5
  * The console exporter in tracer.ts prints every span as an
7
- * [OTEL_SPAN_JSON] line — good for a terminal, gone when it scrolls.
8
- * Operators who want durable usage data (tokens per model, per provider,
9
- * over time) can opt in with TELEMETRY_SUPABASE=true, and every
10
- * `llm.request` and `Syndicate Execution:*` span is also inserted into
11
- * the adk_telemetry table (schema: db/telemetry.sql, RLS: db/hardening.sql).
6
+ * [OTEL_SPAN_JSON] line — good for a terminal, gone when it scrolls. With
7
+ * TELEMETRY_SUPABASE=true (and Supabase credentials) every turn and every
8
+ * model call is also written to Supabase, in three tiers with three
9
+ * lifetimes (schema: db/telemetry.sql, lockdown: db/hardening.sql):
10
+ *
11
+ * adk_turns one row per turn — the system of record: input, output,
12
+ * route, agent, errors, tokens, model-vs-tool time, the
13
+ * tool calls WITH their responses, the ids that join it to
14
+ * the session (session_id, invocation_id) and the task,
15
+ * and provenance (config_hash, engine_version).
16
+ * adk_telemetry one row per span — llm.request and root spans, raw.
17
+ * adk_payloads full request/response per model call, captured by
18
+ * POLICY and expiring. ADK's own call_llm spans carry the
19
+ * assembled prompt and raw response; they are 10-100x a
20
+ * turn row, so: errors and fallbacks always, a
21
+ * deterministic sample of the rest, 30-day TTL.
12
22
  *
13
23
  * DESIGN NOTES:
14
- * - Fire-and-forget: an insert failure is logged once and never thrown
15
- * into the tracing pipeline — telemetry must not break inference.
16
- * - Only spans that carry usage are exported (name filter below); ADK's
17
- * internal spans stay console-only to keep row volume sane.
24
+ * - Never on the hot path: inserts are fire-and-forget behind a
25
+ * BatchSpanProcessor; a failure is logged once per table and the rows
26
+ * are spooled to a dead-letter file (OUTPUTS_DIR/telemetry-deadletter.ndjson)
27
+ * so a sink outage loses nothing silently. `npm run telemetry:stats`
28
+ * shows what landed; `telemetry:replay` re-sends the spool.
29
+ * - Payload decisions need the TURN's outcome (error? fallback?), which is
30
+ * only known when the root span ends — after its call_llm children. So
31
+ * call_llm spans wait in a per-trace buffer until their root arrives,
32
+ * then the decision is applied to all of them at once. Children that
33
+ * arrive after the root (a later batch) find the decision cached.
34
+ * - Sampling is deterministic in the trace id: a trace keeps all of its
35
+ * payloads or none, and a re-run of the same policy keeps the same set.
18
36
  */
19
37
  import type { SpanExporter, ReadableSpan } from '@opentelemetry/sdk-trace-base';
20
- /** True when the operator has opted into the Supabase telemetry sink. */
38
+ /** Row shape for adk_telemetry (raw spans). */
39
+ export interface TelemetryRow {
40
+ ts: string;
41
+ trace_id: string;
42
+ span_id: string;
43
+ span_name: string;
44
+ syndicate: string | null;
45
+ agent: string | null;
46
+ provider: string | null;
47
+ model: string | null;
48
+ input_tokens: number | null;
49
+ output_tokens: number | null;
50
+ thinking_tokens: number | null;
51
+ latency_ms: number;
52
+ session_id: string | null;
53
+ user_id: string | null;
54
+ task_id: string | null;
55
+ invocation_id: string | null;
56
+ schema_version: number;
57
+ span: Record<string, unknown>;
58
+ }
59
+ /** Row shape for adk_turns (the system of record). */
60
+ export interface TurnRow {
61
+ ts: string;
62
+ trace_id: string;
63
+ span_id: string;
64
+ session_id: string | null;
65
+ user_id: string | null;
66
+ task_id: string | null;
67
+ invocation_id: string | null;
68
+ syndicate: string;
69
+ stage: string;
70
+ agent: string | null;
71
+ route: string | null;
72
+ route_reason: string | null;
73
+ route_fell_back: boolean | null;
74
+ route_via_override: boolean | null;
75
+ relay_fallback: boolean;
76
+ input: string;
77
+ output: string;
78
+ error_code: string | null;
79
+ error_message: string | null;
80
+ input_tokens: number | null;
81
+ output_tokens: number | null;
82
+ thinking_tokens: number | null;
83
+ latency_ms: number;
84
+ model_ms: number | null;
85
+ tool_ms: number | null;
86
+ llm_calls: number | null;
87
+ tool_calls: number;
88
+ models: string[];
89
+ tool_events: Array<Record<string, unknown>>;
90
+ config_hash: string | null;
91
+ engine_version: string | null;
92
+ eval_run: string | null;
93
+ eval_suite: string | null;
94
+ eval_case: string | null;
95
+ eval_variant: string | null;
96
+ eval_trial: number | null;
97
+ attributes: Record<string, unknown>;
98
+ schema_version: number;
99
+ }
100
+ export type PayloadReason = 'error' | 'fallback' | 'sample' | 'all';
101
+ /** Row shape for adk_payloads. */
102
+ export interface PayloadRow {
103
+ ts: string;
104
+ trace_id: string;
105
+ span_id: string;
106
+ session_id: string | null;
107
+ invocation_id: string | null;
108
+ agent: string | null;
109
+ provider: string | null;
110
+ model: string | null;
111
+ reason: PayloadReason;
112
+ request: unknown;
113
+ response: unknown;
114
+ request_chars: number;
115
+ response_chars: number;
116
+ expires_at: string;
117
+ schema_version: number;
118
+ }
119
+ export type PayloadMode = 'off' | 'errors' | 'sample' | 'all';
120
+ export interface PayloadPolicy {
121
+ mode: PayloadMode;
122
+ /** Fraction of non-error, non-fallback traces kept in 'sample' mode. */
123
+ sampleRate: number;
124
+ ttlDays: number;
125
+ }
126
+ /**
127
+ * TELEMETRY_PAYLOADS: off | errors | sample (default) | all
128
+ * TELEMETRY_PAYLOAD_SAMPLE: 0..1, default 0.10
129
+ * TELEMETRY_PAYLOAD_TTL_DAYS: default 30
130
+ */
131
+ export declare function payloadPolicyFromEnv(env?: NodeJS.ProcessEnv): PayloadPolicy;
132
+ /** Deterministic 0..1 value from a trace id (first 8 hex chars). */
133
+ export declare function traceSampleValue(traceId: string): number;
134
+ export interface TurnFacts {
135
+ error: boolean;
136
+ fallback: boolean;
137
+ }
138
+ /** Which payloads of a turn to keep, given the policy and the turn's outcome. */
139
+ export declare function payloadDecision(policy: PayloadPolicy, traceId: string, facts: TurnFacts): PayloadReason | null;
140
+ export declare function isRootSpan(span: ReadableSpan): boolean;
141
+ export declare function isPayloadSpan(span: ReadableSpan): boolean;
142
+ /** `syndicate.input` is JSON.stringify of either a string or A2A parts. */
143
+ export declare function parseInputText(raw: unknown): string;
144
+ /** Flatten an llm.request or root span into one adk_telemetry row. */
145
+ export declare function toTelemetryRow(span: ReadableSpan): TelemetryRow;
146
+ /** Project a root span into the adk_turns system-of-record row. */
147
+ export declare function toTurnRow(span: ReadableSpan): TurnRow;
148
+ /** The facts a payload decision needs, read off a root span. */
149
+ export declare function turnFacts(span: ReadableSpan): TurnFacts;
150
+ /** Map an ADK call_llm span into an adk_payloads row. */
151
+ export declare function toPayloadRow(span: ReadableSpan, reason: PayloadReason, ttlDays: number, turn: {
152
+ sessionId: string | null;
153
+ invocationId: string | null;
154
+ } | undefined): PayloadRow;
155
+ /** True when the operator has opted into the Supabase ledger. */
21
156
  export declare function telemetrySinkEnabled(): boolean;
157
+ export declare function deadLetterPath(): string;
158
+ export interface ExportStats {
159
+ inserted: Record<string, number>;
160
+ failed: Record<string, number>;
161
+ deadLettered: number;
162
+ payloadsDropped: number;
163
+ }
164
+ interface SupabaseLikeClient {
165
+ from(table: string): {
166
+ insert(rows: unknown[]): PromiseLike<{
167
+ error: {
168
+ message: string;
169
+ } | null;
170
+ }>;
171
+ };
172
+ }
173
+ export interface ExporterOptions {
174
+ /** Injected client (tests); default: lazily created supabase-js client. */
175
+ client?: SupabaseLikeClient;
176
+ policy?: PayloadPolicy;
177
+ /** Where failed batches are spooled; '' disables the spool. */
178
+ deadLetterFile?: string;
179
+ }
22
180
  export declare class SupabaseSpanExporter implements SpanExporter {
23
- /** Lazily created on first export so constructing the exporter is free
24
- * and synchronous (NodeTracerProvider wants processors at construction). */
25
181
  private clientPromise;
26
- private insertFailureLogged;
27
- private pendingInserts;
182
+ private readonly policy;
183
+ private readonly deadLetterFile;
184
+ private readonly failureLogged;
185
+ private readonly pendingInserts;
186
+ /** call_llm spans waiting for their root span's outcome, by trace id. */
187
+ private readonly pendingPayloads;
188
+ /** Decisions already taken for a trace, for children arriving late. */
189
+ private readonly decisions;
190
+ private pendingCount;
191
+ readonly stats: ExportStats;
192
+ constructor(options?: ExporterOptions);
28
193
  private getClient;
29
194
  export(spans: ReadableSpan[], resultCallback: (result: any) => void): void;
195
+ private pruneBuffers;
196
+ /** Fire-and-forget insert; failures are logged once per table and spooled. */
197
+ private insert;
198
+ private onFailure;
30
199
  /** Waits for in-flight inserts so short-lived scripts don't drop rows. */
31
200
  shutdown(): Promise<void>;
32
201
  forceFlush(): Promise<void>;
33
- /** Flatten a span into one adk_telemetry row. */
34
- private toRow;
35
202
  }
203
+ export {};