opsveritas-sdk 0.1.4 → 0.2.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 ADDED
@@ -0,0 +1,65 @@
1
+ # opsveritas-sdk
2
+
3
+ Monitor your AI agents in **three lines of code**. Tracks tokens, cost, latency, model, and silent failures (200 OK with empty output) — and routes alerts to Slack / Email / Teams via [OpsVeritas AI Agents Control Tower](https://agents.opsveritas.com).
4
+
5
+ ```bash
6
+ npm install opsveritas-sdk
7
+ ```
8
+
9
+ ## Quick start (3 lines)
10
+
11
+ ```ts
12
+ import { OpsVeritas } from 'opsveritas-sdk';
13
+
14
+ OpsVeritas.init('<your-ingest-key>'); // key from Settings → Integrations
15
+ const client = OpsVeritas.wrap(new OpenAI(), { agentName: 'Support Bot' });
16
+ // use `client` exactly as before — runs appear in your dashboard automatically
17
+ ```
18
+
19
+ Works the same for Anthropic and Gemini clients. Prefer manual control? Wrap a function:
20
+
21
+ ```ts
22
+ await OpsVeritas.trace('Nightly Report', async () => runReport());
23
+ ```
24
+
25
+ ## What data is sent
26
+
27
+ By design the SDK sends **metadata only, plus a short output snippet** — never your prompts/inputs:
28
+
29
+ | Sent | Detail |
30
+ |------|--------|
31
+ | ✅ Metadata | agent name, status, timestamps, duration, token counts, model, cost, tool-call count |
32
+ | ⚠️ Output snippet | first 300 chars of the response (`output_summary`) — powers silent-failure detection |
33
+ | ⚠️ Error message | the exception text, if a call fails |
34
+ | ❌ Prompts / inputs | **never sent** — only token counts |
35
+
36
+ ### Metadata-only mode (for regulated / client data)
37
+
38
+ Drop the output snippet and redact error text so **no response content ever leaves your environment** — token/cost/latency metadata still flows:
39
+
40
+ ```ts
41
+ OpsVeritas.init('<your-ingest-key>', { metadataOnly: true });
42
+ ```
43
+
44
+ Or set the environment variable:
45
+
46
+ ```bash
47
+ OPSVERITAS_METADATA_ONLY=true
48
+ ```
49
+
50
+ ## Reliability
51
+
52
+ Telemetry is **non-blocking and fire-and-forget** — it never throws into your code and never slows your agent. If the ingest endpoint is briefly unreachable, sends are **retried with backoff** and **buffered in memory** (bounded), then flushed on the next event — so a transient outage doesn't lose telemetry.
53
+
54
+ ## Configuration
55
+
56
+ ```ts
57
+ OpsVeritas.init(apiKey, {
58
+ endpoint, // optional — defaults to https://agents.opsveritas.com
59
+ metadataOnly, // optional — default false; when true, no response content is sent
60
+ });
61
+ ```
62
+
63
+ ## License
64
+
65
+ MIT
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  declare function init(apiKey: string, options?: {
2
2
  endpoint?: string;
3
+ metadataOnly?: boolean;
3
4
  }): void;
4
5
 
5
6
  declare function run<T>(agentName: string, fn: () => Promise<T>, opts?: {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  declare function init(apiKey: string, options?: {
2
2
  endpoint?: string;
3
+ metadataOnly?: boolean;
3
4
  }): void;
4
5
 
5
6
  declare function run<T>(agentName: string, fn: () => Promise<T>, opts?: {
package/dist/index.js CHANGED
@@ -35,7 +35,9 @@ function init(apiKey, options) {
35
35
  if (!apiKey || typeof apiKey !== "string") throw new Error("[OpsVeritas] apiKey is required");
36
36
  _config = {
37
37
  apiKey,
38
- endpoint: (options?.endpoint ?? "https://agents.opsveritas.com").replace(/\/$/, "")
38
+ endpoint: (options?.endpoint ?? "https://agents.opsveritas.com").replace(/\/$/, ""),
39
+ // Opt-in via init() or the OPSVERITAS_METADATA_ONLY=true env var. Defaults off (unchanged behavior).
40
+ metadataOnly: options?.metadataOnly ?? (typeof process !== "undefined" && process.env?.OPSVERITAS_METADATA_ONLY === "true")
39
41
  };
40
42
  }
41
43
  function getConfig() {
@@ -47,19 +49,77 @@ function getConfig() {
47
49
  var import_async_hooks = require("async_hooks");
48
50
 
49
51
  // src/http.ts
50
- async function sendExecution(payload) {
51
- const { apiKey, endpoint } = getConfig();
52
+ var RETRY_BACKOFF_MS = [500, 2e3, 5e3];
53
+ var MAX_BUFFER = 200;
54
+ var buffer = [];
55
+ var flushing = false;
56
+ function sleep(ms) {
57
+ return new Promise((resolve) => {
58
+ const t = setTimeout(resolve, ms);
59
+ if (typeof t?.unref === "function") t.unref();
60
+ });
61
+ }
62
+ function scrubForMetadataOnly(payload) {
63
+ return {
64
+ ...payload,
65
+ output_summary: void 0,
66
+ error_message: payload.error_message != null ? "[redacted \u2014 metadata-only mode]" : payload.error_message
67
+ };
68
+ }
69
+ async function postOnce(endpoint, apiKey, body) {
52
70
  try {
53
- await fetch(`${endpoint}/webhooks/agent-execution`, {
71
+ const res = await fetch(`${endpoint}/webhooks/agent-execution`, {
54
72
  method: "POST",
55
- headers: {
56
- "Content-Type": "application/json",
57
- "x-opsveritas-key": apiKey
58
- },
59
- body: JSON.stringify(payload)
73
+ headers: { "Content-Type": "application/json", "x-opsveritas-key": apiKey },
74
+ body: JSON.stringify(body)
60
75
  });
76
+ if (res.ok) return "ok";
77
+ if (res.status >= 400 && res.status < 500) return "drop";
78
+ return "retry";
79
+ } catch {
80
+ return "retry";
81
+ }
82
+ }
83
+ async function deliver(endpoint, apiKey, body) {
84
+ for (let attempt = 0; ; attempt++) {
85
+ const outcome = await postOnce(endpoint, apiKey, body);
86
+ if (outcome === "ok" || outcome === "drop") return true;
87
+ if (attempt >= RETRY_BACKOFF_MS.length) return false;
88
+ await sleep(RETRY_BACKOFF_MS[attempt]);
89
+ }
90
+ }
91
+ function enqueue(body) {
92
+ buffer.push(body);
93
+ while (buffer.length > MAX_BUFFER) buffer.shift();
94
+ }
95
+ async function flush(endpoint, apiKey) {
96
+ if (flushing || buffer.length === 0) return;
97
+ flushing = true;
98
+ try {
99
+ const pending = buffer.splice(0, buffer.length);
100
+ for (let i = 0; i < pending.length; i++) {
101
+ const ok = await deliver(endpoint, apiKey, pending[i]);
102
+ if (!ok) {
103
+ for (let j = pending.length - 1; j >= i; j--) buffer.unshift(pending[j]);
104
+ break;
105
+ }
106
+ }
107
+ } finally {
108
+ flushing = false;
109
+ }
110
+ }
111
+ async function sendExecution(payload) {
112
+ let cfg;
113
+ try {
114
+ cfg = getConfig();
61
115
  } catch {
116
+ return;
62
117
  }
118
+ const { apiKey, endpoint, metadataOnly } = cfg;
119
+ const body = metadataOnly ? scrubForMetadataOnly(payload) : payload;
120
+ void flush(endpoint, apiKey);
121
+ const ok = await deliver(endpoint, apiKey, body);
122
+ if (!ok) enqueue(body);
63
123
  }
64
124
 
65
125
  // src/context.ts
package/dist/index.mjs CHANGED
@@ -4,7 +4,9 @@ function init(apiKey, options) {
4
4
  if (!apiKey || typeof apiKey !== "string") throw new Error("[OpsVeritas] apiKey is required");
5
5
  _config = {
6
6
  apiKey,
7
- endpoint: (options?.endpoint ?? "https://agents.opsveritas.com").replace(/\/$/, "")
7
+ endpoint: (options?.endpoint ?? "https://agents.opsveritas.com").replace(/\/$/, ""),
8
+ // Opt-in via init() or the OPSVERITAS_METADATA_ONLY=true env var. Defaults off (unchanged behavior).
9
+ metadataOnly: options?.metadataOnly ?? (typeof process !== "undefined" && process.env?.OPSVERITAS_METADATA_ONLY === "true")
8
10
  };
9
11
  }
10
12
  function getConfig() {
@@ -16,19 +18,77 @@ function getConfig() {
16
18
  import { AsyncLocalStorage } from "async_hooks";
17
19
 
18
20
  // src/http.ts
19
- async function sendExecution(payload) {
20
- const { apiKey, endpoint } = getConfig();
21
+ var RETRY_BACKOFF_MS = [500, 2e3, 5e3];
22
+ var MAX_BUFFER = 200;
23
+ var buffer = [];
24
+ var flushing = false;
25
+ function sleep(ms) {
26
+ return new Promise((resolve) => {
27
+ const t = setTimeout(resolve, ms);
28
+ if (typeof t?.unref === "function") t.unref();
29
+ });
30
+ }
31
+ function scrubForMetadataOnly(payload) {
32
+ return {
33
+ ...payload,
34
+ output_summary: void 0,
35
+ error_message: payload.error_message != null ? "[redacted \u2014 metadata-only mode]" : payload.error_message
36
+ };
37
+ }
38
+ async function postOnce(endpoint, apiKey, body) {
21
39
  try {
22
- await fetch(`${endpoint}/webhooks/agent-execution`, {
40
+ const res = await fetch(`${endpoint}/webhooks/agent-execution`, {
23
41
  method: "POST",
24
- headers: {
25
- "Content-Type": "application/json",
26
- "x-opsveritas-key": apiKey
27
- },
28
- body: JSON.stringify(payload)
42
+ headers: { "Content-Type": "application/json", "x-opsveritas-key": apiKey },
43
+ body: JSON.stringify(body)
29
44
  });
45
+ if (res.ok) return "ok";
46
+ if (res.status >= 400 && res.status < 500) return "drop";
47
+ return "retry";
48
+ } catch {
49
+ return "retry";
50
+ }
51
+ }
52
+ async function deliver(endpoint, apiKey, body) {
53
+ for (let attempt = 0; ; attempt++) {
54
+ const outcome = await postOnce(endpoint, apiKey, body);
55
+ if (outcome === "ok" || outcome === "drop") return true;
56
+ if (attempt >= RETRY_BACKOFF_MS.length) return false;
57
+ await sleep(RETRY_BACKOFF_MS[attempt]);
58
+ }
59
+ }
60
+ function enqueue(body) {
61
+ buffer.push(body);
62
+ while (buffer.length > MAX_BUFFER) buffer.shift();
63
+ }
64
+ async function flush(endpoint, apiKey) {
65
+ if (flushing || buffer.length === 0) return;
66
+ flushing = true;
67
+ try {
68
+ const pending = buffer.splice(0, buffer.length);
69
+ for (let i = 0; i < pending.length; i++) {
70
+ const ok = await deliver(endpoint, apiKey, pending[i]);
71
+ if (!ok) {
72
+ for (let j = pending.length - 1; j >= i; j--) buffer.unshift(pending[j]);
73
+ break;
74
+ }
75
+ }
76
+ } finally {
77
+ flushing = false;
78
+ }
79
+ }
80
+ async function sendExecution(payload) {
81
+ let cfg;
82
+ try {
83
+ cfg = getConfig();
30
84
  } catch {
85
+ return;
31
86
  }
87
+ const { apiKey, endpoint, metadataOnly } = cfg;
88
+ const body = metadataOnly ? scrubForMetadataOnly(payload) : payload;
89
+ void flush(endpoint, apiKey);
90
+ const ok = await deliver(endpoint, apiKey, body);
91
+ if (!ok) enqueue(body);
32
92
  }
33
93
 
34
94
  // src/context.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opsveritas-sdk",
3
- "version": "0.1.4",
4
- "description": "Monitor your AI agents with 2 lines of code",
3
+ "version": "0.2.0",
4
+ "description": "Monitor your AI agents in 3 lines of code — tokens, cost, latency, and silent failures",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",