@intelli-1113/stratos-sdk 1.2.2 → 1.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 +552 -64
- package/package.json +41 -22
- package/src/cli-inspect.js +95 -0
- package/src/index.js +122 -34
- package/src/inspect-langchain.js +428 -0
- package/src/postinstall.js +29 -0
- package/src/register.js +41 -5
- package/src/vercel-ai-inject.js +78 -0
- package/src/vercel-ai-loader.js +99 -0
- package/src/vercel-ai.js +62 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* stratos-inspect — check LangChain version compatibility for Stratos metrics.
|
|
4
|
+
*
|
|
5
|
+
* npx stratos-inspect
|
|
6
|
+
* npx stratos-inspect --json
|
|
7
|
+
* npx stratos-inspect --fix
|
|
8
|
+
* npx stratos-inspect --fix --yes
|
|
9
|
+
* npx stratos-inspect --fix --dry-run
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
inspectLangChain,
|
|
14
|
+
fixLangChain,
|
|
15
|
+
printInspectReport,
|
|
16
|
+
} from "./inspect-langchain.js";
|
|
17
|
+
|
|
18
|
+
function parseArgs(argv) {
|
|
19
|
+
const flags = new Set(argv);
|
|
20
|
+
return {
|
|
21
|
+
json: flags.has("--json"),
|
|
22
|
+
fix: flags.has("--fix") || flags.has("--repair"),
|
|
23
|
+
yes: flags.has("--yes") || flags.has("-y"),
|
|
24
|
+
dryRun: flags.has("--dry-run"),
|
|
25
|
+
help: flags.has("--help") || flags.has("-h"),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function printHelp() {
|
|
30
|
+
console.log(`
|
|
31
|
+
stratos-inspect — LangChain compatibility for @intelli-1113/stratos-sdk
|
|
32
|
+
|
|
33
|
+
Usage:
|
|
34
|
+
stratos-inspect Inspect current project (cwd)
|
|
35
|
+
stratos-inspect --json Machine-readable report
|
|
36
|
+
stratos-inspect --fix Uninstall old LangChain (<1.0) and install 1.x
|
|
37
|
+
stratos-inspect --fix --yes Same, no confirmation prompt
|
|
38
|
+
stratos-inspect --fix --dry-run Show plan only
|
|
39
|
+
|
|
40
|
+
Why:
|
|
41
|
+
Stratos LangChain metrics need @langchain/core >=1.0.0 <2.0.0
|
|
42
|
+
(OpenLLMetry / @traceloop/instrumentation-langchain peer range).
|
|
43
|
+
|
|
44
|
+
Exit codes:
|
|
45
|
+
0 compatible (or no LangChain) / fix succeeded
|
|
46
|
+
1 incompatible or fix failed / cancelled
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function main() {
|
|
51
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
52
|
+
if (opts.help) {
|
|
53
|
+
printHelp();
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const report = inspectLangChain();
|
|
58
|
+
|
|
59
|
+
if (!opts.fix) {
|
|
60
|
+
printInspectReport(report, { json: opts.json });
|
|
61
|
+
process.exit(report.compatible ? 0 : 1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!opts.json) {
|
|
65
|
+
printInspectReport(report, { json: false });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const result = await fixLangChain({
|
|
69
|
+
yes: opts.yes,
|
|
70
|
+
dryRun: opts.dryRun,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (opts.json) {
|
|
74
|
+
console.log(JSON.stringify(result, null, 2));
|
|
75
|
+
} else if (result.dryRun) {
|
|
76
|
+
console.log("[stratos-inspect] Dry run plan:");
|
|
77
|
+
console.log(JSON.stringify(result.plan, null, 2));
|
|
78
|
+
} else if (result.cancelled) {
|
|
79
|
+
console.log("[stratos-inspect] Cancelled — no changes made.");
|
|
80
|
+
} else if (result.skipped) {
|
|
81
|
+
console.log(`[stratos-inspect] Skipped (${result.reason}). ${result.message || ""}`);
|
|
82
|
+
} else if (result.ok) {
|
|
83
|
+
console.log("[stratos-inspect] Done. LangChain should now be on 1.x.");
|
|
84
|
+
if (result.reportAfter) printInspectReport(result.reportAfter);
|
|
85
|
+
} else {
|
|
86
|
+
console.error(`[stratos-inspect] Fix failed: ${result.message || result.step || "unknown"}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
process.exit(result.ok || result.skipped ? 0 : 1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
main().catch((err) => {
|
|
93
|
+
console.error("[stratos-inspect]", err);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
});
|
package/src/index.js
CHANGED
|
@@ -1,38 +1,57 @@
|
|
|
1
1
|
// @intelli-1113/stratos-sdk — initialize OpenLLMetry and stream telemetry to Stratos AI.
|
|
2
2
|
//
|
|
3
|
-
// Config
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// Config (environment):
|
|
4
|
+
// STRATOS_TOKEN enrollment token from Stratos "Add agent" (required)
|
|
5
|
+
// STRATOS_URL Stratos origin (default http://localhost:4000)
|
|
6
|
+
// STRATOS_APP_NAME display name for this agent (optional)
|
|
7
|
+
// STRATOS_VERCEL_AI set 0 to disable auto Vercel AI patching (default on)
|
|
8
|
+
// STRATOS_FRAMEWORK override auto framework detection (optional)
|
|
8
9
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// right URL and runs a heartbeat so the agent shows online while it's up.
|
|
10
|
+
// Vercel AI: clients only need this register entry (or --import). No
|
|
11
|
+
// experimental_telemetry in their generateText/streamText calls.
|
|
12
12
|
import * as traceloop from "@traceloop/node-server-sdk";
|
|
13
13
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
14
14
|
import { createRequire } from "node:module";
|
|
15
15
|
import { readFileSync } from "node:fs";
|
|
16
16
|
import { join } from "node:path";
|
|
17
|
+
import { enableVercelAiTelemetry } from "./vercel-ai.js";
|
|
18
|
+
import { inspectLangChain } from "./inspect-langchain.js";
|
|
19
|
+
|
|
20
|
+
export { inspectLangChain, fixLangChain } from "./inspect-langchain.js";
|
|
17
21
|
|
|
18
22
|
const _require = createRequire(import.meta.url);
|
|
19
|
-
const resolvable = (pkg) => {
|
|
23
|
+
const resolvable = (pkg) => {
|
|
24
|
+
try {
|
|
25
|
+
_require.resolve(pkg);
|
|
26
|
+
return true;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const resolvableFromCwd = (pkg) => {
|
|
32
|
+
try {
|
|
33
|
+
createRequire(join(process.cwd(), "package.json")).resolve(pkg);
|
|
34
|
+
return true;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
20
39
|
|
|
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
40
|
function agentDeps() {
|
|
25
41
|
try {
|
|
26
|
-
const pkg = JSON.parse(
|
|
42
|
+
const pkg = JSON.parse(
|
|
43
|
+
readFileSync(join(process.cwd(), "package.json"), "utf8")
|
|
44
|
+
);
|
|
27
45
|
return { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
28
|
-
} catch {
|
|
46
|
+
} catch {
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
29
49
|
}
|
|
30
50
|
|
|
31
|
-
// Detect the agent framework from declared deps (preferred) or resolution — no manual input.
|
|
32
51
|
function detectFramework() {
|
|
52
|
+
if (process.env.STRATOS_FRAMEWORK) return process.env.STRATOS_FRAMEWORK;
|
|
33
53
|
const deps = agentDeps();
|
|
34
|
-
const has = (n) => n in deps || resolvable(n);
|
|
35
|
-
// Higher-level agent frameworks FIRST (several pull in @langchain/* transitively).
|
|
54
|
+
const has = (n) => n in deps || resolvableFromCwd(n) || resolvable(n);
|
|
36
55
|
if (has("@google/adk") || has("google-adk") || has("@iqai/adk")) return "google-adk";
|
|
37
56
|
if (has("@openai/agents")) return "openai-agents";
|
|
38
57
|
if (has("llamaindex")) return "llamaindex";
|
|
@@ -45,23 +64,44 @@ function detectFramework() {
|
|
|
45
64
|
if (has("openai")) return "openai";
|
|
46
65
|
return null;
|
|
47
66
|
}
|
|
48
|
-
|
|
67
|
+
|
|
49
68
|
function detectModel(opts) {
|
|
50
|
-
return
|
|
51
|
-
|
|
69
|
+
return (
|
|
70
|
+
opts.model ||
|
|
71
|
+
process.env.STRATOS_MODEL ||
|
|
72
|
+
process.env.NVIDIA_MODEL ||
|
|
73
|
+
process.env.OPENAI_MODEL ||
|
|
74
|
+
process.env.ANTHROPIC_MODEL ||
|
|
75
|
+
process.env.GEMINI_MODEL ||
|
|
76
|
+
process.env.GOOGLE_MODEL ||
|
|
77
|
+
process.env.LLM_MODEL ||
|
|
78
|
+
process.env.MODEL ||
|
|
79
|
+
null
|
|
80
|
+
);
|
|
52
81
|
}
|
|
53
82
|
|
|
54
83
|
let started = false;
|
|
55
84
|
|
|
56
85
|
export function start(opts = {}) {
|
|
57
|
-
if (started) return;
|
|
86
|
+
if (started) return;
|
|
58
87
|
const token = opts.token || process.env.STRATOS_TOKEN || "";
|
|
59
|
-
const origin = (opts.url || process.env.STRATOS_URL || "http://localhost:4000").replace(
|
|
60
|
-
|
|
61
|
-
|
|
88
|
+
const origin = (opts.url || process.env.STRATOS_URL || "http://localhost:4000").replace(
|
|
89
|
+
/\/+$/,
|
|
90
|
+
""
|
|
91
|
+
);
|
|
92
|
+
const appName =
|
|
93
|
+
opts.appName ||
|
|
94
|
+
process.env.STRATOS_APP_NAME ||
|
|
95
|
+
process.env.npm_package_name ||
|
|
96
|
+
"agent";
|
|
97
|
+
const heartbeatMs = Number(
|
|
98
|
+
opts.heartbeatMs || process.env.STRATOS_HEARTBEAT_MS || 30000
|
|
99
|
+
);
|
|
62
100
|
|
|
63
101
|
if (!token) {
|
|
64
|
-
console.warn(
|
|
102
|
+
console.warn(
|
|
103
|
+
"[stratos] STRATOS_TOKEN not set — telemetry disabled. Add the token from Stratos > Add agent."
|
|
104
|
+
);
|
|
65
105
|
return;
|
|
66
106
|
}
|
|
67
107
|
started = true;
|
|
@@ -72,26 +112,74 @@ export function start(opts = {}) {
|
|
|
72
112
|
traceloop.initialize({
|
|
73
113
|
appName,
|
|
74
114
|
disableBatch: true,
|
|
75
|
-
exporter: new OTLPTraceExporter({
|
|
115
|
+
exporter: new OTLPTraceExporter({
|
|
116
|
+
url: ingest,
|
|
117
|
+
headers: { "x-stratos-token": token },
|
|
118
|
+
}),
|
|
76
119
|
});
|
|
77
120
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
121
|
+
// LangChain version check (warn only — fix via: npx stratos-inspect --fix)
|
|
122
|
+
try {
|
|
123
|
+
const lc = inspectLangChain();
|
|
124
|
+
if (lc.hasLangChain && lc.needsAttention) {
|
|
125
|
+
console.warn(`[stratos] ${lc.message}`);
|
|
126
|
+
console.warn("[stratos] Fix: npx stratos-inspect --fix");
|
|
127
|
+
if (process.env.STRATOS_STRICT_LANGCHAIN === "1" && lc.needsUpgrade) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
"Incompatible @langchain/core (<1.0). Upgrade with: npx stratos-inspect --fix --yes"
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
} catch (err) {
|
|
134
|
+
if (process.env.STRATOS_STRICT_LANGCHAIN === "1") throw err;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Vercel AI v7 optional global register; v5/v6 covered by ESM loader in register.js
|
|
138
|
+
enableVercelAiTelemetry()
|
|
139
|
+
.then((r) => {
|
|
140
|
+
if (r.enabled) {
|
|
141
|
+
console.log(`[stratos] vercel-ai auto-telemetry: ${r.mode}`);
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
.catch(() => {});
|
|
145
|
+
|
|
146
|
+
const toolsEnv = (
|
|
147
|
+
opts.tools ||
|
|
148
|
+
(process.env.STRATOS_TOOLS || "").split(",")
|
|
149
|
+
)
|
|
150
|
+
.map((s) => String(s).trim())
|
|
151
|
+
.filter(Boolean);
|
|
152
|
+
|
|
153
|
+
const meta = {
|
|
154
|
+
framework: opts.framework || detectFramework(),
|
|
155
|
+
model: detectModel(opts),
|
|
156
|
+
tools: toolsEnv,
|
|
157
|
+
};
|
|
82
158
|
|
|
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
159
|
const ping = () =>
|
|
86
160
|
fetch(heartbeatUrl, {
|
|
87
161
|
method: "POST",
|
|
88
|
-
headers: {
|
|
162
|
+
headers: {
|
|
163
|
+
"x-stratos-token": token,
|
|
164
|
+
"Content-Type": "application/json",
|
|
165
|
+
},
|
|
89
166
|
body: JSON.stringify(meta),
|
|
90
167
|
}).catch(() => {});
|
|
91
168
|
ping();
|
|
92
169
|
if (heartbeatMs > 0) setInterval(ping, heartbeatMs).unref();
|
|
93
170
|
|
|
94
|
-
|
|
171
|
+
process.on("beforeExit", () => {
|
|
172
|
+
traceloop.forceFlush().catch(() => {});
|
|
173
|
+
});
|
|
174
|
+
for (const sig of ["SIGINT", "SIGTERM"]) {
|
|
175
|
+
process.on(sig, () => {
|
|
176
|
+
traceloop.forceFlush().finally(() => process.exit(0));
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log(
|
|
181
|
+
`[stratos] telemetry → ${ingest} (heartbeat ${heartbeatMs}ms, framework=${meta.framework || "?"})`
|
|
182
|
+
);
|
|
95
183
|
}
|
|
96
184
|
|
|
97
185
|
export default { start };
|