@sentry/junior 0.263.0 → 0.265.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/README.md +1 -1
- package/dist/{adapter-BIacI0Bt.js → adapter-cUkPH3Om.js} +1 -1
- package/dist/{admin-C7vUk7s9.js → admin-Cf0rDmWV.js} +1 -1
- package/dist/{agent-runner-BUBas7Yy.js → agent-runner-C6MwHJEs.js} +296 -238
- package/dist/api/schema.d.ts +213 -16
- package/dist/api/schema.js +3 -3
- package/dist/api.js +107 -40
- package/dist/{app-Bo0kB987.d.ts → app-Csbi9dW7.d.ts} +4 -3
- package/dist/app.d.ts +1 -1
- package/dist/app.js +101 -393
- package/dist/{assistant-reply-BFmjgJjD.js → assistant-reply-UPA8vKlC.js} +1 -1
- package/dist/{automation-CWX0qL8U.js → automation-2RbKzpMT.js} +30 -9
- package/dist/{briefs-h55v5lX9.js → briefs-DRjx8kQ9.js} +3 -3
- package/dist/{catalog-runtime-Suf-aLlh.js → catalog-runtime-D3qbJlYz.js} +1 -1
- package/dist/cli/chat.js +15 -15
- package/dist/cli/check.js +3 -3
- package/dist/cli/init.js +4 -18
- package/dist/cli/main.js +4 -4
- package/dist/cli/plugins.js +4 -4
- package/dist/cli/snapshot-create.js +4 -4
- package/dist/cli/upgrade.js +3 -3
- package/dist/{client-DZBCBj1M.js → client-DX34VNtH.js} +3 -8
- package/dist/{config-Dnv8KmNs.js → config-BayQ9hHH.js} +100 -3
- package/dist/{connections-Br0_xv27.js → connections-mpN5Lsnj.js} +11 -10
- package/dist/{conversation-privacy-FY8yc2q3.js → conversation-privacy-frjQCJa9.js} +1 -1
- package/dist/{credential-sync-BvkiyWF5.js → credential-sync-CZmyDNdR.js} +20 -20
- package/dist/{agent-hooks-CqnZfuCt.js → credentialed-C6pKlB1p.js} +3197 -66
- package/dist/{executor-J9k2sp9m.js → executor-CAr7xQr2.js} +10 -300
- package/dist/{images-DV2FlEGL.js → images-B2yA3HWE.js} +2 -2
- package/dist/instrumentation.js +41 -25
- package/dist/{job-queue-B4yTgklN.js → job-queue-Cjo6Yg_b.js} +53 -14
- package/dist/{logging-Dk_FpF36.js → logging-D2QBriUo.js} +19 -32
- package/dist/{message-BzseAFH1.js → message-C9ymnpBS.js} +4 -4
- package/dist/nitro.d.ts +17 -2
- package/dist/nitro.js +26 -27
- package/dist/{oauth-callback-server-bTspTMCC.js → oauth-callback-server-BtMf3TPZ.js} +2 -2
- package/dist/{prompt-CxatQVaj.js → prompt-CvaDdSX3.js} +1 -1
- package/dist/{registry-BFzQFV_y.js → registry-COTeZ2cV.js} +1 -1
- package/dist/{resolve-CnRHib0U.js → resolve-g9PKz9pH.js} +7 -106
- package/dist/{result-DczfmNBa.js → result-COnC42GR.js} +8 -8
- package/dist/{runner-CJd9Wec-.js → runner-BnTNS7x_.js} +10 -10
- package/dist/{sandbox-egress-signals-DUmVkOx4.js → sandbox-egress-signals-C_IIdLFk.js} +1 -1
- package/dist/{schema-QidbykYl.js → schema-D5Amlzkp.js} +44 -3
- package/dist/{sentry-BBUlHih9.js → sentry-MDkYAVPV.js} +3 -6
- package/dist/{service-account-BI2kQDrb.js → service-account-CwvToidT.js} +3 -3
- package/dist/{service-account-x2QZXm4X.js → service-account-YdYftwV2.js} +5 -5
- package/dist/{session-stop-CtyJsnEj.js → session-stop-CpCUy1ZJ.js} +121 -81
- package/dist/{skills-Dbzx9-rS.js → skills-Bb2KaJ3m.js} +2 -2
- package/dist/{spawn-D8WU99UV.js → spawn-mbTcrLb3.js} +2 -2
- package/dist/{store-TKg1HVKx.js → store-CqRnaZSq.js} +3 -3
- package/dist/{store-UlOrW6JC.js → store-DdT74Lvq.js} +18 -9
- package/dist/{task-queue-BRB49H-J.js → task-queue-8XjDIORF.js} +14 -19
- package/dist/{task-runner-C575f2Dd.js → task-runner-6mLmG6g_.js} +46 -28
- package/dist/{tasks-LOItiYgL.js → tasks-DGbrur6x.js} +14 -2075
- package/dist/{thread-state-IDHdZA7R.js → thread-state-D45lz-oC.js} +5 -5
- package/dist/{turn-failure-response-h_LSXJ-M.js → turn-failure-response-CaEPLSBn.js} +7 -7
- package/dist/{turn-lifecycle-Cvi6Sb8Y.js → turn-lifecycle-C35IyRGp.js} +1 -1
- package/dist/{turn-session-routing-5Nyv4fso.js → turn-session-routing-BKx6rfVd.js} +1 -1
- package/dist/{validation-BeTriWC2.js → validation-C0X3CX51.js} +1 -1
- package/dist/{version-BQX_hLDC.js → version-BPHgJwnm.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/{viewer-DmNRM88V.js → viewer-B2wXNspU.js} +21 -5
- package/dist/{web-input-BHcGXSox.js → web-input-Y6aXvmfa.js} +145 -46
- package/dist/{work-DLJMV02b.js → work-DMbqK0kT.js} +10 -10
- package/dist/{worker-vfG2ESg1.js → worker-B-rDJ3XN.js} +8 -6
- package/package.json +10 -9
- package/dist/profile-Dq5I7TV1.js +0 -582
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
import { $t as isToolResultMessage,
|
|
2
|
-
import { S as resolveGatewayCredential, _ as getProviderErrorAttributes, a as completeText, b as MISSING_GATEWAY_CREDENTIALS_ERROR, c as COMPACTION_SUMMARY_PREFIX, d as renderCurrentInstruction, f as unwrapCurrentInstruction, g as findProviderError, h as createProviderError, i as completeObject, l as hasCompactedConversationContext, m as ProviderError, n as GEN_AI_SERVER_ADDRESS, p as escapeXml, s as resolveGatewayModel, t as GEN_AI_PROVIDER_NAME, u as isCompactionSummaryText, x as getGatewayApiKey, y as isProviderRetryError } from "./client-
|
|
3
|
-
import {
|
|
4
|
-
import { m as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { $t as isToolResultMessage, B as recordAttachmentsDelivered, Cn as getConfigDefaults, Ct as canReusePendingAuthLink, Dt as continuableMessages, G as recordMcpProviderConnected, Gt as getPiMessageRole, Ht as isTurnExecutionLimitExceededError, It as TURN_LIMIT_DISABLED_REASON, J as recordTurnRoute, Jt as hasRuntimeTurnContext, Kt as getTerminalAssistantMessages, L as loadTurnRoute, Lt as TurnBudgetExceededError, M as loadConnectedMcpProviders, N as loadConversationProjection, O as automationRevision, Ot as loadTurnCheckpoint, P as loadLastModelProfile, Qt as isToolResultError, R as openConversationProjection, Rt as TurnSliceLimitExceededError, Sn as piMessageFromHistoryItem, St as abandonReplacedPendingAuth, U as recordAuthorizationRequested, Vt as createTurnLimitGate, W as recordGuardianActionReviewed, Wt as extractAssistantText, Xt as isAssistantMessage, Zt as isContinuablePiBoundary, _n as isExperimentalFeatureEnabled, _t as createPluginAuthOrchestration, a as saveScheduledAutomation, an as SESSION_CONTEXT_SECTION_TAG, bt as AuthorizationFlowDisabledError, d as createEventAutomation, en as normalizeToolNameFromResult, f as deleteEventAutomation, g as listEventAutomationsForTeam, gt as PluginCredentialFailureError, hn as getAgentContextInputLimitTokens, ht as createPluginEgress, i as readScheduledAutomation, in as REQUEST_CONTEXT_SECTION_TAG, kt as saveTurnCheckpoint, m as getEventAutomation, mn as getAgentContextCompactionTriggerTokens, n as listScheduledAutomationsForTeam, nn as stripRuntimeTurnContext, nt as fallbackShortTitle, on as TURN_CONTEXT_TAG, pn as estimateTextTokens, q as recordToolExecutionStarted, qt as getUserMessageInstructionText, rn as trimTrailingAssistantMessages, rt as resolveTaskTitle, t as createScheduledAutomation, tn as retainRuntimeTurnContext, v as saveEventAutomation, vt as authorizationId, xn as historyItemFromPiMessage, xt as AuthorizationPauseError, y as setEventAutomationStatus, yt as AuthPausePersistenceError, z as recordAgentsInstructionsUpdated, zt as TurnToolCallLimitExceededError } from "./tasks-DGbrur6x.js";
|
|
2
|
+
import { S as resolveGatewayCredential, _ as getProviderErrorAttributes, a as completeText, b as MISSING_GATEWAY_CREDENTIALS_ERROR, c as COMPACTION_SUMMARY_PREFIX, d as renderCurrentInstruction, f as unwrapCurrentInstruction, g as findProviderError, h as createProviderError, i as completeObject, l as hasCompactedConversationContext, m as ProviderError, n as GEN_AI_SERVER_ADDRESS, p as escapeXml, s as resolveGatewayModel, t as GEN_AI_PROVIDER_NAME, u as isCompactionSummaryText, x as getGatewayApiKey, y as isProviderRetryError } from "./client-DX34VNtH.js";
|
|
3
|
+
import { n as botConfig, v as normalizeSlackEmojiName } from "./config-BayQ9hHH.js";
|
|
4
|
+
import { R as normalizeIdentityEmail, S as summarizeMessageText, T as withSpan, V as toOptionalString, _ as serializeGenAiAttribute, a as extractGenAiUsageSummary, b as setSpanStatus, c as getLogContextAttributesForSpan, d as logError, f as logException, h as normalizeGenAiFinishReason, i as extractGenAiUsageAttributes, l as getTracePropagationHeaders, m as logWarn, p as logInfo, w as withLogContext, x as setTags, y as setSpanAttributes, z as isRecord$4 } from "./logging-D2QBriUo.js";
|
|
5
|
+
import { g as withActiveSpan, m as startInactiveSpan } from "./sentry-MDkYAVPV.js";
|
|
6
|
+
import { a as toCanonicalInputMessage, c as toGenAiPayloadMetadata, i as runWithConversationPrivacy, l as toGenAiPayloadTraceAttributes, o as toCanonicalOutputMessage, r as resolveConversationPrivacy, s as toGenAiMessagesTraceAttributes, t as canExposeConversationPayload } from "./conversation-privacy-frjQCJa9.js";
|
|
7
7
|
import { a as formatModelProfiles, c as profileConfig, i as formatModelProfile, l as TURN_REASONING_LEVELS, n as ModelProfileNotConfiguredError, o as modelIdForProfile, s as modelProfileSchema } from "./model-profile-Bg8EoCKD.js";
|
|
8
8
|
import { a as isUserActor, d as parseSlackTeamId, f as parseSlackUserId, g as parseSlackMessageTs, l as parseSlackChannelId, u as parseSlackChannelReferenceId } from "./actor-tlxzqaRe.js";
|
|
9
|
-
import {
|
|
9
|
+
import { O as hasAgentTurnUsage, T as agentTurnCostUsd, d as getConversationStore, f as getDb, l as getConversationEventStore, p as getSqlExecutor, r as readActorIdentity, u as getConversationMessageSearchStore, w as addAgentTurnUsage, z as parseDestination } from "./viewer-B2wXNspU.js";
|
|
10
10
|
import { a as juniorAgentInvocations, c as juniorIdentities, d as juniorDestinations, i as juniorAgentBindings, s as juniorConversations } from "./agent-invocations-CxKldAeB.js";
|
|
11
|
-
import { _ as juniorConversationAnnotations, a as juniorAutomationRuns, b as juniorAttachments, c as juniorStats, f as juniorConversationBriefs, x as juniorArtifacts } from "./executor-
|
|
11
|
+
import { _ as juniorConversationAnnotations, a as juniorAutomationRuns, b as juniorAttachments, c as juniorStats, f as juniorConversationBriefs, x as juniorArtifacts } from "./executor-CAr7xQr2.js";
|
|
12
12
|
import { d as contextProvenance, f as instructionActors, m as sameActorIdentity, p as instructionProvenanceFor, t as KNOWN_CONVERSATION_EVENT_TYPES, u as agentInstructionProvenance } from "./history-AY8rs-FR.js";
|
|
13
13
|
import { a as listReferenceFiles, c as soulPathCandidates, l as worldPathCandidates } from "./package-discovery-DJBompdd.js";
|
|
14
|
-
import { c as fetchWithBoundedOAuthErrorBodies, d as actorLogContext, f as credentialContextForActor, g as credentialUserSubjectId, i as resolvePluginHeaderEnvRefs, l as getOAuthProviderErrorAttributes, s as OAuthProviderError } from "./registry-
|
|
15
|
-
import { n as pluginCatalogRuntime } from "./catalog-runtime-
|
|
16
|
-
import { a as parseSkillInvocation, i as parseSkillFile, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-
|
|
17
|
-
import { A as
|
|
18
|
-
import { o as fenceLock, r as getStateAdapter, s as withLock } from "./adapter-
|
|
14
|
+
import { c as fetchWithBoundedOAuthErrorBodies, d as actorLogContext, f as credentialContextForActor, g as credentialUserSubjectId, i as resolvePluginHeaderEnvRefs, l as getOAuthProviderErrorAttributes, s as OAuthProviderError } from "./registry-COTeZ2cV.js";
|
|
15
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-D3qbJlYz.js";
|
|
16
|
+
import { a as parseSkillInvocation, i as parseSkillFile, n as findSkillByName, r as loadSkillsByName, t as discoverSkills } from "./skills-Bb2KaJ3m.js";
|
|
17
|
+
import { $n as defaultTimezone, A as setWorkspaceSnapshotBuild, At as RESOURCE_SUBSCRIPTION_MAX_TTL_MS, B as wrapSandboxSetupError, Bt as getWatch, C as listWorkspaces, Cn as SANDBOX_WORKSPACE_ROOT, Ct as tryWorkspaceRepoCheckoutPath, D as invalidateReadySnapshot, Dt as isSlackMessageTurn, E as WorkspaceValidationError, En as sandboxSkillPathResolution, Et as getSlackToolContext, F as ensureDockerDaemon, Gn as matchSlackAttachments, H as getWorkspaceSnapshotNotReadyError, I as getSandboxProvider, It as createTimerWatch, J as consumeSandboxEgressAuthRequiredSignal, L as isAbortError, Lt as createWatch, M as create, Mt as STOP_WATCHING_TOOL_NAME, N as hash, Nt as cancelSubscriptions, O as loadSnapshotsForProfile, Ot as slackMessageTurnDisabledReason, P as isStale, Pt as cancelWatch, Qt as getFilePermalink, R as isAlreadyExistsError, Rt as deliverWatch, S as getWorkspaceByName, Sn as SANDBOX_SKILLS_ROOT, T as updateWorkspace, Tn as sandboxSkillFile, Tt as resolveChannelCapabilities, U as isWorkspaceSnapshotNotReadyError, V as WorkspaceSnapshotNotReadyError, Vt as listWatches, W as workspaceSnapshotNotReadyUserMessage, X as createSandboxEgressCredentialToken, Xn as createPluginAnnotations, Xt as SlackActionError, Y as consumeSandboxEgressPermissionDeniedSignal, Yn as saveObjectAnnotations, Zt as downloadPrivateSlackFile, _n as buildNonInteractiveShellScript, _t as openSlackDirectMessage, an as withSlackRetries, at as formatProviderLabel, b as deleteWorkspace, bn as SANDBOX_DATA_ROOT, bt as uploadFilesToConversation, cr as conversationNoteEvent, d as getPluginTools, en as getSlackClient, er as resolveUserTimezone, et as buildSandboxEgressNetworkPolicy, f as getPluginUserPromptContributions, fn as getDashboardTaskLink, gn as buildCommandScript, gt as getSlackMessagePermalink, hn as PluginToolDeniedError, ht as addReactionToMessage, ir as JUNIOR_NATIVE_EVENT_NAMESPACE, it as deliverOAuthAuthorization, j as SANDBOX_RUNTIME, jt as RESOURCE_WATCH_TOOL_SOURCE, k as setWorkspaceSnapshot, kt as RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS, mn as ToolInputError, n as createUserTokenStore, o as createPluginHookRunner, on as sleep, p as getPlugins, pt as slackMention, q as clearSandboxEgressSignals, r as getOAuthAccountProviders, rn as normalizeSlackConversationId, st as resolveBaseUrl, tn as isConversationScopedChannel, tt as resolveSandboxCommandEnvironment, u as getPluginSystemPromptContributions, un as getDashboardConversationLink, vn as runNonInteractiveCommand, wn as sandboxSkillDir, wt as workspaceRepoCheckoutPath, x as getWorkspace, xn as SANDBOX_REPOS_ROOT, y as createWorkspace, yn as SANDBOX_COMMAND_PATH, z as throwSandboxOperationError, zt as findMatchingWatches } from "./credentialed-C6pKlB1p.js";
|
|
18
|
+
import { o as fenceLock, r as getStateAdapter, s as withLock } from "./adapter-cUkPH3Om.js";
|
|
19
19
|
import { i as isValidTimeZone, r as getZonedDateTimeParts } from "./cadence-R7Em4RjE.js";
|
|
20
20
|
import { G as briefLinkSchema, H as detectImageMediaType, I as removedCardSchema, K as briefOutcomeStatusSchema, U as isVisionImageMediaType, q as conversationBriefSchema } from "./conversation-B0baEwoA.js";
|
|
21
|
-
import { A as
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { a as
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { F as taskOutcomeInputSchema, M as compileScheduleIntent, N as scheduleIntentSchema, O as automationInstructionToolSchema, T as SCHEDULED_AUTOMATION_SYSTEM_ACTOR, j as ScheduleIntentError, k as automationTitleSchema } from "./automation-CWX0qL8U.js";
|
|
21
|
+
import { A as AgentMessageQueueFullError, F as agentNameSchema, H as TurnInputCommitLostError, I as AGENT_TYPES, K as isTurnInputCommitLostError, M as AgentNameInUseError, N as CHILD_AGENT_RESULTS, P as PARENT_AGENT_TARGET, V as CooperativeTurnYieldError, _ as getLatestAgentInvocationForConversation, d as getAgentInvocationIdForResult, f as getAgentInvocationMessageId, g as getChildAgentLockName, j as AgentMessageTargetError, k as AgentInvocationLimitError, t as NON_TERMINAL_AGENT_INVOCATION_STATUSES, v as invocationFromRow, y as isTerminalAgentInvocation, z as formatAgentTypes } from "./store-CqRnaZSq.js";
|
|
22
|
+
import { a as isNoReplyMarker, i as NO_REPLY_MARKER, n as getAssistantReplyText, r as sanitizeAssistantText, t as decideReply } from "./assistant-reply-UPA8vKlC.js";
|
|
23
|
+
import { A as requireEventIdentifier, D as registeredEventMatchSchema, E as hasEventCatalogEntries, H as remindMissingAutomationResult, L as FINISH_AUTOMATION_RUN_TOOL_NAME, O as registeredEventTypeSchema, R as automationResultSchema, S as describeRegisteredEventTrigger, T as eventWatchUnavailable, V as readAutomationResult, _ as WORKSPACE_SNAPSHOT_FAILED_EVENT, b as workspaceSnapshotWatch, d as getEventCatalog, j as requireValidEventTrigger, k as registeredResourceTypeSchema, n as markConversationsStopped, o as enqueueEventNotification, p as requireSlackChannelMessageScope, t as getConversationStoppedAtMs, v as WORKSPACE_SNAPSHOT_READY_EVENT, w as eventNamespaceSchema, x as automationEventCatalog, y as workspaceSnapshotFinishedEvent } from "./session-stop-CpCUy1ZJ.js";
|
|
24
|
+
import { a as setSnapshotSpanAttributes, i as postinstall, n as resolve$1, r as dependencies, s as getSandboxResources } from "./resolve-g9PKz9pH.js";
|
|
25
|
+
import { a as getVercelConversationWorkQueue, f as getTurnRequestDeadline, n as sendNextWorkspaceSnapshotJob, r as sendWorkspaceSnapshotJob } from "./job-queue-Cjo6Yg_b.js";
|
|
26
|
+
import { E as stopConversationWork } from "./store-DdT74Lvq.js";
|
|
27
|
+
import { _ as getMcpProviderErrorAttributes, a as serviceAccountOnly, c as createMcpServiceAccountClientProvider, d as PluginMcpClient, f as McpProviderError, g as getMcpAwareTelemetryMessage, h as getMcpAwareErrorType, i as serviceAccountAllows, l as getMcpServiceAccountCredentials, m as McpToolError, p as McpServiceAccountRequiredError, u as McpAuthorizationRequiredError, v as toMcpProviderError } from "./service-account-YdYftwV2.js";
|
|
28
|
+
import { F as taskOutcomeInputSchema, M as compileScheduleIntent, N as scheduleIntentSchema, O as automationInstructionToolSchema, T as SCHEDULED_AUTOMATION_SYSTEM_ACTOR, j as ScheduleIntentError, k as automationTitleSchema } from "./automation-2RbKzpMT.js";
|
|
30
29
|
import { n as privateTraceResultAttributes } from "./private-trace-result-CE7_lEdq.js";
|
|
31
30
|
import { streamSimple } from "@earendil-works/pi-ai/compat";
|
|
32
31
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
@@ -36,13 +35,13 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
36
35
|
import { z } from "zod";
|
|
37
36
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
38
37
|
import { and, asc, desc, eq, gt, gte, inArray, isNotNull, isNull, lt, lte, ne, notExists, or, sql } from "drizzle-orm";
|
|
39
|
-
import { PluginToolInputError, eventSchema, missingToolAnnotationKeys, ownedObjectAnnotationSchema, sourceSchema, stableEventMatchKey, watchResultSchema } from "@sentry/junior-plugin-api";
|
|
38
|
+
import { PluginToolInputError, eventMatchFieldSchema, eventSchema, eventTriggerText, missingToolAnnotationKeys, ownedObjectAnnotationSchema, sourceSchema, stableEventMatchKey, watchResultSchema } from "@sentry/junior-plugin-api";
|
|
40
39
|
import { alias } from "drizzle-orm/pg-core";
|
|
41
40
|
import { Agent, estimateContextTokens } from "@earendil-works/pi-agent-core";
|
|
42
41
|
import fs from "node:fs/promises";
|
|
43
42
|
import fs$1 from "node:fs";
|
|
44
|
-
import {
|
|
45
|
-
import { isRetryableAssistantError } from "@earendil-works/pi-ai";
|
|
43
|
+
import { SignJWT, importPKCS8 } from "jose";
|
|
44
|
+
import { createAssistantMessageEventStream, isRetryableAssistantError } from "@earendil-works/pi-ai";
|
|
46
45
|
import { Kind } from "@sinclair/typebox";
|
|
47
46
|
import { Bash, defineCommand } from "just-bash";
|
|
48
47
|
import { structuredPatch } from "diff";
|
|
@@ -53,7 +52,6 @@ import https from "node:https";
|
|
|
53
52
|
import net from "node:net";
|
|
54
53
|
import { NodeHtmlMarkdown } from "node-html-markdown";
|
|
55
54
|
import { Value } from "@sinclair/typebox/value";
|
|
56
|
-
import { SignJWT, importPKCS8 } from "jose";
|
|
57
55
|
// src/chat/sandbox/skill-sandbox.ts
|
|
58
56
|
const MAX_SKILL_FILE_BYTES = 262144;
|
|
59
57
|
const DEFAULT_MAX_SKILL_FILE_CHARS = 2e4;
|
|
@@ -716,6 +714,53 @@ function buildChatEndAttributes(message, mode) {
|
|
|
716
714
|
}
|
|
717
715
|
return attributes;
|
|
718
716
|
}
|
|
717
|
+
const NON_CONTENT_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
718
|
+
"start",
|
|
719
|
+
"done",
|
|
720
|
+
"error"
|
|
721
|
+
]);
|
|
722
|
+
function createResponseTiming(requestStartedAtMs) {
|
|
723
|
+
let firstByteAtMs;
|
|
724
|
+
let firstToken;
|
|
725
|
+
return {
|
|
726
|
+
observe: (event) => {
|
|
727
|
+
if (firstByteAtMs === void 0 && event.type !== "error") firstByteAtMs = Date.now();
|
|
728
|
+
if (!firstToken && !NON_CONTENT_EVENT_TYPES.has(event.type)) firstToken = {
|
|
729
|
+
type: event.type,
|
|
730
|
+
receivedAtMs: Date.now()
|
|
731
|
+
};
|
|
732
|
+
},
|
|
733
|
+
attributes: () => {
|
|
734
|
+
if (firstByteAtMs === void 0) return { "gen_ai.response.streaming": false };
|
|
735
|
+
return {
|
|
736
|
+
"gen_ai.response.streaming": true,
|
|
737
|
+
"app.ai.time_to_first_byte_ms": firstByteAtMs - requestStartedAtMs,
|
|
738
|
+
...firstToken ? {
|
|
739
|
+
"gen_ai.response.time_to_first_chunk": (firstToken.receivedAtMs - requestStartedAtMs) / 1e3,
|
|
740
|
+
"app.ai.first_token_type": firstToken.type
|
|
741
|
+
} : void 0
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function relayStream(source, onEvent) {
|
|
747
|
+
const relayed = createAssistantMessageEventStream();
|
|
748
|
+
const finished = (async () => {
|
|
749
|
+
try {
|
|
750
|
+
for await (const event of source) {
|
|
751
|
+
onEvent(event);
|
|
752
|
+
relayed.push(event);
|
|
753
|
+
}
|
|
754
|
+
} finally {
|
|
755
|
+
relayed.end();
|
|
756
|
+
}
|
|
757
|
+
})();
|
|
758
|
+
finished.then(() => source.result()).then((message) => relayed.end(message), () => {});
|
|
759
|
+
return {
|
|
760
|
+
stream: relayed,
|
|
761
|
+
finished
|
|
762
|
+
};
|
|
763
|
+
}
|
|
719
764
|
/**
|
|
720
765
|
* Wraps pi-ai's `streamSimple` so each LLM call inside a pi-agent-core agent
|
|
721
766
|
* loop produces its own `gen_ai.chat` Sentry span. The returned function is
|
|
@@ -737,10 +782,16 @@ function createTracedStreamFn(baseOrOptions = streamSimple) {
|
|
|
737
782
|
}
|
|
738
783
|
});
|
|
739
784
|
try {
|
|
785
|
+
const requestStartedAtMs = Date.now();
|
|
740
786
|
const stream = await withActiveSpan(span, () => Promise.resolve(base(model, context, options)));
|
|
741
|
-
|
|
787
|
+
const responseTiming = createResponseTiming(requestStartedAtMs);
|
|
788
|
+
const relay = relayStream(stream, responseTiming.observe);
|
|
789
|
+
relay.finished.then(() => stream.result()).then((finalMessage) => {
|
|
742
790
|
try {
|
|
743
|
-
const endAttributes =
|
|
791
|
+
const endAttributes = {
|
|
792
|
+
...buildChatEndAttributes(finalMessage, mode),
|
|
793
|
+
...responseTiming.attributes()
|
|
794
|
+
};
|
|
744
795
|
for (const [key, value] of Object.entries(endAttributes)) span.setAttribute(key, value);
|
|
745
796
|
if (finalMessage.stopReason === "error") {
|
|
746
797
|
const summary = endAttributes["app.ai.provider_error.summary"];
|
|
@@ -753,6 +804,7 @@ function createTracedStreamFn(baseOrOptions = streamSimple) {
|
|
|
753
804
|
span.end();
|
|
754
805
|
}
|
|
755
806
|
}, (error) => {
|
|
807
|
+
span.setAttributes(responseTiming.attributes());
|
|
756
808
|
span.setAttribute("error.type", error instanceof Error ? error.name : typeof error);
|
|
757
809
|
span.setStatus({
|
|
758
810
|
code: 2,
|
|
@@ -760,7 +812,7 @@ function createTracedStreamFn(baseOrOptions = streamSimple) {
|
|
|
760
812
|
});
|
|
761
813
|
span.end();
|
|
762
814
|
}).catch(() => {});
|
|
763
|
-
return stream;
|
|
815
|
+
return relay.stream;
|
|
764
816
|
} catch (error) {
|
|
765
817
|
span.setAttribute("error.type", error instanceof Error ? error.name : typeof error);
|
|
766
818
|
span.setStatus({
|
|
@@ -1664,7 +1716,7 @@ function formatAvailableSkillsForPrompt(skills) {
|
|
|
1664
1716
|
}
|
|
1665
1717
|
function formatActiveMcpCatalogsForPrompt(catalogs) {
|
|
1666
1718
|
if (catalogs.length === 0) return null;
|
|
1667
|
-
const lines = [
|
|
1719
|
+
const lines = [];
|
|
1668
1720
|
for (const catalog of catalogs) {
|
|
1669
1721
|
lines.push(" <catalog>");
|
|
1670
1722
|
lines.push(` <provider>${escapeXml(catalog.provider)}</provider>`);
|
|
@@ -1702,31 +1754,22 @@ const SLACK_HEADER = "You are a Slack-based helper assistant. Follow the persona
|
|
|
1702
1754
|
const LOCAL_HEADER = "You are a helper assistant. Follow the personality section for voice and tone in every reply. Platform mechanics and output rules override personality and world context when they conflict.";
|
|
1703
1755
|
const TURN_CONTEXT_HEADER = "Runtime context for this request. Treat these blocks as trusted runtime facts; the static system prompt remains authoritative.";
|
|
1704
1756
|
const TOOL_POLICY_RULES = [
|
|
1705
|
-
"- Tool schemas are the source of truth for parameters; tool names are case-sensitive, so call tools exactly by their exposed names and do not invent arguments.",
|
|
1706
1757
|
"- Use tools for actionable work and for facts that are mutable, external, repository-backed, provider-backed, or requested as verified/current. Stable general knowledge and already-provided context may be answered directly.",
|
|
1707
1758
|
"- Do not use tools to rediscover content already present in the current conversation. For drafting or rewriting with no referenced retrievable source, use clear placeholders or ask one focused question instead of searching unrelated memory, history, files, or providers.",
|
|
1708
1759
|
"- Resolve provider action targets before calls: explicit target wins; ambient `<configuration>` fills omitted targets. Treat non-target links/references as context.",
|
|
1709
1760
|
"- Verification source order: conversation/thread context; user-provided attachments, links, and reference files; local/sandbox files when present; loaded skill references; repository/provider tools; public web. Use the nearest authoritative available source before weaker sources.",
|
|
1710
1761
|
"- For repository or implementation questions, inspect the target repository first: local checkout when present, otherwise the configured GitHub/source provider. Do not treat loaded skill files as repo source unless the user asks about the skill. Cite file paths, symbols, PRs/issues, commits, or URLs that support the answer.",
|
|
1711
|
-
"- Workspaces are named prepared Sandbox recipes. Use `listWorkspaces` and `switchWorkspace` with them. Prefer a matching Workspace over an ad-hoc checkout when one fits.",
|
|
1712
1762
|
"- After changing files, name the changed paths and summarize the completed result in the final answer.",
|
|
1713
|
-
"- If a sandbox-backed tool reports that sandbox execution is unavailable, treat that as a blocker for local file/shell inspection; do not pretend host files were inspected.",
|
|
1714
|
-
"- For user-provided URLs, use `webFetch`; for discovery, use `webSearch` then fetch/read promising sources; for current time/date context, use `systemTime`.",
|
|
1715
|
-
"- When searchEventTypes is exposed, use it only when the user asks what events are supported or the required resource type or event name is unclear. It discovers options but does not watch a resource or create an automation. When explaining how results can be used, distinguish temporary current-thread watches from durable event automations.",
|
|
1716
1763
|
"- When a tool result includes a subscription, those events are already watched; do not call watchEvents for them. When a tool result includes a subscribable resource with suggestedEvents, use watchEvents only for those remaining events that serve the current intent. If suggestedEvents is empty or omitted, do not invent a watch. Do not create scheduled polling tasks for events a watch can deliver. Write a concise intent summary, and tell the user when the temporary watch expires. Stop only the requested watch by id unless the user explicitly asks to stop every watch in the thread.",
|
|
1717
1764
|
"- Cards returned by tools attach to your next visible reply automatically. Explain the outcome; do not repeat the card fields or draw a card in text.",
|
|
1718
|
-
"-
|
|
1719
|
-
"-
|
|
1720
|
-
"- Event automations list for the current destination, not one thread. Public automations can also be updated or deleted by automation id from another destination in the same workspace. When listing them, use createdBy to explain creator-only credential changes and warn when trigger.available is false; an unavailable automation remains stored but cannot receive events until its plugin event is enabled again.",
|
|
1721
|
-
"- Before loading a skill or starting substantial work, decide how to run it. When `handoff` is available and another profile fits better, switch first. When `spawnAgent` is available and its delegation rules fit, give independent tracks to child agents. Otherwise do the work inline.",
|
|
1722
|
-
"- Run `jr-rpc config get|set|unset|list` for provider defaults and `jr-rpc plugins list` for installed plugin introspection as standalone bash commands; do not chain them with `cd`, `&&`, pipes, or provider commands.",
|
|
1765
|
+
"- Scheduled and event automations use their creator's connected credentials by default when the requested work needs them. Do not ask for separate confirmation merely to use those credentials.",
|
|
1766
|
+
"- Before loading a skill or starting substantial work, decide whether `handoff` or `spawnAgent` fits better than inline work.",
|
|
1723
1767
|
"- If the first result is empty, stale, ambiguous, or incomplete, try a focused alternate query, path, command, or source before concluding the answer cannot be verified."
|
|
1724
1768
|
];
|
|
1725
1769
|
const TOOL_CALL_STYLE_RULES = [
|
|
1726
1770
|
"- For routine low-risk tool use, call the tool directly without narrating the obvious step first.",
|
|
1727
1771
|
"- Briefly narrate only when it helps the user understand multi-step work, sensitive actions, destructive actions, or a notable change in approach.",
|
|
1728
|
-
"- When a first-class tool exists for an action, use it directly instead of asking the user to run an equivalent command, slash command, or manual lookup."
|
|
1729
|
-
"- Keep tool-call explanations separate from final answers; final answers should report results, evidence, or blockers."
|
|
1772
|
+
"- When a first-class tool exists for an action, use it directly instead of asking the user to run an equivalent command, slash command, or manual lookup."
|
|
1730
1773
|
];
|
|
1731
1774
|
const SKILL_POLICY_RULES = [
|
|
1732
1775
|
"- A `<skill>` block in the current user turn is already loaded. Follow its instructions directly and do not call `loadSkill` for that skill.",
|
|
@@ -1739,9 +1782,8 @@ const PLANNING_RULES = [
|
|
|
1739
1782
|
"- The tool displays the plan. Do not repeat it in chat, and do not finish with a plan when you can complete the work now."
|
|
1740
1783
|
];
|
|
1741
1784
|
const TASK_EXECUTION_RULES = [
|
|
1742
|
-
"- Actionable request: act in this turn.",
|
|
1743
1785
|
"- Continue until done, genuinely blocked, or waiting on child agents you started. Do not finish with a plan, promise, or offer to check next when an available tool or source can move the request forward.",
|
|
1744
|
-
"- Ask the user only for missing access
|
|
1786
|
+
"- Ask the user only for missing access or a decision that blocks safe progress. Ask one focused question; otherwise infer conservatively and continue. An open scope or follow-up question does not block delivery: deliver the requested work and state the question.",
|
|
1745
1787
|
"- For conflicting evidence, compare sources and state which source is authoritative for the answer.",
|
|
1746
1788
|
"- A tool result with `timed_out: true` means that attempt did not finish. Continue the active task. Before retrying work that may have side effects, inspect authoritative state and do not repeat a mutation that already applied."
|
|
1747
1789
|
];
|
|
@@ -1753,8 +1795,7 @@ const CONVERSATION_RULES = [
|
|
|
1753
1795
|
"- Runtime owns continuation and authorization notices; on resumed turns, answer with the final requested content only."
|
|
1754
1796
|
];
|
|
1755
1797
|
const SLACK_ACTION_RULES = [
|
|
1756
|
-
"- Slack posts, reactions, new canvases, new lists, and file sends go only to the current conversation
|
|
1757
|
-
"- Assistant text is delivered only into the active conversation or thread. You cannot create a new top-level channel post; if asked to do so, explain that limitation and do not present the requested text as delivered.",
|
|
1798
|
+
"- Assistant text, Slack posts, reactions, new canvases, new lists, and file sends go only to the current conversation or thread. Your reply is not a channel post, and you cannot create a new top-level channel post. When asked to post to a channel or anywhere else right now, explain that limitation; do not call a Slack send tool, and do not reply with only the requested text or present it as delivered. Scheduled automations can still post to the active channel later. Slack read tools can target other public channels with `channel_id`.",
|
|
1758
1799
|
"- Ambient reaction requests target the current inbound message; do not ask for a message reference.",
|
|
1759
1800
|
`- When no visible thread reply is requested or useful, keep tool-calling messages text-free and make the final message exactly ${NO_REPLY_MARKER}.`
|
|
1760
1801
|
];
|
|
@@ -1898,22 +1939,12 @@ function formatDestinationLines(destination) {
|
|
|
1898
1939
|
`- destination.channel_id: ${escapeXml(destination.channelId)}`
|
|
1899
1940
|
];
|
|
1900
1941
|
}
|
|
1901
|
-
function formatOutcomeLines(outcomes) {
|
|
1902
|
-
if (!outcomes) return ["- dispatch.outcomes: send_message to the destination below (legacy default)"];
|
|
1903
|
-
if (outcomes.length === 0) return ["- dispatch.outcomes: none; successful work posts nothing"];
|
|
1904
|
-
return outcomes.map((outcome, index) => {
|
|
1905
|
-
const { channelId, threadTs } = outcome.destination;
|
|
1906
|
-
const recipient = isDmChannel$1(channelId) ? "the creator's direct message" : "a slack channel";
|
|
1907
|
-
const target = [`channel_id=${escapeXml(channelId)}`, ...threadTs ? [`thread_ts=${escapeXml(threadTs)}`] : []].join(" ");
|
|
1908
|
-
return `- dispatch.outcome.${index + 1}: ${outcome.action} to ${recipient} (${target})`;
|
|
1909
|
-
});
|
|
1910
|
-
}
|
|
1911
1942
|
function buildDispatchSection(params) {
|
|
1912
1943
|
if (!params) return null;
|
|
1913
1944
|
const metadataLines = Object.entries(params.metadata ?? {}).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `- dispatch.metadata.${escapeXml(key)}: ${escapeXml(value)}`);
|
|
1914
1945
|
return renderTag("dispatch", [
|
|
1915
1946
|
"- dispatch.execution: execute the dispatched input now",
|
|
1916
|
-
...params.declaresResult ?
|
|
1947
|
+
...params.declaresResult ? [] : ["- dispatch.delivery: the runtime delivers the final answer to the destination", "- dispatch.delivery_rule: do not request or require a separate posting tool just to deliver the final answer"],
|
|
1917
1948
|
...params.actor ? [`- dispatch.actor.platform: ${escapeXml(params.actor.platform)}`, `- dispatch.actor.name: ${escapeXml(params.actor.name)}`] : [],
|
|
1918
1949
|
...params.plugin ? [`- dispatch.plugin: ${escapeXml(params.plugin)}`] : [],
|
|
1919
1950
|
...formatSourceLines(params.source),
|
|
@@ -2718,24 +2749,38 @@ function createJrRpcCommand(deps) {
|
|
|
2718
2749
|
});
|
|
2719
2750
|
});
|
|
2720
2751
|
}
|
|
2752
|
+
function toolCommandResult(command, output) {
|
|
2753
|
+
return {
|
|
2754
|
+
ok: output.exitCode === 0,
|
|
2755
|
+
command,
|
|
2756
|
+
cwd: "/",
|
|
2757
|
+
exit_code: output.exitCode,
|
|
2758
|
+
signal: null,
|
|
2759
|
+
timed_out: false,
|
|
2760
|
+
stdout: output.stdout,
|
|
2761
|
+
stderr: output.stderr,
|
|
2762
|
+
stdout_truncated: false,
|
|
2763
|
+
stderr_truncated: false
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
const CHAINED_JR_RPC_PATTERN = /(?:&&|\|\||[;|\n])\s*jr-rpc(?:\s|$)/;
|
|
2767
|
+
/** Run a standalone `jr-rpc` bash command, or reject one chained after other shell steps. */
|
|
2721
2768
|
async function maybeExecuteJrRpcCustomCommand(command, deps) {
|
|
2722
2769
|
const normalized = command.trim();
|
|
2723
|
-
if (!/^jr-rpc(?:\s|$)/.test(normalized))
|
|
2724
|
-
|
|
2770
|
+
if (!/^jr-rpc(?:\s|$)/.test(normalized)) {
|
|
2771
|
+
if (!CHAINED_JR_RPC_PATTERN.test(normalized)) return { handled: false };
|
|
2772
|
+
return {
|
|
2773
|
+
handled: true,
|
|
2774
|
+
result: toolCommandResult(normalized, {
|
|
2775
|
+
exitCode: 2,
|
|
2776
|
+
stdout: "",
|
|
2777
|
+
stderr: "jr-rpc runs only as a standalone bash command. Run the jr-rpc command by itself, without cd, &&, pipes, or other commands.\n"
|
|
2778
|
+
})
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2725
2781
|
return {
|
|
2726
2782
|
handled: true,
|
|
2727
|
-
result: {
|
|
2728
|
-
ok: execResult.exitCode === 0,
|
|
2729
|
-
command: normalized,
|
|
2730
|
-
cwd: "/",
|
|
2731
|
-
exit_code: execResult.exitCode,
|
|
2732
|
-
signal: null,
|
|
2733
|
-
timed_out: false,
|
|
2734
|
-
stdout: execResult.stdout,
|
|
2735
|
-
stderr: execResult.stderr,
|
|
2736
|
-
stdout_truncated: false,
|
|
2737
|
-
stderr_truncated: false
|
|
2738
|
-
}
|
|
2783
|
+
result: toolCommandResult(normalized, await new Bash({ customCommands: [createJrRpcCommand(deps)] }).exec(normalized))
|
|
2739
2784
|
};
|
|
2740
2785
|
}
|
|
2741
2786
|
// src/chat/sandbox/command-result.ts
|
|
@@ -2960,9 +3005,9 @@ const BUILD_COMMAND_TIMEOUT_ERROR = "Workspace snapshot build phase timed out af
|
|
|
2960
3005
|
const COMMAND_STATUS_POLL_TIMEOUT_MS = 1e3;
|
|
2961
3006
|
/** Leave time to save the build state before this request ends. */
|
|
2962
3007
|
const STOP_BUFFER_MS = 4e4;
|
|
2963
|
-
/** Keep the build open when a request stops or
|
|
3008
|
+
/** Keep the build open when a request stops or the provider has a short failure. */
|
|
2964
3009
|
function isCancelOrTransient(error) {
|
|
2965
|
-
return isAbortError(error) ||
|
|
3010
|
+
return isAbortError(error) || getSandboxProvider().errors.isTransient(error);
|
|
2966
3011
|
}
|
|
2967
3012
|
function buildLockKey(profileHash) {
|
|
2968
3013
|
return `${BUILD_LOCK_PREFIX}:${profileHash}`;
|
|
@@ -3003,7 +3048,7 @@ function activeBuild(build) {
|
|
|
3003
3048
|
}
|
|
3004
3049
|
async function deleteBuilder(sandboxName) {
|
|
3005
3050
|
if (!sandboxName) return;
|
|
3006
|
-
await deleteWorkspaceSnapshotBuilders([sandboxName]);
|
|
3051
|
+
await getSandboxProvider().deleteWorkspaceSnapshotBuilders([sandboxName]);
|
|
3007
3052
|
}
|
|
3008
3053
|
function workspaceDeletedError(workspace) {
|
|
3009
3054
|
return /* @__PURE__ */ new Error(`Workspace ${workspace.name} was deleted while its snapshot was building`);
|
|
@@ -3044,8 +3089,8 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3044
3089
|
if (!build?.commandId || !build.sandboxName) return null;
|
|
3045
3090
|
try {
|
|
3046
3091
|
await requireRemainingBuildTime(workspace, build, beforeWrite);
|
|
3047
|
-
const
|
|
3048
|
-
const command = await
|
|
3092
|
+
const builder = await getSandboxProvider().getWorkspaceSnapshotBuilder(build.sandboxName, signal);
|
|
3093
|
+
const command = await builder.getCommand(build.commandId, { signal });
|
|
3049
3094
|
const pollSignal = AbortSignal.timeout(COMMAND_STATUS_POLL_TIMEOUT_MS);
|
|
3050
3095
|
const waitSignal = signal ? AbortSignal.any([signal, pollSignal]) : pollSignal;
|
|
3051
3096
|
let finished;
|
|
@@ -3065,7 +3110,7 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3065
3110
|
throw new Error(`Workspace ${workspace.name} snapshot setup failed: ${detail}`);
|
|
3066
3111
|
}
|
|
3067
3112
|
await requireRemainingBuildTime(workspace, build, beforeWrite);
|
|
3068
|
-
const snapshot = await
|
|
3113
|
+
const snapshot = await builder.snapshot({ signal });
|
|
3069
3114
|
await requireRemainingBuildTime(workspace, build, beforeWrite);
|
|
3070
3115
|
const createdAtMs = Date.now();
|
|
3071
3116
|
const buildDurationMs = Math.max(0, createdAtMs - build.startedAt.getTime());
|
|
@@ -3080,7 +3125,7 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3080
3125
|
}, { buildId: build.id });
|
|
3081
3126
|
requireBuildWrite(result.written, workspace);
|
|
3082
3127
|
try {
|
|
3083
|
-
await deleteWorkspaceSnapshotBuilders(result.replacedBuilderNames);
|
|
3128
|
+
await getSandboxProvider().deleteWorkspaceSnapshotBuilders(result.replacedBuilderNames);
|
|
3084
3129
|
} catch (error) {
|
|
3085
3130
|
logException(error, "sandbox.workspace_snapshot.builder.delete_failed", {
|
|
3086
3131
|
"app.workspace.id": workspace.id,
|
|
@@ -3107,19 +3152,16 @@ async function finishBuild(workspace, value, signal, beforeWrite) {
|
|
|
3107
3152
|
/** Create the Sandbox and save its name. */
|
|
3108
3153
|
async function startBuild(params) {
|
|
3109
3154
|
const { workspace, value, signal } = params;
|
|
3110
|
-
const credentials = getVercelSandboxCredentials();
|
|
3111
3155
|
const resources = getSandboxResources(workspace);
|
|
3112
3156
|
const name = builderName();
|
|
3113
3157
|
const buildId = randomUUID();
|
|
3114
3158
|
const startedAt = /* @__PURE__ */ new Date();
|
|
3115
3159
|
try {
|
|
3116
|
-
await
|
|
3160
|
+
await getSandboxProvider().createWorkspaceSnapshotBuilder({
|
|
3117
3161
|
name,
|
|
3118
|
-
persistent: true,
|
|
3119
|
-
timeout: BUILD_TIMEOUT_MS,
|
|
3120
3162
|
runtime: params.runtime,
|
|
3163
|
+
timeoutMs: BUILD_TIMEOUT_MS,
|
|
3121
3164
|
signal,
|
|
3122
|
-
...credentials ?? {},
|
|
3123
3165
|
...resources ? { resources } : void 0
|
|
3124
3166
|
});
|
|
3125
3167
|
await params.beforeWrite();
|
|
@@ -3181,8 +3223,8 @@ async function continueBuild(params) {
|
|
|
3181
3223
|
const phaseTimeoutSignal = AbortSignal.timeout(commandTimeoutMs);
|
|
3182
3224
|
const phaseSignal = params.signal ? AbortSignal.any([params.signal, phaseTimeoutSignal]) : phaseTimeoutSignal;
|
|
3183
3225
|
try {
|
|
3184
|
-
const
|
|
3185
|
-
const session =
|
|
3226
|
+
const builder = await getSandboxProvider().getWorkspaceSnapshotBuilder(build.sandboxName, phaseSignal);
|
|
3227
|
+
const session = builder.session();
|
|
3186
3228
|
if (build.phase === "created") {
|
|
3187
3229
|
await dependencies(session, params.value.dependencies, phaseSignal, commandTimeoutMs);
|
|
3188
3230
|
await postinstall(session, params.value.postinstall, phaseSignal, commandTimeoutMs);
|
|
@@ -3212,16 +3254,15 @@ async function continueBuild(params) {
|
|
|
3212
3254
|
return;
|
|
3213
3255
|
}
|
|
3214
3256
|
await params.beforeWrite();
|
|
3215
|
-
const
|
|
3257
|
+
const commandId = await builder.startDetachedCommand({
|
|
3216
3258
|
...workspaceSnapshotSetupCommand(params.workspace, build.id),
|
|
3217
|
-
detached: true,
|
|
3218
3259
|
timeoutMs: remainingMs,
|
|
3219
3260
|
signal: phaseSignal
|
|
3220
3261
|
});
|
|
3221
3262
|
await params.beforeWrite();
|
|
3222
3263
|
requireBuildWrite(await setWorkspaceSnapshotBuild(params.workspace.id, {
|
|
3223
3264
|
...build,
|
|
3224
|
-
commandId
|
|
3265
|
+
commandId,
|
|
3225
3266
|
error: null
|
|
3226
3267
|
}), params.workspace);
|
|
3227
3268
|
} catch (error) {
|
|
@@ -3318,7 +3359,7 @@ async function resolveWorkspaceSnapshot(params) {
|
|
|
3318
3359
|
try {
|
|
3319
3360
|
snapshot = await advanceWorkspaceSnapshot(current);
|
|
3320
3361
|
} catch (error) {
|
|
3321
|
-
if (!
|
|
3362
|
+
if (!getSandboxProvider().errors.isTransient(error)) throw error;
|
|
3322
3363
|
advanced = true;
|
|
3323
3364
|
if (shouldStopForTimeLimit(current.shouldStop)) throw new WorkspaceSnapshotNotReadyError(workspace.name);
|
|
3324
3365
|
await sleep(TRANSIENT_API_RETRY_MS, params.signal);
|
|
@@ -3583,6 +3624,42 @@ async function syncSkillsToSandbox(params) {
|
|
|
3583
3624
|
});
|
|
3584
3625
|
});
|
|
3585
3626
|
}
|
|
3627
|
+
// src/chat/sandbox/workspace.ts
|
|
3628
|
+
/** Bind one tool call's cancellation to every sandbox filesystem operation. */
|
|
3629
|
+
function bindSandboxFileSystem(fs, signal) {
|
|
3630
|
+
if (!signal) return fs;
|
|
3631
|
+
return {
|
|
3632
|
+
readFile(filePath, options) {
|
|
3633
|
+
signal.throwIfAborted();
|
|
3634
|
+
return fs.readFile(filePath, {
|
|
3635
|
+
...options,
|
|
3636
|
+
signal
|
|
3637
|
+
});
|
|
3638
|
+
},
|
|
3639
|
+
writeFile(filePath, content, options) {
|
|
3640
|
+
signal.throwIfAborted();
|
|
3641
|
+
return fs.writeFile(filePath, content, {
|
|
3642
|
+
...options,
|
|
3643
|
+
signal
|
|
3644
|
+
});
|
|
3645
|
+
},
|
|
3646
|
+
readdir(filePath) {
|
|
3647
|
+
signal.throwIfAborted();
|
|
3648
|
+
return fs.readdir(filePath, { signal });
|
|
3649
|
+
},
|
|
3650
|
+
stat(filePath) {
|
|
3651
|
+
signal.throwIfAborted();
|
|
3652
|
+
return fs.stat(filePath, { signal });
|
|
3653
|
+
}
|
|
3654
|
+
};
|
|
3655
|
+
}
|
|
3656
|
+
/** Best-effort stop; ignore secondary stop failures during cleanup. */
|
|
3657
|
+
async function stopSession(session) {
|
|
3658
|
+
if (!session) return;
|
|
3659
|
+
try {
|
|
3660
|
+
await session.stop();
|
|
3661
|
+
} catch {}
|
|
3662
|
+
}
|
|
3586
3663
|
// src/chat/sandbox/session.ts
|
|
3587
3664
|
const DEFAULT_MAX_OUTPUT_LENGTH = 3e4;
|
|
3588
3665
|
const DEFAULT_BASH_COMMAND_TIMEOUT_MS = 3e5;
|
|
@@ -3591,16 +3668,6 @@ const SNAPSHOT_BOOT_RETRY_DELAY_MS = 1e3;
|
|
|
3591
3668
|
const SANDBOX_NAME_PREFIX = "junior-";
|
|
3592
3669
|
const MAX_KEEPALIVE_INTERVAL_MS = 3e4;
|
|
3593
3670
|
const MIN_KEEPALIVE_INTERVAL_MS = 1e3;
|
|
3594
|
-
function sandboxFetchOptions(signal) {
|
|
3595
|
-
if (!signal) return {};
|
|
3596
|
-
return { fetch: (input, init) => {
|
|
3597
|
-
const requestSignal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
3598
|
-
return globalThis.fetch(input, {
|
|
3599
|
-
...init,
|
|
3600
|
-
signal: requestSignal ? AbortSignal.any([requestSignal, signal]) : signal
|
|
3601
|
-
});
|
|
3602
|
-
} };
|
|
3603
|
-
}
|
|
3604
3671
|
function truncateOutput(output, maxLength) {
|
|
3605
3672
|
if (output.length <= maxLength) return {
|
|
3606
3673
|
value: output,
|
|
@@ -3650,7 +3717,10 @@ function createSandboxRuntime(options) {
|
|
|
3650
3717
|
keepAliveTimer = void 0;
|
|
3651
3718
|
}
|
|
3652
3719
|
};
|
|
3653
|
-
const
|
|
3720
|
+
const createSession = (input) => getSandboxProvider().createSession({
|
|
3721
|
+
...input,
|
|
3722
|
+
onUnavailable: invalidateSession
|
|
3723
|
+
});
|
|
3654
3724
|
const createSandboxName = () => `${SANDBOX_NAME_PREFIX}${randomUUID()}`;
|
|
3655
3725
|
const preflightNetworkPolicy = (sandboxName) => options.createNetworkPolicy?.(sandboxName);
|
|
3656
3726
|
const persistSandboxRef = async (nextRef) => {
|
|
@@ -3717,30 +3787,26 @@ function createSandboxRuntime(options) {
|
|
|
3717
3787
|
}
|
|
3718
3788
|
});
|
|
3719
3789
|
};
|
|
3720
|
-
const createSandboxFromSnapshot = async (snapshotId,
|
|
3790
|
+
const createSandboxFromSnapshot = async (snapshotId, initialSandboxName, workspace, signal) => {
|
|
3721
3791
|
const resources = getSandboxResources(workspace);
|
|
3722
3792
|
for (let attempt = 0; attempt < SNAPSHOT_BOOT_RETRY_COUNT; attempt += 1) {
|
|
3723
3793
|
signal?.throwIfAborted();
|
|
3724
3794
|
const sandboxName = attempt === 0 ? initialSandboxName : createSandboxName();
|
|
3725
3795
|
const networkPolicy = preflightNetworkPolicy(sandboxName);
|
|
3726
3796
|
try {
|
|
3727
|
-
return
|
|
3728
|
-
|
|
3797
|
+
return await createSession({
|
|
3798
|
+
timeoutMs,
|
|
3729
3799
|
...networkPolicy ? {
|
|
3730
3800
|
name: sandboxName,
|
|
3731
3801
|
persistent: false,
|
|
3732
3802
|
networkPolicy
|
|
3733
3803
|
} : void 0,
|
|
3734
|
-
|
|
3735
|
-
type: "snapshot",
|
|
3736
|
-
snapshotId
|
|
3737
|
-
},
|
|
3804
|
+
snapshotId,
|
|
3738
3805
|
...resources ? { resources } : void 0,
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
}));
|
|
3806
|
+
scopeSignal: signal
|
|
3807
|
+
});
|
|
3742
3808
|
} catch (error) {
|
|
3743
|
-
if (!
|
|
3809
|
+
if (!getSandboxProvider().errors.isSnapshotting(error) || attempt === 2) throw error;
|
|
3744
3810
|
await sleep(SNAPSHOT_BOOT_RETRY_DELAY_MS, signal);
|
|
3745
3811
|
}
|
|
3746
3812
|
}
|
|
@@ -3756,14 +3822,14 @@ function createSandboxRuntime(options) {
|
|
|
3756
3822
|
}
|
|
3757
3823
|
};
|
|
3758
3824
|
const createSandboxFromResolvedSnapshot = async (params) => {
|
|
3759
|
-
const { runtime, snapshot,
|
|
3825
|
+
const { runtime, snapshot, sandboxName, signal } = params;
|
|
3760
3826
|
signal?.throwIfAborted();
|
|
3761
3827
|
if (!snapshot.snapshotId) {
|
|
3762
3828
|
const networkPolicy = preflightNetworkPolicy(sandboxName);
|
|
3763
3829
|
const resources = getSandboxResources(params.workspace);
|
|
3764
3830
|
return {
|
|
3765
|
-
session:
|
|
3766
|
-
|
|
3831
|
+
session: await createSession({
|
|
3832
|
+
timeoutMs,
|
|
3767
3833
|
runtime,
|
|
3768
3834
|
...networkPolicy ? {
|
|
3769
3835
|
name: sandboxName,
|
|
@@ -3771,19 +3837,18 @@ function createSandboxRuntime(options) {
|
|
|
3771
3837
|
networkPolicy
|
|
3772
3838
|
} : void 0,
|
|
3773
3839
|
...resources ? { resources } : void 0,
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
})),
|
|
3840
|
+
scopeSignal: signal
|
|
3841
|
+
}),
|
|
3777
3842
|
snapshot
|
|
3778
3843
|
};
|
|
3779
3844
|
}
|
|
3780
3845
|
try {
|
|
3781
3846
|
return {
|
|
3782
|
-
session: await createSandboxFromSnapshot(snapshot.snapshotId,
|
|
3847
|
+
session: await createSandboxFromSnapshot(snapshot.snapshotId, sandboxName, params.workspace, signal),
|
|
3783
3848
|
snapshot
|
|
3784
3849
|
};
|
|
3785
3850
|
} catch (error) {
|
|
3786
|
-
if (!
|
|
3851
|
+
if (!getSandboxProvider().errors.isSnapshotMissing(error)) throw error;
|
|
3787
3852
|
setSpanAttributes({ "app.sandbox.snapshot.rebuild_after_missing": true });
|
|
3788
3853
|
let rebuilt;
|
|
3789
3854
|
if (params.workspace) rebuilt = await requireWorkspaceSnapshot({
|
|
@@ -3802,14 +3867,13 @@ function createSandboxRuntime(options) {
|
|
|
3802
3867
|
if (!rebuilt.snapshotId) throw error;
|
|
3803
3868
|
signal?.throwIfAborted();
|
|
3804
3869
|
return {
|
|
3805
|
-
session: await createSandboxFromSnapshot(rebuilt.snapshotId,
|
|
3870
|
+
session: await createSandboxFromSnapshot(rebuilt.snapshotId, sandboxName, params.workspace, signal),
|
|
3806
3871
|
snapshot: rebuilt
|
|
3807
3872
|
};
|
|
3808
3873
|
}
|
|
3809
3874
|
};
|
|
3810
3875
|
const createSandboxCandidate = async (workspace, hash, signal) => {
|
|
3811
3876
|
const runtime = SANDBOX_RUNTIME;
|
|
3812
|
-
const sandboxCredentials = getVercelSandboxCredentials();
|
|
3813
3877
|
const sandboxName = createSandboxName();
|
|
3814
3878
|
const prepareWorkspace = workspace ? async (sandbox) => await prepareWorkspaceSnapshot({
|
|
3815
3879
|
sandbox,
|
|
@@ -3840,7 +3904,6 @@ function createSandboxRuntime(options) {
|
|
|
3840
3904
|
return (await createSandboxFromResolvedSnapshot({
|
|
3841
3905
|
runtime,
|
|
3842
3906
|
snapshot,
|
|
3843
|
-
sandboxCredentials,
|
|
3844
3907
|
sandboxName,
|
|
3845
3908
|
signal,
|
|
3846
3909
|
workspace,
|
|
@@ -3899,22 +3962,20 @@ function createSandboxRuntime(options) {
|
|
|
3899
3962
|
if (!ref) return null;
|
|
3900
3963
|
let hintedSandbox = null;
|
|
3901
3964
|
try {
|
|
3902
|
-
const sandboxCredentials = getVercelSandboxCredentials();
|
|
3903
3965
|
hintedSandbox = await withSandboxSpan("sandbox.get", "sandbox.get", {
|
|
3904
3966
|
"app.sandbox.reused": true,
|
|
3905
3967
|
"app.sandbox.source": "id_hint"
|
|
3906
|
-
}, async () =>
|
|
3968
|
+
}, async () => await getSandboxProvider().getSession({
|
|
3907
3969
|
name: ref.id,
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
})));
|
|
3970
|
+
onUnavailable: invalidateSession,
|
|
3971
|
+
scopeSignal: signal
|
|
3972
|
+
}));
|
|
3912
3973
|
} catch (error) {
|
|
3913
|
-
if (
|
|
3974
|
+
if (getSandboxProvider().errors.isMissing(error)) {
|
|
3914
3975
|
sandboxRef = void 0;
|
|
3915
3976
|
return null;
|
|
3916
3977
|
}
|
|
3917
|
-
if (
|
|
3978
|
+
if (getSandboxProvider().errors.isUnavailable(error)) {
|
|
3918
3979
|
invalidateSession();
|
|
3919
3980
|
throw error;
|
|
3920
3981
|
}
|
|
@@ -3931,7 +3992,7 @@ function createSandboxRuntime(options) {
|
|
|
3931
3992
|
});
|
|
3932
3993
|
return rememberSandbox(hintedSandbox, networkPolicyKey);
|
|
3933
3994
|
} catch (error) {
|
|
3934
|
-
if (
|
|
3995
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw error;
|
|
3935
3996
|
return failSetup(error);
|
|
3936
3997
|
}
|
|
3937
3998
|
};
|
|
@@ -3941,13 +4002,21 @@ function createSandboxRuntime(options) {
|
|
|
3941
4002
|
"app.sandbox.timeout_ms": timeoutMs,
|
|
3942
4003
|
"app.sandbox.runtime": SANDBOX_RUNTIME,
|
|
3943
4004
|
"app.sandbox.skills_count": availableSkills.length
|
|
3944
|
-
}, async () => {
|
|
4005
|
+
}, async (setSpanAttributes) => {
|
|
3945
4006
|
const cachedSandbox = await tryReuseCachedSandbox();
|
|
3946
|
-
if (cachedSandbox)
|
|
4007
|
+
if (cachedSandbox) {
|
|
4008
|
+
setSpanAttributes({ "app.sandbox.acquire.outcome": "memory" });
|
|
4009
|
+
return cachedSandbox;
|
|
4010
|
+
}
|
|
3947
4011
|
signal?.throwIfAborted();
|
|
3948
4012
|
const hintedSandbox = await tryRestoreHintedSandbox(signal);
|
|
3949
|
-
if (hintedSandbox)
|
|
3950
|
-
|
|
4013
|
+
if (hintedSandbox) {
|
|
4014
|
+
setSpanAttributes({ "app.sandbox.acquire.outcome": "resumed" });
|
|
4015
|
+
return hintedSandbox;
|
|
4016
|
+
}
|
|
4017
|
+
const createdSandbox = await createFreshSandbox(signal);
|
|
4018
|
+
setSpanAttributes({ "app.sandbox.acquire.outcome": "created" });
|
|
4019
|
+
return createdSandbox;
|
|
3951
4020
|
});
|
|
3952
4021
|
};
|
|
3953
4022
|
const getOrAcquireSandbox = async (signal) => {
|
|
@@ -4017,7 +4086,7 @@ function createSandboxRuntime(options) {
|
|
|
4017
4086
|
await session.extendTimeout(keepAliveMs);
|
|
4018
4087
|
});
|
|
4019
4088
|
} catch (error) {
|
|
4020
|
-
if (
|
|
4089
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw error;
|
|
4021
4090
|
}
|
|
4022
4091
|
};
|
|
4023
4092
|
const startKeepAlive = (session) => {
|
|
@@ -5172,27 +5241,21 @@ function createSandbox(options) {
|
|
|
5172
5241
|
const { bash: executeBash, sessionId: activeSessionId } = await runtime.tools(context.signal);
|
|
5173
5242
|
await clearEgressSignals(activeSessionId);
|
|
5174
5243
|
const result = await withSandboxToolSpan("bash", "process.exec", { "process.executable.name": "bash" }, async () => {
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
return response;
|
|
5191
|
-
} catch (error) {
|
|
5192
|
-
setSpanAttributes({ "error.type": error instanceof Error ? error.name : "sandbox_execute_error" });
|
|
5193
|
-
setSpanStatus("error");
|
|
5194
|
-
throw error;
|
|
5195
|
-
}
|
|
5244
|
+
const response = await executeBash({
|
|
5245
|
+
command,
|
|
5246
|
+
cwd,
|
|
5247
|
+
...env ? { env } : void 0,
|
|
5248
|
+
...timeoutMs ? { timeoutMs } : void 0,
|
|
5249
|
+
...context.signal ? { signal: context.signal } : void 0
|
|
5250
|
+
});
|
|
5251
|
+
setSpanAttributes({
|
|
5252
|
+
"process.exit.code": response.exitCode,
|
|
5253
|
+
"app.sandbox.stdout_bytes": Buffer.byteLength(response.stdout ?? "", "utf8"),
|
|
5254
|
+
"app.sandbox.stderr_bytes": Buffer.byteLength(response.stderr ?? "", "utf8"),
|
|
5255
|
+
...response.aborted ? { "error.type": "outcome_unknown" } : response.exitCode !== 0 ? { "error.type": "nonzero_exit" } : {}
|
|
5256
|
+
});
|
|
5257
|
+
setSpanStatus(response.exitCode === 0 ? "ok" : "error");
|
|
5258
|
+
return response;
|
|
5196
5259
|
});
|
|
5197
5260
|
const { authRequired, permissionDenied } = await consumeEgressSignals(activeSessionId);
|
|
5198
5261
|
return formatSandboxCommandResult({
|
|
@@ -5386,8 +5449,8 @@ function createSandbox(options) {
|
|
|
5386
5449
|
} catch (error) {
|
|
5387
5450
|
params.signal?.throwIfAborted();
|
|
5388
5451
|
if (getWorkspaceSnapshotNotReadyError(error)) return createWorkspaceSnapshotNotReadyToolResult(error);
|
|
5389
|
-
if (
|
|
5390
|
-
if (
|
|
5452
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw createSandboxUnavailableToolError(params.toolName, error);
|
|
5453
|
+
if (getSandboxProvider().errors.isCommandStreamInterrupted(error)) throw new ToolInputError(`The sandbox command stream was interrupted during ${params.toolName}, so the operation did not complete reliably. It may have produced side effects; inspect the workspace or retry only if it is safe.`, { cause: error });
|
|
5391
5454
|
throw error;
|
|
5392
5455
|
}
|
|
5393
5456
|
throw new Error(`unsupported sandbox tool: ${params.toolName}`);
|
|
@@ -5398,7 +5461,7 @@ function createSandbox(options) {
|
|
|
5398
5461
|
} catch (error) {
|
|
5399
5462
|
const notReady = getWorkspaceSnapshotNotReadyError(error);
|
|
5400
5463
|
if (notReady) throw new ToolInputError(workspaceSnapshotNotReadyUserMessage(notReady), { cause: notReady });
|
|
5401
|
-
if (
|
|
5464
|
+
if (getSandboxProvider().errors.isUnavailable(error)) throw createSandboxUnavailableToolError(operation, error);
|
|
5402
5465
|
throw error;
|
|
5403
5466
|
}
|
|
5404
5467
|
};
|
|
@@ -5664,7 +5727,7 @@ function upstreamPermissionDeniedText(value) {
|
|
|
5664
5727
|
`Status: ${status}`,
|
|
5665
5728
|
...command ? [`Command: ${command}`] : [],
|
|
5666
5729
|
"",
|
|
5667
|
-
"
|
|
5730
|
+
"The runtime had a credential lease for this grant and forwarded the request. Do not diagnose this as a missing user token or a local runtime block.",
|
|
5668
5731
|
"Read the provider's error in the command output before you choose a cause. A provider can reject a request because of permissions, installation scope, SSO, or account access. It can also reject a valid credential because of the target's state, a rate limit, or another provider rule.",
|
|
5669
5732
|
...stderr ? ["", `stderr:\n${stderr}`] : [],
|
|
5670
5733
|
...stdout ? ["", `stdout:\n${stdout}`] : []
|
|
@@ -6068,7 +6131,7 @@ var McpToolManager = class {
|
|
|
6068
6131
|
async clientForTool(plugin, client, toolName) {
|
|
6069
6132
|
const provider = plugin.manifest.name;
|
|
6070
6133
|
if (!this.serviceAccountProviders.has(provider) || serviceAccountAllows(plugin.manifest, { tool: toolName })) return client;
|
|
6071
|
-
if (serviceAccountOnly(plugin.manifest)) throw new McpToolError(`${plugin.manifest.displayName} tool ${toolName} is not available:
|
|
6134
|
+
if (serviceAccountOnly(plugin.manifest)) throw new McpToolError(`${plugin.manifest.displayName} tool ${toolName} is not available: the shared ${plugin.manifest.displayName} account cannot use it`);
|
|
6072
6135
|
const existing = this.actorClientsByProvider.get(provider);
|
|
6073
6136
|
if (existing) return existing;
|
|
6074
6137
|
const actorClient = await this.newClient(plugin);
|
|
@@ -6646,7 +6709,7 @@ function createLoadSkillTool(availableSkills, options) {
|
|
|
6646
6709
|
readOnlyHint: false
|
|
6647
6710
|
},
|
|
6648
6711
|
description: "Load a skill by name for this turn. The result includes working_directory; resolve skill paths there and run skill-owned bash commands from there or with absolute paths. When the skill instructions name an MCP provider, use searchMcpTools before callMcpTool. Use when a request clearly matches a known skill.",
|
|
6649
|
-
inputSchema: z.object({ skill_name: z.string().min(1).describe("Skill name to load, without the leading
|
|
6712
|
+
inputSchema: z.object({ skill_name: z.string().min(1).describe("Skill name to load, without the leading `$`.") }),
|
|
6650
6713
|
outputSchema: juniorToolOutputSchema,
|
|
6651
6714
|
execute: async ({ skill_name }) => {
|
|
6652
6715
|
const result = await loadSkillFromHost(availableSkills, skill_name);
|
|
@@ -6795,10 +6858,10 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
6795
6858
|
openWorldHint: true,
|
|
6796
6859
|
readOnlyHint: true
|
|
6797
6860
|
},
|
|
6798
|
-
description: "List or search MCP providers and active MCP tools. When provider is supplied and not yet active,
|
|
6861
|
+
description: "List or search MCP providers and active MCP tools. When provider is supplied and not yet active, the runtime connects to it on demand and returns tool descriptors including schemas. Without provider, returns active tools plus matching configured providers without connecting. Use when choosing a provider tool or when callMcpTool arguments are unclear.",
|
|
6799
6862
|
inputSchema: z.object({
|
|
6800
6863
|
query: z.string().min(1).describe("Optional search terms describing the MCP tool or arguments needed.").optional(),
|
|
6801
|
-
provider: z.string().min(1).describe("Optional provider name to list or search within. If configured but not yet connected,
|
|
6864
|
+
provider: z.string().min(1).describe("Optional provider name to list or search within. If configured but not yet connected, the runtime activates it on demand.").optional(),
|
|
6802
6865
|
intent: z.string().min(1).describe("Set this when you pass provider. A short purpose to show the user if this call needs them to connect their account, for example \"search Notion for the Q3 offsite doc\".").optional(),
|
|
6803
6866
|
max_results: z.number().int().min(1).max(MAX_RESULTS$2).describe("Maximum matching tool descriptors to return.").optional()
|
|
6804
6867
|
}).strict(),
|
|
@@ -7628,15 +7691,7 @@ const searchedResourceTypeSchema = z.object({
|
|
|
7628
7691
|
identifierFormat: z.string().optional(),
|
|
7629
7692
|
supportedEvents: z.array(z.string()),
|
|
7630
7693
|
suggestedEvents: z.array(z.string()).optional(),
|
|
7631
|
-
matchFields: z.record(z.string(),
|
|
7632
|
-
kind: z.enum([
|
|
7633
|
-
"boolean",
|
|
7634
|
-
"string",
|
|
7635
|
-
"number"
|
|
7636
|
-
]),
|
|
7637
|
-
description: z.string(),
|
|
7638
|
-
enum: z.array(z.string()).optional()
|
|
7639
|
-
}).strict()).optional()
|
|
7694
|
+
matchFields: z.record(z.string(), eventMatchFieldSchema).optional()
|
|
7640
7695
|
}).strict();
|
|
7641
7696
|
const outputSchema$4 = juniorToolOutputSchema.extend({
|
|
7642
7697
|
query: z.string().nullable(),
|
|
@@ -7666,7 +7721,7 @@ function createSearchEventTypesTool(catalog) {
|
|
|
7666
7721
|
openWorldHint: false,
|
|
7667
7722
|
readOnlyHint: true
|
|
7668
7723
|
},
|
|
7669
|
-
description: "Search the event types currently enabled without creating anything. Includes plugin resources and core Workspace snapshot events. Use watchEvents for temporary updates in the current conversation; use createEventAutomation for durable automation. This tool does not watch a resource, create an automation, or list concrete resources.",
|
|
7724
|
+
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. Use watchEvents for temporary updates in the current conversation; use createEventAutomation for durable automation. This tool does not watch a resource, create an automation, or list concrete resources.",
|
|
7670
7725
|
inputSchema: z.object({
|
|
7671
7726
|
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(),
|
|
7672
7727
|
namespace: eventNamespaceSchema(catalog).nullable().describe("Optional enabled plugin namespace to search within.").optional(),
|
|
@@ -7801,15 +7856,7 @@ function inputSchema(catalog) {
|
|
|
7801
7856
|
match: registeredEventMatchSchema(),
|
|
7802
7857
|
intent: z.string().trim().min(1).max(4e3).describe("Concise reason this conversation wants these events, used when an event arrives."),
|
|
7803
7858
|
ttlMs: z.coerce.number().describe("How long to keep the subscription active. Defaults to 14 days and must not exceed 30 days.").optional()
|
|
7804
|
-
}).strict()
|
|
7805
|
-
subscription.events.forEach((eventType, index) => {
|
|
7806
|
-
if (!pluginSupportsEvent(catalog, subscription.namespace, subscription.resourceType, eventType)) context.addIssue({
|
|
7807
|
-
code: "custom",
|
|
7808
|
-
message: `Resource type "${subscription.namespace}:${subscription.resourceType}" does not support event "${eventType}".`,
|
|
7809
|
-
path: ["events", index]
|
|
7810
|
-
});
|
|
7811
|
-
});
|
|
7812
|
-
});
|
|
7859
|
+
}).strict();
|
|
7813
7860
|
}
|
|
7814
7861
|
const stopWatchingActionSchema = z.object({
|
|
7815
7862
|
execution_tool: z.literal("executeTool"),
|
|
@@ -7854,17 +7901,17 @@ function createWatchEventsTool(context, catalog) {
|
|
|
7854
7901
|
inputSchema: inputSchema(catalog),
|
|
7855
7902
|
outputSchema: outputSchema$2,
|
|
7856
7903
|
async execute(input) {
|
|
7857
|
-
|
|
7858
|
-
if (
|
|
7904
|
+
const unavailable = eventWatchUnavailable(catalog, input.namespace, input.resourceType);
|
|
7905
|
+
if (unavailable) throw new ToolInputError(unavailable);
|
|
7859
7906
|
const events = cleanStrings(input.events);
|
|
7860
|
-
for (const eventType of events) if (!pluginSupportsEvent(catalog, input.namespace, input.resourceType, eventType)) throw new ToolInputError(`Resource type "${input.namespace}:${input.resourceType}" does not support event "${eventType}".`);
|
|
7861
7907
|
const intent = input.intent.trim();
|
|
7862
7908
|
if (!intent) throw new ToolInputError("intent is required");
|
|
7863
|
-
const match =
|
|
7909
|
+
const match = requireValidEventTrigger(catalog, {
|
|
7910
|
+
events,
|
|
7864
7911
|
match: input.match,
|
|
7865
7912
|
namespace: input.namespace,
|
|
7866
7913
|
resourceType: input.resourceType
|
|
7867
|
-
});
|
|
7914
|
+
}, "watch");
|
|
7868
7915
|
const nowMs = Date.now();
|
|
7869
7916
|
const subscription = await createWatch({
|
|
7870
7917
|
conversationId: context.conversationId,
|
|
@@ -7988,7 +8035,8 @@ const compactEventAutomationResultSchema = z.object({
|
|
|
7988
8035
|
label: z.string().min(1),
|
|
7989
8036
|
events: z.array(z.string().min(1)).min(1),
|
|
7990
8037
|
match: z.record(z.string(), z.unknown()).optional(),
|
|
7991
|
-
available: z.boolean()
|
|
8038
|
+
available: z.boolean(),
|
|
8039
|
+
problems: z.array(z.string().min(1)).min(1).optional()
|
|
7992
8040
|
}).strict(),
|
|
7993
8041
|
credentialMode: z.enum(["system", "creator"]),
|
|
7994
8042
|
isCreator: z.boolean(),
|
|
@@ -8026,15 +8074,9 @@ function registeredEventAutomationTriggerSchema(catalog) {
|
|
|
8026
8074
|
match: registeredEventMatchSchema()
|
|
8027
8075
|
}).strict();
|
|
8028
8076
|
}
|
|
8029
|
-
/** Reject an event-automation trigger that
|
|
8077
|
+
/** Reject an event-automation trigger that cannot work with the enabled plugins. */
|
|
8030
8078
|
function requireSupportedEventAutomationTrigger(catalog, trigger) {
|
|
8031
|
-
|
|
8032
|
-
for (const eventType of trigger.events) if (!pluginSupportsEvent(plugins, trigger.namespace, trigger.resourceType, eventType)) throw new ToolInputError(`Resource type "${trigger.namespace}:${trigger.resourceType}" does not support event "${eventType}".`);
|
|
8033
|
-
return requireSupportedEventMatch(plugins, {
|
|
8034
|
-
match: trigger.match,
|
|
8035
|
-
namespace: trigger.namespace,
|
|
8036
|
-
resourceType: trigger.resourceType
|
|
8037
|
-
});
|
|
8079
|
+
return requireValidEventTrigger(automationEventCatalog(catalog), trigger, "event_automation");
|
|
8038
8080
|
}
|
|
8039
8081
|
/** Require the active Slack authority used for event-automation management. */
|
|
8040
8082
|
function requireEventAutomationSlackContext(context) {
|
|
@@ -8069,12 +8111,18 @@ async function writableEventAutomation(context, id) {
|
|
|
8069
8111
|
if (!task || task.status === "deleted" || !eventAutomationIsWritableFrom(task, destination)) throw new ToolInputError("Event automation was not found.");
|
|
8070
8112
|
return task;
|
|
8071
8113
|
}
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8114
|
+
/**
|
|
8115
|
+
* Describe a saved trigger with the enabled plugins. Its problems say why it
|
|
8116
|
+
* cannot work: a plugin can remove or rename a resource type, event, or filter
|
|
8117
|
+
* after the trigger was saved. Resource types with `automation: false` never
|
|
8118
|
+
* dispatch event automations.
|
|
8119
|
+
*/
|
|
8120
|
+
function describeEventAutomationTrigger(trigger, catalog) {
|
|
8121
|
+
return describeRegisteredEventTrigger(automationEventCatalog(catalog), trigger);
|
|
8075
8122
|
}
|
|
8076
8123
|
/** Project an event automation into the bounded tool-result shape. */
|
|
8077
8124
|
function compactEventAutomation(task, catalog, requesterSlackUserId) {
|
|
8125
|
+
const { problems } = describeEventAutomationTrigger(task.trigger, catalog);
|
|
8078
8126
|
return compactEventAutomationResultSchema.parse({
|
|
8079
8127
|
id: task.id,
|
|
8080
8128
|
status: task.status,
|
|
@@ -8089,7 +8137,8 @@ function compactEventAutomation(task, catalog, requesterSlackUserId) {
|
|
|
8089
8137
|
label: task.trigger.label,
|
|
8090
8138
|
events: task.trigger.events,
|
|
8091
8139
|
...task.trigger.match ? { match: task.trigger.match } : void 0,
|
|
8092
|
-
available:
|
|
8140
|
+
available: problems.length === 0,
|
|
8141
|
+
...problems.length > 0 ? { problems } : void 0
|
|
8093
8142
|
},
|
|
8094
8143
|
credentialMode: task.credentialMode,
|
|
8095
8144
|
isCreator: task.createdBy.slackUserId === requesterSlackUserId,
|
|
@@ -8109,7 +8158,7 @@ function compactEventAutomation(task, catalog, requesterSlackUserId) {
|
|
|
8109
8158
|
/** Return the standard successful event-automation tool result. */
|
|
8110
8159
|
async function eventAutomationToolResult(conversationId, task, catalog, requesterSlackUserId) {
|
|
8111
8160
|
const automation = compactEventAutomation(task, catalog, requesterSlackUserId);
|
|
8112
|
-
const
|
|
8161
|
+
const description = describeEventAutomationTrigger(task.trigger, catalog);
|
|
8113
8162
|
const title = automation.title ?? fallbackShortTitle(task.task.text, "Event automation");
|
|
8114
8163
|
return {
|
|
8115
8164
|
automation,
|
|
@@ -8121,13 +8170,9 @@ async function eventAutomationToolResult(conversationId, task, catalog, requeste
|
|
|
8121
8170
|
title,
|
|
8122
8171
|
url: automation.dashboardUrl,
|
|
8123
8172
|
description: task.task.text,
|
|
8124
|
-
status:
|
|
8125
|
-
trigger:
|
|
8126
|
-
|
|
8127
|
-
task.trigger.events.join(", "),
|
|
8128
|
-
...filters
|
|
8129
|
-
].join(" · "),
|
|
8130
|
-
warning: !automation.trigger.available ? "Trigger unavailable. This automation cannot receive events." : void 0
|
|
8173
|
+
status: description.problems.length === 0 ? "ready" : "unavailable",
|
|
8174
|
+
trigger: eventTriggerText(task.trigger.label, description),
|
|
8175
|
+
warning: description.problems.length > 0 ? ["Trigger unavailable.", ...description.problems].join(" ") : void 0
|
|
8131
8176
|
}])
|
|
8132
8177
|
};
|
|
8133
8178
|
}
|
|
@@ -8155,7 +8200,7 @@ function createEventAutomationTool(context, catalog) {
|
|
|
8155
8200
|
readOnlyHint: false
|
|
8156
8201
|
},
|
|
8157
8202
|
executionMode: "sequential",
|
|
8158
|
-
description: "Create a durable event automation in the active Slack channel or DM, never a thread. It executes the supplied instruction for every matching event. Use for whenever-this-happens-do-X automation; ordinary watch, notify, or tell-me-when requests use watchEvents instead. The automation may use the creator's connected credentials. Prefer a subscribable tool result when available.",
|
|
8203
|
+
description: "Create a durable event automation in the active Slack channel or DM, never a thread. It executes the supplied instruction for every matching event. Use only when the user explicitly asks for an event automation or durable whenever-this-happens-do-X automation; ordinary watch, notify, or tell-me-when requests use watchEvents instead. When the resource and events are known, create it without redundant confirmation. The automation may use the creator's connected credentials. Prefer a subscribable tool result when available.",
|
|
8159
8204
|
inputSchema: z.object({
|
|
8160
8205
|
instruction: automationInstructionToolSchema,
|
|
8161
8206
|
title: z.string().trim().min(1).max(60).nullable().describe("Optional short display title. Omit or use null to generate one from the task instruction.").optional(),
|
|
@@ -8269,7 +8314,7 @@ function createListEventAutomationsTool(context, catalog) {
|
|
|
8269
8314
|
openWorldHint: false,
|
|
8270
8315
|
readOnlyHint: true
|
|
8271
8316
|
},
|
|
8272
|
-
description: "List event automations for the current destination. Each result says whether the requester is the creator
|
|
8317
|
+
description: "List event automations for the current destination, not one thread. Each result says whether the requester is the creator (isCreator); only the creator can change its credential use. Warn when trigger.available is false and explain trigger.problems: the automation stays stored, but a plugin no longer supports its resource type, an event, or a filter. Update the trigger to fix it. Public automations can also be updated or deleted by id from another destination in the same workspace.",
|
|
8273
8318
|
inputSchema: z.object({}).strict(),
|
|
8274
8319
|
outputSchema: eventAutomationListToolResultSchema,
|
|
8275
8320
|
async execute() {
|
|
@@ -8724,7 +8769,7 @@ function createSlackScheduleCreateAutomationTool(context) {
|
|
|
8724
8769
|
openWorldHint: true,
|
|
8725
8770
|
readOnlyHint: false
|
|
8726
8771
|
},
|
|
8727
|
-
description: "Create a one-time or recurring
|
|
8772
|
+
description: "Create a one-time or recurring scheduled task in the active Slack channel. Store the requested future work; do not perform it or check its service access now unless the user also asks for that.",
|
|
8728
8773
|
executionMode: "sequential",
|
|
8729
8774
|
inputSchema: z.object({
|
|
8730
8775
|
instruction: automationInstructionToolSchema,
|
|
@@ -8822,7 +8867,7 @@ function createSlackScheduleDeleteAutomationTool(context) {
|
|
|
8822
8867
|
openWorldHint: false,
|
|
8823
8868
|
readOnlyHint: false
|
|
8824
8869
|
},
|
|
8825
|
-
description: "Delete one scheduled
|
|
8870
|
+
description: "Delete one scheduled task from the active Slack conversation. Use only task IDs returned for this conversation. Do not delete schedules from threads, other channels, or another user's DM.",
|
|
8826
8871
|
executionMode: "sequential",
|
|
8827
8872
|
inputSchema: z.object({ automationId: z.string().min(1).describe("ID of the task to delete. Must be from this active Slack conversation.") }),
|
|
8828
8873
|
outputSchema: scheduleAutomationToolResultSchema.extend({ removedCards: z.array(removedCardSchema) }),
|
|
@@ -8953,7 +8998,7 @@ function createSlackScheduleRunAutomationNowTool(context) {
|
|
|
8953
8998
|
openWorldHint: true,
|
|
8954
8999
|
readOnlyHint: false
|
|
8955
9000
|
},
|
|
8956
|
-
description: "Queue an existing active scheduled
|
|
9001
|
+
description: "Queue an existing active scheduled task to run as soon as possible, without changing its cadence. Use when the user asks to run an existing scheduled automation now. Use only task IDs returned for this conversation.",
|
|
8957
9002
|
executionMode: "sequential",
|
|
8958
9003
|
inputSchema: z.object({ automationId: z.string().min(1).describe("ID of the active task to run now. Must be from this active Slack conversation.") }),
|
|
8959
9004
|
outputSchema: scheduleAutomationToolResultSchema,
|
|
@@ -9279,7 +9324,7 @@ async function joinPublicChannelForRead(args) {
|
|
|
9279
9324
|
}
|
|
9280
9325
|
}
|
|
9281
9326
|
/** Model-facing Slack channel id or known channel name parameter. */
|
|
9282
|
-
const slackChannelRefParam = z.string().trim().min(1).max(160).describe("Slack channel id (`C123`), mention (`<#C123>` / `<#C123|name>`),
|
|
9327
|
+
const slackChannelRefParam = z.string().trim().min(1).max(160).describe("Slack channel id (`C123`), mention (`<#C123>` / `<#C123|name>`), Slack reference (`slack:C123`), or a channel name you already know in this workspace.");
|
|
9283
9328
|
/**
|
|
9284
9329
|
* Resolve a channel reference from a tool param value.
|
|
9285
9330
|
*
|
|
@@ -9288,7 +9333,7 @@ const slackChannelRefParam = z.string().trim().min(1).max(160).describe("Slack c
|
|
|
9288
9333
|
*/
|
|
9289
9334
|
async function resolveSlackChannelRef(input) {
|
|
9290
9335
|
const trimmed = input.value.trim();
|
|
9291
|
-
if (!trimmed) throw new ToolInputError(`Invalid \`${input.field}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a
|
|
9336
|
+
if (!trimmed) throw new ToolInputError(`Invalid \`${input.field}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a Slack reference (\`slack:C123\`), or a channel name you already know.`);
|
|
9292
9337
|
const channelId = parseSlackChannelReferenceId(trimmed);
|
|
9293
9338
|
if (channelId) return { channelId };
|
|
9294
9339
|
const known = await getConversationStore().findSlackDestinationByName({
|
|
@@ -9300,7 +9345,7 @@ async function resolveSlackChannelRef(input) {
|
|
|
9300
9345
|
channelId: knownChannelId,
|
|
9301
9346
|
...known.channelName ? { channelName: known.channelName } : void 0
|
|
9302
9347
|
};
|
|
9303
|
-
throw new ToolInputError(`Unknown \`${input.field}\` \`${trimmed}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a link, or a channel name
|
|
9348
|
+
throw new ToolInputError(`Unknown \`${input.field}\` \`${trimmed}\`. Use a channel id (\`C123\`), a Slack mention (\`<#C123>\`), a link, or a channel name you already saw in this workspace. Public search can discover channels; plain names are not scanned from Slack.`);
|
|
9304
9349
|
}
|
|
9305
9350
|
/**
|
|
9306
9351
|
* Resolve an optional channel reference, falling back to the active channel.
|
|
@@ -9607,7 +9652,7 @@ function createSlackConversationBriefSearchPort(teamId) {
|
|
|
9607
9652
|
/** Deferred tool catalog source for retained Junior conversations. */
|
|
9608
9653
|
const CONVERSATIONS_TOOL_SOURCE = {
|
|
9609
9654
|
id: "conversations",
|
|
9610
|
-
description: "Search messages and events in retained
|
|
9655
|
+
description: "Search messages and events in retained conversations."
|
|
9611
9656
|
};
|
|
9612
9657
|
// src/chat/slack/tools/conversation-message-search.ts
|
|
9613
9658
|
const DEFAULT_LIMIT$3 = 20;
|
|
@@ -13351,19 +13396,33 @@ function createWebSearchTool(modelId, override) {
|
|
|
13351
13396
|
const controller = new AbortController();
|
|
13352
13397
|
const credential = await resolveGatewayCredential();
|
|
13353
13398
|
const provider = createGatewayProvider(credential ? { apiKey: credential.token } : {});
|
|
13354
|
-
const results = parseSearchResults((await
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13399
|
+
const results = parseSearchResults((await withSpan(`chat ${modelId}`, "gen_ai.chat", {}, async (setSpanAttributes) => {
|
|
13400
|
+
const response = await withTimeout(generateText({
|
|
13401
|
+
model: provider.chat(modelId),
|
|
13402
|
+
prompt: query,
|
|
13403
|
+
tools: { [SEARCH_TOOL_NAME]: provider.tools.parallelSearch({
|
|
13404
|
+
mode: "agentic",
|
|
13405
|
+
maxResults
|
|
13406
|
+
}) },
|
|
13407
|
+
toolChoice: {
|
|
13408
|
+
type: "tool",
|
|
13409
|
+
toolName: SEARCH_TOOL_NAME
|
|
13410
|
+
},
|
|
13411
|
+
abortSignal: controller.signal
|
|
13412
|
+
}), SEARCH_TIMEOUT_MS, "webSearch", { onTimeout: () => controller.abort() });
|
|
13413
|
+
setSpanAttributes({
|
|
13414
|
+
"gen_ai.response.finish_reasons": [response.finishReason],
|
|
13415
|
+
...extractGenAiUsageAttributes(response.usage)
|
|
13416
|
+
});
|
|
13417
|
+
return response;
|
|
13418
|
+
}, {
|
|
13419
|
+
"gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
|
|
13420
|
+
"gen_ai.operation.name": "chat",
|
|
13421
|
+
"gen_ai.request.model": modelId,
|
|
13422
|
+
"server.address": GEN_AI_SERVER_ADDRESS,
|
|
13423
|
+
"server.port": 443,
|
|
13424
|
+
"gen_ai.provider.auth_mode": credential?.mode ?? "api_key"
|
|
13425
|
+
})).toolResults, maxResults);
|
|
13367
13426
|
return {
|
|
13368
13427
|
model: modelId,
|
|
13369
13428
|
query,
|
|
@@ -15399,7 +15458,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
15399
15458
|
const authorizationRequest = {
|
|
15400
15459
|
authorizationUrl: authSession.authorizationUrl,
|
|
15401
15460
|
label: `Connect your ${providerLabel} account`,
|
|
15402
|
-
completionText: "Once you've authorized,
|
|
15461
|
+
completionText: "Once you've authorized, I'll continue automatically."
|
|
15403
15462
|
};
|
|
15404
15463
|
if (!await deliverOAuthAuthorization(authorizationRequest, {
|
|
15405
15464
|
authorization: input.authorization,
|
|
@@ -15511,7 +15570,7 @@ const GUARDIAN_RULE_IDS = ["none", ...Object.keys(GUARDIAN_BLOCK_RULES)];
|
|
|
15511
15570
|
function renderRules(decision) {
|
|
15512
15571
|
return Object.entries(GUARDIAN_BLOCK_RULES).filter(([, rule]) => rule.decision === decision).map(([id, rule]) => `- \`${id}\`: ${rule.description}`).join("\n");
|
|
15513
15572
|
}
|
|
15514
|
-
const GUARDIAN_ACTION_POLICY = `You are judging one planned
|
|
15573
|
+
const GUARDIAN_ACTION_POLICY = `You are judging one planned action of the assistant agent.
|
|
15515
15574
|
Assess the exact action's intrinsic risk and whether the user's intent authorizes its target and side effects. Then name the one block rule that the action matches, or \`none\`. Actions are allowed by default. Your primary objective is to prevent irreversible damage to the user or organization while allowing ordinary, proportionate work without interruption.
|
|
15516
15575
|
|
|
15517
15576
|
# Evidence Handling
|
|
@@ -15560,7 +15619,7 @@ ${renderRules("deny")}
|
|
|
15560
15619
|
- Whether the work is correct, complete, well proven, or well styled is not your concern, and neither is whether the agent checked enough before it acted. Posting results that the user or the automation instruction asked for matches no rule.
|
|
15561
15620
|
- Content that the current actor's request is about, such as the conversation or examples they pointed to, is part of the requested work. Using it in the requested deliverable at an authorized destination is not data exposure, unless it includes secrets, credentials, or private data about other people.
|
|
15562
15621
|
- Ordinary product context such as internal system names, repository names, or workflow descriptions is not private organization data, including on an authorized public destination.
|
|
15563
|
-
- The active
|
|
15622
|
+
- The active conversation, where the assistant works with the user, is not an untrusted destination merely because it is a public or multi-user channel.
|
|
15564
15623
|
- A user-requested read, query, or upload to a trusted destination is not data exposure. Using an existing credential to authenticate a user-requested action is not credential probing.
|
|
15565
15624
|
- A tool that is external, multi-field, open-world, uses connected credentials, has plugin or catalog identity, or carries a destructive annotation does not match a rule by those facts alone. Judge actual side effects, not tool names or annotations.
|
|
15566
15625
|
- For a scheduled automation or event automation, a request by the current actor for scoped work that needs their connected service access authorizes routine service-native reads and posting the requested result to the task's stored Slack destination. It does not authorize exposing credential values, broad data dumps, or delivery to another destination.
|
|
@@ -15672,7 +15731,6 @@ function createGuardianActionReviewer(options) {
|
|
|
15672
15731
|
system: GUARDIAN_ACTION_POLICY,
|
|
15673
15732
|
prompt: guardianPrompt(proposal),
|
|
15674
15733
|
maxTokens: GUARDIAN_REVIEW_MAX_TOKENS,
|
|
15675
|
-
recordTelemetryPayloads: false,
|
|
15676
15734
|
temperature: 0,
|
|
15677
15735
|
promptName: "junior.guardian_action_review",
|
|
15678
15736
|
signal,
|
|
@@ -18262,7 +18320,7 @@ function createAgentRunner(execute, options) {
|
|
|
18262
18320
|
} } : void 0
|
|
18263
18321
|
};
|
|
18264
18322
|
if (run.instruction.storedAttachments?.length) {
|
|
18265
|
-
const { loadInputImages } = await import("./images-
|
|
18323
|
+
const { loadInputImages } = await import("./images-B2yA3HWE.js").then((n) => n.n);
|
|
18266
18324
|
const storage = nextRun.environment?.attachmentStorage;
|
|
18267
18325
|
if (!storage) throw new Error("Attachment storage is unavailable.");
|
|
18268
18326
|
nextRun.instruction = {
|
|
@@ -18277,4 +18335,4 @@ function createAgentRunner(execute, options) {
|
|
|
18277
18335
|
return await execute(nextRun, streamFn);
|
|
18278
18336
|
} };
|
|
18279
18337
|
}
|
|
18280
|
-
export {
|
|
18338
|
+
export { actorFromRun as $, listThreadReplies as A, stopChildAgentsOf as B, requestAttachmentDeletion as C, resolveSlackChannelIdFromMessage as D, readSlackRawMessageContext as E, AutomationEditError as F, listUnreportedSiblingAgents as G, recordSubagentEnded as H, describeEventAutomationTrigger as I, processWorkspaceSnapshotJob as J, conversationSubtree as K, effectiveTaskOutcomes as L, logScheduledAutomationRunSkipped as M, scheduledAutomationRunAttributes as N, resolveSlackChannelIdFromThreadId as O, editEventAutomation as P, RetryableDeliveryError as Q, resolveTaskOutcomes as R, readLiveAttachment as S, parseSlackThreadId as T, recordSubagentStarted as U, stopConversationSession as V, listChildAgents as W, buildSteeringPiMessage as X, ingestEvent as Y, withoutSavedSteeringMessages as Z, unpublishedArtifactHeaders as _, finalizeMcpAuthorization as a, renderBlockText as b, deleteMcpServerSessionId as c, getMcpStoredOAuthCredentials as d, toolInvocationDestination as et, putMcpStoredOAuthCredentials as f, readPublicArtifact as g, publicArtifactHeaders as h, buildAuthPauseResponse as i, editScheduledAutomation as j, getConversationInfo as k, deleteMcpStoredOAuthCredentials as l, readStats as m, executeAgentRun as n, shouldEmitDevAgentTrace as nt, deleteMcpAuthSession as o, latestProgressStatus as p, conversationSubtreeColumns as q, createContextCompactor as r, deleteMcpAuthSessionsForUserProvider as s, createAgentRunner as t, readBlockedReport as tt, getMcpAuthSession as u, lookupSlackUserProfile as v, storeAttachment as w, collectAttachmentGarbage as x, renderAttachmentText as y, listOwnedWatches as z };
|