@sentry/junior 0.110.0 → 0.112.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/{agent-hooks-ELT4ODFF.js → agent-hooks-6MVTPKP4.js} +8 -8
  2. package/dist/api/people/profile.d.ts +1 -0
  3. package/dist/api/schema/person.d.ts +2 -0
  4. package/dist/api/schema.js +1 -1
  5. package/dist/api.js +13 -12
  6. package/dist/app.js +551 -401
  7. package/dist/build/virtual-config.d.ts +2 -0
  8. package/dist/{catalog-runtime-4GI22PXK.js → catalog-runtime-UEO25P2J.js} +5 -5
  9. package/dist/chat/agent/request.d.ts +3 -6
  10. package/dist/chat/agent/sandbox.d.ts +36 -11
  11. package/dist/chat/agent/tools.d.ts +5 -8
  12. package/dist/chat/config.d.ts +8 -1
  13. package/dist/chat/pi/sdk.d.ts +1 -1
  14. package/dist/chat/plugins/agent-hooks.d.ts +2 -2
  15. package/dist/chat/runtime/agent-continue-runner.d.ts +7 -3
  16. package/dist/chat/runtime/agent-run-outcome.d.ts +1 -0
  17. package/dist/chat/runtime/slack-runtime.d.ts +1 -2
  18. package/dist/chat/runtime/thread-state.d.ts +3 -7
  19. package/dist/chat/runtime/turn-preparation.d.ts +2 -2
  20. package/dist/chat/sandbox/command-result.d.ts +91 -0
  21. package/dist/chat/sandbox/errors.d.ts +3 -1
  22. package/dist/chat/sandbox/ref.d.ts +5 -0
  23. package/dist/chat/sandbox/sandbox.d.ts +19 -46
  24. package/dist/chat/sandbox/session.d.ts +16 -20
  25. package/dist/chat/sandbox/skill-sync.d.ts +2 -2
  26. package/dist/chat/sandbox/workspace.d.ts +14 -12
  27. package/dist/chat/services/auth-pause-response.d.ts +1 -1
  28. package/dist/chat/services/auth-pause.d.ts +2 -1
  29. package/dist/chat/services/mcp-auth-orchestration.d.ts +1 -1
  30. package/dist/chat/services/plugin-auth-orchestration.d.ts +2 -1
  31. package/dist/chat/services/turn-result.d.ts +3 -4
  32. package/dist/chat/task-execution/slack-work.d.ts +3 -1
  33. package/dist/chat/task-execution/state.d.ts +75 -22
  34. package/dist/chat/task-execution/store.d.ts +34 -3
  35. package/dist/chat/task-execution/worker.d.ts +0 -1
  36. package/dist/chat/tool-support/normalize-result.d.ts +2 -2
  37. package/dist/chat/tool-support/pi-tool-adapter.d.ts +2 -2
  38. package/dist/chat/tool-support/structured-result.d.ts +1 -2
  39. package/dist/chat/tools/resource-events.d.ts +3 -129
  40. package/dist/chat/tools/sandbox/file-uploads.d.ts +1 -1
  41. package/dist/chat/{runtime → tools/sandbox}/generated-artifacts.d.ts +3 -3
  42. package/dist/chat/tools/types.d.ts +1 -1
  43. package/dist/chat/tools/web/fetch-content.d.ts +5 -0
  44. package/dist/chat/tools/web/image-generate.d.ts +2 -1
  45. package/dist/chat/tools/web/search.d.ts +1 -1
  46. package/dist/{chunk-3S7YYHBI.js → chunk-2FJ6WEYV.js} +1 -1
  47. package/dist/{chunk-Y5FK3CNG.js → chunk-4EJO4HIC.js} +1 -1
  48. package/dist/{chunk-W6RJZG7F.js → chunk-66IP6WED.js} +306 -31
  49. package/dist/{chunk-W75ZPAGG.js → chunk-AU2JVUDF.js} +1 -1
  50. package/dist/{chunk-3UBQI73J.js → chunk-AWNDKI5K.js} +7 -8
  51. package/dist/{chunk-IYKPU7H6.js → chunk-CSS7JHEM.js} +1 -1
  52. package/dist/{chunk-SBOBTS27.js → chunk-GJG67YFS.js} +2 -2
  53. package/dist/{chunk-RHHRKSPI.js → chunk-GR4IB6OQ.js} +8729 -9024
  54. package/dist/{chunk-ZKIOWEFL.js → chunk-IV2O4HQJ.js} +1 -1
  55. package/dist/{chunk-FPK7XY3F.js → chunk-JE23YR3X.js} +1 -0
  56. package/dist/{chunk-L5XQPJ7T.js → chunk-NDQL4ESR.js} +2 -2
  57. package/dist/{chunk-WNOVRQ67.js → chunk-PK4ETCUQ.js} +46 -18
  58. package/dist/{chunk-4QU44P7Q.js → chunk-QIALGHRN.js} +2 -2
  59. package/dist/{chunk-C5XAFTHY.js → chunk-SKEMI4IF.js} +16 -13
  60. package/dist/{chunk-Y3H2DN6F.js → chunk-TZU3R5OC.js} +1 -1
  61. package/dist/{chunk-2T7TIEXI.js → chunk-VBSVNOLA.js} +11 -15
  62. package/dist/{chunk-GK47NBDE.js → chunk-X3SP5RDW.js} +1 -1
  63. package/dist/{chunk-3TV7OEHL.js → chunk-ZHP4KNF7.js} +1 -1
  64. package/dist/cli/chat.js +19 -19
  65. package/dist/cli/check.js +6 -6
  66. package/dist/cli/plugins.js +11 -11
  67. package/dist/cli/snapshot-warmup.js +8 -8
  68. package/dist/cli/upgrade.js +5 -5
  69. package/dist/{db-Y6W6CWWW.js → db-P5H5RVQV.js} +5 -5
  70. package/dist/instrumentation.js +2 -2
  71. package/dist/nitro.js +14 -8
  72. package/dist/{runner-BBFV5GLR.js → runner-B4ZDUO3R.js} +19 -28
  73. package/dist/{skills-AR4AF32L.js → skills-GWTOZ3XV.js} +6 -6
  74. package/dist/{validation-FBIEPTC2.js → validation-QFIC6XH6.js} +6 -6
  75. package/dist/version.js +1 -1
  76. package/package.json +5 -5
@@ -8,6 +8,7 @@ export interface RuntimePluginModule {
8
8
  }
9
9
  /** Render the virtual config module consumed by createApp(). */
10
10
  export declare function renderVirtualConfig(options: {
11
+ functionMaxDurationSeconds?: number;
11
12
  dashboard?: JuniorDashboardOptions;
12
13
  plugins?: PluginCatalogConfig;
13
14
  pluginModule?: RuntimePluginModule;
@@ -15,6 +16,7 @@ export declare function renderVirtualConfig(options: {
15
16
  }): string;
16
17
  /** Inject a virtual module so createApp() can read the plugin list at runtime. */
17
18
  export declare function injectVirtualConfig(nitro: Nitro, options?: {
19
+ functionMaxDurationSeconds?: number;
18
20
  loadPluginSet?: () => Promise<JuniorPluginSet | undefined>;
19
21
  pluginModule?: RuntimePluginModule;
20
22
  plugins?: PluginCatalogConfig;
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-3TV7OEHL.js";
4
- import "./chunk-Y3H2DN6F.js";
3
+ } from "./chunk-ZHP4KNF7.js";
4
+ import "./chunk-TZU3R5OC.js";
5
5
  import "./chunk-C4MZ3GP5.js";
6
- import "./chunk-IYKPU7H6.js";
6
+ import "./chunk-CSS7JHEM.js";
7
7
  import "./chunk-42WRQLJ6.js";
8
8
  import "./chunk-6GWA276C.js";
9
9
  import "./chunk-B3IT5END.js";
10
10
  import "./chunk-3V7OFJZC.js";
11
- import "./chunk-W75ZPAGG.js";
12
- import "./chunk-ZKIOWEFL.js";
11
+ import "./chunk-AU2JVUDF.js";
12
+ import "./chunk-IV2O4HQJ.js";
13
13
  import "./chunk-MLKGABMK.js";
14
14
  export {
15
15
  pluginCatalogRuntime
@@ -13,7 +13,7 @@ import type { ConversationPrivacy } from "@/chat/conversation-privacy";
13
13
  import type { CredentialContext } from "@/chat/credentials/context";
14
14
  import type { PiMessage } from "@/chat/pi/messages";
15
15
  import type { Actor } from "@/chat/actor";
16
- import type { SandboxAcquiredState } from "@/chat/sandbox/sandbox";
16
+ import type { SandboxRef } from "@/chat/sandbox/ref";
17
17
  import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress/tracing";
18
18
  import type { AuthorizationFlowMode } from "@/chat/services/auth-pause";
19
19
  import type { AssistantStatusSpec } from "@/chat/slack/assistant-thread/status";
@@ -105,10 +105,7 @@ export interface AgentRunState {
105
105
  artifactState?: ThreadArtifactsState;
106
106
  pendingAuth?: ConversationPendingAuthState;
107
107
  /** Persisted sandbox reuse state from prior slices of this conversation. */
108
- sandbox?: {
109
- sandboxId?: string;
110
- sandboxDependencyProfileHash?: string;
111
- };
108
+ sandboxRef?: SandboxRef;
112
109
  }
113
110
  /**
114
111
  * Carries notification-only callbacks for streaming UI and status surfaces;
@@ -142,7 +139,7 @@ export interface AgentRunDurability {
142
139
  shouldYield?: () => boolean;
143
140
  drainSteeringMessages?: (accept: (messages: AgentRunSteeringMessage[]) => Promise<void>) => Promise<AgentRunSteeringMessage[]>;
144
141
  recordPendingAuth?: (pendingAuth: ConversationPendingAuthState | undefined) => void | Promise<void>;
145
- onSandboxAcquired?: (sandbox: SandboxAcquiredState) => void | Promise<void>;
142
+ onSandboxRefChanged?: (sandboxRef: SandboxRef) => void | Promise<void>;
146
143
  onArtifactStateUpdated?: (artifactState: ThreadArtifactsState) => void | Promise<void>;
147
144
  }
148
145
  /** Groups the per-slice run request by the runtime role each field serves. */
@@ -1,15 +1,40 @@
1
1
  /**
2
- * Run-scoped sandbox workspace.
2
+ * Agent-facing sandbox adaptation.
3
3
  *
4
- * Exposes a stable workspace port to tools while deferring the actual
5
- * sandbox boot until a tool first touches the filesystem or runs a command,
6
- * and rebinding when the executor's sandbox identity changes mid-run.
4
+ * The sandbox module owns provider lifecycle and recovery. This module adds
5
+ * agent-specific preparation, durable reference propagation, custom command
6
+ * routing, and generated-artifact materialization.
7
7
  */
8
- import { type LogContext } from "@/chat/logging";
9
- import type { SandboxExecutor } from "@/chat/sandbox/sandbox";
8
+ import type { FileUpload } from "chat";
9
+ import { type Actor } from "@/chat/actor";
10
+ import type { ChannelConfigurationService } from "@/chat/configuration/types";
11
+ import type { CredentialContext } from "@/chat/credentials/context";
12
+ import type { LogContext } from "@/chat/logging";
13
+ import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress/tracing";
14
+ import type { SandboxRef } from "@/chat/sandbox/ref";
15
+ import { type SandboxTools } from "@/chat/sandbox/sandbox";
10
16
  import type { SandboxWorkspace } from "@/chat/sandbox/workspace";
11
- /** Create a lazy-boot workspace port bound to the run's sandbox executor. */
12
- export declare function createLazySandboxWorkspace(args: {
13
- executor: SandboxExecutor;
14
- spanContext: LogContext;
15
- }): SandboxWorkspace;
17
+ import type { Skill, SkillMetadata } from "@/chat/skills";
18
+ import type { GeneratedArtifactFileRef } from "@/chat/tools/sandbox/file-uploads";
19
+ export interface AgentSandboxOptions {
20
+ sandboxRef?: SandboxRef;
21
+ skills: SkillMetadata[];
22
+ traceContext: LogContext;
23
+ tracePropagation?: SandboxEgressTracePropagationConfig;
24
+ credentialEgress?: CredentialContext;
25
+ actor?: Actor;
26
+ channelConfiguration?: ChannelConfigurationService;
27
+ configurationValues: Record<string, unknown>;
28
+ getActiveSkill(): Skill | null;
29
+ prepareSandbox(workspace: SandboxWorkspace): void | Promise<void>;
30
+ onSandboxRefChanged(sandboxRef: SandboxRef): void;
31
+ persistSandboxRef?(sandboxRef: SandboxRef): void | Promise<void>;
32
+ }
33
+ export interface AgentSandbox {
34
+ readonly tools: SandboxTools;
35
+ readonly workspace: SandboxWorkspace;
36
+ sandboxRef(): SandboxRef | undefined;
37
+ writeGeneratedArtifacts(files: FileUpload[]): Promise<GeneratedArtifactFileRef[]>;
38
+ }
39
+ /** Create run-scoped sandbox capabilities adapted to the current agent context. */
40
+ export declare function createAgentSandbox(options: AgentSandboxOptions): AgentSandbox;
@@ -2,7 +2,7 @@
2
2
  * Run tool wiring.
3
3
  *
4
4
  * Builds everything the agent can act through for one run slice: the sandbox
5
- * executor and lazy workspace, MCP and plugin auth orchestration, MCP
5
+ * access, MCP and plugin auth orchestration, MCP
6
6
  * provider restoration from durable history, and the Pi-facing tool surfaces
7
7
  * (main-agent tools plus runtime control tools). Auth pauses raised while
8
8
  * restoring providers are thrown here so the run parks before prompting.
@@ -16,11 +16,11 @@ import { McpToolManager } from "@/chat/mcp/tool-manager";
16
16
  import type { AnyToolDefinition } from "@/chat/tools/definition";
17
17
  import type { ToolRuntimeContext } from "@/chat/tools/types";
18
18
  import { type ActiveMcpCatalogSummary } from "@/chat/tool-support/skill/mcp-tool-summary";
19
- import { type SandboxExecutor } from "@/chat/sandbox/sandbox";
19
+ import type { SandboxRef } from "@/chat/sandbox/ref";
20
20
  import type { PiMessage } from "@/chat/pi/messages";
21
21
  import type { LogContext } from "@/chat/logging";
22
22
  import type { ConversationPrivacy } from "@/chat/conversation-privacy";
23
- import { type Actor } from "@/chat/actor";
23
+ import type { Actor } from "@/chat/actor";
24
24
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
25
25
  import type { AuthorizationPauseError } from "@/chat/services/auth-pause";
26
26
  import type { AgentTurnSurface } from "@/chat/state/turn-session";
@@ -41,10 +41,7 @@ interface ToolWiringArgs {
41
41
  generatedFiles: FileUpload[];
42
42
  invokedSkill: SkillMetadata | null;
43
43
  observers: AgentRunObservers;
44
- onSandboxMetadataChanged: (sandbox: {
45
- sandboxId?: string;
46
- sandboxDependencyProfileHash?: string;
47
- }) => void;
44
+ onSandboxRefChanged: (sandboxRef: SandboxRef) => void;
48
45
  policy: AgentRunPolicy;
49
46
  preAgentPromptMessages: () => PiMessage[];
50
47
  priorPiMessages: PiMessage[] | undefined;
@@ -68,7 +65,7 @@ export interface ToolWiring {
68
65
  getPendingAuthPause: () => AuthorizationPauseError | undefined;
69
66
  mcpToolManager: McpToolManager;
70
67
  pluginHooks: PluginHookRunner;
71
- sandboxExecutor: SandboxExecutor;
68
+ getSandboxRef: () => SandboxRef | undefined;
72
69
  toolGuidance: Array<{
73
70
  name: string;
74
71
  promptGuidelines: AnyToolDefinition["promptGuidelines"];
@@ -5,9 +5,12 @@ import { type ExecutionProfileConfig } from "@/chat/model-profile";
5
5
  * Junior can abort, persist, and schedule continuation before host teardown.
6
6
  */
7
7
  export declare const FUNCTION_TIMEOUT_BUFFER_SECONDS = 20;
8
+ /** Additional buffer that makes conversation work yield before the hard request deadline. */
9
+ export declare const CONVERSATION_WORK_SOFT_YIELD_BUFFER_SECONDS = 40;
8
10
  export interface BotConfig {
9
11
  embeddingModelId: string;
10
12
  fastModelId: string;
13
+ imageGenerationModelId: string;
11
14
  loadingMessages: string[];
12
15
  profiles: Readonly<Record<string, ExecutionProfileConfig>>;
13
16
  reasoningLevel?: TurnReasoningLevel;
@@ -16,11 +19,13 @@ export interface BotConfig {
16
19
  maxSlicesPerTurn: number;
17
20
  turnTimeoutMs: number;
18
21
  userName: string;
22
+ webSearchModelId: string;
19
23
  }
20
24
  export type SqlDriver = "neon" | "postgres";
21
25
  export interface ChatConfig {
22
26
  bot: BotConfig;
23
27
  functionMaxDurationSeconds: number;
28
+ conversationWorkSoftYieldAfterMs: number;
24
29
  sql: {
25
30
  databaseUrl: string;
26
31
  driver: SqlDriver;
@@ -41,7 +46,9 @@ export interface ChatConfig {
41
46
  };
42
47
  }
43
48
  /** Parse all chat configuration from environment variables. */
44
- export declare function readChatConfig(env?: NodeJS.ProcessEnv): ChatConfig;
49
+ export declare function readChatConfig(env?: NodeJS.ProcessEnv, functionMaxDurationSeconds?: number): ChatConfig;
50
+ /** Apply the host execution budget injected by juniorNitro(). */
51
+ export declare function configureFunctionMaxDurationSeconds(functionMaxDurationSeconds: number): void;
45
52
  /** Return the chat configuration (parsed once at startup). */
46
53
  export declare function getChatConfig(): ChatConfig;
47
54
  /** Bot configuration derived from environment at module load. */
@@ -3,5 +3,5 @@
3
3
  * are re-exported here so tests can mock a single Junior-owned path instead
4
4
  * of Pi's internal subpath layout, which changes across SDK versions.
5
5
  */
6
- export { completeSimple, getEnvApiKey, getModels, registerApiProvider, type Message, type Model, type ThinkingLevel, } from "@earendil-works/pi-ai/compat";
6
+ export { completeSimple, getEnvApiKey, getModel, getModels, isRetryableAssistantError, registerApiProvider, type Message, type Model, type ThinkingLevel, } from "@earendil-works/pi-ai/compat";
7
7
  export { stream as streamAnthropic, streamSimple as streamSimpleAnthropic, } from "@earendil-works/pi-ai/api/anthropic-messages";
@@ -2,7 +2,7 @@ import type { PluginRoute, PluginOperationalReport, PluginRouteApp, ResourceEven
2
2
  import type { PluginPromptContributionContext } from "@/chat/plugins/prompt";
3
3
  import type { AnyToolDefinition } from "@/chat/tools/definition";
4
4
  import type { ToolRuntimeContext } from "@/chat/tools/types";
5
- import type { SandboxInstance } from "@/chat/sandbox/workspace";
5
+ import type { SandboxWorkspace } from "@/chat/sandbox/workspace";
6
6
  import type { Actor } from "@/chat/actor";
7
7
  /** Signal that a plugin intentionally denied a tool execution. */
8
8
  export declare class PluginHookDeniedError extends Error {
@@ -25,7 +25,7 @@ export interface PluginApiRouteRegistration {
25
25
  }
26
26
  export interface PluginHookRunner {
27
27
  beforeToolExecute(input: ToolHookInput): Promise<ToolHookResult>;
28
- prepareSandbox(sandbox: SandboxInstance): Promise<void>;
28
+ prepareSandbox(workspace: SandboxWorkspace): Promise<void>;
29
29
  }
30
30
  /** Validate plugin identity before it can affect process-wide hooks. */
31
31
  export declare function validatePlugins(plugins: PluginRegistration[]): void;
@@ -11,14 +11,18 @@ export interface AgentContinueRunnerOptions {
11
11
  sessionId: string;
12
12
  }) => Promise<void>;
13
13
  }
14
+ /** Per-worker controls for one continued run. */
15
+ export interface AgentContinueRunOptions {
16
+ shouldYield?: () => boolean;
17
+ }
14
18
  /**
15
19
  * Continue one paused Slack agent run from durable conversation state.
16
20
  *
17
21
  * Returns false when the session became stale before generation began.
18
22
  */
19
- export declare function continueSlackAgentRun(payload: AgentContinueRequest, options: AgentContinueRunnerOptions): Promise<boolean>;
23
+ export declare function continueSlackAgentRun(payload: AgentContinueRequest, options: AgentContinueRunnerOptions, runOptions?: AgentContinueRunOptions): Promise<boolean>;
20
24
  /** Resume the first valid paused Slack session for an idle conversation. */
21
- export declare function resumeAwaitingSlackContinuation(conversationId: string, options: AgentContinueRunnerOptions): Promise<boolean>;
25
+ export declare function resumeAwaitingSlackContinuation(conversationId: string, options: AgentContinueRunnerOptions, runOptions?: AgentContinueRunOptions): Promise<boolean>;
22
26
  /**
23
27
  * Retry agent continuation when the normal Slack thread lock is briefly busy.
24
28
  *
@@ -26,4 +30,4 @@ export declare function resumeAwaitingSlackContinuation(conversationId: string,
26
30
  * lock that is rescheduled still returns true because runnable work remains
27
31
  * durable.
28
32
  */
29
- export declare function continueSlackAgentRunWithLockRetry(payload: AgentContinueRequest, options: AgentContinueRunnerOptions): Promise<boolean>;
33
+ export declare function continueSlackAgentRunWithLockRetry(payload: AgentContinueRequest, options: AgentContinueRunnerOptions, runOptions?: AgentContinueRunOptions): Promise<boolean>;
@@ -18,6 +18,7 @@ export type AgentRunOutcome = {
18
18
  } | {
19
19
  status: "awaiting_auth";
20
20
  providerDisplayName: string;
21
+ requestText?: string;
21
22
  usage?: AgentTurnUsage;
22
23
  };
23
24
  /** Wrap a terminal result (successful or failed per its diagnostics) as an outcome. */
@@ -21,13 +21,12 @@ export interface AssistantLifecycleEvent {
21
21
  userId?: string;
22
22
  }
23
23
  export interface SteeringCandidateMessage {
24
- activeRequest: boolean;
25
24
  inboundMessageId: string;
26
25
  message: Message;
27
26
  }
28
27
  export interface ReplyHooks {
29
28
  beforeFirstResponsePost?: () => Promise<void>;
30
- drainSteeringMessages?: (accept: (messages: SteeringCandidateMessage[]) => Promise<readonly string[] | void>) => Promise<void>;
29
+ drainSteeringMessages?: (accept: (messages: SteeringCandidateMessage[]) => Promise<readonly string[]>) => Promise<void>;
31
30
  messageContext?: MessageContext;
32
31
  ack?: () => Promise<void>;
33
32
  onToolInvocation?: (invocation: TurnToolInvocation) => void;
@@ -2,19 +2,15 @@ import type { Thread } from "chat";
2
2
  import type { ChannelConfigurationService } from "@/chat/configuration/types";
3
3
  import type { ThreadConversationState } from "@/chat/state/conversation";
4
4
  import { type ThreadArtifactsState } from "@/chat/state/artifacts";
5
+ import type { SandboxRef } from "@/chat/sandbox/ref";
5
6
  export interface ThreadStatePatch {
6
7
  artifacts?: ThreadArtifactsState;
7
8
  conversation?: ThreadConversationState;
8
- sandboxId?: string;
9
- sandboxDependencyProfileHash?: string;
10
- }
11
- export interface PersistedSandboxState {
12
- sandboxDependencyProfileHash?: string;
13
- sandboxId?: string;
9
+ sandboxRef?: SandboxRef | null;
14
10
  }
15
11
  export declare function mergeArtifactsState(artifacts: ThreadArtifactsState, patch: Partial<ThreadArtifactsState> | undefined): ThreadArtifactsState;
16
12
  /** Extract persisted sandbox metadata from thread state payload. */
17
- export declare function getPersistedSandboxState(state: Record<string, unknown>): PersistedSandboxState;
13
+ export declare function getPersistedSandboxState(state: Record<string, unknown>): SandboxRef | undefined;
18
14
  /** Persist a thread-state patch through the Chat SDK thread interface. */
19
15
  export declare function persistThreadState(thread: Thread, patch: ThreadStatePatch): Promise<void>;
20
16
  /** Persist only the Redis-backed runtime scratch in a thread-state patch. */
@@ -1,4 +1,5 @@
1
1
  import type { ThreadConversationState } from "@/chat/state/conversation";
2
+ import type { SandboxRef } from "@/chat/sandbox/ref";
2
3
  import { type ThreadArtifactsState } from "@/chat/state/artifacts";
3
4
  import type { ChannelConfigurationService } from "@/chat/configuration/types";
4
5
  import type { PrepareTurnStateInput, TurnContext } from "@/chat/runtime/turn-input";
@@ -8,8 +9,7 @@ export interface PreparedTurnState {
8
9
  channelConfiguration?: ChannelConfigurationService;
9
10
  conversation: ThreadConversationState;
10
11
  conversationContext?: string;
11
- sandboxId?: string;
12
- sandboxDependencyProfileHash?: string;
12
+ sandboxRef?: SandboxRef;
13
13
  userMessageAlreadyReplied?: boolean;
14
14
  userMessageId?: string;
15
15
  }
@@ -0,0 +1,91 @@
1
+ import type { SandboxEgressAuthRequiredSignal, SandboxEgressPermissionDeniedSignal } from "@/chat/sandbox/egress/session";
2
+ export interface SandboxCommandOutcome {
3
+ ok: boolean;
4
+ command: string;
5
+ cwd: string;
6
+ exit_code: number;
7
+ signal: null;
8
+ timed_out: boolean;
9
+ aborted?: boolean;
10
+ stdout: string;
11
+ stderr: string;
12
+ stdout_truncated: boolean;
13
+ stderr_truncated: boolean;
14
+ auth_required?: SandboxEgressAuthRequiredSignal;
15
+ permission_denied?: SandboxEgressPermissionDeniedSignal;
16
+ }
17
+ /** Format one shell command outcome as Junior's structured tool result. */
18
+ export declare function formatSandboxCommandResult(params: SandboxCommandOutcome): import("@/chat/tool-support/structured-result").JuniorTextToolResultEnvelope<{
19
+ permission_denied?: {
20
+ grant: {
21
+ access: "read" | "write";
22
+ name: string;
23
+ leaseScope?: string | undefined;
24
+ reason?: string | undefined;
25
+ requirements?: string[] | undefined;
26
+ };
27
+ message: string;
28
+ provider: string;
29
+ source: "upstream";
30
+ status: number;
31
+ upstreamHost: string;
32
+ upstreamPath: string;
33
+ createdAtMs: number;
34
+ account?: {
35
+ id: string;
36
+ label?: string | undefined;
37
+ url?: string | undefined;
38
+ } | undefined;
39
+ acceptedPermissions?: string | undefined;
40
+ sso?: string | undefined;
41
+ } | undefined;
42
+ auth_required?: {
43
+ grant: {
44
+ access: "read" | "write";
45
+ name: string;
46
+ leaseScope?: string | undefined;
47
+ reason?: string | undefined;
48
+ requirements?: string[] | undefined;
49
+ };
50
+ kind: "unavailable" | "auth_required";
51
+ provider: string;
52
+ createdAtMs: number;
53
+ authorization?: {
54
+ provider: string;
55
+ type: "oauth";
56
+ scope?: string | undefined;
57
+ } | undefined;
58
+ message?: string | undefined;
59
+ } | undefined;
60
+ command: string;
61
+ cwd: string;
62
+ exit_code: number;
63
+ signal: null;
64
+ timed_out: boolean;
65
+ aborted: boolean;
66
+ stdout: string;
67
+ stderr: string;
68
+ stdout_truncated: boolean;
69
+ stderr_truncated: boolean;
70
+ error?: {
71
+ kind: string;
72
+ message: string;
73
+ retryable: boolean;
74
+ } | undefined;
75
+ ok: boolean;
76
+ status: "error" | "success";
77
+ target: string;
78
+ data: {
79
+ command: string;
80
+ cwd: string;
81
+ exit_code: number;
82
+ signal: null;
83
+ timed_out: boolean;
84
+ aborted: boolean;
85
+ stdout: string;
86
+ stderr: string;
87
+ stdout_truncated: boolean;
88
+ stderr_truncated: boolean;
89
+ };
90
+ truncated: boolean;
91
+ }>;
@@ -1,7 +1,9 @@
1
1
  /** Detect sandbox filesystem operations that can safely ignore existing directories. */
2
2
  export declare function isAlreadyExistsError(error: unknown): boolean;
3
- /** Detect when a cached sandbox can no longer be reused and must be recreated. */
3
+ /** Detect when the current sandbox session is unavailable and must be reacquired. */
4
4
  export declare function isSandboxUnavailableError(error: unknown): boolean;
5
+ /** Detect a durable sandbox reference that can no longer be restored. */
6
+ export declare function isSandboxMissingError(error: unknown): boolean;
5
7
  /** Detect transient snapshot boot races so sandbox creation can retry. */
6
8
  export declare function isSnapshottingError(error: unknown): boolean;
7
9
  /** Detect interrupted command streams where no reliable exit status is available. */
@@ -0,0 +1,5 @@
1
+ /** Durable opaque handle used to reopen a conversation's sandbox. */
2
+ export interface SandboxRef {
3
+ id: string;
4
+ profileHash?: string;
5
+ }
@@ -1,60 +1,33 @@
1
1
  import { type LogContext } from "@/chat/logging";
2
- import { type SandboxEgressAuthRequiredSignal, type SandboxEgressPermissionDeniedSignal } from "@/chat/sandbox/egress/session";
3
2
  import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress/tracing";
4
3
  import type { CredentialContext } from "@/chat/credentials/context";
5
- import type { PluginHookRunner } from "@/chat/plugins/agent-hooks";
6
- import type { SandboxInstance } from "@/chat/sandbox/workspace";
4
+ import type { SandboxRef } from "@/chat/sandbox/ref";
5
+ import type { SandboxWorkspace } from "@/chat/sandbox/workspace";
7
6
  import type { SkillMetadata } from "@/chat/skills";
8
- interface SandboxExecutionInput {
7
+ export interface SandboxToolCall {
9
8
  toolName: string;
10
9
  input: unknown;
11
10
  signal?: AbortSignal;
12
11
  }
13
- export interface SandboxExecutionEnvelope<T = unknown> {
14
- result: T;
12
+ export interface SandboxTools {
13
+ supports(toolName: string): boolean;
14
+ execute(params: SandboxToolCall): Promise<unknown>;
15
15
  }
16
- export interface BashCustomCommandResult {
17
- ok: boolean;
18
- command: string;
19
- cwd: string;
20
- exit_code: number;
21
- signal: null;
22
- timed_out: boolean;
23
- aborted?: boolean;
24
- stdout: string;
25
- stderr: string;
26
- stdout_truncated: boolean;
27
- stderr_truncated: boolean;
28
- auth_required?: SandboxEgressAuthRequiredSignal;
29
- permission_denied?: SandboxEgressPermissionDeniedSignal;
16
+ export interface SandboxAccess {
17
+ readonly tools: SandboxTools;
18
+ readonly workspace: SandboxWorkspace;
19
+ sandboxRef(): SandboxRef | undefined;
30
20
  }
31
- export interface SandboxAcquiredState {
32
- sandboxId: string;
33
- sandboxDependencyProfileHash?: string;
34
- }
35
- export interface SandboxExecutor {
36
- configureSkills(skills: SkillMetadata[]): void;
37
- configureReferenceFiles(files: string[]): void;
38
- getSandboxId(): string | undefined;
39
- getDependencyProfileHash(): string | undefined;
40
- canExecute(toolName: string): boolean;
41
- createSandbox(): Promise<SandboxInstance>;
42
- execute<T>(params: SandboxExecutionInput): Promise<SandboxExecutionEnvelope<T>>;
43
- dispose(): Promise<void>;
44
- }
45
- /** Create one sandbox-backed tool executor facade for the current turn. */
46
- export declare function createSandboxExecutor(options?: {
47
- sandboxId?: string;
48
- sandboxDependencyProfileHash?: string;
21
+ export interface SandboxOptions {
22
+ sandboxRef?: SandboxRef;
23
+ skills: SkillMetadata[];
24
+ referenceFiles: string[];
49
25
  timeoutMs?: number;
50
26
  traceContext?: LogContext;
51
27
  tracePropagation?: SandboxEgressTracePropagationConfig;
52
28
  credentialEgress?: CredentialContext;
53
- agentHooks?: PluginHookRunner;
54
- onSandboxAcquired?: (sandbox: SandboxAcquiredState) => void | Promise<void>;
55
- runBashCustomCommand?: (command: string) => Promise<{
56
- handled: boolean;
57
- result?: BashCustomCommandResult;
58
- }>;
59
- }): SandboxExecutor;
60
- export {};
29
+ prepare?: (workspace: SandboxWorkspace) => void | Promise<void>;
30
+ onSandboxRefChanged?: (sandboxRef: SandboxRef) => void | Promise<void>;
31
+ }
32
+ /** Create lazy run-scoped access to a conversation's durable sandbox. */
33
+ export declare function createSandbox(options: SandboxOptions): SandboxAccess;
@@ -1,8 +1,10 @@
1
1
  import { type NetworkPolicy } from "@vercel/sandbox";
2
2
  import { type LogContext, type TracePropagationHeaders } from "@/chat/logging";
3
- import { type SandboxFileSystem, type SandboxInstance } from "@/chat/sandbox/workspace";
3
+ import { type SandboxFileSystem, type SandboxSession } from "@/chat/sandbox/workspace";
4
4
  import type { SkillMetadata } from "@/chat/skills";
5
+ import type { SandboxRef } from "@/chat/sandbox/ref";
5
6
  interface SandboxToolExecutors {
7
+ sessionId: string;
6
8
  bash: (input: {
7
9
  command: string;
8
10
  env?: Record<string, string>;
@@ -30,29 +32,23 @@ interface SandboxToolExecutors {
30
32
  }>;
31
33
  fs: SandboxFileSystem;
32
34
  }
33
- interface SandboxSessionManager {
34
- configureSkills(skills: SkillMetadata[]): void;
35
- configureReferenceFiles(files: string[]): void;
36
- getSandboxId(): string | undefined;
37
- getSandboxEgressId(): string | undefined;
38
- getDependencyProfileHash(): string | undefined;
39
- createSandbox(): Promise<SandboxInstance>;
40
- ensureToolExecutors(): Promise<SandboxToolExecutors>;
35
+ interface SandboxRuntime {
36
+ sandboxRef(): SandboxRef | undefined;
37
+ acquire(): Promise<SandboxSession>;
38
+ tools(): Promise<SandboxToolExecutors>;
41
39
  refreshNetworkPolicy(traceHeaders?: TracePropagationHeaders): Promise<void>;
42
- dispose(): Promise<void>;
43
40
  }
44
- /** Manage sandbox lifecycle, sync, keepalive, and tool executor caching for one executor instance. */
45
- export declare function createSandboxSessionManager(options?: {
46
- sandboxId?: string;
47
- sandboxDependencyProfileHash?: string;
41
+ interface SandboxRuntimeOptions {
42
+ sandboxRef?: SandboxRef;
43
+ skills: SkillMetadata[];
44
+ referenceFiles: string[];
48
45
  timeoutMs?: number;
49
46
  traceContext?: LogContext;
50
47
  commandEnv?: () => Promise<Record<string, string>>;
51
48
  createNetworkPolicy?: (egressId: string, traceHeaders?: TracePropagationHeaders) => NetworkPolicy | undefined;
52
- onSandboxPrepare?: (sandbox: SandboxInstance) => void | Promise<void>;
53
- onSandboxAcquired?: (sandbox: {
54
- sandboxId: string;
55
- sandboxDependencyProfileHash?: string;
56
- }) => void | Promise<void>;
57
- }): SandboxSessionManager;
49
+ onSandboxPrepare?: (sandbox: SandboxSession) => void | Promise<void>;
50
+ onSandboxRefChanged?: (sandboxRef: SandboxRef) => void | Promise<void>;
51
+ }
52
+ /** Own sandbox acquisition, preparation, and session-scoped tool caching. */
53
+ export declare function createSandboxRuntime(options: SandboxRuntimeOptions): SandboxRuntime;
58
54
  export {};
@@ -1,4 +1,4 @@
1
- import type { SandboxInstance } from "@/chat/sandbox/workspace";
1
+ import type { SandboxSession } from "@/chat/sandbox/workspace";
2
2
  import type { SkillMetadata } from "@/chat/skills";
3
3
  /** Resolve a virtual sandbox skill path back to the host filesystem when no sandbox exists yet. */
4
4
  export declare function resolveHostSkillPath(availableSkills: SkillMetadata[], sandboxPath: string): string | null;
@@ -8,7 +8,7 @@ export declare function resolveHostDataPath(referenceFiles: string[], sandboxPat
8
8
  export declare function isHostFileMissingError(error: unknown): boolean;
9
9
  /** Copy the current skill set and reference files into a sandbox. */
10
10
  export declare function syncSkillsToSandbox(params: {
11
- sandbox: SandboxInstance;
11
+ sandbox: SandboxSession;
12
12
  skills: SkillMetadata[];
13
13
  referenceFiles?: string[];
14
14
  withSpan: <T>(name: string, op: string, attributes: Record<string, unknown>, callback: () => Promise<T>) => Promise<T>;
@@ -1,8 +1,8 @@
1
- import type { NetworkPolicy, Sandbox as VercelSandbox } from "@vercel/sandbox";
1
+ import { type NetworkPolicy, type Sandbox as VercelSandbox } from "@vercel/sandbox";
2
2
  export interface SandboxCommandResult {
3
3
  exitCode: number;
4
- stderr(): Promise<string>;
5
- stdout(): Promise<string>;
4
+ stderr: string;
5
+ stdout: string;
6
6
  }
7
7
  export interface SandboxCommandInput {
8
8
  args?: string[];
@@ -31,10 +31,15 @@ export interface SandboxWorkspace {
31
31
  path: string;
32
32
  }): Promise<Buffer | null | undefined>;
33
33
  runCommand(input: SandboxCommandInput): Promise<SandboxCommandResult>;
34
+ writeFiles(files: Array<{
35
+ content: string | Uint8Array;
36
+ mode?: number;
37
+ path: string;
38
+ }>): Promise<void>;
34
39
  }
35
- export interface SandboxInstance extends SandboxWorkspace {
40
+ export interface SandboxSession extends SandboxWorkspace {
36
41
  readonly sandboxId: string;
37
- readonly sandboxEgressId: string;
42
+ readonly sessionId: string;
38
43
  readonly fs: SandboxFileSystem;
39
44
  extendTimeout(duration: number): Promise<void>;
40
45
  mkDir(path: string): Promise<void>;
@@ -45,11 +50,8 @@ export interface SandboxInstance extends SandboxWorkspace {
45
50
  update(params: {
46
51
  networkPolicy?: NetworkPolicy;
47
52
  }): Promise<void>;
48
- writeFiles(files: Array<{
49
- content: string | Uint8Array;
50
- mode?: number;
51
- path: string;
52
- }>): Promise<void>;
53
53
  }
54
- /** Adapt the Vercel SDK object once so the rest of Junior sees one sandbox contract. */
55
- export declare function createSandboxInstance(sandbox: VercelSandbox): SandboxInstance;
54
+ /** Pin Junior's sandbox contract to one Vercel session without SDK replay. */
55
+ export declare function createSandboxSession(sandbox: VercelSandbox, options?: {
56
+ onUnavailable?: (sessionId: string) => void;
57
+ }): SandboxSession;
@@ -1,2 +1,2 @@
1
1
  /** Build the visible Slack thread note for an auth-paused turn. */
2
- export declare function buildAuthPauseResponse(slackUserId: string | undefined, providerDisplayName: string): string;
2
+ export declare function buildAuthPauseResponse(slackUserId: string | undefined, providerDisplayName: string, requestText?: string): string;