@sentry/junior 0.206.0 → 0.208.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 (64) hide show
  1. package/dist/{agent-C9yuiZUF.js → agent-BfxfHsf1.js} +375 -346
  2. package/dist/{agent-hooks-DNjlz2A-.js → agent-hooks-CuGjLjmR.js} +224 -97
  3. package/dist/{agent-runner-E67lFrDG.js → agent-runner-Dz1PMKP0.js} +9 -9
  4. package/dist/api/schema.d.ts +39 -39
  5. package/dist/api/schema.js +2 -2
  6. package/dist/api.d.ts +1 -1
  7. package/dist/api.js +154 -154
  8. package/dist/{app-AxGmJHwK.d.ts → app-DfNrn_gS.d.ts} +2 -2
  9. package/dist/app.d.ts +1 -1
  10. package/dist/app.js +185 -183
  11. package/dist/{auth-pause-state-MVZ6xvEK.js → auth-pause-state-Bjoh8wCy.js} +7 -7
  12. package/dist/{briefs-CvJFQvhJ.js → briefs-q_onrGmf.js} +3 -3
  13. package/dist/{catalog-runtime-TBR8n4e1.js → catalog-runtime-D8YUMNhb.js} +1 -1
  14. package/dist/{checkpoint-BY47jJCB.js → checkpoint-FKMcINix.js} +8 -8
  15. package/dist/cli/chat.js +13 -13
  16. package/dist/cli/check.js +3 -3
  17. package/dist/cli/main.js +1 -1
  18. package/dist/cli/plugins.js +3 -3
  19. package/dist/cli/snapshot-create.js +3 -3
  20. package/dist/cli/upgrade.d.ts +1 -1
  21. package/dist/cli/upgrade.js +3 -3
  22. package/dist/{client-ceE7NtvC.js → client-bRyPqwAV.js} +4 -4
  23. package/dist/{config-CIE83sR2.js → config-EtF2uEaW.js} +6 -6
  24. package/dist/{context-B45_WqVX.js → context-Bplcgypl.js} +13 -13
  25. package/dist/{conversation-privacy-Auyq26XQ.js → conversation-privacy-whGaV2TG.js} +1 -1
  26. package/dist/{credential-sync-BO33aNQd.js → credential-sync-DM-EE1ey.js} +21 -21
  27. package/dist/{db-BeyXKJOI.d.ts → db-D74z7BZH.d.ts} +1 -1
  28. package/dist/{execution-stats-SiS2FLcv.js → execution-stats-C-f8zwMU.js} +77 -77
  29. package/dist/{executor-BfbYPW63.js → executor-BW5qp0jC.js} +43 -14
  30. package/dist/instrumentation.js +2 -2
  31. package/dist/{job-queue-CyTc24Es.js → job-queue-BIHNIEIX.js} +1 -1
  32. package/dist/{logging-D37bayDc.js → logging-sNS84Yuu.js} +1 -1
  33. package/dist/nitro.d.ts +1 -1
  34. package/dist/nitro.js +3 -3
  35. package/dist/{oauth-callback-server-BtfOeHTZ.js → oauth-callback-server-Co6D_yXP.js} +2 -2
  36. package/dist/{pending-auth-BPUzcs7n.js → pending-auth-CRJCt9Ux.js} +2 -2
  37. package/dist/{profile-CSixooTi.js → profile-BfLMVhWo.js} +4 -4
  38. package/dist/{prompt-3gqNY1Ka.js → prompt-x-0ZtTyb.js} +14 -14
  39. package/dist/{registry-DiR0-xRg.js → registry-Cyww_jnC.js} +2 -2
  40. package/dist/{resolve-Bn5q__9b.js → resolve-BApIFQXX.js} +2 -2
  41. package/dist/{runner-DFx3dIJH.js → runner-C9okx4GL.js} +10 -10
  42. package/dist/{sandbox-egress-signals-bwvjihxA.js → sandbox-egress-signals-BHfx0esj.js} +1 -1
  43. package/dist/{schema-8GXFfclK.js → schema-CwTeb-BF.js} +39 -39
  44. package/dist/{skills-BhM5qyCF.js → skills-DhL_wXEp.js} +2 -2
  45. package/dist/{spawn-Dk0PqdH6.js → spawn-msnzfE8_.js} +2 -2
  46. package/dist/{stats-DKRP4rsY.js → stats-Cq5w_Awk.js} +292 -268
  47. package/dist/{store-C5qxF2ac.d.ts → store-Det8MQ9g.d.ts} +1 -1
  48. package/dist/{task-queue-CdpTvu4R.js → task-queue-JfmWmpjS.js} +3 -3
  49. package/dist/{task-runner-alpjVSxQ.js → task-runner-Cm0gXoLH.js} +15 -15
  50. package/dist/{thread-state-CRK7aA41.js → thread-state-lw2QwQ-y.js} +5 -5
  51. package/dist/{turn-execution-XtyzIHog.js → turn-execution-C7K6lQp1.js} +3 -3
  52. package/dist/{turn-lifecycle-VbwZLfBv.js → turn-lifecycle-DVlJLwB0.js} +1 -1
  53. package/dist/{usage-D4A48Bdl.js → usage-BMuAlKIW.js} +2 -2
  54. package/dist/{validation-jn_46o4U.js → validation-BI-r3iQA.js} +1 -1
  55. package/dist/{version-DcfJxB4z.js → version-s6smK6lP.js} +1 -1
  56. package/dist/version.js +1 -1
  57. package/dist/{web-authorization-CsfLSfEs.js → web-authorization-C9MxPvXX.js} +1 -1
  58. package/dist/{web-input-BPp_sc7t.js → web-input-CwVlaLd0.js} +7 -109
  59. package/dist/{work-Di-ubSGg.js → work-BK0W1QAt.js} +9 -9
  60. package/dist/{worker-Cu_D5Mr8.js → worker-D-WWKHQD.js} +5 -5
  61. package/migrations/0041_automation_outcomes_backfill.sql +27 -0
  62. package/migrations/meta/0041_snapshot.json +3516 -0
  63. package/migrations/meta/_journal.json +7 -0
  64. package/package.json +5 -5
@@ -1,28 +1,28 @@
1
- import { C as resolveGatewayCredential, S as getGatewayApiKey, _ as findProviderError, b as isProviderRetryError, c as COMPACTION_SUMMARY_PREFIX, d as isCompactionSummaryText, f as renderCurrentInstruction, g as createProviderError, h as ProviderError, i as completeText, l as MODEL_HANDOFF_SUMMARY_PREFIX, m as escapeXml, n as GEN_AI_SERVER_ADDRESS, o as resolveGatewayModel, p as unwrapCurrentInstruction, r as completeObject, s as ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX, t as GEN_AI_PROVIDER_NAME, u as hasCompactedConversationContext, v as getProviderErrorAttributes, x as MISSING_GATEWAY_CREDENTIALS_ERROR } from "./client-ceE7NtvC.js";
2
- import { C as withSpan, F as isRecord$2, P as normalizeIdentityEmail, S as withLogContext, _ as setSpanAttributes, a as extractGenAiUsageSummary, b as summarizeMessageText, c as getTracePropagationHeaders, d as logInfo, f as logWarn, h as serializeGenAiAttribute, i as extractGenAiUsageAttributes, l as logError, p as normalizeGenAiFinishReason, s as getLogContextAttributesForSpan, u as logException, v as setSpanStatus, y as setTags } from "./logging-D37bayDc.js";
1
+ import { C as resolveGatewayCredential, S as getGatewayApiKey, _ as findProviderError, b as isProviderRetryError, c as COMPACTION_SUMMARY_PREFIX, d as isCompactionSummaryText, f as renderCurrentInstruction, g as createProviderError, h as ProviderError, i as completeText, l as MODEL_HANDOFF_SUMMARY_PREFIX, m as escapeXml, n as GEN_AI_SERVER_ADDRESS, o as resolveGatewayModel, p as unwrapCurrentInstruction, r as completeObject, s as ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX, t as GEN_AI_PROVIDER_NAME, u as hasCompactedConversationContext, v as getProviderErrorAttributes, x as MISSING_GATEWAY_CREDENTIALS_ERROR } from "./client-bRyPqwAV.js";
2
+ import { C as withSpan, F as isRecord$2, P as normalizeIdentityEmail, S as withLogContext, _ as setSpanAttributes, a as extractGenAiUsageSummary, b as summarizeMessageText, c as getTracePropagationHeaders, d as logInfo, f as logWarn, h as serializeGenAiAttribute, i as extractGenAiUsageAttributes, l as logError, p as normalizeGenAiFinishReason, s as getLogContextAttributesForSpan, u as logException, v as setSpanStatus, y as setTags } from "./logging-sNS84Yuu.js";
3
3
  import { _ as withActiveSpan, m as startInactiveSpan } from "./sentry-CD3SdJl-.js";
4
- 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-Auyq26XQ.js";
5
- import { h as normalizeSlackEmojiName, n as botConfig } from "./config-CIE83sR2.js";
4
+ 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-whGaV2TG.js";
5
+ import { h as normalizeSlackEmojiName, n as botConfig } from "./config-EtF2uEaW.js";
6
6
  import { a as modelIdForProfile, c as TURN_REASONING_LEVELS, i as formatModelProfiles, o as modelProfileSchema, r as formatModelProfile, s as profileConfig, t as ModelProfileNotConfiguredError } from "./model-profile-CZmVoGdX.js";
7
- import { _ as parseSlackMessageTs, g as parseSlackUserId, h as parseSlackTeamId, i as credentialUserSubjectId, l as isUserActor, m as parseSlackChannelReferenceId, n as credentialContextSchema, p as parseSlackChannelId, t as credentialContextForActor } from "./context-B45_WqVX.js";
8
- import { A as tryWorkspaceRepoCheckoutPath, B as downloadPrivateSlackFile, C as invalidateReadySnapshot, D as SANDBOX_RUNTIME, E as setWorkspaceSnapshotBuild, Ft as getConversationStore, It as getDb, J as withSlackRetries, K as normalizeSlackConversationId, Lt as getSqlExecutor, M as resolveChannelCapabilities, Nt as getConversationEventStore, O as deleteWorkspaceSnapshotBuilders, Pt as getConversationMessageSearchStore, Q as readActorIdentity, S as WorkspaceValidationError, T as setWorkspaceSnapshot, U as getSlackClient, V as getFilePermalink, W as isConversationScopedChannel, Xt as parseDestination, _ as deleteWorkspace, at as STOP_WATCHING_TOOL_NAME, b as listWorkspaces, bt as createPluginLogger, c as getPluginTools, dt as findMatchingResourceEventSubscriptions, ft as listResourceEventSubscriptions, g as createWorkspace, ht as getDashboardTaskLink, it as RESOURCE_WATCH_TOOL_SOURCE, j as workspaceRepoCheckoutPath, k as getWorkspaceSnapshotBuilder, l as getPluginUserPromptContributions, lt as createResourceEventSubscription, mt as getDashboardConversationLink, nt as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, ot as cancelResourceEventSubscription, pt as JUNIOR_THREAD_STATE_TTL_MS, r as createPluginHookRunner, s as getPluginSystemPromptContributions, st as cancelSubscriptions, tt as getSlackToolContext, u as getPlugins, ut as deliverResourceEventSubscription, v as getWorkspace, w as loadSnapshotsForProfile, x as updateWorkspace, y as getWorkspaceByName, z as SlackActionError } from "./agent-hooks-DNjlz2A-.js";
7
+ import { _ as parseSlackMessageTs, g as parseSlackUserId, h as parseSlackTeamId, i as credentialUserSubjectId, l as isUserActor, m as parseSlackChannelReferenceId, n as credentialContextSchema, p as parseSlackChannelId, t as credentialContextForActor } from "./context-Bplcgypl.js";
8
+ import { A as tryWorkspaceRepoCheckoutPath, B as downloadPrivateSlackFile, C as invalidateReadySnapshot, D as SANDBOX_RUNTIME, E as setWorkspaceSnapshotBuild, Gt as getDb, Ht as getConversationEventStore, J as withSlackRetries, K as normalizeSlackConversationId, Kt as getSqlExecutor, M as resolveChannelCapabilities, O as deleteWorkspaceSnapshotBuilders, Q as readActorIdentity, S as WorkspaceValidationError, T as setWorkspaceSnapshot, U as getSlackClient, Ut as getConversationMessageSearchStore, V as getFilePermalink, W as isConversationScopedChannel, Wt as getConversationStore, _ as deleteWorkspace, an as parseDestination, at as STOP_WATCHING_TOOL_NAME, b as listWorkspaces, bt as createPluginLogger, c as getPluginTools, dt as findMatchingWatches, ft as listWatches, g as createWorkspace, ht as getDashboardTaskLink, it as RESOURCE_WATCH_TOOL_SOURCE, j as workspaceRepoCheckoutPath, k as getWorkspaceSnapshotBuilder, l as getPluginUserPromptContributions, lt as createWatch, mt as getDashboardConversationLink, nt as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, ot as cancelSubscriptions, pt as JUNIOR_THREAD_STATE_TTL_MS, r as createPluginHookRunner, s as getPluginSystemPromptContributions, st as cancelWatch, tt as getSlackToolContext, u as getPlugins, ut as deliverWatch, v as getWorkspace, w as loadSnapshotsForProfile, x as updateWorkspace, y as getWorkspaceByName, z as SlackActionError } from "./agent-hooks-CuGjLjmR.js";
9
9
  import { n as juniorDestinations } from "./destinations-BeBiJeEM.js";
10
- import { D as juniorArtifacts, S as juniorAttachments, T as juniorIdentities, a as juniorSchedulerRuns, d as AGENT_INVOCATION_MAILBOX_STATUSES, g as juniorConversationBriefs, w as juniorConversations, y as juniorConversationAnnotations } from "./executor-BfbYPW63.js";
10
+ import { D as juniorArtifacts, S as juniorAttachments, T as juniorIdentities, a as juniorSchedulerRuns, d as AGENT_INVOCATION_MAILBOX_STATUSES, g as juniorConversationBriefs, w as juniorConversations, y as juniorConversationAnnotations } from "./executor-BW5qp0jC.js";
11
11
  import { A as briefLinkSchema, F as KNOWN_CONVERSATION_EVENT_TYPES, G as instructionProvenanceFor, K as sameActorIdentity, M as conversationBriefSchema, U as contextProvenance, W as instructionActors, j as briefOutcomeStatusSchema } from "./conversation-AA4R1VUn.js";
12
12
  import { a as listReferenceFiles, c as soulPathCandidates, l as worldPathCandidates } from "./package-discovery-7a9YqLhE.js";
13
- import { a as resolvePluginCommandEnv, c as getOAuthProviderErrorAttributes, i as resolveAuthTokenPlaceholder, o as OAuthProviderError, s as fetchWithBoundedOAuthErrorBodies, u as CredentialUnavailableError } from "./registry-DiR0-xRg.js";
14
- import { n as pluginCatalogRuntime } from "./catalog-runtime-TBR8n4e1.js";
15
- import { a as parseSkillInvocation, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-BhM5qyCF.js";
16
- import { A as normalizeToLf$1, At as retainRuntimeTurnContext, B as openConversationProjection, C as DEFAULT_SEARCH_COMMAND_TIMEOUT_MS, Ct as hasRuntimeTurnContext, D as getRipgrepSearchLocation, Dt as isToolResultError, E as collectFiles, Et as isContinuablePiBoundary, G as recordAuthorizationRequested, H as recordAttachmentsDelivered, I as loadConnectedMcpProviders, K as recordGuardianActionReviewed, L as loadConversationProjection, M as resolveWorkspacePath, Mt as trimTrailingAssistantMessages, N as truncateText$1, Nt as TURN_CONTEXT_TAG, O as isMissingPathError, Ot as isToolResultMessage, S as resolveRepositoryInstructionsForDirectories, St as getUserMessageInstructionText, T as RIPGREP_EXCLUDED_GLOBS, Tt as isAssistantMessage, V as recordAgentsInstructionsUpdated, X as recordTurnRoute, Y as recordToolExecutionStarted, _ as AGENTS_REPLACEMENT_NOTICE, _t as historyItemFromPiMessage, b as listRepositoryDirectories, bt as getPiMessageRole, f as TurnSliceLimitExceededError, g as AGENTS_REMOVAL_NOTICE, gt as getAgentContextInputLimitTokens, h as isTurnExecutionLimitExceededError, ht as getAgentContextCompactionTriggerTokens, j as positiveInteger$1, jt as stripRuntimeTurnContext, k as missingPathSearchResult, kt as normalizeToolNameFromResult, mt as estimateTextTokens, n as loadTurnCheckpoint, p as assertTurnToolCallLimit, q as recordMcpProviderConnected, r as saveTurnCheckpoint, t as continuableMessages, v as buildAgentsInstructionsMessage, vt as piMessageFromHistoryItem, w as MAX_TEXT_CHARS, x as renderAgentsInstructions, xt as getTerminalAssistantMessages, y as findVisibleAgentsInstructions, yt as extractAssistantText, z as loadTurnRoute } from "./checkpoint-BY47jJCB.js";
17
- import { a as hasAgentTurnUsage, c as generateShortTitle, l as resolveTaskTitle, o as ToolInputError, t as addAgentTurnUsage } from "./usage-D4A48Bdl.js";
18
- import { A as sleep$1, D as fenceLock, E as acquireActiveLock, F as sandboxSkillDir, I as sandboxSkillFile, L as sandboxSkillPathResolution, M as SANDBOX_REPOS_ROOT, N as SANDBOX_SKILLS_ROOT, P as SANDBOX_WORKSPACE_ROOT, _ as workspaceSnapshotNotReadyUserMessage, a as isAbortError, b as buildNonInteractiveShellScript, c as isSandboxCommandStreamInterruptedError, d as isSnapshottingError, f as throwSandboxOperationError, g as isWorkspaceSnapshotNotReadyError, h as getWorkspaceSnapshotNotReadyError, i as ensureDockerDaemon, j as SANDBOX_DATA_ROOT, k as withLock, l as isSandboxMissingError, m as WorkspaceSnapshotNotReadyError, n as hash, o as isAlreadyExistsError, p as wrapSandboxSetupError, r as isStale, s as isSandboxApiTransientError, t as create, u as isSandboxUnavailableError, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand, y as buildCommandScript } from "./profile-CSixooTi.js";
19
- import { $ as workspaceSnapshotFinishedEvent, B as createEventTask, C as SCHEDULED_TASK_SYSTEM_ACTOR, D as eventTaskMatchesDestination, E as eventTaskListToolResultSchema, F as effectiveTaskOutcomes, Ht as injectContinuationToolName, I as moveTaskOutcomes, L as resolveTaskOutcomes, M as requireEventTaskSlackContext, N as requireSupportedEventTaskTrigger, O as eventTaskSuccess, P as writableEventTask, Q as WORKSPACE_SNAPSHOT_READY_EVENT, R as taskOutcomeInputSchema, T as compactEventTask, Ut as juniorToolOutputSchema, V as deleteEventTask, W as getEventTask, Wt as makeStructuredToolOutput, X as getResourceEventCatalog, Y as saveEventTask, Z as WORKSPACE_SNAPSHOT_FAILED_EVENT, at as pluginSupportsEvent, c as parseSlackThreadId, ct as registeredResourceTypeSchema, et as workspaceSnapshotWatch, f as createScheduledTask, g as listScheduledTasksForTeam, i as readLiveAttachment, it as normalizeEventIdentifier, j as registeredEventTaskTriggerSchema, k as eventTaskToolResultSchema, lt as requireSupportedResourceEventMatch, nt as hasPluginResourceEventCatalogEntries, ot as registeredEventTypeSchema, pt as appendAndEnqueueInboundMessage, q as listEventTasksForTeam, rt as hasResourceEventCatalogEntries, s as storeAttachments, st as registeredResourceEventMatchSchema, t as incrementStat, tt as eventNamespaceSchema, ut as resourceEventGuidance, v as readScheduledTask, y as saveScheduledTask } from "./stats-DKRP4rsY.js";
20
- import { _ as isTurnInputCommitLostError, c as sanitizeAssistantText, f as CooperativeTurnYieldError, l as NO_REPLY_MARKER, n as canReusePendingAuthLink, o as decideReply, p as TurnInputCommitLostError, s as getAssistantReplyText, t as abandonReplacedPendingAuth, u as isNoReplyMarker } from "./pending-auth-BPUzcs7n.js";
21
- import { C as toolInvocationDestination, S as surfaceFromRun, _ as uploadFilesToConversation, b as assertRunConsistency, h as postSlackMessage, i as formatProviderLabel, m as getSlackMessagePermalink, o as resolveBaseUrl, p as addReactionToMessage, r as deliverOAuthAuthorization, s as startOAuthFlow, v as RetryableDeliveryError, x as isAgentRunFeatureDisabled, y as actorFromRun } from "./agent-runner-E67lFrDG.js";
22
- import { r as RESOURCE_EVENT_AUTHOR_ID } from "./prompt-3gqNY1Ka.js";
23
- import { a as createSandboxSession, c as postinstall, d as getSandboxResources, i as bindSandboxFileSystem, l as setSnapshotSpanAttributes, n as isMissingError, o as stopSession, r as resolve$1, s as dependencies } from "./resolve-Bn5q__9b.js";
13
+ import { a as resolvePluginCommandEnv, c as getOAuthProviderErrorAttributes, i as resolveAuthTokenPlaceholder, o as OAuthProviderError, s as fetchWithBoundedOAuthErrorBodies, u as CredentialUnavailableError } from "./registry-Cyww_jnC.js";
14
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-D8YUMNhb.js";
15
+ import { a as parseSkillInvocation, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-DhL_wXEp.js";
16
+ import { A as normalizeToLf$1, At as retainRuntimeTurnContext, B as openConversationProjection, C as DEFAULT_SEARCH_COMMAND_TIMEOUT_MS, Ct as hasRuntimeTurnContext, D as getRipgrepSearchLocation, Dt as isToolResultError, E as collectFiles, Et as isContinuablePiBoundary, G as recordAuthorizationRequested, H as recordAttachmentsDelivered, I as loadConnectedMcpProviders, K as recordGuardianActionReviewed, L as loadConversationProjection, M as resolveWorkspacePath, Mt as trimTrailingAssistantMessages, N as truncateText$1, Nt as TURN_CONTEXT_TAG, O as isMissingPathError, Ot as isToolResultMessage, S as resolveRepositoryInstructionsForDirectories, St as getUserMessageInstructionText, T as RIPGREP_EXCLUDED_GLOBS, Tt as isAssistantMessage, V as recordAgentsInstructionsUpdated, X as recordTurnRoute, Y as recordToolExecutionStarted, _ as AGENTS_REPLACEMENT_NOTICE, _t as historyItemFromPiMessage, b as listRepositoryDirectories, bt as getPiMessageRole, f as TurnSliceLimitExceededError, g as AGENTS_REMOVAL_NOTICE, gt as getAgentContextInputLimitTokens, h as isTurnExecutionLimitExceededError, ht as getAgentContextCompactionTriggerTokens, j as positiveInteger$1, jt as stripRuntimeTurnContext, k as missingPathSearchResult, kt as normalizeToolNameFromResult, mt as estimateTextTokens, n as loadTurnCheckpoint, p as assertTurnToolCallLimit, q as recordMcpProviderConnected, r as saveTurnCheckpoint, t as continuableMessages, v as buildAgentsInstructionsMessage, vt as piMessageFromHistoryItem, w as MAX_TEXT_CHARS, x as renderAgentsInstructions, xt as getTerminalAssistantMessages, y as findVisibleAgentsInstructions, yt as extractAssistantText, z as loadTurnRoute } from "./checkpoint-FKMcINix.js";
17
+ import { a as hasAgentTurnUsage, c as generateShortTitle, l as resolveTaskTitle, o as ToolInputError, t as addAgentTurnUsage } from "./usage-BMuAlKIW.js";
18
+ import { A as sleep$1, D as fenceLock, E as acquireActiveLock, F as sandboxSkillDir, I as sandboxSkillFile, L as sandboxSkillPathResolution, M as SANDBOX_REPOS_ROOT, N as SANDBOX_SKILLS_ROOT, P as SANDBOX_WORKSPACE_ROOT, _ as workspaceSnapshotNotReadyUserMessage, a as isAbortError, b as buildNonInteractiveShellScript, c as isSandboxCommandStreamInterruptedError, d as isSnapshottingError, f as throwSandboxOperationError, g as isWorkspaceSnapshotNotReadyError, h as getWorkspaceSnapshotNotReadyError, i as ensureDockerDaemon, j as SANDBOX_DATA_ROOT, k as withLock, l as isSandboxMissingError, m as WorkspaceSnapshotNotReadyError, n as hash, o as isAlreadyExistsError, p as wrapSandboxSetupError, r as isStale, s as isSandboxApiTransientError, t as create, u as isSandboxUnavailableError, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand, y as buildCommandScript } from "./profile-BfLMVhWo.js";
19
+ import { $ as workspaceSnapshotFinishedEvent, B as createEventAutomation, C as SCHEDULED_AUTOMATION_SYSTEM_ACTOR, D as eventAutomationMatchesDestination, E as eventAutomationListToolResultSchema, F as effectiveTaskOutcomes, Ht as injectContinuationToolName, I as moveTaskOutcomes, L as resolveTaskOutcomes, M as requireEventAutomationSlackContext, N as requireSupportedEventAutomationTrigger, O as eventAutomationToolResult, P as writableEventAutomation, Q as WORKSPACE_SNAPSHOT_READY_EVENT, R as taskOutcomeInputSchema, T as compactEventAutomation, Ut as juniorToolOutputSchema, V as deleteEventAutomation, W as getEventAutomation, Wt as makeStructuredToolOutput, X as getEventCatalog, Y as saveEventAutomation, Z as WORKSPACE_SNAPSHOT_FAILED_EVENT, at as normalizeCatalogEventIdentifier, c as parseSlackThreadId, ct as registeredEventTypeSchema, et as workspaceSnapshotWatch, f as createScheduledAutomation, g as listScheduledAutomationsForTeam, i as readLiveAttachment, it as hasPluginEventCatalogEntries, j as registeredEventAutomationTriggerSchema, k as eventAutomationToolResultSchema, lt as registeredResourceTypeSchema, nt as eventNamespaceSchema, ot as pluginSupportsEvent, pt as appendAndEnqueueInboundMessage, q as listEventAutomationsForTeam, rt as hasEventCatalogEntries, s as storeAttachments, st as registeredEventMatchSchema, t as incrementStat, tt as eventGuidance, ut as requireSupportedEventMatch, v as readScheduledAutomation, y as saveScheduledAutomation } from "./stats-Cq5w_Awk.js";
20
+ import { _ as isTurnInputCommitLostError, c as sanitizeAssistantText, f as CooperativeTurnYieldError, l as NO_REPLY_MARKER, n as canReusePendingAuthLink, o as decideReply, p as TurnInputCommitLostError, s as getAssistantReplyText, t as abandonReplacedPendingAuth, u as isNoReplyMarker } from "./pending-auth-CRJCt9Ux.js";
21
+ import { C as toolInvocationDestination, S as surfaceFromRun, _ as uploadFilesToConversation, b as assertRunConsistency, h as postSlackMessage, i as formatProviderLabel, m as getSlackMessagePermalink, o as resolveBaseUrl, p as addReactionToMessage, r as deliverOAuthAuthorization, s as startOAuthFlow, v as RetryableDeliveryError, x as isAgentRunFeatureDisabled, y as actorFromRun } from "./agent-runner-Dz1PMKP0.js";
22
+ import { r as EVENT_AUTHOR_ID } from "./prompt-x-0ZtTyb.js";
23
+ import { a as createSandboxSession, c as postinstall, d as getSandboxResources, i as bindSandboxFileSystem, l as setSnapshotSpanAttributes, n as isMissingError, o as stopSession, r as resolve$1, s as dependencies } from "./resolve-BApIFQXX.js";
24
24
  import { t as getVercelConversationWorkQueue } from "./vercel-queue-DIkVcfK4.js";
25
- import { a as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-CyTc24Es.js";
25
+ import { a as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-BIHNIEIX.js";
26
26
  import { n as privateTraceResultAttributes } from "./private-trace-result-BLvBjy_e.js";
27
27
  import { streamSimple } from "@earendil-works/pi-ai/compat";
28
28
  import { createGatewayProvider } from "@ai-sdk/gateway";
@@ -33,7 +33,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
33
33
  import { z } from "zod";
34
34
  import { createHash, createHmac, randomUUID, timingSafeEqual } from "node:crypto";
35
35
  import { and, desc, eq, gt, gte, inArray, isNull, lt, ne, notExists, or, sql } from "drizzle-orm";
36
- import { EgressAuthRequired, EgressPolicyDenied, PluginToolInputError, actorSchema, destinationSchema, missingToolAnnotationKeys, pluginAuthorizationSchema, pluginCredentialHeaderTransformSchema, pluginCredentialResultSchema, pluginGrantSchema, pluginProviderAccountSchema, pluginStoredTokensSchema, resourceEventSchema, resourceEventSubscriptionResultSchema, sourceSchema, stableResourceEventMatchKey, taskOutcomeSchema } from "@sentry/junior-plugin-api";
36
+ import { EgressAuthRequired, EgressPolicyDenied, PluginToolInputError, actorSchema, destinationSchema, eventSchema, missingToolAnnotationKeys, pluginAuthorizationSchema, pluginCredentialHeaderTransformSchema, pluginCredentialResultSchema, pluginGrantSchema, pluginProviderAccountSchema, pluginStoredTokensSchema, sourceSchema, stableEventMatchKey, watchResultSchema } from "@sentry/junior-plugin-api";
37
37
  import { alias } from "drizzle-orm/pg-core";
38
38
  import { Agent, estimateContextTokens } from "@earendil-works/pi-agent-core";
39
39
  import fs from "node:fs/promises";
@@ -405,21 +405,22 @@ function buildTurnResult(input) {
405
405
  "app.ai.generated_files": input.generatedFileCount
406
406
  });
407
407
  const usedPrimaryText = Boolean(rawPrimaryText);
408
+ const suppressedPrimaryText = Boolean(rawPrimaryText && !noReplyRequested && !primaryText);
408
409
  let outcome;
409
410
  if (isProviderError) outcome = "provider_error";
411
+ else if (suppressedPrimaryText) outcome = "execution_failure";
410
412
  else if (primaryText || completedWithoutTerminalText) outcome = "success";
411
413
  else outcome = "execution_failure";
412
- const resolvedOutcome = Boolean(rawPrimaryText && !noReplyRequested && !primaryText) ? "execution_failure" : outcome;
413
414
  if (shouldTrace) logInfo("agent.message.generated", {
414
415
  "app.message.kind": "assistant_outbound",
415
416
  "app.message.length": primaryText.length,
416
417
  "app.message.output": summarizeMessageText(primaryText),
417
- "app.ai.outcome": resolvedOutcome,
418
+ "app.ai.outcome": outcome,
418
419
  "app.ai.assistant_messages": assistantMessages.length,
419
420
  ...stopReason ? { "gen_ai.response.finish_reasons": [stopReason] } : void 0
420
421
  });
421
422
  const resolvedDiagnostics = {
422
- outcome: resolvedOutcome,
423
+ outcome,
423
424
  modelId,
424
425
  assistantMessageCount: assistantMessages.length,
425
426
  reasoningLevel: executionProfile.reasoningLevel,
@@ -431,7 +432,7 @@ function buildTurnResult(input) {
431
432
  usage,
432
433
  stopReason,
433
434
  errorMessage,
434
- providerError: resolvedOutcome === "provider_error" && errorMessage ? createProviderError(errorMessage, {
435
+ providerError: outcome === "provider_error" && errorMessage ? createProviderError(errorMessage, {
435
436
  modelId,
436
437
  retryable: lastAssistant !== void 0 && isAssistantMessage(lastAssistant) && isRetryableAssistantError(lastAssistant)
437
438
  }) : void 0
@@ -1146,12 +1147,12 @@ const TOOL_POLICY_RULES = [
1146
1147
  "- After changing files, name the changed paths and summarize the completed result in the final answer.",
1147
1148
  "- If a sandbox-backed tool reports that sandbox execution is unavailable, treat that as a blocker for local file/shell inspection; do not pretend host files were inspected.",
1148
1149
  "- For user-provided URLs, use `webFetch`; for discovery, use `webSearch` then fetch/read promising sources; for current time/date context, use `systemTime`.",
1149
- "- When searchResourceEventTypes is exposed, use it only when the user asks what resource events are supported or the required resource type or event name is unclear. It discovers options but does not watch a resource or create a task. When explaining how results can be used, distinguish temporary current-thread watches from durable event tasks.",
1150
- "- When a tool result includes a subscription, those events are already watched; do not call watchResourceEvents for them. When a tool result includes a subscribable resource with suggestedEvents, use watchResourceEvents only for those remaining events that serve the current intent. If suggestedEvents is empty or omitted, do not invent a watch. Do not create scheduled polling tasks for events a watch can deliver. Write a concise intent summary, and tell the user when the temporary watch expires. Stop only the requested watch by id unless the user explicitly asks to stop every watch in the thread.",
1151
- "- Use createEventTask only when the user explicitly asks for an event task or durable whenever-this-happens-do-X automation. Ordinary watch, notify, and tell-me-when requests use watchResourceEvents. When an event task's resource and events are known, create it without redundant confirmation.",
1152
- "- Event tasks make the task creator's connected credentials available by default when the requested work needs user-bound authorization. Do not ask for separate confirmation merely to use credentials needed for the requested work. On creation, omit credentialMode for the creator default and set system only when the creator explicitly requires it. For later changes, creator always means the task's original createdBy actor, never the current requester. If the requester is not that creator, do not attempt to enable creator credential use or suggest that confirmation could authorize it.",
1153
- "- Event tasks list for the current destination, not one thread. Public tasks can also be updated or deleted by task id from another destination in the same workspace. When listing them, use createdBy to explain creator-only credential changes and warn when triggerAvailable is false; an unavailable task remains stored but cannot receive events until its plugin event is enabled again.",
1154
- "- Scheduled tasks make the task creator's connected credentials available by default when the requested work needs user-bound authorization. Do not ask for separate confirmation merely to use credentials needed for the requested work. On creation, omit credential_mode for the creator default and set system only when the creator explicitly requires it. For later changes, creator always means the task's original created_by actor, never the current requester. If the requester is not that creator, do not attempt to enable creator credential use or suggest that confirmation could authorize it.",
1150
+ "- When searchEventTypes is exposed, use it only when the user asks what events are supported or the required resource type or event name is unclear. It discovers options but does not watch a resource or create an automation. When explaining how results can be used, distinguish temporary current-thread watches from durable event automations.",
1151
+ "- When a tool result includes a subscription, those events are already watched; do not call watchEvents for them. When a tool result includes a subscribable resource with suggestedEvents, use watchEvents only for those remaining events that serve the current intent. If suggestedEvents is empty or omitted, do not invent a watch. Do not create scheduled polling tasks for events a watch can deliver. Write a concise intent summary, and tell the user when the temporary watch expires. Stop only the requested watch by id unless the user explicitly asks to stop every watch in the thread.",
1152
+ "- Use createEventAutomation only when the user explicitly asks for an event automation or durable whenever-this-happens-do-X automation. Ordinary watch, notify, and tell-me-when requests use watchEvents. When an event automation's resource and events are known, create it without redundant confirmation.",
1153
+ "- Event automations make the automation creator's connected credentials available by default when the requested work needs user-bound authorization. Do not ask for separate confirmation merely to use credentials needed for the requested work. On creation, omit credentialMode for the creator default and set system only when the creator explicitly requires it. For later changes, creator always means the automation's original createdBy actor, never the current requester. If the requester is not that creator, do not attempt to enable creator credential use or suggest that confirmation could authorize it.",
1154
+ "- Event automations list for the current destination, not one thread. Public automations can also be updated or deleted by automation id from another destination in the same workspace. When listing them, use createdBy to explain creator-only credential changes and warn when trigger.available is false; an unavailable automation remains stored but cannot receive events until its plugin event is enabled again.",
1155
+ "- Scheduled automations make the automation creator's connected credentials available by default when the requested work needs user-bound authorization. Do not ask for separate confirmation merely to use credentials needed for the requested work. On creation, omit credentialMode for the creator default and set system only when the creator explicitly requires it. For later changes, creator always means the automation's original createdBy actor, never the current requester. If the requester is not that creator, do not attempt to enable creator credential use or suggest that confirmation could authorize it.",
1155
1156
  "- When another model profile fits the task better, call `handoff` before substantial work. Follow the profile list and selection rules in the tool description.",
1156
1157
  "- Run `jr-rpc config get|set|unset|list` for provider defaults and `jr-rpc plugins list` for installed plugin introspection as standalone bash commands; do not chain them with `cd`, `&&`, pipes, or provider commands.",
1157
1158
  "- If the first result is empty, stale, ambiguous, or incomplete, try a focused alternate query, path, command, or source before concluding the answer cannot be verified."
@@ -1267,14 +1268,14 @@ function formatSourceLines(source) {
1267
1268
  ...source.messageTs ? [`- source.message_ts: ${escapeXml(source.messageTs)}`] : [],
1268
1269
  ...source.threadTs ? [`- source.thread_ts: ${escapeXml(source.threadTs)}`] : []
1269
1270
  ];
1270
- case "resource_event": return [
1271
- "- source.kind: resource_event",
1271
+ case "event": return [
1272
+ "- source.kind: event",
1272
1273
  `- source.namespace: ${escapeXml(source.namespace)}`,
1273
1274
  `- source.identifier: ${escapeXml(source.identifier)}`,
1274
1275
  `- source.event_type: ${escapeXml(source.eventType)}`
1275
1276
  ];
1276
- case "scheduled_task":
1277
- case "event_task":
1277
+ case "scheduled_automation":
1278
+ case "event_automation":
1278
1279
  case "plugin_dispatch":
1279
1280
  case "agent_invocation": return [`- source.kind: ${source.kind}`];
1280
1281
  }
@@ -2490,8 +2491,9 @@ async function prepareWorkspaceRepositories(params) {
2490
2491
  const { sandbox, workspace, signal } = params;
2491
2492
  signal?.throwIfAborted();
2492
2493
  await params.applyNetworkPolicy(sandbox);
2493
- await params.prepareRepositories?.(sandbox, workspace, signal);
2494
+ const finalize = await params.prepareRepositories?.(sandbox, workspace, signal);
2494
2495
  if (params.removeCredentialRoute) await sandbox.update({ networkPolicy: "allow-all" });
2496
+ await finalize?.();
2495
2497
  }
2496
2498
  /** Return bounded setup output for a Workspace failure. */
2497
2499
  function workspaceSetupFailureDetail(input) {
@@ -2614,7 +2616,7 @@ function emptyState(nowMs) {
2614
2616
  /** True when this Source starts an automated Turn rather than a user Turn. */
2615
2617
  function isAutomatedTurnSource(source) {
2616
2618
  if (!source) return false;
2617
- return source.kind === "resource_event" || source.kind === "event_task" || source.kind === "scheduled_task" || source.kind === "plugin_dispatch" || source.kind === "agent_invocation";
2619
+ return source.kind === "event" || source.kind === "event_automation" || source.kind === "scheduled_automation" || source.kind === "plugin_dispatch" || source.kind === "agent_invocation";
2618
2620
  }
2619
2621
  /** Plain notice when automatic updates stop until the user replies. */
2620
2622
  function buildAutomatedTurnLimitResponse(args) {
@@ -2826,15 +2828,15 @@ function renderTaskInput(args) {
2826
2828
  return lines.join("\n");
2827
2829
  }
2828
2830
  //#endregion
2829
- //#region src/chat/resource-events/notification.ts
2831
+ //#region src/chat/events/notification.ts
2830
2832
  /**
2831
2833
  * Render the runtime-owned conversation message for a subscribed event.
2832
2834
  *
2833
2835
  * Keep this short: facts the model cannot reconstruct, plus a one-line handling
2834
2836
  * contract. Stable delivery rules live in runtime and docs, not this prompt.
2835
2837
  */
2836
- function renderResourceEventNotificationText(subscription, event) {
2837
- const guidance = resourceEventGuidance(getResourceEventCatalog(), event.namespace, subscription.resourceType, event.eventType);
2838
+ function renderEventNotificationText(subscription, event) {
2839
+ const guidance = eventGuidance(getEventCatalog(), event.namespace, subscription.resourceType, event.eventType);
2838
2840
  return renderTaskInput({
2839
2841
  about: subscription.label,
2840
2842
  instructions: subscription.intent,
@@ -2844,21 +2846,21 @@ function renderResourceEventNotificationText(subscription, event) {
2844
2846
  externalText: event.untrustedText
2845
2847
  });
2846
2848
  }
2847
- /** Whether mailbox metadata is a plain resource-event wake. */
2848
- function isResourceEventMailboxMetadata(value) {
2849
+ /** Whether mailbox metadata is a plain event wake. */
2850
+ function isEventMailboxMetadata(value) {
2849
2851
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
2850
2852
  const record = value;
2851
- if (record.kind !== "resource_event") return false;
2852
- const resourceEvent = record.resourceEvent;
2853
- if (!resourceEvent || typeof resourceEvent !== "object" || Array.isArray(resourceEvent)) return false;
2854
- const fields = resourceEvent;
2853
+ if (record.kind !== "event") return false;
2854
+ const event = record.event;
2855
+ if (!event || typeof event !== "object" || Array.isArray(event)) return false;
2856
+ const fields = event;
2855
2857
  return typeof fields.eventKey === "string" && typeof fields.eventType === "string" && typeof fields.namespace === "string" && typeof fields.identifier === "string" && typeof fields.subscriptionId === "string" && (fields.trustedSummary === void 0 || typeof fields.trustedSummary === "string");
2856
2858
  }
2857
2859
  /** Build plain conversation mailbox input for one matched watch. */
2858
- function createResourceEventInboundMessage(input) {
2860
+ function createEventInboundMessage(input) {
2859
2861
  const metadata = {
2860
- kind: "resource_event",
2861
- resourceEvent: {
2862
+ kind: "event",
2863
+ event: {
2862
2864
  eventKey: input.event.eventKey,
2863
2865
  eventType: input.event.eventType,
2864
2866
  namespace: input.event.namespace,
@@ -2870,25 +2872,25 @@ function createResourceEventInboundMessage(input) {
2870
2872
  return {
2871
2873
  conversationId: input.subscription.conversationId,
2872
2874
  createdAtMs: input.event.occurredAtMs,
2873
- inboundMessageId: `resource-event:${input.subscription.id}:${input.event.eventKey}`,
2875
+ inboundMessageId: `event:${input.subscription.id}:${input.event.eventKey}`,
2874
2876
  delivery: "defer",
2875
- source: "resource_event",
2877
+ source: "event",
2876
2878
  receivedAtMs: input.receivedAtMs ?? Date.now(),
2877
2879
  input: {
2878
2880
  text: input.text,
2879
- authorId: RESOURCE_EVENT_AUTHOR_ID,
2881
+ authorId: EVENT_AUTHOR_ID,
2880
2882
  metadata
2881
2883
  }
2882
2884
  };
2883
2885
  }
2884
2886
  /**
2885
- * Enqueue a resource event as normal conversation mailbox input.
2887
+ * Enqueue a event as normal conversation mailbox input.
2886
2888
  *
2887
2889
  * The watch only names the conversation. Destination stays on the conversation
2888
2890
  * and is applied when the worker runs. After too many automated Turns with no
2889
2891
  * user Turn, later wakes stay quiet until a user message clears the pause.
2890
2892
  */
2891
- async function enqueueResourceEventNotification(args) {
2893
+ async function enqueueEventNotification(args) {
2892
2894
  const maxTurns = botConfig.maxConsecutiveAutomatedTurns;
2893
2895
  const decision = await admitAutomatedTurn({
2894
2896
  conversationId: args.subscription.conversationId,
@@ -2897,12 +2899,12 @@ async function enqueueResourceEventNotification(args) {
2897
2899
  state: args.state
2898
2900
  });
2899
2901
  if (decision.status === "paused") {
2900
- logInfo("resource_events.automated_turn_limit.paused", {
2902
+ logInfo("events.automated_turn_limit.paused", {
2901
2903
  conversationId: args.subscription.conversationId,
2902
2904
  "app.automated_turn_limit.consecutive": decision.consecutiveAutomatedTurns,
2903
2905
  "app.automated_turn_limit.max": maxTurns,
2904
- "app.resource_event.event_type": args.event.eventType,
2905
- "app.resource_event.namespace": args.event.namespace
2906
+ "app.event.event_type": args.event.eventType,
2907
+ "app.event.namespace": args.event.namespace
2906
2908
  });
2907
2909
  if (decision.shouldPostNotice) await postAutomatedTurnLimitNoticeForConversation({
2908
2910
  conversationId: args.subscription.conversationId,
@@ -2911,9 +2913,9 @@ async function enqueueResourceEventNotification(args) {
2911
2913
  });
2912
2914
  return { status: "duplicate" };
2913
2915
  }
2914
- const text = renderResourceEventNotificationText(args.subscription, args.event);
2916
+ const text = renderEventNotificationText(args.subscription, args.event);
2915
2917
  return await appendAndEnqueueInboundMessage({
2916
- message: createResourceEventInboundMessage({
2918
+ message: createEventInboundMessage({
2917
2919
  event: args.event,
2918
2920
  subscription: {
2919
2921
  conversationId: args.subscription.conversationId,
@@ -2926,12 +2928,12 @@ async function enqueueResourceEventNotification(args) {
2926
2928
  });
2927
2929
  }
2928
2930
  //#endregion
2929
- //#region src/chat/resource-events/ingest.ts
2930
- /** Match a normalized resource event and enqueue notifications into conversations. */
2931
- async function ingestResourceEvent(input, options) {
2932
- const event = resourceEventSchema.parse(input);
2931
+ //#region src/chat/events/ingest.ts
2932
+ /** Match a normalized event and enqueue notifications into conversations. */
2933
+ async function ingestEvent(input, options) {
2934
+ const event = eventSchema.parse(input);
2933
2935
  const nowMs = options.nowMs ?? Date.now();
2934
- const subscriptions = await findMatchingResourceEventSubscriptions({
2936
+ const subscriptions = await findMatchingWatches({
2935
2937
  data: event.data,
2936
2938
  eventType: event.eventType,
2937
2939
  nowMs,
@@ -2943,7 +2945,7 @@ async function ingestResourceEvent(input, options) {
2943
2945
  const errors = [];
2944
2946
  const waitDeadlineMs = Date.now() + 1e4;
2945
2947
  for (const subscription of subscriptions) try {
2946
- if (await deliverResourceEventSubscription({
2948
+ if (await deliverWatch({
2947
2949
  data: event.data,
2948
2950
  eventType: event.eventType,
2949
2951
  namespace: event.namespace,
@@ -2954,7 +2956,7 @@ async function ingestResourceEvent(input, options) {
2954
2956
  subscription,
2955
2957
  waitDeadlineMs,
2956
2958
  deliver: async (current) => {
2957
- return (await enqueueResourceEventNotification({
2959
+ return (await enqueueEventNotification({
2958
2960
  event,
2959
2961
  queue: options.queue,
2960
2962
  state: options.state,
@@ -2965,7 +2967,7 @@ async function ingestResourceEvent(input, options) {
2965
2967
  } catch (error) {
2966
2968
  errors.push(error);
2967
2969
  }
2968
- if (errors.length > 0) throw new AggregateError(errors, "Failed to deliver one or more resource event subscriptions");
2970
+ if (errors.length > 0) throw new AggregateError(errors, "Failed to deliver one or more watches");
2969
2971
  return { enqueued };
2970
2972
  }
2971
2973
  //#endregion
@@ -3361,7 +3363,7 @@ const SNAPSHOT_BUILD_SYSTEM_ACTOR = {
3361
3363
  /** Leave time to send the next job before this request ends. */
3362
3364
  const JOB_STOP_BUFFER_MS = 4e4;
3363
3365
  async function publishFinishedEvent(input) {
3364
- await ingestResourceEvent(workspaceSnapshotFinishedEvent(input), { queue: getVercelConversationWorkQueue() });
3366
+ await ingestEvent(workspaceSnapshotFinishedEvent(input), { queue: getVercelConversationWorkQueue() });
3365
3367
  }
3366
3368
  function createSnapshotBuildHelpers() {
3367
3369
  const credentials = credentialContextForActor(SNAPSHOT_BUILD_SYSTEM_ACTOR);
@@ -3375,9 +3377,7 @@ function createSnapshotBuildHelpers() {
3375
3377
  await sandbox.update({ networkPolicy });
3376
3378
  return networkPolicy;
3377
3379
  };
3378
- const prepareRepositories = async (sandbox, target, signal) => {
3379
- await pluginHooks.prepareWorkspace(sandbox, target.repos, signal);
3380
- };
3380
+ const prepareRepositories = async (sandbox, target, signal) => await pluginHooks.prepareWorkspace(sandbox, target.repos, signal);
3381
3381
  return {
3382
3382
  applyNetworkPolicy,
3383
3383
  prepareRepositories
@@ -3887,7 +3887,14 @@ function createSandboxRuntime(options) {
3887
3887
  let networkPolicyKey;
3888
3888
  try {
3889
3889
  networkPolicyKey = await applyNetworkPolicy(createdSandbox);
3890
- if (workspace) await options.onWorkspacePrepare?.(createdSandbox, workspace, signal);
3890
+ if (workspace) {
3891
+ const finalize = await options.onWorkspacePrepare?.(createdSandbox, workspace, signal);
3892
+ if (options.createNetworkPolicy) {
3893
+ await createdSandbox.update({ networkPolicy: "allow-all" });
3894
+ networkPolicyKey = void 0;
3895
+ }
3896
+ await finalize?.();
3897
+ }
3891
3898
  await prepareSandbox(createdSandbox);
3892
3899
  } catch (error) {
3893
3900
  if (workspace) await stopSession(createdSandbox);
@@ -7144,7 +7151,7 @@ function createSpawnAgentTool(spawnAgent) {
7144
7151
  });
7145
7152
  }
7146
7153
  //#endregion
7147
- //#region src/chat/tools/list-resource-event-subscriptions.ts
7154
+ //#region src/chat/tools/list-watches.ts
7148
7155
  const listedResourceWatchSchema = z.object({
7149
7156
  id: z.string().min(1),
7150
7157
  label: z.string().min(1),
@@ -7158,8 +7165,8 @@ const listedResourceWatchSchema = z.object({
7158
7165
  }).strict();
7159
7166
  const resultDataSchema$2 = z.object({ subscriptions: z.array(listedResourceWatchSchema) }).strict();
7160
7167
  const outputSchema$5 = juniorToolOutputSchema.merge(resultDataSchema$2);
7161
- /** Create the tool that lists active resource watches for this conversation. */
7162
- function createListResourceEventSubscriptionsTool(context) {
7168
+ /** Create the tool that lists active watches for this conversation. */
7169
+ function createListWatchesTool(context) {
7163
7170
  return zodTool({
7164
7171
  annotations: {
7165
7172
  destructiveHint: false,
@@ -7167,13 +7174,13 @@ function createListResourceEventSubscriptionsTool(context) {
7167
7174
  openWorldHint: false,
7168
7175
  readOnlyHint: true
7169
7176
  },
7170
- description: "List active resource event subscriptions for the current conversation.",
7177
+ description: "List active watches for the current conversation.",
7171
7178
  exposure: "deferred",
7172
7179
  source: RESOURCE_WATCH_TOOL_SOURCE,
7173
7180
  inputSchema: z.object({}).strict(),
7174
7181
  outputSchema: outputSchema$5,
7175
7182
  async execute() {
7176
- return { subscriptions: (await listResourceEventSubscriptions({ conversationId: context.conversationId })).map((subscription) => ({
7183
+ return { subscriptions: (await listWatches({ conversationId: context.conversationId })).map((subscription) => ({
7177
7184
  id: subscription.id,
7178
7185
  label: subscription.label,
7179
7186
  identifier: subscription.identifier,
@@ -7188,7 +7195,7 @@ function createListResourceEventSubscriptionsTool(context) {
7188
7195
  });
7189
7196
  }
7190
7197
  //#endregion
7191
- //#region src/chat/tools/search-resource-event-types.ts
7198
+ //#region src/chat/tools/search-event-types.ts
7192
7199
  const DEFAULT_SEARCH_RESULTS = 10;
7193
7200
  const MAX_SEARCH_RESULTS = 20;
7194
7201
  const searchedResourceTypeSchema = z.object({
@@ -7224,8 +7231,8 @@ function searchableResourceTypes(catalog) {
7224
7231
  ...resourceType.matchFields ? { matchFields: resourceType.matchFields } : void 0
7225
7232
  }))).sort((left, right) => left.namespace.localeCompare(right.namespace) || left.type.localeCompare(right.type));
7226
7233
  }
7227
- /** Create the read-only tool that searches enabled resource event types. */
7228
- function createSearchResourceEventTypesTool(catalog) {
7234
+ /** Create the read-only tool that searches enabled event types. */
7235
+ function createSearchEventTypesTool(catalog) {
7229
7236
  return zodTool({
7230
7237
  annotations: {
7231
7238
  destructiveHint: false,
@@ -7233,9 +7240,9 @@ function createSearchResourceEventTypesTool(catalog) {
7233
7240
  openWorldHint: false,
7234
7241
  readOnlyHint: true
7235
7242
  },
7236
- description: "Search the resource event types currently enabled without creating anything. Includes plugin resources and core Workspace snapshot events. Use watchResourceEvents for temporary updates in the current conversation; use createEventTask for durable automation. This tool does not watch a resource, create a task, or list concrete resources.",
7243
+ description: "Search the event types currently enabled without creating anything. Includes plugin resources and core Workspace snapshot events. Use watchEvents for temporary updates in the current conversation; use createEventAutomation for durable automation. This tool does not watch a resource, create an automation, or list concrete resources.",
7237
7244
  inputSchema: z.object({
7238
- query: z.string().nullable().describe("Optional terms matching a namespace, resource type, or event name. Empty lists all enabled resource event types.").optional(),
7245
+ query: z.string().nullable().describe("Optional terms matching a namespace, resource type, or event name. Empty lists all enabled event types.").optional(),
7239
7246
  namespace: eventNamespaceSchema(catalog).nullable().describe("Optional enabled plugin namespace to search within.").optional(),
7240
7247
  maxResults: z.number().int().min(1).max(MAX_SEARCH_RESULTS).nullable().describe("Maximum matching resource types to return.").optional()
7241
7248
  }).strict(),
@@ -7264,13 +7271,13 @@ function createSearchResourceEventTypesTool(catalog) {
7264
7271
  });
7265
7272
  }
7266
7273
  //#endregion
7267
- //#region src/chat/tools/stop-watching-resources.ts
7274
+ //#region src/chat/tools/stop-watches.ts
7268
7275
  const resultDataSchema$1 = z.object({
7269
7276
  watching_status: z.literal("stopped"),
7270
7277
  stoppedIds: z.array(z.string().min(1))
7271
7278
  }).strict();
7272
7279
  const outputSchema$3 = juniorToolOutputSchema.merge(resultDataSchema$1);
7273
- /** Create the tool that stops resource watches for this conversation. */
7280
+ /** Create the tool that stops watches for this conversation. */
7274
7281
  function createStopWatchingResourcesTool(context) {
7275
7282
  return zodTool({
7276
7283
  annotations: {
@@ -7279,7 +7286,7 @@ function createStopWatchingResourcesTool(context) {
7279
7286
  openWorldHint: false,
7280
7287
  readOnlyHint: false
7281
7288
  },
7282
- description: "Stop one resource watch in the current conversation by id. Omit id only when the user explicitly asks to stop every watch in this conversation. Infer terse stop requests from context, inspect active watches when the target is unclear, and call this tool before confirming that watching stopped.",
7289
+ description: "Stop one watch in the current conversation by id. Omit id only when the user explicitly asks to stop every watch in this conversation. Infer terse stop requests from context, inspect active watches when the target is unclear, and call this tool before confirming that watching stopped.",
7283
7290
  exposure: "deferred",
7284
7291
  source: RESOURCE_WATCH_TOOL_SOURCE,
7285
7292
  inputSchema: z.object({ id: z.string().min(1).nullable().optional() }).strict(),
@@ -7287,14 +7294,14 @@ function createStopWatchingResourcesTool(context) {
7287
7294
  async execute({ id }) {
7288
7295
  let stoppedIds;
7289
7296
  if (id) {
7290
- const stopped = await cancelResourceEventSubscription({
7297
+ const stopped = await cancelWatch({
7291
7298
  conversationId: context.conversationId,
7292
7299
  id
7293
7300
  });
7294
- if (!stopped) throw new ToolInputError("Resource watch was not found in the current conversation.");
7301
+ if (!stopped) throw new ToolInputError("Watch was not found in the current conversation.");
7295
7302
  stoppedIds = [stopped.id];
7296
7303
  } else {
7297
- const subscriptions = await listResourceEventSubscriptions({ conversationId: context.conversationId });
7304
+ const subscriptions = await listWatches({ conversationId: context.conversationId });
7298
7305
  await cancelSubscriptions({ conversationId: context.conversationId });
7299
7306
  stoppedIds = subscriptions.map((subscription) => subscription.id);
7300
7307
  }
@@ -7306,7 +7313,7 @@ function createStopWatchingResourcesTool(context) {
7306
7313
  });
7307
7314
  }
7308
7315
  //#endregion
7309
- //#region src/chat/tools/watch-resource-events.ts
7316
+ //#region src/chat/tools/watch-events.ts
7310
7317
  function inputSchema(catalog) {
7311
7318
  return z.object({
7312
7319
  identifier: z.string().trim().min(1).describe("Plugin-defined resource identifier."),
@@ -7314,7 +7321,7 @@ function inputSchema(catalog) {
7314
7321
  resourceType: registeredResourceTypeSchema(catalog).describe("Plugin-defined resource type."),
7315
7322
  label: z.string().trim().min(1).max(500).describe("Human-readable resource label."),
7316
7323
  events: z.array(registeredEventTypeSchema(catalog)).min(1).describe("High-signal event names to deliver to this conversation when they occur."),
7317
- match: registeredResourceEventMatchSchema(),
7324
+ match: registeredEventMatchSchema(),
7318
7325
  intent: z.string().trim().min(1).max(4e3).describe("Concise reason this conversation wants these events, used when an event arrives."),
7319
7326
  ttlMs: z.coerce.number().describe("How long to keep the subscription active. Defaults to 14 days and must not exceed 30 days.").optional()
7320
7327
  }).strict().superRefine((subscription, context) => {
@@ -7354,11 +7361,11 @@ function cleanStrings(values) {
7354
7361
  function ttlMs(input) {
7355
7362
  if (input.ttlMs === void 0) return RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS;
7356
7363
  if (!Number.isFinite(input.ttlMs) || input.ttlMs <= 0) throw new ToolInputError("ttlMs must be a positive finite number");
7357
- if (input.ttlMs > 2592e6) throw new ToolInputError("Resource watches cannot exceed 30 days");
7364
+ if (input.ttlMs > 2592e6) throw new ToolInputError("Watches cannot exceed 30 days");
7358
7365
  return input.ttlMs;
7359
7366
  }
7360
- /** Create the tool that temporarily watches resource events in one conversation. */
7361
- function createWatchResourceEventsTool(context, catalog) {
7367
+ /** Create the tool that temporarily watches events in one conversation. */
7368
+ function createWatchEventsTool(context, catalog) {
7362
7369
  return zodTool({
7363
7370
  annotations: {
7364
7371
  destructiveHint: false,
@@ -7366,7 +7373,7 @@ function createWatchResourceEventsTool(context, catalog) {
7366
7373
  openWorldHint: true,
7367
7374
  readOnlyHint: false
7368
7375
  },
7369
- description: "Watch one plugin resource in the current conversation for a limited time; matching events return to this conversation as updates. Use for watch, notify, or tell-me-when requests. This does not create an event task or execute a durable task instruction. Prefer a subscribable tool result when available.",
7376
+ description: "Watch one plugin resource in the current conversation for a limited time; matching events return to this conversation as updates. Use for watch, notify, or tell-me-when requests. This does not create an event automation or execute a durable automation instruction. Prefer a subscribable tool result when available.",
7370
7377
  inputSchema: inputSchema(catalog),
7371
7378
  outputSchema: outputSchema$2,
7372
7379
  async execute(input) {
@@ -7374,13 +7381,13 @@ function createWatchResourceEventsTool(context, catalog) {
7374
7381
  for (const eventType of events) if (!pluginSupportsEvent(catalog, input.namespace, input.resourceType, eventType)) throw new ToolInputError(`Resource type "${input.namespace}:${input.resourceType}" does not support event "${eventType}".`);
7375
7382
  const intent = input.intent.trim();
7376
7383
  if (!intent) throw new ToolInputError("intent is required");
7377
- const match = requireSupportedResourceEventMatch(catalog, {
7384
+ const match = requireSupportedEventMatch(catalog, {
7378
7385
  match: input.match,
7379
7386
  namespace: input.namespace,
7380
7387
  resourceType: input.resourceType
7381
7388
  });
7382
7389
  const nowMs = Date.now();
7383
- const subscription = await createResourceEventSubscription({
7390
+ const subscription = await createWatch({
7384
7391
  conversationId: context.conversationId,
7385
7392
  events,
7386
7393
  expiresAtMs: nowMs + ttlMs(input),
@@ -7388,7 +7395,7 @@ function createWatchResourceEventsTool(context, catalog) {
7388
7395
  label: input.label.trim(),
7389
7396
  ...match ? { match } : void 0,
7390
7397
  namespace: input.namespace.trim(),
7391
- identifier: normalizeEventIdentifier(catalog, input.namespace, input.identifier),
7398
+ identifier: normalizeCatalogEventIdentifier(catalog, input.namespace, input.identifier),
7392
7399
  resourceType: input.resourceType.trim()
7393
7400
  });
7394
7401
  return {
@@ -7410,24 +7417,24 @@ function createWatchResourceEventsTool(context, catalog) {
7410
7417
  });
7411
7418
  }
7412
7419
  //#endregion
7413
- //#region src/chat/tools/resource-events.ts
7420
+ //#region src/chat/tools/events.ts
7414
7421
  /** Build the complete resource-watch tool set for this runtime context. */
7415
- function createResourceEventTools(context, catalog) {
7422
+ function createEventTools(context, catalog) {
7416
7423
  return {
7417
- ...hasResourceEventCatalogEntries(catalog) ? {
7418
- searchResourceEventTypes: createSearchResourceEventTypesTool(catalog),
7419
- watchResourceEvents: createWatchResourceEventsTool(context, catalog)
7424
+ ...hasEventCatalogEntries(catalog) ? {
7425
+ searchEventTypes: createSearchEventTypesTool(catalog),
7426
+ watchEvents: createWatchEventsTool(context, catalog)
7420
7427
  } : void 0,
7421
- listResourceEventSubscriptions: createListResourceEventSubscriptionsTool(context),
7428
+ listWatches: createListWatchesTool(context),
7422
7429
  stopWatchingResources: createStopWatchingResourcesTool(context)
7423
7430
  };
7424
7431
  }
7425
7432
  //#endregion
7426
- //#region src/chat/tools/create-event-task.ts
7427
- /** Build a retry-stable task id scoped to actor, destination, and tool call. */
7428
- function buildEventTaskId(args) {
7433
+ //#region src/chat/tools/create-event-automation.ts
7434
+ /** Build a retry-stable automation id scoped to actor, destination, and tool call. */
7435
+ function buildEventAutomationId(args) {
7429
7436
  const toolCallId = args.toolCallId?.trim();
7430
- if (!toolCallId) throw new Error("Event task creation requires a tool-call identity.");
7437
+ if (!toolCallId) throw new Error("Event automation creation requires a tool-call identity.");
7431
7438
  return `evt_${createHash("sha256").update(JSON.stringify({
7432
7439
  actor: args.userId,
7433
7440
  channel: args.channelId,
@@ -7435,9 +7442,9 @@ function buildEventTaskId(args) {
7435
7442
  team: args.teamId
7436
7443
  })).digest("hex").slice(0, 32)}`;
7437
7444
  }
7438
- /** Create the core tool that stores an event task. */
7439
- function createEventTaskTool(context, catalog) {
7440
- const trigger = registeredEventTaskTriggerSchema(catalog);
7445
+ /** Create the core tool that stores an event automation. */
7446
+ function createEventAutomationTool(context, catalog) {
7447
+ const trigger = registeredEventAutomationTriggerSchema(catalog);
7441
7448
  return zodTool({
7442
7449
  approvalMode: "review",
7443
7450
  annotations: {
@@ -7447,12 +7454,12 @@ function createEventTaskTool(context, catalog) {
7447
7454
  readOnlyHint: false
7448
7455
  },
7449
7456
  executionMode: "sequential",
7450
- description: "Create a durable event task that executes the supplied instruction for every matching resource event. Use for whenever-this-happens-do-X automation; ordinary watch, notify, or tell-me-when requests use watchResourceEvents instead. The task may use the creator's connected credentials. Prefer a subscribable tool result when available.",
7457
+ description: "Create a durable event automation that executes the supplied instruction for every matching event. Use for whenever-this-happens-do-X automation; ordinary watch, notify, or tell-me-when requests use watchEvents instead. The automation may use the creator's connected credentials. Prefer a subscribable tool result when available.",
7451
7458
  inputSchema: z.object({
7452
- task: z.string().trim().min(1).max(4e3),
7459
+ instruction: z.string().trim().min(1).max(4e3),
7453
7460
  title: z.string().trim().min(1).max(60).nullable().describe("Optional short display title. Omit or use null to generate one from the task instruction.").optional(),
7454
7461
  trigger,
7455
- outcomes: z.array(taskOutcomeInputSchema).max(5).describe("Messages to send after successful work. Use an empty list to send nothing. Omit to send one message to the current Slack conversation.").optional(),
7462
+ outcomes: z.array(taskOutcomeInputSchema).max(5).describe("Successful work is silent by default. Omit this field or use an empty list when the Automation should act through tools without a status message. Add send_message only when the user asks for a notification, post, digest, summary, or other visible result.").optional(),
7456
7463
  credentialMode: z.enum(["creator", "system"]).nullable().describe("Use creator to make the task creator's connected credentials available, or system when the creator says not to use them. Omit or use null for the creator default.").optional()
7457
7464
  }).strict(),
7458
7465
  prepareArguments(args) {
@@ -7461,25 +7468,25 @@ function createEventTaskTool(context, catalog) {
7461
7468
  if (prepared.credentialMode === "creator" || prepared.credentialMode === null) delete prepared.credentialMode;
7462
7469
  return prepared;
7463
7470
  },
7464
- outputSchema: eventTaskToolResultSchema,
7471
+ outputSchema: eventAutomationToolResultSchema,
7465
7472
  async execute(input, options) {
7466
- const { actor, destination, source } = requireEventTaskSlackContext(context);
7467
- const match = requireSupportedEventTaskTrigger(catalog, input.trigger);
7468
- const id = buildEventTaskId({
7473
+ const { actor, destination, source } = requireEventAutomationSlackContext(context);
7474
+ const match = requireSupportedEventAutomationTrigger(catalog, input.trigger);
7475
+ const id = buildEventAutomationId({
7469
7476
  channelId: destination.channelId,
7470
7477
  teamId: destination.teamId,
7471
7478
  toolCallId: options.toolCallId,
7472
7479
  userId: actor.userId
7473
7480
  });
7474
7481
  const db = getDb();
7475
- const existing = await getEventTask(db, id);
7482
+ const existing = await getEventAutomation(db, id);
7476
7483
  if (existing) {
7477
- if (!eventTaskMatchesDestination(existing, destination) || existing.createdBy.slackUserId !== actor.userId) throw new ToolInputError("Event task operation identity is invalid.");
7478
- if (existing.status !== "deleted") return eventTaskSuccess(existing, catalog);
7484
+ if (!eventAutomationMatchesDestination(existing, destination) || existing.createdBy.slackUserId !== actor.userId) throw new ToolInputError("Event automation operation identity is invalid.");
7485
+ if (existing.status !== "deleted") return eventAutomationToolResult(existing, catalog, actor.userId);
7479
7486
  }
7480
7487
  const title = await resolveTaskTitle({
7481
7488
  completeText,
7482
- instruction: input.task,
7489
+ instruction: input.instruction,
7483
7490
  title: input.title
7484
7491
  });
7485
7492
  const task = {
@@ -7494,25 +7501,25 @@ function createEventTaskTool(context, catalog) {
7494
7501
  credentialMode: input.credentialMode ?? "creator",
7495
7502
  destination,
7496
7503
  outcomes: await resolveTaskOutcomes(input.outcomes, destination, actor.userId),
7497
- task: { text: input.task },
7504
+ task: { text: input.instruction },
7498
7505
  ...title ? { title } : void 0,
7499
7506
  trigger: {
7500
7507
  namespace: input.trigger.namespace,
7501
- identifier: normalizeEventIdentifier(catalog, input.trigger.namespace, input.trigger.identifier),
7508
+ identifier: normalizeCatalogEventIdentifier(catalog, input.trigger.namespace, input.trigger.identifier),
7502
7509
  resourceType: input.trigger.resourceType,
7503
7510
  label: input.trigger.label,
7504
7511
  events: [...new Set(input.trigger.events)],
7505
7512
  ...match ? { match } : void 0
7506
7513
  }
7507
7514
  };
7508
- return eventTaskSuccess(await createEventTask(db, task), catalog);
7515
+ return eventAutomationToolResult(await createEventAutomation(db, task), catalog, actor.userId);
7509
7516
  }
7510
7517
  });
7511
7518
  }
7512
7519
  //#endregion
7513
- //#region src/chat/tools/delete-event-task.ts
7514
- /** Create the core tool that deletes an event task. */
7515
- function createDeleteEventTaskTool(context, catalog) {
7520
+ //#region src/chat/tools/delete-event-automation.ts
7521
+ /** Create the core tool that deletes an event automation. */
7522
+ function createDeleteEventAutomationTool(context, catalog) {
7516
7523
  return zodTool({
7517
7524
  approvalMode: "review",
7518
7525
  annotations: {
@@ -7522,22 +7529,23 @@ function createDeleteEventTaskTool(context, catalog) {
7522
7529
  readOnlyHint: false
7523
7530
  },
7524
7531
  executionMode: "sequential",
7525
- description: "Delete an event task.",
7526
- inputSchema: z.object({ taskId: z.string().min(1) }).strict(),
7527
- outputSchema: eventTaskToolResultSchema,
7528
- async execute({ taskId }) {
7529
- const current = await writableEventTask(context, taskId);
7530
- const deleted = await deleteEventTask(getDb(), current.id);
7531
- if (!deleted) throw new ToolInputError("Event task was not found.");
7532
- return eventTaskSuccess(deleted, catalog);
7532
+ description: "Delete an event automation.",
7533
+ inputSchema: z.object({ automationId: z.string().min(1) }).strict(),
7534
+ outputSchema: eventAutomationToolResultSchema,
7535
+ async execute({ automationId }) {
7536
+ const { actor } = requireEventAutomationSlackContext(context);
7537
+ const current = await writableEventAutomation(context, automationId);
7538
+ const deleted = await deleteEventAutomation(getDb(), current.id);
7539
+ if (!deleted) throw new ToolInputError("Event automation was not found.");
7540
+ return eventAutomationToolResult(deleted, catalog, actor.userId);
7533
7541
  }
7534
7542
  });
7535
7543
  }
7536
7544
  //#endregion
7537
- //#region src/chat/tools/list-event-tasks.ts
7538
- const MAX_LISTED_EVENT_TASKS = 50;
7539
- /** Create the core tool that lists event tasks for this destination. */
7540
- function createListEventTasksTool(context, catalog) {
7545
+ //#region src/chat/tools/list-event-automations.ts
7546
+ const MAX_LISTED_EVENT_AUTOMATIONS = 50;
7547
+ /** Create the core tool that lists event automations for this destination. */
7548
+ function createListEventAutomationsTool(context, catalog) {
7541
7549
  return zodTool({
7542
7550
  annotations: {
7543
7551
  destructiveHint: false,
@@ -7545,30 +7553,30 @@ function createListEventTasksTool(context, catalog) {
7545
7553
  openWorldHint: false,
7546
7554
  readOnlyHint: true
7547
7555
  },
7548
- description: "List event tasks for the current destination. A false triggerAvailable value means the task remains stored but its plugin event is not currently enabled.",
7556
+ description: "List event automations for the current destination. Each result says whether the requester is the creator and whether its trigger is available.",
7549
7557
  inputSchema: z.object({}).strict(),
7550
- outputSchema: eventTaskListToolResultSchema,
7558
+ outputSchema: eventAutomationListToolResultSchema,
7551
7559
  async execute() {
7552
- const { destination } = requireEventTaskSlackContext(context);
7553
- const matching = (await listEventTasksForTeam(getDb(), destination.teamId)).filter((task) => eventTaskMatchesDestination(task, destination));
7554
- const tasks = matching.slice(0, MAX_LISTED_EVENT_TASKS).map((task) => compactEventTask(task, catalog));
7560
+ const { actor, destination } = requireEventAutomationSlackContext(context);
7561
+ const matching = (await listEventAutomationsForTeam(getDb(), destination.teamId)).filter((task) => eventAutomationMatchesDestination(task, destination));
7562
+ const automations = matching.slice(0, MAX_LISTED_EVENT_AUTOMATIONS).map((task) => compactEventAutomation(task, catalog, actor.userId));
7555
7563
  return {
7556
- tasks,
7557
- truncated: matching.length > tasks.length
7564
+ automations,
7565
+ truncated: matching.length > automations.length
7558
7566
  };
7559
7567
  }
7560
7568
  });
7561
7569
  }
7562
7570
  //#endregion
7563
- //#region src/chat/tools/update-event-task.ts
7571
+ //#region src/chat/tools/update-event-automation.ts
7564
7572
  /** Return whether an edit changes the task's executable event source. */
7565
- function changesEventTaskTrigger(current, next) {
7573
+ function changesEventAutomationTrigger(current, next) {
7566
7574
  const currentEvents = [...current.events].sort();
7567
7575
  const nextEvents = [...next.events].sort();
7568
- return current.namespace !== next.namespace || current.identifier !== next.identifier || currentEvents.length !== nextEvents.length || currentEvents.some((event, index) => event !== nextEvents[index]) || stableResourceEventMatchKey(current.match) !== stableResourceEventMatchKey(next.match);
7576
+ return current.namespace !== next.namespace || current.identifier !== next.identifier || currentEvents.length !== nextEvents.length || currentEvents.some((event, index) => event !== nextEvents[index]) || stableEventMatchKey(current.match) !== stableEventMatchKey(next.match);
7569
7577
  }
7570
- /** Create the core tool that updates an event task. */
7571
- function createUpdateEventTaskTool(context, catalog) {
7578
+ /** Create the core tool that updates an event automation. */
7579
+ function createUpdateEventAutomationTool(context, catalog) {
7572
7580
  return zodTool({
7573
7581
  approvalMode: "review",
7574
7582
  annotations: {
@@ -7578,44 +7586,44 @@ function createUpdateEventTaskTool(context, catalog) {
7578
7586
  readOnlyHint: false
7579
7587
  },
7580
7588
  executionMode: "sequential",
7581
- description: "Update the instruction, registered trigger, or credential use for an event task.",
7589
+ description: "Update the instruction, registered trigger, or credential use for an event automation.",
7582
7590
  inputSchema: z.object({
7583
- taskId: z.string().min(1),
7584
- task: z.string().trim().min(1).max(4e3).nullable().optional(),
7585
- trigger: registeredEventTaskTriggerSchema(catalog).nullable().optional(),
7591
+ automationId: z.string().min(1),
7592
+ instruction: z.string().trim().min(1).max(4e3).nullable().optional(),
7593
+ trigger: registeredEventAutomationTriggerSchema(catalog).nullable().optional(),
7586
7594
  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(),
7587
7595
  credentialMode: z.enum(["system", "creator"]).nullable().describe("Set creator to make the task's original creator credentials available, or system to disable them. Creator always means the task's createdBy actor, never the current requester. Only that original creator may enable creator mode. Omit or use null to leave unchanged.").optional()
7588
7596
  }).strict(),
7589
7597
  prepareArguments(args) {
7590
- const { credentialMode, outcomes, task, trigger, ...prepared } = args;
7598
+ const { credentialMode, outcomes, instruction, trigger, ...prepared } = args;
7591
7599
  return {
7592
7600
  ...prepared,
7593
- ...task != null ? { task } : void 0,
7601
+ ...instruction != null ? { instruction } : void 0,
7594
7602
  ...trigger != null ? { trigger } : void 0,
7595
7603
  ...outcomes != null ? { outcomes } : void 0,
7596
7604
  ...credentialMode != null ? { credentialMode } : void 0
7597
7605
  };
7598
7606
  },
7599
- outputSchema: eventTaskToolResultSchema,
7607
+ outputSchema: eventAutomationToolResultSchema,
7600
7608
  async execute(input) {
7601
- const current = await writableEventTask(context, input.taskId);
7602
- const match = input.trigger ? requireSupportedEventTaskTrigger(catalog, input.trigger) : void 0;
7603
- const { actor } = requireEventTaskSlackContext(context);
7609
+ const current = await writableEventAutomation(context, input.automationId);
7610
+ const match = input.trigger ? requireSupportedEventAutomationTrigger(catalog, input.trigger) : void 0;
7611
+ const { actor } = requireEventAutomationSlackContext(context);
7604
7612
  const isCreator = actor.userId === current.createdBy.slackUserId;
7605
- if (input.credentialMode === "creator" && !isCreator) throw new ToolInputError("Only the event task creator can enable creator credential use.");
7606
- if (input.outcomes != null && !isCreator) throw new ToolInputError("Only the event task creator can change message destinations.");
7607
- if (input.task === void 0 && input.trigger === void 0 && input.outcomes == null && input.credentialMode == null) throw new ToolInputError("Event task update requires a change.");
7613
+ if (input.credentialMode === "creator" && !isCreator) throw new ToolInputError("Only the event automation creator can enable creator credential use.");
7614
+ if (input.outcomes != null && !isCreator) throw new ToolInputError("Only the event automation creator can change message destinations.");
7615
+ if (input.instruction === void 0 && input.trigger === void 0 && input.outcomes == null && input.credentialMode == null) throw new ToolInputError("Event automation update requires a change.");
7608
7616
  const nextTrigger = input.trigger ? {
7609
7617
  namespace: input.trigger.namespace,
7610
- identifier: normalizeEventIdentifier(catalog, input.trigger.namespace, input.trigger.identifier),
7618
+ identifier: normalizeCatalogEventIdentifier(catalog, input.trigger.namespace, input.trigger.identifier),
7611
7619
  resourceType: input.trigger.resourceType,
7612
7620
  label: input.trigger.label,
7613
7621
  events: [...new Set(input.trigger.events)],
7614
7622
  ...match ? { match } : void 0
7615
7623
  } : current.trigger;
7616
- const nextInstruction = input.task != null ? input.task : current.task.text;
7624
+ const nextInstruction = input.instruction != null ? input.instruction : current.task.text;
7617
7625
  const instructionChanged = nextInstruction !== current.task.text;
7618
- const changesExecution = instructionChanged || changesEventTaskTrigger(current.trigger, nextTrigger);
7626
+ const changesExecution = instructionChanged || changesEventAutomationTrigger(current.trigger, nextTrigger);
7619
7627
  const next = {
7620
7628
  ...current,
7621
7629
  credentialMode: changesExecution && !isCreator ? "system" : input.credentialMode ?? current.credentialMode,
@@ -7632,26 +7640,26 @@ function createUpdateEventTaskTool(context, catalog) {
7632
7640
  if (title) next.title = title;
7633
7641
  else delete next.title;
7634
7642
  }
7635
- const saved = await saveEventTask(getDb(), next);
7636
- if (!saved) throw new ToolInputError("Event task was not found.");
7637
- return eventTaskSuccess(saved, catalog);
7643
+ const saved = await saveEventAutomation(getDb(), next);
7644
+ if (!saved) throw new ToolInputError("Event automation was not found.");
7645
+ return eventAutomationToolResult(saved, catalog, actor.userId);
7638
7646
  }
7639
7647
  });
7640
7648
  }
7641
7649
  //#endregion
7642
- //#region src/chat/tools/event-tasks.ts
7643
- /** Build event task tools for an interactive Slack actor. */
7644
- function createEventTaskTools(context, catalog) {
7650
+ //#region src/chat/tools/event-automations.ts
7651
+ /** Build event automation tools for an interactive Slack actor. */
7652
+ function createEventAutomationTools(context, catalog) {
7645
7653
  if (context.source.kind !== "slack" || context.destination.platform !== "slack" || context.actor?.platform !== "slack") return {};
7646
7654
  return {
7647
- ...hasPluginResourceEventCatalogEntries(catalog) ? { createEventTask: createEventTaskTool(context, catalog) } : void 0,
7648
- listEventTasks: createListEventTasksTool(context, catalog),
7649
- updateEventTask: createUpdateEventTaskTool(context, catalog),
7650
- deleteEventTask: createDeleteEventTaskTool(context, catalog)
7655
+ ...hasPluginEventCatalogEntries(catalog) ? { createEventAutomation: createEventAutomationTool(context, catalog) } : void 0,
7656
+ listEventAutomations: createListEventAutomationsTool(context, catalog),
7657
+ updateEventAutomation: createUpdateEventAutomationTool(context, catalog),
7658
+ deleteEventAutomation: createDeleteEventAutomationTool(context, catalog)
7651
7659
  };
7652
7660
  }
7653
7661
  //#endregion
7654
- //#region src/chat/scheduled-tasks/cadence.ts
7662
+ //#region src/chat/scheduled-automations/cadence.ts
7655
7663
  const FORMATTERS = /* @__PURE__ */ new Map();
7656
7664
  function getFormatter(timezone) {
7657
7665
  const existing = FORMATTERS.get(timezone);
@@ -7894,7 +7902,7 @@ function getNextRunAtMs(task, scheduledForMs, afterMs = scheduledForMs) {
7894
7902
  });
7895
7903
  }
7896
7904
  //#endregion
7897
- //#region src/chat/scheduled-tasks/schedule-intent.ts
7905
+ //#region src/chat/scheduled-automations/schedule-intent.ts
7898
7906
  /**
7899
7907
  * Owns model-facing schedule intent and materializes it against the trusted
7900
7908
  * server clock into the canonical schedule persisted by core.
@@ -7941,9 +7949,9 @@ const recurringScheduleIntentSchema = z.object({
7941
7949
  interval: z.number().int().positive().max(365).describe("Repeat every N frequency units. Defaults to 1.").nullable().optional(),
7942
7950
  time: localTimeSchema.describe("Local wall-clock time for each occurrence in HH:MM format."),
7943
7951
  weekdays: z.array(weekdaySchema).min(1).max(7).describe("Required for weekly schedules.").nullable().optional(),
7944
- day_of_month: z.number().int().min(1).max(31).describe("Required for monthly and yearly schedules.").nullable().optional(),
7952
+ dayOfMonth: z.number().int().min(1).max(31).describe("Required for monthly and yearly schedules.").nullable().optional(),
7945
7953
  month: z.number().int().min(1).max(12).describe("Required for yearly schedules, where January is 1.").nullable().optional(),
7946
- start_date: localDateSchema.describe("Optional local calendar date that anchors the recurrence. Omit to start with the next matching occurrence.").nullable().optional(),
7954
+ startDate: localDateSchema.describe("Optional local calendar date that anchors the recurrence. Omit to start with the next matching occurrence.").nullable().optional(),
7947
7955
  timezone: timezoneSchema
7948
7956
  }).strict().superRefine((schedule, context) => {
7949
7957
  if (schedule.frequency === "weekly" && schedule.weekdays == null) context.addIssue({
@@ -7951,10 +7959,10 @@ const recurringScheduleIntentSchema = z.object({
7951
7959
  message: "Weekly schedules require weekdays.",
7952
7960
  path: ["weekdays"]
7953
7961
  });
7954
- if ((schedule.frequency === "monthly" || schedule.frequency === "yearly") && schedule.day_of_month == null) context.addIssue({
7962
+ if ((schedule.frequency === "monthly" || schedule.frequency === "yearly") && schedule.dayOfMonth == null) context.addIssue({
7955
7963
  code: "custom",
7956
- message: `${schedule.frequency} schedules require day_of_month.`,
7957
- path: ["day_of_month"]
7964
+ message: `${schedule.frequency} schedules require dayOfMonth.`,
7965
+ path: ["dayOfMonth"]
7958
7966
  });
7959
7967
  if (schedule.frequency === "yearly" && schedule.month == null) context.addIssue({
7960
7968
  code: "custom",
@@ -7966,10 +7974,10 @@ const recurringScheduleIntentSchema = z.object({
7966
7974
  message: "weekdays applies only to weekly schedules.",
7967
7975
  path: ["weekdays"]
7968
7976
  });
7969
- if (schedule.frequency !== "monthly" && schedule.frequency !== "yearly" && schedule.day_of_month != null) context.addIssue({
7977
+ if (schedule.frequency !== "monthly" && schedule.frequency !== "yearly" && schedule.dayOfMonth != null) context.addIssue({
7970
7978
  code: "custom",
7971
- message: "day_of_month applies only to monthly or yearly schedules.",
7972
- path: ["day_of_month"]
7979
+ message: "dayOfMonth applies only to monthly or yearly schedules.",
7980
+ path: ["dayOfMonth"]
7973
7981
  });
7974
7982
  if (schedule.frequency !== "yearly" && schedule.month != null) context.addIssue({
7975
7983
  code: "custom",
@@ -8036,8 +8044,8 @@ function recurringDescription(schedule, timezone) {
8036
8044
  const cadence = interval === 1 ? cadenceUnit : `${interval} ${cadenceUnit}s`;
8037
8045
  let detail = "";
8038
8046
  if (schedule.frequency === "weekly") detail = ` on ${formatWeekdays(schedule.weekdays)}`;
8039
- else if (schedule.frequency === "monthly") detail = ` on day ${schedule.day_of_month}`;
8040
- else if (schedule.frequency === "yearly") detail = ` on ${String(schedule.month).padStart(2, "0")}-${String(schedule.day_of_month).padStart(2, "0")}`;
8047
+ else if (schedule.frequency === "monthly") detail = ` on day ${schedule.dayOfMonth}`;
8048
+ else if (schedule.frequency === "yearly") detail = ` on ${String(schedule.month).padStart(2, "0")}-${String(schedule.dayOfMonth).padStart(2, "0")}`;
8041
8049
  return `Every ${cadence}${detail} at ${schedule.time} (${timezone})`;
8042
8050
  }
8043
8051
  var ScheduleIntentError = class extends Error {};
@@ -8073,13 +8081,13 @@ function compileScheduleIntent(args) {
8073
8081
  const recurrence = {
8074
8082
  frequency: args.intent.frequency,
8075
8083
  interval: args.intent.interval ?? 1,
8076
- startDate: args.intent.start_date ?? localDateAt(args.nowMs, timezone),
8084
+ startDate: args.intent.startDate ?? localDateAt(args.nowMs, timezone),
8077
8085
  time: parseLocalTime(args.intent.time),
8078
8086
  ...args.intent.frequency === "weekly" ? { weekdays: [...new Set(args.intent.weekdays.map((weekday) => WEEKDAY_INDEX[weekday]))].sort((left, right) => left - right) } : void 0,
8079
- ...args.intent.frequency === "monthly" || args.intent.frequency === "yearly" ? { dayOfMonth: args.intent.day_of_month ?? void 0 } : void 0,
8087
+ ...args.intent.frequency === "monthly" || args.intent.frequency === "yearly" ? { dayOfMonth: args.intent.dayOfMonth ?? void 0 } : void 0,
8080
8088
  ...args.intent.frequency === "yearly" ? { month: args.intent.month ?? void 0 } : void 0
8081
8089
  };
8082
- const searchRecurrence = args.intent.start_date ? recurrence : {
8090
+ const searchRecurrence = args.intent.startDate ? recurrence : {
8083
8091
  ...recurrence,
8084
8092
  interval: 1
8085
8093
  };
@@ -8089,7 +8097,7 @@ function compileScheduleIntent(args) {
8089
8097
  timezone
8090
8098
  });
8091
8099
  if (nextRunAtMs === void 0) throw new ScheduleIntentError("The recurring schedule has no valid future occurrence.");
8092
- const materializedRecurrence = args.intent.start_date ? recurrence : {
8100
+ const materializedRecurrence = args.intent.startDate ? recurrence : {
8093
8101
  ...recurrence,
8094
8102
  startDate: localDateAt(nextRunAtMs, timezone)
8095
8103
  };
@@ -8104,10 +8112,10 @@ function compileScheduleIntent(args) {
8104
8112
  };
8105
8113
  }
8106
8114
  //#endregion
8107
- //#region src/chat/scheduled-tasks/telemetry.ts
8108
- /** Safe structured telemetry attributes for scheduled-task lifecycle events. */
8109
- /** Correlation attributes shared by scheduled-task create and run events. */
8110
- function scheduledTaskAttributes(task, extras = {}) {
8115
+ //#region src/chat/scheduled-automations/telemetry.ts
8116
+ /** Safe structured telemetry attributes for scheduled-automation lifecycle events. */
8117
+ /** Correlation attributes shared by scheduled-automation create and run events. */
8118
+ function scheduledAutomationAttributes(task, extras = {}) {
8111
8119
  return {
8112
8120
  "app.task.id": task.id,
8113
8121
  "app.task.type": "scheduled",
@@ -8124,9 +8132,9 @@ function scheduledTaskAttributes(task, extras = {}) {
8124
8132
  ...extras
8125
8133
  };
8126
8134
  }
8127
- /** Correlation attributes for one scheduled-task run transition. */
8128
- function scheduledTaskRunAttributes(task, run, extras = {}) {
8129
- return scheduledTaskAttributes(task, {
8135
+ /** Correlation attributes for one scheduled-automation run transition. */
8136
+ function scheduledAutomationRunAttributes(task, run, extras = {}) {
8137
+ return scheduledAutomationAttributes(task, {
8130
8138
  "app.task.run.id": run.id,
8131
8139
  "app.task.run.status": run.status,
8132
8140
  "app.task.run.scheduled_for": new Date(run.scheduledForMs).toISOString(),
@@ -8135,12 +8143,12 @@ function scheduledTaskRunAttributes(task, run, extras = {}) {
8135
8143
  ...extras
8136
8144
  });
8137
8145
  }
8138
- /** Emit the lifecycle event for one skipped scheduled-task run. */
8139
- function logScheduledTaskRunSkipped(task, run, extras = {}) {
8140
- logInfo("scheduled_task.run.skipped", scheduledTaskRunAttributes(task, run, extras));
8146
+ /** Emit the lifecycle event for one skipped scheduled-automation run. */
8147
+ function logScheduledAutomationRunSkipped(task, run, extras = {}) {
8148
+ logInfo("scheduled_automation.run.skipped", scheduledAutomationRunAttributes(task, run, extras));
8141
8149
  }
8142
8150
  //#endregion
8143
- //#region src/chat/scheduled-tasks/identity.ts
8151
+ //#region src/chat/scheduled-automations/identity.ts
8144
8152
  const SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{5,}$/;
8145
8153
  function clean(value) {
8146
8154
  const normalized = value?.trim();
@@ -8156,9 +8164,9 @@ function cleanDisplay(value, slackUserId) {
8156
8164
  return SLACK_USER_ID_PATTERN.test(normalized) ? void 0 : normalized;
8157
8165
  }
8158
8166
  /** Keep scheduler creator metadata from promoting Slack IDs into display names. */
8159
- function sanitizeScheduledTaskPrincipal(principal) {
8167
+ function sanitizeScheduledAutomationPrincipal(principal) {
8160
8168
  const slackUserId = cleanSlackUserId(principal.slackUserId);
8161
- if (!slackUserId) throw new Error("Scheduled task principal requires a Slack user id");
8169
+ if (!slackUserId) throw new Error("Scheduled automation principal requires a Slack user id");
8162
8170
  const fullName = cleanDisplay(principal.fullName, slackUserId);
8163
8171
  const userName = cleanDisplay(principal.userName, slackUserId);
8164
8172
  return {
@@ -8168,28 +8176,32 @@ function sanitizeScheduledTaskPrincipal(principal) {
8168
8176
  };
8169
8177
  }
8170
8178
  //#endregion
8171
- //#region src/chat/scheduled-tasks/tool-support.ts
8179
+ //#region src/chat/scheduled-automations/tool-support.ts
8172
8180
  const TASK_ID_PREFIX = "sched";
8173
8181
  const DEFAULT_SCHEDULE_TIMEZONE = "America/Los_Angeles";
8174
8182
  const compactTaskResultSchema = z.object({
8175
8183
  id: z.string(),
8184
+ title: z.string().nullable(),
8176
8185
  status: z.enum([
8177
8186
  "active",
8178
8187
  "blocked",
8179
8188
  "completed",
8180
8189
  "deleted"
8181
8190
  ]),
8182
- task: z.string(),
8191
+ statusReason: z.string().nullable(),
8192
+ createdAt: z.string().datetime(),
8193
+ updatedAt: z.string().datetime(),
8194
+ originalRequest: z.string().nullable(),
8195
+ instruction: z.string(),
8183
8196
  schedule: z.string(),
8184
8197
  timezone: z.string(),
8185
8198
  recurrence: z.unknown().nullable(),
8186
- next_run_at: z.string().nullable(),
8199
+ nextRunAt: z.string().nullable(),
8187
8200
  destination: z.object({
8188
- platform: z.literal("slack"),
8189
- team_id: z.string().min(1),
8190
- channel_id: z.string().min(1)
8201
+ channel: z.string().min(1),
8202
+ thread: z.string().min(1).nullable()
8191
8203
  }).strict(),
8192
- conversation_access: z.object({
8204
+ conversationAccess: z.object({
8193
8205
  audience: z.enum([
8194
8206
  "direct",
8195
8207
  "group",
@@ -8197,22 +8209,29 @@ const compactTaskResultSchema = z.object({
8197
8209
  ]),
8198
8210
  visibility: z.enum(["private", "public"])
8199
8211
  }).strict(),
8200
- credential_mode: z.enum(["system", "creator"]),
8201
- outcomes: z.array(taskOutcomeSchema).max(5),
8202
- dashboard_url: z.string().url().nullable(),
8203
- last_run_at: z.string().nullable(),
8204
- run_now_at: z.string().nullable()
8205
- }).strict();
8206
- const scheduleTaskToolResultSchema = juniorToolOutputSchema.extend({
8207
- target: z.string(),
8208
- task: compactTaskResultSchema
8212
+ credentialMode: z.enum(["system", "creator"]),
8213
+ isCreator: z.boolean(),
8214
+ createdBy: z.object({
8215
+ name: z.string().min(1).nullable(),
8216
+ username: z.string().min(1).nullable()
8217
+ }).strict(),
8218
+ outcomes: z.array(z.object({
8219
+ action: z.literal("send_message"),
8220
+ destination: z.object({
8221
+ channel: z.string().min(1),
8222
+ thread: z.string().min(1).nullable()
8223
+ }).strict()
8224
+ }).strict()).max(5),
8225
+ dashboardUrl: z.string().url().nullable(),
8226
+ lastRunAt: z.string().nullable(),
8227
+ runNowAt: z.string().nullable()
8209
8228
  }).strict();
8229
+ const scheduleAutomationToolResultSchema = juniorToolOutputSchema.extend({ automation: compactTaskResultSchema }).strict();
8210
8230
  const scheduleListToolResultSchema = juniorToolOutputSchema.extend({
8211
- target: z.string(),
8212
- tasks: z.array(compactTaskResultSchema),
8231
+ automations: z.array(compactTaskResultSchema),
8213
8232
  truncated: z.boolean()
8214
8233
  }).strict();
8215
- /** Normalize scheduled-task validation failures into the core tool contract. */
8234
+ /** Normalize scheduled-automation validation failures into the core tool contract. */
8216
8235
  function throwToolInputError(error) {
8217
8236
  throw new ToolInputError(error);
8218
8237
  }
@@ -8241,7 +8260,7 @@ function requireActor(context, destination) {
8241
8260
  if (context.actor?.platform !== "slack" || context.actor.teamId !== destination.teamId) throwToolInputError("No active Slack actor context is available.");
8242
8261
  const userId = context.actor?.userId?.trim();
8243
8262
  if (!userId || userId.toLowerCase() === "unknown") throwToolInputError("No active Slack actor context is available.");
8244
- return sanitizeScheduledTaskPrincipal({
8263
+ return sanitizeScheduledAutomationPrincipal({
8245
8264
  slackUserId: userId,
8246
8265
  ...context.actor?.userName ? { userName: context.actor.userName } : void 0,
8247
8266
  ...context.actor?.fullName ? { fullName: context.actor.fullName } : void 0
@@ -8273,54 +8292,65 @@ function sameDestination(task, destination) {
8273
8292
  /** Look up a mutable task only after enforcing active-conversation ownership. */
8274
8293
  async function getWritableTask(args) {
8275
8294
  const destination = requireActiveConversation(args.context);
8276
- const task = await readScheduledTask(getDb(), args.taskId);
8277
- if (!task || task.status === "deleted") throwToolInputError("Scheduled task was not found in the active Slack conversation.");
8278
- if (!sameDestination(task, destination)) throwToolInputError("Scheduled task can only be managed from the Slack destination where it currently delivers.");
8295
+ const task = await readScheduledAutomation(getDb(), args.taskId);
8296
+ if (!task || task.status === "deleted") throwToolInputError("Scheduled automation was not found in the active Slack conversation.");
8297
+ if (!sameDestination(task, destination)) throwToolInputError("Scheduled automation can only be managed from the Slack destination where it currently delivers.");
8279
8298
  return task;
8280
8299
  }
8281
- /** Project scheduled task state into the stable model-facing result shape. */
8282
- function compactTask(task) {
8300
+ /** Project scheduled automation state into the stable model-facing result shape. */
8301
+ function compactTask(task, requesterSlackUserId) {
8283
8302
  return compactTaskResultSchema.parse({
8284
8303
  id: task.id,
8304
+ title: task.title?.trim() || null,
8285
8305
  status: task.status,
8286
- task: task.task.text,
8306
+ statusReason: task.statusReason ?? null,
8307
+ createdAt: new Date(task.createdAtMs).toISOString(),
8308
+ updatedAt: new Date(task.updatedAtMs).toISOString(),
8309
+ originalRequest: task.originalRequest ?? null,
8310
+ instruction: task.task.text,
8287
8311
  schedule: task.schedule.description,
8288
8312
  timezone: task.schedule.timezone,
8289
8313
  recurrence: task.schedule.recurrence ? {
8290
8314
  frequency: task.schedule.recurrence.frequency,
8291
8315
  interval: task.schedule.recurrence.interval,
8292
- start_date: task.schedule.recurrence.startDate,
8316
+ startDate: task.schedule.recurrence.startDate,
8293
8317
  time: task.schedule.recurrence.time,
8294
8318
  weekdays: task.schedule.recurrence.weekdays,
8295
8319
  month: task.schedule.recurrence.month,
8296
- day_of_month: task.schedule.recurrence.dayOfMonth
8320
+ dayOfMonth: task.schedule.recurrence.dayOfMonth
8297
8321
  } : null,
8298
- next_run_at: task.nextRunAtMs ? new Date(task.nextRunAtMs).toISOString() : null,
8322
+ nextRunAt: task.nextRunAtMs ? new Date(task.nextRunAtMs).toISOString() : null,
8299
8323
  destination: {
8300
- platform: "slack",
8301
- team_id: task.destination.teamId,
8302
- channel_id: task.destination.channelId
8324
+ channel: task.destination.channelId,
8325
+ thread: task.destination.threadTs ?? null
8326
+ },
8327
+ conversationAccess: task.conversationAccess,
8328
+ credentialMode: task.credentialMode,
8329
+ isCreator: task.createdBy.slackUserId === requesterSlackUserId,
8330
+ createdBy: {
8331
+ name: task.createdBy.fullName ?? null,
8332
+ username: task.createdBy.userName ?? null
8303
8333
  },
8304
- conversation_access: task.conversationAccess,
8305
- credential_mode: task.credentialMode,
8306
- outcomes: effectiveTaskOutcomes(task.outcomes, task.destination),
8307
- dashboard_url: getDashboardTaskLink(task.id) ?? null,
8308
- last_run_at: task.lastRunAtMs ? new Date(task.lastRunAtMs).toISOString() : null,
8309
- run_now_at: task.runNowAtMs ? new Date(task.runNowAtMs).toISOString() : null
8334
+ outcomes: effectiveTaskOutcomes(task.outcomes, task.destination).map((outcome) => ({
8335
+ action: outcome.action,
8336
+ destination: {
8337
+ channel: outcome.destination.channelId,
8338
+ thread: outcome.destination.threadTs ?? null
8339
+ }
8340
+ })),
8341
+ dashboardUrl: getDashboardTaskLink(task.id) ?? null,
8342
+ lastRunAt: task.lastRunAtMs ? new Date(task.lastRunAtMs).toISOString() : null,
8343
+ runNowAt: task.runNowAtMs ? new Date(task.runNowAtMs).toISOString() : null
8310
8344
  });
8311
8345
  }
8312
8346
  /** Build the structured result shared by single-task scheduler tools. */
8313
- function scheduleTaskToolResult(target, task) {
8314
- return {
8315
- target,
8316
- task
8317
- };
8347
+ function scheduleAutomationToolResult(task, requesterSlackUserId) {
8348
+ return { automation: compactTask(task, requesterSlackUserId) };
8318
8349
  }
8319
8350
  /** Build the structured result for listing scheduler tools. */
8320
8351
  function scheduleListToolResult(args) {
8321
8352
  return {
8322
- target: args.target,
8323
- tasks: args.tasks,
8353
+ automations: args.automations,
8324
8354
  truncated: args.truncated
8325
8355
  };
8326
8356
  }
@@ -8346,9 +8376,9 @@ function getDefaultScheduleTimezone() {
8346
8376
  return process.env.JUNIOR_TIMEZONE?.trim() || DEFAULT_SCHEDULE_TIMEZONE;
8347
8377
  }
8348
8378
  //#endregion
8349
- //#region src/chat/scheduled-tasks/tools/create.ts
8350
- /** Create a tool that stores a scheduled task for the active Slack context. */
8351
- function createSlackScheduleCreateTaskTool(context) {
8379
+ //#region src/chat/scheduled-automations/tools/create.ts
8380
+ /** Create a tool that stores a scheduled automation for the active Slack context. */
8381
+ function createSlackScheduleCreateAutomationTool(context) {
8352
8382
  return zodTool({
8353
8383
  approvalMode: "review",
8354
8384
  annotations: {
@@ -8360,19 +8390,19 @@ function createSlackScheduleCreateTaskTool(context) {
8360
8390
  description: "Create a one-time or recurring Junior task in the active Slack conversation when the user asks Junior to do work later or repeatedly.",
8361
8391
  executionMode: "sequential",
8362
8392
  inputSchema: z.object({
8363
- task: z.string().min(1).max(4e3),
8393
+ instruction: z.string().min(1).max(4e3),
8364
8394
  title: z.string().trim().min(1).max(60).nullable().describe("Optional short display title. Omit or use null to generate one from the task instruction.").optional(),
8365
8395
  schedule: scheduleIntentSchema.describe("When the task runs. The scheduler computes the exact next run from this intent and the server clock."),
8366
- outcomes: z.array(taskOutcomeInputSchema).max(5).describe("Messages to send after successful work. Use an empty list to send nothing. Omit to send one message to the current Slack conversation.").optional(),
8367
- credential_mode: z.enum(["creator", "system"]).nullable().describe("Use creator to make the task creator's connected credentials available, or system when the creator says not to use them. Omit or use null for the creator default.").optional()
8396
+ outcomes: z.array(taskOutcomeInputSchema).max(5).describe("Successful work is silent by default. Omit this field or use an empty list when the Automation should act through tools without a status message. Add send_message only when the user asks for a reminder, post, digest, summary, or other visible result.").optional(),
8397
+ credentialMode: z.enum(["creator", "system"]).nullable().describe("Use creator to make the task creator's connected credentials available, or system when the creator says not to use them. Omit or use null for the creator default.").optional()
8368
8398
  }).strict(),
8369
8399
  prepareArguments(args) {
8370
8400
  const prepared = { ...args };
8371
8401
  if (prepared.title == null) delete prepared.title;
8372
- if (prepared.credential_mode === "creator" || prepared.credential_mode === null) delete prepared.credential_mode;
8402
+ if (prepared.credentialMode === "creator" || prepared.credentialMode === null) delete prepared.credentialMode;
8373
8403
  return prepared;
8374
8404
  },
8375
- outputSchema: scheduleTaskToolResultSchema,
8405
+ outputSchema: scheduleAutomationToolResultSchema,
8376
8406
  execute: async (input, options) => {
8377
8407
  const destination = requireActiveConversation(context);
8378
8408
  const actor = requireActor(context, destination);
@@ -8382,13 +8412,13 @@ function createSlackScheduleCreateTaskTool(context) {
8382
8412
  toolCallId: options.toolCallId
8383
8413
  });
8384
8414
  const db = getDb();
8385
- const existing = await readScheduledTask(db, id);
8415
+ const existing = await readScheduledAutomation(db, id);
8386
8416
  if (existing) {
8387
- if (!sameDestination(existing, destination) || existing.createdBy.slackUserId !== actor.slackUserId) throwToolInputError("Scheduled task operation identity is invalid.");
8388
- return scheduleTaskToolResult("slackScheduleCreateTask", compactTask(existing));
8417
+ if (!sameDestination(existing, destination) || existing.createdBy.slackUserId !== actor.slackUserId) throwToolInputError("Scheduled automation operation identity is invalid.");
8418
+ return scheduleAutomationToolResult(existing, actor.slackUserId);
8389
8419
  }
8390
8420
  const identity = (await context.users.resolveActor())?.identity;
8391
- if (!identity || identity.provider !== "slack" || identity.providerTenantId !== destination.teamId || identity.providerSubjectId !== actor.slackUserId) throwToolInputError("Scheduled task creator identity is unavailable.");
8421
+ if (!identity || identity.provider !== "slack" || identity.providerTenantId !== destination.teamId || identity.providerSubjectId !== actor.slackUserId) throwToolInputError("Scheduled automation creator identity is unavailable.");
8392
8422
  const nowMs = context.now?.() ?? Date.now();
8393
8423
  let compiled;
8394
8424
  try {
@@ -8404,7 +8434,7 @@ function createSlackScheduleCreateTaskTool(context) {
8404
8434
  const conversationAccess = getConversationAccess(destination, context.source);
8405
8435
  const title = await resolveTaskTitle({
8406
8436
  completeText,
8407
- instruction: input.task,
8437
+ instruction: input.instruction,
8408
8438
  title: input.title
8409
8439
  });
8410
8440
  const task = {
@@ -8414,28 +8444,28 @@ function createSlackScheduleCreateTaskTool(context) {
8414
8444
  createdBy: actor,
8415
8445
  creatorIdentityId: identity.id,
8416
8446
  conversationAccess,
8417
- credentialMode: input.credential_mode ?? "creator",
8447
+ credentialMode: input.credentialMode ?? "creator",
8418
8448
  destination,
8419
- executionActor: SCHEDULED_TASK_SYSTEM_ACTOR,
8449
+ executionActor: SCHEDULED_AUTOMATION_SYSTEM_ACTOR,
8420
8450
  nextRunAtMs: compiled.nextRunAtMs,
8421
8451
  originalRequest: context.userText,
8422
8452
  schedule: compiled.schedule,
8423
8453
  status: "active",
8424
8454
  outcomes: await resolveTaskOutcomes(input.outcomes, destination, actor.slackUserId),
8425
- task: { text: input.task },
8455
+ task: { text: input.instruction },
8426
8456
  ...title ? { title } : void 0
8427
8457
  };
8428
- const committed = await createScheduledTask(db, task);
8429
- if (!sameDestination(committed, destination) || committed.createdBy.slackUserId !== actor.slackUserId) throwToolInputError("Scheduled task operation identity is invalid.");
8430
- logInfo("scheduled_task.create.completed", scheduledTaskAttributes(committed));
8431
- return scheduleTaskToolResult("slackScheduleCreateTask", compactTask(committed));
8458
+ const committed = await createScheduledAutomation(db, task);
8459
+ if (!sameDestination(committed, destination) || committed.createdBy.slackUserId !== actor.slackUserId) throwToolInputError("Scheduled automation operation identity is invalid.");
8460
+ logInfo("scheduled_automation.create.completed", scheduledAutomationAttributes(committed));
8461
+ return scheduleAutomationToolResult(committed, actor.slackUserId);
8432
8462
  }
8433
8463
  });
8434
8464
  }
8435
8465
  //#endregion
8436
- //#region src/chat/scheduled-tasks/tools/delete.ts
8437
- /** Create a tool that removes a scheduled task from the active Slack conversation. */
8438
- function createSlackScheduleDeleteTaskTool(context) {
8466
+ //#region src/chat/scheduled-automations/tools/delete.ts
8467
+ /** Create a tool that removes a scheduled automation from the active Slack conversation. */
8468
+ function createSlackScheduleDeleteAutomationTool(context) {
8439
8469
  return zodTool({
8440
8470
  approvalMode: "review",
8441
8471
  annotations: {
@@ -8446,21 +8476,21 @@ function createSlackScheduleDeleteTaskTool(context) {
8446
8476
  },
8447
8477
  description: "Delete one scheduled Junior task from the active Slack conversation. Use only task IDs returned for this conversation. Do not delete schedules from threads, other channels, or another user's DM.",
8448
8478
  executionMode: "sequential",
8449
- inputSchema: z.object({ task_id: z.string().min(1).describe("ID of the task to delete. Must be from this active Slack conversation.") }),
8450
- outputSchema: scheduleTaskToolResultSchema,
8451
- execute: async ({ task_id }) => {
8479
+ inputSchema: z.object({ automationId: z.string().min(1).describe("ID of the task to delete. Must be from this active Slack conversation.") }),
8480
+ outputSchema: scheduleAutomationToolResultSchema,
8481
+ execute: async ({ automationId }) => {
8452
8482
  const next = {
8453
8483
  ...await getWritableTask({
8454
8484
  context,
8455
- taskId: task_id
8485
+ taskId: automationId
8456
8486
  }),
8457
8487
  updatedAtMs: Date.now(),
8458
8488
  status: "deleted",
8459
8489
  nextRunAtMs: void 0,
8460
8490
  runNowAtMs: void 0
8461
8491
  };
8462
- await saveScheduledTask(getDb(), next);
8463
- return scheduleTaskToolResult("slackScheduleDeleteTask", compactTask(next));
8492
+ await saveScheduledAutomation(getDb(), next);
8493
+ return scheduleAutomationToolResult(next, context.actor?.userId);
8464
8494
  }
8465
8495
  });
8466
8496
  }
@@ -8499,7 +8529,7 @@ function parseRequiredSlackUserIdParam(field, value) {
8499
8529
  };
8500
8530
  }
8501
8531
  //#endregion
8502
- //#region src/chat/scheduled-tasks/tools/list.ts
8532
+ //#region src/chat/scheduled-automations/tools/list.ts
8503
8533
  function taskMatchesQuery(task, query) {
8504
8534
  const normalized = query.toLowerCase();
8505
8535
  return [
@@ -8510,10 +8540,10 @@ function taskMatchesQuery(task, query) {
8510
8540
  task.status
8511
8541
  ].some((value) => value?.toLowerCase().includes(normalized));
8512
8542
  }
8513
- /** Create a tool that lists scheduled tasks for the active conversation or the requester. */
8514
- function createSlackScheduleListTasksTool(context) {
8543
+ /** Create a tool that lists scheduled automations for the active conversation or the requester. */
8544
+ function createSlackScheduleListAutomationsTool(context) {
8515
8545
  return zodTool({
8516
- description: "List scheduled tasks in this Slack conversation. To find one of the requester's tasks elsewhere in the workspace, pass channel_id and/or query.",
8546
+ description: "List scheduled automations in this Slack conversation. Each result says whether the requester is the creator. To find one of the requester's automations elsewhere in the workspace, pass channel_id and/or query.",
8517
8547
  annotations: {
8518
8548
  destructiveHint: false,
8519
8549
  idempotentHint: true,
@@ -8522,7 +8552,7 @@ function createSlackScheduleListTasksTool(context) {
8522
8552
  },
8523
8553
  inputSchema: z.object({
8524
8554
  channel_id: slackChannelIdParam("Current destination channel ID to filter by. Use the ID from a channel mention; do not guess.").nullable().optional(),
8525
- query: z.string().trim().min(1).max(200).nullable().describe("Text to match in the requester's scheduled tasks.").optional()
8555
+ query: z.string().trim().min(1).max(200).nullable().describe("Text to match in the requester's scheduled automations.").optional()
8526
8556
  }).strict(),
8527
8557
  outputSchema: scheduleListToolResultSchema,
8528
8558
  execute: async (input) => {
@@ -8536,7 +8566,7 @@ function createSlackScheduleListTasksTool(context) {
8536
8566
  }
8537
8567
  const query = input.query?.trim() || void 0;
8538
8568
  const crossConversation = Boolean(query) || channelId !== void 0 && channelId !== destination.channelId;
8539
- const matching = (await listScheduledTasksForTeam(getDb(), destination.teamId)).filter((task) => {
8569
+ const matching = (await listScheduledAutomationsForTeam(getDb(), destination.teamId)).filter((task) => {
8540
8570
  if (task.destination.platform !== "slack") return false;
8541
8571
  if (task.destination.teamId !== destination.teamId) return false;
8542
8572
  if (task.status === "completed") return false;
@@ -8546,19 +8576,18 @@ function createSlackScheduleListTasksTool(context) {
8546
8576
  if (query && !taskMatchesQuery(task, query)) return false;
8547
8577
  return true;
8548
8578
  }).sort((left, right) => right.createdAtMs - left.createdAtMs || right.id.localeCompare(left.id));
8549
- const visible = matching.slice(0, 50).map(compactTask);
8579
+ const visible = matching.slice(0, 50).map((task) => compactTask(task, actor.slackUserId));
8550
8580
  return scheduleListToolResult({
8551
- target: "slackScheduleListTasks",
8552
- tasks: visible,
8581
+ automations: visible,
8553
8582
  truncated: matching.length > visible.length
8554
8583
  });
8555
8584
  }
8556
8585
  });
8557
8586
  }
8558
8587
  //#endregion
8559
- //#region src/chat/scheduled-tasks/tools/run-now.ts
8560
- /** Create a tool that marks an existing scheduled task due immediately. */
8561
- function createSlackScheduleRunTaskNowTool(context) {
8588
+ //#region src/chat/scheduled-automations/tools/run-now.ts
8589
+ /** Create a tool that marks an existing scheduled automation due immediately. */
8590
+ function createSlackScheduleRunAutomationNowTool(context) {
8562
8591
  return zodTool({
8563
8592
  approvalMode: "review",
8564
8593
  annotations: {
@@ -8567,31 +8596,31 @@ function createSlackScheduleRunTaskNowTool(context) {
8567
8596
  openWorldHint: true,
8568
8597
  readOnlyHint: false
8569
8598
  },
8570
- description: "Queue an existing active scheduled Junior task to run as soon as possible, without changing its cadence. Use when the user asks to run an existing scheduled task now. Use only task IDs returned for this conversation.",
8599
+ description: "Queue an existing active scheduled Junior task to run as soon as possible, without changing its cadence. Use when the user asks to run an existing scheduled automation now. Use only task IDs returned for this conversation.",
8571
8600
  executionMode: "sequential",
8572
- inputSchema: z.object({ task_id: z.string().min(1).describe("ID of the active task to run now. Must be from this active Slack conversation.") }),
8573
- outputSchema: scheduleTaskToolResultSchema,
8574
- execute: async ({ task_id }) => {
8601
+ inputSchema: z.object({ automationId: z.string().min(1).describe("ID of the active task to run now. Must be from this active Slack conversation.") }),
8602
+ outputSchema: scheduleAutomationToolResultSchema,
8603
+ execute: async ({ automationId }) => {
8575
8604
  const lookup = await getWritableTask({
8576
8605
  context,
8577
- taskId: task_id
8606
+ taskId: automationId
8578
8607
  });
8579
- if (lookup.status !== "active") throwToolInputError("Scheduled task must be active before it can be run now.");
8608
+ if (lookup.status !== "active") throwToolInputError("Scheduled automation must be active before it can be run now.");
8580
8609
  const nowMs = Date.now();
8581
8610
  const next = {
8582
8611
  ...lookup,
8583
8612
  updatedAtMs: nowMs,
8584
8613
  runNowAtMs: nowMs
8585
8614
  };
8586
- await saveScheduledTask(getDb(), next);
8587
- return scheduleTaskToolResult("slackScheduleRunTaskNow", compactTask(next));
8615
+ await saveScheduledAutomation(getDb(), next);
8616
+ return scheduleAutomationToolResult(next, context.actor?.userId);
8588
8617
  }
8589
8618
  });
8590
8619
  }
8591
8620
  //#endregion
8592
- //#region src/chat/scheduled-tasks/tools/update.ts
8593
- /** Create a tool that edits a scheduled task, including moving it here. */
8594
- function createSlackScheduleUpdateTaskTool(context) {
8621
+ //#region src/chat/scheduled-automations/tools/update.ts
8622
+ /** Create a tool that edits a scheduled automation, including moving it here. */
8623
+ function createSlackScheduleUpdateAutomationTool(context) {
8595
8624
  return zodTool({
8596
8625
  approvalMode: "review",
8597
8626
  annotations: {
@@ -8600,37 +8629,37 @@ function createSlackScheduleUpdateTaskTool(context) {
8600
8629
  openWorldHint: true,
8601
8630
  readOnlyHint: false
8602
8631
  },
8603
- description: "Update a scheduled task. To move the requester's task into this Slack conversation, set destination to \"here\".",
8632
+ description: "Update a scheduled automation. To move the requester's task into this Slack conversation, set destination to \"here\".",
8604
8633
  executionMode: "sequential",
8605
8634
  inputSchema: z.object({
8606
- task_id: z.string().min(1).describe("Scheduled task ID returned by slackScheduleListTasks."),
8607
- task: z.string().min(1).max(4e3).optional(),
8635
+ automationId: z.string().min(1).describe("Scheduled automation ID returned by slackScheduleListAutomations."),
8636
+ instruction: z.string().min(1).max(4e3).optional(),
8608
8637
  schedule: scheduleIntentSchema.describe("Complete replacement schedule. Omit to keep it unchanged.").nullable().optional(),
8609
8638
  outcomes: z.array(taskOutcomeInputSchema).max(5).describe("Replacement messages to send after successful work. Use an empty list to send nothing. Omit to keep unchanged.").optional(),
8610
8639
  status: z.enum(["active", "blocked"]).describe("Set active to resume a blocked task, or blocked to stop dispatch.").optional(),
8611
8640
  destination: z.literal("here").nullable().describe("Set to \"here\" to move the creator's task into this Slack conversation. Omit to keep its destination.").optional(),
8612
- credential_mode: z.enum(["system", "creator"]).nullable().describe("Use creator credentials or system credentials. Only the task creator may enable creator mode. Omit to keep unchanged.").optional()
8641
+ credentialMode: z.enum(["system", "creator"]).nullable().describe("Use creator credentials or system credentials. Only the task creator may enable creator mode. Omit to keep unchanged.").optional()
8613
8642
  }).strict(),
8614
- outputSchema: scheduleTaskToolResultSchema,
8643
+ outputSchema: scheduleAutomationToolResultSchema,
8615
8644
  execute: async (input) => {
8616
8645
  const activeDestination = requireActiveConversation(context);
8617
8646
  const actor = requireActor(context, activeDestination);
8618
8647
  const db = getDb();
8619
- const lookup = await readScheduledTask(db, input.task_id);
8620
- if (!lookup || lookup.status === "deleted") throwToolInputError("Scheduled task was not found.");
8621
- if (lookup.status === "completed") throwToolInputError("Completed scheduled tasks cannot be updated. Create a new task instead.");
8622
- if (lookup.destination.platform !== "slack") throwToolInputError("Scheduled task destination is invalid.");
8623
- if (lookup.destination.teamId !== activeDestination.teamId) throwToolInputError("Scheduled tasks can only be managed within the same Slack workspace.");
8648
+ const lookup = await readScheduledAutomation(db, input.automationId);
8649
+ if (!lookup || lookup.status === "deleted") throwToolInputError("Scheduled automation was not found.");
8650
+ if (lookup.status === "completed") throwToolInputError("Completed scheduled automations cannot be updated. Create a new automation instead.");
8651
+ if (lookup.destination.platform !== "slack") throwToolInputError("Scheduled automation destination is invalid.");
8652
+ if (lookup.destination.teamId !== activeDestination.teamId) throwToolInputError("Scheduled automations can only be managed within the same Slack workspace.");
8624
8653
  const moveHere = input.destination === "here";
8625
8654
  const alreadyHere = sameDestination(lookup, activeDestination);
8626
8655
  const isCreator = actor.slackUserId === lookup.createdBy.slackUserId;
8627
- if (!alreadyHere && !moveHere) throwToolInputError("Scheduled task can only be managed from the Slack destination where it currently delivers. Set destination to \"here\" to move it into this conversation.");
8628
- if (moveHere && !isCreator) throwToolInputError("Only the scheduled task creator can move this task.");
8629
- if (input.credential_mode === "creator" && !isCreator) throwToolInputError("Only the scheduled task creator can enable creator credential use.");
8630
- if (input.outcomes !== void 0 && !isCreator) throwToolInputError("Only the scheduled task creator can change message destinations.");
8656
+ if (!alreadyHere && !moveHere) throwToolInputError("Scheduled automation can only be managed from the Slack destination where it currently delivers. Set destination to \"here\" to move it into this conversation.");
8657
+ if (moveHere && !isCreator) throwToolInputError("Only the scheduled automation creator can move this task.");
8658
+ if (input.credentialMode === "creator" && !isCreator) throwToolInputError("Only the scheduled automation creator can enable creator credential use.");
8659
+ if (input.outcomes !== void 0 && !isCreator) throwToolInputError("Only the scheduled automation creator can change message destinations.");
8631
8660
  const changingDestination = moveHere && !alreadyHere;
8632
8661
  if (changingDestination) {
8633
- if ((await db.select({ id: juniorSchedulerRuns.id }).from(juniorSchedulerRuns).where(and(eq(juniorSchedulerRuns.taskId, lookup.id), inArray(juniorSchedulerRuns.status, ["pending", "running"]))).limit(1)).length > 0) throwToolInputError("Scheduled task cannot be moved while an occurrence is already running. Try again after the current run finishes.");
8662
+ if ((await db.select({ id: juniorSchedulerRuns.id }).from(juniorSchedulerRuns).where(and(eq(juniorSchedulerRuns.taskId, lookup.id), inArray(juniorSchedulerRuns.status, ["pending", "running"]))).limit(1)).length > 0) throwToolInputError("Scheduled automation cannot be moved while an occurrence is already running. Try again after the current run finishes.");
8634
8663
  }
8635
8664
  const nowMs = context.now?.() ?? Date.now();
8636
8665
  let compiled;
@@ -8647,10 +8676,10 @@ function createSlackScheduleUpdateTaskTool(context) {
8647
8676
  const nextRunAtMs = compiled?.nextRunAtMs ?? lookup.nextRunAtMs;
8648
8677
  const status = normalizeStatus(input.status);
8649
8678
  if (input.status && !status) throwToolInputError("status must be active or blocked.");
8650
- if (status === "active" && !nextRunAtMs) throwToolInputError("Active scheduled tasks require a schedule with a future occurrence.");
8679
+ if (status === "active" && !nextRunAtMs) throwToolInputError("Active scheduled automations require a schedule with a future occurrence.");
8651
8680
  const nextStatus = status ?? lookup.status;
8652
- const credentialMode = input.task !== void 0 && input.task !== lookup.task.text && !isCreator ? "system" : input.credential_mode ?? lookup.credentialMode;
8653
- const nextInstruction = input.task !== void 0 ? input.task : lookup.task.text;
8681
+ const credentialMode = input.instruction !== void 0 && input.instruction !== lookup.task.text && !isCreator ? "system" : input.credentialMode ?? lookup.credentialMode;
8682
+ const nextInstruction = input.instruction !== void 0 ? input.instruction : lookup.task.text;
8654
8683
  const instructionChanged = nextInstruction !== lookup.task.text;
8655
8684
  const nextDestination = changingDestination ? activeDestination : lookup.destination;
8656
8685
  const next = {
@@ -8676,16 +8705,16 @@ function createSlackScheduleUpdateTaskTool(context) {
8676
8705
  if (title) next.title = title;
8677
8706
  else delete next.title;
8678
8707
  }
8679
- if (!changingDestination && !instructionChanged && !compiled && status === void 0 && (input.credential_mode === void 0 || input.credential_mode === null || input.credential_mode === lookup.credentialMode) && input.outcomes === void 0 && moveHere) return scheduleTaskToolResult("slackScheduleUpdateTask", compactTask(lookup));
8680
- const committed = await saveScheduledTask(db, next);
8681
- if (changingDestination) logInfo("scheduled_task.move.completed", scheduledTaskAttributes(committed));
8682
- return scheduleTaskToolResult("slackScheduleUpdateTask", compactTask(committed));
8708
+ if (!changingDestination && !instructionChanged && !compiled && status === void 0 && (input.credentialMode === void 0 || input.credentialMode === null || input.credentialMode === lookup.credentialMode) && input.outcomes === void 0 && moveHere) return scheduleAutomationToolResult(lookup, actor.slackUserId);
8709
+ const committed = await saveScheduledAutomation(db, next);
8710
+ if (changingDestination) logInfo("scheduled_automation.move.completed", scheduledAutomationAttributes(committed));
8711
+ return scheduleAutomationToolResult(committed, actor.slackUserId);
8683
8712
  }
8684
8713
  });
8685
8714
  }
8686
8715
  //#endregion
8687
- //#region src/chat/tools/scheduled-tasks.ts
8688
- function scheduledTaskToolContext(context) {
8716
+ //#region src/chat/tools/scheduled-automations.ts
8717
+ function scheduledAutomationToolContext(context) {
8689
8718
  if (context.source.kind !== "slack" || context.destination.platform !== "slack" || context.actor?.platform !== "slack" || !context.resolveActorIdentity) return;
8690
8719
  return {
8691
8720
  actor: context.actor,
@@ -8694,16 +8723,16 @@ function scheduledTaskToolContext(context) {
8694
8723
  ...context.userText ? { userText: context.userText } : void 0
8695
8724
  };
8696
8725
  }
8697
- /** Build scheduled-task tools for an interactive Slack actor. */
8698
- function createScheduledTaskTools(context) {
8699
- const taskContext = scheduledTaskToolContext(context);
8726
+ /** Build scheduled-automation tools for an interactive Slack actor. */
8727
+ function createScheduledAutomationTools(context) {
8728
+ const taskContext = scheduledAutomationToolContext(context);
8700
8729
  if (!taskContext) return {};
8701
8730
  return {
8702
- slackScheduleCreateTask: createSlackScheduleCreateTaskTool(taskContext),
8703
- slackScheduleListTasks: createSlackScheduleListTasksTool(taskContext),
8704
- slackScheduleUpdateTask: createSlackScheduleUpdateTaskTool(taskContext),
8705
- slackScheduleDeleteTask: createSlackScheduleDeleteTaskTool(taskContext),
8706
- slackScheduleRunTaskNow: createSlackScheduleRunTaskNowTool(taskContext)
8731
+ slackScheduleCreateAutomation: createSlackScheduleCreateAutomationTool(taskContext),
8732
+ slackScheduleListAutomations: createSlackScheduleListAutomationsTool(taskContext),
8733
+ slackScheduleUpdateAutomation: createSlackScheduleUpdateAutomationTool(taskContext),
8734
+ slackScheduleDeleteAutomation: createSlackScheduleDeleteAutomationTool(taskContext),
8735
+ slackScheduleRunAutomationNow: createSlackScheduleRunAutomationNowTool(taskContext)
8707
8736
  };
8708
8737
  }
8709
8738
  //#endregion
@@ -12770,7 +12799,7 @@ async function tryRecordWorkspaceSwitchStat(workspace) {
12770
12799
  }
12771
12800
  async function stopWorkspaceSnapshotWatch(input) {
12772
12801
  try {
12773
- await cancelResourceEventSubscription({
12802
+ await cancelWatch({
12774
12803
  conversationId: input.conversationId,
12775
12804
  id: input.subscriptionId
12776
12805
  });
@@ -12967,7 +12996,7 @@ function createWorkspaceTools(context) {
12967
12996
  outputSchema: juniorToolOutputSchema.extend({
12968
12997
  workspace: workspaceSchema,
12969
12998
  status: z.enum(["ready", "building"]),
12970
- subscription: resourceEventSubscriptionResultSchema.optional().describe("Present when the snapshot ready and failed events are already watched for this conversation.")
12999
+ subscription: watchResultSchema.optional().describe("Present when the snapshot ready and failed events are already watched for this conversation.")
12971
13000
  }),
12972
13001
  async execute({ name }, options) {
12973
13002
  const workspace = await getWorkspaceByName(getDb(), name);
@@ -12977,7 +13006,7 @@ function createWorkspaceTools(context) {
12977
13006
  workspaceName: workspace.name
12978
13007
  });
12979
13008
  const conversationId = context.conversationId.trim();
12980
- const subscription = conversationId ? await createResourceEventSubscription({
13009
+ const subscription = conversationId ? await createWatch({
12981
13010
  conversationId,
12982
13011
  events: [WORKSPACE_SNAPSHOT_READY_EVENT, WORKSPACE_SNAPSHOT_FAILED_EVENT],
12983
13012
  expiresAtMs: Date.now() + RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS,
@@ -13042,7 +13071,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
13042
13071
  const slackContext = getSlackToolContext(context);
13043
13072
  const slackLocationCapabilities = slackContext ? resolveChannelCapabilities(slackContext.locationChannelId) : void 0;
13044
13073
  const canSendFilesToActiveConversation = Boolean(slackContext && slackLocationCapabilities?.canSendFiles);
13045
- const resourceEventCatalog = getResourceEventCatalog();
13074
+ const eventCatalog = getEventCatalog();
13046
13075
  const tools = {
13047
13076
  ...options.includeLoadSkill === false ? void 0 : { loadSkill: createLoadSkillTool(availableSkills, { onSkillLoaded: hooks.onSkillLoaded }) },
13048
13077
  reportProgress: createReportProgressTool(),
@@ -13056,9 +13085,9 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
13056
13085
  writeFile: createWriteFileTool(),
13057
13086
  webSearch: createWebSearchTool(botConfig.webSearchModelId, hooks.toolOverrides?.webSearch),
13058
13087
  webFetch: createWebFetchTool(hooks, { canSendFilesToActiveConversation }),
13059
- ...createResourceEventTools(context, resourceEventCatalog),
13060
- ...createEventTaskTools(context, resourceEventCatalog),
13061
- ...createScheduledTaskTools(context),
13088
+ ...createEventTools(context, eventCatalog),
13089
+ ...createEventAutomationTools(context, eventCatalog),
13090
+ ...createScheduledAutomationTools(context),
13062
13091
  ...createWorkspaceTools(context)
13063
13092
  };
13064
13093
  tools.searchConversationEvents = createSearchConversationEventsTool(context);
@@ -15434,7 +15463,7 @@ Assess the exact action's intrinsic risk and whether the user's intent authorize
15434
15463
  ## Data Exfiltration
15435
15464
  - Sending private data, organization data, secrets, or credentials to an untrusted destination is high or critical risk.
15436
15465
  - A user-requested read, query, or upload to a trusted destination is not exfiltration by default.
15437
- - The active Junior conversation is not an untrusted destination merely because it is a public or multi-user channel. For a scheduled task or event task, a request by the current actor for scoped work that needs their connected service access authorizes routine service-native reads and posting the requested result to the task's stored Slack destination. It does not authorize exposing credential values, broad data dumps, or delivery to another destination.
15466
+ - The active Junior conversation is not an untrusted destination merely because it is a public or multi-user channel. For a scheduled automation or event automation, a request by the current actor for scoped work that needs their connected service access authorizes routine service-native reads and posting the requested result to the task's stored Slack destination. It does not authorize exposing credential values, broad data dumps, or delivery to another destination.
15438
15467
  - Using an existing credential to authenticate a user-requested action is not credential exfiltration by itself.
15439
15468
  - Ordinary product context such as internal system names, repository names, or workflow descriptions is not private organization data by itself, including on an authorized public write destination.
15440
15469
  - Deny disclosure of secrets, credentials, or private organization data to an untrusted destination even when the user requested it.
@@ -15728,9 +15757,9 @@ function resolveToolRuntimeRoute(args) {
15728
15757
  actor: args.actor?.platform === "web" ? args.actor : void 0,
15729
15758
  source: args.run.source
15730
15759
  };
15731
- case "resource_event":
15732
- case "scheduled_task":
15733
- case "event_task":
15760
+ case "event":
15761
+ case "scheduled_automation":
15762
+ case "event_automation":
15734
15763
  case "plugin_dispatch":
15735
15764
  case "agent_invocation": return {
15736
15765
  destination,
@@ -17698,4 +17727,4 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
17698
17727
  }
17699
17728
  }
17700
17729
  //#endregion
17701
- export { shouldEmitDevAgentTrace as $, createAgentInvocationSchema as A, resolveSandboxEgressProviderForHost as B, renderBlockText as C, getNextRunAtMs as D, scheduledTaskRunAttributes as E, ingestResourceEvent as F, consumeSandboxEgressAuthRequiredSignal as G, shouldPropagateSandboxEgressTrace as H, isResourceEventMailboxMetadata as I, sandboxEgressSignalsResponseSchema as J, consumeSandboxEgressPermissionDeniedSignal as K, renderTaskInput as L, AgentInvocationLimitError as M, getMcpProviderErrorAttributes as N, agentBindingSchema as O, processWorkspaceSnapshotJob as P, AuthorizationFlowDisabledError as Q, maybePostAutomatedTurnLimitNotice as R, renderAttachmentText as S, logScheduledTaskRunSkipped as T, SANDBOX_EGRESS_PROXY_PATH as U, normalizeSandboxEgressTracePropagationDomains as V, clearSandboxEgressSignals as W, buildSteeringPiMessage as X, createUserTokenStore as Y, isVisionImageMediaType as Z, readPublicArtifact as _, deleteMcpAuthSession as a, readAttachmentVisionSummary as b, deleteMcpStoredOAuthCredentials as c, putMcpStoredOAuthCredentials as d, getConfigDefaults as et, PluginCredentialFailureError as f, publicArtifactHeaders as g, resolvePluginOAuthAccount as h, finalizeMcpAuthorization as i, AgentInvocationBusyError as j, agentInvocationSchema as k, getMcpAuthSession as l, latestReportedProgress as m, createContextCompactor as n, deleteMcpAuthSessionsForUserProvider as o, authorizationId as p, parseSandboxEgressCredentialToken as q, executeCredentialedEgressRequest as r, deleteMcpServerSessionId as s, executeAgentRun as t, setConfigDefaults as tt, getMcpStoredOAuthCredentials as u, unpublishedArtifactHeaders as v, listThreadReplies as w, recordSlackAttachment as x, lookupSlackUserProfile as y, recordFinishedTurnForAutomatedLimit as z };
17730
+ export { shouldEmitDevAgentTrace as $, createAgentInvocationSchema as A, resolveSandboxEgressProviderForHost as B, renderBlockText as C, getNextRunAtMs as D, scheduledAutomationRunAttributes as E, ingestEvent as F, consumeSandboxEgressAuthRequiredSignal as G, shouldPropagateSandboxEgressTrace as H, isEventMailboxMetadata as I, sandboxEgressSignalsResponseSchema as J, consumeSandboxEgressPermissionDeniedSignal as K, renderTaskInput as L, AgentInvocationLimitError as M, getMcpProviderErrorAttributes as N, agentBindingSchema as O, processWorkspaceSnapshotJob as P, AuthorizationFlowDisabledError as Q, maybePostAutomatedTurnLimitNotice as R, renderAttachmentText as S, logScheduledAutomationRunSkipped as T, SANDBOX_EGRESS_PROXY_PATH as U, normalizeSandboxEgressTracePropagationDomains as V, clearSandboxEgressSignals as W, buildSteeringPiMessage as X, createUserTokenStore as Y, isVisionImageMediaType as Z, readPublicArtifact as _, deleteMcpAuthSession as a, readAttachmentVisionSummary as b, deleteMcpStoredOAuthCredentials as c, putMcpStoredOAuthCredentials as d, getConfigDefaults as et, PluginCredentialFailureError as f, publicArtifactHeaders as g, resolvePluginOAuthAccount as h, finalizeMcpAuthorization as i, AgentInvocationBusyError as j, agentInvocationSchema as k, getMcpAuthSession as l, latestReportedProgress as m, createContextCompactor as n, deleteMcpAuthSessionsForUserProvider as o, authorizationId as p, parseSandboxEgressCredentialToken as q, executeCredentialedEgressRequest as r, deleteMcpServerSessionId as s, executeAgentRun as t, setConfigDefaults as tt, getMcpStoredOAuthCredentials as u, unpublishedArtifactHeaders as v, listThreadReplies as w, recordSlackAttachment as x, lookupSlackUserProfile as y, recordFinishedTurnForAutomatedLimit as z };