@sentry/junior 0.264.0 → 0.266.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/README.md +1 -1
- package/dist/{adapter-BIbMSKlG.js → adapter-eRFA_naf.js} +1 -1
- package/dist/{admin-D4d0HXax.js → admin-tILpP51p.js} +1 -1
- package/dist/{agent-runner-CvRxb09K.js → agent-runner-BtYK7bht.js} +263 -198
- package/dist/api/schema.d.ts +216 -15
- package/dist/api/schema.js +5 -5
- package/dist/api.js +109 -42
- package/dist/{app-Buc5gIWz.d.ts → app-Csbi9dW7.d.ts} +0 -4
- package/dist/app.d.ts +1 -1
- package/dist/app.js +79 -390
- package/dist/{assistant-reply-BcJj_ORj.js → assistant-reply-UyzAfZQo.js} +1 -1
- package/dist/{automation-CWX0qL8U.js → automation-BKpY9LPa.js} +31 -10
- package/dist/{briefs-BFfIE5N6.js → briefs-DgfWMU7e.js} +5 -5
- package/dist/{catalog-runtime-R53MWcMi.js → catalog-runtime-DAJjAbSx.js} +1 -1
- package/dist/cli/chat.js +15 -15
- package/dist/cli/check.js +3 -3
- package/dist/cli/init.js +4 -18
- package/dist/cli/main.js +4 -4
- package/dist/cli/plugins.js +4 -4
- package/dist/cli/snapshot-create.js +4 -4
- package/dist/cli/upgrade.js +3 -3
- package/dist/{client-DpOwh_zX.js → client-B0YZfxNy.js} +3 -8
- package/dist/{config-BxPrFVJP.js → config-C0UwYqDK.js} +100 -3
- package/dist/{connections-BnTM1nRf.js → connections-Bwu3VORi.js} +11 -10
- package/dist/{conversation-B0baEwoA.js → conversation-DF4rUcjb.js} +6 -2
- package/dist/{conversation-privacy-ueJ6i-t9.js → conversation-privacy-CY7JVjxn.js} +1 -1
- package/dist/{credential-sync-DeDkof_D.js → credential-sync-VGAMUTGp.js} +20 -20
- package/dist/{agent-hooks-D_PbluRX.js → credentialed-enF5Bf3y.js} +3316 -179
- package/dist/{executor-D3WIS4vl.js → executor-TnWbvL09.js} +10 -300
- package/dist/{history-AY8rs-FR.js → history-C84mlAwO.js} +2 -1
- package/dist/{images-5VNK_yYC.js → images-BKQqSi5W.js} +3 -3
- package/dist/instrumentation.js +41 -25
- package/dist/{job-queue-BYHonCAH.js → job-queue-DBpHmKnd.js} +53 -14
- package/dist/{logging-DNQqsQ57.js → logging-Ce0mXZ8J.js} +19 -32
- package/dist/{message-CDTJISxL.js → message-VZ3DFpGb.js} +4 -4
- package/dist/nitro.d.ts +17 -2
- package/dist/nitro.js +26 -27
- package/dist/{oauth-callback-server-Bk4rbLOs.js → oauth-callback-server-CpqWLjVY.js} +2 -2
- package/dist/{prompt-CxatQVaj.js → prompt-BcCGlmg2.js} +2 -2
- package/dist/{registry-CfdUEk4N.js → registry-1BEIPdbT.js} +1 -1
- package/dist/{resolve-BXShI336.js → resolve-BSHHkEGE.js} +7 -106
- package/dist/{result-R35jcahx.js → result-CwOpzqdh.js} +8 -8
- package/dist/{runner-IC4Drh3Y.js → runner-CEaX04kz.js} +11 -11
- package/dist/{sandbox-egress-signals-C4RIfjb8.js → sandbox-egress-signals-BwtGHwqa.js} +1 -1
- package/dist/{schema-QidbykYl.js → schema-RsaBHxRH.js} +45 -4
- package/dist/{sentry-BBUlHih9.js → sentry-MDkYAVPV.js} +3 -6
- package/dist/{service-account-DJSRo2cL.js → service-account-6wC76eBZ.js} +5 -5
- package/dist/{service-account-DifohWyX.js → service-account-Dg4lIbHm.js} +3 -3
- package/dist/{session-stop-B9RRGC-P.js → session-stop-tZOw9AJD.js} +120 -80
- package/dist/{skills-DVJmS_ZP.js → skills-DzyGN7wd.js} +2 -2
- package/dist/{spawn-DkVYGfSY.js → spawn-6rokq7l_.js} +2 -2
- package/dist/{store-BvolNnx4.js → store-DcKkzrdt.js} +3 -3
- package/dist/{store-C_mHwAnR.js → store-FALy-JQb.js} +6 -6
- package/dist/{task-queue-BcEyPhtX.js → task-queue-Bg4RS2Gy.js} +14 -19
- package/dist/{task-runner-CiQj5M_9.js → task-runner-8N5LIkSg.js} +47 -29
- package/dist/{tasks-OgXmReUv.js → tasks-DDT-J3Rf.js} +17 -2078
- package/dist/{thread-state-XFvpWXE9.js → thread-state-cprEaxgl.js} +5 -5
- package/dist/{turn-failure-response-BjBAtnVt.js → turn-failure-response-C8sMdsdX.js} +8 -8
- package/dist/{turn-lifecycle-nvKL2rul.js → turn-lifecycle-DaBVoz7h.js} +2 -2
- package/dist/{turn-session-routing-DEMxHySb.js → turn-session-routing-a9CHX-w6.js} +1 -1
- package/dist/{validation-XOFldwvE.js → validation-C2lllinq.js} +1 -1
- package/dist/{version-C9f5hdHD.js → version-oaLfxxnf.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/{viewer-BuPwzOC9.js → viewer-BpE6Z3qf.js} +22 -6
- package/dist/{web-input-4t7TYLsY.js → web-input-B-bMjD1V.js} +147 -48
- package/dist/{work-C_aF6JN5.js → work-VX1SHWha.js} +52 -51
- package/dist/{worker-DR633sA-.js → worker-hook-y_Y.js} +5 -5
- package/package.json +10 -9
- package/dist/profile-ieODOp4u.js +0 -582
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
import { $t as isToolResultMessage,
|
|
2
|
-
import { S as resolveGatewayCredential, _ as getProviderErrorAttributes, a as completeText, b as MISSING_GATEWAY_CREDENTIALS_ERROR, c as COMPACTION_SUMMARY_PREFIX, d as renderCurrentInstruction, f as unwrapCurrentInstruction, g as findProviderError, h as createProviderError, i as completeObject, l as hasCompactedConversationContext, m as ProviderError, n as GEN_AI_SERVER_ADDRESS, p as escapeXml, s as resolveGatewayModel, t as GEN_AI_PROVIDER_NAME, u as isCompactionSummaryText, x as getGatewayApiKey, y as isProviderRetryError } from "./client-
|
|
3
|
-
import {
|
|
4
|
-
import { m as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { $t as isToolResultMessage, B as recordAttachmentsDelivered, Cn as getConfigDefaults, Ct as canReusePendingAuthLink, Dt as continuableMessages, G as recordMcpProviderConnected, Gt as getPiMessageRole, Ht as isTurnExecutionLimitExceededError, It as TURN_LIMIT_DISABLED_REASON, J as recordTurnRoute, Jt as hasRuntimeTurnContext, Kt as getTerminalAssistantMessages, L as loadTurnRoute, Lt as TurnBudgetExceededError, M as loadConnectedMcpProviders, N as loadConversationProjection, O as automationRevision, Ot as loadTurnCheckpoint, P as loadLastModelProfile, Qt as isToolResultError, R as openConversationProjection, Rt as TurnSliceLimitExceededError, Sn as piMessageFromHistoryItem, St as abandonReplacedPendingAuth, U as recordAuthorizationRequested, Vt as createTurnLimitGate, W as recordGuardianActionReviewed, Wt as extractAssistantText, Xt as isAssistantMessage, Zt as isContinuablePiBoundary, _n as isExperimentalFeatureEnabled, _t as createPluginAuthOrchestration, a as saveScheduledAutomation, an as SESSION_CONTEXT_SECTION_TAG, bt as AuthorizationFlowDisabledError, d as createEventAutomation, en as normalizeToolNameFromResult, f as deleteEventAutomation, g as listEventAutomationsForTeam, gt as PluginCredentialFailureError, hn as getAgentContextInputLimitTokens, ht as createPluginEgress, i as readScheduledAutomation, in as REQUEST_CONTEXT_SECTION_TAG, kt as saveTurnCheckpoint, m as getEventAutomation, mn as getAgentContextCompactionTriggerTokens, n as listScheduledAutomationsForTeam, nn as stripRuntimeTurnContext, nt as fallbackShortTitle, on as TURN_CONTEXT_TAG, pn as estimateTextTokens, q as recordToolExecutionStarted, qt as getUserMessageInstructionText, rn as trimTrailingAssistantMessages, rt as resolveTaskTitle, t as createScheduledAutomation, tn as retainRuntimeTurnContext, v as saveEventAutomation, vt as authorizationId, xn as historyItemFromPiMessage, xt as AuthorizationPauseError, y as setEventAutomationStatus, yt as AuthPausePersistenceError, z as recordAgentsInstructionsUpdated, zt as TurnToolCallLimitExceededError } from "./tasks-DDT-J3Rf.js";
|
|
2
|
+
import { S as resolveGatewayCredential, _ as getProviderErrorAttributes, a as completeText, b as MISSING_GATEWAY_CREDENTIALS_ERROR, c as COMPACTION_SUMMARY_PREFIX, d as renderCurrentInstruction, f as unwrapCurrentInstruction, g as findProviderError, h as createProviderError, i as completeObject, l as hasCompactedConversationContext, m as ProviderError, n as GEN_AI_SERVER_ADDRESS, p as escapeXml, s as resolveGatewayModel, t as GEN_AI_PROVIDER_NAME, u as isCompactionSummaryText, x as getGatewayApiKey, y as isProviderRetryError } from "./client-B0YZfxNy.js";
|
|
3
|
+
import { n as botConfig, v as normalizeSlackEmojiName } from "./config-C0UwYqDK.js";
|
|
4
|
+
import { R as normalizeIdentityEmail, S as summarizeMessageText, T as withSpan, V as toOptionalString, _ as serializeGenAiAttribute, a as extractGenAiUsageSummary, b as setSpanStatus, c as getLogContextAttributesForSpan, d as logError, f as logException, h as normalizeGenAiFinishReason, i as extractGenAiUsageAttributes, l as getTracePropagationHeaders, m as logWarn, p as logInfo, w as withLogContext, x as setTags, y as setSpanAttributes, z as isRecord$4 } from "./logging-Ce0mXZ8J.js";
|
|
5
|
+
import { g as withActiveSpan, m as startInactiveSpan } from "./sentry-MDkYAVPV.js";
|
|
6
|
+
import { a as toCanonicalInputMessage, c as toGenAiPayloadMetadata, i as runWithConversationPrivacy, l as toGenAiPayloadTraceAttributes, o as toCanonicalOutputMessage, r as resolveConversationPrivacy, s as toGenAiMessagesTraceAttributes, t as canExposeConversationPayload } from "./conversation-privacy-CY7JVjxn.js";
|
|
7
7
|
import { a as formatModelProfiles, c as profileConfig, i as formatModelProfile, l as TURN_REASONING_LEVELS, n as ModelProfileNotConfiguredError, o as modelIdForProfile, s as modelProfileSchema } from "./model-profile-Bg8EoCKD.js";
|
|
8
8
|
import { a as isUserActor, d as parseSlackTeamId, f as parseSlackUserId, g as parseSlackMessageTs, l as parseSlackChannelId, u as parseSlackChannelReferenceId } from "./actor-tlxzqaRe.js";
|
|
9
|
-
import {
|
|
9
|
+
import { O as hasAgentTurnUsage, T as agentTurnCostUsd, d as getConversationStore, f as getDb, l as getConversationEventStore, p as getSqlExecutor, r as readActorIdentity, u as getConversationMessageSearchStore, w as addAgentTurnUsage, z as parseDestination } from "./viewer-BpE6Z3qf.js";
|
|
10
10
|
import { a as juniorAgentInvocations, c as juniorIdentities, d as juniorDestinations, i as juniorAgentBindings, s as juniorConversations } from "./agent-invocations-CxKldAeB.js";
|
|
11
|
-
import { _ as juniorConversationAnnotations, a as juniorAutomationRuns, b as juniorAttachments, c as juniorStats, f as juniorConversationBriefs, x as juniorArtifacts } from "./executor-
|
|
12
|
-
import { d as contextProvenance, f as instructionActors, m as sameActorIdentity, p as instructionProvenanceFor, t as KNOWN_CONVERSATION_EVENT_TYPES, u as agentInstructionProvenance } from "./history-
|
|
11
|
+
import { _ as juniorConversationAnnotations, a as juniorAutomationRuns, b as juniorAttachments, c as juniorStats, f as juniorConversationBriefs, x as juniorArtifacts } from "./executor-TnWbvL09.js";
|
|
12
|
+
import { d as contextProvenance, f as instructionActors, m as sameActorIdentity, p as instructionProvenanceFor, t as KNOWN_CONVERSATION_EVENT_TYPES, u as agentInstructionProvenance } from "./history-C84mlAwO.js";
|
|
13
13
|
import { a as listReferenceFiles, c as soulPathCandidates, l as worldPathCandidates } from "./package-discovery-DJBompdd.js";
|
|
14
|
-
import { c as fetchWithBoundedOAuthErrorBodies, d as actorLogContext, f as credentialContextForActor, g as credentialUserSubjectId, i as resolvePluginHeaderEnvRefs, l as getOAuthProviderErrorAttributes, s as OAuthProviderError } from "./registry-
|
|
15
|
-
import { n as pluginCatalogRuntime } from "./catalog-runtime-
|
|
16
|
-
import { a as parseSkillInvocation, i as parseSkillFile, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-
|
|
17
|
-
import { A as
|
|
18
|
-
import { o as fenceLock, r as getStateAdapter, s as withLock } from "./adapter-
|
|
14
|
+
import { c as fetchWithBoundedOAuthErrorBodies, d as actorLogContext, f as credentialContextForActor, g as credentialUserSubjectId, i as resolvePluginHeaderEnvRefs, l as getOAuthProviderErrorAttributes, s as OAuthProviderError } from "./registry-1BEIPdbT.js";
|
|
15
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-DAJjAbSx.js";
|
|
16
|
+
import { a as parseSkillInvocation, i as parseSkillFile, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-DzyGN7wd.js";
|
|
17
|
+
import { $n as defaultTimezone, A as setWorkspaceSnapshotBuild, At as RESOURCE_SUBSCRIPTION_MAX_TTL_MS, B as wrapSandboxSetupError, Bt as getWatch, C as listWorkspaces, Cn as SANDBOX_WORKSPACE_ROOT, Ct as tryWorkspaceRepoCheckoutPath, D as invalidateReadySnapshot, Dt as isSlackMessageTurn, E as WorkspaceValidationError, En as sandboxSkillPathResolution, Et as getSlackToolContext, F as ensureDockerDaemon, Gn as matchSlackAttachments, H as getWorkspaceSnapshotNotReadyError, I as getSandboxProvider, It as createTimerWatch, J as consumeSandboxEgressAuthRequiredSignal, L as isAbortError, Lt as createWatch, M as create, Mt as STOP_WATCHING_TOOL_NAME, N as hash, Nt as cancelSubscriptions, O as loadSnapshotsForProfile, Ot as slackMessageTurnDisabledReason, P as isStale, Pt as cancelWatch, Qt as getFilePermalink, R as isAlreadyExistsError, Rt as deliverWatch, S as getWorkspaceByName, Sn as SANDBOX_SKILLS_ROOT, T as updateWorkspace, Tn as sandboxSkillFile, Tt as resolveChannelCapabilities, U as isWorkspaceSnapshotNotReadyError, V as WorkspaceSnapshotNotReadyError, Vt as listWatches, W as workspaceSnapshotNotReadyUserMessage, X as createSandboxEgressCredentialToken, Xn as createPluginAnnotations, Xt as SlackActionError, Y as consumeSandboxEgressPermissionDeniedSignal, Yn as saveObjectAnnotations, Zt as downloadPrivateSlackFile, _n as buildNonInteractiveShellScript, _t as openSlackDirectMessage, an as withSlackRetries, at as formatProviderLabel, b as deleteWorkspace, bn as SANDBOX_DATA_ROOT, bt as uploadFilesToConversation, cr as conversationNoteEvent, d as getPluginTools, en as getSlackClient, er as resolveUserTimezone, et as buildSandboxEgressNetworkPolicy, f as getPluginUserPromptContributions, fn as getDashboardTaskLink, gn as buildCommandScript, gt as getSlackMessagePermalink, hn as PluginToolDeniedError, ht as addReactionToMessage, ir as JUNIOR_NATIVE_EVENT_NAMESPACE, it as deliverOAuthAuthorization, j as SANDBOX_RUNTIME, jt as RESOURCE_WATCH_TOOL_SOURCE, k as setWorkspaceSnapshot, kt as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, mn as ToolInputError, n as createUserTokenStore, o as createPluginHookRunner, on as sleep, p as getPlugins, pt as slackMention, q as clearSandboxEgressSignals, r as getOAuthAccountProviders, rn as normalizeSlackConversationId, st as resolveBaseUrl, tn as isConversationScopedChannel, tt as resolveSandboxCommandEnvironment, u as getPluginSystemPromptContributions, un as getDashboardConversationLink, vn as runNonInteractiveCommand, wn as sandboxSkillDir, wt as workspaceRepoCheckoutPath, x as getWorkspace, xn as SANDBOX_REPOS_ROOT, y as createWorkspace, yn as SANDBOX_COMMAND_PATH, z as throwSandboxOperationError, zt as findMatchingWatches } from "./credentialed-enF5Bf3y.js";
|
|
18
|
+
import { o as fenceLock, r as getStateAdapter, s as withLock } from "./adapter-eRFA_naf.js";
|
|
19
19
|
import { i as isValidTimeZone, r as getZonedDateTimeParts } from "./cadence-R7Em4RjE.js";
|
|
20
|
-
import { G as briefLinkSchema, H as detectImageMediaType, I as removedCardSchema, K as briefOutcomeStatusSchema, U as isVisionImageMediaType, q as conversationBriefSchema } from "./conversation-
|
|
21
|
-
import { A as
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { a as
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { F as taskOutcomeInputSchema, M as compileScheduleIntent, N as scheduleIntentSchema, O as automationInstructionToolSchema, T as SCHEDULED_AUTOMATION_SYSTEM_ACTOR, j as ScheduleIntentError, k as automationTitleSchema } from "./automation-CWX0qL8U.js";
|
|
20
|
+
import { G as briefLinkSchema, H as detectImageMediaType, I as removedCardSchema, K as briefOutcomeStatusSchema, U as isVisionImageMediaType, q as conversationBriefSchema } from "./conversation-DF4rUcjb.js";
|
|
21
|
+
import { A as AgentMessageQueueFullError, F as agentNameSchema, H as TurnInputCommitLostError, I as AGENT_TYPES, K as isTurnInputCommitLostError, M as AgentNameInUseError, N as CHILD_AGENT_RESULTS, P as PARENT_AGENT_TARGET, V as CooperativeTurnYieldError, _ as getLatestAgentInvocationForConversation, d as getAgentInvocationIdForResult, f as getAgentInvocationMessageId, g as getChildAgentLockName, j as AgentMessageTargetError, k as AgentInvocationLimitError, t as NON_TERMINAL_AGENT_INVOCATION_STATUSES, v as invocationFromRow, y as isTerminalAgentInvocation, z as formatAgentTypes } from "./store-DcKkzrdt.js";
|
|
22
|
+
import { a as isNoReplyMarker, i as NO_REPLY_MARKER, n as getAssistantReplyText, r as sanitizeAssistantText, t as decideReply } from "./assistant-reply-UyzAfZQo.js";
|
|
23
|
+
import { A as requireEventIdentifier, D as registeredEventMatchSchema, E as hasEventCatalogEntries, H as remindMissingAutomationResult, L as FINISH_AUTOMATION_RUN_TOOL_NAME, O as registeredEventTypeSchema, R as automationResultSchema, S as describeRegisteredEventTrigger, T as eventWatchUnavailable, V as readAutomationResult, _ as WORKSPACE_SNAPSHOT_FAILED_EVENT, b as workspaceSnapshotWatch, d as getEventCatalog, j as requireValidEventTrigger, k as registeredResourceTypeSchema, n as markConversationsStopped, o as enqueueEventNotification, p as requireSlackChannelMessageScope, t as getConversationStoppedAtMs, v as WORKSPACE_SNAPSHOT_READY_EVENT, w as eventNamespaceSchema, x as automationEventCatalog, y as workspaceSnapshotFinishedEvent } from "./session-stop-tZOw9AJD.js";
|
|
24
|
+
import { a as setSnapshotSpanAttributes, i as postinstall, n as resolve$1, r as dependencies, s as getSandboxResources } from "./resolve-BSHHkEGE.js";
|
|
25
|
+
import { a as getVercelConversationWorkQueue, f as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-DBpHmKnd.js";
|
|
26
|
+
import { E as stopConversationWork } from "./store-FALy-JQb.js";
|
|
27
|
+
import { _ as getMcpProviderErrorAttributes, a as serviceAccountOnly, c as createMcpServiceAccountClientProvider, d as PluginMcpClient, f as McpProviderError, g as getMcpAwareTelemetryMessage, h as getMcpAwareErrorType, i as serviceAccountAllows, l as getMcpServiceAccountCredentials, m as McpToolError, p as McpServiceAccountRequiredError, u as McpAuthorizationRequiredError, v as toMcpProviderError } from "./service-account-6wC76eBZ.js";
|
|
28
|
+
import { F as taskOutcomeInputSchema, M as compileScheduleIntent, N as scheduleIntentSchema, O as automationInstructionToolSchema, T as SCHEDULED_AUTOMATION_SYSTEM_ACTOR, j as ScheduleIntentError, k as automationTitleSchema } from "./automation-BKpY9LPa.js";
|
|
30
29
|
import { n as privateTraceResultAttributes } from "./private-trace-result-CE7_lEdq.js";
|
|
31
30
|
import { streamSimple } from "@earendil-works/pi-ai/compat";
|
|
32
31
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
@@ -36,13 +35,13 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
36
35
|
import { z } from "zod";
|
|
37
36
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
38
37
|
import { and, asc, desc, eq, gt, gte, inArray, isNotNull, isNull, lt, lte, ne, notExists, or, sql } from "drizzle-orm";
|
|
39
|
-
import { PluginToolInputError, eventSchema, missingToolAnnotationKeys, ownedObjectAnnotationSchema, sourceSchema, stableEventMatchKey, watchResultSchema } from "@sentry/junior-plugin-api";
|
|
38
|
+
import { PluginToolInputError, eventMatchFieldSchema, eventSchema, eventTriggerText, missingToolAnnotationKeys, ownedObjectAnnotationSchema, sourceSchema, stableEventMatchKey, watchResultSchema } from "@sentry/junior-plugin-api";
|
|
40
39
|
import { alias } from "drizzle-orm/pg-core";
|
|
41
40
|
import { Agent, estimateContextTokens } from "@earendil-works/pi-agent-core";
|
|
42
41
|
import fs from "node:fs/promises";
|
|
43
42
|
import fs$1 from "node:fs";
|
|
44
|
-
import {
|
|
45
|
-
import { isRetryableAssistantError } from "@earendil-works/pi-ai";
|
|
43
|
+
import { SignJWT, importPKCS8 } from "jose";
|
|
44
|
+
import { createAssistantMessageEventStream, isRetryableAssistantError } from "@earendil-works/pi-ai";
|
|
46
45
|
import { Kind } from "@sinclair/typebox";
|
|
47
46
|
import { Bash, defineCommand } from "just-bash";
|
|
48
47
|
import { structuredPatch } from "diff";
|
|
@@ -53,7 +52,6 @@ import https from "node:https";
|
|
|
53
52
|
import net from "node:net";
|
|
54
53
|
import { NodeHtmlMarkdown } from "node-html-markdown";
|
|
55
54
|
import { Value } from "@sinclair/typebox/value";
|
|
56
|
-
import { SignJWT, importPKCS8 } from "jose";
|
|
57
55
|
// src/chat/sandbox/skill-sandbox.ts
|
|
58
56
|
const MAX_SKILL_FILE_BYTES = 262144;
|
|
59
57
|
const DEFAULT_MAX_SKILL_FILE_CHARS = 2e4;
|
|
@@ -716,6 +714,53 @@ function buildChatEndAttributes(message, mode) {
|
|
|
716
714
|
}
|
|
717
715
|
return attributes;
|
|
718
716
|
}
|
|
717
|
+
const NON_CONTENT_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
718
|
+
"start",
|
|
719
|
+
"done",
|
|
720
|
+
"error"
|
|
721
|
+
]);
|
|
722
|
+
function createResponseTiming(requestStartedAtMs) {
|
|
723
|
+
let firstByteAtMs;
|
|
724
|
+
let firstToken;
|
|
725
|
+
return {
|
|
726
|
+
observe: (event) => {
|
|
727
|
+
if (firstByteAtMs === void 0 && event.type !== "error") firstByteAtMs = Date.now();
|
|
728
|
+
if (!firstToken && !NON_CONTENT_EVENT_TYPES.has(event.type)) firstToken = {
|
|
729
|
+
type: event.type,
|
|
730
|
+
receivedAtMs: Date.now()
|
|
731
|
+
};
|
|
732
|
+
},
|
|
733
|
+
attributes: () => {
|
|
734
|
+
if (firstByteAtMs === void 0) return { "gen_ai.response.streaming": false };
|
|
735
|
+
return {
|
|
736
|
+
"gen_ai.response.streaming": true,
|
|
737
|
+
"app.ai.time_to_first_byte_ms": firstByteAtMs - requestStartedAtMs,
|
|
738
|
+
...firstToken ? {
|
|
739
|
+
"gen_ai.response.time_to_first_chunk": (firstToken.receivedAtMs - requestStartedAtMs) / 1e3,
|
|
740
|
+
"app.ai.first_token_type": firstToken.type
|
|
741
|
+
} : void 0
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function relayStream(source, onEvent) {
|
|
747
|
+
const relayed = createAssistantMessageEventStream();
|
|
748
|
+
const finished = (async () => {
|
|
749
|
+
try {
|
|
750
|
+
for await (const event of source) {
|
|
751
|
+
onEvent(event);
|
|
752
|
+
relayed.push(event);
|
|
753
|
+
}
|
|
754
|
+
} finally {
|
|
755
|
+
relayed.end();
|
|
756
|
+
}
|
|
757
|
+
})();
|
|
758
|
+
finished.then(() => source.result()).then((message) => relayed.end(message), () => {});
|
|
759
|
+
return {
|
|
760
|
+
stream: relayed,
|
|
761
|
+
finished
|
|
762
|
+
};
|
|
763
|
+
}
|
|
719
764
|
/**
|
|
720
765
|
* Wraps pi-ai's `streamSimple` so each LLM call inside a pi-agent-core agent
|
|
721
766
|
* loop produces its own `gen_ai.chat` Sentry span. The returned function is
|
|
@@ -737,10 +782,16 @@ function createTracedStreamFn(baseOrOptions = streamSimple) {
|
|
|
737
782
|
}
|
|
738
783
|
});
|
|
739
784
|
try {
|
|
785
|
+
const requestStartedAtMs = Date.now();
|
|
740
786
|
const stream = await withActiveSpan(span, () => Promise.resolve(base(model, context, options)));
|
|
741
|
-
|
|
787
|
+
const responseTiming = createResponseTiming(requestStartedAtMs);
|
|
788
|
+
const relay = relayStream(stream, responseTiming.observe);
|
|
789
|
+
relay.finished.then(() => stream.result()).then((finalMessage) => {
|
|
742
790
|
try {
|
|
743
|
-
const endAttributes =
|
|
791
|
+
const endAttributes = {
|
|
792
|
+
...buildChatEndAttributes(finalMessage, mode),
|
|
793
|
+
...responseTiming.attributes()
|
|
794
|
+
};
|
|
744
795
|
for (const [key, value] of Object.entries(endAttributes)) span.setAttribute(key, value);
|
|
745
796
|
if (finalMessage.stopReason === "error") {
|
|
746
797
|
const summary = endAttributes["app.ai.provider_error.summary"];
|
|
@@ -753,6 +804,7 @@ function createTracedStreamFn(baseOrOptions = streamSimple) {
|
|
|
753
804
|
span.end();
|
|
754
805
|
}
|
|
755
806
|
}, (error) => {
|
|
807
|
+
span.setAttributes(responseTiming.attributes());
|
|
756
808
|
span.setAttribute("error.type", error instanceof Error ? error.name : typeof error);
|
|
757
809
|
span.setStatus({
|
|
758
810
|
code: 2,
|
|
@@ -760,7 +812,7 @@ function createTracedStreamFn(baseOrOptions = streamSimple) {
|
|
|
760
812
|
});
|
|
761
813
|
span.end();
|
|
762
814
|
}).catch(() => {});
|
|
763
|
-
return stream;
|
|
815
|
+
return relay.stream;
|
|
764
816
|
} catch (error) {
|
|
765
817
|
span.setAttribute("error.type", error instanceof Error ? error.name : typeof error);
|
|
766
818
|
span.setStatus({
|
|
@@ -1743,7 +1795,7 @@ const CONVERSATION_RULES = [
|
|
|
1743
1795
|
"- Runtime owns continuation and authorization notices; on resumed turns, answer with the final requested content only."
|
|
1744
1796
|
];
|
|
1745
1797
|
const SLACK_ACTION_RULES = [
|
|
1746
|
-
"- Assistant text, Slack posts, reactions, new canvases, new lists, and file sends go only to the current conversation or thread.
|
|
1798
|
+
"- Assistant text, Slack posts, reactions, new canvases, new lists, and file sends go only to the current conversation or thread. Your reply is not a channel post, and you cannot create a new top-level channel post. When asked to post to a channel or anywhere else right now, explain that limitation; do not call a Slack send tool, and do not reply with only the requested text or present it as delivered. Scheduled automations can still post to the active channel later. Slack read tools can target other public channels with `channel_id`.",
|
|
1747
1799
|
"- Ambient reaction requests target the current inbound message; do not ask for a message reference.",
|
|
1748
1800
|
`- When no visible thread reply is requested or useful, keep tool-calling messages text-free and make the final message exactly ${NO_REPLY_MARKER}.`
|
|
1749
1801
|
];
|
|
@@ -2953,9 +3005,9 @@ const BUILD_COMMAND_TIMEOUT_ERROR = "Workspace snapshot build phase timed out af
|
|
|
2953
3005
|
const COMMAND_STATUS_POLL_TIMEOUT_MS = 1e3;
|
|
2954
3006
|
/** Leave time to save the build state before this request ends. */
|
|
2955
3007
|
const STOP_BUFFER_MS = 4e4;
|
|
2956
|
-
/** Keep the build open when a request stops or
|
|
3008
|
+
/** Keep the build open when a request stops or the provider has a short failure. */
|
|
2957
3009
|
function isCancelOrTransient(error) {
|
|
2958
|
-
return isAbortError(error) ||
|
|
3010
|
+
return isAbortError(error) || getSandboxProvider().errors.isTransient(error);
|
|
2959
3011
|
}
|
|
2960
3012
|
function buildLockKey(profileHash) {
|
|
2961
3013
|
return `${BUILD_LOCK_PREFIX}:${profileHash}`;
|
|
@@ -2996,7 +3048,7 @@ function activeBuild(build) {
|
|
|
2996
3048
|
}
|
|
2997
3049
|
async function deleteBuilder(sandboxName) {
|
|
2998
3050
|
if (!sandboxName) return;
|
|
2999
|
-
await deleteWorkspaceSnapshotBuilders([sandboxName]);
|
|
3051
|
+
await getSandboxProvider().deleteWorkspaceSnapshotBuilders([sandboxName]);
|
|
3000
3052
|
}
|
|
3001
3053
|
function workspaceDeletedError(workspace) {
|
|
3002
3054
|
return /* @__PURE__ */ new Error(`Workspace ${workspace.name} was deleted while its snapshot was building`);
|
|
@@ -3037,8 +3089,8 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3037
3089
|
if (!build?.commandId || !build.sandboxName) return null;
|
|
3038
3090
|
try {
|
|
3039
3091
|
await requireRemainingBuildTime(workspace, build, beforeWrite);
|
|
3040
|
-
const
|
|
3041
|
-
const command = await
|
|
3092
|
+
const builder = await getSandboxProvider().getWorkspaceSnapshotBuilder(build.sandboxName, signal);
|
|
3093
|
+
const command = await builder.getCommand(build.commandId, { signal });
|
|
3042
3094
|
const pollSignal = AbortSignal.timeout(COMMAND_STATUS_POLL_TIMEOUT_MS);
|
|
3043
3095
|
const waitSignal = signal ? AbortSignal.any([signal, pollSignal]) : pollSignal;
|
|
3044
3096
|
let finished;
|
|
@@ -3058,7 +3110,7 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3058
3110
|
throw new Error(`Workspace ${workspace.name} snapshot setup failed: ${detail}`);
|
|
3059
3111
|
}
|
|
3060
3112
|
await requireRemainingBuildTime(workspace, build, beforeWrite);
|
|
3061
|
-
const snapshot = await
|
|
3113
|
+
const snapshot = await builder.snapshot({ signal });
|
|
3062
3114
|
await requireRemainingBuildTime(workspace, build, beforeWrite);
|
|
3063
3115
|
const createdAtMs = Date.now();
|
|
3064
3116
|
const buildDurationMs = Math.max(0, createdAtMs - build.startedAt.getTime());
|
|
@@ -3073,7 +3125,7 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3073
3125
|
}, { buildId: build.id });
|
|
3074
3126
|
requireBuildWrite(result.written, workspace);
|
|
3075
3127
|
try {
|
|
3076
|
-
await deleteWorkspaceSnapshotBuilders(result.replacedBuilderNames);
|
|
3128
|
+
await getSandboxProvider().deleteWorkspaceSnapshotBuilders(result.replacedBuilderNames);
|
|
3077
3129
|
} catch (error) {
|
|
3078
3130
|
logException(error, "sandbox.workspace_snapshot.builder.delete_failed", {
|
|
3079
3131
|
"app.workspace.id": workspace.id,
|
|
@@ -3100,19 +3152,16 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3100
3152
|
/** Create the Sandbox and save its name. */
|
|
3101
3153
|
async function startBuild(params) {
|
|
3102
3154
|
const { workspace, value, signal } = params;
|
|
3103
|
-
const credentials = getVercelSandboxCredentials();
|
|
3104
3155
|
const resources = getSandboxResources(workspace);
|
|
3105
3156
|
const name = builderName();
|
|
3106
3157
|
const buildId = randomUUID();
|
|
3107
3158
|
const startedAt = /* @__PURE__ */ new Date();
|
|
3108
3159
|
try {
|
|
3109
|
-
await
|
|
3160
|
+
await getSandboxProvider().createWorkspaceSnapshotBuilder({
|
|
3110
3161
|
name,
|
|
3111
|
-
persistent: true,
|
|
3112
|
-
timeout: BUILD_TIMEOUT_MS,
|
|
3113
3162
|
runtime: params.runtime,
|
|
3163
|
+
timeoutMs: BUILD_TIMEOUT_MS,
|
|
3114
3164
|
signal,
|
|
3115
|
-
...credentials ?? {},
|
|
3116
3165
|
...resources ? { resources } : void 0
|
|
3117
3166
|
});
|
|
3118
3167
|
await params.beforeWrite();
|
|
@@ -3174,8 +3223,8 @@ async function continueBuild(params) {
|
|
|
3174
3223
|
const phaseTimeoutSignal = AbortSignal.timeout(commandTimeoutMs);
|
|
3175
3224
|
const phaseSignal = params.signal ? AbortSignal.any([params.signal, phaseTimeoutSignal]) : phaseTimeoutSignal;
|
|
3176
3225
|
try {
|
|
3177
|
-
const
|
|
3178
|
-
const session =
|
|
3226
|
+
const builder = await getSandboxProvider().getWorkspaceSnapshotBuilder(build.sandboxName, phaseSignal);
|
|
3227
|
+
const session = builder.session();
|
|
3179
3228
|
if (build.phase === "created") {
|
|
3180
3229
|
await dependencies(session, params.value.dependencies, phaseSignal, commandTimeoutMs);
|
|
3181
3230
|
await postinstall(session, params.value.postinstall, phaseSignal, commandTimeoutMs);
|
|
@@ -3205,16 +3254,15 @@ async function continueBuild(params) {
|
|
|
3205
3254
|
return;
|
|
3206
3255
|
}
|
|
3207
3256
|
await params.beforeWrite();
|
|
3208
|
-
const
|
|
3257
|
+
const commandId = await builder.startDetachedCommand({
|
|
3209
3258
|
...workspaceSnapshotSetupCommand(params.workspace, build.id),
|
|
3210
|
-
detached: true,
|
|
3211
3259
|
timeoutMs: remainingMs,
|
|
3212
3260
|
signal: phaseSignal
|
|
3213
3261
|
});
|
|
3214
3262
|
await params.beforeWrite();
|
|
3215
3263
|
requireBuildWrite(await setWorkspaceSnapshotBuild(params.workspace.id, {
|
|
3216
3264
|
...build,
|
|
3217
|
-
commandId
|
|
3265
|
+
commandId,
|
|
3218
3266
|
error: null
|
|
3219
3267
|
}), params.workspace);
|
|
3220
3268
|
} catch (error) {
|
|
@@ -3311,7 +3359,7 @@ async function resolveWorkspaceSnapshot(params) {
|
|
|
3311
3359
|
try {
|
|
3312
3360
|
snapshot = await advanceWorkspaceSnapshot(current);
|
|
3313
3361
|
} catch (error) {
|
|
3314
|
-
if (!
|
|
3362
|
+
if (!getSandboxProvider().errors.isTransient(error)) throw error;
|
|
3315
3363
|
advanced = true;
|
|
3316
3364
|
if (shouldStopForTimeLimit(current.shouldStop)) throw new WorkspaceSnapshotNotReadyError(workspace.name);
|
|
3317
3365
|
await sleep(TRANSIENT_API_RETRY_MS, params.signal);
|
|
@@ -3576,6 +3624,42 @@ async function syncSkillsToSandbox(params) {
|
|
|
3576
3624
|
});
|
|
3577
3625
|
});
|
|
3578
3626
|
}
|
|
3627
|
+
// src/chat/sandbox/workspace.ts
|
|
3628
|
+
/** Bind one tool call's cancellation to every sandbox filesystem operation. */
|
|
3629
|
+
function bindSandboxFileSystem(fs, signal) {
|
|
3630
|
+
if (!signal) return fs;
|
|
3631
|
+
return {
|
|
3632
|
+
readFile(filePath, options) {
|
|
3633
|
+
signal.throwIfAborted();
|
|
3634
|
+
return fs.readFile(filePath, {
|
|
3635
|
+
...options,
|
|
3636
|
+
signal
|
|
3637
|
+
});
|
|
3638
|
+
},
|
|
3639
|
+
writeFile(filePath, content, options) {
|
|
3640
|
+
signal.throwIfAborted();
|
|
3641
|
+
return fs.writeFile(filePath, content, {
|
|
3642
|
+
...options,
|
|
3643
|
+
signal
|
|
3644
|
+
});
|
|
3645
|
+
},
|
|
3646
|
+
readdir(filePath) {
|
|
3647
|
+
signal.throwIfAborted();
|
|
3648
|
+
return fs.readdir(filePath, { signal });
|
|
3649
|
+
},
|
|
3650
|
+
stat(filePath) {
|
|
3651
|
+
signal.throwIfAborted();
|
|
3652
|
+
return fs.stat(filePath, { signal });
|
|
3653
|
+
}
|
|
3654
|
+
};
|
|
3655
|
+
}
|
|
3656
|
+
/** Best-effort stop; ignore secondary stop failures during cleanup. */
|
|
3657
|
+
async function stopSession(session) {
|
|
3658
|
+
if (!session) return;
|
|
3659
|
+
try {
|
|
3660
|
+
await session.stop();
|
|
3661
|
+
} catch {}
|
|
3662
|
+
}
|
|
3579
3663
|
// src/chat/sandbox/session.ts
|
|
3580
3664
|
const DEFAULT_MAX_OUTPUT_LENGTH = 3e4;
|
|
3581
3665
|
const DEFAULT_BASH_COMMAND_TIMEOUT_MS = 3e5;
|
|
@@ -3584,16 +3668,6 @@ const SNAPSHOT_BOOT_RETRY_DELAY_MS = 1e3;
|
|
|
3584
3668
|
const SANDBOX_NAME_PREFIX = "junior-";
|
|
3585
3669
|
const MAX_KEEPALIVE_INTERVAL_MS = 3e4;
|
|
3586
3670
|
const MIN_KEEPALIVE_INTERVAL_MS = 1e3;
|
|
3587
|
-
function sandboxFetchOptions(signal) {
|
|
3588
|
-
if (!signal) return {};
|
|
3589
|
-
return { fetch: (input, init) => {
|
|
3590
|
-
const requestSignal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
3591
|
-
return globalThis.fetch(input, {
|
|
3592
|
-
...init,
|
|
3593
|
-
signal: requestSignal ? AbortSignal.any([requestSignal, signal]) : signal
|
|
3594
|
-
});
|
|
3595
|
-
} };
|
|
3596
|
-
}
|
|
3597
3671
|
function truncateOutput(output, maxLength) {
|
|
3598
3672
|
if (output.length <= maxLength) return {
|
|
3599
3673
|
value: output,
|
|
@@ -3643,7 +3717,10 @@ function createSandboxRuntime(options) {
|
|
|
3643
3717
|
keepAliveTimer = void 0;
|
|
3644
3718
|
}
|
|
3645
3719
|
};
|
|
3646
|
-
const
|
|
3720
|
+
const createSession = (input) => getSandboxProvider().createSession({
|
|
3721
|
+
...input,
|
|
3722
|
+
onUnavailable: invalidateSession
|
|
3723
|
+
});
|
|
3647
3724
|
const createSandboxName = () => `${SANDBOX_NAME_PREFIX}${randomUUID()}`;
|
|
3648
3725
|
const preflightNetworkPolicy = (sandboxName) => options.createNetworkPolicy?.(sandboxName);
|
|
3649
3726
|
const persistSandboxRef = async (nextRef) => {
|
|
@@ -3710,30 +3787,26 @@ function createSandboxRuntime(options) {
|
|
|
3710
3787
|
}
|
|
3711
3788
|
});
|
|
3712
3789
|
};
|
|
3713
|
-
const createSandboxFromSnapshot = async (snapshotId,
|
|
3790
|
+
const createSandboxFromSnapshot = async (snapshotId, initialSandboxName, workspace, signal) => {
|
|
3714
3791
|
const resources = getSandboxResources(workspace);
|
|
3715
3792
|
for (let attempt = 0; attempt < SNAPSHOT_BOOT_RETRY_COUNT; attempt += 1) {
|
|
3716
3793
|
signal?.throwIfAborted();
|
|
3717
3794
|
const sandboxName = attempt === 0 ? initialSandboxName : createSandboxName();
|
|
3718
3795
|
const networkPolicy = preflightNetworkPolicy(sandboxName);
|
|
3719
3796
|
try {
|
|
3720
|
-
return
|
|
3721
|
-
|
|
3797
|
+
return await createSession({
|
|
3798
|
+
timeoutMs,
|
|
3722
3799
|
...networkPolicy ? {
|
|
3723
3800
|
name: sandboxName,
|
|
3724
3801
|
persistent: false,
|
|
3725
3802
|
networkPolicy
|
|
3726
3803
|
} : void 0,
|
|
3727
|
-
|
|
3728
|
-
type: "snapshot",
|
|
3729
|
-
snapshotId
|
|
3730
|
-
},
|
|
3804
|
+
snapshotId,
|
|
3731
3805
|
...resources ? { resources } : void 0,
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
}));
|
|
3806
|
+
scopeSignal: signal
|
|
3807
|
+
});
|
|
3735
3808
|
} catch (error) {
|
|
3736
|
-
if (!
|
|
3809
|
+
if (!getSandboxProvider().errors.isSnapshotting(error) || attempt === 2) throw error;
|
|
3737
3810
|
await sleep(SNAPSHOT_BOOT_RETRY_DELAY_MS, signal);
|
|
3738
3811
|
}
|
|
3739
3812
|
}
|
|
@@ -3749,14 +3822,14 @@ function createSandboxRuntime(options) {
|
|
|
3749
3822
|
}
|
|
3750
3823
|
};
|
|
3751
3824
|
const createSandboxFromResolvedSnapshot = async (params) => {
|
|
3752
|
-
const { runtime, snapshot,
|
|
3825
|
+
const { runtime, snapshot, sandboxName, signal } = params;
|
|
3753
3826
|
signal?.throwIfAborted();
|
|
3754
3827
|
if (!snapshot.snapshotId) {
|
|
3755
3828
|
const networkPolicy = preflightNetworkPolicy(sandboxName);
|
|
3756
3829
|
const resources = getSandboxResources(params.workspace);
|
|
3757
3830
|
return {
|
|
3758
|
-
session:
|
|
3759
|
-
|
|
3831
|
+
session: await createSession({
|
|
3832
|
+
timeoutMs,
|
|
3760
3833
|
runtime,
|
|
3761
3834
|
...networkPolicy ? {
|
|
3762
3835
|
name: sandboxName,
|
|
@@ -3764,19 +3837,18 @@ function createSandboxRuntime(options) {
|
|
|
3764
3837
|
networkPolicy
|
|
3765
3838
|
} : void 0,
|
|
3766
3839
|
...resources ? { resources } : void 0,
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
})),
|
|
3840
|
+
scopeSignal: signal
|
|
3841
|
+
}),
|
|
3770
3842
|
snapshot
|
|
3771
3843
|
};
|
|
3772
3844
|
}
|
|
3773
3845
|
try {
|
|
3774
3846
|
return {
|
|
3775
|
-
session: await createSandboxFromSnapshot(snapshot.snapshotId,
|
|
3847
|
+
session: await createSandboxFromSnapshot(snapshot.snapshotId, sandboxName, params.workspace, signal),
|
|
3776
3848
|
snapshot
|
|
3777
3849
|
};
|
|
3778
3850
|
} catch (error) {
|
|
3779
|
-
if (!
|
|
3851
|
+
if (!getSandboxProvider().errors.isSnapshotMissing(error)) throw error;
|
|
3780
3852
|
setSpanAttributes({ "app.sandbox.snapshot.rebuild_after_missing": true });
|
|
3781
3853
|
let rebuilt;
|
|
3782
3854
|
if (params.workspace) rebuilt = await requireWorkspaceSnapshot({
|
|
@@ -3795,14 +3867,13 @@ function createSandboxRuntime(options) {
|
|
|
3795
3867
|
if (!rebuilt.snapshotId) throw error;
|
|
3796
3868
|
signal?.throwIfAborted();
|
|
3797
3869
|
return {
|
|
3798
|
-
session: await createSandboxFromSnapshot(rebuilt.snapshotId,
|
|
3870
|
+
session: await createSandboxFromSnapshot(rebuilt.snapshotId, sandboxName, params.workspace, signal),
|
|
3799
3871
|
snapshot: rebuilt
|
|
3800
3872
|
};
|
|
3801
3873
|
}
|
|
3802
3874
|
};
|
|
3803
3875
|
const createSandboxCandidate = async (workspace, hash, signal) => {
|
|
3804
3876
|
const runtime = SANDBOX_RUNTIME;
|
|
3805
|
-
const sandboxCredentials = getVercelSandboxCredentials();
|
|
3806
3877
|
const sandboxName = createSandboxName();
|
|
3807
3878
|
const prepareWorkspace = workspace ? async (sandbox) => await prepareWorkspaceSnapshot({
|
|
3808
3879
|
sandbox,
|
|
@@ -3833,7 +3904,6 @@ function createSandboxRuntime(options) {
|
|
|
3833
3904
|
return (await createSandboxFromResolvedSnapshot({
|
|
3834
3905
|
runtime,
|
|
3835
3906
|
snapshot,
|
|
3836
|
-
sandboxCredentials,
|
|
3837
3907
|
sandboxName,
|
|
3838
3908
|
signal,
|
|
3839
3909
|
workspace,
|
|
@@ -3892,22 +3962,20 @@ function createSandboxRuntime(options) {
|
|
|
3892
3962
|
if (!ref) return null;
|
|
3893
3963
|
let hintedSandbox = null;
|
|
3894
3964
|
try {
|
|
3895
|
-
const sandboxCredentials = getVercelSandboxCredentials();
|
|
3896
3965
|
hintedSandbox = await withSandboxSpan("sandbox.get", "sandbox.get", {
|
|
3897
3966
|
"app.sandbox.reused": true,
|
|
3898
3967
|
"app.sandbox.source": "id_hint"
|
|
3899
|
-
}, async () =>
|
|
3968
|
+
}, async () => await getSandboxProvider().getSession({
|
|
3900
3969
|
name: ref.id,
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
})));
|
|
3970
|
+
onUnavailable: invalidateSession,
|
|
3971
|
+
scopeSignal: signal
|
|
3972
|
+
}));
|
|
3905
3973
|
} catch (error) {
|
|
3906
|
-
if (
|
|
3974
|
+
if (getSandboxProvider().errors.isMissing(error)) {
|
|
3907
3975
|
sandboxRef = void 0;
|
|
3908
3976
|
return null;
|
|
3909
3977
|
}
|
|
3910
|
-
if (
|
|
3978
|
+
if (getSandboxProvider().errors.isUnavailable(error)) {
|
|
3911
3979
|
invalidateSession();
|
|
3912
3980
|
throw error;
|
|
3913
3981
|
}
|
|
@@ -3924,7 +3992,7 @@ function createSandboxRuntime(options) {
|
|
|
3924
3992
|
});
|
|
3925
3993
|
return rememberSandbox(hintedSandbox, networkPolicyKey);
|
|
3926
3994
|
} catch (error) {
|
|
3927
|
-
if (
|
|
3995
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw error;
|
|
3928
3996
|
return failSetup(error);
|
|
3929
3997
|
}
|
|
3930
3998
|
};
|
|
@@ -3934,13 +4002,21 @@ function createSandboxRuntime(options) {
|
|
|
3934
4002
|
"app.sandbox.timeout_ms": timeoutMs,
|
|
3935
4003
|
"app.sandbox.runtime": SANDBOX_RUNTIME,
|
|
3936
4004
|
"app.sandbox.skills_count": availableSkills.length
|
|
3937
|
-
}, async () => {
|
|
4005
|
+
}, async (setSpanAttributes) => {
|
|
3938
4006
|
const cachedSandbox = await tryReuseCachedSandbox();
|
|
3939
|
-
if (cachedSandbox)
|
|
4007
|
+
if (cachedSandbox) {
|
|
4008
|
+
setSpanAttributes({ "app.sandbox.acquire.outcome": "memory" });
|
|
4009
|
+
return cachedSandbox;
|
|
4010
|
+
}
|
|
3940
4011
|
signal?.throwIfAborted();
|
|
3941
4012
|
const hintedSandbox = await tryRestoreHintedSandbox(signal);
|
|
3942
|
-
if (hintedSandbox)
|
|
3943
|
-
|
|
4013
|
+
if (hintedSandbox) {
|
|
4014
|
+
setSpanAttributes({ "app.sandbox.acquire.outcome": "resumed" });
|
|
4015
|
+
return hintedSandbox;
|
|
4016
|
+
}
|
|
4017
|
+
const createdSandbox = await createFreshSandbox(signal);
|
|
4018
|
+
setSpanAttributes({ "app.sandbox.acquire.outcome": "created" });
|
|
4019
|
+
return createdSandbox;
|
|
3944
4020
|
});
|
|
3945
4021
|
};
|
|
3946
4022
|
const getOrAcquireSandbox = async (signal) => {
|
|
@@ -4010,7 +4086,7 @@ function createSandboxRuntime(options) {
|
|
|
4010
4086
|
await session.extendTimeout(keepAliveMs);
|
|
4011
4087
|
});
|
|
4012
4088
|
} catch (error) {
|
|
4013
|
-
if (
|
|
4089
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw error;
|
|
4014
4090
|
}
|
|
4015
4091
|
};
|
|
4016
4092
|
const startKeepAlive = (session) => {
|
|
@@ -5165,27 +5241,21 @@ function createSandbox(options) {
|
|
|
5165
5241
|
const { bash: executeBash, sessionId: activeSessionId } = await runtime.tools(context.signal);
|
|
5166
5242
|
await clearEgressSignals(activeSessionId);
|
|
5167
5243
|
const result = await withSandboxToolSpan("bash", "process.exec", { "process.executable.name": "bash" }, async () => {
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
return response;
|
|
5184
|
-
} catch (error) {
|
|
5185
|
-
setSpanAttributes({ "error.type": error instanceof Error ? error.name : "sandbox_execute_error" });
|
|
5186
|
-
setSpanStatus("error");
|
|
5187
|
-
throw error;
|
|
5188
|
-
}
|
|
5244
|
+
const response = await executeBash({
|
|
5245
|
+
command,
|
|
5246
|
+
cwd,
|
|
5247
|
+
...env ? { env } : void 0,
|
|
5248
|
+
...timeoutMs ? { timeoutMs } : void 0,
|
|
5249
|
+
...context.signal ? { signal: context.signal } : void 0
|
|
5250
|
+
});
|
|
5251
|
+
setSpanAttributes({
|
|
5252
|
+
"process.exit.code": response.exitCode,
|
|
5253
|
+
"app.sandbox.stdout_bytes": Buffer.byteLength(response.stdout ?? "", "utf8"),
|
|
5254
|
+
"app.sandbox.stderr_bytes": Buffer.byteLength(response.stderr ?? "", "utf8"),
|
|
5255
|
+
...response.aborted ? { "error.type": "outcome_unknown" } : response.exitCode !== 0 ? { "error.type": "nonzero_exit" } : {}
|
|
5256
|
+
});
|
|
5257
|
+
setSpanStatus(response.exitCode === 0 ? "ok" : "error");
|
|
5258
|
+
return response;
|
|
5189
5259
|
});
|
|
5190
5260
|
const { authRequired, permissionDenied } = await consumeEgressSignals(activeSessionId);
|
|
5191
5261
|
return formatSandboxCommandResult({
|
|
@@ -5379,8 +5449,8 @@ function createSandbox(options) {
|
|
|
5379
5449
|
} catch (error) {
|
|
5380
5450
|
params.signal?.throwIfAborted();
|
|
5381
5451
|
if (getWorkspaceSnapshotNotReadyError(error)) return createWorkspaceSnapshotNotReadyToolResult(error);
|
|
5382
|
-
if (
|
|
5383
|
-
if (
|
|
5452
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw createSandboxUnavailableToolError(params.toolName, error);
|
|
5453
|
+
if (getSandboxProvider().errors.isCommandStreamInterrupted(error)) throw new ToolInputError(`The sandbox command stream was interrupted during ${params.toolName}, so the operation did not complete reliably. It may have produced side effects; inspect the workspace or retry only if it is safe.`, { cause: error });
|
|
5384
5454
|
throw error;
|
|
5385
5455
|
}
|
|
5386
5456
|
throw new Error(`unsupported sandbox tool: ${params.toolName}`);
|
|
@@ -5391,7 +5461,7 @@ function createSandbox(options) {
|
|
|
5391
5461
|
} catch (error) {
|
|
5392
5462
|
const notReady = getWorkspaceSnapshotNotReadyError(error);
|
|
5393
5463
|
if (notReady) throw new ToolInputError(workspaceSnapshotNotReadyUserMessage(notReady), { cause: notReady });
|
|
5394
|
-
if (
|
|
5464
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw createSandboxUnavailableToolError(operation, error);
|
|
5395
5465
|
throw error;
|
|
5396
5466
|
}
|
|
5397
5467
|
};
|
|
@@ -5657,7 +5727,7 @@ function upstreamPermissionDeniedText(value) {
|
|
|
5657
5727
|
`Status: ${status}`,
|
|
5658
5728
|
...command ? [`Command: ${command}`] : [],
|
|
5659
5729
|
"",
|
|
5660
|
-
"
|
|
5730
|
+
"The runtime had a credential lease for this grant and forwarded the request. Do not diagnose this as a missing user token or a local runtime block.",
|
|
5661
5731
|
"Read the provider's error in the command output before you choose a cause. A provider can reject a request because of permissions, installation scope, SSO, or account access. It can also reject a valid credential because of the target's state, a rate limit, or another provider rule.",
|
|
5662
5732
|
...stderr ? ["", `stderr:\n${stderr}`] : [],
|
|
5663
5733
|
...stdout ? ["", `stdout:\n${stdout}`] : []
|
|
@@ -6061,7 +6131,7 @@ var McpToolManager = class {
|
|
|
6061
6131
|
async clientForTool(plugin, client, toolName) {
|
|
6062
6132
|
const provider = plugin.manifest.name;
|
|
6063
6133
|
if (!this.serviceAccountProviders.has(provider) || serviceAccountAllows(plugin.manifest, { tool: toolName })) return client;
|
|
6064
|
-
if (serviceAccountOnly(plugin.manifest)) throw new McpToolError(`${plugin.manifest.displayName} tool ${toolName} is not available:
|
|
6134
|
+
if (serviceAccountOnly(plugin.manifest)) throw new McpToolError(`${plugin.manifest.displayName} tool ${toolName} is not available: the shared ${plugin.manifest.displayName} account cannot use it`);
|
|
6065
6135
|
const existing = this.actorClientsByProvider.get(provider);
|
|
6066
6136
|
if (existing) return existing;
|
|
6067
6137
|
const actorClient = await this.newClient(plugin);
|
|
@@ -6639,7 +6709,7 @@ function createLoadSkillTool(availableSkills, options) {
|
|
|
6639
6709
|
readOnlyHint: false
|
|
6640
6710
|
},
|
|
6641
6711
|
description: "Load a skill by name for this turn. The result includes working_directory; resolve skill paths there and run skill-owned bash commands from there or with absolute paths. When the skill instructions name an MCP provider, use searchMcpTools before callMcpTool. Use when a request clearly matches a known skill.",
|
|
6642
|
-
inputSchema: z.object({ skill_name: z.string().min(1).describe("Skill name to load, without the leading
|
|
6712
|
+
inputSchema: z.object({ skill_name: z.string().min(1).describe("Skill name to load, without the leading `$`.") }),
|
|
6643
6713
|
outputSchema: juniorToolOutputSchema,
|
|
6644
6714
|
execute: async ({ skill_name }) => {
|
|
6645
6715
|
const result = await loadSkillFromHost(availableSkills, skill_name);
|
|
@@ -6788,10 +6858,10 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
6788
6858
|
openWorldHint: true,
|
|
6789
6859
|
readOnlyHint: true
|
|
6790
6860
|
},
|
|
6791
|
-
description: "List or search MCP providers and active MCP tools. When provider is supplied and not yet active,
|
|
6861
|
+
description: "List or search MCP providers and active MCP tools. When provider is supplied and not yet active, the runtime connects to it on demand and returns tool descriptors including schemas. Without provider, returns active tools plus matching configured providers without connecting. Use when choosing a provider tool or when callMcpTool arguments are unclear.",
|
|
6792
6862
|
inputSchema: z.object({
|
|
6793
6863
|
query: z.string().min(1).describe("Optional search terms describing the MCP tool or arguments needed.").optional(),
|
|
6794
|
-
provider: z.string().min(1).describe("Optional provider name to list or search within. If configured but not yet connected,
|
|
6864
|
+
provider: z.string().min(1).describe("Optional provider name to list or search within. If configured but not yet connected, the runtime activates it on demand.").optional(),
|
|
6795
6865
|
intent: z.string().min(1).describe("Set this when you pass provider. A short purpose to show the user if this call needs them to connect their account, for example \"search Notion for the Q3 offsite doc\".").optional(),
|
|
6796
6866
|
max_results: z.number().int().min(1).max(MAX_RESULTS$2).describe("Maximum matching tool descriptors to return.").optional()
|
|
6797
6867
|
}).strict(),
|
|
@@ -7621,15 +7691,7 @@ const searchedResourceTypeSchema = z.object({
|
|
|
7621
7691
|
identifierFormat: z.string().optional(),
|
|
7622
7692
|
supportedEvents: z.array(z.string()),
|
|
7623
7693
|
suggestedEvents: z.array(z.string()).optional(),
|
|
7624
|
-
matchFields: z.record(z.string(),
|
|
7625
|
-
kind: z.enum([
|
|
7626
|
-
"boolean",
|
|
7627
|
-
"string",
|
|
7628
|
-
"number"
|
|
7629
|
-
]),
|
|
7630
|
-
description: z.string(),
|
|
7631
|
-
enum: z.array(z.string()).optional()
|
|
7632
|
-
}).strict()).optional()
|
|
7694
|
+
matchFields: z.record(z.string(), eventMatchFieldSchema).optional()
|
|
7633
7695
|
}).strict();
|
|
7634
7696
|
const outputSchema$4 = juniorToolOutputSchema.extend({
|
|
7635
7697
|
query: z.string().nullable(),
|
|
@@ -7794,15 +7856,7 @@ function inputSchema(catalog) {
|
|
|
7794
7856
|
match: registeredEventMatchSchema(),
|
|
7795
7857
|
intent: z.string().trim().min(1).max(4e3).describe("Concise reason this conversation wants these events, used when an event arrives."),
|
|
7796
7858
|
ttlMs: z.coerce.number().describe("How long to keep the subscription active. Defaults to 14 days and must not exceed 30 days.").optional()
|
|
7797
|
-
}).strict()
|
|
7798
|
-
subscription.events.forEach((eventType, index) => {
|
|
7799
|
-
if (!pluginSupportsEvent(catalog, subscription.namespace, subscription.resourceType, eventType)) context.addIssue({
|
|
7800
|
-
code: "custom",
|
|
7801
|
-
message: `Resource type "${subscription.namespace}:${subscription.resourceType}" does not support event "${eventType}".`,
|
|
7802
|
-
path: ["events", index]
|
|
7803
|
-
});
|
|
7804
|
-
});
|
|
7805
|
-
});
|
|
7859
|
+
}).strict();
|
|
7806
7860
|
}
|
|
7807
7861
|
const stopWatchingActionSchema = z.object({
|
|
7808
7862
|
execution_tool: z.literal("executeTool"),
|
|
@@ -7847,17 +7901,17 @@ function createWatchEventsTool(context, catalog) {
|
|
|
7847
7901
|
inputSchema: inputSchema(catalog),
|
|
7848
7902
|
outputSchema: outputSchema$2,
|
|
7849
7903
|
async execute(input) {
|
|
7850
|
-
|
|
7851
|
-
if (
|
|
7904
|
+
const unavailable = eventWatchUnavailable(catalog, input.namespace, input.resourceType);
|
|
7905
|
+
if (unavailable) throw new ToolInputError(unavailable);
|
|
7852
7906
|
const events = cleanStrings(input.events);
|
|
7853
|
-
for (const eventType of events) if (!pluginSupportsEvent(catalog, input.namespace, input.resourceType, eventType)) throw new ToolInputError(`Resource type "${input.namespace}:${input.resourceType}" does not support event "${eventType}".`);
|
|
7854
7907
|
const intent = input.intent.trim();
|
|
7855
7908
|
if (!intent) throw new ToolInputError("intent is required");
|
|
7856
|
-
const match =
|
|
7909
|
+
const match = requireValidEventTrigger(catalog, {
|
|
7910
|
+
events,
|
|
7857
7911
|
match: input.match,
|
|
7858
7912
|
namespace: input.namespace,
|
|
7859
7913
|
resourceType: input.resourceType
|
|
7860
|
-
});
|
|
7914
|
+
}, "watch");
|
|
7861
7915
|
const nowMs = Date.now();
|
|
7862
7916
|
const subscription = await createWatch({
|
|
7863
7917
|
conversationId: context.conversationId,
|
|
@@ -7981,7 +8035,8 @@ const compactEventAutomationResultSchema = z.object({
|
|
|
7981
8035
|
label: z.string().min(1),
|
|
7982
8036
|
events: z.array(z.string().min(1)).min(1),
|
|
7983
8037
|
match: z.record(z.string(), z.unknown()).optional(),
|
|
7984
|
-
available: z.boolean()
|
|
8038
|
+
available: z.boolean(),
|
|
8039
|
+
problems: z.array(z.string().min(1)).min(1).optional()
|
|
7985
8040
|
}).strict(),
|
|
7986
8041
|
credentialMode: z.enum(["system", "creator"]),
|
|
7987
8042
|
isCreator: z.boolean(),
|
|
@@ -8019,15 +8074,9 @@ function registeredEventAutomationTriggerSchema(catalog) {
|
|
|
8019
8074
|
match: registeredEventMatchSchema()
|
|
8020
8075
|
}).strict();
|
|
8021
8076
|
}
|
|
8022
|
-
/** Reject an event-automation trigger that
|
|
8077
|
+
/** Reject an event-automation trigger that cannot work with the enabled plugins. */
|
|
8023
8078
|
function requireSupportedEventAutomationTrigger(catalog, trigger) {
|
|
8024
|
-
|
|
8025
|
-
for (const eventType of trigger.events) if (!pluginSupportsEvent(plugins, trigger.namespace, trigger.resourceType, eventType)) throw new ToolInputError(`Resource type "${trigger.namespace}:${trigger.resourceType}" does not support event "${eventType}".`);
|
|
8026
|
-
return requireSupportedEventMatch(plugins, {
|
|
8027
|
-
match: trigger.match,
|
|
8028
|
-
namespace: trigger.namespace,
|
|
8029
|
-
resourceType: trigger.resourceType
|
|
8030
|
-
});
|
|
8079
|
+
return requireValidEventTrigger(automationEventCatalog(catalog), trigger, "event_automation");
|
|
8031
8080
|
}
|
|
8032
8081
|
/** Require the active Slack authority used for event-automation management. */
|
|
8033
8082
|
function requireEventAutomationSlackContext(context) {
|
|
@@ -8062,12 +8111,18 @@ async function writableEventAutomation(context, id) {
|
|
|
8062
8111
|
if (!task || task.status === "deleted" || !eventAutomationIsWritableFrom(task, destination)) throw new ToolInputError("Event automation was not found.");
|
|
8063
8112
|
return task;
|
|
8064
8113
|
}
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8114
|
+
/**
|
|
8115
|
+
* Describe a saved trigger with the enabled plugins. Its problems say why it
|
|
8116
|
+
* cannot work: a plugin can remove or rename a resource type, event, or filter
|
|
8117
|
+
* after the trigger was saved. Resource types with `automation: false` never
|
|
8118
|
+
* dispatch event automations.
|
|
8119
|
+
*/
|
|
8120
|
+
function describeEventAutomationTrigger(trigger, catalog) {
|
|
8121
|
+
return describeRegisteredEventTrigger(automationEventCatalog(catalog), trigger);
|
|
8068
8122
|
}
|
|
8069
8123
|
/** Project an event automation into the bounded tool-result shape. */
|
|
8070
8124
|
function compactEventAutomation(task, catalog, requesterSlackUserId) {
|
|
8125
|
+
const { problems } = describeEventAutomationTrigger(task.trigger, catalog);
|
|
8071
8126
|
return compactEventAutomationResultSchema.parse({
|
|
8072
8127
|
id: task.id,
|
|
8073
8128
|
status: task.status,
|
|
@@ -8082,7 +8137,8 @@ function compactEventAutomation(task, catalog, requesterSlackUserId) {
|
|
|
8082
8137
|
label: task.trigger.label,
|
|
8083
8138
|
events: task.trigger.events,
|
|
8084
8139
|
...task.trigger.match ? { match: task.trigger.match } : void 0,
|
|
8085
|
-
available:
|
|
8140
|
+
available: problems.length === 0,
|
|
8141
|
+
...problems.length > 0 ? { problems } : void 0
|
|
8086
8142
|
},
|
|
8087
8143
|
credentialMode: task.credentialMode,
|
|
8088
8144
|
isCreator: task.createdBy.slackUserId === requesterSlackUserId,
|
|
@@ -8102,7 +8158,7 @@ function compactEventAutomation(task, catalog, requesterSlackUserId) {
|
|
|
8102
8158
|
/** Return the standard successful event-automation tool result. */
|
|
8103
8159
|
async function eventAutomationToolResult(conversationId, task, catalog, requesterSlackUserId) {
|
|
8104
8160
|
const automation = compactEventAutomation(task, catalog, requesterSlackUserId);
|
|
8105
|
-
const
|
|
8161
|
+
const description = describeEventAutomationTrigger(task.trigger, catalog);
|
|
8106
8162
|
const title = automation.title ?? fallbackShortTitle(task.task.text, "Event automation");
|
|
8107
8163
|
return {
|
|
8108
8164
|
automation,
|
|
@@ -8114,13 +8170,9 @@ async function eventAutomationToolResult(conversationId, task, catalog, requeste
|
|
|
8114
8170
|
title,
|
|
8115
8171
|
url: automation.dashboardUrl,
|
|
8116
8172
|
description: task.task.text,
|
|
8117
|
-
status:
|
|
8118
|
-
trigger:
|
|
8119
|
-
|
|
8120
|
-
task.trigger.events.join(", "),
|
|
8121
|
-
...filters
|
|
8122
|
-
].join(" · "),
|
|
8123
|
-
warning: !automation.trigger.available ? "Trigger unavailable. This automation cannot receive events." : void 0
|
|
8173
|
+
status: description.problems.length === 0 ? "ready" : "unavailable",
|
|
8174
|
+
trigger: eventTriggerText(task.trigger.label, description),
|
|
8175
|
+
warning: description.problems.length > 0 ? ["Trigger unavailable.", ...description.problems].join(" ") : void 0
|
|
8124
8176
|
}])
|
|
8125
8177
|
};
|
|
8126
8178
|
}
|
|
@@ -8262,7 +8314,7 @@ function createListEventAutomationsTool(context, catalog) {
|
|
|
8262
8314
|
openWorldHint: false,
|
|
8263
8315
|
readOnlyHint: true
|
|
8264
8316
|
},
|
|
8265
|
-
description: "List event automations for the current destination, not one thread. Each result says whether the requester is the creator (isCreator); only the creator can change its credential use. Warn when trigger.available is false: the automation stays stored but
|
|
8317
|
+
description: "List event automations for the current destination, not one thread. Each result says whether the requester is the creator (isCreator); only the creator can change its credential use. Warn when trigger.available is false and explain trigger.problems: the automation stays stored, but a plugin no longer supports its resource type, an event, or a filter. Update the trigger to fix it. Public automations can also be updated or deleted by id from another destination in the same workspace.",
|
|
8266
8318
|
inputSchema: z.object({}).strict(),
|
|
8267
8319
|
outputSchema: eventAutomationListToolResultSchema,
|
|
8268
8320
|
async execute() {
|
|
@@ -8717,7 +8769,7 @@ function createSlackScheduleCreateAutomationTool(context) {
|
|
|
8717
8769
|
openWorldHint: true,
|
|
8718
8770
|
readOnlyHint: false
|
|
8719
8771
|
},
|
|
8720
|
-
description: "Create a one-time or recurring
|
|
8772
|
+
description: "Create a one-time or recurring scheduled task in the active Slack channel. Store the requested future work; do not perform it or check its service access now unless the user also asks for that.",
|
|
8721
8773
|
executionMode: "sequential",
|
|
8722
8774
|
inputSchema: z.object({
|
|
8723
8775
|
instruction: automationInstructionToolSchema,
|
|
@@ -8815,7 +8867,7 @@ function createSlackScheduleDeleteAutomationTool(context) {
|
|
|
8815
8867
|
openWorldHint: false,
|
|
8816
8868
|
readOnlyHint: false
|
|
8817
8869
|
},
|
|
8818
|
-
description: "Delete one scheduled
|
|
8870
|
+
description: "Delete one scheduled task from the active Slack conversation. Use only task IDs returned for this conversation. Do not delete schedules from threads, other channels, or another user's DM.",
|
|
8819
8871
|
executionMode: "sequential",
|
|
8820
8872
|
inputSchema: z.object({ automationId: z.string().min(1).describe("ID of the task to delete. Must be from this active Slack conversation.") }),
|
|
8821
8873
|
outputSchema: scheduleAutomationToolResultSchema.extend({ removedCards: z.array(removedCardSchema) }),
|
|
@@ -8946,7 +8998,7 @@ function createSlackScheduleRunAutomationNowTool(context) {
|
|
|
8946
8998
|
openWorldHint: true,
|
|
8947
8999
|
readOnlyHint: false
|
|
8948
9000
|
},
|
|
8949
|
-
description: "Queue an existing active scheduled
|
|
9001
|
+
description: "Queue an existing active scheduled task to run as soon as possible, without changing its cadence. Use when the user asks to run an existing scheduled automation now. Use only task IDs returned for this conversation.",
|
|
8950
9002
|
executionMode: "sequential",
|
|
8951
9003
|
inputSchema: z.object({ automationId: z.string().min(1).describe("ID of the active task to run now. Must be from this active Slack conversation.") }),
|
|
8952
9004
|
outputSchema: scheduleAutomationToolResultSchema,
|
|
@@ -9272,7 +9324,7 @@ async function joinPublicChannelForRead(args) {
|
|
|
9272
9324
|
}
|
|
9273
9325
|
}
|
|
9274
9326
|
/** Model-facing Slack channel id or known channel name parameter. */
|
|
9275
|
-
const slackChannelRefParam = z.string().trim().min(1).max(160).describe("Slack channel id (`C123`), mention (`<#C123>` / `<#C123|name>`),
|
|
9327
|
+
const slackChannelRefParam = z.string().trim().min(1).max(160).describe("Slack channel id (`C123`), mention (`<#C123>` / `<#C123|name>`), Slack reference (`slack:C123`), or a channel name you already know in this workspace.");
|
|
9276
9328
|
/**
|
|
9277
9329
|
* Resolve a channel reference from a tool param value.
|
|
9278
9330
|
*
|
|
@@ -9281,7 +9333,7 @@ const slackChannelRefParam = z.string().trim().min(1).max(160).describe("Slack c
|
|
|
9281
9333
|
*/
|
|
9282
9334
|
async function resolveSlackChannelRef(input) {
|
|
9283
9335
|
const trimmed = input.value.trim();
|
|
9284
|
-
if (!trimmed) throw new ToolInputError(`Invalid \`${input.field}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a
|
|
9336
|
+
if (!trimmed) throw new ToolInputError(`Invalid \`${input.field}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a Slack reference (\`slack:C123\`), or a channel name you already know.`);
|
|
9285
9337
|
const channelId = parseSlackChannelReferenceId(trimmed);
|
|
9286
9338
|
if (channelId) return { channelId };
|
|
9287
9339
|
const known = await getConversationStore().findSlackDestinationByName({
|
|
@@ -9293,7 +9345,7 @@ async function resolveSlackChannelRef(input) {
|
|
|
9293
9345
|
channelId: knownChannelId,
|
|
9294
9346
|
...known.channelName ? { channelName: known.channelName } : void 0
|
|
9295
9347
|
};
|
|
9296
|
-
throw new ToolInputError(`Unknown \`${input.field}\` \`${trimmed}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a link, or a channel name
|
|
9348
|
+
throw new ToolInputError(`Unknown \`${input.field}\` \`${trimmed}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a link, or a channel name you already saw in this workspace. Public search can discover channels; plain names are not scanned from Slack.`);
|
|
9297
9349
|
}
|
|
9298
9350
|
/**
|
|
9299
9351
|
* Resolve an optional channel reference, falling back to the active channel.
|
|
@@ -9600,7 +9652,7 @@ function createSlackConversationBriefSearchPort(teamId) {
|
|
|
9600
9652
|
/** Deferred tool catalog source for retained Junior conversations. */
|
|
9601
9653
|
const CONVERSATIONS_TOOL_SOURCE = {
|
|
9602
9654
|
id: "conversations",
|
|
9603
|
-
description: "Search messages and events in retained
|
|
9655
|
+
description: "Search messages and events in retained conversations."
|
|
9604
9656
|
};
|
|
9605
9657
|
// src/chat/slack/tools/conversation-message-search.ts
|
|
9606
9658
|
const DEFAULT_LIMIT$3 = 20;
|
|
@@ -13344,19 +13396,33 @@ function createWebSearchTool(modelId, override) {
|
|
|
13344
13396
|
const controller = new AbortController();
|
|
13345
13397
|
const credential = await resolveGatewayCredential();
|
|
13346
13398
|
const provider = createGatewayProvider(credential ? { apiKey: credential.token } : {});
|
|
13347
|
-
const results = parseSearchResults((await
|
|
13348
|
-
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13399
|
+
const results = parseSearchResults((await withSpan(`chat ${modelId}`, "gen_ai.chat", {}, async (setSpanAttributes) => {
|
|
13400
|
+
const response = await withTimeout(generateText({
|
|
13401
|
+
model: provider.chat(modelId),
|
|
13402
|
+
prompt: query,
|
|
13403
|
+
tools: { [SEARCH_TOOL_NAME]: provider.tools.parallelSearch({
|
|
13404
|
+
mode: "agentic",
|
|
13405
|
+
maxResults
|
|
13406
|
+
}) },
|
|
13407
|
+
toolChoice: {
|
|
13408
|
+
type: "tool",
|
|
13409
|
+
toolName: SEARCH_TOOL_NAME
|
|
13410
|
+
},
|
|
13411
|
+
abortSignal: controller.signal
|
|
13412
|
+
}), SEARCH_TIMEOUT_MS, "webSearch", { onTimeout: () => controller.abort() });
|
|
13413
|
+
setSpanAttributes({
|
|
13414
|
+
"gen_ai.response.finish_reasons": [response.finishReason],
|
|
13415
|
+
...extractGenAiUsageAttributes(response.usage)
|
|
13416
|
+
});
|
|
13417
|
+
return response;
|
|
13418
|
+
}, {
|
|
13419
|
+
"gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
|
|
13420
|
+
"gen_ai.operation.name": "chat",
|
|
13421
|
+
"gen_ai.request.model": modelId,
|
|
13422
|
+
"server.address": GEN_AI_SERVER_ADDRESS,
|
|
13423
|
+
"server.port": 443,
|
|
13424
|
+
"gen_ai.provider.auth_mode": credential?.mode ?? "api_key"
|
|
13425
|
+
})).toolResults, maxResults);
|
|
13360
13426
|
return {
|
|
13361
13427
|
model: modelId,
|
|
13362
13428
|
query,
|
|
@@ -15392,7 +15458,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
15392
15458
|
const authorizationRequest = {
|
|
15393
15459
|
authorizationUrl: authSession.authorizationUrl,
|
|
15394
15460
|
label: `Connect your ${providerLabel} account`,
|
|
15395
|
-
completionText: "Once you've authorized,
|
|
15461
|
+
completionText: "Once you've authorized, I'll continue automatically."
|
|
15396
15462
|
};
|
|
15397
15463
|
if (!await deliverOAuthAuthorization(authorizationRequest, {
|
|
15398
15464
|
authorization: input.authorization,
|
|
@@ -15456,7 +15522,7 @@ const GUARDIAN_BLOCK_RULES = {
|
|
|
15456
15522
|
},
|
|
15457
15523
|
different_change: {
|
|
15458
15524
|
decision: "ask",
|
|
15459
|
-
description: "The write is a different kind of change from the one the user asked for, or it adds fields or effects beyond it. Examples: it updates or rewrites an existing resource when the user asked for a new one or only for a review; it publishes as ready when the user asked for a draft; it pushes unreviewed changes straight to a default or protected branch. Upkeep of a resource that the agent created for the work is not a different change."
|
|
15525
|
+
description: "The write is a different kind of change from the one the user asked for, or it adds fields or effects beyond it. Examples: it updates or rewrites an existing resource when the user asked for a new one or only for a review; it publishes as ready when the user asked for a draft; it pushes unreviewed changes straight to a default or protected branch. Upkeep of a resource that the agent created for the work is not a different change. This includes an update to its title or description that describes changes already in it, even when the agent earlier offered to put that work in a separate resource. Such an update moves no work, because the changes are already there."
|
|
15460
15526
|
},
|
|
15461
15527
|
unrequested_write: {
|
|
15462
15528
|
decision: "ask",
|
|
@@ -15504,7 +15570,7 @@ const GUARDIAN_RULE_IDS = ["none", ...Object.keys(GUARDIAN_BLOCK_RULES)];
|
|
|
15504
15570
|
function renderRules(decision) {
|
|
15505
15571
|
return Object.entries(GUARDIAN_BLOCK_RULES).filter(([, rule]) => rule.decision === decision).map(([id, rule]) => `- \`${id}\`: ${rule.description}`).join("\n");
|
|
15506
15572
|
}
|
|
15507
|
-
const GUARDIAN_ACTION_POLICY = `You are judging one planned
|
|
15573
|
+
const GUARDIAN_ACTION_POLICY = `You are judging one planned action of the assistant agent.
|
|
15508
15574
|
Assess the exact action's intrinsic risk and whether the user's intent authorizes its target and side effects. Then name the one block rule that the action matches, or \`none\`. Actions are allowed by default. Your primary objective is to prevent irreversible damage to the user or organization while allowing ordinary, proportionate work without interruption.
|
|
15509
15575
|
|
|
15510
15576
|
# Evidence Handling
|
|
@@ -15553,7 +15619,7 @@ ${renderRules("deny")}
|
|
|
15553
15619
|
- Whether the work is correct, complete, well proven, or well styled is not your concern, and neither is whether the agent checked enough before it acted. Posting results that the user or the automation instruction asked for matches no rule.
|
|
15554
15620
|
- Content that the current actor's request is about, such as the conversation or examples they pointed to, is part of the requested work. Using it in the requested deliverable at an authorized destination is not data exposure, unless it includes secrets, credentials, or private data about other people.
|
|
15555
15621
|
- Ordinary product context such as internal system names, repository names, or workflow descriptions is not private organization data, including on an authorized public destination.
|
|
15556
|
-
- The active
|
|
15622
|
+
- The active conversation, where the assistant works with the user, is not an untrusted destination merely because it is a public or multi-user channel.
|
|
15557
15623
|
- A user-requested read, query, or upload to a trusted destination is not data exposure. Using an existing credential to authenticate a user-requested action is not credential probing.
|
|
15558
15624
|
- A tool that is external, multi-field, open-world, uses connected credentials, has plugin or catalog identity, or carries a destructive annotation does not match a rule by those facts alone. Judge actual side effects, not tool names or annotations.
|
|
15559
15625
|
- For a scheduled automation or event automation, a request by the current actor for scoped work that needs their connected service access authorizes routine service-native reads and posting the requested result to the task's stored Slack destination. It does not authorize exposing credential values, broad data dumps, or delivery to another destination.
|
|
@@ -15665,7 +15731,6 @@ function createGuardianActionReviewer(options) {
|
|
|
15665
15731
|
system: GUARDIAN_ACTION_POLICY,
|
|
15666
15732
|
prompt: guardianPrompt(proposal),
|
|
15667
15733
|
maxTokens: GUARDIAN_REVIEW_MAX_TOKENS,
|
|
15668
|
-
recordTelemetryPayloads: false,
|
|
15669
15734
|
temperature: 0,
|
|
15670
15735
|
promptName: "junior.guardian_action_review",
|
|
15671
15736
|
signal,
|
|
@@ -18255,7 +18320,7 @@ function createAgentRunner(execute, options) {
|
|
|
18255
18320
|
} } : void 0
|
|
18256
18321
|
};
|
|
18257
18322
|
if (run.instruction.storedAttachments?.length) {
|
|
18258
|
-
const { loadInputImages } = await import("./images-
|
|
18323
|
+
const { loadInputImages } = await import("./images-BKQqSi5W.js").then((n) => n.n);
|
|
18259
18324
|
const storage = nextRun.environment?.attachmentStorage;
|
|
18260
18325
|
if (!storage) throw new Error("Attachment storage is unavailable.");
|
|
18261
18326
|
nextRun.instruction = {
|
|
@@ -18270,4 +18335,4 @@ function createAgentRunner(execute, options) {
|
|
|
18270
18335
|
return await execute(nextRun, streamFn);
|
|
18271
18336
|
} };
|
|
18272
18337
|
}
|
|
18273
|
-
export {
|
|
18338
|
+
export { actorFromRun as $, listThreadReplies as A, stopChildAgentsOf as B, requestAttachmentDeletion as C, resolveSlackChannelIdFromMessage as D, readSlackRawMessageContext as E, AutomationEditError as F, listUnreportedSiblingAgents as G, recordSubagentEnded as H, describeEventAutomationTrigger as I, processWorkspaceSnapshotJob as J, conversationSubtree as K, effectiveTaskOutcomes as L, logScheduledAutomationRunSkipped as M, scheduledAutomationRunAttributes as N, resolveSlackChannelIdFromThreadId as O, editEventAutomation as P, RetryableDeliveryError as Q, resolveTaskOutcomes as R, readLiveAttachment as S, parseSlackThreadId as T, recordSubagentStarted as U, stopConversationSession as V, listChildAgents as W, buildSteeringPiMessage as X, ingestEvent as Y, withoutSavedSteeringMessages as Z, unpublishedArtifactHeaders as _, finalizeMcpAuthorization as a, renderBlockText as b, deleteMcpServerSessionId as c, getMcpStoredOAuthCredentials as d, toolInvocationDestination as et, putMcpStoredOAuthCredentials as f, readPublicArtifact as g, publicArtifactHeaders as h, buildAuthPauseResponse as i, editScheduledAutomation as j, getConversationInfo as k, deleteMcpStoredOAuthCredentials as l, readStats as m, executeAgentRun as n, shouldEmitDevAgentTrace as nt, deleteMcpAuthSession as o, latestProgressStatus as p, conversationSubtreeColumns as q, createContextCompactor as r, deleteMcpAuthSessionsForUserProvider as s, createAgentRunner as t, readBlockedReport as tt, getMcpAuthSession as u, lookupSlackUserProfile as v, storeAttachment as w, collectAttachmentGarbage as x, renderAttachmentText as y, listOwnedWatches as z };
|