langsmith 0.8.8 → 0.8.10
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/_openapi_client/resources/annotation-queues/annotation-queues.cjs +10 -0
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.d.ts +10 -0
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.js +10 -0
- package/dist/_openapi_client/resources/annotation-queues/runs.cjs +13 -1
- package/dist/_openapi_client/resources/annotation-queues/runs.d.ts +13 -1
- package/dist/_openapi_client/resources/annotation-queues/runs.js +13 -1
- package/dist/_openapi_client/resources/datasets/experiment-runs.cjs +2 -0
- package/dist/_openapi_client/resources/datasets/experiment-runs.d.ts +2 -0
- package/dist/_openapi_client/resources/datasets/experiment-runs.js +2 -0
- package/dist/_openapi_client/resources/issues.d.ts +1 -1
- package/dist/_openapi_client/resources/public/runs.cjs +9 -7
- package/dist/_openapi_client/resources/public/runs.d.ts +8 -6
- package/dist/_openapi_client/resources/public/runs.js +9 -7
- package/dist/_openapi_client/resources/runs/runs.cjs +11 -6
- package/dist/_openapi_client/resources/runs/runs.d.ts +11 -6
- package/dist/_openapi_client/resources/runs/runs.js +11 -6
- package/dist/_openapi_client/resources/runs/share.cjs +4 -0
- package/dist/_openapi_client/resources/runs/share.d.ts +4 -0
- package/dist/_openapi_client/resources/runs/share.js +4 -0
- package/dist/_openapi_client/resources/threads.cjs +11 -8
- package/dist/_openapi_client/resources/threads.d.ts +11 -8
- package/dist/_openapi_client/resources/threads.js +11 -8
- package/dist/_openapi_client/resources/traces.cjs +6 -3
- package/dist/_openapi_client/resources/traces.d.ts +6 -3
- package/dist/_openapi_client/resources/traces.js +6 -3
- package/dist/client.cjs +295 -24
- package/dist/client.d.ts +63 -9
- package/dist/client.js +295 -24
- package/dist/evaluation/evaluate_comparative.cjs +7 -4
- package/dist/evaluation/evaluate_comparative.js +7 -4
- package/dist/experimental/vercel/_agent_type.cjs +30 -0
- package/dist/experimental/vercel/_agent_type.d.ts +5 -0
- package/dist/experimental/vercel/_agent_type.js +26 -0
- package/dist/experimental/vercel/telemetry.cjs +2 -7
- package/dist/experimental/vercel/telemetry.js +2 -7
- package/dist/experimental/vercel/wrap.cjs +5 -11
- package/dist/experimental/vercel/wrap.js +6 -12
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/sandbox/command_handle.cjs +34 -7
- package/dist/sandbox/command_handle.d.ts +1 -0
- package/dist/sandbox/command_handle.js +34 -7
- package/dist/sandbox/ws_execute.cjs +7 -3
- package/dist/sandbox/ws_execute.d.ts +4 -2
- package/dist/sandbox/ws_execute.js +7 -3
- package/dist/utils/_git.cjs +28 -1
- package/dist/utils/_git.js +28 -1
- package/dist/utils/ls_agent_type.cjs +31 -0
- package/dist/utils/ls_agent_type.d.ts +9 -0
- package/dist/utils/ls_agent_type.js +25 -0
- package/dist/utils/profiles.cjs +125 -1
- package/dist/utils/profiles.d.ts +6 -0
- package/dist/utils/profiles.js +124 -1
- package/dist/utils/v2_migration.cjs +18 -0
- package/dist/utils/v2_migration.d.ts +8 -0
- package/dist/utils/v2_migration.js +16 -0
- package/dist/utils/warn.cjs +30 -4
- package/dist/utils/warn.d.ts +4 -1
- package/dist/utils/warn.js +29 -4
- package/dist/wrappers/openai.cjs +4 -0
- package/dist/wrappers/openai.js +4 -0
- package/dist/wrappers/openai_agents.cjs +15 -12
- package/dist/wrappers/openai_agents.js +15 -12
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@ const env_js_1 = require("../../env.cjs");
|
|
|
7
7
|
const utils_js_1 = require("./utils.cjs");
|
|
8
8
|
const utils_js_2 = require("./utils.cjs");
|
|
9
9
|
const types_js_1 = require("../../utils/types.cjs");
|
|
10
|
+
const _agent_type_js_1 = require("./_agent_type.cjs");
|
|
10
11
|
function _formatMessages(messages) {
|
|
11
12
|
if (!Array.isArray(messages))
|
|
12
13
|
return messages;
|
|
@@ -52,12 +53,6 @@ event, traceRawHttp) {
|
|
|
52
53
|
}
|
|
53
54
|
return (0, utils_js_1.convertMessageToTracedFormat)(output);
|
|
54
55
|
}
|
|
55
|
-
function _getLsAgentType(parentRunTree) {
|
|
56
|
-
if ((0, run_trees_js_1.isRunTree)(parentRunTree) && parentRunTree.run_type === "tool") {
|
|
57
|
-
return "subagent";
|
|
58
|
-
}
|
|
59
|
-
return "root";
|
|
60
|
-
}
|
|
61
56
|
function _hasNonzeroUsageMetadata(runTree) {
|
|
62
57
|
const usageMetadata = runTree.extra?.metadata?.usage_metadata;
|
|
63
58
|
if (!(0, types_js_1.isRecord)(usageMetadata))
|
|
@@ -200,7 +195,7 @@ function LangSmithTelemetry(config) {
|
|
|
200
195
|
metadata: {
|
|
201
196
|
...customMetadata,
|
|
202
197
|
ai_sdk_method: event.operationId,
|
|
203
|
-
|
|
198
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(parentRunTree),
|
|
204
199
|
ls_model_name: event.modelId,
|
|
205
200
|
ls_integration: "vercel-ai-sdk-telemetry",
|
|
206
201
|
},
|
|
@@ -4,6 +4,7 @@ import { isEnvTracingEnabled } from "../../env.js";
|
|
|
4
4
|
import { convertMessageToTracedFormat } from "./utils.js";
|
|
5
5
|
import { setUsageMetadataOnRunTree } from "./utils.js";
|
|
6
6
|
import { isPrimitive, isRecord } from "../../utils/types.js";
|
|
7
|
+
import { vercelLsAgentTypeMetadata } from "./_agent_type.js";
|
|
7
8
|
function _formatMessages(messages) {
|
|
8
9
|
if (!Array.isArray(messages))
|
|
9
10
|
return messages;
|
|
@@ -49,12 +50,6 @@ event, traceRawHttp) {
|
|
|
49
50
|
}
|
|
50
51
|
return convertMessageToTracedFormat(output);
|
|
51
52
|
}
|
|
52
|
-
function _getLsAgentType(parentRunTree) {
|
|
53
|
-
if (isRunTree(parentRunTree) && parentRunTree.run_type === "tool") {
|
|
54
|
-
return "subagent";
|
|
55
|
-
}
|
|
56
|
-
return "root";
|
|
57
|
-
}
|
|
58
53
|
function _hasNonzeroUsageMetadata(runTree) {
|
|
59
54
|
const usageMetadata = runTree.extra?.metadata?.usage_metadata;
|
|
60
55
|
if (!isRecord(usageMetadata))
|
|
@@ -197,7 +192,7 @@ export function LangSmithTelemetry(config) {
|
|
|
197
192
|
metadata: {
|
|
198
193
|
...customMetadata,
|
|
199
194
|
ai_sdk_method: event.operationId,
|
|
200
|
-
|
|
195
|
+
...vercelLsAgentTypeMetadata(parentRunTree),
|
|
201
196
|
ls_model_name: event.modelId,
|
|
202
197
|
ls_integration: "vercel-ai-sdk-telemetry",
|
|
203
198
|
},
|
|
@@ -5,6 +5,7 @@ const middleware_js_1 = require("./middleware.cjs");
|
|
|
5
5
|
const utils_js_1 = require("./utils.cjs");
|
|
6
6
|
Object.defineProperty(exports, "convertMessageToTracedFormat", { enumerable: true, get: function () { return utils_js_1.convertMessageToTracedFormat; } });
|
|
7
7
|
const traceable_js_1 = require("../../traceable.cjs");
|
|
8
|
+
const _agent_type_js_1 = require("./_agent_type.cjs");
|
|
8
9
|
const _getModelDisplayName = (model) => {
|
|
9
10
|
if (typeof model === "string") {
|
|
10
11
|
return model;
|
|
@@ -118,19 +119,12 @@ const _resolveConfigs = (baseLsConfig, runtimeLsConfig) => {
|
|
|
118
119
|
resolvedToolConfig,
|
|
119
120
|
};
|
|
120
121
|
};
|
|
121
|
-
const _getLsAgentType = () => {
|
|
122
|
-
const parentRun = (0, traceable_js_1.getCurrentRunTree)(true);
|
|
123
|
-
if (parentRun != null && parentRun.run_type === "tool") {
|
|
124
|
-
return "subagent";
|
|
125
|
-
}
|
|
126
|
-
return "root";
|
|
127
|
-
};
|
|
128
122
|
const _getGenerateTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolvedLsConfig, hasExplicitOutput, hasExplicitExperimentalOutput, traceResponseMetadata, }) => {
|
|
129
123
|
return {
|
|
130
124
|
name: runName ?? _getModelDisplayName(model),
|
|
131
125
|
...resolvedLsConfig,
|
|
132
126
|
metadata: {
|
|
133
|
-
|
|
127
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
134
128
|
ai_sdk_method: aiSdkMethodName ?? "ai.generateText",
|
|
135
129
|
...resolvedLsConfig?.metadata,
|
|
136
130
|
},
|
|
@@ -206,7 +200,7 @@ const _getStreamTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolved
|
|
|
206
200
|
name: runName ?? _getModelDisplayName(model),
|
|
207
201
|
...resolvedLsConfig,
|
|
208
202
|
metadata: {
|
|
209
|
-
|
|
203
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
210
204
|
ai_sdk_method: aiSdkMethodName ?? "ai.streamText",
|
|
211
205
|
...resolvedLsConfig?.metadata,
|
|
212
206
|
},
|
|
@@ -409,7 +403,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
409
403
|
name: _getModelDisplayName(params.model),
|
|
410
404
|
...resolvedLsConfig,
|
|
411
405
|
metadata: {
|
|
412
|
-
|
|
406
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
413
407
|
ai_sdk_method: "ai.generateObject",
|
|
414
408
|
...resolvedLsConfig?.metadata,
|
|
415
409
|
},
|
|
@@ -531,7 +525,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
531
525
|
name: _getModelDisplayName(params.model),
|
|
532
526
|
...resolvedLsConfig,
|
|
533
527
|
metadata: {
|
|
534
|
-
|
|
528
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
535
529
|
ai_sdk_method: "ai.streamObject",
|
|
536
530
|
...resolvedLsConfig?.metadata,
|
|
537
531
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LangSmithMiddleware, } from "./middleware.js";
|
|
2
2
|
import { convertMessageToTracedFormat } from "./utils.js";
|
|
3
|
-
import { isTraceableFunction, traceable
|
|
3
|
+
import { isTraceableFunction, traceable } from "../../traceable.js";
|
|
4
|
+
import { vercelLsAgentTypeMetadata } from "./_agent_type.js";
|
|
4
5
|
const _getModelDisplayName = (model) => {
|
|
5
6
|
if (typeof model === "string") {
|
|
6
7
|
return model;
|
|
@@ -114,19 +115,12 @@ const _resolveConfigs = (baseLsConfig, runtimeLsConfig) => {
|
|
|
114
115
|
resolvedToolConfig,
|
|
115
116
|
};
|
|
116
117
|
};
|
|
117
|
-
const _getLsAgentType = () => {
|
|
118
|
-
const parentRun = getCurrentRunTree(true);
|
|
119
|
-
if (parentRun != null && parentRun.run_type === "tool") {
|
|
120
|
-
return "subagent";
|
|
121
|
-
}
|
|
122
|
-
return "root";
|
|
123
|
-
};
|
|
124
118
|
const _getGenerateTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolvedLsConfig, hasExplicitOutput, hasExplicitExperimentalOutput, traceResponseMetadata, }) => {
|
|
125
119
|
return {
|
|
126
120
|
name: runName ?? _getModelDisplayName(model),
|
|
127
121
|
...resolvedLsConfig,
|
|
128
122
|
metadata: {
|
|
129
|
-
|
|
123
|
+
...vercelLsAgentTypeMetadata(),
|
|
130
124
|
ai_sdk_method: aiSdkMethodName ?? "ai.generateText",
|
|
131
125
|
...resolvedLsConfig?.metadata,
|
|
132
126
|
},
|
|
@@ -202,7 +196,7 @@ const _getStreamTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolved
|
|
|
202
196
|
name: runName ?? _getModelDisplayName(model),
|
|
203
197
|
...resolvedLsConfig,
|
|
204
198
|
metadata: {
|
|
205
|
-
|
|
199
|
+
...vercelLsAgentTypeMetadata(),
|
|
206
200
|
ai_sdk_method: aiSdkMethodName ?? "ai.streamText",
|
|
207
201
|
...resolvedLsConfig?.metadata,
|
|
208
202
|
},
|
|
@@ -404,7 +398,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
404
398
|
name: _getModelDisplayName(params.model),
|
|
405
399
|
...resolvedLsConfig,
|
|
406
400
|
metadata: {
|
|
407
|
-
|
|
401
|
+
...vercelLsAgentTypeMetadata(),
|
|
408
402
|
ai_sdk_method: "ai.generateObject",
|
|
409
403
|
...resolvedLsConfig?.metadata,
|
|
410
404
|
},
|
|
@@ -526,7 +520,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
526
520
|
name: _getModelDisplayName(params.model),
|
|
527
521
|
...resolvedLsConfig,
|
|
528
522
|
metadata: {
|
|
529
|
-
|
|
523
|
+
...vercelLsAgentTypeMetadata(),
|
|
530
524
|
ai_sdk_method: "ai.streamObject",
|
|
531
525
|
...resolvedLsConfig?.metadata,
|
|
532
526
|
},
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,6 @@ Object.defineProperty(exports, "UnprocessableEntityError", { enumerable: true, g
|
|
|
35
35
|
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return error_js_1.RateLimitError; } });
|
|
36
36
|
Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return error_js_1.InternalServerError; } });
|
|
37
37
|
// Update using pnpm bump-version
|
|
38
|
-
exports.__version__ = "0.8.
|
|
38
|
+
exports.__version__ = "0.8.10";
|
|
39
39
|
// Metadata key to hide a traced run from LangSmith's Messages View.
|
|
40
40
|
exports.LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export { computeRunIdForSecondaryReplica, uuid7, uuid7FromTime, } from "./uuid.j
|
|
|
7
7
|
export { isTracingEnabled } from "./utils/guard.js";
|
|
8
8
|
export { Cache, PromptCache, type CacheConfig, type CacheMetrics, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
9
9
|
export { LangsmithError, APIError, APIUserAbortError, APIConnectionError, APIConnectionTimeoutError, BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, } from "./_openapi_client/core/error.js";
|
|
10
|
-
export declare const __version__ = "0.8.
|
|
10
|
+
export declare const __version__ = "0.8.10";
|
|
11
11
|
export declare const LS_MESSAGE_VIEW_EXCLUDE: "ls_message_view_exclude";
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,6 @@ export { isTracingEnabled } from "./utils/guard.js";
|
|
|
7
7
|
export { Cache, PromptCache, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
8
8
|
export { LangsmithError, APIError, APIUserAbortError, APIConnectionError, APIConnectionTimeoutError, BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, } from "./_openapi_client/core/error.js";
|
|
9
9
|
// Update using pnpm bump-version
|
|
10
|
-
export const __version__ = "0.8.
|
|
10
|
+
export const __version__ = "0.8.10";
|
|
11
11
|
// Metadata key to hide a traced run from LangSmith's Messages View.
|
|
12
12
|
export const LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
|
|
@@ -8,6 +8,22 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.CommandHandle = void 0;
|
|
10
10
|
const errors_js_1 = require("./errors.cjs");
|
|
11
|
+
/**
|
|
12
|
+
* Whether a 'started' frame proves *this* command was reattached to.
|
|
13
|
+
*
|
|
14
|
+
* A command and its WebSocket are separate things: the command keeps running on
|
|
15
|
+
* the server and the socket is only this client's attachment to it. The server
|
|
16
|
+
* acknowledges every successful reattachment with 'started', which for a command
|
|
17
|
+
* that produces no output is the only evidence it landed. One naming a different
|
|
18
|
+
* command is not evidence, and must not clear the reconnect budget.
|
|
19
|
+
*/
|
|
20
|
+
function acknowledgesReconnect(msg, commandId) {
|
|
21
|
+
const acked = msg.command_id;
|
|
22
|
+
if (acked === commandId)
|
|
23
|
+
return true;
|
|
24
|
+
console.warn(`Ignoring reconnect acknowledgement for command ${String(acked)} while attached to ${String(commandId)}`);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
11
27
|
/**
|
|
12
28
|
* Async handle to a running command with streaming output and auto-reconnect.
|
|
13
29
|
*
|
|
@@ -107,6 +123,12 @@ class CommandHandle {
|
|
|
107
123
|
writable: true,
|
|
108
124
|
value: void 0
|
|
109
125
|
});
|
|
126
|
+
Object.defineProperty(this, "_reconnectAttempts", {
|
|
127
|
+
enumerable: true,
|
|
128
|
+
configurable: true,
|
|
129
|
+
writable: true,
|
|
130
|
+
value: 0
|
|
131
|
+
});
|
|
110
132
|
Object.defineProperty(this, "_onStdout", {
|
|
111
133
|
enumerable: true,
|
|
112
134
|
configurable: true,
|
|
@@ -192,7 +214,12 @@ class CommandHandle {
|
|
|
192
214
|
return;
|
|
193
215
|
for await (const msg of this._stream) {
|
|
194
216
|
const msgType = msg.type;
|
|
195
|
-
if (msgType === "
|
|
217
|
+
if (msgType === "started") {
|
|
218
|
+
if (acknowledgesReconnect(msg, this._commandId)) {
|
|
219
|
+
this._reconnectAttempts = 0;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else if (msgType === "stdout" || msgType === "stderr") {
|
|
196
223
|
const chunk = {
|
|
197
224
|
stream: msgType,
|
|
198
225
|
data: msg.data,
|
|
@@ -227,11 +254,11 @@ class CommandHandle {
|
|
|
227
254
|
* - After kill(): no reconnect, error propagates
|
|
228
255
|
*/
|
|
229
256
|
async *[Symbol.asyncIterator]() {
|
|
230
|
-
|
|
257
|
+
this._reconnectAttempts = 0;
|
|
231
258
|
while (true) {
|
|
232
259
|
try {
|
|
233
260
|
for await (const chunk of this._iterStream()) {
|
|
234
|
-
|
|
261
|
+
this._reconnectAttempts = 0; // Reset on successful data
|
|
235
262
|
if (chunk.stream === "stdout") {
|
|
236
263
|
this._lastStdoutOffset =
|
|
237
264
|
chunk.offset + new TextEncoder().encode(chunk.data).length;
|
|
@@ -255,13 +282,13 @@ class CommandHandle {
|
|
|
255
282
|
if (this._control && this._control.killed) {
|
|
256
283
|
throw e;
|
|
257
284
|
}
|
|
258
|
-
|
|
259
|
-
if (
|
|
260
|
-
throw new errors_js_1.LangSmithSandboxConnectionError(`
|
|
285
|
+
this._reconnectAttempts++;
|
|
286
|
+
if (this._reconnectAttempts > CommandHandle.MAX_AUTO_RECONNECTS) {
|
|
287
|
+
throw new errors_js_1.LangSmithSandboxConnectionError(`Failed to reattach to the command ${this._reconnectAttempts} times in succession, giving up`);
|
|
261
288
|
}
|
|
262
289
|
const isHotReload = e instanceof errors_js_1.LangSmithSandboxServerReloadError;
|
|
263
290
|
if (!isHotReload) {
|
|
264
|
-
const delay = Math.min(CommandHandle.BACKOFF_BASE * 2 ** (
|
|
291
|
+
const delay = Math.min(CommandHandle.BACKOFF_BASE * 2 ** (this._reconnectAttempts - 1), CommandHandle.BACKOFF_MAX);
|
|
265
292
|
await new Promise((r) => setTimeout(r, delay * 1000));
|
|
266
293
|
}
|
|
267
294
|
if (this._commandId === null) {
|
|
@@ -5,6 +5,22 @@
|
|
|
5
5
|
* Port of Python's AsyncCommandHandle to TypeScript.
|
|
6
6
|
*/
|
|
7
7
|
import { LangSmithSandboxConnectionError, LangSmithSandboxServerReloadError, LangSmithSandboxOperationError, LangSmithStreamEndedBeforeStartedError, } from "./errors.js";
|
|
8
|
+
/**
|
|
9
|
+
* Whether a 'started' frame proves *this* command was reattached to.
|
|
10
|
+
*
|
|
11
|
+
* A command and its WebSocket are separate things: the command keeps running on
|
|
12
|
+
* the server and the socket is only this client's attachment to it. The server
|
|
13
|
+
* acknowledges every successful reattachment with 'started', which for a command
|
|
14
|
+
* that produces no output is the only evidence it landed. One naming a different
|
|
15
|
+
* command is not evidence, and must not clear the reconnect budget.
|
|
16
|
+
*/
|
|
17
|
+
function acknowledgesReconnect(msg, commandId) {
|
|
18
|
+
const acked = msg.command_id;
|
|
19
|
+
if (acked === commandId)
|
|
20
|
+
return true;
|
|
21
|
+
console.warn(`Ignoring reconnect acknowledgement for command ${String(acked)} while attached to ${String(commandId)}`);
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
8
24
|
/**
|
|
9
25
|
* Async handle to a running command with streaming output and auto-reconnect.
|
|
10
26
|
*
|
|
@@ -104,6 +120,12 @@ export class CommandHandle {
|
|
|
104
120
|
writable: true,
|
|
105
121
|
value: void 0
|
|
106
122
|
});
|
|
123
|
+
Object.defineProperty(this, "_reconnectAttempts", {
|
|
124
|
+
enumerable: true,
|
|
125
|
+
configurable: true,
|
|
126
|
+
writable: true,
|
|
127
|
+
value: 0
|
|
128
|
+
});
|
|
107
129
|
Object.defineProperty(this, "_onStdout", {
|
|
108
130
|
enumerable: true,
|
|
109
131
|
configurable: true,
|
|
@@ -189,7 +211,12 @@ export class CommandHandle {
|
|
|
189
211
|
return;
|
|
190
212
|
for await (const msg of this._stream) {
|
|
191
213
|
const msgType = msg.type;
|
|
192
|
-
if (msgType === "
|
|
214
|
+
if (msgType === "started") {
|
|
215
|
+
if (acknowledgesReconnect(msg, this._commandId)) {
|
|
216
|
+
this._reconnectAttempts = 0;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else if (msgType === "stdout" || msgType === "stderr") {
|
|
193
220
|
const chunk = {
|
|
194
221
|
stream: msgType,
|
|
195
222
|
data: msg.data,
|
|
@@ -224,11 +251,11 @@ export class CommandHandle {
|
|
|
224
251
|
* - After kill(): no reconnect, error propagates
|
|
225
252
|
*/
|
|
226
253
|
async *[Symbol.asyncIterator]() {
|
|
227
|
-
|
|
254
|
+
this._reconnectAttempts = 0;
|
|
228
255
|
while (true) {
|
|
229
256
|
try {
|
|
230
257
|
for await (const chunk of this._iterStream()) {
|
|
231
|
-
|
|
258
|
+
this._reconnectAttempts = 0; // Reset on successful data
|
|
232
259
|
if (chunk.stream === "stdout") {
|
|
233
260
|
this._lastStdoutOffset =
|
|
234
261
|
chunk.offset + new TextEncoder().encode(chunk.data).length;
|
|
@@ -252,13 +279,13 @@ export class CommandHandle {
|
|
|
252
279
|
if (this._control && this._control.killed) {
|
|
253
280
|
throw e;
|
|
254
281
|
}
|
|
255
|
-
|
|
256
|
-
if (
|
|
257
|
-
throw new LangSmithSandboxConnectionError(`
|
|
282
|
+
this._reconnectAttempts++;
|
|
283
|
+
if (this._reconnectAttempts > CommandHandle.MAX_AUTO_RECONNECTS) {
|
|
284
|
+
throw new LangSmithSandboxConnectionError(`Failed to reattach to the command ${this._reconnectAttempts} times in succession, giving up`);
|
|
258
285
|
}
|
|
259
286
|
const isHotReload = e instanceof LangSmithSandboxServerReloadError;
|
|
260
287
|
if (!isHotReload) {
|
|
261
|
-
const delay = Math.min(CommandHandle.BACKOFF_BASE * 2 ** (
|
|
288
|
+
const delay = Math.min(CommandHandle.BACKOFF_BASE * 2 ** (this._reconnectAttempts - 1), CommandHandle.BACKOFF_MAX);
|
|
262
289
|
await new Promise((r) => setTimeout(r, delay * 1000));
|
|
263
290
|
}
|
|
264
291
|
if (this._commandId === null) {
|
|
@@ -382,8 +382,10 @@ async function runWsStream(dataplaneUrl, apiKey, command, options = {}) {
|
|
|
382
382
|
* Reconnect to an existing command over WebSocket.
|
|
383
383
|
*
|
|
384
384
|
* Returns a tuple of [async_message_iterator, control], same as runWsStream.
|
|
385
|
-
* The iterator yields
|
|
386
|
-
*
|
|
385
|
+
* The iterator yields the server's 'started' acknowledgement, then stdout,
|
|
386
|
+
* stderr, exit, and error messages. That acknowledgement is the only evidence a
|
|
387
|
+
* reattachment landed for a command producing no output, so it is forwarded
|
|
388
|
+
* rather than dropped.
|
|
387
389
|
*/
|
|
388
390
|
async function reconnectWsStream(dataplaneUrl, apiKey, commandId, options = {}) {
|
|
389
391
|
const { stdoutOffset = 0, stderrOffset = 0, headers: extraHeaders } = options;
|
|
@@ -405,7 +407,9 @@ async function reconnectWsStream(dataplaneUrl, apiKey, commandId, options = {})
|
|
|
405
407
|
// Read messages until exit or error
|
|
406
408
|
for await (const msg of readWsMessages(ws)) {
|
|
407
409
|
const msgType = msg.type;
|
|
408
|
-
if (msgType === "
|
|
410
|
+
if (msgType === "started" ||
|
|
411
|
+
msgType === "stdout" ||
|
|
412
|
+
msgType === "stderr") {
|
|
409
413
|
yield msg;
|
|
410
414
|
}
|
|
411
415
|
else if (msgType === "exit") {
|
|
@@ -70,8 +70,10 @@ export declare function runWsStream(dataplaneUrl: string, apiKey: string | undef
|
|
|
70
70
|
* Reconnect to an existing command over WebSocket.
|
|
71
71
|
*
|
|
72
72
|
* Returns a tuple of [async_message_iterator, control], same as runWsStream.
|
|
73
|
-
* The iterator yields
|
|
74
|
-
*
|
|
73
|
+
* The iterator yields the server's 'started' acknowledgement, then stdout,
|
|
74
|
+
* stderr, exit, and error messages. That acknowledgement is the only evidence a
|
|
75
|
+
* reattachment landed for a command producing no output, so it is forwarded
|
|
76
|
+
* rather than dropped.
|
|
75
77
|
*/
|
|
76
78
|
export declare function reconnectWsStream(dataplaneUrl: string, apiKey: string | undefined, commandId: string, options?: {
|
|
77
79
|
stdoutOffset?: number;
|
|
@@ -369,8 +369,10 @@ export async function runWsStream(dataplaneUrl, apiKey, command, options = {}) {
|
|
|
369
369
|
* Reconnect to an existing command over WebSocket.
|
|
370
370
|
*
|
|
371
371
|
* Returns a tuple of [async_message_iterator, control], same as runWsStream.
|
|
372
|
-
* The iterator yields
|
|
373
|
-
*
|
|
372
|
+
* The iterator yields the server's 'started' acknowledgement, then stdout,
|
|
373
|
+
* stderr, exit, and error messages. That acknowledgement is the only evidence a
|
|
374
|
+
* reattachment landed for a command producing no output, so it is forwarded
|
|
375
|
+
* rather than dropped.
|
|
374
376
|
*/
|
|
375
377
|
export async function reconnectWsStream(dataplaneUrl, apiKey, commandId, options = {}) {
|
|
376
378
|
const { stdoutOffset = 0, stderrOffset = 0, headers: extraHeaders } = options;
|
|
@@ -392,7 +394,9 @@ export async function reconnectWsStream(dataplaneUrl, apiKey, commandId, options
|
|
|
392
394
|
// Read messages until exit or error
|
|
393
395
|
for await (const msg of readWsMessages(ws)) {
|
|
394
396
|
const msgType = msg.type;
|
|
395
|
-
if (msgType === "
|
|
397
|
+
if (msgType === "started" ||
|
|
398
|
+
msgType === "stdout" ||
|
|
399
|
+
msgType === "stderr") {
|
|
396
400
|
yield msg;
|
|
397
401
|
}
|
|
398
402
|
else if (msgType === "exit") {
|
package/dist/utils/_git.cjs
CHANGED
|
@@ -17,6 +17,33 @@ const execGit = (command, exec) => {
|
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
+
function sanitizeRemoteUrl(remoteUrl) {
|
|
21
|
+
if (remoteUrl == null) {
|
|
22
|
+
return remoteUrl;
|
|
23
|
+
}
|
|
24
|
+
const schemeSeparator = remoteUrl.indexOf("://");
|
|
25
|
+
if (schemeSeparator === -1) {
|
|
26
|
+
return remoteUrl;
|
|
27
|
+
}
|
|
28
|
+
const scheme = remoteUrl.slice(0, schemeSeparator).toLowerCase();
|
|
29
|
+
if (scheme !== "http" && scheme !== "https") {
|
|
30
|
+
return remoteUrl;
|
|
31
|
+
}
|
|
32
|
+
const authorityStart = schemeSeparator + "://".length;
|
|
33
|
+
let authorityEnd = remoteUrl.length;
|
|
34
|
+
for (const delimiter of ["/", "?", "#"]) {
|
|
35
|
+
const delimiterIndex = remoteUrl.indexOf(delimiter, authorityStart);
|
|
36
|
+
if (delimiterIndex !== -1) {
|
|
37
|
+
authorityEnd = Math.min(authorityEnd, delimiterIndex);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const authority = remoteUrl.slice(authorityStart, authorityEnd);
|
|
41
|
+
const userinfoEnd = authority.lastIndexOf("@");
|
|
42
|
+
if (userinfoEnd === -1) {
|
|
43
|
+
return remoteUrl;
|
|
44
|
+
}
|
|
45
|
+
return `${remoteUrl.slice(0, authorityStart)}${authority.slice(userinfoEnd + 1)}${remoteUrl.slice(authorityEnd)}`;
|
|
46
|
+
}
|
|
20
47
|
const getGitInfo = async (remote = "origin") => {
|
|
21
48
|
let exec;
|
|
22
49
|
try {
|
|
@@ -42,7 +69,7 @@ const getGitInfo = async (remote = "origin") => {
|
|
|
42
69
|
execGit(["log", "-1", "--format=%ae"], exec),
|
|
43
70
|
]);
|
|
44
71
|
return {
|
|
45
|
-
remoteUrl,
|
|
72
|
+
remoteUrl: sanitizeRemoteUrl(remoteUrl),
|
|
46
73
|
commit,
|
|
47
74
|
commitTime,
|
|
48
75
|
branch,
|
package/dist/utils/_git.js
CHANGED
|
@@ -14,6 +14,33 @@ const execGit = (command, exec) => {
|
|
|
14
14
|
});
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
|
+
function sanitizeRemoteUrl(remoteUrl) {
|
|
18
|
+
if (remoteUrl == null) {
|
|
19
|
+
return remoteUrl;
|
|
20
|
+
}
|
|
21
|
+
const schemeSeparator = remoteUrl.indexOf("://");
|
|
22
|
+
if (schemeSeparator === -1) {
|
|
23
|
+
return remoteUrl;
|
|
24
|
+
}
|
|
25
|
+
const scheme = remoteUrl.slice(0, schemeSeparator).toLowerCase();
|
|
26
|
+
if (scheme !== "http" && scheme !== "https") {
|
|
27
|
+
return remoteUrl;
|
|
28
|
+
}
|
|
29
|
+
const authorityStart = schemeSeparator + "://".length;
|
|
30
|
+
let authorityEnd = remoteUrl.length;
|
|
31
|
+
for (const delimiter of ["/", "?", "#"]) {
|
|
32
|
+
const delimiterIndex = remoteUrl.indexOf(delimiter, authorityStart);
|
|
33
|
+
if (delimiterIndex !== -1) {
|
|
34
|
+
authorityEnd = Math.min(authorityEnd, delimiterIndex);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const authority = remoteUrl.slice(authorityStart, authorityEnd);
|
|
38
|
+
const userinfoEnd = authority.lastIndexOf("@");
|
|
39
|
+
if (userinfoEnd === -1) {
|
|
40
|
+
return remoteUrl;
|
|
41
|
+
}
|
|
42
|
+
return `${remoteUrl.slice(0, authorityStart)}${authority.slice(userinfoEnd + 1)}${remoteUrl.slice(authorityEnd)}`;
|
|
43
|
+
}
|
|
17
44
|
export const getGitInfo = async (remote = "origin") => {
|
|
18
45
|
let exec;
|
|
19
46
|
try {
|
|
@@ -39,7 +66,7 @@ export const getGitInfo = async (remote = "origin") => {
|
|
|
39
66
|
execGit(["log", "-1", "--format=%ae"], exec),
|
|
40
67
|
]);
|
|
41
68
|
return {
|
|
42
|
-
remoteUrl,
|
|
69
|
+
remoteUrl: sanitizeRemoteUrl(remoteUrl),
|
|
43
70
|
commit,
|
|
44
71
|
commitTime,
|
|
45
72
|
branch,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Shared primitives for the `ls_agent_type` metadata tag.
|
|
3
|
+
// Consumed by wrappers/integrations that stamp or inspect `ls_agent_type` on
|
|
4
|
+
// traced runs (wrap_openai, OpenAI Agents SDK, Vercel, future wrappers).
|
|
5
|
+
// Keep this module SDK-agnostic: the caller passes in the parent run tree.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.NON_ROOT_LS_AGENT_TYPES = void 0;
|
|
8
|
+
exports.resolveDefaultLsAgentType = resolveDefaultLsAgentType;
|
|
9
|
+
exports.lsAgentTypeMetadata = lsAgentTypeMetadata;
|
|
10
|
+
exports.defaultLsAgentTypeMetadata = defaultLsAgentTypeMetadata;
|
|
11
|
+
const run_trees_js_1 = require("../run_trees.cjs");
|
|
12
|
+
// Non-root tags: preserved against default/structural stamping.
|
|
13
|
+
exports.NON_ROOT_LS_AGENT_TYPES = new Set([
|
|
14
|
+
"middleware",
|
|
15
|
+
"subagent",
|
|
16
|
+
"compaction",
|
|
17
|
+
]);
|
|
18
|
+
// `"root"` at trace root; `undefined` when nested (rely on propagation).
|
|
19
|
+
function resolveDefaultLsAgentType(parentRunTree) {
|
|
20
|
+
return (0, run_trees_js_1.isRunTree)(parentRunTree) ? undefined : "root";
|
|
21
|
+
}
|
|
22
|
+
// Spread helper: `{ ls_agent_type: tag }` when tag is set, `{}` when undefined.
|
|
23
|
+
function lsAgentTypeMetadata(tag) {
|
|
24
|
+
return tag !== undefined ? { ls_agent_type: tag } : {};
|
|
25
|
+
}
|
|
26
|
+
// Preserves user-supplied ls_agent_type; stamps default only when key is absent.
|
|
27
|
+
function defaultLsAgentTypeMetadata(existingMetadata, parentRunTree) {
|
|
28
|
+
if ("ls_agent_type" in existingMetadata)
|
|
29
|
+
return {};
|
|
30
|
+
return lsAgentTypeMetadata(resolveDefaultLsAgentType(parentRunTree));
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type LsAgentType = "root" | "middleware" | "subagent" | "compaction";
|
|
2
|
+
export declare const NON_ROOT_LS_AGENT_TYPES: ReadonlySet<string>;
|
|
3
|
+
export declare function resolveDefaultLsAgentType(parentRunTree?: unknown): LsAgentType | undefined;
|
|
4
|
+
export declare function lsAgentTypeMetadata(tag: LsAgentType | undefined): {
|
|
5
|
+
ls_agent_type?: LsAgentType;
|
|
6
|
+
};
|
|
7
|
+
export declare function defaultLsAgentTypeMetadata(existingMetadata: Record<string, unknown>, parentRunTree?: unknown): {
|
|
8
|
+
ls_agent_type?: LsAgentType;
|
|
9
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Shared primitives for the `ls_agent_type` metadata tag.
|
|
2
|
+
// Consumed by wrappers/integrations that stamp or inspect `ls_agent_type` on
|
|
3
|
+
// traced runs (wrap_openai, OpenAI Agents SDK, Vercel, future wrappers).
|
|
4
|
+
// Keep this module SDK-agnostic: the caller passes in the parent run tree.
|
|
5
|
+
import { isRunTree } from "../run_trees.js";
|
|
6
|
+
// Non-root tags: preserved against default/structural stamping.
|
|
7
|
+
export const NON_ROOT_LS_AGENT_TYPES = new Set([
|
|
8
|
+
"middleware",
|
|
9
|
+
"subagent",
|
|
10
|
+
"compaction",
|
|
11
|
+
]);
|
|
12
|
+
// `"root"` at trace root; `undefined` when nested (rely on propagation).
|
|
13
|
+
export function resolveDefaultLsAgentType(parentRunTree) {
|
|
14
|
+
return isRunTree(parentRunTree) ? undefined : "root";
|
|
15
|
+
}
|
|
16
|
+
// Spread helper: `{ ls_agent_type: tag }` when tag is set, `{}` when undefined.
|
|
17
|
+
export function lsAgentTypeMetadata(tag) {
|
|
18
|
+
return tag !== undefined ? { ls_agent_type: tag } : {};
|
|
19
|
+
}
|
|
20
|
+
// Preserves user-supplied ls_agent_type; stamps default only when key is absent.
|
|
21
|
+
export function defaultLsAgentTypeMetadata(existingMetadata, parentRunTree) {
|
|
22
|
+
if ("ls_agent_type" in existingMetadata)
|
|
23
|
+
return {};
|
|
24
|
+
return lsAgentTypeMetadata(resolveDefaultLsAgentType(parentRunTree));
|
|
25
|
+
}
|