langwatch 1.12.1 → 1.13.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/dist/agent/index.d.mts +5 -1
- package/dist/agent/index.d.ts +5 -1
- package/dist/agent/index.js +239 -14
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +239 -14
- package/dist/agent/index.mjs.map +1 -1
- package/dist/{chunk-OSVJ65OO.js → chunk-7R54TMZZ.js} +2 -2
- package/dist/{chunk-OSVJ65OO.js.map → chunk-7R54TMZZ.js.map} +1 -1
- package/dist/{chunk-H2DJGGYQ.js → chunk-G64XZMIU.js} +12 -12
- package/dist/{chunk-H2DJGGYQ.js.map → chunk-G64XZMIU.js.map} +1 -1
- package/dist/{chunk-53NOLJEX.mjs → chunk-N3755EHD.mjs} +2 -2
- package/dist/{chunk-2HA4SJSD.mjs → chunk-NPEK4RSD.mjs} +5 -2
- package/dist/{chunk-2HA4SJSD.mjs.map → chunk-NPEK4RSD.mjs.map} +1 -1
- package/dist/{chunk-4ERRCKOH.js → chunk-O4J3ZPZY.js} +5 -2
- package/dist/chunk-O4J3ZPZY.js.map +1 -0
- package/dist/{chunk-IVRETMQH.mjs → chunk-UHRSTPZ5.mjs} +2 -2
- package/dist/{chunk-IVRETMQH.mjs.map → chunk-UHRSTPZ5.mjs.map} +1 -1
- package/dist/cli/bundle.js +362 -358
- package/dist/{implementation-BNaydX6f.d.ts → implementation-BDK4X-CS.d.ts} +1 -1
- package/dist/{implementation-DLMEZQgA.d.mts → implementation-BOP-3GoX.d.mts} +1 -1
- package/dist/index.d.mts +75 -5
- package/dist/index.d.ts +75 -5
- package/dist/index.js +324 -99
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +242 -17
- package/dist/index.mjs.map +1 -1
- package/dist/observability-sdk/index.d.mts +3 -3
- package/dist/observability-sdk/index.d.ts +3 -3
- package/dist/observability-sdk/index.js +3 -3
- package/dist/observability-sdk/index.mjs +2 -2
- package/dist/observability-sdk/instrumentation/langchain/index.d.mts +1 -1
- package/dist/observability-sdk/instrumentation/langchain/index.d.ts +1 -1
- package/dist/observability-sdk/instrumentation/langchain/index.js +3 -3
- package/dist/observability-sdk/instrumentation/langchain/index.mjs +1 -1
- package/dist/observability-sdk/setup/node/index.js +3 -3
- package/dist/observability-sdk/setup/node/index.mjs +2 -2
- package/dist/{types-CLDQMYpV.d.ts → types-C3SDhizh.d.ts} +1138 -111
- package/dist/{types-DWNdXOWw.d.mts → types-C9abONOS.d.mts} +1138 -111
- package/package.json +1 -1
- package/dist/chunk-4ERRCKOH.js.map +0 -1
- /package/dist/{chunk-53NOLJEX.mjs.map → chunk-N3755EHD.mjs.map} +0 -0
package/dist/agent/index.d.mts
CHANGED
|
@@ -221,7 +221,11 @@ interface ConnectAgentOptions<P extends ParameterInput = ParameterDefinitions> {
|
|
|
221
221
|
instanceLabel?: string;
|
|
222
222
|
/** Per call, default 120000, at most 300000. */
|
|
223
223
|
timeoutMs?: number;
|
|
224
|
-
/**
|
|
224
|
+
/**
|
|
225
|
+
* Calls in flight per instance, default 10. A test suite sends several
|
|
226
|
+
* scenarios at once; the ceiling is there because the model providers rate
|
|
227
|
+
* limit the calls behind them.
|
|
228
|
+
*/
|
|
225
229
|
concurrency?: number;
|
|
226
230
|
/** Keep every turn of a thread on the instance that answered the first one. */
|
|
227
231
|
sticky?: boolean;
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -221,7 +221,11 @@ interface ConnectAgentOptions<P extends ParameterInput = ParameterDefinitions> {
|
|
|
221
221
|
instanceLabel?: string;
|
|
222
222
|
/** Per call, default 120000, at most 300000. */
|
|
223
223
|
timeoutMs?: number;
|
|
224
|
-
/**
|
|
224
|
+
/**
|
|
225
|
+
* Calls in flight per instance, default 10. A test suite sends several
|
|
226
|
+
* scenarios at once; the ceiling is there because the model providers rate
|
|
227
|
+
* limit the calls behind them.
|
|
228
|
+
*/
|
|
225
229
|
concurrency?: number;
|
|
226
230
|
/** Keep every turn of a thread on the instance that answered the first one. */
|
|
227
231
|
sticky?: boolean;
|
package/dist/agent/index.js
CHANGED
|
@@ -87,7 +87,7 @@ var os = __toESM(require("os"));
|
|
|
87
87
|
var import_node_crypto = require("crypto");
|
|
88
88
|
|
|
89
89
|
// package.json
|
|
90
|
-
var version = "1.
|
|
90
|
+
var version = "1.13.0";
|
|
91
91
|
|
|
92
92
|
// src/internal/constants.ts
|
|
93
93
|
var LANGWATCH_SDK_VERSION = version;
|
|
@@ -492,6 +492,213 @@ function createParameterReader({
|
|
|
492
492
|
|
|
493
493
|
// src/agent/transport.ts
|
|
494
494
|
var import_node_module = require("module");
|
|
495
|
+
|
|
496
|
+
// src/internal/http/langwatchFetch.ts
|
|
497
|
+
var REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
498
|
+
var FOLLOWING_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
|
|
499
|
+
var MAX_FOLLOW_HOPS = 5;
|
|
500
|
+
var CREDENTIAL_HEADERS = [
|
|
501
|
+
"authorization",
|
|
502
|
+
"cookie",
|
|
503
|
+
"proxy-authorization",
|
|
504
|
+
"x-api-key",
|
|
505
|
+
"x-auth-token",
|
|
506
|
+
"x-project-id"
|
|
507
|
+
];
|
|
508
|
+
var LangWatchRedirectError = class extends Error {
|
|
509
|
+
constructor({
|
|
510
|
+
url,
|
|
511
|
+
location,
|
|
512
|
+
status
|
|
513
|
+
}) {
|
|
514
|
+
super(
|
|
515
|
+
`LangWatch refused to follow a redirect from ${url} to ${location ?? "an unknown location"} (HTTP ${status}). Set the endpoint to the final URL.`
|
|
516
|
+
);
|
|
517
|
+
this.name = "LangWatchRedirectError";
|
|
518
|
+
this.url = url;
|
|
519
|
+
this.location = location;
|
|
520
|
+
this.status = status;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
var warnedOrigins = /* @__PURE__ */ new Set();
|
|
524
|
+
var isRedirect = (response) => response.type === "opaqueredirect" || REDIRECT_STATUSES.has(response.status);
|
|
525
|
+
var isStream = (body) => typeof ReadableStream !== "undefined" && body instanceof ReadableStream;
|
|
526
|
+
var abortError = (signal) => {
|
|
527
|
+
const reason = signal.reason;
|
|
528
|
+
if (reason instanceof Error) return reason;
|
|
529
|
+
if (typeof DOMException !== "undefined") {
|
|
530
|
+
return new DOMException("This operation was aborted", "AbortError");
|
|
531
|
+
}
|
|
532
|
+
return Object.assign(new Error("This operation was aborted"), { name: "AbortError" });
|
|
533
|
+
};
|
|
534
|
+
var discard = (spare) => {
|
|
535
|
+
void spare?.body?.cancel().catch(() => void 0);
|
|
536
|
+
};
|
|
537
|
+
var replayBody = async ({
|
|
538
|
+
spare,
|
|
539
|
+
signal
|
|
540
|
+
}) => {
|
|
541
|
+
if (!signal) return spare.arrayBuffer();
|
|
542
|
+
if (signal.aborted) throw abortError(signal);
|
|
543
|
+
const aborted = new Promise((_, reject) => {
|
|
544
|
+
signal.addEventListener("abort", () => reject(abortError(signal)), { once: true });
|
|
545
|
+
});
|
|
546
|
+
void aborted.catch(() => void 0);
|
|
547
|
+
try {
|
|
548
|
+
return await Promise.race([spare.arrayBuffer(), aborted]);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
discard(spare);
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
var requestUrl = (input) => {
|
|
555
|
+
if (typeof input === "string") return input;
|
|
556
|
+
if (input instanceof URL) return input.href;
|
|
557
|
+
return input.url;
|
|
558
|
+
};
|
|
559
|
+
var parseHop = ({
|
|
560
|
+
url,
|
|
561
|
+
location
|
|
562
|
+
}) => {
|
|
563
|
+
try {
|
|
564
|
+
const from = new URL(url);
|
|
565
|
+
return { from, to: new URL(location, from) };
|
|
566
|
+
} catch {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
var isSchemeUpgrade = ({ from, to }) => from.protocol === "http:" && to.protocol === "https:" && from.hostname === to.hostname && from.port === to.port;
|
|
571
|
+
var schemeUpgradeTarget = ({
|
|
572
|
+
url,
|
|
573
|
+
location
|
|
574
|
+
}) => {
|
|
575
|
+
const hop = parseHop({ url, location });
|
|
576
|
+
if (hop === null || !isSchemeUpgrade(hop)) return null;
|
|
577
|
+
const { from, to } = hop;
|
|
578
|
+
if (from.pathname !== to.pathname) return null;
|
|
579
|
+
if (from.search !== to.search) return null;
|
|
580
|
+
to.hash = "";
|
|
581
|
+
return to.href;
|
|
582
|
+
};
|
|
583
|
+
var followTarget = ({
|
|
584
|
+
url,
|
|
585
|
+
location
|
|
586
|
+
}) => {
|
|
587
|
+
const hop = parseHop({ url, location });
|
|
588
|
+
if (hop === null) return null;
|
|
589
|
+
const { from, to } = hop;
|
|
590
|
+
if (to.protocol !== "http:" && to.protocol !== "https:") return null;
|
|
591
|
+
if (from.protocol === "https:" && to.protocol === "http:") return null;
|
|
592
|
+
to.hash = "";
|
|
593
|
+
return to.href;
|
|
594
|
+
};
|
|
595
|
+
var keepsCredentials = ({ from, to }) => from.origin === to.origin || isSchemeUpgrade({ from, to });
|
|
596
|
+
var withoutCredentials = (headers) => {
|
|
597
|
+
const stripped = new Headers(headers);
|
|
598
|
+
for (const name of CREDENTIAL_HEADERS) stripped.delete(name);
|
|
599
|
+
return stripped;
|
|
600
|
+
};
|
|
601
|
+
var warnOnce = ({ url, logger }) => {
|
|
602
|
+
const { origin, host } = new URL(url);
|
|
603
|
+
if (warnedOrigins.has(origin)) return;
|
|
604
|
+
warnedOrigins.add(origin);
|
|
605
|
+
logger.warn(
|
|
606
|
+
`LangWatch endpoint ${origin} redirected to https. Set the endpoint to https://${host} to skip the extra round trip.`
|
|
607
|
+
);
|
|
608
|
+
};
|
|
609
|
+
var refusalOf = ({
|
|
610
|
+
url,
|
|
611
|
+
response
|
|
612
|
+
}) => new LangWatchRedirectError({
|
|
613
|
+
url,
|
|
614
|
+
location: response.headers.get("location"),
|
|
615
|
+
status: response.status
|
|
616
|
+
});
|
|
617
|
+
var effectiveRequest = ({
|
|
618
|
+
input,
|
|
619
|
+
init
|
|
620
|
+
}) => typeof Request !== "undefined" && input instanceof Request ? new Request(input, { ...init, redirect: "manual" }) : null;
|
|
621
|
+
var follow = async ({
|
|
622
|
+
send,
|
|
623
|
+
log,
|
|
624
|
+
effective,
|
|
625
|
+
init,
|
|
626
|
+
url,
|
|
627
|
+
method,
|
|
628
|
+
first
|
|
629
|
+
}) => {
|
|
630
|
+
let headers = new Headers(effective?.headers ?? init?.headers);
|
|
631
|
+
const signal = effective?.signal ?? init?.signal;
|
|
632
|
+
let current = url;
|
|
633
|
+
let response = first;
|
|
634
|
+
for (let hop = 0; hop < MAX_FOLLOW_HOPS; hop++) {
|
|
635
|
+
const location = response.headers.get("location");
|
|
636
|
+
const target = location === null ? null : followTarget({ url: current, location });
|
|
637
|
+
if (target === null) throw refusalOf({ url: current, response });
|
|
638
|
+
const from = new URL(current);
|
|
639
|
+
const to = new URL(target);
|
|
640
|
+
if (!keepsCredentials({ from, to })) headers = withoutCredentials(headers);
|
|
641
|
+
if (isSchemeUpgrade({ from, to })) warnOnce({ url: current, logger: log });
|
|
642
|
+
current = target;
|
|
643
|
+
response = effective ? await send(new Request(target, { method, headers, signal, redirect: "manual" })) : await send(target, { ...init, method, headers, body: void 0, redirect: "manual" });
|
|
644
|
+
if (!isRedirect(response)) return response;
|
|
645
|
+
}
|
|
646
|
+
throw refusalOf({ url: current, response });
|
|
647
|
+
};
|
|
648
|
+
var upgrade = async ({
|
|
649
|
+
send,
|
|
650
|
+
log,
|
|
651
|
+
effective,
|
|
652
|
+
init,
|
|
653
|
+
url,
|
|
654
|
+
first,
|
|
655
|
+
spare
|
|
656
|
+
}) => {
|
|
657
|
+
const location = first.headers.get("location");
|
|
658
|
+
const refused = refusalOf({ url, response: first });
|
|
659
|
+
const target = location === null ? null : schemeUpgradeTarget({ url, location });
|
|
660
|
+
if (location === null || first.status === 303 || target === null || isStream(init?.body)) {
|
|
661
|
+
discard(spare);
|
|
662
|
+
throw refused;
|
|
663
|
+
}
|
|
664
|
+
warnOnce({ url, logger: log });
|
|
665
|
+
const second = effective ? await send(
|
|
666
|
+
new Request(target, {
|
|
667
|
+
method: effective.method,
|
|
668
|
+
headers: effective.headers,
|
|
669
|
+
body: spare ? await replayBody({ spare, signal: effective.signal }) : null,
|
|
670
|
+
signal: effective.signal,
|
|
671
|
+
redirect: "manual"
|
|
672
|
+
})
|
|
673
|
+
) : await send(target, { ...init, redirect: "manual" });
|
|
674
|
+
if (!isRedirect(second)) return second;
|
|
675
|
+
throw refusalOf({ url: target, response: second });
|
|
676
|
+
};
|
|
677
|
+
var createLangWatchFetch = ({
|
|
678
|
+
fetch: fetchImpl,
|
|
679
|
+
logger
|
|
680
|
+
} = {}) => {
|
|
681
|
+
const send = fetchImpl ?? ((input, init) => globalThis.fetch(input, init));
|
|
682
|
+
const log = logger ?? new ConsoleLogger({ level: "warn", prefix: "LangWatch" });
|
|
683
|
+
return async (input, init) => {
|
|
684
|
+
const url = requestUrl(input);
|
|
685
|
+
const effective = effectiveRequest({ input, init });
|
|
686
|
+
const method = (effective?.method ?? init?.method ?? "GET").toUpperCase();
|
|
687
|
+
const spare = effective !== null && effective.body !== null ? effective.clone() : null;
|
|
688
|
+
const first = effective ? await send(effective) : await send(input, { ...init, redirect: "manual" });
|
|
689
|
+
if (!isRedirect(first)) {
|
|
690
|
+
discard(spare);
|
|
691
|
+
return first;
|
|
692
|
+
}
|
|
693
|
+
const hop = { send, log, effective, init, url, first };
|
|
694
|
+
if (!FOLLOWING_METHODS.has(method)) return upgrade({ ...hop, spare });
|
|
695
|
+
discard(spare);
|
|
696
|
+
return follow({ ...hop, method });
|
|
697
|
+
};
|
|
698
|
+
};
|
|
699
|
+
var langwatchFetch = createLangWatchFetch();
|
|
700
|
+
|
|
701
|
+
// src/agent/transport.ts
|
|
495
702
|
var AGENT_TRANSPORTS = ["websocket", "http"];
|
|
496
703
|
var INSTANCE_TOKEN_HEADER = "X-Agent-Instance-Token";
|
|
497
704
|
var isSet3 = (value) => typeof value === "string" && value.trim() !== "";
|
|
@@ -576,7 +783,7 @@ var HttpLongPollSocket = class {
|
|
|
576
783
|
this.settleRegistered = () => void 0;
|
|
577
784
|
this.url = options.url;
|
|
578
785
|
this.headers = options.headers;
|
|
579
|
-
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
786
|
+
const fetchImpl = options.fetch ?? (typeof globalThis.fetch === "function" ? langwatchFetch : void 0);
|
|
580
787
|
if (typeof fetchImpl !== "function") {
|
|
581
788
|
throw new Error("the HTTP transport needs a global fetch; run on Node 20 or later");
|
|
582
789
|
}
|
|
@@ -777,10 +984,9 @@ var HttpLongPollSocket = class {
|
|
|
777
984
|
}
|
|
778
985
|
};
|
|
779
986
|
|
|
780
|
-
// src/agent/
|
|
987
|
+
// src/agent/reconnect.ts
|
|
781
988
|
var RECONNECT_BASE_MS = 1e3;
|
|
782
989
|
var RECONNECT_MAX_MS = 3e4;
|
|
783
|
-
var FAILURE_NOTICE_INTERVAL_MS = 5 * 6e4;
|
|
784
990
|
function reconnectDelayMs({
|
|
785
991
|
attempt,
|
|
786
992
|
baseMs = RECONNECT_BASE_MS,
|
|
@@ -791,6 +997,22 @@ function reconnectDelayMs({
|
|
|
791
997
|
const jittered = exponential * (0.75 + random() * 0.5);
|
|
792
998
|
return Math.round(Math.min(maxMs, Math.max(baseMs, jittered)));
|
|
793
999
|
}
|
|
1000
|
+
function watchdogDelayMs(heartbeatIntervalMs) {
|
|
1001
|
+
return Math.max(15e3, heartbeatIntervalMs * 3);
|
|
1002
|
+
}
|
|
1003
|
+
var describeError = (error) => error instanceof Error ? error.message : String(error);
|
|
1004
|
+
function openTransportSocket({
|
|
1005
|
+
transport,
|
|
1006
|
+
websocketUrl,
|
|
1007
|
+
httpUrl,
|
|
1008
|
+
headers,
|
|
1009
|
+
socketFactory = defaultSocketFactory
|
|
1010
|
+
}) {
|
|
1011
|
+
return transport === "http" ? new HttpLongPollSocket({ url: httpUrl, headers }) : socketFactory({ url: websocketUrl, headers });
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// src/agent/client.ts
|
|
1015
|
+
var FAILURE_NOTICE_INTERVAL_MS = 5 * 6e4;
|
|
794
1016
|
var NOT_CONNECTED = "not connected to LangWatch";
|
|
795
1017
|
function refusalAdvice(frame) {
|
|
796
1018
|
switch (frame.code) {
|
|
@@ -823,7 +1045,6 @@ function refusalAdvice(frame) {
|
|
|
823
1045
|
}
|
|
824
1046
|
var SHUTDOWN_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
825
1047
|
var CLOSE_GRACE_MS = 500;
|
|
826
|
-
var describeError = (error) => error instanceof Error ? error.message : String(error);
|
|
827
1048
|
var AgentClient = class {
|
|
828
1049
|
constructor(config) {
|
|
829
1050
|
this.agents = [];
|
|
@@ -984,7 +1205,13 @@ var AgentClient = class {
|
|
|
984
1205
|
if (this.stopped || this.socket) return;
|
|
985
1206
|
let socket;
|
|
986
1207
|
try {
|
|
987
|
-
socket =
|
|
1208
|
+
socket = openTransportSocket({
|
|
1209
|
+
transport: this.activeTransport,
|
|
1210
|
+
websocketUrl: this.url,
|
|
1211
|
+
httpUrl: this.httpUrl,
|
|
1212
|
+
headers: this.headers,
|
|
1213
|
+
socketFactory: this.openSocket
|
|
1214
|
+
});
|
|
988
1215
|
} catch (error) {
|
|
989
1216
|
if (error instanceof NoWebSocketError) {
|
|
990
1217
|
this.giveUp(
|
|
@@ -1072,7 +1299,7 @@ var AgentClient = class {
|
|
|
1072
1299
|
socket.terminate();
|
|
1073
1300
|
} catch {
|
|
1074
1301
|
}
|
|
1075
|
-
},
|
|
1302
|
+
}, watchdogDelayMs(this.heartbeatIntervalMs));
|
|
1076
1303
|
}
|
|
1077
1304
|
registerFrame() {
|
|
1078
1305
|
return {
|
|
@@ -1335,7 +1562,7 @@ var installShutdownHooks = () => {
|
|
|
1335
1562
|
}
|
|
1336
1563
|
process.on("beforeExit", onBeforeExit);
|
|
1337
1564
|
};
|
|
1338
|
-
function
|
|
1565
|
+
function warnOnce2({ logger, key, message }) {
|
|
1339
1566
|
if (noticesGiven.has(key)) {
|
|
1340
1567
|
logger.debug(message);
|
|
1341
1568
|
return;
|
|
@@ -1347,7 +1574,7 @@ function getSharedClient(config) {
|
|
|
1347
1574
|
const key = `${config.endpoint ?? ""}|${config.projectId ?? ""}|${config.apiKey}`;
|
|
1348
1575
|
if (shared) {
|
|
1349
1576
|
if (sharedKey !== key) {
|
|
1350
|
-
|
|
1577
|
+
warnOnce2({
|
|
1351
1578
|
logger: config.logger,
|
|
1352
1579
|
key: "credentials-differ",
|
|
1353
1580
|
message: "connectAgent: this process already has an agent connection with other credentials or endpoint; the first ones are used"
|
|
@@ -1364,6 +1591,7 @@ function getSharedClient(config) {
|
|
|
1364
1591
|
// src/agent/define.ts
|
|
1365
1592
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
1366
1593
|
var MAX_TIMEOUT_MS = 3e5;
|
|
1594
|
+
var DEFAULT_CONCURRENCY = 10;
|
|
1367
1595
|
var isMessage = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.role === "string";
|
|
1368
1596
|
function normalizeReply(reply) {
|
|
1369
1597
|
if (typeof reply === "string") return { output: reply };
|
|
@@ -1403,10 +1631,7 @@ function connectAgent(options, handler) {
|
|
|
1403
1631
|
const parameters = toParameterSchema(options.parameters);
|
|
1404
1632
|
const specs = parameterSpecsFromSchema(parameters);
|
|
1405
1633
|
const timeoutMs = clampTimeout({ timeoutMs: options.timeoutMs, logger, name });
|
|
1406
|
-
const concurrency = Math.max(
|
|
1407
|
-
1,
|
|
1408
|
-
Math.floor(options.concurrency ?? (environment === DEFAULT_ENVIRONMENT ? 1 : 4))
|
|
1409
|
-
);
|
|
1634
|
+
const concurrency = Math.max(1, Math.floor(options.concurrency ?? DEFAULT_CONCURRENCY));
|
|
1410
1635
|
const runHandler = async (call) => normalizeReply(await handler(call));
|
|
1411
1636
|
const readParams2 = createParameterReader({ input: options.parameters, specs });
|
|
1412
1637
|
const invoke = async (call) => {
|
|
@@ -1442,7 +1667,7 @@ function connectAgent(options, handler) {
|
|
|
1442
1667
|
} else {
|
|
1443
1668
|
const apiKey = readApiKey(options.apiKey);
|
|
1444
1669
|
if (!apiKey) {
|
|
1445
|
-
|
|
1670
|
+
warnOnce2({
|
|
1446
1671
|
logger,
|
|
1447
1672
|
key: "no-api-key",
|
|
1448
1673
|
message: `agent "${name}" not connected to LangWatch: no API key. Set LANGWATCH_API_KEY to run simulations against it.`
|