@sentry/junior 0.119.0 → 0.121.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 (52) hide show
  1. package/dist/{agent-hooks-NZSV4QQR.js → agent-hooks-CQDGDBCP.js} +7 -7
  2. package/dist/api.js +58 -79
  3. package/dist/app.js +21 -21
  4. package/dist/build/copy-build-content.d.ts +2 -2
  5. package/dist/{catalog-runtime-TAOYIZIZ.js → catalog-runtime-AD3YNTTM.js} +7 -7
  6. package/dist/chat/discovery.d.ts +2 -0
  7. package/dist/chat/mcp/tool-manager.d.ts +14 -1
  8. package/dist/chat/plugins/types.d.ts +3 -9
  9. package/dist/chat/plugins/user-pages.d.ts +2 -1
  10. package/dist/chat/sandbox/noninteractive-command.d.ts +1 -0
  11. package/dist/chat/sandbox/session.d.ts +2 -2
  12. package/dist/chat/sandbox/snapshot/install.d.ts +2 -2
  13. package/dist/chat/sandbox/snapshot/resolve.d.ts +1 -0
  14. package/dist/chat/sandbox/workspace.d.ts +3 -1
  15. package/dist/{chunk-D3N4BPSL.js → chunk-254MFDOF.js} +2 -2
  16. package/dist/{chunk-4UIUDOOV.js → chunk-3DBMANUI.js} +7 -7
  17. package/dist/{chunk-BLQZACHV.js → chunk-7HYV7KFM.js} +92 -6
  18. package/dist/{chunk-JLJLZS2N.js → chunk-D2EMOH3N.js} +4 -3
  19. package/dist/{chunk-R53UT2OI.js → chunk-ET2SDCNV.js} +9 -5
  20. package/dist/chunk-H4HBKISO.js +417 -0
  21. package/dist/{chunk-VLTWQQKH.js → chunk-IDXLBKPS.js} +1 -1
  22. package/dist/{chunk-NUENIPQL.js → chunk-IK4QSS5H.js} +1 -1
  23. package/dist/{chunk-GKFDU3ZI.js → chunk-ITMEXX5H.js} +44 -23
  24. package/dist/{chunk-ZFX4M743.js → chunk-JYDIBXFY.js} +6 -6
  25. package/dist/{chunk-ZJ6IVZVO.js → chunk-JZ47AFSH.js} +1 -1
  26. package/dist/{chunk-YLYJIQRX.js → chunk-KLUMVJRQ.js} +12 -12
  27. package/dist/{chunk-TAGV4Z3J.js → chunk-LE77HHF3.js} +1 -1
  28. package/dist/{chunk-B3IT5END.js → chunk-OOUNJNMR.js} +16 -152
  29. package/dist/{chunk-QZ7XRJDB.js → chunk-TRECK7RV.js} +3 -3
  30. package/dist/{chunk-VJTWKJWQ.js → chunk-UURFXX66.js} +1 -1
  31. package/dist/{chunk-6ZR455DC.js → chunk-UXQ5XSA2.js} +1 -1
  32. package/dist/{chunk-TGIQN7QW.js → chunk-VWBKDPMQ.js} +242 -69
  33. package/dist/{chunk-JSTGI7TX.js → chunk-WUP7NWMP.js} +1 -1
  34. package/dist/{chunk-JXRAOOXQ.js → chunk-XDRGYDED.js} +1 -1
  35. package/dist/{chunk-BNJEPYTC.js → chunk-Z2XXPUZG.js} +4 -4
  36. package/dist/cli/chat.js +23 -23
  37. package/dist/cli/check.js +8 -8
  38. package/dist/cli/plugins.js +12 -12
  39. package/dist/cli/snapshot-create.js +10 -10
  40. package/dist/cli/upgrade.js +7 -7
  41. package/dist/{db-FWGP5CKY.js → db-7HQT2SXQ.js} +5 -5
  42. package/dist/{discovery-RMHYSRL7.js → discovery-GUFTFBTL.js} +3 -1
  43. package/dist/instrumentation.js +2 -2
  44. package/dist/nitro.js +24 -7
  45. package/dist/{oauth-callback-server-PM3QNXJQ.js → oauth-callback-server-VHTUCNHK.js} +16 -16
  46. package/dist/{runner-DV55N6ZB.js → runner-3ONPZRED.js} +9 -9
  47. package/dist/{skills-MANV5ZK6.js → skills-WGAYGGPA.js} +8 -8
  48. package/dist/{validation-QGB4INTI.js → validation-ZIWNBG4D.js} +8 -8
  49. package/dist/version.js +1 -1
  50. package/package.json +8 -7
  51. package/skills/jr-rpc/SKILL.md +40 -0
  52. package/dist/chunk-3V7OFJZC.js +0 -264
@@ -30,7 +30,7 @@ import {
30
30
  toMcpProviderError,
31
31
  toolInvocationDestination,
32
32
  uploadFilesToConversation
33
- } from "./chunk-4UIUDOOV.js";
33
+ } from "./chunk-3DBMANUI.js";
34
34
  import {
35
35
  CooperativeTurnYieldError,
36
36
  JUNIOR_THREAD_STATE_TTL_MS,
@@ -72,7 +72,7 @@ import {
72
72
  stripRuntimeTurnContext,
73
73
  trimTrailingAssistantMessages,
74
74
  updateConversationStats
75
- } from "./chunk-BNJEPYTC.js";
75
+ } from "./chunk-Z2XXPUZG.js";
76
76
  import {
77
77
  parseSandboxEgressAuthRequiredSignal,
78
78
  parseSandboxEgressPermissionDeniedSignal,
@@ -96,10 +96,10 @@ import {
96
96
  runNonInteractiveCommand,
97
97
  throwSandboxOperationError,
98
98
  wrapSandboxSetupError
99
- } from "./chunk-GKFDU3ZI.js";
99
+ } from "./chunk-ITMEXX5H.js";
100
100
  import {
101
101
  incrementStat
102
- } from "./chunk-JXRAOOXQ.js";
102
+ } from "./chunk-XDRGYDED.js";
103
103
  import {
104
104
  addAgentTurnUsage,
105
105
  hasAgentTurnUsage
@@ -121,7 +121,7 @@ import {
121
121
  normalizeSlackConversationId,
122
122
  resolveChannelCapabilities,
123
123
  withSlackRetries
124
- } from "./chunk-BLQZACHV.js";
124
+ } from "./chunk-7HYV7KFM.js";
125
125
  import {
126
126
  KNOWN_CONVERSATION_EVENT_TYPES,
127
127
  contextProvenance,
@@ -130,7 +130,7 @@ import {
130
130
  getConversationStore,
131
131
  instructionActors,
132
132
  instructionProvenanceFor
133
- } from "./chunk-D3N4BPSL.js";
133
+ } from "./chunk-254MFDOF.js";
134
134
  import {
135
135
  SANDBOX_DATA_ROOT,
136
136
  SANDBOX_SKILLS_ROOT,
@@ -140,7 +140,7 @@ import {
140
140
  sandboxSkillFile,
141
141
  sandboxSkillPathResolution,
142
142
  sleep
143
- } from "./chunk-VJTWKJWQ.js";
143
+ } from "./chunk-UURFXX66.js";
144
144
  import {
145
145
  ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
146
146
  COMPACTION_SUMMARY_PREFIX,
@@ -171,7 +171,7 @@ import {
171
171
  renderCurrentInstruction,
172
172
  resolveGatewayModel,
173
173
  unwrapCurrentInstruction
174
- } from "./chunk-VLTWQQKH.js";
174
+ } from "./chunk-IDXLBKPS.js";
175
175
  import {
176
176
  canExposeConversationPayload,
177
177
  parseSlackThreadId,
@@ -188,10 +188,10 @@ import {
188
188
  findSkillByName,
189
189
  loadSkillsByName,
190
190
  parseSkillInvocation
191
- } from "./chunk-QZ7XRJDB.js";
191
+ } from "./chunk-TRECK7RV.js";
192
192
  import {
193
193
  pluginCatalogRuntime
194
- } from "./chunk-JSTGI7TX.js";
194
+ } from "./chunk-WUP7NWMP.js";
195
195
  import {
196
196
  CredentialUnavailableError,
197
197
  OAuthProviderError,
@@ -199,7 +199,7 @@ import {
199
199
  getOAuthProviderErrorAttributes,
200
200
  resolveAuthTokenPlaceholder,
201
201
  resolvePluginCommandEnv
202
- } from "./chunk-R53UT2OI.js";
202
+ } from "./chunk-ET2SDCNV.js";
203
203
  import {
204
204
  credentialUserSubjectId
205
205
  } from "./chunk-W3U3YQYI.js";
@@ -223,7 +223,7 @@ import {
223
223
  summarizeMessageText,
224
224
  withLogContext,
225
225
  withSpan
226
- } from "./chunk-ZJ6IVZVO.js";
226
+ } from "./chunk-JZ47AFSH.js";
227
227
  import {
228
228
  parseSlackChannelId,
229
229
  parseSlackMessageTs,
@@ -237,7 +237,7 @@ import {
237
237
  listReferenceFiles,
238
238
  soulPathCandidates,
239
239
  worldPathCandidates
240
- } from "./chunk-3V7OFJZC.js";
240
+ } from "./chunk-H4HBKISO.js";
241
241
 
242
242
  // src/chat/configuration/defaults.ts
243
243
  var installDefaults = {};
@@ -1781,10 +1781,11 @@ var TOOL_POLICY_RULES = [
1781
1781
  "- Resolve provider action targets before calls: explicit target wins; ambient `<configuration>` fills omitted targets. Treat non-target links/references as context.",
1782
1782
  "- 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.",
1783
1783
  "- 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.",
1784
+ "- After changing files, name the changed paths and summarize the completed result in the final answer.",
1784
1785
  "- 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.",
1785
1786
  "- For user-provided URLs, use `webFetch`; for discovery, use `webSearch` then fetch/read promising sources; for current time/date context, use `systemTime`.",
1786
1787
  "- When a tool result includes a subscribable resource, use resource-event subscriptions for high-signal provider changes that serve the user's current intent; do not create scheduled polling tasks for events the subscription can deliver. Use the suggested events when they fit and write a concise intent summary.",
1787
- "- For code changes, debugging or root-cause analysis, broad refactors, and software architecture decisions, use `handoff` before substantive analysis when that tool is available.",
1788
+ "- For code changes, debugging or root-cause analysis, broad refactors, and software architecture decisions, use `handoff` before substantive analysis only when it offers a profile that better matches the task. Do not switch merely because the task involves code.",
1788
1789
  "- 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.",
1789
1790
  "- 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."
1790
1791
  ];
@@ -1805,7 +1806,8 @@ var EXECUTION_CONTRACT_RULES = [
1805
1806
  "- Complete the full task, but report only the result and evidence the user needs; do not narrate every step, check, or detail.",
1806
1807
  "- Ask the user only for missing access, approval, or a decision that blocks safe progress. Ask one focused question; otherwise infer conservatively and continue.",
1807
1808
  "- For conflicting evidence, compare sources and state which source is authoritative for the answer.",
1808
- "- For non-trivial or long-running work, call `reportProgress` early when available, then only when the major phase changes. Routine tool calls should stay silent."
1809
+ "- Use `reportProgress` only for work with multiple substantive phases or a materially long wait. Skip short lookups and routine commands; after an initial update, call it again only when the major phase changes.",
1810
+ "- When a tool outcome is unknown and may include side effects, inspect authoritative state before retrying. If state already reflects the intended result, do not repeat the mutation."
1809
1811
  ];
1810
1812
  var CONVERSATION_RULES = [
1811
1813
  "- In thread follow-ups, answer from prior thread context; do not repeat resolved clarifying questions.",
@@ -3259,6 +3261,20 @@ var SNAPSHOT_BOOT_RETRY_DELAY_MS = 1e3;
3259
3261
  var SANDBOX_NAME_PREFIX = "junior-";
3260
3262
  var MAX_KEEPALIVE_INTERVAL_MS = 3e4;
3261
3263
  var MIN_KEEPALIVE_INTERVAL_MS = 1e3;
3264
+ function sandboxFetchOptions(signal) {
3265
+ if (!signal) {
3266
+ return {};
3267
+ }
3268
+ return {
3269
+ fetch: (input, init) => {
3270
+ const requestSignal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
3271
+ return globalThis.fetch(input, {
3272
+ ...init,
3273
+ signal: requestSignal ? AbortSignal.any([requestSignal, signal]) : signal
3274
+ });
3275
+ }
3276
+ };
3277
+ }
3262
3278
  function truncateOutput(output, maxLength) {
3263
3279
  if (output.length <= maxLength) {
3264
3280
  return { value: output, truncated: false };
@@ -3398,9 +3414,10 @@ function createSandboxRuntime(options) {
3398
3414
  }
3399
3415
  );
3400
3416
  };
3401
- const createSandboxFromSnapshot = async (snapshotId, sandboxCredentials, initialSandboxName) => {
3417
+ const createSandboxFromSnapshot = async (snapshotId, sandboxCredentials, initialSandboxName, signal) => {
3402
3418
  const resources = getSandboxResources();
3403
3419
  for (let attempt = 0; attempt < SNAPSHOT_BOOT_RETRY_COUNT; attempt += 1) {
3420
+ signal?.throwIfAborted();
3404
3421
  const sandboxName = attempt === 0 ? initialSandboxName : createSandboxName();
3405
3422
  const networkPolicy = preflightNetworkPolicy(sandboxName);
3406
3423
  try {
@@ -3413,14 +3430,15 @@ function createSandboxRuntime(options) {
3413
3430
  snapshotId
3414
3431
  },
3415
3432
  ...resources ? { resources } : {},
3416
- ...sandboxCredentials ?? {}
3433
+ ...sandboxCredentials ?? {},
3434
+ ...sandboxFetchOptions(signal)
3417
3435
  })
3418
3436
  );
3419
3437
  } catch (error) {
3420
3438
  if (!isSnapshottingError(error) || attempt === SNAPSHOT_BOOT_RETRY_COUNT - 1) {
3421
3439
  throw error;
3422
3440
  }
3423
- await sleep(SNAPSHOT_BOOT_RETRY_DELAY_MS);
3441
+ await sleep(SNAPSHOT_BOOT_RETRY_DELAY_MS, signal);
3424
3442
  }
3425
3443
  }
3426
3444
  throw new Error(`Failed to boot sandbox from snapshot ${snapshotId}`);
@@ -3440,7 +3458,8 @@ function createSandboxRuntime(options) {
3440
3458
  });
3441
3459
  };
3442
3460
  const createSandboxFromResolvedSnapshot = async (params) => {
3443
- const { runtime, snapshot, sandboxCredentials, sandboxName } = params;
3461
+ const { runtime, snapshot, sandboxCredentials, sandboxName, signal } = params;
3462
+ signal?.throwIfAborted();
3444
3463
  if (!snapshot.snapshotId) {
3445
3464
  const networkPolicy = preflightNetworkPolicy(sandboxName);
3446
3465
  const resources = getSandboxResources();
@@ -3450,7 +3469,8 @@ function createSandboxRuntime(options) {
3450
3469
  runtime,
3451
3470
  ...networkPolicy ? { name: sandboxName, persistent: false, networkPolicy } : {},
3452
3471
  ...resources ? { resources } : {},
3453
- ...sandboxCredentials ?? {}
3472
+ ...sandboxCredentials ?? {},
3473
+ ...sandboxFetchOptions(signal)
3454
3474
  })
3455
3475
  );
3456
3476
  }
@@ -3458,7 +3478,8 @@ function createSandboxRuntime(options) {
3458
3478
  return await createSandboxFromSnapshot(
3459
3479
  snapshot.snapshotId,
3460
3480
  sandboxCredentials,
3461
- sandboxName
3481
+ sandboxName,
3482
+ signal
3462
3483
  );
3463
3484
  } catch (error) {
3464
3485
  if (!isMissingError(error)) {
@@ -3471,19 +3492,22 @@ function createSandboxRuntime(options) {
3471
3492
  runtime,
3472
3493
  timeoutMs,
3473
3494
  forceRebuild: true,
3474
- staleSnapshotId: snapshot.snapshotId
3495
+ staleSnapshotId: snapshot.snapshotId,
3496
+ signal
3475
3497
  });
3476
3498
  if (!rebuiltSnapshot.snapshotId) {
3477
3499
  throw error;
3478
3500
  }
3501
+ signal?.throwIfAborted();
3479
3502
  return await createSandboxFromSnapshot(
3480
3503
  rebuiltSnapshot.snapshotId,
3481
3504
  sandboxCredentials,
3482
- sandboxName
3505
+ sandboxName,
3506
+ signal
3483
3507
  );
3484
3508
  }
3485
3509
  };
3486
- const createFreshSandbox = async () => {
3510
+ const createFreshSandbox = async (signal) => {
3487
3511
  const runtime = SANDBOX_RUNTIME;
3488
3512
  const sandboxCredentials = getVercelSandboxCredentials();
3489
3513
  const sandboxName = createSandboxName();
@@ -3500,14 +3524,17 @@ function createSandboxRuntime(options) {
3500
3524
  async () => {
3501
3525
  const snapshot = await resolve({
3502
3526
  runtime,
3503
- timeoutMs
3527
+ timeoutMs,
3528
+ signal
3504
3529
  });
3530
+ signal?.throwIfAborted();
3505
3531
  setSnapshotAttributes(snapshot);
3506
3532
  return await createSandboxFromResolvedSnapshot({
3507
3533
  runtime,
3508
3534
  snapshot,
3509
3535
  sandboxCredentials,
3510
- sandboxName
3536
+ sandboxName,
3537
+ signal
3511
3538
  });
3512
3539
  }
3513
3540
  );
@@ -3552,7 +3579,7 @@ function createSandboxRuntime(options) {
3552
3579
  const tryReuseCachedSandbox = async () => {
3553
3580
  return activeSandbox?.session ?? null;
3554
3581
  };
3555
- const tryRestoreHintedSandbox = async () => {
3582
+ const tryRestoreHintedSandbox = async (signal) => {
3556
3583
  const ref = sandboxRef;
3557
3584
  if (!ref) {
3558
3585
  return null;
@@ -3571,7 +3598,8 @@ function createSandboxRuntime(options) {
3571
3598
  await Sandbox.get({
3572
3599
  name: ref.id,
3573
3600
  resume: true,
3574
- ...sandboxCredentials ?? {}
3601
+ ...sandboxCredentials ?? {},
3602
+ ...sandboxFetchOptions(signal)
3575
3603
  })
3576
3604
  )
3577
3605
  );
@@ -3599,7 +3627,7 @@ function createSandboxRuntime(options) {
3599
3627
  return failSetup(error);
3600
3628
  }
3601
3629
  };
3602
- const acquireSandbox = async () => {
3630
+ const acquireSandbox = async (signal) => {
3603
3631
  return await withSandboxSpan(
3604
3632
  "sandbox.acquire",
3605
3633
  "sandbox.acquire",
@@ -3615,25 +3643,63 @@ function createSandboxRuntime(options) {
3615
3643
  if (cachedSandbox) {
3616
3644
  return cachedSandbox;
3617
3645
  }
3618
- const hintedSandbox = await tryRestoreHintedSandbox();
3646
+ signal?.throwIfAborted();
3647
+ const hintedSandbox = await tryRestoreHintedSandbox(signal);
3619
3648
  if (hintedSandbox) {
3620
3649
  return hintedSandbox;
3621
3650
  }
3622
- return await createFreshSandbox();
3651
+ return await createFreshSandbox(signal);
3623
3652
  }
3624
3653
  );
3625
3654
  };
3626
- const getOrAcquireSandbox = async () => {
3627
- if (acquiringSandbox) {
3628
- return await acquiringSandbox;
3629
- }
3630
- const nextSandbox = acquireSandbox();
3631
- acquiringSandbox = nextSandbox;
3632
- try {
3633
- return await nextSandbox;
3634
- } finally {
3635
- if (acquiringSandbox === nextSandbox) {
3636
- acquiringSandbox = void 0;
3655
+ const getOrAcquireSandbox = async (signal) => {
3656
+ for (; ; ) {
3657
+ signal?.throwIfAborted();
3658
+ let acquisition = acquiringSandbox;
3659
+ if (!acquisition) {
3660
+ const controller = new AbortController();
3661
+ const startedAcquisition = {
3662
+ controller,
3663
+ promise: acquireSandbox(signal ? controller.signal : void 0),
3664
+ settled: false,
3665
+ waiters: 0
3666
+ };
3667
+ const markSettled = () => {
3668
+ startedAcquisition.settled = true;
3669
+ if (acquiringSandbox === startedAcquisition) {
3670
+ acquiringSandbox = void 0;
3671
+ }
3672
+ };
3673
+ void startedAcquisition.promise.then(markSettled, markSettled);
3674
+ acquiringSandbox = startedAcquisition;
3675
+ acquisition = startedAcquisition;
3676
+ }
3677
+ acquisition.waiters += 1;
3678
+ let removeAbortListener;
3679
+ try {
3680
+ if (!signal) {
3681
+ return await acquisition.promise;
3682
+ }
3683
+ const aborted = new Promise((_resolve, reject) => {
3684
+ const onAbort = () => reject(signal.reason);
3685
+ signal.addEventListener("abort", onAbort, { once: true });
3686
+ removeAbortListener = () => signal.removeEventListener("abort", onAbort);
3687
+ });
3688
+ return await Promise.race([acquisition.promise, aborted]);
3689
+ } catch (error) {
3690
+ signal?.throwIfAborted();
3691
+ if (!acquisition.controller.signal.aborted) {
3692
+ throw error;
3693
+ }
3694
+ if (acquiringSandbox === acquisition) {
3695
+ acquiringSandbox = void 0;
3696
+ }
3697
+ } finally {
3698
+ removeAbortListener?.();
3699
+ acquisition.waiters -= 1;
3700
+ if (acquisition.waiters === 0 && !acquisition.settled) {
3701
+ acquisition.controller.abort(signal?.reason);
3702
+ }
3637
3703
  }
3638
3704
  }
3639
3705
  };
@@ -3782,9 +3848,11 @@ function createSandboxRuntime(options) {
3782
3848
  runCommand: async (input) => await sandboxInstance.runCommand(input)
3783
3849
  };
3784
3850
  };
3785
- const ensureReadySandbox = async () => {
3786
- const activeSandbox2 = await getOrAcquireSandbox();
3851
+ const ensureReadySandbox = async (signal) => {
3852
+ const activeSandbox2 = await getOrAcquireSandbox(signal);
3853
+ signal?.throwIfAborted();
3787
3854
  await probeSession(activeSandbox2);
3855
+ signal?.throwIfAborted();
3788
3856
  await extendKeepAlive(activeSandbox2);
3789
3857
  startKeepAlive(activeSandbox2);
3790
3858
  return activeSandbox2;
@@ -3793,11 +3861,11 @@ function createSandboxRuntime(options) {
3793
3861
  sandboxRef() {
3794
3862
  return sandboxRef ? { ...sandboxRef } : void 0;
3795
3863
  },
3796
- async acquire() {
3797
- return await getOrAcquireSandbox();
3864
+ async acquire(signal) {
3865
+ return await getOrAcquireSandbox(signal);
3798
3866
  },
3799
- async tools() {
3800
- return createToolExecutors(await ensureReadySandbox());
3867
+ async tools(signal) {
3868
+ return createToolExecutors(await ensureReadySandbox(signal));
3801
3869
  },
3802
3870
  async refreshNetworkPolicy(traceHeaders) {
3803
3871
  const active = activeSandbox;
@@ -5319,14 +5387,14 @@ function createSandbox(options) {
5319
5387
  setToolCallSpanAttributes,
5320
5388
  fileSystem() {
5321
5389
  signal?.throwIfAborted();
5322
- return fileSystemPromise ??= runtime.tools().then(({ fs: fs5 }) => {
5390
+ return fileSystemPromise ??= runtime.tools(signal).then(({ fs: fs5 }) => {
5323
5391
  signal?.throwIfAborted();
5324
5392
  return bindSandboxFileSystem(fs5, signal);
5325
5393
  });
5326
5394
  },
5327
5395
  commandRunner() {
5328
5396
  signal?.throwIfAborted();
5329
- return commandRunnerPromise ??= runtime.tools().then(({ runCommand }) => {
5397
+ return commandRunnerPromise ??= runtime.tools(signal).then(({ runCommand }) => {
5330
5398
  signal?.throwIfAborted();
5331
5399
  return async (input) => await runCommand({
5332
5400
  ...input,
@@ -5382,7 +5450,7 @@ function createSandbox(options) {
5382
5450
  logSandboxBootRequest("tool.bash", {
5383
5451
  "app.sandbox.command_length": command.length
5384
5452
  });
5385
- const { bash: executeBash, sessionId: activeSessionId } = await runtime.tools();
5453
+ const { bash: executeBash, sessionId: activeSessionId } = await runtime.tools(context.signal);
5386
5454
  await clearEgressSignals(activeSessionId);
5387
5455
  const result = await withSandboxToolSpan(
5388
5456
  "bash",
@@ -6490,6 +6558,7 @@ var McpToolManager = class {
6490
6558
  try {
6491
6559
  const client = await this.getClient(plugin);
6492
6560
  const tools = this.filterListedTools(plugin, await client.listTools());
6561
+ this.assertWrappedToolsAvailable(plugin, tools);
6493
6562
  this.toolsByProvider.set(
6494
6563
  provider,
6495
6564
  tools.map((tool) => this.toManagedTool(plugin, client, tool))
@@ -6540,8 +6609,26 @@ var McpToolManager = class {
6540
6609
  `Plugin ${plugin.manifest.name} MCP discovery missing allowlisted tools: ${missingTools.join(", ")}`
6541
6610
  );
6542
6611
  }
6543
- const allowedToolSet = new Set(allowedTools);
6544
- return tools.filter((tool) => allowedToolSet.has(tool.name));
6612
+ const loadedToolSet = /* @__PURE__ */ new Set([
6613
+ ...allowedTools,
6614
+ ...plugin.manifest.mcp?.wrappedTools ?? []
6615
+ ]);
6616
+ return tools.filter((tool) => loadedToolSet.has(tool.name));
6617
+ }
6618
+ assertWrappedToolsAvailable(plugin, tools) {
6619
+ const wrappedTools = plugin.manifest.mcp?.wrappedTools ?? [];
6620
+ if (wrappedTools.length === 0) {
6621
+ return;
6622
+ }
6623
+ const availableToolNames = new Set(tools.map((tool) => tool.name));
6624
+ const missingTools = wrappedTools.filter(
6625
+ (toolName) => !availableToolNames.has(toolName)
6626
+ );
6627
+ if (missingTools.length > 0) {
6628
+ throw new Error(
6629
+ `Plugin ${plugin.manifest.name} MCP discovery missing wrapped tools: ${missingTools.join(", ")}`
6630
+ );
6631
+ }
6545
6632
  }
6546
6633
  async getClient(plugin) {
6547
6634
  const existing = this.clientsByProvider.get(plugin.manifest.name);
@@ -6627,8 +6714,13 @@ var McpToolManager = class {
6627
6714
  "gen_ai.tool.call.result": resultAttribute
6628
6715
  });
6629
6716
  }
6717
+ const providerContent = boundMcpContent(
6718
+ toAgentToolContent(result)
6719
+ );
6630
6720
  return {
6631
- content: toModelVisibleMcpContent(result)
6721
+ content: toModelVisibleMcpContent(result),
6722
+ providerContent,
6723
+ ...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : {}
6632
6724
  };
6633
6725
  } catch (error) {
6634
6726
  if (error instanceof McpAuthorizationRequiredError && await this.handleAuthorizationRequired(
@@ -6639,7 +6731,9 @@ var McpToolManager = class {
6639
6731
  { type: "text", text: "Authorization pending." }
6640
6732
  ];
6641
6733
  return {
6642
- content: parkedContent
6734
+ authorizationPending: true,
6735
+ content: parkedContent,
6736
+ providerContent: parkedContent
6643
6737
  };
6644
6738
  }
6645
6739
  const errorAttributes = {
@@ -6692,10 +6786,59 @@ var McpToolManager = class {
6692
6786
  if (options.provider && provider !== options.provider) {
6693
6787
  continue;
6694
6788
  }
6695
- resolved.push(...this.toolsByProvider.get(provider) ?? []);
6789
+ const wrappedTools = new Set(
6790
+ this.pluginsByProvider.get(provider)?.manifest.mcp?.wrappedTools ?? []
6791
+ );
6792
+ resolved.push(
6793
+ ...(this.toolsByProvider.get(provider) ?? []).filter(
6794
+ (tool) => !wrappedTools.has(tool.rawName)
6795
+ )
6796
+ );
6696
6797
  }
6697
6798
  return resolved;
6698
6799
  }
6800
+ /** Call one active provider tool declared for plugin-owned wrapping. */
6801
+ async callWrappedTool(provider, rawName, args, options) {
6802
+ if (!this.activeProviders.has(provider)) {
6803
+ throw new McpToolError(`MCP provider is not active: ${provider}`);
6804
+ }
6805
+ const wrappedTools = new Set(
6806
+ this.pluginsByProvider.get(provider)?.manifest.mcp?.wrappedTools ?? []
6807
+ );
6808
+ if (!wrappedTools.has(rawName)) {
6809
+ throw new McpToolError(
6810
+ `Plugin ${provider} cannot call unwrapped MCP tool ${rawName}`
6811
+ );
6812
+ }
6813
+ const tool = (this.toolsByProvider.get(provider) ?? []).find(
6814
+ (candidate) => candidate.rawName === rawName
6815
+ );
6816
+ if (!tool) {
6817
+ throw new McpToolError(
6818
+ `MCP provider ${provider} does not expose tool ${rawName}`
6819
+ );
6820
+ }
6821
+ let result;
6822
+ try {
6823
+ result = await tool.execute(args, {
6824
+ conversationPrivacy: "private",
6825
+ ...options?.toolCallId ? { toolCallId: options.toolCallId } : {}
6826
+ });
6827
+ } catch (error) {
6828
+ if (error instanceof McpToolError) {
6829
+ return { status: "error", message: error.message };
6830
+ }
6831
+ throw error;
6832
+ }
6833
+ if (result.authorizationPending) {
6834
+ return { status: "authorization_pending" };
6835
+ }
6836
+ return {
6837
+ status: "success",
6838
+ content: result.providerContent ?? result.content,
6839
+ ...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : {}
6840
+ };
6841
+ }
6699
6842
  toToolDescriptor(tool) {
6700
6843
  return {
6701
6844
  name: tool.name,
@@ -7451,7 +7594,7 @@ function createViewImageTool(sandbox, supportsImageInput, deps = {}) {
7451
7594
  import { z as z16 } from "zod";
7452
7595
  function createReportProgressTool() {
7453
7596
  return zodTool({
7454
- description: "Update the user-visible assistant loading message with a short progress phase. For every non-trivial turn, call this early with the initial major work phase, then call it again only when the major phase meaningfully changes. Messages must be written in sentence case with a present-participle verb (e.g. 'Searching docs', 'Reviewing results', 'Running checks'). Skip trivial direct answers, generic filler, and minor substeps.",
7597
+ description: "Update the user-visible assistant loading message with a short progress phase. Use this only for work with multiple substantive phases or a materially long wait. Skip short lookups, routine commands, generic filler, and minor substeps. After an initial update, call it again only when the major phase meaningfully changes. Messages must be written in sentence case with a present-participle verb (e.g. 'Searching docs', 'Reviewing results', 'Running checks').",
7455
7598
  inputSchema: z16.object({
7456
7599
  message: z16.string().min(1).describe("Short user-facing progress message.")
7457
7600
  }),
@@ -10591,7 +10734,7 @@ var HANDOFF_TOOL_NAME = "handoff";
10591
10734
  function createHandoffTool(handoff) {
10592
10735
  const profileSchema = z38.enum(handoff.profiles);
10593
10736
  const handoffResultSchema = juniorToolResultSchema.extend({
10594
- model_profile: profileSchema
10737
+ model_profile: modelProfileSchema
10595
10738
  });
10596
10739
  const profileNames = handoff.profiles.map((profile) => `\`${profile}\``).join(", ");
10597
10740
  return zodTool({
@@ -14976,15 +15119,21 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
14976
15119
  activeModelProfile = args.profile;
14977
15120
  activeModelId = target.modelId;
14978
15121
  };
14979
- const requestHandoff = {
14980
- profiles: handoffProfiles,
14981
- execute: async (profile, options) => await scheduleHandoff({
14982
- profile,
14983
- signal: options.signal,
14984
- sourceMessages: [...agent.state.messages],
14985
- triggeringToolCallId: options.toolCallId
14986
- })
15122
+ const handoffControlFor = (activeProfile) => {
15123
+ const profiles = handoffProfiles.filter(
15124
+ (profile) => profile !== activeProfile
15125
+ );
15126
+ return profiles.length > 0 ? {
15127
+ profiles,
15128
+ execute: async (profile, options) => await scheduleHandoff({
15129
+ profile,
15130
+ signal: options.signal,
15131
+ sourceMessages: [...agent.state.messages],
15132
+ triggeringToolCallId: options.toolCallId
15133
+ })
15134
+ } : void 0;
14987
15135
  };
15136
+ const requestHandoff = handoffControlFor(activeModelProfile);
14988
15137
  setTags({
14989
15138
  ...runLogContext,
14990
15139
  modelId: activeModelId
@@ -15028,7 +15177,30 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
15028
15177
  mcpToolManager = wiring.mcpToolManager;
15029
15178
  closeTools = wiring.close;
15030
15179
  const getPendingAuthPause = wiring.getPendingAuthPause;
15031
- const toolsAfterHandoff = wiring.agentTools;
15180
+ const toolsWithoutHandoff = wiring.agentTools.filter(
15181
+ (tool) => tool.name !== HANDOFF_TOOL_NAME
15182
+ );
15183
+ const handoffAgentTool = wiring.agentTools.find(
15184
+ (tool) => tool.name === HANDOFF_TOOL_NAME
15185
+ );
15186
+ const toolsForActiveProfile = () => {
15187
+ const handoff = handoffControlFor(activeModelProfile);
15188
+ if (!handoff) {
15189
+ return toolsWithoutHandoff;
15190
+ }
15191
+ if (!handoffAgentTool) {
15192
+ throw new Error("Handoff control is missing its Pi tool");
15193
+ }
15194
+ const definition = createHandoffTool(handoff);
15195
+ return wiring.agentTools.map(
15196
+ (tool) => tool.name === HANDOFF_TOOL_NAME ? {
15197
+ ...handoffAgentTool,
15198
+ description: definition.description,
15199
+ parameters: definition.inputSchema,
15200
+ prepareArguments: definition.prepareArguments
15201
+ } : tool
15202
+ );
15203
+ };
15032
15204
  const {
15033
15205
  baseInstructions,
15034
15206
  inputMessages,
@@ -15066,7 +15238,8 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
15066
15238
  agent.state.messages = replacement;
15067
15239
  agent.state.model = model;
15068
15240
  agent.state.thinkingLevel = thinkingLevel;
15069
- agent.state.tools = toolsAfterHandoff;
15241
+ const tools = toolsForActiveProfile();
15242
+ agent.state.tools = tools;
15070
15243
  runResume.setBeforeMessageCount(replacement.length);
15071
15244
  runResume.setTurnStartMessageIndex(0);
15072
15245
  runResume.adoptCommittedBoundary(replacement);
@@ -15079,7 +15252,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
15079
15252
  context: {
15080
15253
  systemPrompt: baseInstructions,
15081
15254
  messages: replacement,
15082
- tools: toolsAfterHandoff
15255
+ tools
15083
15256
  },
15084
15257
  model,
15085
15258
  thinkingLevel
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createPluginCatalogRuntime
3
- } from "./chunk-R53UT2OI.js";
3
+ } from "./chunk-ET2SDCNV.js";
4
4
 
5
5
  // src/chat/plugins/catalog-runtime.ts
6
6
  var pluginCatalogRuntime = createPluginCatalogRuntime();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDb
3
- } from "./chunk-D3N4BPSL.js";
3
+ } from "./chunk-254MFDOF.js";
4
4
  import {
5
5
  juniorStats
6
6
  } from "./chunk-GCGJGSQL.js";
@@ -13,17 +13,17 @@ import {
13
13
  instructionProvenanceFor,
14
14
  sanitizePostgresJson,
15
15
  withConversationEventLock
16
- } from "./chunk-D3N4BPSL.js";
16
+ } from "./chunk-254MFDOF.js";
17
17
  import {
18
18
  getStateAdapter,
19
19
  sleep
20
- } from "./chunk-VJTWKJWQ.js";
20
+ } from "./chunk-UURFXX66.js";
21
21
  import {
22
22
  botConfig,
23
23
  escapeXml,
24
24
  resolveGatewayModel,
25
25
  unwrapCurrentInstruction
26
- } from "./chunk-VLTWQQKH.js";
26
+ } from "./chunk-IDXLBKPS.js";
27
27
  import {
28
28
  toStoredSlackActor
29
29
  } from "./chunk-HZF5P5UN.js";
@@ -32,7 +32,7 @@ import {
32
32
  logException,
33
33
  logWarn,
34
34
  setSpanAttributes
35
- } from "./chunk-ZJ6IVZVO.js";
35
+ } from "./chunk-JZ47AFSH.js";
36
36
  import {
37
37
  isRecord,
38
38
  toOptionalNumber,