@sentry/junior 0.270.0 → 0.272.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 (75) hide show
  1. package/dist/{actor-CP9K2Idu.js → actor-B4DYygOB.js} +1 -1
  2. package/dist/{adapter-BQNTKVTF.js → adapter-BDYDi1F9.js} +1 -1
  3. package/dist/{admin-CKVEoXa4.js → admin-Dj7EFycG.js} +1 -1
  4. package/dist/{agent-runner-MSQSMFkq.js → agent-runner-Cl6Usx2Y.js} +336 -280
  5. package/dist/api/schema.d.ts +2 -2
  6. package/dist/api/schema.js +5 -5
  7. package/dist/api.d.ts +1 -1
  8. package/dist/api.js +81 -37
  9. package/dist/{app-Bz8t4P8p.d.ts → app-DjZblE2J.d.ts} +8 -2
  10. package/dist/app.d.ts +1 -1
  11. package/dist/app.js +74 -40
  12. package/dist/{interruption-marker-CdblrIQK.js → assistant-reply-DN2w6JL_.js} +2 -8
  13. package/dist/{automation-Dwh_xcqM.js → automation-CV7g5h3A.js} +1 -1
  14. package/dist/{briefs-DNFzFFVx.js → briefs-PysAqnjV.js} +4 -4
  15. package/dist/{catalog-runtime-Bdym_wKy.js → catalog-runtime-BNeCWIaF.js} +1 -1
  16. package/dist/cli/chat.js +14 -14
  17. package/dist/cli/check.js +3 -3
  18. package/dist/cli/main.js +3 -3
  19. package/dist/cli/plugins.js +4 -4
  20. package/dist/cli/snapshot-create.js +4 -4
  21. package/dist/cli/upgrade.d.ts +1 -1
  22. package/dist/cli/upgrade.js +3 -3
  23. package/dist/{client-B2MjENki.js → client-FRphcDWW.js} +2 -2
  24. package/dist/{config-Dm3pWRqY.js → config-BUP9wjiR.js} +3 -3
  25. package/dist/{connections-0BBhiD-p.js → connections-CesHau9u.js} +10 -10
  26. package/dist/{conversation-AhOVzN_k.js → conversation-BtQzLoK8.js} +12 -1
  27. package/dist/{conversation-privacy-C1pJ89rs.js → conversation-privacy-DiGvA9a3.js} +1 -1
  28. package/dist/{credential-sync-BRiWYs6_.js → credential-sync-D2odJC30.js} +15 -15
  29. package/dist/{credentialed-BeBaJMZ_.js → credentialed-CgTulRDH.js} +33 -26
  30. package/dist/{db-BYOuu6v2.d.ts → db-BPLmOwXf.d.ts} +11 -1
  31. package/dist/{executor-BB6eJkD4.js → executor-DGDpyegI.js} +30 -7
  32. package/dist/instrumentation.js +2 -2
  33. package/dist/{job-queue-DiaXoSDg.js → job-queue-CjB97sii.js} +2 -2
  34. package/dist/{list-BTDRxkOg.js → list-JZUP1yog.js} +37 -53
  35. package/dist/{logging-C6EdT6PP.js → logging-CjkDr-jP.js} +1 -1
  36. package/dist/message-D9y8PKA1.js +186 -0
  37. package/dist/nitro.d.ts +1 -1
  38. package/dist/nitro.js +3 -3
  39. package/dist/{oauth-callback-server-CjFFVGqa.js → oauth-callback-server-02Pej6hj.js} +2 -2
  40. package/dist/{prompt-BPSdXYXV.js → prompt-vfceH0c-.js} +1 -1
  41. package/dist/{registry-CndmkP2P.js → registry-7XgwNgQe.js} +2 -2
  42. package/dist/{reporting-window-DRCi1Ls_.js → reporting-window-DgHgwQB3.js} +6 -1
  43. package/dist/{resolve-BkAA1wH7.js → resolve-CuuxNfWG.js} +3 -3
  44. package/dist/{result-9TJTpuYP.js → result-BRhb6iN1.js} +17 -13
  45. package/dist/{runner-BmKLSyJm.js → runner-DaWCofuS.js} +11 -11
  46. package/dist/{sandbox-egress-signals-CjLaogMo.js → sandbox-egress-signals-Bn6FA1UC.js} +1 -1
  47. package/dist/{schema-WayPSHFu.d.ts → schema-CNjAzYOw.d.ts} +28 -5
  48. package/dist/{schema-DNLJ_MzW.js → schema-D5VLF4NT.js} +13 -9
  49. package/dist/{service-account-DlhYl-Mu.js → service-account-D9vrsi8d.js} +3 -3
  50. package/dist/{service-account-D6e9cVmH.js → service-account-H45LIAG2.js} +3 -3
  51. package/dist/{session-stop-MZRgYqYH.js → session-stop-HKl0ECX0.js} +81 -153
  52. package/dist/{skills-BggTR_ue.js → skills-CsiKu3-g.js} +2 -2
  53. package/dist/{spawn-DmtlcAT_.js → spawn-DqjBxqWh.js} +2 -2
  54. package/dist/{store-BeWGgaMA.js → store-CPF2kzbu.js} +3 -3
  55. package/dist/{store-Byarin7b.js → store-DyVKH0QB.js} +47 -30
  56. package/dist/{task-queue-Dt1_ZoI_.js → task-queue-BbQXCcNX.js} +3 -3
  57. package/dist/{task-runner-DyKqAPpm.js → task-runner-ChzW5E7R.js} +7 -7
  58. package/dist/{thread-state-BHBLMvgb.js → thread-state-Ds8JTsX6.js} +5 -5
  59. package/dist/{turn-failure-response-DWXy_0oJ.js → turn-failure-response-DCMvjsA0.js} +15 -10
  60. package/dist/{turn-lifecycle-AiXkVqCB.js → turn-lifecycle-DM_77q33.js} +1 -1
  61. package/dist/{turn-session-routing-B9KLBhaT.js → turn-session-routing-BV_gX7n3.js} +13 -13
  62. package/dist/{validation-BW60Vtx_.js → validation-DcGelbBi.js} +1 -1
  63. package/dist/{version-CivPYmkH.js → version-C48azPKq.js} +1 -1
  64. package/dist/version.js +1 -1
  65. package/dist/{viewer-BTgAfdUg.js → viewer-BCRuO8Wg.js} +26 -10
  66. package/dist/{work-Bjm52fHo.js → work-zxkmbJAp.js} +27 -11
  67. package/dist/{worker-CMbgtHLu.js → worker-CNNxHF1V.js} +6 -6
  68. package/migrations/0071_review_item_turn.sql +1 -0
  69. package/migrations/0072_conversation_read_positions.sql +10 -0
  70. package/migrations/meta/0071_snapshot.json +4003 -0
  71. package/migrations/meta/0072_snapshot.json +4064 -0
  72. package/migrations/meta/_journal.json +14 -0
  73. package/package.json +4 -4
  74. package/dist/message-DsjiWRVg.js +0 -59
  75. package/migrations/AGENTS.md +0 -17
@@ -1,45 +1,45 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
2
- import { $ as saveEventAutomation, A as readAutomationRuns, Ar as trimTrailingAssistantMessages, B as readScheduledAutomation, Br as estimateTextTokens, Bt as recordMcpProviderConnected, C as readAutomationExecutionByConversationId, Cn as loadTurnCheckpoint, Cr as isAssistantMessage, Ct as requireEventIdentifier, D as readAutomationExecutionStatusHours, Dr as normalizeToolNameFromResult, Dt as loadConnectedMcpProviders, E as readAutomationExecutionStatusDays, Er as isToolResultMessage, Fr as buildDeterministicTurnId, Ft as recordAttachmentsDelivered, Hr as getAgentContextInputLimitTokens, Ht as recordToolExecutionStarted, I as createScheduledAutomation, J as deleteEventAutomation, Jr as historyItemFromPiMessage, L as deleteScheduledAutomation, Mr as SESSION_CONTEXT_SECTION_TAG, Mt as loadTurnRoute, Nr as TURN_CONTEXT_TAG, Nt as openConversationProjection, O as readAutomationExecutionSummaries, Or as retainRuntimeTurnContext, Ot as loadConversationProjection, Pt as recordAgentsInstructionsUpdated, Q as parseEventAutomationRow, Qt as resolveTaskTitle, Rt as recordAuthorizationRequested, Sn as continuableMessages, St as registeredResourceTypeSchema, T as readAutomationExecutionHours, Tr as isToolResultError, Ut as recordTurnRoute, V as saveScheduledAutomation, Vr as getAgentContextCompactionTriggerTokens, Wr as isExperimentalFeatureEnabled, X as getEventAutomation, Xr as getConfigDefaults, Yr as piMessageFromHistoryItem, Z as listDeletedEventAutomationsCreatedBy, Zt as fallbackShortTitle, _n as abandonReplacedPendingAuth, _r as extractAssistantText, _t as eventWatchUnavailable, at as listAutomationVersions, br as getUserMessageInstructionText, bt as registeredEventTriggerProblems, c as getDispatchIdForConversation, cr as TURN_LIMIT_WRAP_UP_MESSAGE, dn as PluginCredentialFailureError, dr as TurnToolCallLimitExceededError, et as setEventAutomationStatus, fn as createPluginAuthOrchestration, ft as automationEventCatalog, gn as AuthorizationPauseError, gt as eventNamespaceSchema, hn as AuthorizationFlowDisabledError, hr as CODEMODE_TOOL_NAME, jr as REQUEST_CONTEXT_SECTION_TAG, k as readAutomationExecutions, kr as stripRuntimeTurnContext, kt as loadLastModelProfile, l as getDispatchInputMessageId, lr as TurnBudgetExceededError, lt as automationRevision, mn as AuthPausePersistenceError, mr as isTurnExecutionLimitExceededError, ot as readAutomationVersion, pn as authorizationId, pr as createTurnLimitGate, pt as describeRegisteredEventTrigger, q as createEventAutomation, rt as automationDefinition, st as sameDefinitionValue, t as resolveConversationRouting, u as getDispatchRecord, un as createPluginEgress, ur as TurnSliceLimitExceededError, ut as requireAutomationRevision, vn as canReusePendingAuthLink, vr as getPiMessageRole, vt as hasEventCatalogEntries, w as readAutomationExecutionDays, wn as saveTurnCheckpoint, wr as isContinuablePiBoundary, wt as requireValidEventTrigger, x as emptyAutomationRunWindows, xr as hasRuntimeTurnContext, xt as registeredEventTypeSchema, yr as getTerminalAssistantMessages, yt as registeredEventMatchSchema, z as parseScheduledAutomationRow, zt as recordGuardianActionReviewed } from "./turn-session-routing-B9KLBhaT.js";
3
- import { _ as getProviderErrorAttributes, a as completeText, b as getGatewayApiKey, 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 resolveGatewayCredential, y as isProviderRetryError } from "./client-B2MjENki.js";
4
- import { n as botConfig, v as normalizeSlackEmojiName } from "./config-Dm3pWRqY.js";
5
- import { B as isRecord$4, C as summarizeMessageText, E as withSpan, H as toOptionalString, S as setTags, T as withLogContext, _ as runBestEffort, a as extractGenAiUsageSummary, b as setSpanAttributes, f as logError, g as normalizeGenAiFinishReason, h as logWarn, i as extractGenAiUsageAttributes, l as getLogContextAttributesForSpan, m as logInfo, p as logException, u as getTracePropagationHeaders, v as serializeGenAiAttribute, x as setSpanStatus, z as normalizeIdentityEmail } from "./logging-C6EdT6PP.js";
2
+ import { $ as saveEventAutomation, A as readAutomationRuns, Ar as trimTrailingAssistantMessages, B as readScheduledAutomation, Br as estimateTextTokens, Bt as recordMcpProviderConnected, C as readAutomationExecutionByConversationId, Cn as loadTurnCheckpoint, Cr as isAssistantMessage, Ct as requireEventIdentifier, D as readAutomationExecutionStatusHours, Dr as normalizeToolNameFromResult, Dt as loadConnectedMcpProviders, E as readAutomationExecutionStatusDays, Er as isToolResultMessage, Fr as buildDeterministicTurnId, Ft as recordAttachmentsDelivered, Hr as getAgentContextInputLimitTokens, Ht as recordToolExecutionStarted, I as createScheduledAutomation, J as deleteEventAutomation, Jr as historyItemFromPiMessage, L as deleteScheduledAutomation, Mr as SESSION_CONTEXT_SECTION_TAG, Mt as loadTurnRoute, Nr as TURN_CONTEXT_TAG, Nt as openConversationProjection, O as readAutomationExecutionSummaries, Or as retainRuntimeTurnContext, Ot as loadConversationProjection, Pt as recordAgentsInstructionsUpdated, Q as parseEventAutomationRow, Qt as resolveTaskTitle, Rt as recordAuthorizationRequested, Sn as continuableMessages, St as registeredResourceTypeSchema, T as readAutomationExecutionHours, Tr as isToolResultError, Ut as recordTurnRoute, V as saveScheduledAutomation, Vr as getAgentContextCompactionTriggerTokens, Wr as isExperimentalFeatureEnabled, X as getEventAutomation, Xr as getConfigDefaults, Yr as piMessageFromHistoryItem, Z as listDeletedEventAutomationsCreatedBy, Zt as fallbackShortTitle, _n as abandonReplacedPendingAuth, _r as extractAssistantText, _t as eventWatchUnavailable, at as listAutomationVersions, br as getUserMessageInstructionText, bt as registeredEventTriggerProblems, c as getDispatchIdForConversation, cr as TURN_LIMIT_WRAP_UP_MESSAGE, dn as PluginCredentialFailureError, dr as TurnToolCallLimitExceededError, et as setEventAutomationStatus, fn as createPluginAuthOrchestration, ft as automationEventCatalog, gn as AuthorizationPauseError, gt as eventNamespaceSchema, hn as AuthorizationFlowDisabledError, hr as CODEMODE_TOOL_NAME, jr as REQUEST_CONTEXT_SECTION_TAG, k as readAutomationExecutions, kr as stripRuntimeTurnContext, kt as loadLastModelProfile, l as getDispatchInputMessageId, lr as TurnBudgetExceededError, lt as automationRevision, mn as AuthPausePersistenceError, mr as isTurnExecutionLimitExceededError, ot as readAutomationVersion, pn as authorizationId, pr as createTurnLimitGate, pt as describeRegisteredEventTrigger, q as createEventAutomation, rt as automationDefinition, st as sameDefinitionValue, t as resolveConversationRouting, u as getDispatchRecord, un as createPluginEgress, ur as TurnSliceLimitExceededError, ut as requireAutomationRevision, vn as canReusePendingAuthLink, vr as getPiMessageRole, vt as hasEventCatalogEntries, w as readAutomationExecutionDays, wn as saveTurnCheckpoint, wr as isContinuablePiBoundary, wt as requireValidEventTrigger, x as emptyAutomationRunWindows, xr as hasRuntimeTurnContext, xt as registeredEventTypeSchema, yr as getTerminalAssistantMessages, yt as registeredEventMatchSchema, z as parseScheduledAutomationRow, zt as recordGuardianActionReviewed } from "./turn-session-routing-BV_gX7n3.js";
3
+ import { _ as getProviderErrorAttributes, a as completeText, b as getGatewayApiKey, 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 resolveGatewayCredential, y as isProviderRetryError } from "./client-FRphcDWW.js";
4
+ import { n as botConfig, v as normalizeSlackEmojiName } from "./config-BUP9wjiR.js";
5
+ import { B as isRecord$4, C as summarizeMessageText, E as withSpan, H as toOptionalString, S as setTags, T as withLogContext, _ as runBestEffort, a as extractGenAiUsageSummary, b as setSpanAttributes, f as logError, g as normalizeGenAiFinishReason, h as logWarn, i as extractGenAiUsageAttributes, l as getLogContextAttributesForSpan, m as logInfo, p as logException, u as getTracePropagationHeaders, v as serializeGenAiAttribute, x as setSpanStatus, z as normalizeIdentityEmail } from "./logging-CjkDr-jP.js";
6
6
  import { g as withActiveSpan, i as getActiveSpan, m as startInactiveSpan } from "./sentry-MDkYAVPV.js";
7
- 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-C1pJ89rs.js";
7
+ 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-DiGvA9a3.js";
8
8
  import { a as formatModelProfile, c as modelProfileSchema, l as profileConfig, n as ModelProfileNotConfiguredError, o as formatModelProfiles, r as boundProfile, s as modelIdForProfile, u as TURN_REASONING_LEVELS } from "./model-profile-B998sjVd.js";
9
- import { d as parseSlackChannelReferenceId, f as parseSlackTeamId, m as parseSlackMessageTs, n as createSlackActor, o as isUserActor, p as parseSlackUserId, u as parseSlackChannelId } from "./actor-CP9K2Idu.js";
10
- import { C as getSqlExecutor, M as resolveActorIdentityId, Q as sameDestination, S as getDb, U as addAgentTurnUsage, W as agentTurnCostUsd, X as parseDestination, a as readActorIdentityFromSql, b as getConversationMessageSearchStore, f as identityAvatarUrl, h as readUserAvatarUrls, i as readActorIdentity, j as SYSTEM_IDENTITY_ID, q as hasAgentTurnUsage, x as getConversationStore, y as getConversationEventStore } from "./viewer-BTgAfdUg.js";
9
+ import { d as parseSlackChannelReferenceId, f as parseSlackTeamId, h as parseSlackMessageTs, n as createSlackActor, o as isUserActor, p as parseSlackUserId, u as parseSlackChannelId } from "./actor-B4DYygOB.js";
10
+ import { C as getSqlExecutor, M as resolveActorIdentityId, Q as sameDestination, S as getDb, U as addAgentTurnUsage, W as agentTurnCostUsd, X as parseDestination, a as readActorIdentityFromSql, b as getConversationMessageSearchStore, f as identityAvatarUrl, h as readUserAvatarUrls, i as readActorIdentity, j as SYSTEM_IDENTITY_ID, q as hasAgentTurnUsage, x as getConversationStore, y as getConversationEventStore } from "./viewer-BCRuO8Wg.js";
11
11
  import { a as juniorAgentInvocations, c as juniorIdentities, d as juniorDestinations, i as juniorAgentBindings, l as juniorUsers, s as juniorConversations } from "./agent-invocations-C1RNOCs8.js";
12
- import { T as juniorArtifacts, d as juniorAutomations, f as juniorStats, g as juniorConversationBriefs, l as juniorAutomationRuns, s as juniorReviewItemSlackCards, w as juniorAttachments, x as juniorConversationAnnotations } from "./executor-BB6eJkD4.js";
12
+ import { E as juniorArtifacts, S as juniorConversationAnnotations, T as juniorAttachments, _ as juniorConversationBriefs, d as juniorAutomations, f as juniorStats, l as juniorAutomationRuns, s as juniorReviewItemSlackCards } from "./executor-DGDpyegI.js";
13
13
  import { _ as sameActorIdentity, g as instructionProvenanceFor, h as instructionActors, i as KNOWN_CONVERSATION_EVENT_TYPES, m as contextProvenance, n as detectImageMediaType, p as agentInstructionProvenance, r as isVisionImageMediaType } from "./media-U6Tuz6Mi.js";
14
14
  import { a as listReferenceFiles, c as soulPathCandidates, l as worldPathCandidates } from "./package-discovery-DJBompdd.js";
15
- import { c as fetchWithBoundedOAuthErrorBodies, d as actorLogContext, f as credentialContextForActor, g as credentialUserSubjectId, i as resolvePluginHeaderEnvRefs, l as getOAuthProviderErrorAttributes, s as OAuthProviderError } from "./registry-CndmkP2P.js";
16
- import { n as pluginCatalogRuntime } from "./catalog-runtime-Bdym_wKy.js";
17
- import { a as parseSkillInvocation, i as parseSkillFile, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-BggTR_ue.js";
18
- import { $ as loadSnapshotsForProfile, $n as sandboxSkillDir, $t as workspaceRepoCheckoutPath, A as updateReviewItemContent, An as normalizeSlackConversationId, B as EVERYONE_ASSIGNEE, Bn as getDashboardTaskLink, Bt as clearSandboxEgressSignals, C as getOpenReviewItemByDedupeKey, Cn as SlackActionError, Ct as openSlackDirectMessage, Dn as getSlackClient, Et as postSlackMessage, Ft as wrapSandboxSetupError, G as deleteWorkspace, Gn as buildNonInteractiveShellScript, H as resolveAssignee, Hn as ToolInputError, Ht as consumeSandboxEgressPermissionDeniedSignal, I as readReviewItemAgentScope, Ir as conversationNoteEvent, It as WorkspaceSnapshotNotReadyError, J as listWorkspaces, Jn as SANDBOX_DATA_ROOT, Jt as resolveSandboxCommandEnvironment, K as getWorkspace, Kn as runNonInteractiveCommand, L as requireReviewItemAssignees, Ln as getDashboardConversationLink, Lt as getWorkspaceSnapshotNotReadyError, Mn as withSlackRetries, Mr as JUNIOR_NATIVE_EVENT_NAMESPACE, Mt as isAbortError, N as canAgentChangeReviewItem, Nn as sleep, Nt as isAlreadyExistsError, O as searchReviewItems, On as isConversationScopedChannel, Or as defaultTimezone, Ot as updateSlackMessage, P as canReadReviewItem, Pt as throwSandboxOperationError, Q as invalidateReadySnapshot, Qn as SANDBOX_WORKSPACE_ROOT, Qt as tryWorkspaceRepoCheckoutPath, R as requireReviewItemLinks, Rt as isWorkspaceSnapshotNotReadyError, S as dismissOpenReviewItems, St as getSlackMessagePermalink, T as insertReviewItem, Tn as getFilePermalink, Tr as createPluginAnnotations, U as resolveAssignees, Un as PluginToolDeniedError, Ut as createSandboxEgressCredentialToken, V as automationCreatorUserId, Vt as consumeSandboxEgressAuthRequiredSignal, W as createWorkspace, Wn as buildCommandScript, X as updateWorkspace, Xn as SANDBOX_REPOS_ROOT, Yn as SANDBOX_JUNIOR_ROOT, Z as WorkspaceValidationError, Zn as SANDBOX_SKILLS_ROOT, Zt as SANDBOX_RUNTIME, an as STOP_WATCHING_TOOL_NAME, at as ensureDockerDaemon, b as closeReviewItem, br as matchSlackAttachments, bt as addReactionToMessage, d as getPluginTools, dn as deliverWatch, en as resolveChannelCapabilities, er as sandboxSkillFile, et as setWorkspaceSnapshot, f as getPluginUserPromptContributions, fn as findMatchingWatches, ft as resolveBaseUrl, gt as normalizeSlackReplyMarkdown, in as RESOURCE_WATCH_TOOL_SOURCE, it as isStale, j as PLUGIN_REVIEW_ITEM_KEY_PREFIX, jn as runWithSlackInstallationToken, kr as resolveUserTimezone, kt as uploadFilesToConversation, ln as createTimerWatch, lt as deliverOAuthAuthorization, mn as listWatches, mt as escapeSlackMrkdwnText, n as createUserTokenStore, nn as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, nt as create, o as createPluginHookRunner, on as cancelSubscriptions, ot as getSandboxProvider, p as getPlugins, pn as getWatch, q as getWorkspaceByName, qn as SANDBOX_COMMAND_PATH, qt as buildSandboxEgressNetworkPolicy, r as getOAuthAccountProviders, rn as RESOURCE_SUBSCRIPTION_MAX_TTL_MS, rt as hash, sn as cancelWatch, tn as getSlackToolContext, tr as sandboxSkillPathResolution, tt as setWorkspaceSnapshotBuild, u as getPluginSystemPromptContributions, un as createWatch, ut as formatProviderLabel, vt as slackMention, w as getReviewItem, wn as downloadPrivateSlackFile, wr as saveObjectAnnotations, xt as deleteSlackMessage, zn as getDashboardReviewItemLink, zt as workspaceSnapshotNotReadyUserMessage } from "./credentialed-BeBaJMZ_.js";
15
+ import { c as fetchWithBoundedOAuthErrorBodies, d as actorLogContext, f as credentialContextForActor, g as credentialUserSubjectId, i as resolvePluginHeaderEnvRefs, l as getOAuthProviderErrorAttributes, s as OAuthProviderError } from "./registry-7XgwNgQe.js";
16
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-BNeCWIaF.js";
17
+ import { a as parseSkillInvocation, i as parseSkillFile, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-CsiKu3-g.js";
18
+ import { $ as loadSnapshotsForProfile, $n as sandboxSkillDir, $t as workspaceRepoCheckoutPath, A as updateReviewItemContent, An as normalizeSlackConversationId, B as EVERYONE_ASSIGNEE, Bn as getDashboardTaskLink, Bt as clearSandboxEgressSignals, C as getOpenReviewItemByDedupeKey, Cn as SlackActionError, Ct as openSlackDirectMessage, Dn as getSlackClient, Et as postSlackMessage, Ft as wrapSandboxSetupError, G as deleteWorkspace, Gn as buildNonInteractiveShellScript, H as resolveAssignee, Hn as ToolInputError, Ht as consumeSandboxEgressPermissionDeniedSignal, I as readReviewItemAgentScope, Ir as conversationNoteEvent, It as WorkspaceSnapshotNotReadyError, J as listWorkspaces, Jn as SANDBOX_DATA_ROOT, Jt as resolveSandboxCommandEnvironment, K as getWorkspace, Kn as runNonInteractiveCommand, L as requireReviewItemAssignees, Ln as getDashboardConversationLink, Lt as getWorkspaceSnapshotNotReadyError, Mn as withSlackRetries, Mr as JUNIOR_NATIVE_EVENT_NAMESPACE, Mt as isAbortError, N as canAgentChangeReviewItem, Nn as sleep, Nt as isAlreadyExistsError, O as searchReviewItems, On as isConversationScopedChannel, Or as defaultTimezone, Ot as updateSlackMessage, P as canReadReviewItem, Pt as throwSandboxOperationError, Q as invalidateReadySnapshot, Qn as SANDBOX_WORKSPACE_ROOT, Qt as tryWorkspaceRepoCheckoutPath, R as requireReviewItemLinks, Rt as isWorkspaceSnapshotNotReadyError, S as dismissOpenReviewItems, St as getSlackMessagePermalink, T as insertReviewItem, Tn as getFilePermalink, Tr as createPluginAnnotations, U as resolveAssignees, Un as PluginToolDeniedError, Ut as createSandboxEgressCredentialToken, V as automationCreatorUserId, Vt as consumeSandboxEgressAuthRequiredSignal, W as createWorkspace, Wn as buildCommandScript, X as updateWorkspace, Xn as SANDBOX_REPOS_ROOT, Yn as SANDBOX_JUNIOR_ROOT, Z as WorkspaceValidationError, Zn as SANDBOX_SKILLS_ROOT, Zt as SANDBOX_RUNTIME, an as STOP_WATCHING_TOOL_NAME, at as ensureDockerDaemon, b as closeReviewItem, br as matchSlackAttachments, bt as addReactionToMessage, d as getPluginTools, dn as deliverWatch, en as resolveChannelCapabilities, er as sandboxSkillFile, et as setWorkspaceSnapshot, f as getPluginUserPromptContributions, fn as findMatchingWatches, ft as resolveBaseUrl, gt as normalizeSlackReplyMarkdown, in as RESOURCE_WATCH_TOOL_SOURCE, it as isStale, j as PLUGIN_REVIEW_ITEM_KEY_PREFIX, jn as runWithSlackInstallationToken, kr as resolveUserTimezone, kt as uploadFilesToConversation, ln as createTimerWatch, lt as deliverOAuthAuthorization, mn as listWatches, mt as escapeSlackMrkdwnText, n as createUserTokenStore, nn as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, nt as create, o as createPluginHookRunner, on as cancelSubscriptions, ot as getSandboxProvider, p as getPlugins, pn as getWatch, q as getWorkspaceByName, qn as SANDBOX_COMMAND_PATH, qt as buildSandboxEgressNetworkPolicy, r as getOAuthAccountProviders, rn as RESOURCE_SUBSCRIPTION_MAX_TTL_MS, rt as hash, sn as cancelWatch, tn as getSlackToolContext, tr as sandboxSkillPathResolution, tt as setWorkspaceSnapshotBuild, u as getPluginSystemPromptContributions, un as createWatch, ut as formatProviderLabel, vt as slackMention, w as getReviewItem, wn as downloadPrivateSlackFile, wr as saveObjectAnnotations, xt as deleteSlackMessage, zn as getDashboardReviewItemLink, zt as workspaceSnapshotNotReadyUserMessage } from "./credentialed-CgTulRDH.js";
19
19
  import { a as withLock, i as fenceLock } from "./locks-D-0h111u.js";
20
- import { r as getStateAdapter } from "./adapter-BQNTKVTF.js";
20
+ import { r as getStateAdapter } from "./adapter-BDYDi1F9.js";
21
21
  import { i as isValidTimeZone, r as getZonedDateTimeParts, t as getFirstRunAtMs } from "./cadence-R7Em4RjE.js";
22
- import { B as removedCardSchema, J as conversationBriefSchema, K as briefLinkSchema, q as briefOutcomeStatusSchema } from "./conversation-AhOVzN_k.js";
23
- import { r as EVENT_AUTHOR_ID } from "./prompt-BPSdXYXV.js";
24
- 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-Byarin7b.js";
25
- import { a as NO_REPLY_MARKER, i as sanitizeAssistantText, n as decideReply, o as isNoReplyMarker, r as getAssistantReplyText } from "./interruption-marker-CdblrIQK.js";
26
- import { A as automationResultSchema$1, F as remindMissingAutomationResult, P as readAutomationResult, _ as WORKSPACE_SNAPSHOT_FAILED_EVENT, a as EVENT_WAIT_MS, b as workspaceSnapshotWatch, d as getEventCatalog, k as FINISH_AUTOMATION_RUN_TOOL_NAME, n as markConversationsStopped, o as enqueueEventNotification, p as requireSlackChannelMessageScope, t as getConversationStoppedAtMs, v as WORKSPACE_SNAPSHOT_READY_EVENT, w as resolveSlackReplyTarget, y as workspaceSnapshotFinishedEvent } from "./session-stop-MZRgYqYH.js";
27
- import { C as userCustomizationTextSchema, b as webMessageId, g as formatUserInputAnswer, h as buttonUserInputField, m as USER_INPUT_NOTE, p as USER_INPUT_LIMITS, s as sumUtcHoursIntoSixHours, v as normalizeUserInputAnswer, x as USER_CUSTOMIZATION_MAX_CHARS, y as userInputRequestSchema } from "./reporting-window-DRCi1Ls_.js";
28
- import { a as setSnapshotSpanAttributes, i as postinstall, n as resolve$1, r as dependencies, s as getSandboxResources } from "./resolve-BkAA1wH7.js";
29
- import { a as getVercelConversationWorkQueue, f as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-DiaXoSDg.js";
30
- import { D as stopConversationWork, n as appendAndEnqueueExclusiveInboundMessage, r as appendAndEnqueueInboundMessage } from "./store-BeWGgaMA.js";
31
- 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-D6e9cVmH.js";
32
- import { A as SCHEDULED_AUTOMATION_SYSTEM_ACTOR, D as taskOutcomeInputSchema, E as automationTitleSchema, F as scheduleIntentSchema, I as weekdaySchema, N as ScheduleIntentError, P as compileScheduleIntent, T as automationInstructionToolSchema, k as eventAutomationTriggerSchema, l as automationListQuerySchema } from "./automation-Dwh_xcqM.js";
22
+ import { J as briefOutcomeStatusSchema, V as removedCardSchema, Y as conversationBriefSchema, q as briefLinkSchema } from "./conversation-BtQzLoK8.js";
23
+ import { r as EVENT_AUTHOR_ID } from "./prompt-vfceH0c-.js";
24
+ import { A as AgentMessagePausedError, F as CHILD_AGENT_RESULTS, I as PARENT_AGENT_TARGET, J as isTurnInputCommitLostError, L as agentNameSchema, M as AgentMessageTargetError, N as AgentNameInUseError, R as AGENT_TYPES, U as CooperativeTurnYieldError, V as formatAgentTypes, W as TurnInputCommitLostError, _ as invocationFromRow, d as getAgentInvocationMessageId, g as getLatestAgentInvocationForConversation, h as getChildAgentLockName, j as AgentMessageQueueFullError, k as AgentInvocationLimitError, t as NON_TERMINAL_AGENT_INVOCATION_STATUSES, u as getAgentInvocationIdForResult, v as isTerminalAgentInvocation } from "./store-DyVKH0QB.js";
25
+ import { a as isNoReplyMarker, i as NO_REPLY_MARKER, n as getAssistantReplyText, r as sanitizeAssistantText, t as decideReply } from "./assistant-reply-DN2w6JL_.js";
26
+ import { E as resolveSlackReplyTarget, L as readAutomationResult, M as FINISH_AUTOMATION_RUN_TOOL_NAME, N as automationResultSchema$1, R as remindMissingAutomationResult, _ as slackChannelMessageTrigger, a as EVENT_WAIT_MS, b as workspaceSnapshotFinishedEvent, d as getEventCatalog, n as markConversationsStopped, o as enqueueEventNotification, p as requireSlackChannelMessageScope, t as getConversationStoppedAtMs, v as WORKSPACE_SNAPSHOT_FAILED_EVENT, x as workspaceSnapshotWatch, y as WORKSPACE_SNAPSHOT_READY_EVENT } from "./session-stop-HKl0ECX0.js";
27
+ import { C as userCustomizationTextSchema, b as webMessageId, g as formatUserInputAnswer, h as buttonUserInputField, m as USER_INPUT_NOTE, p as USER_INPUT_LIMITS, s as sumUtcHoursIntoSixHours, v as normalizeUserInputAnswer, x as USER_CUSTOMIZATION_MAX_CHARS, y as userInputRequestSchema } from "./reporting-window-DgHgwQB3.js";
28
+ import { a as setSnapshotSpanAttributes, i as postinstall, n as resolve$1, r as dependencies, s as getSandboxResources } from "./resolve-CuuxNfWG.js";
29
+ import { a as getVercelConversationWorkQueue, f as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-CjB97sii.js";
30
+ import { D as stopConversationWork, n as appendAndEnqueueExclusiveInboundMessage, r as appendAndEnqueueInboundMessage } from "./store-CPF2kzbu.js";
31
+ 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-H45LIAG2.js";
32
+ import { A as SCHEDULED_AUTOMATION_SYSTEM_ACTOR, D as taskOutcomeInputSchema, E as automationTitleSchema, F as scheduleIntentSchema, I as weekdaySchema, N as ScheduleIntentError, P as compileScheduleIntent, T as automationInstructionToolSchema, k as eventAutomationTriggerSchema, l as automationListQuerySchema } from "./automation-CV7g5h3A.js";
33
33
  import { n as privateTraceResultAttributes } from "./private-trace-result-CE7_lEdq.js";
34
34
  import { streamSimple } from "@earendil-works/pi-ai/compat";
35
35
  import { createGatewayProvider } from "@ai-sdk/gateway";
36
- import { generateText } from "ai";
36
+ import { NoImageGeneratedError, generateImage, generateText } from "ai";
37
37
  import path from "node:path";
38
38
  import { isDeepStrictEqual } from "node:util";
39
39
  import { z } from "zod";
40
40
  import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
41
41
  import { and, asc, count, desc, eq, exists, gt, gte, inArray, isNotNull, isNull, lt, lte, ne, notExists, notInArray, or, sql } from "drizzle-orm";
42
- import { PluginToolInputError, createWebSource, eventMatchFieldSchema, eventReachSchema, eventSchema, eventTriggerText, localDestinationSchema, missingToolAnnotationKeys, ownedObjectAnnotationSchema, sourceSchema, stableEventMatchKey, watchResultSchema } from "@sentry/junior-plugin-api";
42
+ import { PluginToolInputError, createWebSource, eventMatchFieldSchema, eventMatchSchema, eventReachSchema, eventSchema, eventTriggerText, localDestinationSchema, missingToolAnnotationKeys, ownedObjectAnnotationSchema, sourceSchema, stableEventMatchKey, watchResultSchema } from "@sentry/junior-plugin-api";
43
43
  import { alias } from "drizzle-orm/pg-core";
44
44
  import { Agent, estimateContextTokens } from "@earendil-works/pi-agent-core";
45
45
  import fs from "node:fs/promises";
@@ -847,7 +847,7 @@ function shouldEmitDevAgentTrace() {
847
847
  return process.env.NODE_ENV === "development";
848
848
  }
849
849
  // src/chat/agent-invocations/blocked-report.ts
850
- /** Blocked report of a child agent. See "Delivery rules" in AGENTS.md. */
850
+ /** Blocked report of a child agent. */
851
851
  /** Model-facing tool that ends a child agent run as blocked. */
852
852
  const REPORT_BLOCKED_TOOL_NAME = "reportBlocked";
853
853
  const blockedReportSchema = z.object({ missing: z.string().trim().min(1) });
@@ -2217,8 +2217,8 @@ function buildTurnContextPrompt(params) {
2217
2217
  /**
2218
2218
  * Conversation notes: short facts that core attaches to a Conversation without
2219
2219
  * starting a Turn. The next Turn shows them to the model in its runtime turn
2220
- * context. A failed Turn also becomes a note for the next Turn. See
2221
- * "Conversation notes" in AGENTS.md.
2220
+ * context. A failed Turn also becomes a note for the next Turn. A note is
2221
+ * context, never user intent, and only core adds one.
2222
2222
  */
2223
2223
  /**
2224
2224
  * Tell the next Turn that a Turn failed. Pi drops a failed assistant message
@@ -6647,7 +6647,6 @@ async function enrichImagePrompt(rawPrompt) {
6647
6647
  async function shrinkImage(image, maxBytes) {
6648
6648
  const { default: sharp } = await import("sharp");
6649
6649
  const { hasAlpha } = await sharp(image.data).metadata();
6650
- const mimeType = hasAlpha ? "image/webp" : "image/jpeg";
6651
6650
  for (const edge of RESIZE_LONGEST_EDGES) {
6652
6651
  const resized = sharp(image.data).rotate().resize({
6653
6652
  width: edge,
@@ -6659,8 +6658,7 @@ async function shrinkImage(image, maxBytes) {
6659
6658
  if (data.byteLength <= maxBytes) return {
6660
6659
  image: {
6661
6660
  path: image.path,
6662
- data,
6663
- mimeType
6661
+ data
6664
6662
  },
6665
6663
  width: info.width,
6666
6664
  height: info.height
@@ -6710,17 +6708,6 @@ function extensionForMediaType$1(mediaType) {
6710
6708
  if (mediaType === "image/gif") return "gif";
6711
6709
  return "bin";
6712
6710
  }
6713
- function parseImageGenerationError(status, body, model) {
6714
- if (!body) return `image generation failed: ${status}`;
6715
- try {
6716
- const message = JSON.parse(body).error?.message?.trim();
6717
- if (!message) return `image generation failed: ${status} ${body}`;
6718
- if (message.includes("not an image model")) return `image generation failed: configured model "${model}" is not an image generation model. Set AI_IMAGE_MODEL to a compatible image model.`;
6719
- return `image generation failed: ${status} ${message}`;
6720
- } catch {
6721
- return `image generation failed: ${status} ${body}`;
6722
- }
6723
- }
6724
6711
  /** Create the image tool with sandbox artifact guidance matched to file-send capability. */
6725
6712
  function createImageGenerateTool(hooks, options, deps = {}) {
6726
6713
  return zodTool({
@@ -6737,8 +6724,10 @@ function createImageGenerateTool(hooks, options, deps = {}) {
6737
6724
  }),
6738
6725
  outputSchema: imageGenerateOutputSchema,
6739
6726
  execute: async ({ prompt, images = [] }) => {
6740
- const fetchImpl = deps.fetch ?? fetch;
6741
- const apiKey = await getGatewayApiKey();
6727
+ const gateway = createGatewayProvider({
6728
+ apiKey: await getGatewayApiKey(),
6729
+ ...deps.fetch ? { fetch: deps.fetch } : void 0
6730
+ });
6742
6731
  const model = options.modelId;
6743
6732
  const { images: inputImages, resized } = await fitImagesToRequest(await Promise.all(images.map(async (path) => ({
6744
6733
  path,
@@ -6749,58 +6738,26 @@ function createImageGenerateTool(hooks, options, deps = {}) {
6749
6738
  resize_notice: "Some input images were too large for the image model, so they were resized first. Tell the user which images were resized."
6750
6739
  } : {};
6751
6740
  const enrichedPrompt = inputImages.length > 0 ? prompt : await enrichImagePrompt(prompt);
6752
- const content = inputImages.length > 0 ? [{
6753
- type: "text",
6754
- text: enrichedPrompt
6755
- }, ...inputImages.map((image) => ({
6756
- type: "image_url",
6757
- image_url: { url: `data:${image.mimeType};base64,${image.data.toString("base64")}` }
6758
- }))] : enrichedPrompt;
6759
- const response = await fetchImpl("https://ai-gateway.vercel.sh/v1/chat/completions", {
6760
- method: "POST",
6761
- headers: {
6762
- "content-type": "application/json",
6763
- authorization: `Bearer ${apiKey}`
6764
- },
6765
- body: JSON.stringify({
6766
- model,
6767
- messages: [{
6768
- role: "user",
6769
- content
6770
- }],
6771
- modalities: ["image"]
6772
- })
6773
- });
6774
- if (!response.ok) {
6775
- const text = await response.text();
6776
- throw new Error(parseImageGenerationError(response.status, text, model));
6777
- }
6778
- const payload = await response.json();
6779
- const uploads = [];
6780
- const generatedImages = payload.choices?.[0]?.message?.images ?? [];
6781
- for (const [index, image] of generatedImages.entries()) {
6782
- let bytes = null;
6783
- let mimeType = "image/png";
6784
- const url = image.image_url?.url;
6785
- if (typeof url === "string" && url.startsWith("data:")) {
6786
- const match = url.match(/^data:([^;,]+);base64,(.+)$/);
6787
- if (!match) continue;
6788
- mimeType = match[1] ?? mimeType;
6789
- bytes = Buffer.from(match[2] ?? "", "base64");
6790
- } else if (typeof url === "string" && url.length > 0) {
6791
- const fetched = await fetchImpl(url);
6792
- if (!fetched.ok) continue;
6793
- mimeType = fetched.headers.get("content-type") ?? mimeType;
6794
- bytes = Buffer.from(await fetched.arrayBuffer());
6795
- }
6796
- if (!bytes) continue;
6797
- const extension = extensionForMediaType$1(mimeType);
6798
- uploads.push({
6799
- data: bytes,
6800
- filename: `generated-image-${Date.now()}-${index + 1}.${extension}`,
6801
- mimeType
6802
- });
6741
+ let generatedImages;
6742
+ try {
6743
+ ({images: generatedImages} = await generateImage({
6744
+ model: gateway.imageModel(model),
6745
+ prompt: inputImages.length > 0 ? {
6746
+ text: enrichedPrompt,
6747
+ images: inputImages.map((image) => image.data)
6748
+ } : enrichedPrompt,
6749
+ n: 1
6750
+ }));
6751
+ } catch (error) {
6752
+ if (NoImageGeneratedError.isInstance(error)) generatedImages = [];
6753
+ else if (error instanceof Error && error.message.includes("not an image model")) throw new Error(`image generation failed: configured model "${model}" is not an image generation model. Set AI_IMAGE_MODEL to an AI Gateway image model.`);
6754
+ else throw error;
6803
6755
  }
6756
+ const uploads = generatedImages.map((image, index) => ({
6757
+ data: Buffer.from(image.uint8Array),
6758
+ filename: `generated-image-${Date.now()}-${index + 1}.${extensionForMediaType$1(image.mediaType)}`,
6759
+ mimeType: image.mediaType
6760
+ }));
6804
6761
  if (uploads.length > 0) {
6805
6762
  const artifactRefs = await hooks.writeGeneratedArtifacts(uploads);
6806
6763
  return {
@@ -7448,10 +7405,13 @@ const messageAgentOutputSchema = juniorToolOutputSchema.extend({
7448
7405
  conversation_id: z.string().min(1).describe("Target conversation ID"),
7449
7406
  delivery: z.enum(["started", "queued"]).describe("started: the child agent starts work on the message now. queued: the target reads the message at its next step or after its current work.")
7450
7407
  });
7451
- /** Create the tool that sends one message to the parent or a child agent. */
7408
+ /**
7409
+ * Create the tool that sends one message to the parent, a child agent, or
7410
+ * another top-level agent.
7411
+ */
7452
7412
  function createMessageAgentTool(messageAgent) {
7453
7413
  return zodTool({
7454
- description: `Send a message to your parent agent or to a child agent that this conversation started. Use it to give an existing child agent more work, an answer, or a correction, and to send your parent agent a finding or a question while you keep working. A message to a child continues its history. If the child is still working, it reads the message at its next step or after its current work, and one result covers both. The result arrives later as a new task in this conversation; do not wait or poll for it. A message to your parent does not end your task. Use spawnAgent only to start a new child agent. Your text is not user approval. A child's action review reads the user's own messages in the root conversation.`,
7414
+ description: `Send a message to your parent agent or to a child agent that this conversation started. Use it to give an existing child agent more work, an answer, or a correction, and to send your parent agent a finding or a question while you keep working. A message to a child continues its history. If the child is still working, it reads the message at its next step or after its current work, and one result covers both. The result arrives later as a new task in this conversation; do not wait or poll for it. A message to your parent does not end your task. A top-level agent (its conversation is not a child agent, such as a Slack thread) can also message another top-level agent by its conversation_id, such as one from slackThreadRead. Both conversations must be public, or both private. A private one also needs the person in this Turn to be a member. The target runs the message as its own task and sends no result. Use spawnAgent only to start a new child agent. Your text is not user approval. A child's action review reads the user's own messages in the root conversation.`,
7455
7415
  exposure: "modelOnly",
7456
7416
  annotations: {
7457
7417
  destructiveHint: false,
@@ -7460,7 +7420,7 @@ function createMessageAgentTool(messageAgent) {
7460
7420
  readOnlyHint: false
7461
7421
  },
7462
7422
  inputSchema: z.object({
7463
- to: z.string().trim().min(1).describe(`"${PARENT_AGENT_TARGET}" for your parent agent, or the name or conversation_id of a child agent from spawnAgent or listAgents`),
7423
+ to: z.string().trim().min(1).describe(`"${PARENT_AGENT_TARGET}" for your parent agent, the name or conversation_id of a child agent from spawnAgent or listAgents, or the conversation_id of another top-level agent`),
7464
7424
  text: z.string().trim().min(1).max(MESSAGE_AGENT_TEXT_MAX_LENGTH).describe("Message text. Include all context the target needs.")
7465
7425
  }).strict(),
7466
7426
  outputSchema: messageAgentOutputSchema,
@@ -7477,6 +7437,7 @@ function createMessageAgentTool(messageAgent) {
7477
7437
  });
7478
7438
  } catch (error) {
7479
7439
  if (error instanceof AgentMessageTargetError) throw new ToolInputError(`${error.message}. Use listAgents to find a child agent.`, { cause: error });
7440
+ if (error instanceof AgentMessagePausedError) throw new ToolInputError(`${error.message}. Do not send it more messages. Tell the user instead.`, { cause: error });
7480
7441
  if (error instanceof AgentMessageQueueFullError) throw new ToolInputError(`${error.message}. Wait for its result, then send one message with everything it needs.`, { cause: error });
7481
7442
  if (error instanceof AgentInvocationLimitError) throw new ToolInputError(`${error.message}. Wait for active children to finish before you give more work.`, { cause: error });
7482
7443
  throw error;
@@ -8390,7 +8351,6 @@ function renderReviewItemMessage(item, change) {
8390
8351
  "",
8391
8352
  item.request && item.answer ? formatUserInputAnswer(item.request, item.answer) : "(no answer)"
8392
8353
  ].join("\n");
8393
- case "completed": return [`${personName$1(change.user)} marked ${label} done.`, ...question].join("\n");
8394
8354
  case "dismissed": return [`${personName$1(change.user)} dismissed ${label}.`, ...question].join("\n");
8395
8355
  case "taken": return [`${personName$1(change.user)} took ${label}. They are now its only assignee.`, ...question].join("\n");
8396
8356
  case "replied": return [
@@ -8605,7 +8565,7 @@ function subjectInput(subject) {
8605
8565
  /** Create the tool that adds a Review item or updates the open one. */
8606
8566
  function createAddReviewItemTool(context, services) {
8607
8567
  return zodTool({
8608
- description: `Ask a person for input, or tell them about work that needs them. This is how you ask a person anything: the item goes on the review desk, and in a Slack thread it also shows as a card with buttons. Write the question so it stands alone: a person who sees only the card must understand it. Put the recommended option first and say why in its description. Use kind \`action\` with a \`request\` to ask: a question and 1-4 fields. Each field is \`choice\` (pick one), \`multi_choice\` (pick any), or \`text\` (a short answer). For a simple decision, use one \`choice\` field. Ask for related input in one item. Use kind \`notice\` only to tell a person something. Assignees default to the person in this Turn, or to the Automation creator in an Automation run. The current Conversation is always linked. The answer arrives later as a message from the person who answered. A reply that the assignee types in the thread also closes the item when the reply answers it. If your next step needs the answer, end the Turn now: the card is your reply, so end with exactly ${NO_REPLY_MARKER}, or finish the Automation run. If other work does not need the answer, continue with it. If an open item has the same \`dedupe_key\`, this updates that item instead of adding another.`,
8568
+ description: `Ask a person for input, or tell them about work that needs them. This is how you ask a person anything: the item goes on the review desk, and in a Slack thread it also shows as a card with buttons. Write the question so it stands alone: a person who sees only the card must understand it. Put the option that you recommend first, set \`recommended: true\` on it, and say why in its description. Use kind \`action\` with a \`request\` to ask: a question and 1-4 fields. Each field is \`choice\` (pick one), \`multi_choice\` (pick any), or \`text\` (a short answer). For a simple decision, use one \`choice\` field. Ask for related input in one item. Use kind \`notice\` only to tell a person something. Assignees default to the person in this Turn, or to the Automation creator in an Automation run. The current Conversation is always linked. The answer arrives later as a message from the person who answered. A reply that the assignee types in the thread also closes the item when the reply answers it. If your next step needs the answer, end the Turn now: the card is your reply, so end with exactly ${NO_REPLY_MARKER}, or finish the Automation run. If other work does not need the answer, continue with it. If an open item has the same \`dedupe_key\`, this updates that item instead of adding another.`,
8609
8569
  annotations: {
8610
8570
  destructiveHint: false,
8611
8571
  idempotentHint: true,
@@ -8670,7 +8630,8 @@ function createAddReviewItemTool(context, services) {
8670
8630
  if (!await updateReviewItemContent(db, {
8671
8631
  ...content,
8672
8632
  id: existing.id,
8673
- nowMs: Date.now()
8633
+ nowMs: Date.now(),
8634
+ ...context.turnId && existing.addedByConversationId === context.conversationId ? { addedByTurnId: context.turnId } : void 0
8674
8635
  })) throw new ToolInputError(`Review item ${existing.id} closed. Add the item again.`);
8675
8636
  const item = await readableItem(existing.id, scope);
8676
8637
  await deliverReviewItemChange({
@@ -8687,6 +8648,7 @@ function createAddReviewItemTool(context, services) {
8687
8648
  ...content,
8688
8649
  addedByConversationId: context.conversationId,
8689
8650
  dedupeKey,
8651
+ ...context.turnId ? { addedByTurnId: context.turnId } : void 0,
8690
8652
  nowMs: Date.now(),
8691
8653
  ...scope.reader.automationId ? { automationId: scope.reader.automationId } : void 0,
8692
8654
  ...scope.tenant ? { tenant: scope.tenant } : void 0
@@ -9017,7 +8979,7 @@ function createSearchEventTypesTool(catalog) {
9017
8979
  openWorldHint: false,
9018
8980
  readOnlyHint: true
9019
8981
  },
9020
- description: "Search the event types currently enabled without creating anything. Use only when the user asks what events are supported or the required resource type or event name is unclear. Includes plugin resources and core Workspace snapshot events. namespaces gives the reach of each event. With reach \"all\" or { anyOf }, an event can start an event automation for every resource of its namespace: leave out identifier and resourceType, and narrow it with match filters from that namespace. For { anyOf }, set at least one of those filters. With reach \"resource\", the automation needs an identifier. Use watchEvents for temporary updates in the current conversation; use createAutomation with an event trigger for durable automation. This tool does not watch a resource, create an automation, or list concrete resources.",
8982
+ description: "Search the event types currently enabled without creating anything. Use only when the user asks what events are supported or the required resource type or event name is unclear. Includes plugin resources and core Workspace snapshot events. namespaces gives the reach of each event. An event automation selects its events with match filters from the matchFields of its namespace. With reach \"all\", match can be left out to run for every resource. With { anyOf }, match must set at least one of those filters. With reach \"resource\", only watchEvents can use the event. Use watchEvents for temporary updates in the current conversation; use createAutomation with an event trigger for durable automation. This tool does not watch a resource, create an automation, or list concrete resources.",
9021
8983
  inputSchema: z.object({
9022
8984
  query: z.string().nullable().describe("Optional terms matching a namespace, resource type, or event name. Resource types that match more terms come first. Empty lists all enabled event types.").optional(),
9023
8985
  namespace: eventNamespaceSchema(catalog).nullable().describe("Optional enabled plugin namespace to search within.").optional(),
@@ -9459,11 +9421,16 @@ function requireCredentialStart(automation, isCreator) {
9459
9421
  if (isCreator || automation.credentialMode !== "creator") return;
9460
9422
  throw new AutomationEditError(`This ${"schedule" in automation ? "scheduled" : "event"} automation uses its creator's credentials. Only the creator can resume it or run it now. Switch it to system credentials first.`, "credentialMode");
9461
9423
  }
9462
- /** Apply shared title, instruction, outcome, and creator credential rules. */
9424
+ /**
9425
+ * Apply shared title, instruction, outcome, and creator credential rules.
9426
+ * Anyone who can manage the Automation can change any field except turning on
9427
+ * creator credentials. A non-creator change to execution or outcomes switches
9428
+ * it to system credentials, so creator credential output stays where the
9429
+ * creator approved.
9430
+ */
9463
9431
  async function editAutomationFields(current, input, isCreator, changesExecution) {
9464
9432
  const kind = "schedule" in current ? "scheduled" : "event";
9465
9433
  if (input.credentialMode === "creator" && !isCreator) throw new AutomationEditError(`Only the ${kind} automation creator can enable creator credential use.`, "credentialMode");
9466
- if (input.outcomes !== void 0 && !isCreator) throw new AutomationEditError(`Only the ${kind} automation creator can change message destinations.`, "outcomes");
9467
9434
  let outcomes = current.outcomes;
9468
9435
  if (input.outcomes !== void 0) {
9469
9436
  for (const outcome of input.outcomes) if (typeof outcome.destination !== "string" && !current.outcomes.some((stored) => isDeepStrictEqual(stored, outcome))) throw new AutomationEditError("Use the current Destination or the creator for a new message outcome.", "outcomes");
@@ -9477,10 +9444,11 @@ async function editAutomationFields(current, input, isCreator, changesExecution)
9477
9444
  destination: outcome.destination
9478
9445
  });
9479
9446
  }
9447
+ const changesOutcomes = !isDeepStrictEqual(outcomes, current.outcomes);
9480
9448
  return {
9481
9449
  title: input.title ?? current.title,
9482
9450
  task: { text: input.instruction ?? current.task.text },
9483
- credentialMode: changesExecution && !isCreator ? "system" : input.credentialMode ?? current.credentialMode,
9451
+ credentialMode: (changesExecution || changesOutcomes) && !isCreator ? "system" : input.credentialMode ?? current.credentialMode,
9484
9452
  outcomes
9485
9453
  };
9486
9454
  }
@@ -9533,14 +9501,32 @@ function registeredEventAutomationTriggerSchema(catalog) {
9533
9501
  const plugins = automationEventCatalog(catalog);
9534
9502
  return z.object({
9535
9503
  namespace: eventNamespaceSchema(plugins),
9536
- identifier: z.string().trim().min(1).max(300).nullable().describe("Exact resource identifier. Use null, with a null resourceType, to run for every resource of the namespace. Only events whose searchEventTypes reach is \"all\" or { anyOf } can run that way, and match must set one of the anyOf filters. When creating, omit it to run for every resource. When updating, omit it to keep the saved identifier.").optional(),
9537
- resourceType: registeredResourceTypeSchema(plugins).nullable().describe("Resource type of the identifier. Use null when identifier is null. When updating, omit it to keep the saved resource type.").optional(),
9538
9504
  label: z.string().trim().min(1).max(500),
9539
9505
  events: z.array(registeredEventTypeSchema(plugins)).min(1),
9540
- match: registeredEventMatchSchema()
9506
+ match: registeredEventMatchSchema().describe("Filters that select the events, from the matchFields of the namespace. Use the match of a subscribable tool result to select one resource, such as { repo, pullRequest } for one pull request. Leave it out to run for every resource, when the reach of each event allows that. A single value must equal the event data. A list means the event value may be any one entry. For a field with list: true, the event value is a list, and it matches when it includes the value or any entry.")
9541
9507
  }).strict();
9542
9508
  }
9543
9509
  /**
9510
+ * Filter changes of an update. A value sets the filter, and null removes it.
9511
+ * A filter that is left out keeps its saved value, so an update cannot make
9512
+ * a trigger broader by leaving out a filter.
9513
+ */
9514
+ const eventMatchChangesSchema = z.record(z.string(), z.union([eventMatchSchema.valueType, z.null()])).optional().describe("Filter changes, from the matchFields of the namespace. A value sets the filter, null removes it, and a filter that is left out keeps its saved value. When the namespace changes, the saved filters are dropped.");
9515
+ /** Build the event trigger that the update tool accepts. */
9516
+ function registeredEventAutomationTriggerChangesSchema(catalog) {
9517
+ return registeredEventAutomationTriggerSchema(catalog).extend({ match: eventMatchChangesSchema });
9518
+ }
9519
+ /**
9520
+ * Apply filter changes to the saved trigger, key by key. A change to another
9521
+ * namespace starts from no filters.
9522
+ */
9523
+ function changedEventMatch(saved, namespace, changes) {
9524
+ const match = { ...namespace === saved.namespace ? saved.match : void 0 };
9525
+ for (const [key, value] of Object.entries(changes ?? {})) if (value === null) delete match[key];
9526
+ else match[key] = value;
9527
+ return Object.keys(match).length > 0 ? match : void 0;
9528
+ }
9529
+ /**
9544
9530
  * Check a new event-automation trigger with the enabled plugins and return
9545
9531
  * it as it is saved. It names a resource type and an identifier, or neither.
9546
9532
  * The identifier gets its plugin's convention. Events and list values lose
@@ -9653,15 +9639,16 @@ function changesEventAutomationTrigger(current, next) {
9653
9639
  async function editEventAutomation(current, input, isCreator, catalog) {
9654
9640
  let trigger = current.trigger;
9655
9641
  if (input.trigger !== void 0) {
9656
- if (changesEventAutomationTrigger(current.trigger, input.trigger) || current.trigger.resourceType !== input.trigger.resourceType) try {
9657
- trigger = requireEventAutomationTrigger(catalog, input.trigger);
9642
+ const inputTrigger = slackChannelMessageTrigger(input.trigger, current.destination.channelId);
9643
+ if (changesEventAutomationTrigger(current.trigger, inputTrigger) || current.trigger.resourceType !== inputTrigger.resourceType) try {
9644
+ trigger = requireEventAutomationTrigger(catalog, inputTrigger);
9658
9645
  } catch (error) {
9659
9646
  if (error instanceof ToolInputError) throw new AutomationEditError(error.message, "trigger");
9660
9647
  throw error;
9661
9648
  }
9662
9649
  else trigger = {
9663
9650
  ...current.trigger,
9664
- label: input.trigger.label
9651
+ label: inputTrigger.label
9665
9652
  };
9666
9653
  }
9667
9654
  const changesExecution = input.instruction !== void 0 && input.instruction !== current.task.text || changesEventAutomationTrigger(current.trigger, trigger);
@@ -10171,7 +10158,7 @@ async function readConversationSourceTask(args) {
10171
10158
  // src/chat/automations/edit.ts
10172
10159
  /**
10173
10160
  * Web edits and lifecycle actions. Anyone who can read an Automation can
10174
- * manage it. Creator-only fields and credential rules still apply.
10161
+ * manage it. Creator credential rules still apply.
10175
10162
  */
10176
10163
  /** Owners and public Destination readers can manage. Others get not found. */
10177
10164
  async function requireEditableAutomation(user, id) {
@@ -10296,7 +10283,7 @@ async function restorableOutcomes(current, outcomes) {
10296
10283
  });
10297
10284
  continue;
10298
10285
  }
10299
- if (current.ownedByViewer && !task.outcomes.some((stored) => sameDefinitionValue(stored, outcome))) {
10286
+ if (!task.outcomes.some((stored) => sameDefinitionValue(stored, outcome))) {
10300
10287
  creatorDm ??= (await resolveTaskOutcomes([{
10301
10288
  action: "send_message",
10302
10289
  destination: "task_creator"
@@ -10776,15 +10763,23 @@ const automationSearchResultSchema = juniorToolOutputSchema.extend({
10776
10763
  automations: z.array(automationResultSchema),
10777
10764
  truncated: z.boolean()
10778
10765
  }).strict();
10766
+ const scheduleTriggerSchema = z.object({
10767
+ type: z.literal("schedule"),
10768
+ schedule: scheduleIntentSchema.describe("When the automation runs. The scheduler computes the exact next run from this intent and the server clock.")
10769
+ }).strict();
10779
10770
  /**
10780
- * Build the trigger input of the create and update tools: a schedule, or the
10781
- * events of an enabled plugin.
10771
+ * Build the trigger input of the create tool: a schedule, or the events of an
10772
+ * enabled plugin.
10782
10773
  */
10783
10774
  function automationTriggerSchema(catalog) {
10784
- return z.discriminatedUnion("type", [z.object({
10785
- type: z.literal("schedule"),
10786
- schedule: scheduleIntentSchema.describe("When the automation runs. The scheduler computes the exact next run from this intent and the server clock.")
10787
- }).strict(), registeredEventAutomationTriggerSchema(catalog).extend({ type: z.literal("event") })]);
10775
+ return z.discriminatedUnion("type", [scheduleTriggerSchema, registeredEventAutomationTriggerSchema(catalog).extend({ type: z.literal("event") })]);
10776
+ }
10777
+ /**
10778
+ * Build the trigger input of the update tool. An event trigger changes its
10779
+ * filters key by key.
10780
+ */
10781
+ function automationTriggerChangesSchema(catalog) {
10782
+ return z.discriminatedUnion("type", [scheduleTriggerSchema, registeredEventAutomationTriggerChangesSchema(catalog).extend({ type: z.literal("event") })]);
10788
10783
  }
10789
10784
  /** Return the Automation kind of a trigger input. */
10790
10785
  function triggerKind(trigger) {
@@ -10978,7 +10973,7 @@ function createAutomationTool(context, catalog) {
10978
10973
  creator: createdBy,
10979
10974
  destinationChannelId: destination.channelId
10980
10975
  });
10981
- const eventTrigger = input.trigger.type === "event" ? requireEventAutomationTrigger(catalog, input.trigger) : void 0;
10976
+ const eventTrigger = input.trigger.type === "event" ? requireEventAutomationTrigger(catalog, slackChannelMessageTrigger(input.trigger, destination.channelId)) : void 0;
10982
10977
  const toolCallId = options.toolCallId?.trim();
10983
10978
  if (!toolCallId) throw new Error("Automation creation requires a tool-call identity.");
10984
10979
  const id = automationIdForToolCall({
@@ -11102,147 +11097,17 @@ function createSearchAutomationsTool(context, catalog) {
11102
11097
  }
11103
11098
  });
11104
11099
  }
11105
- // src/chat/automations/tools/update.ts
11106
- /** Reject a move while an occurrence is pending or running. */
11107
- async function requireNoIncompleteRun(automationId) {
11108
- if ((await getDb().select({ id: juniorAutomationRuns.id }).from(juniorAutomationRuns).where(and(eq(juniorAutomationRuns.automationId, automationId), inArray(juniorAutomationRuns.status, ["pending", "running"]))).limit(1)).length > 0) throw new ToolInputError("Scheduled automation cannot be moved while an occurrence is already running. Try again after the current run finishes.");
11109
- }
11110
- /** Edit and save a scheduled Automation, including a move to this Conversation. */
11111
- async function updateScheduled(context, current, input, editor) {
11112
- const { task, ownedByViewer: isCreator } = current;
11113
- const destination = input.destination ? requireToolDestination(context) : void 0;
11114
- const moving = destination !== void 0 && !sameDestination(task.destination, destination);
11115
- if (destination && !moving && Object.keys(input).every((key) => key === "destination" || key === "credentialMode" && input.credentialMode === task.credentialMode)) return current;
11116
- if (moving) await requireNoIncompleteRun(task.id);
11117
- const next = await editScheduledAutomation(task, {
11118
- title: input.title,
11119
- instruction: input.instruction,
11120
- schedule: input.trigger?.type === "schedule" ? input.trigger.schedule : void 0,
11121
- credentialMode: input.credentialMode,
11122
- outcomes: moving ? void 0 : input.outcomes
11123
- }, isCreator, context.now?.() ?? Date.now());
11124
- if (moving) {
11125
- next.destination = destination;
11126
- next.conversationAccess = getConversationAccess(destination, context.visibility);
11127
- next.outcomes = input.outcomes === void 0 ? moveTaskOutcomes(task.outcomes, task.destination, destination) : await resolveTaskOutcomes(input.outcomes, destination, task.createdBy.slackUserId);
11128
- }
11129
- const saved = await saveScheduledAutomation(getDb(), next, automationRevision(task), editor);
11130
- if (moving) logInfo("scheduled_automation.move.completed", scheduledAutomationAttributes(saved));
11131
- return {
11132
- ...current,
11133
- task: saved
11134
- };
11135
- }
11136
- /** Edit and save an event Automation. */
11137
- async function updateEvent(current, input, editor, catalog) {
11138
- const { task } = current;
11139
- const trigger = input.trigger?.type === "event" ? input.trigger : void 0;
11140
- const next = await editEventAutomation(task, {
11141
- title: input.title,
11142
- instruction: input.instruction,
11143
- trigger: trigger ? {
11144
- ...trigger,
11145
- identifier: trigger.identifier === void 0 ? task.trigger.identifier : trigger.identifier ?? void 0,
11146
- resourceType: trigger.resourceType === void 0 ? task.trigger.resourceType : trigger.resourceType ?? void 0
11147
- } : void 0,
11148
- outcomes: input.outcomes,
11149
- credentialMode: input.credentialMode
11150
- }, current.ownedByViewer, catalog);
11151
- const saved = await saveEventAutomation(getDb(), next, automationRevision(task), editor);
11152
- if (!saved) throw new ToolInputError("Automation was not found.");
11153
- return {
11154
- ...current,
11155
- task: saved
11156
- };
11157
- }
11158
- /** Create the tool that edits, pauses, resumes, or moves one Automation. */
11159
- function createUpdateAutomationTool(context, catalog) {
11160
- const trigger = automationTriggerSchema(catalog);
11161
- return zodTool({
11162
- approvalMode: "review",
11163
- annotations: {
11164
- destructiveHint: true,
11165
- idempotentHint: true,
11166
- openWorldHint: true,
11167
- readOnlyHint: false
11168
- },
11169
- executionMode: "sequential",
11170
- description: "Update the title, instruction, trigger, outcomes, credential use, or status of a scheduled or event automation. Anyone in the workspace can update an automation in a public channel. Automations in private channels and DMs can be updated from there or by their creator. Only the creator can enable creator credentials, change outcomes, or move it. A non-creator who changes the instruction or trigger switches it to system credentials. The trigger type cannot change. Set destination to \"current_conversation\" to move a scheduled automation to the channel or DM of this conversation.",
11171
- inputSchema: z.object({
11172
- automationId: z.string().min(1).describe("ID of the automation, from searchAutomations or its dashboard URL."),
11173
- title: automationTitleSchema.optional(),
11174
- instruction: automationInstructionToolSchema.nullable().optional(),
11175
- trigger: trigger.nullable().describe("Complete replacement trigger of the same type. For an event trigger, omit identifier or resourceType to keep the saved one. Omit or use null to keep the trigger.").optional(),
11176
- outcomes: z.array(taskOutcomeInputSchema).max(5).nullable().describe("Replacement messages to send after successful work. Use an empty list to send nothing. Omit or use null to leave unchanged.").optional(),
11177
- credentialMode: z.enum(["system", "creator"]).nullable().describe("Set creator to make the automation creator's credentials available, or system to disable them. Creator always means the automation's createdBy actor, never the current requester. Only that creator may enable creator mode. Omit or use null to leave unchanged.").optional(),
11178
- status: z.enum(["active", "paused"]).nullable().describe("Set active to resume a paused or blocked automation, or paused to stop it. When it uses its creator's credentials, only the creator can resume it. Omit or use null to leave unchanged.").optional(),
11179
- destination: z.literal("current_conversation").nullable().describe("Set to \"current_conversation\" to move the creator's scheduled automation into the channel or DM of this conversation. Omit to keep its destination.").optional()
11180
- }).strict(),
11181
- prepareArguments(args) {
11182
- return Object.fromEntries(Object.entries(args).filter(([, value]) => value != null));
11183
- },
11184
- outputSchema: automationToolResultSchema,
11185
- async execute({ automationId, status: requestedStatus, ...fields }) {
11186
- const input = fields;
11187
- const status = requestedStatus ?? void 0;
11188
- const caller = await requireToolCaller(context);
11189
- const current = await requireToolAutomation(caller, automationId);
11190
- if (input.trigger && triggerKind(input.trigger) !== current.kind) throw new ToolInputError(`This automation runs on ${current.kind === "scheduled" ? "a schedule" : "events"}. The trigger type cannot change. Create a new automation instead.`);
11191
- if (Object.keys(input).length === 0 && status === void 0) throw new ToolInputError("Automation update requires a change.");
11192
- if (current.kind === "scheduled" && current.task.status === "completed") throw new ToolInputError("Completed scheduled automations cannot be updated. Create a new automation instead.");
11193
- if (input.destination && !current.ownedByViewer) throw new ToolInputError("Only the automation creator can move this automation.");
11194
- if (input.destination && current.kind === "event") throw new ToolInputError("Event automations cannot move. Create a new event automation in this conversation instead.");
11195
- const editor = automationEditor(caller.viewer, current);
11196
- if (input.instruction !== void 0 && input.instruction !== current.task.task.text) requireInstructionReferences(input.instruction, {
11197
- creator: current.task.createdBy,
11198
- destinationChannelId: current.task.destination.channelId,
11199
- requester: editor,
11200
- previousInstruction: current.task.task.text
11201
- });
11202
- let saved = current;
11203
- if (Object.keys(input).length > 0) saved = current.kind === "scheduled" ? await updateScheduled(context, current, input, editor) : await updateEvent(current, input, editor, catalog);
11204
- if (status !== void 0 && status !== saved.task.status) saved = await changeAutomationLifecycle(saved, {
11205
- action: status === "paused" ? "pause" : "resume",
11206
- revision: automationRevision(saved.task)
11207
- });
11208
- return automationToolResult(context.conversationId, saved, catalog);
11209
- }
11100
+ // src/chat/conversations/destination-visibility.ts
11101
+ /** Read confirmed visibility from the current signal or persisted destination. */
11102
+ async function resolveDestinationVisibility(args) {
11103
+ if (args.visibility) return args.visibility;
11104
+ if (args.destination.platform === "local") return "private";
11105
+ return await getConversationStore().getDestinationVisibility({
11106
+ provider: "slack",
11107
+ providerDestinationId: args.destination.channelId,
11108
+ providerTenantId: args.destination.teamId
11210
11109
  });
11211
11110
  }
11212
- // src/chat/tools/definition.ts
11213
- /** Distinguish legacy TypeBox schemas from JSON Schema projected from Zod. */
11214
- function isTypeBoxInputSchema(schema) {
11215
- return typeof schema === "object" && schema !== null && Kind in schema;
11216
- }
11217
- /** Tool error text for a call to a tool that is disabled in this Turn. */
11218
- function disabledToolMessage(toolName, reason) {
11219
- return `${toolName} is disabled in this Turn. ${reason} Do not call it again in this Turn.`;
11220
- }
11221
- /**
11222
- * Disable tools for this Turn without removing them from the tool list.
11223
- *
11224
- * The tool adapter rejects their calls, and the Turn context lists them. An
11225
- * unset reason keeps the tools enabled.
11226
- */
11227
- function disableTools(tools, reason) {
11228
- if (!reason) return tools;
11229
- return Object.fromEntries(Object.entries(tools).map(([name, tool]) => [name, {
11230
- ...tool,
11231
- disabledReason: reason
11232
- }]));
11233
- }
11234
- // src/chat/tools/automations.ts
11235
- /** Build the Automation tools. A Turn that no person started cannot use them. */
11236
- function createAutomationTools(context, catalog) {
11237
- const automationContext = automationToolContext(context);
11238
- return disableTools({
11239
- createAutomation: createAutomationTool(automationContext, catalog),
11240
- searchAutomations: createSearchAutomationsTool(automationContext, catalog),
11241
- updateAutomation: createUpdateAutomationTool(automationContext, catalog),
11242
- deleteAutomation: createDeleteAutomationTool(automationContext, catalog),
11243
- runAutomationNow: createRunAutomationNowTool(automationContext, catalog)
11244
- }, automationToolsDisabledReason(context));
11245
- }
11246
11111
  // src/chat/slack/channel.ts
11247
11112
  const replySubtypeSchema = z.object({ subtype: z.string().optional() });
11248
11113
  /** List channel history using Slack-native, pre-validated timestamp bounds. */
@@ -11455,6 +11320,203 @@ async function resolveOptionalSlackChannelRef(input) {
11455
11320
  if (input.defaultChannelId) return { channelId: input.defaultChannelId };
11456
11321
  throw new ToolInputError("Provide `channel_id`, or use this tool in an active Slack channel context.");
11457
11322
  }
11323
+ // src/chat/automations/tools/update.ts
11324
+ /** Reject a move while an occurrence is pending or running. */
11325
+ async function requireNoIncompleteRun(automationId) {
11326
+ if ((await getDb().select({ id: juniorAutomationRuns.id }).from(juniorAutomationRuns).where(and(eq(juniorAutomationRuns.automationId, automationId), inArray(juniorAutomationRuns.status, ["pending", "running"]))).limit(1)).length > 0) throw new ToolInputError("Scheduled automation cannot be moved while an occurrence is already running. Try again after the current run finishes.");
11327
+ }
11328
+ /**
11329
+ * Resolve where a move goes. "current_conversation" is this Conversation. A
11330
+ * channel reference must name a public Slack channel in this workspace, and
11331
+ * Junior joins it so the Automation can post there.
11332
+ */
11333
+ async function requireMoveDestination(context, value) {
11334
+ const here = requireToolDestination(context);
11335
+ if (value === "current_conversation") return {
11336
+ destination: here,
11337
+ visibility: context.visibility
11338
+ };
11339
+ const teamId = parseSlackTeamId(here.teamId);
11340
+ if (!teamId) throw new ToolInputError("Slack workspace is unavailable.");
11341
+ const { channelId, channelName } = await resolveSlackChannelRef({
11342
+ field: "destination",
11343
+ value,
11344
+ teamId
11345
+ });
11346
+ if (channelId === here.channelId) return {
11347
+ destination: here,
11348
+ visibility: context.visibility
11349
+ };
11350
+ const access = await checkSlackChannelReadAccess({
11351
+ currentChannelIds: [],
11352
+ targetChannelId: channelId,
11353
+ teamId
11354
+ });
11355
+ if (!access.allowed) throw new ToolInputError(access.reason === "private" ? "Only a public channel can be named as a destination. To move an automation into a private channel or DM, ask from there." : access.error);
11356
+ if (access.isMember !== true) {
11357
+ const joined = await joinPublicChannelForRead({
11358
+ targetChannelId: channelId,
11359
+ ...channelName ? { channelName } : void 0
11360
+ });
11361
+ if (!joined.ok) throw new ToolInputError(joined.error);
11362
+ }
11363
+ const destination = {
11364
+ platform: "slack",
11365
+ teamId,
11366
+ channelId
11367
+ };
11368
+ const name = access.channelName ?? channelName;
11369
+ await getConversationStore().recordDestinationVisibility({
11370
+ destination,
11371
+ ...name ? { channelName: name } : void 0,
11372
+ visibility: "public"
11373
+ });
11374
+ return {
11375
+ destination,
11376
+ visibility: "public"
11377
+ };
11378
+ }
11379
+ /** Edit and save a scheduled Automation, including a move to a new Destination. */
11380
+ async function updateScheduled(context, current, input, editor) {
11381
+ const { task, ownedByViewer: isCreator } = current;
11382
+ const target = input.destination ? await requireMoveDestination(context, input.destination) : void 0;
11383
+ const destination = target?.destination;
11384
+ const moving = destination !== void 0 && !sameDestination(task.destination, destination);
11385
+ if (destination && !moving && Object.keys(input).every((key) => key === "destination" || key === "credentialMode" && input.credentialMode === task.credentialMode)) return current;
11386
+ if (moving) await requireNoIncompleteRun(task.id);
11387
+ const next = await editScheduledAutomation(task, {
11388
+ title: input.title,
11389
+ instruction: input.instruction,
11390
+ schedule: input.trigger?.type === "schedule" ? input.trigger.schedule : void 0,
11391
+ credentialMode: input.credentialMode,
11392
+ outcomes: moving ? void 0 : input.outcomes
11393
+ }, isCreator, context.now?.() ?? Date.now());
11394
+ if (moving) {
11395
+ next.destination = destination;
11396
+ next.conversationAccess = getConversationAccess(destination, target?.visibility);
11397
+ if (!isCreator) next.credentialMode = "system";
11398
+ next.outcomes = input.outcomes === void 0 ? moveTaskOutcomes(task.outcomes, task.destination, destination) : await resolveTaskOutcomes(input.outcomes, destination, task.createdBy.slackUserId);
11399
+ }
11400
+ const saved = await saveScheduledAutomation(getDb(), next, automationRevision(task), editor);
11401
+ if (moving) logInfo("scheduled_automation.move.completed", scheduledAutomationAttributes(saved));
11402
+ return {
11403
+ ...current,
11404
+ task: saved
11405
+ };
11406
+ }
11407
+ /** Edit and save an event Automation. */
11408
+ async function updateEvent(current, input, editor, catalog) {
11409
+ const { task } = current;
11410
+ const trigger = input.trigger?.type === "event" ? input.trigger : void 0;
11411
+ const next = await editEventAutomation(task, {
11412
+ title: input.title,
11413
+ instruction: input.instruction,
11414
+ trigger: trigger ? {
11415
+ ...trigger,
11416
+ ...trigger.namespace === task.trigger.namespace ? {
11417
+ identifier: task.trigger.identifier,
11418
+ resourceType: task.trigger.resourceType
11419
+ } : void 0,
11420
+ match: changedEventMatch(task.trigger, trigger.namespace, trigger.match)
11421
+ } : void 0,
11422
+ outcomes: input.outcomes,
11423
+ credentialMode: input.credentialMode
11424
+ }, current.ownedByViewer, catalog);
11425
+ const saved = await saveEventAutomation(getDb(), next, automationRevision(task), editor);
11426
+ if (!saved) throw new ToolInputError("Automation was not found.");
11427
+ return {
11428
+ ...current,
11429
+ task: saved
11430
+ };
11431
+ }
11432
+ /** Create the tool that edits, pauses, resumes, or moves one Automation. */
11433
+ function createUpdateAutomationTool(context, catalog) {
11434
+ const trigger = automationTriggerChangesSchema(catalog);
11435
+ return zodTool({
11436
+ approvalMode: "review",
11437
+ annotations: {
11438
+ destructiveHint: true,
11439
+ idempotentHint: true,
11440
+ openWorldHint: true,
11441
+ readOnlyHint: false
11442
+ },
11443
+ executionMode: "sequential",
11444
+ description: "Update the title, instruction, trigger, outcomes, credential use, or status of a scheduled or event automation. Anyone in the workspace can update anything on an automation in a public channel, including its outcomes and destination. Automations in private channels and DMs can be updated from there or by their creator, and only their creator can move them. Only the creator can enable creator credentials. A non-creator who changes the instruction, trigger, outcomes, or destination switches it to system credentials. The trigger type cannot change. Set destination to move a scheduled automation to this conversation or to a public channel.",
11445
+ inputSchema: z.object({
11446
+ automationId: z.string().min(1).describe("ID of the automation, from searchAutomations or its dashboard URL."),
11447
+ title: automationTitleSchema.optional(),
11448
+ instruction: automationInstructionToolSchema.nullable().optional(),
11449
+ trigger: trigger.nullable().describe("Replacement trigger of the same type. For an event trigger, match changes only the filters that it names. Omit or use null to keep the trigger.").optional(),
11450
+ outcomes: z.array(taskOutcomeInputSchema).max(5).nullable().describe("Replacement messages to send after successful work. Use an empty list to send nothing. Omit or use null to leave unchanged.").optional(),
11451
+ credentialMode: z.enum(["system", "creator"]).nullable().describe("Set creator to make the automation creator's credentials available, or system to disable them. Creator always means the automation's createdBy actor, never the current requester. Only that creator may enable creator mode. Omit or use null to leave unchanged.").optional(),
11452
+ status: z.enum(["active", "paused"]).nullable().describe("Set active to resume a paused or blocked automation, or paused to stop it. When it uses its creator's credentials, only the creator can resume it. Omit or use null to leave unchanged.").optional(),
11453
+ destination: slackChannelRefParam.nullable().describe("Where to move a scheduled automation. Set \"current_conversation\" for the channel or DM of this conversation, or name a public Slack channel by id, mention, or known name. Omit to keep its destination.").optional()
11454
+ }).strict(),
11455
+ prepareArguments(args) {
11456
+ return Object.fromEntries(Object.entries(args).filter(([, value]) => value != null));
11457
+ },
11458
+ outputSchema: automationToolResultSchema,
11459
+ async execute({ automationId, status: requestedStatus, ...fields }) {
11460
+ const input = fields;
11461
+ const status = requestedStatus ?? void 0;
11462
+ const caller = await requireToolCaller(context);
11463
+ const current = await requireToolAutomation(caller, automationId);
11464
+ if (input.trigger && triggerKind(input.trigger) !== current.kind) throw new ToolInputError(`This automation runs on ${current.kind === "scheduled" ? "a schedule" : "events"}. The trigger type cannot change. Create a new automation instead.`);
11465
+ if (Object.keys(input).length === 0 && status === void 0) throw new ToolInputError("Automation update requires a change.");
11466
+ if (current.kind === "scheduled" && current.task.status === "completed") throw new ToolInputError("Completed scheduled automations cannot be updated. Create a new automation instead.");
11467
+ if (input.destination && current.kind === "event") throw new ToolInputError("Event automations cannot move. Create a new event automation in this conversation instead.");
11468
+ if (input.destination && !current.ownedByViewer && await resolveDestinationVisibility({ destination: current.task.destination }) !== "public") throw new ToolInputError("Only the creator can move an automation out of a private channel or DM.");
11469
+ const editor = automationEditor(caller.viewer, current);
11470
+ if (input.instruction !== void 0 && input.instruction !== current.task.task.text) requireInstructionReferences(input.instruction, {
11471
+ creator: current.task.createdBy,
11472
+ destinationChannelId: current.task.destination.channelId,
11473
+ requester: editor,
11474
+ previousInstruction: current.task.task.text
11475
+ });
11476
+ let saved = current;
11477
+ if (Object.keys(input).length > 0) saved = current.kind === "scheduled" ? await updateScheduled(context, current, input, editor) : await updateEvent(current, input, editor, catalog);
11478
+ if (status !== void 0 && status !== saved.task.status) saved = await changeAutomationLifecycle(saved, {
11479
+ action: status === "paused" ? "pause" : "resume",
11480
+ revision: automationRevision(saved.task)
11481
+ });
11482
+ return automationToolResult(context.conversationId, saved, catalog);
11483
+ }
11484
+ });
11485
+ }
11486
+ // src/chat/tools/definition.ts
11487
+ /** Distinguish legacy TypeBox schemas from JSON Schema projected from Zod. */
11488
+ function isTypeBoxInputSchema(schema) {
11489
+ return typeof schema === "object" && schema !== null && Kind in schema;
11490
+ }
11491
+ /** Tool error text for a call to a tool that is disabled in this Turn. */
11492
+ function disabledToolMessage(toolName, reason) {
11493
+ return `${toolName} is disabled in this Turn. ${reason} Do not call it again in this Turn.`;
11494
+ }
11495
+ /**
11496
+ * Disable tools for this Turn without removing them from the tool list.
11497
+ *
11498
+ * The tool adapter rejects their calls, and the Turn context lists them. An
11499
+ * unset reason keeps the tools enabled.
11500
+ */
11501
+ function disableTools(tools, reason) {
11502
+ if (!reason) return tools;
11503
+ return Object.fromEntries(Object.entries(tools).map(([name, tool]) => [name, {
11504
+ ...tool,
11505
+ disabledReason: reason
11506
+ }]));
11507
+ }
11508
+ // src/chat/tools/automations.ts
11509
+ /** Build the Automation tools. A Turn that no person started cannot use them. */
11510
+ function createAutomationTools(context, catalog) {
11511
+ const automationContext = automationToolContext(context);
11512
+ return disableTools({
11513
+ createAutomation: createAutomationTool(automationContext, catalog),
11514
+ searchAutomations: createSearchAutomationsTool(automationContext, catalog),
11515
+ updateAutomation: createUpdateAutomationTool(automationContext, catalog),
11516
+ deleteAutomation: createDeleteAutomationTool(automationContext, catalog),
11517
+ runAutomationNow: createRunAutomationNowTool(automationContext, catalog)
11518
+ }, automationToolsDisabledReason(context));
11519
+ }
11458
11520
  // src/chat/slack/tools/channel-join.ts
11459
11521
  /** Create a tool that joins one public Slack channel. */
11460
11522
  function createSlackChannelJoinTool(context) {
@@ -12273,18 +12335,22 @@ function plainText$1(text) {
12273
12335
  emoji: true
12274
12336
  };
12275
12337
  }
12338
+ const SUGGESTED_SUFFIX = " (suggested)";
12339
+ function optionLabel(option, maxChars = Number.POSITIVE_INFINITY) {
12340
+ return option.recommended ? `${truncate$2(option.label, maxChars - 12)}${SUGGESTED_SUFFIX}` : option.label;
12341
+ }
12276
12342
  /** The question and a short list of what to answer, in Slack markdown. */
12277
12343
  function slackUserInputText(request) {
12278
12344
  const buttonField = buttonUserInputField(request);
12279
- const notes = buttonField ? buttonField.options.filter((option) => option.description).map((option) => `- **${option.label}**: ${option.description}`) : request.fields.map((field) => {
12280
- const detail = field.kind === "text" ? "short answer" : `${field.kind === "multi_choice" ? "pick any" : "pick one"}: ${field.options.map((option) => option.label).join(", ")}`;
12345
+ const notes = buttonField ? buttonField.options.filter((option) => option.description).map((option) => `- **${optionLabel(option)}**: ${option.description}`) : request.fields.map((field) => {
12346
+ const detail = field.kind === "text" ? "short answer" : `${field.kind === "multi_choice" ? "pick any" : "pick one"}: ${field.options.map((option) => optionLabel(option)).join(", ")}`;
12281
12347
  return `- **${field.label}** (${detail})${field.description ? `: ${field.description}` : ""}`;
12282
12348
  });
12283
12349
  return normalizeSlackReplyMarkdown([request.question, ...notes.length ? [notes.join("\n")] : []].join("\n\n"));
12284
12350
  }
12285
12351
  function toOption(option) {
12286
12352
  return {
12287
- text: plainText$1(option.label),
12353
+ text: plainText$1(optionLabel(option, USER_INPUT_LIMITS.maxLabelChars)),
12288
12354
  value: option.label,
12289
12355
  ...option.description ? { description: plainText$1(truncate$2(option.description, MAX_OPTION_DESCRIPTION_CHARS)) } : void 0
12290
12356
  };
@@ -12382,7 +12448,6 @@ const SLACK_REVIEW_ITEM_VIEW_ID = "junior_review_item";
12382
12448
  const ACTION_ID_PREFIX = "junior_review_item:";
12383
12449
  const CHOICE_ACTION_ID_PREFIX = `${ACTION_ID_PREFIX}choice:`;
12384
12450
  const ANSWER_ACTION_ID = `${ACTION_ID_PREFIX}answer`;
12385
- const DONE_ACTION_ID = `${ACTION_ID_PREFIX}done`;
12386
12451
  const DISMISS_ACTION_ID = `${ACTION_ID_PREFIX}dismiss`;
12387
12452
  const MAX_BODY_CHARS = 3e3;
12388
12453
  const MAX_CONTEXT_CHARS = 3e3;
@@ -12418,13 +12483,7 @@ function controls(item) {
12418
12483
  text: plainText("Dismiss"),
12419
12484
  value: item.id
12420
12485
  };
12421
- if (item.kind === "notice" || !item.request) return [{
12422
- type: "button",
12423
- action_id: DONE_ACTION_ID,
12424
- style: "primary",
12425
- text: plainText("Done"),
12426
- value: item.id
12427
- }, dismiss];
12486
+ if (item.kind === "notice" || !item.request) return [dismiss];
12428
12487
  const buttonField = buttonUserInputField(item.request);
12429
12488
  if (!buttonField) return [{
12430
12489
  type: "button",
@@ -12437,6 +12496,7 @@ function controls(item) {
12437
12496
  ...buttonField.options.map((option, index) => ({
12438
12497
  type: "button",
12439
12498
  action_id: `${CHOICE_ACTION_ID_PREFIX}${index}`,
12499
+ ...option.recommended ? { style: "primary" } : void 0,
12440
12500
  text: plainText(option.label),
12441
12501
  value: JSON.stringify({
12442
12502
  itemId: item.id,
@@ -12468,8 +12528,8 @@ function closedNote(item) {
12468
12528
  /**
12469
12529
  * Render a Review item as one Slack message. An open item shows its
12470
12530
  * controls: one button per choice when one click can answer it, an Answer
12471
- * button that opens a form otherwise, and Done for a notice. A closed item
12472
- * shows a note instead, so nobody can act on it again.
12531
+ * button that opens a form otherwise, and only Dismiss for a notice. A
12532
+ * closed item shows a note instead, so nobody can act on it again.
12473
12533
  */
12474
12534
  function buildSlackReviewItemCard(item) {
12475
12535
  const text = itemText(item);
@@ -12537,10 +12597,6 @@ function parseSlackReviewItemClick(action) {
12537
12597
  kind: "answer",
12538
12598
  itemId: value
12539
12599
  };
12540
- if (action.action_id === DONE_ACTION_ID) return {
12541
- kind: "done",
12542
- itemId: value
12543
- };
12544
12600
  if (action.action_id === DISMISS_ACTION_ID) return {
12545
12601
  kind: "dismiss",
12546
12602
  itemId: value
@@ -14746,9 +14802,8 @@ function createPublishImageTool(args) {
14746
14802
  openWorldHint: true,
14747
14803
  readOnlyHint: false
14748
14804
  },
14749
- approvalMode: "review",
14805
+ approvalMode: "approve",
14750
14806
  description: "Publish one sandbox image to a durable public HTTPS URL. Anyone on the internet with the URL can view the image. Use only when an external destination needs a public image URL. Do not use for private file sharing or private conversation storage. Supports PNG, JPEG, GIF, and WebP up to 10 MB.",
14751
- describeProposal: ({ path }) => `Publish sandbox image ${path} to a public internet URL.`,
14752
14807
  executionMode: "sequential",
14753
14808
  inputSchema: z.object({ path: z.string().min(1).describe("Exact sandbox path of an existing image file.") }).strict(),
14754
14809
  outputSchema: outputSchema$1,
@@ -19514,6 +19569,7 @@ async function wireAgentTools(args) {
19514
19569
  const getPendingAuthPause = () => pluginAuth.getPendingPause() ?? mcpAuth.getPendingPause();
19515
19570
  const commonToolRuntimeContext = {
19516
19571
  conversationId: args.run.conversationId,
19572
+ turnId: args.run.turnId,
19517
19573
  ...args.run.parentConversationId ? { parentConversationId: args.run.parentConversationId } : void 0,
19518
19574
  ...args.run.location ? {
19519
19575
  location: args.run.location,
@@ -21657,4 +21713,4 @@ function createAgentRunner(execute, options) {
21657
21713
  return await execute(nextRun, streamFn);
21658
21714
  } };
21659
21715
  }
21660
- export { listOwnedWatches as $, verifySlackSignature as A, actorFromRun as At, changeViewerAutomationLifecycle as B, syncReviewItemSlackCards as C, processWorkspaceSnapshotJob as Ct, parseSlackReviewItemFormTarget as D, readUserCustomization as Dt, parseSlackReviewItemClick as E, withoutSavedSteeringMessages as Et, getConversationInfo as F, readConversationSourceTask as G, readViewerAutomationEdit as H, listThreadReplies as I, readViewerAutomationSummary as J, readViewerAutomationExecutions as K, logScheduledAutomationRunSkipped as L, readSlackRawMessageContext as M, readBlockedReport as Mt, resolveSlackChannelIdFromMessage as N, shouldEmitDevAgentTrace as Nt, parseSlackUserInputSubmission as O, saveUserCustomization as Ot, resolveSlackChannelIdFromThreadId as P, effectiveTaskOutcomes as Q, scheduledAutomationRunAttributes as R, readSlackReviewItemCardConversationId as S, conversationSubtreeColumns as St, buildSlackReviewItemModal as T, buildSteeringPiMessage as Tt, updateViewerAutomation as U, deleteViewerTask as V, ViewerTaskNotFoundError as W, readViewerAutomations as X, readViewerAutomationVersions as Y, AutomationEditError as Z, unpublishedArtifactHeaders as _, recordSubagentEnded as _t, finalizeMcpAuthorization as a, createAndEnqueueConversation as at, renderBlockText as b, listUnreportedSiblingAgents as bt, deleteMcpServerSessionId as c, webActorFromEmail as ct, getMcpStoredOAuthCredentials as d, collectAttachmentGarbage as dt, deliverReviewItemChange as et, putMcpStoredOAuthCredentials as f, readLiveAttachment as ft, readPublicArtifact as g, stopConversationSession as gt, publicArtifactHeaders as h, stopChildAgentsOf as ht, buildAuthPauseResponse as i, conversationTurnIdForMessage as it, parseSlackThreadId as j, toolInvocationDestination as jt, runWithSlackInstallation as k, RetryableDeliveryError as kt, deleteMcpStoredOAuthCredentials as l, resolveConversationDestination as lt, readStats as m, storeAttachment as mt, executeAgentRun as n, acceptsWebMessages as nt, deleteMcpAuthSession as o, createConversationId as ot, latestProgressStatus as p, requestAttachmentDeletion as pt, readViewerAutomationRuns as q, createContextCompactor as r, appendAndEnqueueWebMessage as rt, deleteMcpAuthSessionsForUserProvider as s, recordWebConversationActivity as st, createAgentRunner as t, renderReviewItemMessage as tt, getMcpAuthSession as u, decodeInputImages as ut, lookupSlackUserProfile as v, recordSubagentStarted as vt, SLACK_REVIEW_ITEM_VIEW_ID as w, ingestEvent as wt, createSlackReviewItemShow as x, conversationSubtree as xt, renderAttachmentText as y, listChildAgents as yt, activateViewerAutomationVersion as z };
21716
+ export { AutomationEditError as $, verifySlackSignature as A, saveUserCustomization as At, scheduledAutomationRunAttributes as B, syncReviewItemSlackCards as C, conversationSubtree as Ct, parseSlackReviewItemFormTarget as D, buildSteeringPiMessage as Dt, parseSlackReviewItemClick as E, ingestEvent as Et, getConversationInfo as F, shouldEmitDevAgentTrace as Ft, updateViewerAutomation as G, changeViewerAutomationLifecycle as H, joinPublicChannel as I, readViewerAutomationExecutions as J, ViewerTaskNotFoundError as K, listThreadReplies as L, readSlackRawMessageContext as M, actorFromRun as Mt, resolveSlackChannelIdFromMessage as N, toolInvocationDestination as Nt, parseSlackUserInputSubmission as O, withoutSavedSteeringMessages as Ot, resolveSlackChannelIdFromThreadId as P, readBlockedReport as Pt, readViewerAutomations as Q, resolveDestinationVisibility as R, readSlackReviewItemCardConversationId as S, listUnreportedSiblingAgents as St, buildSlackReviewItemModal as T, processWorkspaceSnapshotJob as Tt, deleteViewerTask as U, activateViewerAutomationVersion as V, readViewerAutomationEdit as W, readViewerAutomationSummary as X, readViewerAutomationRuns as Y, readViewerAutomationVersions as Z, unpublishedArtifactHeaders as _, stopChildAgentsOf as _t, finalizeMcpAuthorization as a, appendAndEnqueueWebMessage as at, renderBlockText as b, recordSubagentStarted as bt, deleteMcpServerSessionId as c, createConversationId as ct, getMcpStoredOAuthCredentials as d, resolveConversationDestination as dt, effectiveTaskOutcomes as et, putMcpStoredOAuthCredentials as f, decodeInputImages as ft, readPublicArtifact as g, storeAttachment as gt, publicArtifactHeaders as h, requestAttachmentDeletion as ht, buildAuthPauseResponse as i, acceptsWebMessages as it, parseSlackThreadId as j, RetryableDeliveryError as jt, runWithSlackInstallation as k, readUserCustomization as kt, deleteMcpStoredOAuthCredentials as l, recordWebConversationActivity as lt, readStats as m, readLiveAttachment as mt, executeAgentRun as n, deliverReviewItemChange as nt, deleteMcpAuthSession as o, conversationTurnIdForMessage as ot, latestProgressStatus as p, collectAttachmentGarbage as pt, readConversationSourceTask as q, createContextCompactor as r, renderReviewItemMessage as rt, deleteMcpAuthSessionsForUserProvider as s, createAndEnqueueConversation as st, createAgentRunner as t, listOwnedWatches as tt, getMcpAuthSession as u, webActorFromEmail as ut, lookupSlackUserProfile as v, stopConversationSession as vt, SLACK_REVIEW_ITEM_VIEW_ID as w, conversationSubtreeColumns as wt, createSlackReviewItemShow as x, listChildAgents as xt, renderAttachmentText as y, recordSubagentEnded as yt, logScheduledAutomationRunSkipped as z };