@sentry/junior 0.109.0 → 0.111.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-hooks-FHHVLNPA.js → agent-hooks-QQ2IWKOP.js} +12 -13
- package/dist/api/conversations/access.d.ts +9 -0
- package/dist/api/conversations/aggregate.d.ts +12 -1
- package/dist/api/conversations/archive.d.ts +3 -5
- package/dist/api/conversations/detail.d.ts +156 -7
- package/dist/api/conversations/events.d.ts +1 -1
- package/dist/api/conversations/list.d.ts +57 -6
- package/dist/api/conversations/projection.d.ts +6 -7
- package/dist/api/conversations/reporting.d.ts +10 -4
- package/dist/api/conversations/routes.d.ts +2 -1
- package/dist/api/conversations/shared.d.ts +1 -1
- package/dist/api/conversations/stats.d.ts +37 -6
- package/dist/api/conversations/stats.query.d.ts +1 -1
- package/dist/api/conversations/usage.d.ts +9 -0
- package/dist/api/http.d.ts +7 -0
- package/dist/api/locations/detail.d.ts +102 -6
- package/dist/api/locations/list.d.ts +43 -5
- package/dist/api/locations/query.d.ts +4 -2
- package/dist/api/locations/routes.d.ts +2 -1
- package/dist/api/people/list.d.ts +28 -6
- package/dist/api/people/list.query.d.ts +1 -1
- package/dist/api/people/profile.d.ts +96 -7
- package/dist/api/people/profile.query.d.ts +4 -2
- package/dist/api/people/routes.d.ts +2 -1
- package/dist/api/people/shared.d.ts +1219 -2
- package/dist/api/route.d.ts +18 -4
- package/dist/api/schema/common.d.ts +6 -0
- package/dist/api/{conversations/schema.d.ts → schema/conversation.d.ts} +31 -3
- package/dist/api/{locations/schema.d.ts → schema/location.d.ts} +5 -0
- package/dist/api/{people/schema.d.ts → schema/person.d.ts} +37 -45
- package/dist/api/schema.d.ts +8 -22
- package/dist/api/schema.js +10 -2
- package/dist/api.d.ts +5 -1
- package/dist/api.js +767 -384
- package/dist/app.js +591 -447
- package/dist/build/virtual-config.d.ts +2 -0
- package/dist/catalog-runtime-D22W6QEJ.js +16 -0
- package/dist/chat/agent/request.d.ts +3 -6
- package/dist/chat/agent/resume.d.ts +11 -12
- package/dist/chat/agent/sandbox.d.ts +36 -11
- package/dist/chat/agent/tools.d.ts +5 -8
- package/dist/chat/config.d.ts +8 -1
- package/dist/chat/conversations/history.d.ts +3 -0
- package/dist/chat/conversations/sql/privacy.d.ts +3 -15
- package/dist/chat/pi/messages.d.ts +2 -2
- package/dist/chat/pi/sdk.d.ts +1 -1
- package/dist/chat/pi/sql-model-usage.d.ts +4 -1
- package/dist/chat/plugins/agent-hooks.d.ts +2 -2
- package/dist/chat/runtime/agent-continue-runner.d.ts +7 -3
- package/dist/chat/runtime/slack-runtime.d.ts +1 -2
- package/dist/chat/runtime/thread-state.d.ts +3 -7
- package/dist/chat/runtime/turn-preparation.d.ts +2 -2
- package/dist/chat/sandbox/command-result.d.ts +91 -0
- package/dist/chat/sandbox/errors.d.ts +3 -1
- package/dist/chat/sandbox/ref.d.ts +5 -0
- package/dist/chat/sandbox/sandbox.d.ts +19 -46
- package/dist/chat/sandbox/session.d.ts +16 -20
- package/dist/chat/sandbox/skill-sync.d.ts +2 -2
- package/dist/chat/sandbox/workspace.d.ts +14 -12
- package/dist/chat/services/auth-pause.d.ts +4 -0
- package/dist/chat/services/context-compaction.d.ts +1 -0
- package/dist/chat/services/turn-result.d.ts +3 -4
- package/dist/chat/task-execution/queue-signing.d.ts +10 -8
- package/dist/chat/task-execution/queue.d.ts +9 -7
- package/dist/chat/task-execution/slack-work.d.ts +9 -7
- package/dist/chat/task-execution/state.d.ts +75 -22
- package/dist/chat/task-execution/store.d.ts +34 -3
- package/dist/chat/task-execution/worker.d.ts +0 -1
- package/dist/chat/tool-support/normalize-result.d.ts +2 -2
- package/dist/chat/tool-support/pi-tool-adapter.d.ts +2 -2
- package/dist/chat/tool-support/structured-result.d.ts +1 -2
- package/dist/chat/tools/sandbox/file-uploads.d.ts +1 -1
- package/dist/chat/{runtime → tools/sandbox}/generated-artifacts.d.ts +3 -3
- package/dist/chat/tools/types.d.ts +1 -1
- package/dist/chat/tools/web/fetch-content.d.ts +5 -0
- package/dist/chat/tools/web/image-generate.d.ts +2 -1
- package/dist/chat/tools/web/search.d.ts +1 -1
- package/dist/{chunk-CEA3A3UA.js → chunk-2ZTTXTSZ.js} +24 -1
- package/dist/{chunk-IVVGFRQQ.js → chunk-42WRQLJ6.js} +10 -38
- package/dist/{chunk-O3JMSZLI.js → chunk-6Y5L4BOM.js} +3 -5
- package/dist/{chunk-HO5NT6OE.js → chunk-B45FPP2A.js} +306 -31
- package/dist/{chunk-WHMOBKT7.js → chunk-BTRNMS6A.js} +2 -2
- package/dist/{chunk-PLB7MRCQ.js → chunk-C4MZ3GP5.js} +1 -1
- package/dist/{chunk-HHVY4SMP.js → chunk-FPK7XY3F.js} +98 -92
- package/dist/{chunk-RGX4V75M.js → chunk-IFAHK54X.js} +3 -3
- package/dist/{chunk-ISMWX44P.js → chunk-J7APPQIJ.js} +2 -2
- package/dist/{chunk-TMBRFULF.js → chunk-JQFJO5WH.js} +7 -1
- package/dist/{chunk-FWJRXN4F.js → chunk-L6JPKANW.js} +3 -139
- package/dist/{chunk-7Q6WCISF.js → chunk-MIAKQNYX.js} +43 -31
- package/dist/chunk-MPVES2IC.js +44 -0
- package/dist/{chunk-JNAVF45E.js → chunk-NQLWOTY4.js} +47 -19
- package/dist/{chunk-IXKSQGIO.js → chunk-OOLU34J4.js} +8860 -9137
- package/dist/{chunk-OUHNWH46.js → chunk-PYKKM4MM.js} +1 -1
- package/dist/{chunk-MXW4GL53.js → chunk-PZELBSHC.js} +8 -9
- package/dist/{chunk-QY636HZU.js → chunk-QQIVLZW4.js} +96 -17
- package/dist/{chunk-72OMGPDS.js → chunk-SL3ZKNLQ.js} +19 -18
- package/dist/{chunk-3SXUV423.js → chunk-WSRBFHPX.js} +1 -1
- package/dist/{chunk-TT6GMXNA.js → chunk-XQAYFRWT.js} +2 -2
- package/dist/{chunk-MGUMR35T.js → chunk-Z2W4SJZ7.js} +1 -1
- package/dist/{chunk-OCD3OZRK.js → chunk-Z4G3WCP3.js} +1 -1
- package/dist/{chunk-FENLIFJD.js → chunk-ZRZ4SVWG.js} +69 -10
- package/dist/cli/chat.js +23 -24
- package/dist/cli/check.js +8 -8
- package/dist/cli/plugins.js +15 -16
- package/dist/cli/snapshot-warmup.js +11 -11
- package/dist/cli/upgrade.js +9 -9
- package/dist/db/schema/conversations.d.ts +17 -0
- package/dist/db/schema.d.ts +17 -0
- package/dist/{db-V3NU72O2.js → db-WXQOQESG.js} +8 -9
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +15 -10
- package/dist/reporting-schema.d.ts +46 -0
- package/dist/{runner-JYBCQBLK.js → runner-4QY4XH4B.js} +23 -33
- package/dist/{skills-U6MDAST7.js → skills-P5MU4EBX.js} +8 -8
- package/dist/{validation-72N3JVRU.js → validation-PQF5OP6T.js} +8 -8
- package/dist/version.js +1 -1
- package/migrations/0007_thick_sugar_man.sql +23 -0
- package/migrations/meta/0007_snapshot.json +1013 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +6 -6
- package/dist/catalog-runtime-DMGJSLV2.js +0 -16
- package/dist/chunk-OB42YVAE.js +0 -16
- package/dist/chunk-SYAQIR5Z.js +0 -53
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { FileUpload } from "chat";
|
|
2
2
|
import { type GeneratedArtifactFileRef } from "@/chat/tools/sandbox/file-uploads";
|
|
3
3
|
import type { SandboxCommandResult } from "@/chat/sandbox/workspace";
|
|
4
|
-
/**
|
|
5
|
-
export interface
|
|
4
|
+
/** Workspace operations needed to make generated artifacts visible to later tools. */
|
|
5
|
+
export interface GeneratedArtifactWorkspace {
|
|
6
6
|
runCommand(input: {
|
|
7
7
|
args?: string[];
|
|
8
8
|
cmd: string;
|
|
@@ -13,4 +13,4 @@ export interface GeneratedArtifactSandbox {
|
|
|
13
13
|
}>): Promise<void>;
|
|
14
14
|
}
|
|
15
15
|
/** Persist generated artifacts into the sandbox before returning model-visible handles. */
|
|
16
|
-
export declare function writeSandboxGeneratedArtifacts(
|
|
16
|
+
export declare function writeSandboxGeneratedArtifacts(workspace: GeneratedArtifactWorkspace, files: FileUpload[]): Promise<GeneratedArtifactFileRef[]>;
|
|
@@ -69,7 +69,7 @@ interface BaseToolRuntimeContext {
|
|
|
69
69
|
configuration?: Record<string, unknown>;
|
|
70
70
|
egress: PluginEgress;
|
|
71
71
|
mcpToolManager?: McpToolManager;
|
|
72
|
-
|
|
72
|
+
workspace: SandboxWorkspace;
|
|
73
73
|
}
|
|
74
74
|
interface SlackToolRuntimeContext extends BaseToolRuntimeContext {
|
|
75
75
|
destination: SlackDestination;
|
|
@@ -17,6 +17,11 @@ export type WebFetchResponse = {
|
|
|
17
17
|
extracted_chars: number;
|
|
18
18
|
truncated: boolean;
|
|
19
19
|
} & Record<string, unknown>;
|
|
20
|
+
/** Apply the web-fetch character limit to already extracted text content. */
|
|
21
|
+
export declare function truncateWebFetchContent(content: string, maxChars: number): {
|
|
22
|
+
content: string;
|
|
23
|
+
truncated: boolean;
|
|
24
|
+
};
|
|
20
25
|
/** Extract readable content and metadata from a fetched response body. */
|
|
21
26
|
export declare function extractContentDetails(body: string, contentType: string, maxChars: number): WebFetchResponseContent;
|
|
22
27
|
/** Extract readable content from a fetched response body, converting HTML to markdown. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ImageGenerateToolDeps, ToolHooks } from "@/chat/tools/types";
|
|
2
2
|
/** Create the image tool with sandbox artifact guidance matched to file-send capability. */
|
|
3
|
-
export declare function createImageGenerateTool(hooks: Required<Pick<ToolHooks, "writeGeneratedArtifacts">>, options
|
|
3
|
+
export declare function createImageGenerateTool(hooks: Required<Pick<ToolHooks, "writeGeneratedArtifacts">>, options: {
|
|
4
|
+
modelId: string;
|
|
4
5
|
canSendFilesToActiveConversation?: boolean;
|
|
5
6
|
}, deps?: ImageGenerateToolDeps): Omit<import("../definition").AnyToolDefinition, "inputSchema" | "outputSchema" | "prepareArguments" | "execute"> & {
|
|
6
7
|
inputSchema: import("../definition").JsonSchemaObject;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WebSearchToolDeps } from "@/chat/tools/types";
|
|
2
|
-
export declare function createWebSearchTool(override?: WebSearchToolDeps): Omit<import("../definition").AnyToolDefinition, "inputSchema" | "outputSchema" | "prepareArguments" | "execute"> & {
|
|
2
|
+
export declare function createWebSearchTool(modelId: string, override?: WebSearchToolDeps): Omit<import("../definition").AnyToolDefinition, "inputSchema" | "outputSchema" | "prepareArguments" | "execute"> & {
|
|
3
3
|
inputSchema: import("../definition").JsonSchemaObject;
|
|
4
4
|
outputSchema: import("../definition").JsonSchemaObject;
|
|
5
5
|
prepareArguments(args: unknown): {
|
|
@@ -59,12 +59,35 @@ var pluginOperationalRecordSetSchema = z.object({
|
|
|
59
59
|
records: z.array(pluginOperationalRecordSchema).optional(),
|
|
60
60
|
title: z.string()
|
|
61
61
|
}).strict();
|
|
62
|
+
var pluginOperationalBarChartWidgetSchema = z.object({
|
|
63
|
+
categories: z.array(
|
|
64
|
+
z.object({
|
|
65
|
+
id: z.string().min(1),
|
|
66
|
+
label: z.string().min(1),
|
|
67
|
+
values: z.record(z.string(), z.number().finite())
|
|
68
|
+
}).strict()
|
|
69
|
+
).max(100),
|
|
70
|
+
description: z.string().optional(),
|
|
71
|
+
emptyText: z.string().optional(),
|
|
72
|
+
id: z.string().min(1),
|
|
73
|
+
series: z.array(
|
|
74
|
+
z.object({
|
|
75
|
+
key: z.string().min(1),
|
|
76
|
+
label: z.string().min(1),
|
|
77
|
+
tone: pluginOperationalToneSchema.optional()
|
|
78
|
+
}).strict()
|
|
79
|
+
).min(1).max(8),
|
|
80
|
+
timeRangeDays: z.array(z.union([z.literal(7), z.literal(30), z.literal(90)])).min(1).max(3).optional(),
|
|
81
|
+
title: z.string().min(1),
|
|
82
|
+
type: z.literal("bar_chart")
|
|
83
|
+
}).strict();
|
|
62
84
|
var pluginOperationalReportSchema = z.object({
|
|
63
85
|
generatedAt: z.string().optional(),
|
|
64
86
|
metrics: z.array(pluginOperationalMetricSchema).optional(),
|
|
65
87
|
recordSets: z.array(pluginOperationalRecordSetSchema).optional(),
|
|
66
88
|
title: z.string().optional(),
|
|
67
|
-
pluginName: z.string()
|
|
89
|
+
pluginName: z.string(),
|
|
90
|
+
widgets: z.array(pluginOperationalBarChartWidgetSchema).max(12).optional()
|
|
68
91
|
}).strict();
|
|
69
92
|
var pluginOperationalReportFeedSchema = z.object({
|
|
70
93
|
generatedAt: z.string(),
|
|
@@ -1,34 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// src/deployment.ts
|
|
6
|
-
var JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
|
|
7
|
-
var JUNIOR_HEARTBEAT_CRON_SCHEDULE = "* * * * *";
|
|
8
|
-
var JUNIOR_RETENTION_ROUTE = "/api/internal/retention";
|
|
9
|
-
var JUNIOR_RETENTION_CRON_SCHEDULE = "0 4 * * *";
|
|
10
|
-
var JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE = "/api/internal/agent/continue";
|
|
11
|
-
var JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE = "/api/internal/plugin/tasks";
|
|
12
|
-
var LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION = "api/internal/agent/continue.ts";
|
|
13
|
-
function toOptionalTrimmed(value) {
|
|
14
|
-
const trimmed = value?.trim();
|
|
15
|
-
return trimmed ? trimmed : void 0;
|
|
1
|
+
// src/chat/coerce.ts
|
|
2
|
+
function toOptionalString(value) {
|
|
3
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
16
4
|
}
|
|
17
|
-
function
|
|
18
|
-
return
|
|
5
|
+
function toOptionalNumber(value) {
|
|
6
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
19
7
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
const serviceVersion = getDeploymentServiceVersion();
|
|
23
|
-
const deploymentId = toOptionalTrimmed(process.env.VERCEL_DEPLOYMENT_ID);
|
|
24
|
-
attributes["app.junior.version"] = JUNIOR_VERSION;
|
|
25
|
-
if (serviceVersion) {
|
|
26
|
-
attributes["service.version"] = serviceVersion;
|
|
27
|
-
}
|
|
28
|
-
if (deploymentId) {
|
|
29
|
-
attributes["deployment.id"] = deploymentId;
|
|
30
|
-
}
|
|
31
|
-
return attributes;
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return typeof value === "object" && value !== null;
|
|
32
10
|
}
|
|
33
11
|
|
|
34
12
|
// src/chat/slack/timestamp.ts
|
|
@@ -82,15 +60,9 @@ function parseSlackUserId(value) {
|
|
|
82
60
|
}
|
|
83
61
|
|
|
84
62
|
export {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
JUNIOR_RETENTION_CRON_SCHEDULE,
|
|
89
|
-
JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
|
|
90
|
-
JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE,
|
|
91
|
-
LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION,
|
|
92
|
-
getDeploymentServiceVersion,
|
|
93
|
-
getDeploymentTelemetryAttributes,
|
|
63
|
+
toOptionalString,
|
|
64
|
+
toOptionalNumber,
|
|
65
|
+
isRecord,
|
|
94
66
|
parseSlackMessageTs,
|
|
95
67
|
parseSlackChannelId,
|
|
96
68
|
parseSlackChannelReferenceId,
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
toOptionalString
|
|
3
|
-
} from "./chunk-OB42YVAE.js";
|
|
4
1
|
import {
|
|
5
2
|
parseSlackChannelId,
|
|
6
3
|
parseSlackMessageTs,
|
|
7
|
-
parseSlackTeamId
|
|
8
|
-
|
|
4
|
+
parseSlackTeamId,
|
|
5
|
+
toOptionalString
|
|
6
|
+
} from "./chunk-42WRQLJ6.js";
|
|
9
7
|
|
|
10
8
|
// src/chat/conversation-privacy.ts
|
|
11
9
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SANDBOX_WORKSPACE_ROOT,
|
|
3
3
|
getStateAdapter
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PYKKM4MM.js";
|
|
5
5
|
import {
|
|
6
6
|
sleep
|
|
7
7
|
} from "./chunk-4ZNGQH7C.js";
|
|
8
8
|
import {
|
|
9
9
|
toOptionalTrimmed
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NQLWOTY4.js";
|
|
11
11
|
import {
|
|
12
12
|
pluginCatalogRuntime
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WSRBFHPX.js";
|
|
14
14
|
import {
|
|
15
|
+
setSpanAttributes,
|
|
16
|
+
setSpanStatus,
|
|
15
17
|
withSpan
|
|
16
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-J7APPQIJ.js";
|
|
17
19
|
|
|
18
20
|
// src/chat/sandbox/runtime-dependencies.ts
|
|
19
21
|
var GLOBAL_RUNTIME_DEPENDENCIES = [
|
|
@@ -105,37 +107,303 @@ function getVercelSandboxCredentials() {
|
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
// src/chat/sandbox/workspace.ts
|
|
108
|
-
|
|
110
|
+
import {
|
|
111
|
+
FileSystem
|
|
112
|
+
} from "@vercel/sandbox";
|
|
113
|
+
|
|
114
|
+
// src/chat/sandbox/http-error-details.ts
|
|
115
|
+
var DEFAULT_PREVIEW_LIMIT = 512;
|
|
116
|
+
function toTrimmedString(value, maxChars) {
|
|
117
|
+
if (typeof value !== "string") {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
const normalized = value.trim();
|
|
121
|
+
if (!normalized) {
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
return normalized.length > maxChars ? `${normalized.slice(0, maxChars)}\u2026` : normalized;
|
|
125
|
+
}
|
|
126
|
+
function extractHttpErrorDetails(error, options = {}) {
|
|
127
|
+
const prefix = options.attributePrefix ?? "app.http_error";
|
|
128
|
+
const previewLimit = options.previewLimit ?? DEFAULT_PREVIEW_LIMIT;
|
|
129
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
130
|
+
const err = error ?? {};
|
|
131
|
+
const attributes = {
|
|
132
|
+
"error.type": normalizedError.name || "Error",
|
|
133
|
+
"exception.message": toTrimmedString(normalizedError.message, previewLimit) ?? "HTTP error"
|
|
134
|
+
};
|
|
135
|
+
const response = err.response;
|
|
136
|
+
const statusCode = typeof response?.status === "number" ? response.status : void 0;
|
|
137
|
+
const statusText = toTrimmedString(response?.statusText, previewLimit);
|
|
138
|
+
const responseUrl = toTrimmedString(response?.url, previewLimit);
|
|
139
|
+
const responseText = toTrimmedString(err.text, previewLimit);
|
|
140
|
+
const responseJson = toTrimmedString(
|
|
141
|
+
err.json && typeof err.json === "object" ? JSON.stringify(err.json) : void 0,
|
|
142
|
+
previewLimit
|
|
143
|
+
);
|
|
144
|
+
const contentType = toTrimmedString(
|
|
145
|
+
response?.headers?.get?.("content-type"),
|
|
146
|
+
previewLimit
|
|
147
|
+
);
|
|
148
|
+
const requestIdHeader = toTrimmedString(
|
|
149
|
+
response?.headers?.get?.("x-request-id"),
|
|
150
|
+
previewLimit
|
|
151
|
+
);
|
|
152
|
+
const vercelIdHeader = toTrimmedString(
|
|
153
|
+
response?.headers?.get?.("x-vercel-id"),
|
|
154
|
+
previewLimit
|
|
155
|
+
);
|
|
156
|
+
const requestId = requestIdHeader ?? vercelIdHeader;
|
|
157
|
+
if (statusCode !== void 0) {
|
|
158
|
+
attributes["http.response.status_code"] = statusCode;
|
|
159
|
+
}
|
|
160
|
+
if (statusText) {
|
|
161
|
+
attributes[`${prefix}.status_text`] = statusText;
|
|
162
|
+
}
|
|
163
|
+
if (responseUrl) {
|
|
164
|
+
attributes["url.full"] = responseUrl;
|
|
165
|
+
}
|
|
166
|
+
if (contentType) {
|
|
167
|
+
attributes["http.response.header.content-type"] = [contentType];
|
|
168
|
+
}
|
|
169
|
+
if (requestIdHeader) {
|
|
170
|
+
attributes["http.response.header.x-request-id"] = [requestIdHeader];
|
|
171
|
+
}
|
|
172
|
+
if (vercelIdHeader) {
|
|
173
|
+
attributes["http.response.header.x-vercel-id"] = [vercelIdHeader];
|
|
174
|
+
}
|
|
175
|
+
if (responseText) {
|
|
176
|
+
attributes[`${prefix}.response_text_preview`] = responseText;
|
|
177
|
+
attributes[`${prefix}.response_text_length`] = responseText.length;
|
|
178
|
+
}
|
|
179
|
+
if (responseJson) {
|
|
180
|
+
attributes[`${prefix}.response_json_preview`] = responseJson;
|
|
181
|
+
}
|
|
182
|
+
const summaryParts = [];
|
|
183
|
+
if (statusCode !== void 0) {
|
|
184
|
+
summaryParts.push(`status=${statusCode}`);
|
|
185
|
+
}
|
|
186
|
+
if (statusText) {
|
|
187
|
+
summaryParts.push(`statusText=${statusText}`);
|
|
188
|
+
}
|
|
189
|
+
if (responseUrl) {
|
|
190
|
+
summaryParts.push(`url=${responseUrl}`);
|
|
191
|
+
}
|
|
192
|
+
if (requestId) {
|
|
193
|
+
summaryParts.push(`requestId=${requestId}`);
|
|
194
|
+
}
|
|
195
|
+
for (const field of options.extraFields ?? []) {
|
|
196
|
+
const value = toTrimmedString(err[field.sourceKey], previewLimit);
|
|
197
|
+
if (!value) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
attributes[`${prefix}.${field.attributeKey}`] = value;
|
|
201
|
+
summaryParts.push(`${field.summaryKey ?? field.attributeKey}=${value}`);
|
|
202
|
+
}
|
|
203
|
+
if (responseJson) {
|
|
204
|
+
summaryParts.push(`json=${responseJson}`);
|
|
205
|
+
} else if (responseText) {
|
|
206
|
+
summaryParts.push(`text=${responseText}`);
|
|
207
|
+
}
|
|
208
|
+
const searchableText = `${normalizedError.message} ${responseText ?? ""} ${responseJson ?? ""}`.toLowerCase();
|
|
209
|
+
return {
|
|
210
|
+
attributes,
|
|
211
|
+
summary: summaryParts.join(", "),
|
|
212
|
+
searchableText
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/chat/sandbox/errors.ts
|
|
217
|
+
var SANDBOX_ERROR_FIELDS = [
|
|
218
|
+
{
|
|
219
|
+
sourceKey: "sandboxId",
|
|
220
|
+
attributeKey: "sandbox_id",
|
|
221
|
+
summaryKey: "sandboxId"
|
|
222
|
+
}
|
|
223
|
+
];
|
|
224
|
+
function getSandboxErrorDetails(error) {
|
|
225
|
+
return extractHttpErrorDetails(error, {
|
|
226
|
+
attributePrefix: "app.sandbox.api_error",
|
|
227
|
+
extraFields: [...SANDBOX_ERROR_FIELDS]
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
function findInErrorChain(error, predicate) {
|
|
231
|
+
const seen = /* @__PURE__ */ new Set();
|
|
232
|
+
let current = error;
|
|
233
|
+
while (current && !seen.has(current)) {
|
|
234
|
+
if (predicate(current)) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
seen.add(current);
|
|
238
|
+
current = typeof current === "object" ? current.cause : void 0;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
function isRecord(value) {
|
|
243
|
+
return typeof value === "object" && value !== null;
|
|
244
|
+
}
|
|
245
|
+
function isInvalidSandboxSessionError(error) {
|
|
246
|
+
if (!isRecord(error)) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
if (isRecord(error.json) && error.json.invalidToken === true) {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
const response = error.response;
|
|
253
|
+
return isRecord(response) && response.status === 403 && typeof response.url === "string" && response.url.includes("/sandboxes/sessions");
|
|
254
|
+
}
|
|
255
|
+
function getFirstErrorMessage(error) {
|
|
256
|
+
const seen = /* @__PURE__ */ new Set();
|
|
257
|
+
let current = error;
|
|
258
|
+
while (current && !seen.has(current)) {
|
|
259
|
+
if (current instanceof Error) {
|
|
260
|
+
const message = current.message.trim();
|
|
261
|
+
if (message) {
|
|
262
|
+
return message;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
seen.add(current);
|
|
266
|
+
current = typeof current === "object" ? current.cause : void 0;
|
|
267
|
+
}
|
|
268
|
+
return void 0;
|
|
269
|
+
}
|
|
270
|
+
function isAlreadyExistsError(error) {
|
|
271
|
+
const details = getSandboxErrorDetails(error);
|
|
272
|
+
return details.searchableText.includes("already exists") || details.searchableText.includes("file exists") || details.searchableText.includes("eexist");
|
|
273
|
+
}
|
|
274
|
+
function isSandboxUnavailableError(error) {
|
|
275
|
+
return findInErrorChain(error, (candidate) => {
|
|
276
|
+
if (isInvalidSandboxSessionError(candidate)) {
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
const details = getSandboxErrorDetails(candidate);
|
|
280
|
+
const searchable = `${details.searchableText} ${details.summary}`.toLowerCase();
|
|
281
|
+
return searchable.includes("sandbox_stopped") || searchable.includes("status=410") || searchable.includes("status code 410") || searchable.includes("no longer available") || searchable.includes("stream was closed and is not accepting commands");
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function isSandboxMissingError(error) {
|
|
285
|
+
return findInErrorChain(error, (candidate) => {
|
|
286
|
+
const details = getSandboxErrorDetails(candidate);
|
|
287
|
+
const searchable = `${details.searchableText} ${details.summary}`.toLowerCase();
|
|
288
|
+
return searchable.includes("status=404") || searchable.includes("status code 404") || searchable.includes("snapshot_not_found");
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
function isSnapshottingError(error) {
|
|
292
|
+
return findInErrorChain(error, (candidate) => {
|
|
293
|
+
const details = getSandboxErrorDetails(candidate);
|
|
294
|
+
const searchable = `${details.searchableText} ${details.summary}`.toLowerCase();
|
|
295
|
+
return searchable.includes("sandbox_snapshotting") || searchable.includes("creating a snapshot") || searchable.includes("stopped shortly");
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
function isSandboxCommandStreamInterruptedError(error) {
|
|
299
|
+
return findInErrorChain(error, (candidate) => {
|
|
300
|
+
if (!(candidate instanceof Error)) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
return candidate.name === "StreamError" && candidate.message.toLowerCase().includes("stream ended before command finished");
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
function wrapSandboxSetupError(error) {
|
|
307
|
+
try {
|
|
308
|
+
const details = getSandboxErrorDetails(error);
|
|
309
|
+
if (details.summary) {
|
|
310
|
+
return new Error(`sandbox setup failed (${details.summary})`, {
|
|
311
|
+
cause: error
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
} catch {
|
|
315
|
+
}
|
|
316
|
+
let causeMessage;
|
|
317
|
+
try {
|
|
318
|
+
causeMessage = getFirstErrorMessage(error);
|
|
319
|
+
} catch (cause) {
|
|
320
|
+
causeMessage = cause instanceof Error ? cause.message : void 0;
|
|
321
|
+
}
|
|
322
|
+
if (causeMessage && causeMessage.trim() && causeMessage !== "sandbox setup failed") {
|
|
323
|
+
const oneLine = causeMessage.replace(/\s+/g, " ").trim();
|
|
324
|
+
return new Error(`sandbox setup failed (${oneLine})`, { cause: error });
|
|
325
|
+
}
|
|
326
|
+
return new Error("sandbox setup failed", { cause: error });
|
|
327
|
+
}
|
|
328
|
+
function throwSandboxOperationError(action, error, includeMissingPath = false) {
|
|
329
|
+
const details = getSandboxErrorDetails(error);
|
|
330
|
+
setSpanAttributes({
|
|
331
|
+
...details.attributes,
|
|
332
|
+
...includeMissingPath ? {
|
|
333
|
+
"app.sandbox.api_error.missing_path": details.searchableText.includes("no such file") || details.searchableText.includes("enoent")
|
|
334
|
+
} : {},
|
|
335
|
+
"app.sandbox.success": false
|
|
336
|
+
});
|
|
337
|
+
setSpanStatus("error");
|
|
338
|
+
throw new Error(
|
|
339
|
+
details.summary ? `${action} failed (${details.summary})` : `${action} failed`,
|
|
340
|
+
{
|
|
341
|
+
cause: error
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// src/chat/sandbox/workspace.ts
|
|
347
|
+
function createSandboxSession(sandbox, options) {
|
|
348
|
+
const session = sandbox.currentSession();
|
|
349
|
+
const fileSystem = new FileSystem(session);
|
|
350
|
+
const run = async (operation) => {
|
|
351
|
+
try {
|
|
352
|
+
return await operation();
|
|
353
|
+
} catch (error) {
|
|
354
|
+
if (isSandboxUnavailableError(error)) {
|
|
355
|
+
options?.onUnavailable?.(session.sessionId);
|
|
356
|
+
}
|
|
357
|
+
throw error;
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
const fs = {
|
|
361
|
+
readFile: async (filePath, readOptions) => await run(async () => await fileSystem.readFile(filePath, readOptions)),
|
|
362
|
+
writeFile: async (filePath, content, writeOptions) => await run(
|
|
363
|
+
async () => await fileSystem.writeFile(filePath, content, writeOptions)
|
|
364
|
+
),
|
|
365
|
+
readdir: async (filePath) => await run(async () => await fileSystem.readdir(filePath)),
|
|
366
|
+
stat: async (filePath) => await run(async () => await fileSystem.stat(filePath))
|
|
367
|
+
};
|
|
109
368
|
return {
|
|
110
369
|
sandboxId: sandbox.name,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
fs: sandbox.fs,
|
|
370
|
+
sessionId: session.sessionId,
|
|
371
|
+
fs,
|
|
115
372
|
extendTimeout(duration) {
|
|
116
|
-
return
|
|
373
|
+
return run(async () => await session.extendTimeout(duration));
|
|
117
374
|
},
|
|
118
375
|
mkDir(path) {
|
|
119
|
-
return
|
|
376
|
+
return run(async () => await session.mkDir(path));
|
|
120
377
|
},
|
|
121
378
|
readFileToBuffer(input) {
|
|
122
|
-
return
|
|
379
|
+
return run(async () => await session.readFileToBuffer(input));
|
|
123
380
|
},
|
|
124
|
-
runCommand(input) {
|
|
125
|
-
|
|
381
|
+
async runCommand(input) {
|
|
382
|
+
const result = await run(async () => await session.runCommand(input));
|
|
383
|
+
const [stdout, stderr] = await Promise.all([
|
|
384
|
+
run(async () => await result.stdout()),
|
|
385
|
+
run(async () => await result.stderr())
|
|
386
|
+
]);
|
|
387
|
+
return {
|
|
388
|
+
exitCode: result.exitCode,
|
|
389
|
+
stdout,
|
|
390
|
+
stderr
|
|
391
|
+
};
|
|
126
392
|
},
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
393
|
+
snapshot() {
|
|
394
|
+
return run(async () => {
|
|
395
|
+
const snapshot = await session.snapshot();
|
|
396
|
+
return { snapshotId: snapshot.snapshotId };
|
|
397
|
+
});
|
|
130
398
|
},
|
|
131
399
|
stop() {
|
|
132
|
-
return
|
|
400
|
+
return run(async () => await session.stop());
|
|
133
401
|
},
|
|
134
402
|
update(params) {
|
|
135
|
-
return
|
|
403
|
+
return run(async () => await session.update(params));
|
|
136
404
|
},
|
|
137
405
|
writeFiles(files) {
|
|
138
|
-
return
|
|
406
|
+
return run(async () => await session.writeFiles(files));
|
|
139
407
|
}
|
|
140
408
|
};
|
|
141
409
|
}
|
|
@@ -258,8 +526,8 @@ async function runOrThrow(sandbox, params, label) {
|
|
|
258
526
|
if (result.exitCode === 0) {
|
|
259
527
|
return;
|
|
260
528
|
}
|
|
261
|
-
const stderr =
|
|
262
|
-
const stdout =
|
|
529
|
+
const stderr = result.stderr.trim();
|
|
530
|
+
const stdout = result.stdout.trim();
|
|
263
531
|
const detail = stderr || stdout || "command failed";
|
|
264
532
|
throw new Error(`${label} failed: ${detail}`);
|
|
265
533
|
}
|
|
@@ -268,8 +536,8 @@ async function tryRun(sandbox, params) {
|
|
|
268
536
|
if (result.exitCode === 0) {
|
|
269
537
|
return { ok: true };
|
|
270
538
|
}
|
|
271
|
-
const stderr =
|
|
272
|
-
const stdout =
|
|
539
|
+
const stderr = result.stderr.trim();
|
|
540
|
+
const stdout = result.stdout.trim();
|
|
273
541
|
return { ok: false, detail: stderr || stdout || "command failed" };
|
|
274
542
|
}
|
|
275
543
|
async function installGhCliViaDnf(sandbox) {
|
|
@@ -368,8 +636,8 @@ async function installRuntimeDependencies(sandbox, deps) {
|
|
|
368
636
|
cmd: "sha256sum",
|
|
369
637
|
args: [rpmPath]
|
|
370
638
|
});
|
|
371
|
-
const checksumStdout =
|
|
372
|
-
const checksumStderr =
|
|
639
|
+
const checksumStdout = checksumResult.stdout.trim();
|
|
640
|
+
const checksumStderr = checksumResult.stderr.trim();
|
|
373
641
|
if (checksumResult.exitCode !== 0) {
|
|
374
642
|
throw new Error(
|
|
375
643
|
`sha256sum failed: ${checksumStderr || checksumStdout || "command failed"}`
|
|
@@ -460,8 +728,8 @@ async function runRuntimePostinstall(sandbox, commands) {
|
|
|
460
728
|
if (result.exitCode === 0) {
|
|
461
729
|
continue;
|
|
462
730
|
}
|
|
463
|
-
const stderr =
|
|
464
|
-
const stdout =
|
|
731
|
+
const stderr = result.stderr.trim();
|
|
732
|
+
const stdout = result.stdout.trim();
|
|
465
733
|
const detail = stderr || stdout || "command failed";
|
|
466
734
|
throw new Error(`runtime-postinstall ${command.cmd} failed: ${detail}`);
|
|
467
735
|
}
|
|
@@ -479,7 +747,7 @@ async function createDependencySnapshot(profile, runtime, timeoutMs) {
|
|
|
479
747
|
async () => {
|
|
480
748
|
const sandboxCredentials = getVercelSandboxCredentials();
|
|
481
749
|
const resources = getSandboxResources();
|
|
482
|
-
const sandbox =
|
|
750
|
+
const sandbox = createSandboxSession(
|
|
483
751
|
await Sandbox.create({
|
|
484
752
|
timeout: timeoutMs,
|
|
485
753
|
runtime,
|
|
@@ -697,12 +965,19 @@ function isSnapshotMissingError(error) {
|
|
|
697
965
|
}
|
|
698
966
|
|
|
699
967
|
export {
|
|
968
|
+
isAlreadyExistsError,
|
|
969
|
+
isSandboxUnavailableError,
|
|
970
|
+
isSandboxMissingError,
|
|
971
|
+
isSnapshottingError,
|
|
972
|
+
isSandboxCommandStreamInterruptedError,
|
|
973
|
+
wrapSandboxSetupError,
|
|
974
|
+
throwSandboxOperationError,
|
|
975
|
+
getVercelSandboxCredentials,
|
|
700
976
|
buildNonInteractiveShellScript,
|
|
701
977
|
runNonInteractiveCommand,
|
|
702
|
-
getVercelSandboxCredentials,
|
|
703
978
|
getSandboxResources,
|
|
704
979
|
GLOBAL_RUNTIME_DEPENDENCIES,
|
|
705
|
-
|
|
980
|
+
createSandboxSession,
|
|
706
981
|
getRuntimeDependencyProfileHash,
|
|
707
982
|
resolveRuntimeDependencySnapshot,
|
|
708
983
|
isSnapshotMissingError
|