@sentry/junior 0.204.0 → 0.206.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/{agent-CMyTD4DD.js → agent-C9yuiZUF.js} +277 -85
- package/dist/{agent-hooks-Bbcp9e33.js → agent-hooks-DNjlz2A-.js} +1084 -16
- package/dist/{agent-runner-DNb1A49M.js → agent-runner-E67lFrDG.js} +5 -5
- package/dist/api/schema.d.ts +85 -0
- package/dist/api/schema.js +2 -2
- package/dist/api.js +44 -511
- package/dist/{app-B1TOqBI8.d.ts → app-AxGmJHwK.d.ts} +8 -0
- package/dist/app.d.ts +1 -1
- package/dist/app.js +56 -84
- package/dist/{auth-pause-state-DosEalIG.js → auth-pause-state-MVZ6xvEK.js} +6 -6
- package/dist/briefs-CvJFQvhJ.js +398 -0
- package/dist/{catalog-runtime-BReos-D4.js → catalog-runtime-TBR8n4e1.js} +1 -1
- package/dist/{checkpoint-CNrPyRJN.js → checkpoint-BY47jJCB.js} +7 -6
- package/dist/cli/chat.js +14 -12
- package/dist/cli/check.js +3 -3
- package/dist/cli/init.js +1 -0
- package/dist/cli/main.js +5 -1
- package/dist/cli/plugins.js +3 -3
- package/dist/cli/run.d.ts +2 -1
- package/dist/cli/run.js +2 -1
- package/dist/cli/snapshot-create.js +3 -3
- package/dist/cli/upgrade.js +3 -3
- package/dist/{config-nGCW1OTG.js → client-ceE7NtvC.js} +4 -367
- package/dist/config-CIE83sR2.js +386 -0
- package/dist/{schema-Rn8-XEaN.js → conversation-AA4R1VUn.js} +580 -558
- package/dist/{conversation-privacy-B4voFRSm.js → conversation-privacy-Auyq26XQ.js} +1 -1
- package/dist/{credential-sync-kXr1hvO1.js → credential-sync-BO33aNQd.js} +22 -20
- package/dist/{execution-stats-DWfSihcH.js → execution-stats-SiS2FLcv.js} +4 -4
- package/dist/{executor-DcMSlI5c.js → executor-BfbYPW63.js} +31 -3
- package/dist/instrumentation.js +2 -2
- package/dist/{job-queue-Drn_LXlM.js → job-queue-CyTc24Es.js} +1 -1
- package/dist/{logging-BzAk1S_s.js → logging-D37bayDc.js} +1 -1
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +3 -3
- package/dist/{oauth-callback-server-JiftokvA.js → oauth-callback-server-BtfOeHTZ.js} +2 -2
- package/dist/{pending-auth-CWmSdZVg.js → pending-auth-BPUzcs7n.js} +2 -2
- package/dist/{profile-CrT5nXbw.js → profile-CSixooTi.js} +4 -3
- package/dist/prompt-3gqNY1Ka.js +552 -0
- package/dist/{registry-DH1xUo2N.js → registry-DiR0-xRg.js} +1 -1
- package/dist/{resolve-CZHnfxaS.js → resolve-Bn5q__9b.js} +2 -2
- package/dist/{runner-CZV2sC46.js → runner-DFx3dIJH.js} +9 -9
- package/dist/{sandbox-egress-signals-bHZfmhbd.js → sandbox-egress-signals-bwvjihxA.js} +1 -1
- package/dist/schema-8GXFfclK.js +559 -0
- package/dist/{skills-CIcDQSgM.js → skills-BhM5qyCF.js} +2 -2
- package/dist/{spawn-DdkUFRmq.js → spawn-Dk0PqdH6.js} +2 -2
- package/dist/{stats-DTUbAb88.js → stats-DKRP4rsY.js} +26 -12
- package/dist/{task-queue-CJIR4RF7.js → task-queue-CdpTvu4R.js} +3 -3
- package/dist/{task-runner-D-O3A-Cp.js → task-runner-alpjVSxQ.js} +10 -10
- package/dist/{thread-state-CRc9jTJS.js → thread-state-CRK7aA41.js} +5 -5
- package/dist/{turn-execution-BkinIdJF.js → turn-execution-XtyzIHog.js} +3 -3
- package/dist/{turn-lifecycle-DQV19VTW.js → turn-lifecycle-VbwZLfBv.js} +1 -1
- package/dist/{usage-D3EbSO7w.js → usage-D4A48Bdl.js} +4 -125
- package/dist/{validation-C2CR-OX3.js → validation-jn_46o4U.js} +1 -1
- package/dist/{version-DxcWdoKa.js → version-DcfJxB4z.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/web-authorization-CsfLSfEs.js +38 -0
- package/dist/{web-input-3EPfpf55.js → web-input-BPp_sc7t.js} +6 -6
- package/dist/{work-fGofI7Op.js → work-Di-ubSGg.js} +9 -9
- package/dist/{worker-CsOLq-mR.js → worker-Cu_D5Mr8.js} +5 -4
- package/migrations/0040_conversation_briefs.sql +17 -0
- package/migrations/meta/0040_snapshot.json +3516 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +4 -4
- package/dist/history-CqTuSAdI.js +0 -441
- package/dist/usage-schema-CKaDkH_j.js +0 -20
- package/dist/web-authorization-RMBxAR_t.js +0 -76
|
@@ -1,25 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { C as withSpan, F as isRecord$2, P as normalizeIdentityEmail, S as withLogContext, _ as setSpanAttributes, a as extractGenAiUsageSummary, b as summarizeMessageText, c as getTracePropagationHeaders, d as logInfo, f as logWarn, h as serializeGenAiAttribute, i as extractGenAiUsageAttributes, l as logError, p as normalizeGenAiFinishReason, s as getLogContextAttributesForSpan, u as logException, v as setSpanStatus, y as setTags } from "./logging-
|
|
1
|
+
import { C as resolveGatewayCredential, S as getGatewayApiKey, _ as findProviderError, b as isProviderRetryError, c as COMPACTION_SUMMARY_PREFIX, d as isCompactionSummaryText, f as renderCurrentInstruction, g as createProviderError, h as ProviderError, i as completeText, l as MODEL_HANDOFF_SUMMARY_PREFIX, m as escapeXml, n as GEN_AI_SERVER_ADDRESS, o as resolveGatewayModel, p as unwrapCurrentInstruction, r as completeObject, s as ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX, t as GEN_AI_PROVIDER_NAME, u as hasCompactedConversationContext, v as getProviderErrorAttributes, x as MISSING_GATEWAY_CREDENTIALS_ERROR } from "./client-ceE7NtvC.js";
|
|
2
|
+
import { C as withSpan, F as isRecord$2, P as normalizeIdentityEmail, S as withLogContext, _ as setSpanAttributes, a as extractGenAiUsageSummary, b as summarizeMessageText, c as getTracePropagationHeaders, d as logInfo, f as logWarn, h as serializeGenAiAttribute, i as extractGenAiUsageAttributes, l as logError, p as normalizeGenAiFinishReason, s as getLogContextAttributesForSpan, u as logException, v as setSpanStatus, y as setTags } from "./logging-D37bayDc.js";
|
|
3
3
|
import { _ as withActiveSpan, m as startInactiveSpan } from "./sentry-CD3SdJl-.js";
|
|
4
|
-
import { a as toCanonicalInputMessage, c as toGenAiPayloadMetadata, i as runWithConversationPrivacy, l as toGenAiPayloadTraceAttributes, o as toCanonicalOutputMessage, r as resolveConversationPrivacy, s as toGenAiMessagesTraceAttributes, t as canExposeConversationPayload } from "./conversation-privacy-
|
|
4
|
+
import { a as toCanonicalInputMessage, c as toGenAiPayloadMetadata, i as runWithConversationPrivacy, l as toGenAiPayloadTraceAttributes, o as toCanonicalOutputMessage, r as resolveConversationPrivacy, s as toGenAiMessagesTraceAttributes, t as canExposeConversationPayload } from "./conversation-privacy-Auyq26XQ.js";
|
|
5
|
+
import { h as normalizeSlackEmojiName, n as botConfig } from "./config-CIE83sR2.js";
|
|
5
6
|
import { a as modelIdForProfile, c as TURN_REASONING_LEVELS, i as formatModelProfiles, o as modelProfileSchema, r as formatModelProfile, s as profileConfig, t as ModelProfileNotConfiguredError } from "./model-profile-CZmVoGdX.js";
|
|
6
7
|
import { _ as parseSlackMessageTs, g as parseSlackUserId, h as parseSlackTeamId, i as credentialUserSubjectId, l as isUserActor, m as parseSlackChannelReferenceId, n as credentialContextSchema, p as parseSlackChannelId, t as credentialContextForActor } from "./context-B45_WqVX.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { A as tryWorkspaceRepoCheckoutPath, B as downloadPrivateSlackFile, C as invalidateReadySnapshot, D as SANDBOX_RUNTIME, E as setWorkspaceSnapshotBuild, Ft as getConversationStore, It as getDb, J as withSlackRetries, K as normalizeSlackConversationId, Lt as getSqlExecutor, M as resolveChannelCapabilities, Nt as getConversationEventStore, O as deleteWorkspaceSnapshotBuilders, Pt as getConversationMessageSearchStore, Q as readActorIdentity, S as WorkspaceValidationError, T as setWorkspaceSnapshot, U as getSlackClient, V as getFilePermalink, W as isConversationScopedChannel, Xt as parseDestination, _ as deleteWorkspace, at as STOP_WATCHING_TOOL_NAME, b as listWorkspaces, bt as createPluginLogger, c as getPluginTools, dt as findMatchingResourceEventSubscriptions, ft as listResourceEventSubscriptions, g as createWorkspace, ht as getDashboardTaskLink, it as RESOURCE_WATCH_TOOL_SOURCE, j as workspaceRepoCheckoutPath, k as getWorkspaceSnapshotBuilder, l as getPluginUserPromptContributions, lt as createResourceEventSubscription, mt as getDashboardConversationLink, nt as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, ot as cancelResourceEventSubscription, pt as JUNIOR_THREAD_STATE_TTL_MS, r as createPluginHookRunner, s as getPluginSystemPromptContributions, st as cancelSubscriptions, tt as getSlackToolContext, u as getPlugins, ut as deliverResourceEventSubscription, v as getWorkspace, w as loadSnapshotsForProfile, x as updateWorkspace, y as getWorkspaceByName, z as SlackActionError } from "./agent-hooks-DNjlz2A-.js";
|
|
9
|
+
import { n as juniorDestinations } from "./destinations-BeBiJeEM.js";
|
|
10
|
+
import { D as juniorArtifacts, S as juniorAttachments, T as juniorIdentities, a as juniorSchedulerRuns, d as AGENT_INVOCATION_MAILBOX_STATUSES, g as juniorConversationBriefs, w as juniorConversations, y as juniorConversationAnnotations } from "./executor-BfbYPW63.js";
|
|
11
|
+
import { A as briefLinkSchema, F as KNOWN_CONVERSATION_EVENT_TYPES, G as instructionProvenanceFor, K as sameActorIdentity, M as conversationBriefSchema, U as contextProvenance, W as instructionActors, j as briefOutcomeStatusSchema } from "./conversation-AA4R1VUn.js";
|
|
10
12
|
import { a as listReferenceFiles, c as soulPathCandidates, l as worldPathCandidates } from "./package-discovery-7a9YqLhE.js";
|
|
11
|
-
import { a as resolvePluginCommandEnv, c as getOAuthProviderErrorAttributes, i as resolveAuthTokenPlaceholder, o as OAuthProviderError, s as fetchWithBoundedOAuthErrorBodies, u as CredentialUnavailableError } from "./registry-
|
|
12
|
-
import { n as pluginCatalogRuntime } from "./catalog-runtime-
|
|
13
|
-
import { a as parseSkillInvocation, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-
|
|
14
|
-
import { A as normalizeToLf$1, At as retainRuntimeTurnContext, B as openConversationProjection, C as DEFAULT_SEARCH_COMMAND_TIMEOUT_MS, Ct as hasRuntimeTurnContext, D as getRipgrepSearchLocation, Dt as isToolResultError, E as collectFiles, Et as isContinuablePiBoundary, G as recordAuthorizationRequested, H as recordAttachmentsDelivered, I as loadConnectedMcpProviders, K as recordGuardianActionReviewed, L as loadConversationProjection, M as resolveWorkspacePath, Mt as trimTrailingAssistantMessages, N as truncateText$1, Nt as TURN_CONTEXT_TAG, O as isMissingPathError, Ot as isToolResultMessage, S as resolveRepositoryInstructionsForDirectories, St as getUserMessageInstructionText, T as RIPGREP_EXCLUDED_GLOBS, Tt as isAssistantMessage, V as recordAgentsInstructionsUpdated, X as recordTurnRoute, Y as recordToolExecutionStarted, _ as AGENTS_REPLACEMENT_NOTICE, _t as historyItemFromPiMessage, b as listRepositoryDirectories, bt as getPiMessageRole, f as TurnSliceLimitExceededError, g as AGENTS_REMOVAL_NOTICE, gt as getAgentContextInputLimitTokens, h as isTurnExecutionLimitExceededError, ht as getAgentContextCompactionTriggerTokens, j as positiveInteger$1, jt as stripRuntimeTurnContext, k as missingPathSearchResult, kt as normalizeToolNameFromResult, mt as estimateTextTokens, n as loadTurnCheckpoint, p as assertTurnToolCallLimit, q as recordMcpProviderConnected, r as saveTurnCheckpoint, t as continuableMessages, v as buildAgentsInstructionsMessage, vt as piMessageFromHistoryItem, w as MAX_TEXT_CHARS, x as renderAgentsInstructions, xt as getTerminalAssistantMessages, y as findVisibleAgentsInstructions, yt as extractAssistantText, z as loadTurnRoute } from "./checkpoint-
|
|
15
|
-
import { a as hasAgentTurnUsage, c as generateShortTitle, l as resolveTaskTitle, o as ToolInputError, t as addAgentTurnUsage } from "./usage-
|
|
16
|
-
import { A as sleep$1, D as fenceLock, E as acquireActiveLock, F as sandboxSkillDir, I as sandboxSkillFile, L as sandboxSkillPathResolution, M as SANDBOX_REPOS_ROOT, N as SANDBOX_SKILLS_ROOT, P as SANDBOX_WORKSPACE_ROOT, _ as workspaceSnapshotNotReadyUserMessage, a as isAbortError, b as buildNonInteractiveShellScript, c as isSandboxCommandStreamInterruptedError, d as isSnapshottingError, f as throwSandboxOperationError, g as isWorkspaceSnapshotNotReadyError, h as getWorkspaceSnapshotNotReadyError, i as ensureDockerDaemon, j as SANDBOX_DATA_ROOT, k as withLock, l as isSandboxMissingError, m as WorkspaceSnapshotNotReadyError, n as hash, o as isAlreadyExistsError, p as wrapSandboxSetupError, r as isStale, s as isSandboxApiTransientError, t as create, u as isSandboxUnavailableError, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand, y as buildCommandScript } from "./profile-
|
|
17
|
-
import { $ as
|
|
18
|
-
import { _ as isTurnInputCommitLostError, c as sanitizeAssistantText, f as CooperativeTurnYieldError, l as NO_REPLY_MARKER, n as canReusePendingAuthLink, o as decideReply, p as TurnInputCommitLostError, s as getAssistantReplyText, t as abandonReplacedPendingAuth, u as isNoReplyMarker } from "./pending-auth-
|
|
19
|
-
import { C as toolInvocationDestination, S as surfaceFromRun, _ as uploadFilesToConversation, b as assertRunConsistency, h as postSlackMessage, i as formatProviderLabel, m as getSlackMessagePermalink, o as resolveBaseUrl, p as addReactionToMessage, r as deliverOAuthAuthorization, s as startOAuthFlow, v as RetryableDeliveryError, x as isAgentRunFeatureDisabled, y as actorFromRun } from "./agent-runner-
|
|
20
|
-
import {
|
|
13
|
+
import { a as resolvePluginCommandEnv, c as getOAuthProviderErrorAttributes, i as resolveAuthTokenPlaceholder, o as OAuthProviderError, s as fetchWithBoundedOAuthErrorBodies, u as CredentialUnavailableError } from "./registry-DiR0-xRg.js";
|
|
14
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-TBR8n4e1.js";
|
|
15
|
+
import { a as parseSkillInvocation, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-BhM5qyCF.js";
|
|
16
|
+
import { A as normalizeToLf$1, At as retainRuntimeTurnContext, B as openConversationProjection, C as DEFAULT_SEARCH_COMMAND_TIMEOUT_MS, Ct as hasRuntimeTurnContext, D as getRipgrepSearchLocation, Dt as isToolResultError, E as collectFiles, Et as isContinuablePiBoundary, G as recordAuthorizationRequested, H as recordAttachmentsDelivered, I as loadConnectedMcpProviders, K as recordGuardianActionReviewed, L as loadConversationProjection, M as resolveWorkspacePath, Mt as trimTrailingAssistantMessages, N as truncateText$1, Nt as TURN_CONTEXT_TAG, O as isMissingPathError, Ot as isToolResultMessage, S as resolveRepositoryInstructionsForDirectories, St as getUserMessageInstructionText, T as RIPGREP_EXCLUDED_GLOBS, Tt as isAssistantMessage, V as recordAgentsInstructionsUpdated, X as recordTurnRoute, Y as recordToolExecutionStarted, _ as AGENTS_REPLACEMENT_NOTICE, _t as historyItemFromPiMessage, b as listRepositoryDirectories, bt as getPiMessageRole, f as TurnSliceLimitExceededError, g as AGENTS_REMOVAL_NOTICE, gt as getAgentContextInputLimitTokens, h as isTurnExecutionLimitExceededError, ht as getAgentContextCompactionTriggerTokens, j as positiveInteger$1, jt as stripRuntimeTurnContext, k as missingPathSearchResult, kt as normalizeToolNameFromResult, mt as estimateTextTokens, n as loadTurnCheckpoint, p as assertTurnToolCallLimit, q as recordMcpProviderConnected, r as saveTurnCheckpoint, t as continuableMessages, v as buildAgentsInstructionsMessage, vt as piMessageFromHistoryItem, w as MAX_TEXT_CHARS, x as renderAgentsInstructions, xt as getTerminalAssistantMessages, y as findVisibleAgentsInstructions, yt as extractAssistantText, z as loadTurnRoute } from "./checkpoint-BY47jJCB.js";
|
|
17
|
+
import { a as hasAgentTurnUsage, c as generateShortTitle, l as resolveTaskTitle, o as ToolInputError, t as addAgentTurnUsage } from "./usage-D4A48Bdl.js";
|
|
18
|
+
import { A as sleep$1, D as fenceLock, E as acquireActiveLock, F as sandboxSkillDir, I as sandboxSkillFile, L as sandboxSkillPathResolution, M as SANDBOX_REPOS_ROOT, N as SANDBOX_SKILLS_ROOT, P as SANDBOX_WORKSPACE_ROOT, _ as workspaceSnapshotNotReadyUserMessage, a as isAbortError, b as buildNonInteractiveShellScript, c as isSandboxCommandStreamInterruptedError, d as isSnapshottingError, f as throwSandboxOperationError, g as isWorkspaceSnapshotNotReadyError, h as getWorkspaceSnapshotNotReadyError, i as ensureDockerDaemon, j as SANDBOX_DATA_ROOT, k as withLock, l as isSandboxMissingError, m as WorkspaceSnapshotNotReadyError, n as hash, o as isAlreadyExistsError, p as wrapSandboxSetupError, r as isStale, s as isSandboxApiTransientError, t as create, u as isSandboxUnavailableError, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand, y as buildCommandScript } from "./profile-CSixooTi.js";
|
|
19
|
+
import { $ as workspaceSnapshotFinishedEvent, B as createEventTask, C as SCHEDULED_TASK_SYSTEM_ACTOR, D as eventTaskMatchesDestination, E as eventTaskListToolResultSchema, F as effectiveTaskOutcomes, Ht as injectContinuationToolName, I as moveTaskOutcomes, L as resolveTaskOutcomes, M as requireEventTaskSlackContext, N as requireSupportedEventTaskTrigger, O as eventTaskSuccess, P as writableEventTask, Q as WORKSPACE_SNAPSHOT_READY_EVENT, R as taskOutcomeInputSchema, T as compactEventTask, Ut as juniorToolOutputSchema, V as deleteEventTask, W as getEventTask, Wt as makeStructuredToolOutput, X as getResourceEventCatalog, Y as saveEventTask, Z as WORKSPACE_SNAPSHOT_FAILED_EVENT, at as pluginSupportsEvent, c as parseSlackThreadId, ct as registeredResourceTypeSchema, et as workspaceSnapshotWatch, f as createScheduledTask, g as listScheduledTasksForTeam, i as readLiveAttachment, it as normalizeEventIdentifier, j as registeredEventTaskTriggerSchema, k as eventTaskToolResultSchema, lt as requireSupportedResourceEventMatch, nt as hasPluginResourceEventCatalogEntries, ot as registeredEventTypeSchema, pt as appendAndEnqueueInboundMessage, q as listEventTasksForTeam, rt as hasResourceEventCatalogEntries, s as storeAttachments, st as registeredResourceEventMatchSchema, t as incrementStat, tt as eventNamespaceSchema, ut as resourceEventGuidance, v as readScheduledTask, y as saveScheduledTask } from "./stats-DKRP4rsY.js";
|
|
20
|
+
import { _ as isTurnInputCommitLostError, c as sanitizeAssistantText, f as CooperativeTurnYieldError, l as NO_REPLY_MARKER, n as canReusePendingAuthLink, o as decideReply, p as TurnInputCommitLostError, s as getAssistantReplyText, t as abandonReplacedPendingAuth, u as isNoReplyMarker } from "./pending-auth-BPUzcs7n.js";
|
|
21
|
+
import { C as toolInvocationDestination, S as surfaceFromRun, _ as uploadFilesToConversation, b as assertRunConsistency, h as postSlackMessage, i as formatProviderLabel, m as getSlackMessagePermalink, o as resolveBaseUrl, p as addReactionToMessage, r as deliverOAuthAuthorization, s as startOAuthFlow, v as RetryableDeliveryError, x as isAgentRunFeatureDisabled, y as actorFromRun } from "./agent-runner-E67lFrDG.js";
|
|
22
|
+
import { r as RESOURCE_EVENT_AUTHOR_ID } from "./prompt-3gqNY1Ka.js";
|
|
23
|
+
import { a as createSandboxSession, c as postinstall, d as getSandboxResources, i as bindSandboxFileSystem, l as setSnapshotSpanAttributes, n as isMissingError, o as stopSession, r as resolve$1, s as dependencies } from "./resolve-Bn5q__9b.js";
|
|
21
24
|
import { t as getVercelConversationWorkQueue } from "./vercel-queue-DIkVcfK4.js";
|
|
22
|
-
import { a as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-
|
|
25
|
+
import { a as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-CyTc24Es.js";
|
|
23
26
|
import { n as privateTraceResultAttributes } from "./private-trace-result-BLvBjy_e.js";
|
|
24
27
|
import { streamSimple } from "@earendil-works/pi-ai/compat";
|
|
25
28
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
@@ -29,7 +32,7 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
29
32
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
30
33
|
import { z } from "zod";
|
|
31
34
|
import { createHash, createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
32
|
-
import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
|
|
35
|
+
import { and, desc, eq, gt, gte, inArray, isNull, lt, ne, notExists, or, sql } from "drizzle-orm";
|
|
33
36
|
import { EgressAuthRequired, EgressPolicyDenied, PluginToolInputError, actorSchema, destinationSchema, missingToolAnnotationKeys, pluginAuthorizationSchema, pluginCredentialHeaderTransformSchema, pluginCredentialResultSchema, pluginGrantSchema, pluginProviderAccountSchema, pluginStoredTokensSchema, resourceEventSchema, resourceEventSubscriptionResultSchema, sourceSchema, stableResourceEventMatchKey, taskOutcomeSchema } from "@sentry/junior-plugin-api";
|
|
34
37
|
import { alias } from "drizzle-orm/pg-core";
|
|
35
38
|
import { Agent, estimateContextTokens } from "@earendil-works/pi-agent-core";
|
|
@@ -694,13 +697,25 @@ function applyProfileReasoningOverride(route, profiles) {
|
|
|
694
697
|
reason: `profile_reasoning_override:${route.profile}:${route.reason}`
|
|
695
698
|
};
|
|
696
699
|
}
|
|
700
|
+
/**
|
|
701
|
+
* The fast classifier model occasionally returns a malformed object
|
|
702
|
+
* (`ProviderError` kind `invalid_response`, e.g. the AI SDK's
|
|
703
|
+
* `NoObjectGeneratedError`) even though a retry usually succeeds. Give it
|
|
704
|
+
* one retry before falling back to `defaultProfile`; any other error kind
|
|
705
|
+
* still falls back immediately.
|
|
706
|
+
*/
|
|
707
|
+
const CLASSIFIER_MAX_ATTEMPTS = 2;
|
|
708
|
+
function isRetryableClassifierError(error) {
|
|
709
|
+
return error instanceof ProviderError && error.kind === "invalid_response";
|
|
710
|
+
}
|
|
697
711
|
async function classifyTurn(args) {
|
|
698
|
-
|
|
712
|
+
let lastError;
|
|
713
|
+
for (let attempt = 1; attempt <= CLASSIFIER_MAX_ATTEMPTS; attempt++) try {
|
|
699
714
|
const schema = createTurnRouteSchema(args.profiles);
|
|
700
715
|
const result = await args.completeObject({
|
|
701
716
|
modelId: args.fastModelId,
|
|
702
717
|
schema,
|
|
703
|
-
maxTokens:
|
|
718
|
+
maxTokens: 5e3,
|
|
704
719
|
metadata: args.metadata,
|
|
705
720
|
prompt: args.prompt,
|
|
706
721
|
thinkingLevel: "low",
|
|
@@ -727,14 +742,17 @@ async function classifyTurn(args) {
|
|
|
727
742
|
source: "router"
|
|
728
743
|
};
|
|
729
744
|
} catch (error) {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
reasoningLevel: CLASSIFIER_FALLBACK_REASONING_LEVEL,
|
|
734
|
-
reason: "classifier_error_default",
|
|
735
|
-
source: "router"
|
|
736
|
-
};
|
|
745
|
+
lastError = error;
|
|
746
|
+
if (attempt < CLASSIFIER_MAX_ATTEMPTS && isRetryableClassifierError(error)) continue;
|
|
747
|
+
break;
|
|
737
748
|
}
|
|
749
|
+
logWarn("turn.router.classifier.failed", { "exception.message": lastError instanceof Error ? lastError.message : String(lastError) });
|
|
750
|
+
return {
|
|
751
|
+
profile: args.defaultProfile,
|
|
752
|
+
reasoningLevel: CLASSIFIER_FALLBACK_REASONING_LEVEL,
|
|
753
|
+
reason: "classifier_error_default",
|
|
754
|
+
source: "router"
|
|
755
|
+
};
|
|
738
756
|
}
|
|
739
757
|
/** Convert a routing bucket into the Pi Agent reasoning setting for a main turn. */
|
|
740
758
|
function toPiReasoningLevel(level) {
|
|
@@ -1213,7 +1231,7 @@ function buildOutputSection(platform) {
|
|
|
1213
1231
|
`<output format="slack-markdown">`,
|
|
1214
1232
|
"- Default to the shortest complete reply—usually 1–5 sentences and under 800 characters. Include only the outcome, decisive evidence, and any blocker or required next action. If useful detail would exceed that, put it in a Slack canvas and reply with the link. An explicit user request for detail overrides this target.",
|
|
1215
1233
|
"- Start with the answer or result, not internal process narration.",
|
|
1216
|
-
"- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No hash-prefixed headings and no tables.
|
|
1234
|
+
"- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No hash-prefixed headings and no tables.",
|
|
1217
1235
|
"- End every turn with a final user-facing markdown response unless the Slack action rules allow a no-reply completion.",
|
|
1218
1236
|
"</output>"
|
|
1219
1237
|
].join("\n");
|
|
@@ -2770,12 +2788,8 @@ async function maybePostAutomatedTurnLimitNotice(args) {
|
|
|
2770
2788
|
//#region src/chat/task-input.ts
|
|
2771
2789
|
/** Shared closing lines for the stored outcomes. */
|
|
2772
2790
|
function replyContractLines(outcomes) {
|
|
2773
|
-
if (outcomes?.length === 0) return ["
|
|
2774
|
-
return [
|
|
2775
|
-
"When you reply, follow any reply format in the instructions.",
|
|
2776
|
-
`If no visible reply is needed, your final assistant message must be exactly ${NO_REPLY_MARKER} and nothing else.`,
|
|
2777
|
-
"Otherwise briefly summarize what you acted on and what you did or need next."
|
|
2778
|
-
];
|
|
2791
|
+
if (outcomes?.length === 0) return ["Do the work without writing a status message.", "No successful output will be delivered."];
|
|
2792
|
+
return ["When you reply, follow any reply format in the instructions.", "Briefly report what you did or what is needed next."];
|
|
2779
2793
|
}
|
|
2780
2794
|
function oneLine(value) {
|
|
2781
2795
|
return value.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -2812,39 +2826,6 @@ function renderTaskInput(args) {
|
|
|
2812
2826
|
return lines.join("\n");
|
|
2813
2827
|
}
|
|
2814
2828
|
//#endregion
|
|
2815
|
-
//#region src/chat/resource-events/actor.ts
|
|
2816
|
-
/**
|
|
2817
|
-
* System author ID stamped on resource-event mailbox messages.
|
|
2818
|
-
*
|
|
2819
|
-
* Keep this stable so conversation history can recognize the same system input
|
|
2820
|
-
* for resource-event Turns.
|
|
2821
|
-
*
|
|
2822
|
-
* TODO(dcramer): Delete this ID after resumes read resource-event Source.kind
|
|
2823
|
-
* from the Turn checkpoint instead of Message author data.
|
|
2824
|
-
*/
|
|
2825
|
-
const RESOURCE_EVENT_AUTHOR_ID = "UJRNEVENT";
|
|
2826
|
-
/** System Message author for resource-event input. */
|
|
2827
|
-
const RESOURCE_EVENT_MESSAGE_AUTHOR = {
|
|
2828
|
-
fullName: "Junior event",
|
|
2829
|
-
isBot: true,
|
|
2830
|
-
userId: RESOURCE_EVENT_AUTHOR_ID,
|
|
2831
|
-
userName: "junior-event"
|
|
2832
|
-
};
|
|
2833
|
-
/** System execution actor for every resource-event turn. */
|
|
2834
|
-
const RESOURCE_EVENT_SYSTEM_ACTOR = {
|
|
2835
|
-
platform: "system",
|
|
2836
|
-
name: "resource-event"
|
|
2837
|
-
};
|
|
2838
|
-
/**
|
|
2839
|
-
* Whether a saved Message started a resource-event Turn.
|
|
2840
|
-
*
|
|
2841
|
-
* TODO(dcramer): Delete this marker check after deployed Turn cursors all store
|
|
2842
|
-
* Source and Actor. `eventType` only supports saved synthetic Slack input.
|
|
2843
|
-
*/
|
|
2844
|
-
function isResourceEventConversationMessage(message) {
|
|
2845
|
-
return Boolean(message.meta?.eventType) || message.author?.userId === "UJRNEVENT";
|
|
2846
|
-
}
|
|
2847
|
-
//#endregion
|
|
2848
2829
|
//#region src/chat/resource-events/notification.ts
|
|
2849
2830
|
/**
|
|
2850
2831
|
* Render the runtime-owned conversation message for a subscribed event.
|
|
@@ -8251,7 +8232,8 @@ function requireActiveConversation(context) {
|
|
|
8251
8232
|
return {
|
|
8252
8233
|
platform: "slack",
|
|
8253
8234
|
teamId: parsed.data.teamId,
|
|
8254
|
-
channelId: parsed.data.channelId
|
|
8235
|
+
channelId: parsed.data.channelId,
|
|
8236
|
+
threadTs: parsed.data.threadTs ?? parsed.data.messageTs
|
|
8255
8237
|
};
|
|
8256
8238
|
}
|
|
8257
8239
|
/** Require a concrete Slack actor before creating scheduler ownership state. */
|
|
@@ -8682,7 +8664,7 @@ function createSlackScheduleUpdateTaskTool(context) {
|
|
|
8682
8664
|
status: nextStatus,
|
|
8683
8665
|
statusReason: nextStatus === "blocked" ? lookup.statusReason : void 0,
|
|
8684
8666
|
schedule: compiled?.schedule ?? lookup.schedule,
|
|
8685
|
-
outcomes: input.outcomes === void 0 ? lookup.outcomes : await resolveTaskOutcomes(input.outcomes,
|
|
8667
|
+
outcomes: input.outcomes === void 0 ? changingDestination ? moveTaskOutcomes(lookup.outcomes, lookup.destination, nextDestination) : lookup.outcomes : await resolveTaskOutcomes(input.outcomes, nextDestination, lookup.createdBy.slackUserId),
|
|
8686
8668
|
task: { text: nextInstruction }
|
|
8687
8669
|
};
|
|
8688
8670
|
if (instructionChanged) {
|
|
@@ -9135,6 +9117,34 @@ function createSlackChannelListMessagesTool(context) {
|
|
|
9135
9117
|
});
|
|
9136
9118
|
}
|
|
9137
9119
|
//#endregion
|
|
9120
|
+
//#region src/chat/slack/tools/conversation-brief-search.ts
|
|
9121
|
+
/** Create Slack-owned filtering and match details for Brief search. */
|
|
9122
|
+
function createSlackConversationBriefSearchPort(teamId) {
|
|
9123
|
+
return {
|
|
9124
|
+
channelFilterSchema: slackChannelRefParam,
|
|
9125
|
+
async resolveChannel(input) {
|
|
9126
|
+
return (await resolveSlackChannelRef({
|
|
9127
|
+
field: "channel_id",
|
|
9128
|
+
value: input,
|
|
9129
|
+
teamId
|
|
9130
|
+
})).channelId;
|
|
9131
|
+
},
|
|
9132
|
+
async describeMatch(match) {
|
|
9133
|
+
const reference = parseSlackThreadId(match.conversationId);
|
|
9134
|
+
if (!reference || reference.channelId !== match.providerDestinationId) return {};
|
|
9135
|
+
const permalink = await getSlackMessagePermalink({
|
|
9136
|
+
channelId: reference.channelId,
|
|
9137
|
+
messageTs: reference.threadTs
|
|
9138
|
+
});
|
|
9139
|
+
return {
|
|
9140
|
+
channel_id: reference.channelId,
|
|
9141
|
+
...match.channelName ? { channel_name: match.channelName } : void 0,
|
|
9142
|
+
...permalink ? { permalink } : void 0
|
|
9143
|
+
};
|
|
9144
|
+
}
|
|
9145
|
+
};
|
|
9146
|
+
}
|
|
9147
|
+
//#endregion
|
|
9138
9148
|
//#region src/chat/conversations/tool-source.ts
|
|
9139
9149
|
/** Deferred tool catalog source for retained Junior conversations. */
|
|
9140
9150
|
const CONVERSATIONS_TOOL_SOURCE = {
|
|
@@ -9143,8 +9153,8 @@ const CONVERSATIONS_TOOL_SOURCE = {
|
|
|
9143
9153
|
};
|
|
9144
9154
|
//#endregion
|
|
9145
9155
|
//#region src/chat/slack/tools/conversation-message-search.ts
|
|
9146
|
-
const DEFAULT_LIMIT$
|
|
9147
|
-
const MAX_LIMIT$
|
|
9156
|
+
const DEFAULT_LIMIT$3 = 20;
|
|
9157
|
+
const MAX_LIMIT$2 = 50;
|
|
9148
9158
|
const conversationMessageSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
9149
9159
|
after: z.string().datetime().optional(),
|
|
9150
9160
|
annotation: z.string().min(1).optional(),
|
|
@@ -9164,17 +9174,17 @@ const conversationMessageSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
|
9164
9174
|
thread_ts: z.string().min(1)
|
|
9165
9175
|
}).strict())
|
|
9166
9176
|
});
|
|
9167
|
-
function parseTimestamp(field, value) {
|
|
9177
|
+
function parseTimestamp$1(field, value) {
|
|
9168
9178
|
if (value == null || value.trim() === "") return;
|
|
9169
9179
|
const parsed = Date.parse(value);
|
|
9170
9180
|
if (!Number.isFinite(parsed)) throw new ToolInputError(`${field} must be a valid ISO-8601 timestamp`);
|
|
9171
9181
|
return parsed;
|
|
9172
9182
|
}
|
|
9173
|
-
async function resolveSearchFilters(input) {
|
|
9183
|
+
async function resolveSearchFilters$1(input) {
|
|
9174
9184
|
const query = input.query?.trim() || void 0;
|
|
9175
9185
|
const annotation = input.annotation?.trim() || void 0;
|
|
9176
|
-
const afterMs = parseTimestamp("after", input.after);
|
|
9177
|
-
const beforeMs = parseTimestamp("before", input.before);
|
|
9186
|
+
const afterMs = parseTimestamp$1("after", input.after);
|
|
9187
|
+
const beforeMs = parseTimestamp$1("before", input.before);
|
|
9178
9188
|
let channelId;
|
|
9179
9189
|
if (input.channel_id != null && input.channel_id.trim() !== "") channelId = (await resolveSlackChannelRef({
|
|
9180
9190
|
field: "channel_id",
|
|
@@ -9209,20 +9219,20 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
|
|
|
9209
9219
|
before: z.string().datetime().nullable().describe("Include conversations active before this timestamp.").optional(),
|
|
9210
9220
|
channel_id: slackChannelRefParam.nullable().optional(),
|
|
9211
9221
|
query: z.string().trim().min(1).max(200).nullable().describe("Words or phrase to match in message text.").optional(),
|
|
9212
|
-
limit: z.number().int().min(1).max(MAX_LIMIT$
|
|
9222
|
+
limit: z.number().int().min(1).max(MAX_LIMIT$2).describe(`Maximum conversations. Default ${DEFAULT_LIMIT$3}; max ${MAX_LIMIT$2}.`).nullable().optional()
|
|
9213
9223
|
}).strict(),
|
|
9214
9224
|
outputSchema: conversationMessageSearchOutputSchema,
|
|
9215
9225
|
execute: async (input) => {
|
|
9216
9226
|
const teamId = parseSlackTeamId(scope.providerTenantId);
|
|
9217
9227
|
if (!teamId) throw new ToolInputError("Cannot search retained messages without a valid Slack workspace id.");
|
|
9218
|
-
const filters = await resolveSearchFilters({
|
|
9228
|
+
const filters = await resolveSearchFilters$1({
|
|
9219
9229
|
...input,
|
|
9220
9230
|
teamId
|
|
9221
9231
|
});
|
|
9222
9232
|
const matches = await getConversationMessageSearchStore().search({
|
|
9223
9233
|
currentConversationId,
|
|
9224
9234
|
filters,
|
|
9225
|
-
limit: input.limit ?? DEFAULT_LIMIT$
|
|
9235
|
+
limit: input.limit ?? DEFAULT_LIMIT$3,
|
|
9226
9236
|
scope
|
|
9227
9237
|
});
|
|
9228
9238
|
const matchesOutput = await Promise.all(matches.map(async (match) => {
|
|
@@ -9258,7 +9268,7 @@ function createSlackConversationMessageSearchTool(scope, currentConversationId)
|
|
|
9258
9268
|
}
|
|
9259
9269
|
//#endregion
|
|
9260
9270
|
//#region src/chat/slack/tools/public-search.ts
|
|
9261
|
-
const DEFAULT_LIMIT$
|
|
9271
|
+
const DEFAULT_LIMIT$2 = 10;
|
|
9262
9272
|
const DEFAULT_CONTENT_TYPES = ["messages"];
|
|
9263
9273
|
const CONTENT_TYPES = [
|
|
9264
9274
|
"messages",
|
|
@@ -9521,7 +9531,7 @@ function createSlackPublicSearchTool(actionToken) {
|
|
|
9521
9531
|
channel_types: ["public_channel"],
|
|
9522
9532
|
content_types: normalizedContentTypes,
|
|
9523
9533
|
include_bots: true,
|
|
9524
|
-
limit: limit ?? DEFAULT_LIMIT$
|
|
9534
|
+
limit: limit ?? DEFAULT_LIMIT$2,
|
|
9525
9535
|
...normalizedAfter !== void 0 ? { after: normalizedAfter } : void 0,
|
|
9526
9536
|
...normalizedBefore !== void 0 ? { before: normalizedBefore } : void 0,
|
|
9527
9537
|
...cursor ? { cursor } : void 0,
|
|
@@ -11697,8 +11707,8 @@ function createLoadAttachmentTool(args) {
|
|
|
11697
11707
|
}
|
|
11698
11708
|
//#endregion
|
|
11699
11709
|
//#region src/chat/tools/search-conversation-events.ts
|
|
11700
|
-
const DEFAULT_LIMIT = 25;
|
|
11701
|
-
const MAX_LIMIT = 100;
|
|
11710
|
+
const DEFAULT_LIMIT$1 = 25;
|
|
11711
|
+
const MAX_LIMIT$1 = 100;
|
|
11702
11712
|
const MAX_EVENT_DATA_BYTES = 4e3;
|
|
11703
11713
|
const MAX_EVENTS_JSON_BYTES = 2e4;
|
|
11704
11714
|
const MAX_IDENTITY_CHARS = 256;
|
|
@@ -11734,7 +11744,7 @@ function createSearchConversationEventsTool(context) {
|
|
|
11734
11744
|
conversation_id: z.string().trim().min(1).nullable().describe("Conversation ID to search. Omit or null for the current conversation.").optional(),
|
|
11735
11745
|
after_seq: z.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
|
|
11736
11746
|
before_seq: z.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
|
|
11737
|
-
limit: z.number().int().min(1).max(MAX_LIMIT).nullable().describe(`Maximum events. Default ${DEFAULT_LIMIT}; max ${MAX_LIMIT}.`).optional(),
|
|
11747
|
+
limit: z.number().int().min(1).max(MAX_LIMIT$1).nullable().describe(`Maximum events. Default ${DEFAULT_LIMIT$1}; max ${MAX_LIMIT$1}.`).optional(),
|
|
11738
11748
|
types: z.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
|
|
11739
11749
|
}).strict(),
|
|
11740
11750
|
outputSchema: searchConversationEventsOutputSchema,
|
|
@@ -11743,7 +11753,7 @@ function createSearchConversationEventsTool(context) {
|
|
|
11743
11753
|
const conversationId = input.conversation_id?.trim() || currentConversationId;
|
|
11744
11754
|
const afterSeq = input.after_seq ?? void 0;
|
|
11745
11755
|
const beforeSeq = input.before_seq ?? void 0;
|
|
11746
|
-
const limit = input.limit ?? DEFAULT_LIMIT;
|
|
11756
|
+
const limit = input.limit ?? DEFAULT_LIMIT$1;
|
|
11747
11757
|
const types = input.types ?? void 0;
|
|
11748
11758
|
if (afterSeq !== void 0 && beforeSeq !== void 0 && afterSeq >= beforeSeq) throw new ToolInputError("after_seq must be less than before_seq when both are provided");
|
|
11749
11759
|
const conversationStore = getConversationStore();
|
|
@@ -11907,6 +11917,183 @@ function stripReplacementHistoryField(value) {
|
|
|
11907
11917
|
};
|
|
11908
11918
|
}
|
|
11909
11919
|
//#endregion
|
|
11920
|
+
//#region src/chat/briefs/search.ts
|
|
11921
|
+
/** Search the latest Brief of each public root Conversation in one scope. */
|
|
11922
|
+
async function searchConversationBriefs(db, args) {
|
|
11923
|
+
const query = args.filters.query?.trim() || void 0;
|
|
11924
|
+
const tsquery = query ? sql`websearch_to_tsquery('english', ${query})` : void 0;
|
|
11925
|
+
const briefs = juniorConversationBriefs;
|
|
11926
|
+
const newer = alias(juniorConversationBriefs, "newer_briefs");
|
|
11927
|
+
const searchVector = sql`to_tsvector('english', ${briefs.searchText})`;
|
|
11928
|
+
const rank = tsquery ? sql`ts_rank_cd(${searchVector}, ${tsquery})` : sql`1`;
|
|
11929
|
+
const excerpt = tsquery ? sql`ts_headline('english', ${briefs.searchText}, ${tsquery}, 'MaxFragments=2, MinWords=8, MaxWords=40, FragmentDelimiter=" … ", StartSel=**, StopSel=**')` : sql`${briefs.content}->>'summary'`;
|
|
11930
|
+
const outcomeStatus = sql`${briefs.content}->'outcome'->>'status'`;
|
|
11931
|
+
const conditions = [
|
|
11932
|
+
notExists(db.select({ one: sql`1` }).from(newer).where(and(eq(newer.conversationId, briefs.conversationId), gt(newer.version, briefs.version)))),
|
|
11933
|
+
isNull(juniorConversations.parentConversationId),
|
|
11934
|
+
ne(juniorConversations.conversationId, args.currentConversationId),
|
|
11935
|
+
eq(juniorDestinations.visibility, "public")
|
|
11936
|
+
];
|
|
11937
|
+
if (args.scope.kind === "public_provider_tenant") conditions.push(eq(juniorConversations.source, args.scope.provider), eq(juniorDestinations.provider, args.scope.provider), eq(juniorDestinations.providerTenantId, args.scope.providerTenantId));
|
|
11938
|
+
if (tsquery) conditions.push(sql`${searchVector} @@ ${tsquery}`);
|
|
11939
|
+
if (args.filters.channelId) conditions.push(eq(juniorDestinations.providerDestinationId, args.filters.channelId));
|
|
11940
|
+
if (args.filters.status) conditions.push(sql`${outcomeStatus} = ${args.filters.status}`);
|
|
11941
|
+
if (args.filters.afterMs !== void 0) conditions.push(gte(briefs.createdAt, new Date(args.filters.afterMs)));
|
|
11942
|
+
if (args.filters.beforeMs !== void 0) conditions.push(lt(briefs.createdAt, new Date(args.filters.beforeMs)));
|
|
11943
|
+
if (args.filters.annotation) {
|
|
11944
|
+
const annotation = args.filters.annotation.toLowerCase();
|
|
11945
|
+
const nestedAnnotationPrefix = `${annotation}#`;
|
|
11946
|
+
conditions.push(sql`exists (
|
|
11947
|
+
select 1
|
|
11948
|
+
from ${juniorConversationAnnotations}
|
|
11949
|
+
where ${and(eq(juniorConversationAnnotations.conversationId, juniorConversations.conversationId), sql`(
|
|
11950
|
+
lower(${juniorConversationAnnotations.key}) = ${annotation}
|
|
11951
|
+
or starts_with(
|
|
11952
|
+
lower(${juniorConversationAnnotations.key}),
|
|
11953
|
+
${nestedAnnotationPrefix}
|
|
11954
|
+
)
|
|
11955
|
+
)`)}
|
|
11956
|
+
)`);
|
|
11957
|
+
}
|
|
11958
|
+
return (await db.select({
|
|
11959
|
+
channelName: juniorDestinations.displayName,
|
|
11960
|
+
content: briefs.content,
|
|
11961
|
+
conversationId: juniorConversations.conversationId,
|
|
11962
|
+
excerpt: excerpt.as("excerpt"),
|
|
11963
|
+
providerDestinationId: juniorDestinations.providerDestinationId,
|
|
11964
|
+
rank: rank.as("rank"),
|
|
11965
|
+
title: juniorConversations.title,
|
|
11966
|
+
updatedAt: briefs.createdAt,
|
|
11967
|
+
version: briefs.version
|
|
11968
|
+
}).from(briefs).innerJoin(juniorConversations, eq(juniorConversations.conversationId, briefs.conversationId)).innerJoin(juniorDestinations, eq(juniorDestinations.id, juniorConversations.destinationId)).where(and(...conditions)).orderBy(desc(rank), desc(briefs.createdAt)).limit(args.limit)).map((row) => {
|
|
11969
|
+
const content = conversationBriefSchema.parse(row.content);
|
|
11970
|
+
return {
|
|
11971
|
+
conversationId: row.conversationId,
|
|
11972
|
+
excerpt: row.excerpt,
|
|
11973
|
+
links: content.links.slice(0, 5),
|
|
11974
|
+
outcomeStatus: content.outcome.status,
|
|
11975
|
+
providerDestinationId: row.providerDestinationId,
|
|
11976
|
+
summary: content.summary,
|
|
11977
|
+
updatedAtMs: row.updatedAt.getTime(),
|
|
11978
|
+
version: row.version,
|
|
11979
|
+
...row.channelName ? { channelName: row.channelName } : void 0,
|
|
11980
|
+
...row.title ? { title: row.title } : void 0
|
|
11981
|
+
};
|
|
11982
|
+
});
|
|
11983
|
+
}
|
|
11984
|
+
//#endregion
|
|
11985
|
+
//#region src/chat/tools/search-conversation-briefs.ts
|
|
11986
|
+
const DEFAULT_LIMIT = 10;
|
|
11987
|
+
const MAX_LIMIT = 25;
|
|
11988
|
+
const conversationBriefSearchOutputSchema = juniorToolOutputSchema.extend({
|
|
11989
|
+
after: z.string().datetime().optional(),
|
|
11990
|
+
annotation: z.string().min(1).optional(),
|
|
11991
|
+
before: z.string().datetime().optional(),
|
|
11992
|
+
channel_id: z.string().min(1).optional(),
|
|
11993
|
+
count: z.number().int().nonnegative(),
|
|
11994
|
+
matches: z.array(z.object({
|
|
11995
|
+
channel_id: z.string().min(1).optional(),
|
|
11996
|
+
channel_name: z.string().min(1).optional(),
|
|
11997
|
+
conversation_id: z.string().min(1),
|
|
11998
|
+
dashboard_url: z.string().url().optional(),
|
|
11999
|
+
excerpt: z.string(),
|
|
12000
|
+
links: z.array(briefLinkSchema).max(5),
|
|
12001
|
+
permalink: z.string().url().optional(),
|
|
12002
|
+
status: briefOutcomeStatusSchema,
|
|
12003
|
+
summary: z.string().min(1),
|
|
12004
|
+
title: z.string().min(1).optional(),
|
|
12005
|
+
updated_at: z.string().datetime(),
|
|
12006
|
+
version: z.number().int().positive()
|
|
12007
|
+
}).strict()),
|
|
12008
|
+
query: z.string().optional(),
|
|
12009
|
+
status: briefOutcomeStatusSchema.optional()
|
|
12010
|
+
});
|
|
12011
|
+
function parseTimestamp(field, value) {
|
|
12012
|
+
if (value == null || value.trim() === "") return void 0;
|
|
12013
|
+
const parsed = Date.parse(value);
|
|
12014
|
+
if (!Number.isFinite(parsed)) throw new ToolInputError(`${field} must be a valid ISO-8601 timestamp`);
|
|
12015
|
+
return parsed;
|
|
12016
|
+
}
|
|
12017
|
+
async function resolveSearchFilters(input, provider) {
|
|
12018
|
+
const query = input.query?.trim() || void 0;
|
|
12019
|
+
const annotation = input.annotation?.trim() || void 0;
|
|
12020
|
+
const afterMs = parseTimestamp("after", input.after);
|
|
12021
|
+
const beforeMs = parseTimestamp("before", input.before);
|
|
12022
|
+
let channelId;
|
|
12023
|
+
if (typeof input.channel_id === "string" && input.channel_id.trim() !== "") {
|
|
12024
|
+
if (!provider) throw new ToolInputError("channel_id is not available in this conversation.");
|
|
12025
|
+
channelId = await provider.resolveChannel(input.channel_id);
|
|
12026
|
+
}
|
|
12027
|
+
if (afterMs !== void 0 && beforeMs !== void 0 && afterMs >= beforeMs) throw new ToolInputError("`after` must be earlier than `before`");
|
|
12028
|
+
return {
|
|
12029
|
+
...afterMs !== void 0 ? { afterMs } : void 0,
|
|
12030
|
+
...annotation ? { annotation } : void 0,
|
|
12031
|
+
...beforeMs !== void 0 ? { beforeMs } : void 0,
|
|
12032
|
+
...channelId ? { channelId } : void 0,
|
|
12033
|
+
...query ? { query } : void 0,
|
|
12034
|
+
...input.status ? { status: input.status } : void 0
|
|
12035
|
+
};
|
|
12036
|
+
}
|
|
12037
|
+
/** Create a deferred tool that searches the latest public Conversation Briefs. */
|
|
12038
|
+
function createSearchConversationBriefsTool(scope, currentConversationId, provider) {
|
|
12039
|
+
return zodTool({
|
|
12040
|
+
description: "Search Briefs from past public conversations. Briefs preserve intent, outcomes, decisions, facts, and links after transcripts expire. Use this before searchConversationMessages for questions such as what was decided or which pull request handled the work.",
|
|
12041
|
+
exposure: "deferred",
|
|
12042
|
+
source: CONVERSATIONS_TOOL_SOURCE,
|
|
12043
|
+
annotations: {
|
|
12044
|
+
destructiveHint: false,
|
|
12045
|
+
idempotentHint: true,
|
|
12046
|
+
openWorldHint: false,
|
|
12047
|
+
readOnlyHint: true
|
|
12048
|
+
},
|
|
12049
|
+
inputSchema: z.object({
|
|
12050
|
+
after: z.string().datetime().nullable().describe("Include Briefs updated at or after this timestamp.").optional(),
|
|
12051
|
+
annotation: z.string().trim().min(1).max(256).nullable().describe("Linked resource key. Matches that key, or nested children that continue with #.").optional(),
|
|
12052
|
+
before: z.string().datetime().nullable().describe("Include Briefs updated before this timestamp.").optional(),
|
|
12053
|
+
...provider ? { channel_id: provider.channelFilterSchema.nullable().optional() } : void 0,
|
|
12054
|
+
limit: z.number().int().min(1).max(MAX_LIMIT).nullable().describe(`Maximum conversations. Default ${DEFAULT_LIMIT}; max ${MAX_LIMIT}.`).optional(),
|
|
12055
|
+
query: z.string().trim().min(1).max(200).nullable().describe("Words or phrase to match in current Briefs.").optional(),
|
|
12056
|
+
status: briefOutcomeStatusSchema.nullable().describe("Current Brief outcome status.").optional()
|
|
12057
|
+
}).strict(),
|
|
12058
|
+
outputSchema: conversationBriefSearchOutputSchema,
|
|
12059
|
+
execute: async (input) => {
|
|
12060
|
+
const filters = await resolveSearchFilters(input, provider);
|
|
12061
|
+
const matches = await searchConversationBriefs(getDb(), {
|
|
12062
|
+
currentConversationId,
|
|
12063
|
+
filters,
|
|
12064
|
+
limit: input.limit ?? DEFAULT_LIMIT,
|
|
12065
|
+
scope
|
|
12066
|
+
});
|
|
12067
|
+
const outputMatches = await Promise.all(matches.map(async (match) => {
|
|
12068
|
+
const providerFields = provider ? await provider.describeMatch(match) : void 0;
|
|
12069
|
+
const dashboardUrl = getDashboardConversationLink(match.conversationId);
|
|
12070
|
+
return {
|
|
12071
|
+
conversation_id: match.conversationId,
|
|
12072
|
+
status: match.outcomeStatus,
|
|
12073
|
+
updated_at: new Date(match.updatedAtMs).toISOString(),
|
|
12074
|
+
version: match.version,
|
|
12075
|
+
summary: match.summary,
|
|
12076
|
+
excerpt: match.excerpt,
|
|
12077
|
+
links: match.links,
|
|
12078
|
+
...match.title ? { title: match.title } : void 0,
|
|
12079
|
+
...dashboardUrl ? { dashboard_url: dashboardUrl } : void 0,
|
|
12080
|
+
...providerFields
|
|
12081
|
+
};
|
|
12082
|
+
}));
|
|
12083
|
+
return {
|
|
12084
|
+
...filters.afterMs !== void 0 ? { after: new Date(filters.afterMs).toISOString() } : void 0,
|
|
12085
|
+
...filters.annotation ? { annotation: filters.annotation } : void 0,
|
|
12086
|
+
...filters.beforeMs !== void 0 ? { before: new Date(filters.beforeMs).toISOString() } : void 0,
|
|
12087
|
+
...filters.channelId ? { channel_id: filters.channelId } : void 0,
|
|
12088
|
+
...filters.query ? { query: filters.query } : void 0,
|
|
12089
|
+
...filters.status ? { status: filters.status } : void 0,
|
|
12090
|
+
count: outputMatches.length,
|
|
12091
|
+
matches: outputMatches
|
|
12092
|
+
};
|
|
12093
|
+
}
|
|
12094
|
+
});
|
|
12095
|
+
}
|
|
12096
|
+
//#endregion
|
|
11910
12097
|
//#region src/chat/tools/handoff/tool.ts
|
|
11911
12098
|
const HANDOFF_TOOL_NAME = "handoff";
|
|
11912
12099
|
function formatHandoffProfiles(handoff) {
|
|
@@ -12875,6 +13062,11 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
|
|
|
12875
13062
|
...createWorkspaceTools(context)
|
|
12876
13063
|
};
|
|
12877
13064
|
tools.searchConversationEvents = createSearchConversationEventsTool(context);
|
|
13065
|
+
if (context.conversationPrivacy === "public") tools.searchConversationBriefs = createSearchConversationBriefsTool(slackContext ? {
|
|
13066
|
+
kind: "public_provider_tenant",
|
|
13067
|
+
provider: "slack",
|
|
13068
|
+
providerTenantId: slackContext.teamId
|
|
13069
|
+
} : { kind: "public" }, context.conversationId, slackContext ? createSlackConversationBriefSearchPort(slackContext.teamId) : void 0);
|
|
12878
13070
|
if (context.supportsImageInput) tools.viewImage = createViewImageTool(context.workspace, context.supportsImageInput, hooks.toolOverrides?.viewImage);
|
|
12879
13071
|
if (hooks.writeGeneratedArtifacts) tools.imageGenerate = createImageGenerateTool({ writeGeneratedArtifacts: hooks.writeGeneratedArtifacts }, {
|
|
12880
13072
|
modelId: botConfig.imageGenerationModelId,
|
|
@@ -17506,4 +17698,4 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
|
|
|
17506
17698
|
}
|
|
17507
17699
|
}
|
|
17508
17700
|
//#endregion
|
|
17509
|
-
export {
|
|
17701
|
+
export { shouldEmitDevAgentTrace as $, createAgentInvocationSchema as A, resolveSandboxEgressProviderForHost as B, renderBlockText as C, getNextRunAtMs as D, scheduledTaskRunAttributes as E, ingestResourceEvent as F, consumeSandboxEgressAuthRequiredSignal as G, shouldPropagateSandboxEgressTrace as H, isResourceEventMailboxMetadata as I, sandboxEgressSignalsResponseSchema as J, consumeSandboxEgressPermissionDeniedSignal as K, renderTaskInput as L, AgentInvocationLimitError as M, getMcpProviderErrorAttributes as N, agentBindingSchema as O, processWorkspaceSnapshotJob as P, AuthorizationFlowDisabledError as Q, maybePostAutomatedTurnLimitNotice as R, renderAttachmentText as S, logScheduledTaskRunSkipped as T, SANDBOX_EGRESS_PROXY_PATH as U, normalizeSandboxEgressTracePropagationDomains as V, clearSandboxEgressSignals as W, buildSteeringPiMessage as X, createUserTokenStore as Y, isVisionImageMediaType as Z, readPublicArtifact as _, deleteMcpAuthSession as a, readAttachmentVisionSummary as b, deleteMcpStoredOAuthCredentials as c, putMcpStoredOAuthCredentials as d, getConfigDefaults as et, PluginCredentialFailureError as f, publicArtifactHeaders as g, resolvePluginOAuthAccount as h, finalizeMcpAuthorization as i, AgentInvocationBusyError as j, agentInvocationSchema as k, getMcpAuthSession as l, latestReportedProgress as m, createContextCompactor as n, deleteMcpAuthSessionsForUserProvider as o, authorizationId as p, parseSandboxEgressCredentialToken as q, executeCredentialedEgressRequest as r, deleteMcpServerSessionId as s, executeAgentRun as t, setConfigDefaults as tt, getMcpStoredOAuthCredentials as u, unpublishedArtifactHeaders as v, listThreadReplies as w, recordSlackAttachment as x, lookupSlackUserProfile as y, recordFinishedTurnForAutomatedLimit as z };
|