@lmnr-ai/lmnr 0.8.39 → 0.8.41
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/dist/cli.cjs +2 -2
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{dist-oS06mAi1.cjs → dist-BNoIH9xW.cjs} +67 -6
- package/dist/dist-BNoIH9xW.cjs.map +1 -0
- package/dist/{dist-Dgq2z7AD.mjs → dist-D-1LE3Xx.mjs} +62 -7
- package/dist/dist-D-1LE3Xx.mjs.map +1 -0
- package/dist/{evaluations-BUitiaxR.d.cts → evaluations-CeDsphK5.d.cts} +99 -27
- package/dist/{evaluations-gHrXUnIp.d.mts → evaluations-pCcE5lVy.d.mts} +99 -27
- package/dist/{file-utils-Bf15ARiL.cjs → file-utils-B7VBQSna.cjs} +2 -2
- package/dist/{file-utils-Bf15ARiL.cjs.map → file-utils-B7VBQSna.cjs.map} +1 -1
- package/dist/{file-utils-D0UCmQi0.mjs → file-utils-DNyYjjV3.mjs} +2 -2
- package/dist/{file-utils-D0UCmQi0.mjs.map → file-utils-DNyYjjV3.mjs.map} +1 -1
- package/dist/index.cjs +337 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +337 -48
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/dist-Dgq2z7AD.mjs.map +0 -1
- package/dist/dist-oS06mAi1.cjs.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as __exportAll, S as TracingLevel, _ as MaskInputOptions, a as HumanEvaluator, b as SpanType, c as InitializeOptions, d as LaminarClient, f as Dataset, g as LaminarSpanContext, h as Event, i as EvaluatorFunctionReturn, l as EvaluationDataset, m as EvaluationDatapointDatasetLink, o as evaluate, p as EvaluationDatapoint, r as EvaluatorFunction, s as StringUUID, t as Datapoint, u as LaminarDataset, v as PushDatapointsResponse, x as TraceType, y as SessionRecordingOptions } from "./evaluations-
|
|
1
|
+
import { C as __exportAll, S as TracingLevel, _ as MaskInputOptions, a as HumanEvaluator, b as SpanType, c as InitializeOptions, d as LaminarClient, f as Dataset, g as LaminarSpanContext, h as Event, i as EvaluatorFunctionReturn, l as EvaluationDataset, m as EvaluationDatapointDatasetLink, o as evaluate, p as EvaluationDatapoint, r as EvaluatorFunction, s as StringUUID, t as Datapoint, u as LaminarDataset, v as PushDatapointsResponse, x as TraceType, y as SessionRecordingOptions } from "./evaluations-CeDsphK5.cjs";
|
|
2
2
|
import { ServerResponse } from "node:http";
|
|
3
3
|
import { ReadableSpan, SpanExporter, SpanProcessor, TimedEvent } from "@opentelemetry/sdk-trace-base";
|
|
4
4
|
import { AttributeValue, Attributes, Context, Exception, HrTime, Link, Span, Span as Span$1, SpanContext, SpanKind, SpanStatus, TimeInput, Tracer, TracerProvider } from "@opentelemetry/api";
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as TracingLevel, _ as MaskInputOptions, a as HumanEvaluator, b as SpanType, c as InitializeOptions, d as LaminarClient, f as Dataset, g as LaminarSpanContext, h as Event, i as EvaluatorFunctionReturn, l as EvaluationDataset, m as EvaluationDatapointDatasetLink, o as evaluate, p as EvaluationDatapoint, r as EvaluatorFunction, s as StringUUID, t as Datapoint, u as LaminarDataset, v as PushDatapointsResponse, x as TraceType, y as SessionRecordingOptions } from "./evaluations-
|
|
1
|
+
import { S as TracingLevel, _ as MaskInputOptions, a as HumanEvaluator, b as SpanType, c as InitializeOptions, d as LaminarClient, f as Dataset, g as LaminarSpanContext, h as Event, i as EvaluatorFunctionReturn, l as EvaluationDataset, m as EvaluationDatapointDatasetLink, o as evaluate, p as EvaluationDatapoint, r as EvaluatorFunction, s as StringUUID, t as Datapoint, u as LaminarDataset, v as PushDatapointsResponse, x as TraceType, y as SessionRecordingOptions } from "./evaluations-pCcE5lVy.mjs";
|
|
2
2
|
import { AttributeValue, Attributes, Context, Exception, HrTime, Link, Span, Span as Span$1, SpanContext, SpanKind, SpanStatus, TimeInput, Tracer, TracerProvider } from "@opentelemetry/api";
|
|
3
3
|
import { Instrumentation, InstrumentationBase } from "@opentelemetry/instrumentation";
|
|
4
4
|
import { ReadableSpan, SpanExporter, SpanProcessor, TimedEvent } from "@opentelemetry/sdk-trace-base";
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __require } from "./rolldown-runtime-2rV9d50f.mjs";
|
|
2
|
-
import { A as
|
|
2
|
+
import { A as SPAN_INSTRUMENTATION_SCOPE_VERSION, B as version, C as LaminarAttributes, D as SPAN_IDS_PATH, E as SESSION_ID, F as SPAN_SDK_VERSION, H as DEBUG_SESSION_FILE, I as SPAN_TYPE, L as TRACE_HAS_BROWSER_SESSION, M as SPAN_LANGUAGE_VERSION, N as SPAN_OUTPUT, O as SPAN_INPUT, P as SPAN_PATH, R as TRACE_TYPE, S as HUMAN_EVALUATOR_OPTIONS, T as PARENT_SPAN_PATH, U as TracingLevel, V as DEBUG_SESSION_DIR, W as errorMessage, _ as truncateSpanPayload, b as ASSOCIATION_PROPERTIES, c as initializeLogger, d as newUUID, f as normalizeOtelSpanId, g as parseOtelHeaders, h as otelTraceIdToUUID, i as deserializeLaminarSpanContext, j as SPAN_INSTRUMENTATION_SOURCE, k as SPAN_INSTRUMENTATION_SCOPE_NAME, l as loadEnv, m as otelSpanIdToUUID, n as NIL_UUID, o as getFrontendUrl, p as normalizeOtelTraceId, r as Semaphore, s as getOtelEnvVar, t as LaminarClient, u as metadataToAttributes, v as tryToOtelSpanContext, w as PARENT_SPAN_IDS_PATH, x as ASSOCIATION_PROPERTIES_OVERRIDES, y as validateTracingConfig, z as USER_ID } from "./dist-D-1LE3Xx.mjs";
|
|
3
3
|
import { n as TRACEPARENT_HEADER, t as LAMINAR_SPAN_CONTEXT_HEADER } from "./consts-3AfXaMBI.mjs";
|
|
4
4
|
import { DiagConsoleLogger, DiagLogLevel, ROOT_CONTEXT, SpanKind, SpanStatusCode, TraceFlags, context, createContextKey, diag, isSpanContextValid, trace } from "@opentelemetry/api";
|
|
5
5
|
import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
|
|
@@ -34,6 +34,25 @@ import * as cliProgress from "cli-progress";
|
|
|
34
34
|
import { blake3 } from "@noble/hashes/blake3.js";
|
|
35
35
|
import { bytesToHex } from "@noble/hashes/utils.js";
|
|
36
36
|
import * as diagnosticsChannel from "node:diagnostics_channel";
|
|
37
|
+
//#region src/datasets/prng.ts
|
|
38
|
+
const UINT32 = 4294967296;
|
|
39
|
+
const seededPerm = (n, seed) => {
|
|
40
|
+
let state = seed >>> 0;
|
|
41
|
+
const next = () => {
|
|
42
|
+
state = state + 1831565813 >>> 0;
|
|
43
|
+
let t = state;
|
|
44
|
+
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
45
|
+
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
46
|
+
return ((t ^ t >>> 14) >>> 0) / UINT32;
|
|
47
|
+
};
|
|
48
|
+
const ix = Array.from({ length: n }, (_, i) => i);
|
|
49
|
+
for (let i = n - 1; i > 0; i--) {
|
|
50
|
+
const j = Math.floor(next() * (i + 1));
|
|
51
|
+
[ix[i], ix[j]] = [ix[j], ix[i]];
|
|
52
|
+
}
|
|
53
|
+
return ix;
|
|
54
|
+
};
|
|
55
|
+
//#endregion
|
|
37
56
|
//#region src/datasets.ts
|
|
38
57
|
const DEFAULT_FETCH_SIZE = 25;
|
|
39
58
|
var EvaluationDataset = class {
|
|
@@ -42,13 +61,66 @@ var EvaluationDataset = class {
|
|
|
42
61
|
for (let i = Math.max(start, 0); i < Math.min(end, await this.size()); i++) result.push(await this.get(i));
|
|
43
62
|
return result;
|
|
44
63
|
}
|
|
64
|
+
sourceDataset() {}
|
|
65
|
+
take(n) {
|
|
66
|
+
return new Transformed(this, async (base) => {
|
|
67
|
+
if (!Number.isInteger(n)) throw new Error(`take count ${n} is not an integer`);
|
|
68
|
+
const size = await base.size();
|
|
69
|
+
const count = Math.max(0, Math.min(n, size));
|
|
70
|
+
return Array.from({ length: count }, (_, i) => i);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
select(indices) {
|
|
74
|
+
const selected = [...indices];
|
|
75
|
+
return new Transformed(this, async (base) => {
|
|
76
|
+
const size = await base.size();
|
|
77
|
+
for (const index of selected) {
|
|
78
|
+
if (!Number.isInteger(index)) throw new Error(`select index ${index} is not an integer`);
|
|
79
|
+
if (index < 0 || index >= size) throw new Error(`select index ${index} is out of range for dataset of size ${size}`);
|
|
80
|
+
}
|
|
81
|
+
return selected;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
shuffle({ seed = 0 } = {}) {
|
|
85
|
+
return new Transformed(this, async (base) => seededPerm(await base.size(), seed));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var Transformed = class extends EvaluationDataset {
|
|
89
|
+
constructor(base, resolve) {
|
|
90
|
+
super();
|
|
91
|
+
this.indices = null;
|
|
92
|
+
this.resolving = null;
|
|
93
|
+
this.base = base;
|
|
94
|
+
this.resolve = resolve;
|
|
95
|
+
}
|
|
96
|
+
resolveIndices() {
|
|
97
|
+
if (this.indices !== null) return Promise.resolve(this.indices);
|
|
98
|
+
if (this.resolving === null) this.resolving = this.resolve(this.base).then((indices) => {
|
|
99
|
+
this.indices = indices;
|
|
100
|
+
return indices;
|
|
101
|
+
}).catch((err) => {
|
|
102
|
+
this.resolving = null;
|
|
103
|
+
throw err;
|
|
104
|
+
});
|
|
105
|
+
return this.resolving;
|
|
106
|
+
}
|
|
107
|
+
async size() {
|
|
108
|
+
return (await this.resolveIndices()).length;
|
|
109
|
+
}
|
|
110
|
+
async get(index) {
|
|
111
|
+
const indices = await this.resolveIndices();
|
|
112
|
+
if (index < 0 || index >= indices.length) throw new Error(`Index ${index} is out of range for dataset of size ${indices.length}`);
|
|
113
|
+
return await this.base.get(indices[index]);
|
|
114
|
+
}
|
|
115
|
+
sourceDataset() {
|
|
116
|
+
return this.base.sourceDataset();
|
|
117
|
+
}
|
|
45
118
|
};
|
|
46
119
|
var LaminarDataset = class extends EvaluationDataset {
|
|
47
120
|
constructor(name, options) {
|
|
48
121
|
super();
|
|
49
|
-
this.
|
|
122
|
+
this.pages = /* @__PURE__ */ new Map();
|
|
50
123
|
this.len = null;
|
|
51
|
-
this.offset = 0;
|
|
52
124
|
this.client = void 0;
|
|
53
125
|
if (!name && !options?.id) throw new Error("Either name or id must be provided");
|
|
54
126
|
if (name && options?.id) throw new Error("Only one of name or id must be provided");
|
|
@@ -59,25 +131,42 @@ var LaminarDataset = class extends EvaluationDataset {
|
|
|
59
131
|
setClient(client) {
|
|
60
132
|
this.client = client;
|
|
61
133
|
}
|
|
62
|
-
|
|
134
|
+
sourceDataset() {
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
fetchPage(offset) {
|
|
138
|
+
const existing = this.pages.get(offset);
|
|
139
|
+
if (existing) return existing;
|
|
140
|
+
const pending = this.doFetchPage(offset).catch((err) => {
|
|
141
|
+
this.pages.delete(offset);
|
|
142
|
+
throw err;
|
|
143
|
+
});
|
|
144
|
+
this.pages.set(offset, pending);
|
|
145
|
+
return pending;
|
|
146
|
+
}
|
|
147
|
+
async doFetchPage(offset) {
|
|
63
148
|
if (!this.client) throw new Error("Client not set");
|
|
64
149
|
const identifier = this.id ? { id: this.id } : { name: this.name };
|
|
65
150
|
const resp = await this.client.datasets.pull({
|
|
66
151
|
...identifier,
|
|
67
|
-
offset
|
|
152
|
+
offset,
|
|
68
153
|
limit: this.fetchSize
|
|
69
154
|
});
|
|
70
|
-
this.fetchedItems = this.fetchedItems.concat(resp.items);
|
|
71
|
-
this.offset = this.fetchedItems.length;
|
|
72
155
|
if (this.len === null) this.len = resp.totalCount;
|
|
156
|
+
return resp.items;
|
|
73
157
|
}
|
|
74
158
|
async size() {
|
|
75
|
-
if (this.len === null) await this.
|
|
159
|
+
if (this.len === null) await this.fetchPage(0);
|
|
76
160
|
return this.len;
|
|
77
161
|
}
|
|
78
162
|
async get(index) {
|
|
79
|
-
if (index
|
|
80
|
-
|
|
163
|
+
if (index < 0) throw new Error(`Index ${index} is out of range`);
|
|
164
|
+
if (this.len !== null && index >= this.len) throw new Error(`Index ${index} is out of range for dataset of size ${this.len}`);
|
|
165
|
+
const offset = Math.floor(index / this.fetchSize) * this.fetchSize;
|
|
166
|
+
const page = await this.fetchPage(offset);
|
|
167
|
+
const local = index - offset;
|
|
168
|
+
if (local >= page.length) throw new Error(`Index ${index} is out of range for dataset of size ${this.len ?? "unknown"}`);
|
|
169
|
+
return page[local];
|
|
81
170
|
}
|
|
82
171
|
/**
|
|
83
172
|
* Push data from files to this dataset.
|
|
@@ -87,7 +176,7 @@ var LaminarDataset = class extends EvaluationDataset {
|
|
|
87
176
|
*/
|
|
88
177
|
async push(paths, recursive = false) {
|
|
89
178
|
if (!this.client) throw new Error("Client not set");
|
|
90
|
-
const { loadFromPaths } = await import("./file-utils-
|
|
179
|
+
const { loadFromPaths } = await import("./file-utils-DNyYjjV3.mjs").then((n) => n.t);
|
|
91
180
|
const data = await loadFromPaths(Array.isArray(paths) ? paths : [paths], recursive);
|
|
92
181
|
if (data.length === 0) {
|
|
93
182
|
console.warn("No data to push. Skipping");
|
|
@@ -1056,11 +1145,11 @@ var LaminarSpan = class LaminarSpan {
|
|
|
1056
1145
|
}
|
|
1057
1146
|
setInput(input) {
|
|
1058
1147
|
const finalInput = typeof input === "string" ? input : JSON.stringify(input);
|
|
1059
|
-
this._span.setAttribute(SPAN_INPUT, finalInput);
|
|
1148
|
+
this._span.setAttribute(SPAN_INPUT, truncateSpanPayload(finalInput, "input"));
|
|
1060
1149
|
}
|
|
1061
1150
|
setOutput(output) {
|
|
1062
1151
|
const finalOutput = typeof output === "string" ? output : JSON.stringify(output);
|
|
1063
|
-
this._span.setAttribute(SPAN_OUTPUT, finalOutput);
|
|
1152
|
+
this._span.setAttribute(SPAN_OUTPUT, truncateSpanPayload(finalOutput, "output"));
|
|
1064
1153
|
}
|
|
1065
1154
|
setTags(tags) {
|
|
1066
1155
|
this._span.setAttribute(`${ASSOCIATION_PROPERTIES}.tags`, Array.from(new Set(tags)));
|
|
@@ -1333,12 +1422,181 @@ const BEDROCK_USE_ENV = "CLAUDE_CODE_USE_BEDROCK";
|
|
|
1333
1422
|
const BEDROCK_AWS_REGION_ENV = "AWS_REGION";
|
|
1334
1423
|
const VERTEX_BASE_URL_ENV = "ANTHROPIC_VERTEX_BASE_URL";
|
|
1335
1424
|
const VERTEX_USE_ENV = "CLAUDE_CODE_USE_VERTEX";
|
|
1425
|
+
const PROXY_BASE_URL_ENV_KEYS = [
|
|
1426
|
+
"ANTHROPIC_BASE_URL",
|
|
1427
|
+
FOUNDRY_BASE_URL_ENV,
|
|
1428
|
+
BEDROCK_BASE_URL_ENV,
|
|
1429
|
+
VERTEX_BASE_URL_ENV
|
|
1430
|
+
];
|
|
1431
|
+
const PROVIDER_BASE_URL_ENV_KEYS = [
|
|
1432
|
+
[FOUNDRY_BASE_URL_ENV, FOUNDRY_USE_ENV],
|
|
1433
|
+
[BEDROCK_BASE_URL_ENV, BEDROCK_USE_ENV],
|
|
1434
|
+
[VERTEX_BASE_URL_ENV, VERTEX_USE_ENV]
|
|
1435
|
+
];
|
|
1436
|
+
const PROXY_ENV_KEYS = [
|
|
1437
|
+
"HTTP_PROXY",
|
|
1438
|
+
"HTTPS_PROXY",
|
|
1439
|
+
"http_proxy",
|
|
1440
|
+
"https_proxy"
|
|
1441
|
+
];
|
|
1442
|
+
const PROXY_NEUTRALIZED_ENV_KEYS = [...PROXY_ENV_KEYS, FOUNDRY_RESOURCE_ENV];
|
|
1443
|
+
const UPSTREAM_SETTINGS_EXCLUDED_ENV_KEYS = PROXY_ENV_KEYS;
|
|
1336
1444
|
const activeProxyServers = /* @__PURE__ */ new Set();
|
|
1337
1445
|
let globalShutdownRegistered = false;
|
|
1338
1446
|
/**
|
|
1339
|
-
* Check
|
|
1447
|
+
* Check whether an env value enables a feature.
|
|
1448
|
+
*
|
|
1449
|
+
* Claude Code accepts `1`, `true`, `yes`, and `on` (case-insensitive) — verified
|
|
1450
|
+
* against the bundled CLI. Accepting only `"1"` would miss a provider the CLI
|
|
1451
|
+
* considers enabled, so we would blank its routing keys without pinning a base
|
|
1452
|
+
* URL and break the run.
|
|
1340
1453
|
*/
|
|
1341
|
-
const isTruthyEnv = (value) =>
|
|
1454
|
+
const isTruthyEnv = (value) => {
|
|
1455
|
+
if (typeof value !== "string") return value === true;
|
|
1456
|
+
return [
|
|
1457
|
+
"1",
|
|
1458
|
+
"true",
|
|
1459
|
+
"yes",
|
|
1460
|
+
"on"
|
|
1461
|
+
].includes(value.trim().toLowerCase());
|
|
1462
|
+
};
|
|
1463
|
+
/**
|
|
1464
|
+
* Whether a provider flag is enabled in the given env, using the CLI's own
|
|
1465
|
+
* truthiness rules.
|
|
1466
|
+
*
|
|
1467
|
+
* Exported so the subprocess-env pin path shares ONE definition of "enabled"
|
|
1468
|
+
* with `getEnvVarsToRemove` / `buildProxyFlagSettings`. If they disagree, the
|
|
1469
|
+
* resource gets stripped without a base URL being pinned and the CLI hard-fails.
|
|
1470
|
+
*/
|
|
1471
|
+
const isProviderEnabledInEnv = (env, useKey) => isTruthyEnv(env[useKey]);
|
|
1472
|
+
/**
|
|
1473
|
+
* Load a Claude settings JSON file, or `null` when it could not be read.
|
|
1474
|
+
*
|
|
1475
|
+
* `null` (unreadable / malformed / not a JSON object) is deliberately distinct
|
|
1476
|
+
* from `{}` (a valid but empty settings file): callers that would otherwise
|
|
1477
|
+
* REPLACE a user's settings need to know they failed to read it.
|
|
1478
|
+
*/
|
|
1479
|
+
const loadSettingsFile = (filePath) => {
|
|
1480
|
+
try {
|
|
1481
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
1482
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
|
|
1483
|
+
} catch {}
|
|
1484
|
+
return null;
|
|
1485
|
+
};
|
|
1486
|
+
const settingsEnvBlock = (settings) => {
|
|
1487
|
+
const env = settings.env;
|
|
1488
|
+
if (!env || typeof env !== "object" || Array.isArray(env)) return {};
|
|
1489
|
+
const result = {};
|
|
1490
|
+
for (const [key, value] of Object.entries(env)) if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") result[key] = String(value);
|
|
1491
|
+
return result;
|
|
1492
|
+
};
|
|
1493
|
+
/**
|
|
1494
|
+
* Read the merged `env` block from Claude Code's on-disk settings layers.
|
|
1495
|
+
*
|
|
1496
|
+
* Claude Code applies these to the CLI session with HIGHER priority than the
|
|
1497
|
+
* subprocess environment, so a user with `ANTHROPIC_BASE_URL` in
|
|
1498
|
+
* `~/.claude/settings.json` silently bypasses our proxy. We read them to resolve
|
|
1499
|
+
* the real upstream and to detect conflicts.
|
|
1500
|
+
*
|
|
1501
|
+
* Precedence (highest first): local project, shared project, user.
|
|
1502
|
+
*
|
|
1503
|
+
* `settingSources` mirrors `options.settingSources` and gates which layers are
|
|
1504
|
+
* read: `undefined` means the CLI loads all of them, an array means only those,
|
|
1505
|
+
* and `[]` disables on-disk settings entirely. Honoring it matters because
|
|
1506
|
+
* reading a layer the CLI was told to ignore would resolve an upstream the CLI
|
|
1507
|
+
* never uses, pointing the proxy at an unintended host.
|
|
1508
|
+
*/
|
|
1509
|
+
const readClaudeSettingsEnv = (cwd, settingSources) => {
|
|
1510
|
+
const sessionCwd = cwd ?? process.cwd();
|
|
1511
|
+
const userDir = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), ".claude");
|
|
1512
|
+
const layers = [
|
|
1513
|
+
["user", path.join(userDir, "settings.json")],
|
|
1514
|
+
["project", path.join(sessionCwd, ".claude", "settings.json")],
|
|
1515
|
+
["local", path.join(sessionCwd, ".claude", "settings.local.json")]
|
|
1516
|
+
];
|
|
1517
|
+
const merged = {};
|
|
1518
|
+
for (const [source, filePath] of layers) {
|
|
1519
|
+
if (settingSources !== void 0 && !settingSources.includes(source)) continue;
|
|
1520
|
+
Object.assign(merged, settingsEnvBlock(loadSettingsFile(filePath) ?? {}));
|
|
1521
|
+
}
|
|
1522
|
+
return merged;
|
|
1523
|
+
};
|
|
1524
|
+
/**
|
|
1525
|
+
* Read the `env` block out of the caller's `options.settings` (the flag layer).
|
|
1526
|
+
*
|
|
1527
|
+
* This layer OUTRANKS every on-disk layer, so a gateway or provider config that
|
|
1528
|
+
* lives only here is what the CLI would actually use — and
|
|
1529
|
+
* `buildProxyFlagSettings` is about to overwrite those keys with the proxy URL.
|
|
1530
|
+
* Upstream resolution must therefore see it FIRST, or we forward to the wrong
|
|
1531
|
+
* host (or to the default endpoint) while the caller's gateway is silently lost.
|
|
1532
|
+
*
|
|
1533
|
+
* Returns `{}` for a value we could not read; the caller's own bail-out logic in
|
|
1534
|
+
* `buildProxyFlagSettings` handles that case.
|
|
1535
|
+
*/
|
|
1536
|
+
const flagSettingsEnv = (existing, cwd) => {
|
|
1537
|
+
if (typeof existing === "object" && existing !== null) return settingsEnvBlock(existing);
|
|
1538
|
+
if (typeof existing !== "string" || !existing.trim()) return {};
|
|
1539
|
+
const trimmed = existing.trim();
|
|
1540
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
1541
|
+
try {
|
|
1542
|
+
const parsed = JSON.parse(trimmed);
|
|
1543
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return settingsEnvBlock(parsed);
|
|
1544
|
+
} catch {}
|
|
1545
|
+
return {};
|
|
1546
|
+
}
|
|
1547
|
+
return settingsEnvBlock(loadSettingsFile(path.isAbsolute(trimmed) ? trimmed : path.join(cwd ?? process.cwd(), trimmed)) ?? {});
|
|
1548
|
+
};
|
|
1549
|
+
/**
|
|
1550
|
+
* Build the `--settings` value that forces the CLI through our proxy.
|
|
1551
|
+
*
|
|
1552
|
+
* Claude Code resolves `env` from its settings layers with higher priority than
|
|
1553
|
+
* the subprocess environment, so rewriting `options.env` alone leaves a user with
|
|
1554
|
+
* `ANTHROPIC_BASE_URL` in `~/.claude/settings.json` talking straight to their
|
|
1555
|
+
* upstream while the proxy sees zero traffic (lmnr#2167). `--settings` is the
|
|
1556
|
+
* highest user-controlled layer, so writing the proxy URL there wins without ever
|
|
1557
|
+
* touching the user's files on disk.
|
|
1558
|
+
*
|
|
1559
|
+
* Layers merge per key, so keys we simply omit keep their lower-layer value.
|
|
1560
|
+
* Redirecting keys are therefore blanked rather than dropped.
|
|
1561
|
+
*
|
|
1562
|
+
* Returns the value to assign to `options.settings`, or `null` when the caller's
|
|
1563
|
+
* existing value is a file path we could not read (in that case the path must be
|
|
1564
|
+
* left alone so the CLI can still resolve it itself).
|
|
1565
|
+
*/
|
|
1566
|
+
const buildProxyFlagSettings = (existing, proxyUrl, cwd, settingSources) => {
|
|
1567
|
+
let settingsObj = {};
|
|
1568
|
+
if (typeof existing === "object" && existing !== null) settingsObj = { ...existing };
|
|
1569
|
+
else if (typeof existing === "string" && existing.trim()) {
|
|
1570
|
+
const trimmed = existing.trim();
|
|
1571
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
1572
|
+
let parsed;
|
|
1573
|
+
try {
|
|
1574
|
+
parsed = JSON.parse(trimmed);
|
|
1575
|
+
} catch {
|
|
1576
|
+
return null;
|
|
1577
|
+
}
|
|
1578
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
1579
|
+
settingsObj = parsed;
|
|
1580
|
+
} else {
|
|
1581
|
+
const loaded = loadSettingsFile(path.isAbsolute(trimmed) ? trimmed : path.join(cwd ?? process.cwd(), trimmed));
|
|
1582
|
+
if (loaded === null) return null;
|
|
1583
|
+
settingsObj = loaded;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
const envDict = { ...settingsEnvBlock(settingsObj) };
|
|
1587
|
+
const settingsEnv = readClaudeSettingsEnv(cwd, settingSources);
|
|
1588
|
+
const inPlay = (key) => key in envDict || key in settingsEnv || process.env[key] !== void 0;
|
|
1589
|
+
envDict.ANTHROPIC_BASE_URL = proxyUrl;
|
|
1590
|
+
for (const [baseUrlKey, useKey] of PROVIDER_BASE_URL_ENV_KEYS) {
|
|
1591
|
+
if (isTruthyEnv(envDict[useKey]) || isTruthyEnv(settingsEnv[useKey]) || isTruthyEnv(process.env[useKey]) || inPlay(baseUrlKey)) envDict[baseUrlKey] = proxyUrl;
|
|
1592
|
+
if (baseUrlKey === FOUNDRY_BASE_URL_ENV && envDict[baseUrlKey] === proxyUrl) envDict[FOUNDRY_RESOURCE_ENV] = "";
|
|
1593
|
+
}
|
|
1594
|
+
for (const key of PROXY_NEUTRALIZED_ENV_KEYS) if (key in settingsEnv || key in envDict || process.env[key] !== void 0) envDict[key] = "";
|
|
1595
|
+
return {
|
|
1596
|
+
...settingsObj,
|
|
1597
|
+
env: envDict
|
|
1598
|
+
};
|
|
1599
|
+
};
|
|
1342
1600
|
/**
|
|
1343
1601
|
* Read region for a given profile from ~/.aws/config.
|
|
1344
1602
|
*/
|
|
@@ -1377,17 +1635,27 @@ const getRegionFromAwsConfig = (profile) => {
|
|
|
1377
1635
|
* 4. ANTHROPIC_BASE_URL - standard Anthropic API base URL
|
|
1378
1636
|
* 5. Fall back to default (https://api.anthropic.com)
|
|
1379
1637
|
*
|
|
1380
|
-
* For each environment variable, checks envDict first, then process.env
|
|
1638
|
+
* For each environment variable, checks envDict first, then process.env, then
|
|
1639
|
+
* Claude Code's on-disk settings `env` block. The settings layer is checked last
|
|
1640
|
+
* as a source for the *upstream* URL, but note it wins over process env inside
|
|
1641
|
+
* the CLI itself — see `buildProxyFlagSettings`.
|
|
1381
1642
|
*
|
|
1382
1643
|
* @param envDict - Dictionary of environment variables (e.g., from options.env)
|
|
1383
1644
|
* @param fallback - Fallback URL if no other source found (default: DEFAULT_ANTHROPIC_BASE_URL)
|
|
1645
|
+
* @param cwd - Session root used to locate project settings (`options.cwd`)
|
|
1384
1646
|
* @returns Resolved target URL, or null if provider is misconfigured
|
|
1385
1647
|
*/
|
|
1386
|
-
const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL) => {
|
|
1387
|
-
const
|
|
1388
|
-
const
|
|
1648
|
+
const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL, cwd, settingSources, settings) => {
|
|
1649
|
+
const flagEnv = flagSettingsEnv(settings, cwd);
|
|
1650
|
+
const settingsEnv = readClaudeSettingsEnv(cwd, settingSources);
|
|
1651
|
+
const getEnvValue = (key) => {
|
|
1652
|
+
const value = envDict[key] || process.env[key];
|
|
1653
|
+
if (value || UPSTREAM_SETTINGS_EXCLUDED_ENV_KEYS.includes(key)) return value;
|
|
1654
|
+
return flagEnv[key] || settingsEnv[key];
|
|
1655
|
+
};
|
|
1656
|
+
const httpsProxy = getEnvValue("HTTPS_PROXY") || getEnvValue("https_proxy");
|
|
1389
1657
|
if (httpsProxy) return httpsProxy.replace(/\/$/, "");
|
|
1390
|
-
const httpProxy = getEnvValue("HTTP_PROXY");
|
|
1658
|
+
const httpProxy = getEnvValue("HTTP_PROXY") || getEnvValue("http_proxy");
|
|
1391
1659
|
if (httpProxy) return httpProxy.replace(/\/$/, "");
|
|
1392
1660
|
if (isTruthyEnv(getEnvValue(FOUNDRY_USE_ENV))) {
|
|
1393
1661
|
const foundryBaseUrl = getEnvValue(FOUNDRY_BASE_URL_ENV);
|
|
@@ -1423,9 +1691,10 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL)
|
|
|
1423
1691
|
* @param envDict - Dictionary of environment variables
|
|
1424
1692
|
* @returns Array of environment variable keys to remove
|
|
1425
1693
|
*/
|
|
1426
|
-
const getEnvVarsToRemove = (envDict) => {
|
|
1427
|
-
const toRemove = [
|
|
1428
|
-
const
|
|
1694
|
+
const getEnvVarsToRemove = (envDict, cwd, settingSources) => {
|
|
1695
|
+
const toRemove = [...PROXY_ENV_KEYS];
|
|
1696
|
+
const settingsEnv = readClaudeSettingsEnv(cwd, settingSources);
|
|
1697
|
+
const getEnvValue = (key) => envDict[key] || process.env[key] || settingsEnv[key];
|
|
1429
1698
|
if (isTruthyEnv(getEnvValue(FOUNDRY_USE_ENV))) toRemove.push(FOUNDRY_RESOURCE_ENV);
|
|
1430
1699
|
return toRemove;
|
|
1431
1700
|
};
|
|
@@ -1500,14 +1769,14 @@ const registerGlobalProxyShutdown = () => {
|
|
|
1500
1769
|
* Create and start a new claude-code proxy server instance
|
|
1501
1770
|
* Each call creates an independent proxy on a unique port
|
|
1502
1771
|
*/
|
|
1503
|
-
const createProxyInstance = async ({ env }) => {
|
|
1772
|
+
const createProxyInstance = async ({ env, cwd, settingSources, settings, targetUrl: resolvedTargetUrl }) => {
|
|
1504
1773
|
try {
|
|
1505
1774
|
const port = await findAvailablePort(DEFAULT_CC_PROXY_PORT, CC_PROXY_PORT_ATTEMPTS);
|
|
1506
1775
|
if (port === null) {
|
|
1507
1776
|
logger$20.warn("Unable to allocate port for cc-proxy.");
|
|
1508
1777
|
return null;
|
|
1509
1778
|
}
|
|
1510
|
-
const targetUrl = resolveTargetUrlFromEnv(env);
|
|
1779
|
+
const targetUrl = resolvedTargetUrl ?? resolveTargetUrlFromEnv(env, void 0, cwd, settingSources, settings);
|
|
1511
1780
|
if (!targetUrl) {
|
|
1512
1781
|
logger$20.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
|
|
1513
1782
|
return null;
|
|
@@ -1644,24 +1913,41 @@ function instrumentClaudeAgentQuery(originalQuery) {
|
|
|
1644
1913
|
...process.env,
|
|
1645
1914
|
...params.options?.env ?? {}
|
|
1646
1915
|
};
|
|
1647
|
-
const
|
|
1648
|
-
|
|
1916
|
+
const sessionCwd = typeof params.options?.cwd === "string" ? params.options.cwd : void 0;
|
|
1917
|
+
const settingSources = Array.isArray(params.options?.settingSources) ? params.options.settingSources : void 0;
|
|
1918
|
+
const callerSettings = params.options?.settings;
|
|
1919
|
+
const targetUrl = resolveTargetUrlFromEnv(mergedEnv, void 0, sessionCwd, settingSources, callerSettings);
|
|
1920
|
+
proxyInstance = await createProxyInstance({
|
|
1921
|
+
env: mergedEnv,
|
|
1922
|
+
cwd: sessionCwd,
|
|
1923
|
+
settingSources,
|
|
1924
|
+
settings: callerSettings,
|
|
1925
|
+
targetUrl
|
|
1926
|
+
});
|
|
1649
1927
|
if (proxyInstance && targetUrl) {
|
|
1650
1928
|
logger$19.debug(`Using proxy on port ${proxyInstance.port}`);
|
|
1651
1929
|
await Laminar.withSpan(span, async () => {
|
|
1652
1930
|
logger$19.debug("Setting trace to proxy instance...");
|
|
1653
1931
|
await setTraceToProxyInstance(proxyInstance);
|
|
1654
1932
|
});
|
|
1655
|
-
const varsToRemove = getEnvVarsToRemove(mergedEnv);
|
|
1933
|
+
const varsToRemove = getEnvVarsToRemove(mergedEnv, sessionCwd, settingSources);
|
|
1656
1934
|
if (!params.options) params.options = {};
|
|
1657
1935
|
if (!params.options.env) params.options.env = {};
|
|
1658
1936
|
params.options.env = { ...mergedEnv };
|
|
1659
1937
|
params.options.env.ANTHROPIC_BASE_URL = proxyInstance.baseUrl;
|
|
1660
1938
|
params.options.env.ANTHROPIC_ORIGINAL_BASE_URL = targetUrl;
|
|
1661
1939
|
for (const varName of varsToRemove) delete params.options.env[varName];
|
|
1662
|
-
|
|
1663
|
-
if (
|
|
1664
|
-
if (
|
|
1940
|
+
const subprocessEnv = params.options.env;
|
|
1941
|
+
if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_FOUNDRY")) subprocessEnv.ANTHROPIC_FOUNDRY_BASE_URL = proxyInstance.baseUrl;
|
|
1942
|
+
if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_BEDROCK")) subprocessEnv.ANTHROPIC_BEDROCK_BASE_URL = proxyInstance.baseUrl;
|
|
1943
|
+
if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_VERTEX")) subprocessEnv.ANTHROPIC_VERTEX_BASE_URL = proxyInstance.baseUrl;
|
|
1944
|
+
const flagSettings = buildProxyFlagSettings(callerSettings, proxyInstance.baseUrl, sessionCwd, settingSources);
|
|
1945
|
+
if (flagSettings === null) logger$19.warn(`Could not read options.settings ${JSON.stringify(callerSettings)}; Claude Code settings that define a base URL will bypass the Laminar proxy and produce no LLM spans.`);
|
|
1946
|
+
else {
|
|
1947
|
+
params.options.settings = flagSettings;
|
|
1948
|
+
const conflicting = Object.entries(readClaudeSettingsEnv(sessionCwd, settingSources)).filter(([key, value]) => PROXY_BASE_URL_ENV_KEYS.includes(key) && value !== "" && value !== proxyInstance.baseUrl).map(([key]) => key);
|
|
1949
|
+
if (conflicting.length > 0) logger$19.info(`Claude Code settings define ${conflicting.sort().join(", ")}, which outranks the subprocess environment. Injected settings so the Laminar proxy at ${proxyInstance.baseUrl} still intercepts API traffic; your settings files were not modified.`);
|
|
1950
|
+
}
|
|
1665
1951
|
} else logger$19.debug("No claude proxy server available. Proceeding without proxy.");
|
|
1666
1952
|
const originalGenerator = originalQuery(params);
|
|
1667
1953
|
for await (const message of originalGenerator) {
|
|
@@ -6597,9 +6883,9 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6597
6883
|
return context.with(entityContext, () => getTracer().startActiveSpan(name, { attributes: spanAttributes }, entityContext, (span) => {
|
|
6598
6884
|
if (shouldSendTraces() && !ignoreInput) try {
|
|
6599
6885
|
const spanInput = inputParameters ?? args;
|
|
6600
|
-
if (input !== void 0) span.setAttribute(SPAN_INPUT, typeof input === "string" ? input : serialize(input));
|
|
6601
|
-
else if (spanInput.length === 1 && typeof spanInput[0] === "object" && !(spanInput[0] instanceof Map)) span.setAttribute(SPAN_INPUT, typeof spanInput[0] === "string" ? spanInput[0] : serialize(spanInput[0]));
|
|
6602
|
-
else span.setAttribute(SPAN_INPUT, serialize(spanInput.length > 0 ? spanInput : {}));
|
|
6886
|
+
if (input !== void 0) span.setAttribute(SPAN_INPUT, typeof input === "string" ? truncateSpanPayload(input, "input") : serialize(input, "input"));
|
|
6887
|
+
else if (spanInput.length === 1 && typeof spanInput[0] === "object" && !(spanInput[0] instanceof Map)) span.setAttribute(SPAN_INPUT, typeof spanInput[0] === "string" ? truncateSpanPayload(spanInput[0], "input") : serialize(spanInput[0], "input"));
|
|
6888
|
+
else span.setAttribute(SPAN_INPUT, serialize(spanInput.length > 0 ? spanInput : {}, "input"));
|
|
6603
6889
|
} catch (error) {
|
|
6604
6890
|
logger$4.warn("Failed to serialize input: " + errorMessage(error));
|
|
6605
6891
|
}
|
|
@@ -6652,7 +6938,7 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6652
6938
|
}
|
|
6653
6939
|
if (streamInfo.type !== null) return handleStreamResult(res, streamInfo, span, ignoreOutput, serialize);
|
|
6654
6940
|
try {
|
|
6655
|
-
if (shouldSendTraces() && !ignoreOutput) span.setAttribute(SPAN_OUTPUT, typeof res === "string" ? res : serialize(res));
|
|
6941
|
+
if (shouldSendTraces() && !ignoreOutput) span.setAttribute(SPAN_OUTPUT, typeof res === "string" ? truncateSpanPayload(res, "output") : serialize(res));
|
|
6656
6942
|
} catch (error) {
|
|
6657
6943
|
logger$4.warn("Failed to serialize output: " + errorMessage(error));
|
|
6658
6944
|
} finally {
|
|
@@ -6680,7 +6966,7 @@ const normalizePayload = (payload, seen) => {
|
|
|
6680
6966
|
}
|
|
6681
6967
|
return payload;
|
|
6682
6968
|
};
|
|
6683
|
-
const serialize = (payload) => JSON.stringify(normalizePayload(payload, /* @__PURE__ */ new WeakSet()));
|
|
6969
|
+
const serialize = (payload, kind = "output") => truncateSpanPayload(JSON.stringify(normalizePayload(payload, /* @__PURE__ */ new WeakSet())), kind);
|
|
6684
6970
|
//#endregion
|
|
6685
6971
|
//#region src/decorators.ts
|
|
6686
6972
|
const logger$3 = initializeLogger();
|
|
@@ -7057,6 +7343,7 @@ var Evaluation = class {
|
|
|
7057
7343
|
this.frontendPort = config?.frontendPort;
|
|
7058
7344
|
this.progressReporter = new EvaluationReporter(config?.baseUrl, config?.frontendPort);
|
|
7059
7345
|
this.data = data;
|
|
7346
|
+
this.datasetSource = data instanceof EvaluationDataset ? data.sourceDataset() : void 0;
|
|
7060
7347
|
this.executor = executor;
|
|
7061
7348
|
this.evaluators = evaluators;
|
|
7062
7349
|
this.groupName = groupName;
|
|
@@ -7103,22 +7390,24 @@ var Evaluation = class {
|
|
|
7103
7390
|
}
|
|
7104
7391
|
async run() {
|
|
7105
7392
|
if (this.isFinished) throw new Error("Evaluation is already finished");
|
|
7106
|
-
if (this.data instanceof
|
|
7107
|
-
this.
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7393
|
+
if (this.data instanceof EvaluationDataset) {
|
|
7394
|
+
const source = this.datasetSource;
|
|
7395
|
+
source?.setClient(this.client);
|
|
7396
|
+
if (source && !source.id) try {
|
|
7397
|
+
const datasets = await this.client.datasets.getDatasetByName(source.name);
|
|
7398
|
+
if (datasets.length > 0) source.id = datasets[0].id;
|
|
7399
|
+
else logger$2.warn(`Dataset ${source.name} not found`);
|
|
7112
7400
|
} catch (error) {
|
|
7113
|
-
logger$2.warn(`Error getting dataset ${
|
|
7401
|
+
logger$2.warn(`Error getting dataset ${source.name}: ` + errorMessage(error));
|
|
7114
7402
|
}
|
|
7115
7403
|
}
|
|
7116
7404
|
let resultDatapoints;
|
|
7117
7405
|
try {
|
|
7406
|
+
const length = await this.getLength();
|
|
7118
7407
|
const evaluation = await this.client.evals.init(this.name, this.groupName, withSessionMetadata(this.metadata));
|
|
7119
7408
|
const url = getEvaluationUrl(evaluation.projectId, evaluation.id, this.progressReporter.baseUrl, this.frontendPort);
|
|
7120
7409
|
process.stdout.write(`\nCheck results at ${url}\n`);
|
|
7121
|
-
this.progressReporter.start({ length
|
|
7410
|
+
this.progressReporter.start({ length });
|
|
7122
7411
|
resultDatapoints = await this.evaluateInBatches(evaluation.id);
|
|
7123
7412
|
const averageScores = getAverageScores(resultDatapoints);
|
|
7124
7413
|
if (this.uploadPromises.length > 0) await Promise.all(this.uploadPromises);
|
|
@@ -7199,8 +7488,8 @@ var Evaluation = class {
|
|
|
7199
7488
|
executorSpanId,
|
|
7200
7489
|
index
|
|
7201
7490
|
};
|
|
7202
|
-
if (this.
|
|
7203
|
-
datasetId: this.
|
|
7491
|
+
if (this.datasetSource?.id && datapoint.id && datapoint.createdAt) partialDatapoint.datasetLink = {
|
|
7492
|
+
datasetId: this.datasetSource.id,
|
|
7204
7493
|
datapointId: datapoint.id,
|
|
7205
7494
|
createdAt: datapoint.createdAt
|
|
7206
7495
|
};
|
|
@@ -7254,8 +7543,8 @@ var Evaluation = class {
|
|
|
7254
7543
|
executorSpanId,
|
|
7255
7544
|
index
|
|
7256
7545
|
};
|
|
7257
|
-
if (this.
|
|
7258
|
-
datasetId: this.
|
|
7546
|
+
if (this.datasetSource?.id && datapoint.id && datapoint.createdAt) resultDatapoint.datasetLink = {
|
|
7547
|
+
datasetId: this.datasetSource.id,
|
|
7259
7548
|
datapointId: datapoint.id,
|
|
7260
7549
|
createdAt: datapoint.createdAt
|
|
7261
7550
|
};
|