@intelli-1113/stratos-sdk 1.1.0 → 1.2.2
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 +10 -1
- package/package.json +1 -1
- package/src/index.js +97 -49
package/README.md
CHANGED
|
@@ -35,6 +35,12 @@ start({ token: "...", url: "https://stratos.lnt.com", appName: "my-agent" });
|
|
|
35
35
|
## Why it must load first
|
|
36
36
|
OpenLLMetry patches `openai`/`langchain` to capture spans — it has to run **before** those modules are imported. The `--import` flag and the `/register` entry both guarantee that.
|
|
37
37
|
|
|
38
|
+
## Auto-detected metadata (no manual entry)
|
|
39
|
+
On each heartbeat the SDK reports, and Stratos auto-fills:
|
|
40
|
+
- **framework** — detected from installed deps (langchain/langgraph, llamaindex, google-adk, vercel-ai, anthropic, openai…).
|
|
41
|
+
- **model** — from `STRATOS_MODEL` / `NVIDIA_MODEL` / `OPENAI_MODEL` / `ANTHROPIC_MODEL` / `LLM_MODEL` / `MODEL` (or `start({ model })`).
|
|
42
|
+
- **tools** — captured from spans automatically; you can also declare them via `STRATOS_TOOLS=a,b,c` or `start({ tools: [...] })`.
|
|
43
|
+
|
|
38
44
|
## Changing the URL or token
|
|
39
45
|
Both come from env, read at startup — change the `.env` value and restart. No code edit, no SDK re-publish.
|
|
40
46
|
|
|
@@ -48,7 +54,10 @@ npm i -g @intelli-1113/stratos-sdk
|
|
|
48
54
|
"weather": {
|
|
49
55
|
"command": "stratos-mcp-proxy",
|
|
50
56
|
"args": ["--","npx","-y","@scope/weather-mcp@latest"],
|
|
51
|
-
"env": {
|
|
57
|
+
"env": {
|
|
58
|
+
"STRATOS_TOKEN":"<token>",
|
|
59
|
+
"STRATOS_URL":"http://localhost:4000",
|
|
60
|
+
"STRATOS_APP_NAME":"weather" }
|
|
52
61
|
}
|
|
53
62
|
```
|
|
54
63
|
It forwards the JSON-RPC stream verbatim and reports each **tool call** (name, args, result, latency) + liveness.
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,49 +1,97 @@
|
|
|
1
|
-
// @intelli-1113/stratos-sdk — initialize OpenLLMetry and stream telemetry to Stratos AI.
|
|
2
|
-
//
|
|
3
|
-
// Config comes from the environment (so the ingest URL / token can change
|
|
4
|
-
// without editing code or re-publishing the SDK):
|
|
5
|
-
// STRATOS_TOKEN enrollment token from Stratos "Add agent" (required)
|
|
6
|
-
// STRATOS_URL Stratos origin, e.g. https://stratos.lnt.com (default http://localhost:4000)
|
|
7
|
-
// STRATOS_APP_NAME display name for this agent (optional)
|
|
8
|
-
//
|
|
9
|
-
// Why this exists: traceloop defaults to OTLP *protobuf* at <baseUrl>/v1/traces;
|
|
10
|
-
// Stratos ingests OTLP *JSON* at /api/ingest. This wires a JSON exporter to the
|
|
11
|
-
// right URL and runs a heartbeat so the agent shows online while it's up.
|
|
12
|
-
import * as traceloop from "@traceloop/node-server-sdk";
|
|
13
|
-
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
1
|
+
// @intelli-1113/stratos-sdk — initialize OpenLLMetry and stream telemetry to Stratos AI.
|
|
2
|
+
//
|
|
3
|
+
// Config comes from the environment (so the ingest URL / token can change
|
|
4
|
+
// without editing code or re-publishing the SDK):
|
|
5
|
+
// STRATOS_TOKEN enrollment token from Stratos "Add agent" (required)
|
|
6
|
+
// STRATOS_URL Stratos origin, e.g. https://stratos.lnt.com (default http://localhost:4000)
|
|
7
|
+
// STRATOS_APP_NAME display name for this agent (optional)
|
|
8
|
+
//
|
|
9
|
+
// Why this exists: traceloop defaults to OTLP *protobuf* at <baseUrl>/v1/traces;
|
|
10
|
+
// Stratos ingests OTLP *JSON* at /api/ingest. This wires a JSON exporter to the
|
|
11
|
+
// right URL and runs a heartbeat so the agent shows online while it's up.
|
|
12
|
+
import * as traceloop from "@traceloop/node-server-sdk";
|
|
13
|
+
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
|
|
18
|
+
const _require = createRequire(import.meta.url);
|
|
19
|
+
const resolvable = (pkg) => { try { _require.resolve(pkg); return true; } catch { return false; } };
|
|
20
|
+
|
|
21
|
+
// The agent's DIRECT dependencies (most reliable signal of the framework in use).
|
|
22
|
+
// Resolution alone is unreliable — some packages (e.g. @google/adk) block default
|
|
23
|
+
// resolution via "exports", and others appear only transitively.
|
|
24
|
+
function agentDeps() {
|
|
25
|
+
try {
|
|
26
|
+
const pkg = JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf8"));
|
|
27
|
+
return { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
28
|
+
} catch { return {}; }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Detect the agent framework from declared deps (preferred) or resolution — no manual input.
|
|
32
|
+
function detectFramework() {
|
|
33
|
+
const deps = agentDeps();
|
|
34
|
+
const has = (n) => n in deps || resolvable(n);
|
|
35
|
+
// Higher-level agent frameworks FIRST (several pull in @langchain/* transitively).
|
|
36
|
+
if (has("@google/adk") || has("google-adk") || has("@iqai/adk")) return "google-adk";
|
|
37
|
+
if (has("@openai/agents")) return "openai-agents";
|
|
38
|
+
if (has("llamaindex")) return "llamaindex";
|
|
39
|
+
if (has("crewai")) return "crewai";
|
|
40
|
+
if (has("@langchain/langgraph")) return "langgraph";
|
|
41
|
+
if (has("langchain") || has("@langchain/core")) return "langchain";
|
|
42
|
+
if (has("ai")) return "vercel-ai";
|
|
43
|
+
if (has("@google/generative-ai") || has("@google/genai")) return "google-genai";
|
|
44
|
+
if (has("@anthropic-ai/sdk")) return "anthropic";
|
|
45
|
+
if (has("openai")) return "openai";
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
// Best-effort model from common env vars (or opts.model). Spans still refine it.
|
|
49
|
+
function detectModel(opts) {
|
|
50
|
+
return opts.model || process.env.STRATOS_MODEL || process.env.NVIDIA_MODEL || process.env.OPENAI_MODEL
|
|
51
|
+
|| process.env.ANTHROPIC_MODEL || process.env.LLM_MODEL || process.env.MODEL || null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let started = false;
|
|
55
|
+
|
|
56
|
+
export function start(opts = {}) {
|
|
57
|
+
if (started) return; // idempotent — safe to import/register more than once
|
|
58
|
+
const token = opts.token || process.env.STRATOS_TOKEN || "";
|
|
59
|
+
const origin = (opts.url || process.env.STRATOS_URL || "http://localhost:4000").replace(/\/+$/, "");
|
|
60
|
+
const appName = opts.appName || process.env.STRATOS_APP_NAME || process.env.npm_package_name || "agent";
|
|
61
|
+
const heartbeatMs = Number(opts.heartbeatMs || process.env.STRATOS_HEARTBEAT_MS || 30000);
|
|
62
|
+
|
|
63
|
+
if (!token) {
|
|
64
|
+
console.warn("[stratos] STRATOS_TOKEN not set — telemetry disabled. Add the token from Stratos > Add agent.");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
started = true;
|
|
68
|
+
|
|
69
|
+
const ingest = `${origin}/api/ingest`;
|
|
70
|
+
const heartbeatUrl = `${origin}/api/heartbeat`;
|
|
71
|
+
|
|
72
|
+
traceloop.initialize({
|
|
73
|
+
appName,
|
|
74
|
+
disableBatch: true,
|
|
75
|
+
exporter: new OTLPTraceExporter({ url: ingest, headers: { "x-stratos-token": token } }),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Auto-detected metadata sent on every heartbeat → Stratos auto-fills the
|
|
79
|
+
// agent's framework/model/tools (no manual entry, no reliance on span quality).
|
|
80
|
+
const toolsEnv = (opts.tools || (process.env.STRATOS_TOOLS || "").split(",")).map((s) => String(s).trim()).filter(Boolean);
|
|
81
|
+
const meta = { framework: detectFramework(), model: detectModel(opts), tools: toolsEnv };
|
|
82
|
+
|
|
83
|
+
// Keep the agent "online" while the process is alive (telemetry alone only
|
|
84
|
+
// fires on LLM calls, which would let liveness lapse between requests).
|
|
85
|
+
const ping = () =>
|
|
86
|
+
fetch(heartbeatUrl, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "x-stratos-token": token, "Content-Type": "application/json" },
|
|
89
|
+
body: JSON.stringify(meta),
|
|
90
|
+
}).catch(() => {});
|
|
91
|
+
ping();
|
|
92
|
+
if (heartbeatMs > 0) setInterval(ping, heartbeatMs).unref();
|
|
93
|
+
|
|
94
|
+
console.log(`[stratos] telemetry → ${ingest} (heartbeat ${heartbeatMs}ms, framework=${meta.framework || "?"})`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export default { start };
|