@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.
Files changed (69) hide show
  1. package/README.md +1 -1
  2. package/dist/{adapter-BIbMSKlG.js → adapter-eRFA_naf.js} +1 -1
  3. package/dist/{admin-D4d0HXax.js → admin-tILpP51p.js} +1 -1
  4. package/dist/{agent-runner-CvRxb09K.js → agent-runner-BtYK7bht.js} +263 -198
  5. package/dist/api/schema.d.ts +216 -15
  6. package/dist/api/schema.js +5 -5
  7. package/dist/api.js +109 -42
  8. package/dist/{app-Buc5gIWz.d.ts → app-Csbi9dW7.d.ts} +0 -4
  9. package/dist/app.d.ts +1 -1
  10. package/dist/app.js +79 -390
  11. package/dist/{assistant-reply-BcJj_ORj.js → assistant-reply-UyzAfZQo.js} +1 -1
  12. package/dist/{automation-CWX0qL8U.js → automation-BKpY9LPa.js} +31 -10
  13. package/dist/{briefs-BFfIE5N6.js → briefs-DgfWMU7e.js} +5 -5
  14. package/dist/{catalog-runtime-R53MWcMi.js → catalog-runtime-DAJjAbSx.js} +1 -1
  15. package/dist/cli/chat.js +15 -15
  16. package/dist/cli/check.js +3 -3
  17. package/dist/cli/init.js +4 -18
  18. package/dist/cli/main.js +4 -4
  19. package/dist/cli/plugins.js +4 -4
  20. package/dist/cli/snapshot-create.js +4 -4
  21. package/dist/cli/upgrade.js +3 -3
  22. package/dist/{client-DpOwh_zX.js → client-B0YZfxNy.js} +3 -8
  23. package/dist/{config-BxPrFVJP.js → config-C0UwYqDK.js} +100 -3
  24. package/dist/{connections-BnTM1nRf.js → connections-Bwu3VORi.js} +11 -10
  25. package/dist/{conversation-B0baEwoA.js → conversation-DF4rUcjb.js} +6 -2
  26. package/dist/{conversation-privacy-ueJ6i-t9.js → conversation-privacy-CY7JVjxn.js} +1 -1
  27. package/dist/{credential-sync-DeDkof_D.js → credential-sync-VGAMUTGp.js} +20 -20
  28. package/dist/{agent-hooks-D_PbluRX.js → credentialed-enF5Bf3y.js} +3316 -179
  29. package/dist/{executor-D3WIS4vl.js → executor-TnWbvL09.js} +10 -300
  30. package/dist/{history-AY8rs-FR.js → history-C84mlAwO.js} +2 -1
  31. package/dist/{images-5VNK_yYC.js → images-BKQqSi5W.js} +3 -3
  32. package/dist/instrumentation.js +41 -25
  33. package/dist/{job-queue-BYHonCAH.js → job-queue-DBpHmKnd.js} +53 -14
  34. package/dist/{logging-DNQqsQ57.js → logging-Ce0mXZ8J.js} +19 -32
  35. package/dist/{message-CDTJISxL.js → message-VZ3DFpGb.js} +4 -4
  36. package/dist/nitro.d.ts +17 -2
  37. package/dist/nitro.js +26 -27
  38. package/dist/{oauth-callback-server-Bk4rbLOs.js → oauth-callback-server-CpqWLjVY.js} +2 -2
  39. package/dist/{prompt-CxatQVaj.js → prompt-BcCGlmg2.js} +2 -2
  40. package/dist/{registry-CfdUEk4N.js → registry-1BEIPdbT.js} +1 -1
  41. package/dist/{resolve-BXShI336.js → resolve-BSHHkEGE.js} +7 -106
  42. package/dist/{result-R35jcahx.js → result-CwOpzqdh.js} +8 -8
  43. package/dist/{runner-IC4Drh3Y.js → runner-CEaX04kz.js} +11 -11
  44. package/dist/{sandbox-egress-signals-C4RIfjb8.js → sandbox-egress-signals-BwtGHwqa.js} +1 -1
  45. package/dist/{schema-QidbykYl.js → schema-RsaBHxRH.js} +45 -4
  46. package/dist/{sentry-BBUlHih9.js → sentry-MDkYAVPV.js} +3 -6
  47. package/dist/{service-account-DJSRo2cL.js → service-account-6wC76eBZ.js} +5 -5
  48. package/dist/{service-account-DifohWyX.js → service-account-Dg4lIbHm.js} +3 -3
  49. package/dist/{session-stop-B9RRGC-P.js → session-stop-tZOw9AJD.js} +120 -80
  50. package/dist/{skills-DVJmS_ZP.js → skills-DzyGN7wd.js} +2 -2
  51. package/dist/{spawn-DkVYGfSY.js → spawn-6rokq7l_.js} +2 -2
  52. package/dist/{store-BvolNnx4.js → store-DcKkzrdt.js} +3 -3
  53. package/dist/{store-C_mHwAnR.js → store-FALy-JQb.js} +6 -6
  54. package/dist/{task-queue-BcEyPhtX.js → task-queue-Bg4RS2Gy.js} +14 -19
  55. package/dist/{task-runner-CiQj5M_9.js → task-runner-8N5LIkSg.js} +47 -29
  56. package/dist/{tasks-OgXmReUv.js → tasks-DDT-J3Rf.js} +17 -2078
  57. package/dist/{thread-state-XFvpWXE9.js → thread-state-cprEaxgl.js} +5 -5
  58. package/dist/{turn-failure-response-BjBAtnVt.js → turn-failure-response-C8sMdsdX.js} +8 -8
  59. package/dist/{turn-lifecycle-nvKL2rul.js → turn-lifecycle-DaBVoz7h.js} +2 -2
  60. package/dist/{turn-session-routing-DEMxHySb.js → turn-session-routing-a9CHX-w6.js} +1 -1
  61. package/dist/{validation-XOFldwvE.js → validation-C2lllinq.js} +1 -1
  62. package/dist/{version-C9f5hdHD.js → version-oaLfxxnf.js} +1 -1
  63. package/dist/version.js +1 -1
  64. package/dist/{viewer-BuPwzOC9.js → viewer-BpE6Z3qf.js} +22 -6
  65. package/dist/{web-input-4t7TYLsY.js → web-input-B-bMjD1V.js} +147 -48
  66. package/dist/{work-C_aF6JN5.js → work-VX1SHWha.js} +52 -51
  67. package/dist/{worker-DR633sA-.js → worker-hook-y_Y.js} +5 -5
  68. package/package.json +10 -9
  69. package/dist/profile-ieODOp4u.js +0 -582
@@ -1,32 +1,31 @@
1
- import { $t as isToolResultMessage, An as createSandboxEgressCredentialToken, B as recordAttachmentsDelivered, Ct as canReusePendingAuthLink, Dn as clearSandboxEgressSignals, Dt as continuableMessages, G as recordMcpProviderConnected, Gn as getSlackMessagePermalink, Gt as getPiMessageRole, Hn as slackMention, Ht as isTurnExecutionLimitExceededError, In as resolveBaseUrl, It as TURN_LIMIT_DISABLED_REASON, J as recordTurnRoute, Jt as hasRuntimeTurnContext, Kn as openSlackDirectMessage, Kt as getTerminalAssistantMessages, L as loadTurnRoute, Lt as TurnBudgetExceededError, M as loadConnectedMcpProviders, N as loadConversationProjection, Nn as deliverOAuthAuthorization, O as automationRevision, On as consumeSandboxEgressAuthRequiredSignal, Ot as loadTurnCheckpoint, P as loadLastModelProfile, Pn as formatProviderLabel, Qn as getOAuthAccountProviders, Qt as isToolResultError, R as openConversationProjection, Rt as TurnSliceLimitExceededError, Sn as resolveSandboxCommandEnvironment, St as abandonReplacedPendingAuth, U as recordAuthorizationRequested, Vt as createTurnLimitGate, W as recordGuardianActionReviewed, Wn as addReactionToMessage, Wt as extractAssistantText, Xt as isAssistantMessage, Yn as uploadFilesToConversation, Zt as isContinuablePiBoundary, _n as isExperimentalFeatureEnabled, _t as createPluginAuthOrchestration, a as saveScheduledAutomation, an as SESSION_CONTEXT_SECTION_TAG, bn as createUserTokenStore, 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, ir as getConfigDefaults, kn as consumeSandboxEgressPermissionDeniedSignal, kt as saveTurnCheckpoint, m as getEventAutomation, mn as getAgentContextCompactionTriggerTokens, n as listScheduledAutomationsForTeam, nn as stripRuntimeTurnContext, nr as historyItemFromPiMessage, nt as fallbackShortTitle, on as TURN_CONTEXT_TAG, pn as estimateTextTokens, q as recordToolExecutionStarted, qt as getUserMessageInstructionText, rn as trimTrailingAssistantMessages, rr as piMessageFromHistoryItem, rt as resolveTaskTitle, t as createScheduledAutomation, tn as retainRuntimeTurnContext, v as saveEventAutomation, vt as authorizationId, xn as buildSandboxEgressNetworkPolicy, xt as AuthorizationPauseError, y as setEventAutomationStatus, yt as AuthPausePersistenceError, z as recordAgentsInstructionsUpdated, zt as TurnToolCallLimitExceededError } from "./tasks-OgXmReUv.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-DpOwh_zX.js";
3
- 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-DNQqsQ57.js";
4
- import { m as startInactiveSpan, v as withActiveSpan } from "./sentry-BBUlHih9.js";
5
- 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-ueJ6i-t9.js";
6
- import { n as botConfig, v as normalizeSlackEmojiName } from "./config-BxPrFVJP.js";
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 { C as addAgentTurnUsage, D as hasAgentTurnUsage, R as parseDestination, c as getConversationEventStore, d as getDb, f as getSqlExecutor, l as getConversationMessageSearchStore, r as readActorIdentity, u as getConversationStore, w as agentTurnCostUsd } from "./viewer-BuPwzOC9.js";
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-D3WIS4vl.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-AY8rs-FR.js";
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-CfdUEk4N.js";
15
- import { n as pluginCatalogRuntime } from "./catalog-runtime-R53MWcMi.js";
16
- import { a as parseSkillInvocation, i as parseSkillFile, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-DVJmS_ZP.js";
17
- import { A as getWorkspaceSnapshotBuilder, B as STOP_WATCHING_TOOL_NAME, C as WorkspaceValidationError, D as setWorkspaceSnapshotBuild, E as setWorkspaceSnapshot, F as isSlackMessageTurn, G as createWatch, Gt as saveObjectAnnotations, H as cancelWatch, I as slackMessageTurnDisabledReason, J as getWatch, K as deliverWatch, Kt as createPluginAnnotations, L as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, M as workspaceRepoCheckoutPath, N as resolveChannelCapabilities, O as SANDBOX_RUNTIME, P as getSlackToolContext, R as RESOURCE_SUBSCRIPTION_MAX_TTL_MS, S as updateWorkspace, St as PluginToolDeniedError, T as loadSnapshotsForProfile, V as cancelSubscriptions, Vt as matchSlackAttachments, W as createTimerWatch, Xt as resolveUserTimezone, Y as listWatches, Yt as defaultTimezone, _ as deleteWorkspace, _t as getDashboardConversationLink, at as downloadPrivateSlackFile, b as listWorkspaces, c as getPluginTools, ct as getSlackClient, dt as normalizeSlackConversationId, en as JUNIOR_NATIVE_EVENT_NAMESPACE, g as createWorkspace, in as conversationNoteEvent, it as SlackActionError, j as tryWorkspaceRepoCheckoutPath, k as deleteWorkspaceSnapshotBuilders, l as getPluginUserPromptContributions, lt as isConversationScopedChannel, ot as getFilePermalink, pt as withSlackRetries, q as findMatchingWatches, r as createPluginHookRunner, s as getPluginSystemPromptContributions, u as getPlugins, v as getWorkspace, w as invalidateReadySnapshot, xt as ToolInputError, y as getWorkspaceByName, yt as getDashboardTaskLink, z as RESOURCE_WATCH_TOOL_SOURCE } from "./agent-hooks-D_PbluRX.js";
18
- import { o as fenceLock, r as getStateAdapter, s as withLock } from "./adapter-BIbMSKlG.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-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-B0baEwoA.js";
21
- import { A as sandboxSkillPathResolution, C as SANDBOX_COMMAND_PATH, D as SANDBOX_WORKSPACE_ROOT, E as SANDBOX_SKILLS_ROOT, O as sandboxSkillDir, S as runNonInteractiveCommand, T as SANDBOX_REPOS_ROOT, _ as workspaceSnapshotNotReadyUserMessage, a as isAbortError, b as buildCommandScript, c as isSandboxCommandStreamInterruptedError, d as isSnapshottingError, f as throwSandboxOperationError, g as isWorkspaceSnapshotNotReadyError, h as getWorkspaceSnapshotNotReadyError, i as ensureDockerDaemon, k as sandboxSkillFile, l as isSandboxMissingError, m as WorkspaceSnapshotNotReadyError, n as hash, o as isAlreadyExistsError, p as wrapSandboxSetupError, r as isStale, s as isSandboxApiTransientError, t as create, u as isSandboxUnavailableError, v as getVercelSandboxCredentials, w as SANDBOX_DATA_ROOT, x as buildNonInteractiveShellScript, y as sleep } from "./profile-ieODOp4u.js";
22
- 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-BvolNnx4.js";
23
- import { a as isNoReplyMarker, i as NO_REPLY_MARKER, n as getAssistantReplyText, r as sanitizeAssistantText, t as decideReply } from "./assistant-reply-BcJj_ORj.js";
24
- import { A as requireSupportedEventMatch, B as readAutomationResult, C as eventNamespaceSchema, D as registeredEventTypeSchema, E as registeredEventMatchSchema, I as FINISH_AUTOMATION_RUN_TOOL_NAME, L as automationResultSchema, O as registeredResourceTypeSchema, T as pluginSupportsEvent, V as remindMissingAutomationResult, _ as WORKSPACE_SNAPSHOT_FAILED_EVENT, b as workspaceSnapshotWatch, d as getEventCatalog, k as requireEventIdentifier, n as markConversationsStopped, o as enqueueEventNotification, p as requireSlackChannelMessageScope, t as getConversationStoppedAtMs, v as WORKSPACE_SNAPSHOT_READY_EVENT, w as hasEventCatalogEntries, x as automationEventCatalog, y as workspaceSnapshotFinishedEvent } from "./session-stop-B9RRGC-P.js";
25
- import { a as createSandboxSession, c as postinstall, d as getSandboxResources, i as bindSandboxFileSystem, l as setSnapshotSpanAttributes, n as isMissingError, o as stopSession, r as resolve$1, s as dependencies } from "./resolve-BXShI336.js";
26
- import { a as getVercelConversationWorkQueue, f as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-BYHonCAH.js";
27
- import { E as stopConversationWork } from "./store-C_mHwAnR.js";
28
- 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-DJSRo2cL.js";
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 { Sandbox } from "@vercel/sandbox";
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
- stream.result().then((finalMessage) => {
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 = buildChatEndAttributes(finalMessage, mode);
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. If asked to post elsewhere or create a new top-level channel post, explain the limitation instead of calling a tool, and do not present the text as delivered. Slack read tools can target other public channels with `channel_id`.",
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 Vercel has a short failure. */
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) || isSandboxApiTransientError(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 sandbox = await getWorkspaceSnapshotBuilder(build.sandboxName, signal);
3041
- const command = await sandbox.getCommand(build.commandId, { signal });
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 sandbox.snapshot({ signal });
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 Sandbox.create({
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 sandbox = await getWorkspaceSnapshotBuilder(build.sandboxName, phaseSignal);
3178
- const session = createSandboxSession(sandbox);
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 command = await sandbox.runCommand({
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: command.cmdId,
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 (!isSandboxApiTransientError(error)) throw error;
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 adaptSandbox = (vercelSandbox) => createSandboxSession(vercelSandbox, { onUnavailable: invalidateSession });
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, sandboxCredentials, initialSandboxName, workspace, signal) => {
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 adaptSandbox(await Sandbox.create({
3721
- timeout: timeoutMs,
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
- source: {
3728
- type: "snapshot",
3729
- snapshotId
3730
- },
3804
+ snapshotId,
3731
3805
  ...resources ? { resources } : void 0,
3732
- ...sandboxCredentials ?? {},
3733
- ...sandboxFetchOptions(signal)
3734
- }));
3806
+ scopeSignal: signal
3807
+ });
3735
3808
  } catch (error) {
3736
- if (!isSnapshottingError(error) || attempt === 2) throw error;
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, sandboxCredentials, sandboxName, signal } = params;
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: adaptSandbox(await Sandbox.create({
3759
- timeout: timeoutMs,
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
- ...sandboxCredentials ?? {},
3768
- ...sandboxFetchOptions(signal)
3769
- })),
3840
+ scopeSignal: signal
3841
+ }),
3770
3842
  snapshot
3771
3843
  };
3772
3844
  }
3773
3845
  try {
3774
3846
  return {
3775
- session: await createSandboxFromSnapshot(snapshot.snapshotId, sandboxCredentials, sandboxName, params.workspace, signal),
3847
+ session: await createSandboxFromSnapshot(snapshot.snapshotId, sandboxName, params.workspace, signal),
3776
3848
  snapshot
3777
3849
  };
3778
3850
  } catch (error) {
3779
- if (!isMissingError(error)) throw error;
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, sandboxCredentials, sandboxName, params.workspace, signal),
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 () => adaptSandbox(await Sandbox.get({
3968
+ }, async () => await getSandboxProvider().getSession({
3900
3969
  name: ref.id,
3901
- resume: true,
3902
- ...sandboxCredentials ?? {},
3903
- ...sandboxFetchOptions(signal)
3904
- })));
3970
+ onUnavailable: invalidateSession,
3971
+ scopeSignal: signal
3972
+ }));
3905
3973
  } catch (error) {
3906
- if (isSandboxMissingError(error)) {
3974
+ if (getSandboxProvider().errors.isMissing(error)) {
3907
3975
  sandboxRef = void 0;
3908
3976
  return null;
3909
3977
  }
3910
- if (isSandboxUnavailableError(error)) {
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 (isSandboxUnavailableError(error)) throw error;
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) return 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) return hintedSandbox;
3943
- return await createFreshSandbox(signal);
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 (isSandboxUnavailableError(error)) throw error;
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
- try {
5169
- const response = await executeBash({
5170
- command,
5171
- cwd,
5172
- ...env ? { env } : void 0,
5173
- ...timeoutMs ? { timeoutMs } : void 0,
5174
- ...context.signal ? { signal: context.signal } : void 0
5175
- });
5176
- setSpanAttributes({
5177
- "process.exit.code": response.exitCode,
5178
- "app.sandbox.stdout_bytes": Buffer.byteLength(response.stdout ?? "", "utf8"),
5179
- "app.sandbox.stderr_bytes": Buffer.byteLength(response.stderr ?? "", "utf8"),
5180
- ...response.aborted ? { "error.type": "outcome_unknown" } : response.exitCode !== 0 ? { "error.type": "nonzero_exit" } : {}
5181
- });
5182
- setSpanStatus(response.exitCode === 0 ? "ok" : "error");
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 (isSandboxUnavailableError(error)) throw createSandboxUnavailableToolError(params.toolName, error);
5383
- if (isSandboxCommandStreamInterruptedError(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 });
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 (isSandboxUnavailableError(error)) throw createSandboxUnavailableToolError(operation, error);
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
- "Junior had a credential lease for this grant and forwarded the request. Do not diagnose this as a missing user token or a local Junior runtime block.",
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: Junior's shared ${plugin.manifest.displayName} account cannot use it`);
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 slash.") }),
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, Junior 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.",
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, Junior activates it on demand.").optional(),
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(), z.object({
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().superRefine((subscription, context) => {
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
- if (input.namespace === "junior" && input.resourceType === "timer") throw new ToolInputError("Use watchTimer to create a timer Watch.");
7851
- if (input.namespace === "slack") throw new ToolInputError("Slack channel messages can trigger only an event automation in that channel. Use createEventAutomation.");
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 = requireSupportedEventMatch(catalog, {
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 is no longer supported by the catalog. */
8077
+ /** Reject an event-automation trigger that cannot work with the enabled plugins. */
8023
8078
  function requireSupportedEventAutomationTrigger(catalog, trigger) {
8024
- const plugins = automationEventCatalog(catalog);
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
- function eventAutomationTriggerAvailable(task, catalog) {
8066
- const registration = automationEventCatalog(catalog)[task.trigger.namespace];
8067
- return Boolean(registration && task.trigger.events.every((eventType) => registration.resourceTypes.some((resourceType) => resourceType.supportedEvents.includes(eventType))));
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: eventAutomationTriggerAvailable(task, catalog)
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 filters = Object.entries(task.trigger.match ?? {}).map(([key, value]) => `${key} = ${JSON.stringify(value)}`);
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: automation.trigger.available ? "ready" : "unavailable",
8118
- trigger: [
8119
- task.trigger.label,
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 cannot receive events until its plugin event is enabled again. Public automations can also be updated or deleted by id from another destination in the same workspace.",
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 Junior 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.",
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 Junior 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.",
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 Junior 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.",
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>`), Junior slack reference (`slack:C123`), or a channel name Junior already knows in this workspace.");
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 Junior slack reference (\`slack:C123\`), or a channel name Junior already knows.`);
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 Junior has already seen in this workspace. Public search can discover channels; plain names are not scanned from Slack.`);
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 Junior conversations."
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 withTimeout(generateText({
13348
- model: provider.chat(modelId),
13349
- prompt: query,
13350
- tools: { [SEARCH_TOOL_NAME]: provider.tools.parallelSearch({
13351
- mode: "agentic",
13352
- maxResults
13353
- }) },
13354
- toolChoice: {
13355
- type: "tool",
13356
- toolName: SEARCH_TOOL_NAME
13357
- },
13358
- abortSignal: controller.signal
13359
- }), SEARCH_TIMEOUT_MS, "webSearch", { onTimeout: () => controller.abort() })).toolResults, maxResults);
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, Junior will continue automatically."
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 Junior agent action.
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 Junior conversation is not an untrusted destination merely because it is a public or multi-user channel.
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-5VNK_yYC.js").then((n) => n.n);
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 { toolInvocationDestination as $, listThreadReplies as A, stopConversationSession as B, requestAttachmentDeletion as C, resolveSlackChannelIdFromMessage as D, readSlackRawMessageContext as E, AutomationEditError as F, conversationSubtree as G, recordSubagentStarted as H, eventAutomationTriggerAvailable as I, ingestEvent as J, conversationSubtreeColumns as K, effectiveTaskOutcomes as L, logScheduledAutomationRunSkipped as M, scheduledAutomationRunAttributes as N, resolveSlackChannelIdFromThreadId as O, editEventAutomation as P, actorFromRun as Q, resolveTaskOutcomes as R, readLiveAttachment as S, parseSlackThreadId as T, listChildAgents as U, recordSubagentEnded as V, listUnreportedSiblingAgents as W, withoutSavedSteeringMessages as X, buildSteeringPiMessage as Y, RetryableDeliveryError as Z, unpublishedArtifactHeaders as _, finalizeMcpAuthorization as a, renderBlockText as b, deleteMcpServerSessionId as c, getMcpStoredOAuthCredentials as d, readBlockedReport 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, deleteMcpAuthSession as o, latestProgressStatus as p, processWorkspaceSnapshotJob as q, createContextCompactor as r, deleteMcpAuthSessionsForUserProvider as s, createAgentRunner as t, shouldEmitDevAgentTrace as tt, getMcpAuthSession as u, lookupSlackUserProfile as v, storeAttachment as w, collectAttachmentGarbage as x, renderAttachmentText as y, stopChildAgentsOf as z };
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 };