@vauban-org/agent-sdk 1.2.0 → 1.4.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 (82) hide show
  1. package/CONTRACT.md +595 -7
  2. package/dist/index.d.ts +4 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/orchestration/ooda/agent.d.ts.map +1 -1
  7. package/dist/orchestration/ooda/agent.js +77 -0
  8. package/dist/orchestration/ooda/agent.js.map +1 -1
  9. package/dist/orchestration/ooda/types.d.ts +11 -0
  10. package/dist/orchestration/ooda/types.d.ts.map +1 -1
  11. package/dist/skills/_secrets.d.ts +16 -0
  12. package/dist/skills/_secrets.d.ts.map +1 -0
  13. package/dist/skills/_secrets.js +20 -0
  14. package/dist/skills/_secrets.js.map +1 -0
  15. package/dist/skills/alpaca-quote.d.ts +2 -2
  16. package/dist/skills/alpaca-quote.d.ts.map +1 -1
  17. package/dist/skills/alpaca-quote.js +51 -20
  18. package/dist/skills/alpaca-quote.js.map +1 -1
  19. package/dist/skills/send-email.d.ts +2 -2
  20. package/dist/skills/send-email.d.ts.map +1 -1
  21. package/dist/skills/send-email.js +1 -12
  22. package/dist/skills/send-email.js.map +1 -1
  23. package/dist/skills/slack-notify.d.ts.map +1 -1
  24. package/dist/skills/slack-notify.js +52 -21
  25. package/dist/skills/slack-notify.js.map +1 -1
  26. package/dist/skills/telegram-notify.d.ts.map +1 -1
  27. package/dist/skills/telegram-notify.js +48 -19
  28. package/dist/skills/telegram-notify.js.map +1 -1
  29. package/dist/skills/web-search.d.ts.map +1 -1
  30. package/dist/skills/web-search.js +85 -40
  31. package/dist/skills/web-search.js.map +1 -1
  32. package/dist/telemetry/bus.d.ts +54 -0
  33. package/dist/telemetry/bus.d.ts.map +1 -0
  34. package/dist/telemetry/bus.js +159 -0
  35. package/dist/telemetry/bus.js.map +1 -0
  36. package/dist/telemetry/index.d.ts +35 -0
  37. package/dist/telemetry/index.d.ts.map +1 -0
  38. package/dist/telemetry/index.js +30 -0
  39. package/dist/telemetry/index.js.map +1 -0
  40. package/dist/telemetry/port.d.ts +121 -0
  41. package/dist/telemetry/port.d.ts.map +1 -0
  42. package/dist/telemetry/port.js +48 -0
  43. package/dist/telemetry/port.js.map +1 -0
  44. package/dist/telemetry/sinks/otlp.d.ts +45 -0
  45. package/dist/telemetry/sinks/otlp.d.ts.map +1 -0
  46. package/dist/telemetry/sinks/otlp.js +195 -0
  47. package/dist/telemetry/sinks/otlp.js.map +1 -0
  48. package/dist/telemetry/sinks/sqlite.d.ts +32 -0
  49. package/dist/telemetry/sinks/sqlite.d.ts.map +1 -0
  50. package/dist/telemetry/sinks/sqlite.js +170 -0
  51. package/dist/telemetry/sinks/sqlite.js.map +1 -0
  52. package/dist/telemetry/sinks/stdout.d.ts +22 -0
  53. package/dist/telemetry/sinks/stdout.d.ts.map +1 -0
  54. package/dist/telemetry/sinks/stdout.js +38 -0
  55. package/dist/telemetry/sinks/stdout.js.map +1 -0
  56. package/docs/telemetry/migration.md +155 -0
  57. package/docs/telemetry/overview.md +154 -0
  58. package/docs/telemetry/privacy.md +127 -0
  59. package/docs/telemetry/sinks/cc.md +155 -0
  60. package/docs/telemetry/sinks/otlp.md +146 -0
  61. package/docs/telemetry/sinks/sqlite.md +126 -0
  62. package/docs/telemetry/sinks/stdout.md +82 -0
  63. package/package.json +18 -19
  64. package/src/index.ts +30 -1
  65. package/src/orchestration/ooda/agent.ts +105 -0
  66. package/src/orchestration/ooda/types.ts +12 -0
  67. package/src/skills/_secrets.ts +25 -0
  68. package/src/skills/alpaca-quote.ts +68 -23
  69. package/src/skills/send-email.ts +1 -12
  70. package/src/skills/slack-notify.ts +73 -30
  71. package/src/skills/telegram-notify.ts +70 -24
  72. package/src/skills/web-search.ts +132 -50
  73. package/src/telemetry/bus.test.ts +231 -0
  74. package/src/telemetry/bus.ts +241 -0
  75. package/src/telemetry/index.ts +49 -0
  76. package/src/telemetry/port.ts +160 -0
  77. package/src/telemetry/sinks/otlp.test.ts +146 -0
  78. package/src/telemetry/sinks/otlp.ts +250 -0
  79. package/src/telemetry/sinks/sqlite.test.ts +121 -0
  80. package/src/telemetry/sinks/sqlite.ts +260 -0
  81. package/src/telemetry/sinks/stdout.test.ts +109 -0
  82. package/src/telemetry/sinks/stdout.ts +59 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otlp.js","sourceRoot":"","sources":["../../../src/telemetry/sinks/otlp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * localSqliteTelemetrySink — sovereign local mirror of agent runs.
3
+ *
4
+ * Per ADR-ECO-039 §5 : SQLite sink is ON by default. It is the exit plan for
5
+ * any remote sink (CC SaaS, OTLP backend) — if the network sink is revoked,
6
+ * the local SQLite file retains the full history.
7
+ *
8
+ * Schema (created on first use) :
9
+ * - `agent_run` : one row per OODA cycle (start + finish join)
10
+ * - `agent_run_step` : one row per OODA step
11
+ *
12
+ * Dependency : `better-sqlite3` declared as **peerDependency optional**.
13
+ * If absent, this sink degrades gracefully — logs a warning and no-ops.
14
+ *
15
+ * Ref: command-center:sprint-693:sink-sqlite
16
+ */
17
+ import type { TelemetrySink } from "../port.js";
18
+ export interface LocalSqliteTelemetrySinkOptions {
19
+ /**
20
+ * Database file path. Default `~/.vauban/runs.db`.
21
+ * Pass `:memory:` for ephemeral test mode.
22
+ */
23
+ path?: string;
24
+ /** Synchronous mode (better-sqlite3 default). Tests may override. */
25
+ readonly?: boolean;
26
+ }
27
+ /**
28
+ * Build a local SQLite sink. Returns a no-op sink if `better-sqlite3` is not
29
+ * installed — the caller is warned via `console.warn` once.
30
+ */
31
+ export declare function localSqliteTelemetrySink(opts?: LocalSqliteTelemetrySinkOptions): TelemetrySink;
32
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../src/telemetry/sinks/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,KAAK,EAIV,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,+BAA+B;IAC9C;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,GAAE,+BAAoC,GACzC,aAAa,CA2Ff"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * localSqliteTelemetrySink — sovereign local mirror of agent runs.
3
+ *
4
+ * Per ADR-ECO-039 §5 : SQLite sink is ON by default. It is the exit plan for
5
+ * any remote sink (CC SaaS, OTLP backend) — if the network sink is revoked,
6
+ * the local SQLite file retains the full history.
7
+ *
8
+ * Schema (created on first use) :
9
+ * - `agent_run` : one row per OODA cycle (start + finish join)
10
+ * - `agent_run_step` : one row per OODA step
11
+ *
12
+ * Dependency : `better-sqlite3` declared as **peerDependency optional**.
13
+ * If absent, this sink degrades gracefully — logs a warning and no-ops.
14
+ *
15
+ * Ref: command-center:sprint-693:sink-sqlite
16
+ */
17
+ import { homedir } from "node:os";
18
+ import { dirname, resolve as resolvePath } from "node:path";
19
+ import { mkdirSync } from "node:fs";
20
+ // ─── Schema ──────────────────────────────────────────────────────────────────
21
+ const SCHEMA = `
22
+ CREATE TABLE IF NOT EXISTS agent_run (
23
+ run_id TEXT PRIMARY KEY,
24
+ agent_id TEXT NOT NULL,
25
+ agent_version TEXT NOT NULL,
26
+ model TEXT,
27
+ provider TEXT,
28
+ tenant_id TEXT,
29
+ trace_id TEXT,
30
+ started_at TEXT NOT NULL,
31
+ finished_at TEXT,
32
+ status TEXT,
33
+ stop_reason TEXT,
34
+ error_message TEXT,
35
+ total_input_tokens INTEGER DEFAULT 0,
36
+ total_output_tokens INTEGER DEFAULT 0,
37
+ total_cost_usd REAL DEFAULT 0,
38
+ total_tool_calls INTEGER DEFAULT 0
39
+ );
40
+
41
+ CREATE INDEX IF NOT EXISTS idx_agent_run_agent_started
42
+ ON agent_run (agent_id, started_at DESC);
43
+
44
+ CREATE INDEX IF NOT EXISTS idx_agent_run_status
45
+ ON agent_run (status, started_at DESC);
46
+
47
+ CREATE TABLE IF NOT EXISTS agent_run_step (
48
+ run_id TEXT NOT NULL,
49
+ step_index INTEGER NOT NULL,
50
+ kind TEXT NOT NULL,
51
+ status TEXT NOT NULL,
52
+ input_tokens INTEGER DEFAULT 0,
53
+ output_tokens INTEGER DEFAULT 0,
54
+ tool_calls INTEGER DEFAULT 0,
55
+ cost_usd REAL DEFAULT 0,
56
+ duration_ms INTEGER,
57
+ metadata TEXT,
58
+ recorded_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
59
+ PRIMARY KEY (run_id, step_index)
60
+ );
61
+
62
+ CREATE INDEX IF NOT EXISTS idx_agent_run_step_run
63
+ ON agent_run_step (run_id, step_index);
64
+ `;
65
+ // ─── Factory ─────────────────────────────────────────────────────────────────
66
+ /**
67
+ * Build a local SQLite sink. Returns a no-op sink if `better-sqlite3` is not
68
+ * installed — the caller is warned via `console.warn` once.
69
+ */
70
+ export function localSqliteTelemetrySink(opts = {}) {
71
+ const dbPath = resolveDbPath(opts.path);
72
+ const db = openDatabaseSafely(dbPath, opts.readonly ?? false);
73
+ if (!db) {
74
+ return degradedSink(dbPath);
75
+ }
76
+ db.exec(SCHEMA);
77
+ db.pragma("journal_mode = WAL");
78
+ db.pragma("synchronous = NORMAL");
79
+ const insertRun = db.prepare(`
80
+ INSERT INTO agent_run
81
+ (run_id, agent_id, agent_version, model, provider,
82
+ tenant_id, trace_id, started_at)
83
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
84
+ ON CONFLICT (run_id) DO NOTHING
85
+ `);
86
+ const insertStep = db.prepare(`
87
+ INSERT INTO agent_run_step
88
+ (run_id, step_index, kind, status,
89
+ input_tokens, output_tokens, tool_calls, cost_usd,
90
+ duration_ms, metadata)
91
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
92
+ ON CONFLICT (run_id, step_index) DO NOTHING
93
+ `);
94
+ const updateFinish = db.prepare(`
95
+ UPDATE agent_run
96
+ SET finished_at = ?,
97
+ status = ?,
98
+ stop_reason = ?,
99
+ error_message = ?,
100
+ total_input_tokens = COALESCE(?, total_input_tokens),
101
+ total_output_tokens = COALESCE(?, total_output_tokens),
102
+ total_cost_usd = COALESCE(?, total_cost_usd),
103
+ total_tool_calls = COALESCE(?, total_tool_calls)
104
+ WHERE run_id = ?
105
+ `);
106
+ return {
107
+ name: "sqlite",
108
+ async start(event) {
109
+ insertRun.run(event.runId, event.agentId, event.agentVersion, event.model ?? null, event.provider ?? null, event.tenantId ?? null, event.traceId ?? null, event.startedAt);
110
+ },
111
+ async step(runId, delta) {
112
+ insertStep.run(runId, delta.stepIndex, delta.kind, delta.status, delta.inputTokens, delta.outputTokens, delta.toolCalls ?? 0, delta.costUsd, delta.durationMs ?? null, delta.metadata ? JSON.stringify(delta.metadata) : null);
113
+ },
114
+ async finish(runId, event) {
115
+ updateFinish.run(event.finishedAt, event.status, event.stopReason ?? null, event.errorMessage ?? null, event.totalInputTokens ?? null, event.totalOutputTokens ?? null, event.totalCostUsd ?? null, event.totalToolCalls ?? null, runId);
116
+ },
117
+ async flush() {
118
+ // better-sqlite3 is synchronous — no buffer to flush.
119
+ },
120
+ };
121
+ }
122
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
123
+ function resolveDbPath(input) {
124
+ if (!input)
125
+ return resolvePath(homedir(), ".vauban", "runs.db");
126
+ if (input === ":memory:")
127
+ return input;
128
+ // Expand leading ~ manually (Node doesn't do it).
129
+ if (input.startsWith("~/")) {
130
+ return resolvePath(homedir(), input.slice(2));
131
+ }
132
+ return resolvePath(input);
133
+ }
134
+ let warnedMissing = false;
135
+ function openDatabaseSafely(path, readonly) {
136
+ try {
137
+ // Dynamic require so better-sqlite3 stays optional.
138
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
139
+ const createRequire = require("node:module").createRequire;
140
+ const req = createRequire(import.meta.url);
141
+ const BetterSqlite = req("better-sqlite3");
142
+ if (path !== ":memory:") {
143
+ mkdirSync(dirname(path), { recursive: true });
144
+ }
145
+ return new BetterSqlite(path, { readonly });
146
+ }
147
+ catch (err) {
148
+ if (!warnedMissing) {
149
+ warnedMissing = true;
150
+ // eslint-disable-next-line no-console
151
+ console.warn("[telemetry:sqlite] better-sqlite3 not installed — sink degraded to no-op.", "Install with: `pnpm add better-sqlite3` (peerDependencyOptional).", err instanceof Error ? err.message : "");
152
+ }
153
+ return null;
154
+ }
155
+ }
156
+ function degradedSink(path) {
157
+ return {
158
+ name: `sqlite:degraded(${path})`,
159
+ async start() {
160
+ /* no-op when better-sqlite3 missing */
161
+ },
162
+ async step() {
163
+ /* no-op */
164
+ },
165
+ async finish() {
166
+ /* no-op */
167
+ },
168
+ };
169
+ }
170
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../../src/telemetry/sinks/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAkCpC,gFAAgF;AAEhF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2Cd,CAAC;AAEF,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAwC,EAAE;IAE1C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;IAE9D,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAElC,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;GAM5B,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;GAO7B,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;GAW/B,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,QAAQ;QAEd,KAAK,CAAC,KAAK,CAAC,KAAwB;YAClC,SAAS,CAAC,GAAG,CACX,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,KAAK,IAAI,IAAI,EACnB,KAAK,CAAC,QAAQ,IAAI,IAAI,EACtB,KAAK,CAAC,QAAQ,IAAI,IAAI,EACtB,KAAK,CAAC,OAAO,IAAI,IAAI,EACrB,KAAK,CAAC,SAAS,CAChB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,KAAuB;YAC/C,UAAU,CAAC,GAAG,CACZ,KAAK,EACL,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,WAAW,EACjB,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,SAAS,IAAI,CAAC,EACpB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,UAAU,IAAI,IAAI,EACxB,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CACvD,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAAyB;YACnD,YAAY,CAAC,GAAG,CACd,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,UAAU,IAAI,IAAI,EACxB,KAAK,CAAC,YAAY,IAAI,IAAI,EAC1B,KAAK,CAAC,gBAAgB,IAAI,IAAI,EAC9B,KAAK,CAAC,iBAAiB,IAAI,IAAI,EAC/B,KAAK,CAAC,YAAY,IAAI,IAAI,EAC1B,KAAK,CAAC,cAAc,IAAI,IAAI,EAC5B,KAAK,CACN,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,KAAK;YACT,sDAAsD;QACxD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,WAAW,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IACvC,kDAAkD;IAClD,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B,SAAS,kBAAkB,CAAC,IAAY,EAAE,QAAiB;IACzD,IAAI,CAAC;QACH,oDAAoD;QACpD,iEAAiE;QACjE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,aAE1B,CAAC;QACpB,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,YAAY,GAAG,GAAG,CAAC,gBAAgB,CAG5B,CAAC;QAEd,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,aAAa,GAAG,IAAI,CAAC;YACrB,sCAAsC;YACtC,OAAO,CAAC,IAAI,CACV,2EAA2E,EAC3E,mEAAmE,EACnE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CACxC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO;QACL,IAAI,EAAE,mBAAmB,IAAI,GAAG;QAChC,KAAK,CAAC,KAAK;YACT,uCAAuC;QACzC,CAAC;QACD,KAAK,CAAC,IAAI;YACR,WAAW;QACb,CAAC;QACD,KAAK,CAAC,MAAM;YACV,WAAW;QACb,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * stdoutTelemetrySink — JSON line emission to stderr (dev-friendly default).
3
+ *
4
+ * One JSON object per event, suitable for `jq`, `pino-pretty`, or any
5
+ * structured-log pipeline. Writes to stderr (not stdout) so that the agent's
6
+ * own stdout remains free for user output.
7
+ *
8
+ * Ref: command-center:sprint-693:sink-stdout
9
+ */
10
+ import type { TelemetrySink } from "../port.js";
11
+ export interface StdoutTelemetrySinkOptions {
12
+ /** Stream to write to. Defaults to `process.stderr`. */
13
+ stream?: NodeJS.WritableStream;
14
+ /** When true (default), emits as `key=value` instead of JSON. */
15
+ json?: boolean;
16
+ }
17
+ /**
18
+ * Default sink for dev visibility. Zero dependency, zero I/O latency
19
+ * (synchronous write to stream).
20
+ */
21
+ export declare function stdoutTelemetrySink(opts?: StdoutTelemetrySinkOptions): TelemetrySink;
22
+ //# sourceMappingURL=stdout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdout.d.ts","sourceRoot":"","sources":["../../../src/telemetry/sinks/stdout.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAIV,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA0B;IACzC,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,iEAAiE;IACjE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,0BAA+B,GACpC,aAAa,CA4Bf"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * stdoutTelemetrySink — JSON line emission to stderr (dev-friendly default).
3
+ *
4
+ * One JSON object per event, suitable for `jq`, `pino-pretty`, or any
5
+ * structured-log pipeline. Writes to stderr (not stdout) so that the agent's
6
+ * own stdout remains free for user output.
7
+ *
8
+ * Ref: command-center:sprint-693:sink-stdout
9
+ */
10
+ /**
11
+ * Default sink for dev visibility. Zero dependency, zero I/O latency
12
+ * (synchronous write to stream).
13
+ */
14
+ export function stdoutTelemetrySink(opts = {}) {
15
+ const stream = opts.stream ?? process.stderr;
16
+ const useJson = opts.json ?? true;
17
+ function emit(event) {
18
+ const line = useJson
19
+ ? JSON.stringify(event)
20
+ : Object.entries(event)
21
+ .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
22
+ .join(" ");
23
+ stream.write(`${line}\n`);
24
+ }
25
+ return {
26
+ name: "stdout",
27
+ async start(event) {
28
+ emit({ telemetry: "run.start", ...event });
29
+ },
30
+ async step(runId, delta) {
31
+ emit({ telemetry: "run.step", runId, ...delta });
32
+ },
33
+ async finish(runId, event) {
34
+ emit({ telemetry: "run.finish", runId, ...event });
35
+ },
36
+ };
37
+ }
38
+ //# sourceMappingURL=stdout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdout.js","sourceRoot":"","sources":["../../../src/telemetry/sinks/stdout.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAmC,EAAE;IAErC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;IAElC,SAAS,IAAI,CAAC,KAA8B;QAC1C,MAAM,IAAI,GAAG,OAAO;YAClB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YACvB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;iBAClB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC5C,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QAEd,KAAK,CAAC,KAAK,CAAC,KAAwB;YAClC,IAAI,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,KAAuB;YAC/C,IAAI,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QACnD,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAAyB;YACnD,IAAI,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QACrD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,155 @@
1
+ # Migration : 1.2 → 1.3
2
+
3
+ !!! success "Zero breaking changes"
4
+ Existing 1.2.x consumers continue to work unchanged. All new APIs are
5
+ additive.
6
+
7
+ ## TL;DR
8
+
9
+ - `AgentRunTracker` still works. Marked deprecated, will be removed in 2.0.
10
+ - New `telemetry` field on `OODAAgentConfig`. Opt-in.
11
+ - 4 new sinks shipped : `stdout`, `sqlite`, `otlp` in core ; `cc` in
12
+ `@vauban-org/cc-telemetry`.
13
+
14
+ ## What changed
15
+
16
+ ### `AgentRunFinalStatus` adds `"skipped"`
17
+
18
+ Before :
19
+
20
+ ```ts
21
+ type AgentRunFinalStatus = "success" | "failed" | "timeout" | "incoherent";
22
+ ```
23
+
24
+ After :
25
+
26
+ ```ts
27
+ type AgentRunFinalStatus = "success" | "failed" | "skipped" | "timeout" | "incoherent";
28
+ ```
29
+
30
+ `"skipped"` distinguishes session_guard / risk_guard / heap_exceeded
31
+ short-circuits from real successes. Existing exhaustive `switch` statements
32
+ on this type will need to add a case (TypeScript will surface it).
33
+
34
+ For the new `TelemetryRunStatus` type (used by the new sinks), see the
35
+ [port.ts source](https://github.com/vauban-org/command-center/blob/main/packages/agent-sdk/src/telemetry/port.ts).
36
+
37
+ ### New optional `OODAAgentConfig.telemetry`
38
+
39
+ ```ts
40
+ interface OODAAgentConfig {
41
+ // …existing fields…
42
+ readonly telemetry?: TelemetrySink; // NEW, optional
43
+ }
44
+ ```
45
+
46
+ When set, the OODA loop auto-emits `start` + `step` + `finish` events.
47
+ When omitted, behavior is identical to 1.2.
48
+
49
+ ### Legacy `AgentRunTracker` is deprecated
50
+
51
+ ```ts
52
+ import { createAgentRunTracker } from "@vauban-org/agent-sdk"; // deprecated
53
+
54
+ const tracker = createAgentRunTracker(db);
55
+ // Still works, still INSERTs into agent_run. Will be removed in 2.0.
56
+ ```
57
+
58
+ Migration target :
59
+
60
+ ```ts
61
+ import {
62
+ createTelemetryBus,
63
+ localSqliteTelemetrySink,
64
+ } from "@vauban-org/agent-sdk";
65
+ import { commandCenterTelemetrySink } from "@vauban-org/cc-telemetry";
66
+
67
+ const telemetry = createTelemetryBus({
68
+ sinks: [
69
+ localSqliteTelemetrySink(),
70
+ commandCenterTelemetrySink({ apiKey: process.env.VAUBAN_API_KEY! }),
71
+ ],
72
+ });
73
+
74
+ createOODAAgent({
75
+ agentId: "my-agent",
76
+ telemetry,
77
+ // …no more `createAgentRunTracker(db)` needed
78
+ });
79
+ ```
80
+
81
+ ## Recipes for common migrations
82
+
83
+ ### From `AgentRunTracker` to sinks
84
+
85
+ Before :
86
+
87
+ ```ts
88
+ const tracker = createAgentRunTracker(db);
89
+ const uuid = await tracker.start({ agentId, agentVersion, runId, model, provider });
90
+ await tracker.recordStep(uuid, { inputTokens, outputTokens, costUsd });
91
+ await tracker.finish(uuid, { status: "success" });
92
+ ```
93
+
94
+ After :
95
+
96
+ ```ts
97
+ // No imperative calls — the OODA loop handles it.
98
+ createOODAAgent({
99
+ agentId: "my-agent",
100
+ telemetry: localSqliteTelemetrySink(),
101
+ });
102
+ // runCycle() automatically emits start/step/finish.
103
+ ```
104
+
105
+ If you ran tracker calls *outside* the OODA loop (e.g. from a custom
106
+ event handler), you can still use it ; the loop's telemetry and the
107
+ custom calls coexist (they write to different tables in v1.3 :
108
+ `agent_run` for legacy tracker, `telemetry_run_step` for SDK sinks).
109
+
110
+ ### From `console.log` to stdoutTelemetrySink
111
+
112
+ Before :
113
+
114
+ ```ts
115
+ console.log("[my-agent] cycle start", { runId, agentId });
116
+ ```
117
+
118
+ After :
119
+
120
+ ```ts
121
+ createOODAAgent({
122
+ agentId: "my-agent",
123
+ telemetry: stdoutTelemetrySink(),
124
+ });
125
+ ```
126
+
127
+ You get structured JSON automatically, plus the same data lands in any
128
+ other sinks you configure later.
129
+
130
+ ## Removed (only in 2.0, not yet)
131
+
132
+ Targeted for removal in **2.0** (no earlier than Q4 2026) :
133
+
134
+ - `createAgentRunTracker(db)`
135
+ - `AgentRunTracker` interface
136
+ - `tracking/agent-run-tracker.ts` module
137
+ - `tracking/cost-tracked-agent-run-tracker.ts` (consumer in CC backend)
138
+
139
+ Until then, both APIs coexist.
140
+
141
+ ## Testing the upgrade
142
+
143
+ ```bash
144
+ # Pin to old version
145
+ pnpm add @vauban-org/agent-sdk@1.2.0
146
+
147
+ # Pin to new version
148
+ pnpm add @vauban-org/agent-sdk@1.3.0
149
+
150
+ # Run your test suite
151
+ pnpm test
152
+ ```
153
+
154
+ You should see 0 failures, 0 new warnings (other than the deprecation
155
+ notice if you still call `createAgentRunTracker`).
@@ -0,0 +1,154 @@
1
+ # Telemetry Overview
2
+
3
+ !!! info "Status — public-experimental"
4
+ Introduced in `@vauban-org/agent-sdk@1.3.0` (ADR-ECO-039). Interface
5
+ stable, additional event fields may be added before 2.0.
6
+
7
+ The agent-sdk exposes a **port-based telemetry pipeline** : agents emit
8
+ lifecycle events (`start` → `step…` → `finish`) and configurable **sinks**
9
+ decide where those events go. Sovereignty is preserved by default — no
10
+ network calls happen unless you explicitly opt in.
11
+
12
+ ## Why a port + sinks pattern ?
13
+
14
+ Before v1.3, the SDK had an implicit DB coupling (`AgentRunTracker.start`
15
+ INSERTed directly into a Command Center–specific `agent_run` table). That
16
+ violated three invariants : sovereignty (SDK unusable without the CC DB),
17
+ boundary discipline (SDK knowing CC schema), and standalone-product
18
+ design (CC should be an optional consumer).
19
+
20
+ The port pattern fixes all three. See the design rationale in
21
+ [ADR-ECO-039](https://github.com/vauban-org/vauban-gouvernance/blob/main/governance/decisions/ADR-ECO-039-sdk-telemetry-port.md).
22
+
23
+ ## Three usage modes
24
+
25
+ ```mermaid
26
+ graph TD
27
+ A[OODA loop runCycle()] -->|TelemetrySink| B[TelemetryBus]
28
+ B --> S1[stdoutTelemetrySink]
29
+ B --> S2[localSqliteTelemetrySink]
30
+ B --> S3[otlpTelemetrySink]
31
+ B --> S4["commandCenterTelemetrySink<br/>(separate npm pkg)"]
32
+
33
+ S1 -.-> O1[stderr / pino-pretty]
34
+ S2 -.-> O2["~/.vauban/runs.db"]
35
+ S3 -.-> O3["Langfuse / Tempo / Jaeger"]
36
+ S4 -.-> O4["command.vauban.tech<br/>or self-hosted CC"]
37
+ ```
38
+
39
+ ### Mode 1 — Standalone (sovereign default)
40
+
41
+ Zero phone-home. Zero account required. Runs everywhere.
42
+
43
+ ```ts
44
+ import {
45
+ createOODAAgent,
46
+ createTelemetryBus,
47
+ stdoutTelemetrySink,
48
+ localSqliteTelemetrySink,
49
+ } from "@vauban-org/agent-sdk";
50
+
51
+ createOODAAgent({
52
+ agentId: "my-agent",
53
+ /* …other config… */
54
+ telemetry: createTelemetryBus({
55
+ sinks: [
56
+ stdoutTelemetrySink(),
57
+ localSqliteTelemetrySink(), // ~/.vauban/runs.db by default
58
+ ],
59
+ }),
60
+ });
61
+ ```
62
+
63
+ Inspect locally via `sqlite3` or the upcoming `vauban-agent runs list` CLI.
64
+
65
+ ### Mode 2 — Free Vauban CC SaaS
66
+
67
+ Adds remote backup + a hosted dashboard at `command.vauban.tech`.
68
+
69
+ ```bash
70
+ pnpm add @vauban-org/cc-telemetry
71
+ ```
72
+
73
+ ```ts
74
+ import {
75
+ createOODAAgent,
76
+ createTelemetryBus,
77
+ localSqliteTelemetrySink,
78
+ } from "@vauban-org/agent-sdk";
79
+ import { commandCenterTelemetrySink } from "@vauban-org/cc-telemetry";
80
+
81
+ createOODAAgent({
82
+ agentId: "my-agent",
83
+ telemetry: createTelemetryBus({
84
+ sinks: [
85
+ localSqliteTelemetrySink(), // sovereign mirror
86
+ commandCenterTelemetrySink({ apiKey: process.env.VAUBAN_API_KEY! }),
87
+ ],
88
+ }),
89
+ });
90
+ ```
91
+
92
+ Free tier policy : **1 000 runs / month + 7 day retention** (see
93
+ [ADR-ECO-039 §3](https://github.com/vauban-org/vauban-gouvernance/blob/main/governance/decisions/ADR-ECO-039-sdk-telemetry-port.md)).
94
+ Sign up at [`command.vauban.tech`](https://command.vauban.tech).
95
+
96
+ ### Mode 3 — Tiered (Team / Pro / Sovereign)
97
+
98
+ Same code as Mode 2. The API key prefix (`vauban_team_*` / `vauban_pro_*` /
99
+ `vauban_sovereign_*`) determines server-side entitlement. Pro tier signs
100
+ each run with a Vauban Claim Algebra attestation ; Sovereign runs in a
101
+ TDX/SEV-SNP enclave with L3 Madara anchoring. See
102
+ [sinks/cc.md](sinks/cc.md#tiers).
103
+
104
+ ### Mode 4 — Self-hosted Command Center
105
+
106
+ Compatible with the AGPL CC backend (per [ADR-ECO-014](https://github.com/vauban-org/vauban-gouvernance/blob/main/governance/decisions/ADR-ECO-014-cc-oss-release.md)).
107
+
108
+ ```ts
109
+ commandCenterTelemetrySink({
110
+ apiKey: "internal",
111
+ baseUrl: "https://cc.myorg.internal",
112
+ });
113
+ ```
114
+
115
+ ## Privacy guarantees
116
+
117
+ | # | Guarantee | Enforced by |
118
+ |---|---|---|
119
+ | 1 | Zero phone-home by default | No sinks configured = no network |
120
+ | 2 | Local sink always available | `localSqliteTelemetrySink` ships with SDK |
121
+ | 3 | PII never crosses sinks | `metadata` hashed unless `includePayloads: true` |
122
+ | 4 | Tenant isolation | RLS in CC backend, scoped Bearer keys |
123
+ | 5 | Audit log of active sinks | `vauban-agent telemetry status` (upcoming) |
124
+ | 6 | Sink failures never block agent | TelemetryBus isolates per-sink failures |
125
+
126
+ ## Failure modes & guarantees
127
+
128
+ - **One sink crashes** → others continue. The agent loop is never blocked.
129
+ - **Network sink unreachable** → events queue locally up to `maxQueueDepth`
130
+ (default 1000), then drop-oldest with a Prometheus-friendly counter.
131
+ - **OOM / heap exceeded** → no retry storm ; the agent enters `skipped`
132
+ state with a `stopReason: "heap_exceeded:Xmb"` that surfaces in every
133
+ sink.
134
+ - **CC backend down** → SDK auto-retries 5xx with exponential backoff +
135
+ jitter. 4xx (auth, quota) are NOT retried (would only burn quota).
136
+
137
+ ## Where it sits relative to Langfuse
138
+
139
+ Both coexist by design ([Brain entry 1b9ab97d](https://command.vauban.tech/brain/1b9ab97d)) :
140
+
141
+ | Layer | What | Tool |
142
+ |---|---|---|
143
+ | Token-level | Per LLM call, latency, tokens, cost | Langfuse self-host |
144
+ | **Run-level** | **Per OODA cycle, status, outcome** | **TelemetryPort (this module)** |
145
+ | Outcome-level | Business value, HITL, proof | CC `outcome` table + L3 anchor |
146
+
147
+ ## Next steps
148
+
149
+ - [stdout sink](sinks/stdout.md) — dev visibility
150
+ - [SQLite sink](sinks/sqlite.md) — sovereign local mirror
151
+ - [OTLP sink](sinks/otlp.md) — push to any OpenTelemetry receiver
152
+ - [CC sink](sinks/cc.md) — Vauban Command Center (free → sovereign)
153
+ - [Privacy & spotlighting](privacy.md)
154
+ - [Migration 1.2 → 1.3](migration.md)