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