@sentry/junior 0.136.1 → 0.138.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 (103) hide show
  1. package/dist/{agent-hooks-2KDSPPO4.js → agent-hooks-SCR74Q3E.js} +11 -9
  2. package/dist/api/conversations/projection.d.ts +1 -0
  3. package/dist/api/conversations/stats.d.ts +1 -0
  4. package/dist/api/schema/conversation.d.ts +2 -0
  5. package/dist/api/schema.js +1 -1
  6. package/dist/api.js +187 -46
  7. package/dist/app.d.ts +8 -1
  8. package/dist/app.js +519 -860
  9. package/dist/{catalog-runtime-WSZQGC4D.js → catalog-runtime-IU3QF4GG.js} +5 -5
  10. package/dist/chat/agent/request.d.ts +32 -2
  11. package/dist/chat/agent-dispatch/heartbeat.d.ts +5 -0
  12. package/dist/chat/agent-dispatch/types.d.ts +1 -1
  13. package/dist/chat/agent-invocations/errors.d.ts +8 -0
  14. package/dist/chat/agent-invocations/spawn.d.ts +12 -0
  15. package/dist/chat/agent-invocations/store.d.ts +44 -0
  16. package/dist/chat/agent-invocations/types.d.ts +449 -0
  17. package/dist/chat/agent-invocations/work.d.ts +31 -0
  18. package/dist/chat/config.d.ts +1 -0
  19. package/dist/chat/configuration/defaults.d.ts +1 -1
  20. package/dist/chat/conversations/sql/store.d.ts +8 -0
  21. package/dist/chat/conversations/store.d.ts +9 -1
  22. package/dist/chat/experimental.d.ts +16 -0
  23. package/dist/chat/pi/client.d.ts +1 -8
  24. package/dist/chat/pi/gateway-auth.d.ts +16 -0
  25. package/dist/chat/runtime/agent-runner.d.ts +2 -1
  26. package/dist/chat/sandbox/docker.d.ts +17 -0
  27. package/dist/chat/services/agent-continue.d.ts +2 -0
  28. package/dist/chat/services/auth-pause.d.ts +0 -1
  29. package/dist/chat/services/mcp-auth-orchestration.d.ts +3 -2
  30. package/dist/chat/services/plugin-auth-orchestration.d.ts +3 -2
  31. package/dist/chat/services/subscribed-reply-router-policy.d.ts +12 -0
  32. package/dist/chat/services/turn-session-routing.d.ts +17 -0
  33. package/dist/chat/slack/message.d.ts +6 -1
  34. package/dist/chat/slack/source-link.d.ts +8 -2
  35. package/dist/chat/slack/team-domain.d.ts +4 -0
  36. package/dist/chat/source.d.ts +5 -5
  37. package/dist/chat/state/turn-session.d.ts +0 -2
  38. package/dist/chat/task-execution/state.d.ts +23 -11
  39. package/dist/chat/task-execution/store.d.ts +20 -11
  40. package/dist/chat/task-execution/worker.d.ts +2 -2
  41. package/dist/chat/tools/runtime/spawn-agent.d.ts +31 -0
  42. package/dist/chat/tools/types.d.ts +2 -0
  43. package/dist/chunk-3Y47VMHV.js +6 -0
  44. package/dist/chunk-5IDFPCON.js +46 -0
  45. package/dist/chunk-5LTJ4ITU.js +1523 -0
  46. package/dist/{chunk-KLBYCSLJ.js → chunk-5MXWHTCK.js} +17 -434
  47. package/dist/{chunk-CZZDCH3Q.js → chunk-A7WCHXZV.js} +206 -78
  48. package/dist/{chunk-4YQ6I6VF.js → chunk-BOLJOV5T.js} +2 -56
  49. package/dist/{chunk-XCZ6COFO.js → chunk-BYW4B4PR.js} +90 -54
  50. package/dist/{chunk-JQRTXJHD.js → chunk-C7ZVPO4Z.js} +2 -1
  51. package/dist/{chunk-MW2QRPGW.js → chunk-DCLLQGS6.js} +119 -50
  52. package/dist/{chunk-CDVCCOMF.js → chunk-E5UYAIKJ.js} +75 -1475
  53. package/dist/{chunk-3SUK3UXX.js → chunk-ELKW5FIB.js} +5 -5
  54. package/dist/chunk-EM225ITJ.js +56 -0
  55. package/dist/{chunk-Y6JNHTRD.js → chunk-FEUNPTGV.js} +34 -70
  56. package/dist/{chunk-TYNMSQKA.js → chunk-FNLBTB4K.js} +1 -1
  57. package/dist/{chunk-TRZSM67C.js → chunk-HCIVH3JS.js} +1 -0
  58. package/dist/chunk-HIWJWWMT.js +668 -0
  59. package/dist/chunk-IUFM5JWV.js +24 -0
  60. package/dist/{chunk-XWPA5KZF.js → chunk-JNNJZURV.js} +1 -1
  61. package/dist/{chunk-6ZK6FZIV.js → chunk-KCBZSJRU.js} +6 -27
  62. package/dist/{chunk-BG3KWWDJ.js → chunk-KDCHVT25.js} +1 -1
  63. package/dist/{chunk-VH6MI4L7.js → chunk-KFRHRSCJ.js} +1 -1
  64. package/dist/chunk-LPVUNO2W.js +320 -0
  65. package/dist/{chunk-G66RYKRS.js → chunk-N7WARMC6.js} +16 -776
  66. package/dist/chunk-PB3CXNVL.js +41 -0
  67. package/dist/chunk-Q6QZTTLS.js +55 -0
  68. package/dist/{chunk-3QNJOHKG.js → chunk-QS527AV5.js} +1 -1
  69. package/dist/chunk-R776HKPK.js +81 -0
  70. package/dist/{chunk-OTJMQYVP.js → chunk-RZIBSCYC.js} +517 -608
  71. package/dist/chunk-SD3OFRWY.js +714 -0
  72. package/dist/{chunk-HIRIWTWD.js → chunk-SIPKWSXK.js} +58 -10
  73. package/dist/chunk-TCS76X5D.js +441 -0
  74. package/dist/{chunk-UX2TNH5D.js → chunk-TDJCLNDH.js} +3 -3
  75. package/dist/{chunk-NVVBEJUB.js → chunk-TUUDXEXU.js} +336 -300
  76. package/dist/{chunk-22Z6MGMK.js → chunk-VPZFVJND.js} +1 -1
  77. package/dist/{chunk-RFDD3Z2I.js → chunk-YU5QUF67.js} +1 -1
  78. package/dist/chunk-ZBSMCXKV.js +710 -0
  79. package/dist/{chunk-FSYXYBWU.js → chunk-ZXNTJJIE.js} +2 -2
  80. package/dist/cli/chat.js +65 -26
  81. package/dist/cli/check.js +7 -7
  82. package/dist/cli/plugins.js +14 -12
  83. package/dist/cli/snapshot-create.js +10 -9
  84. package/dist/cli/upgrade.js +7 -7
  85. package/dist/conversation-work-KATFHLG3.js +56 -0
  86. package/dist/db/schema/agent-invocations.d.ts +544 -0
  87. package/dist/db/schema.d.ts +543 -1
  88. package/dist/{db-Z2NNL2JC.js → db-UO2IWXGA.js} +7 -7
  89. package/dist/experimental-HH6OM6UH.js +13 -0
  90. package/dist/instrumentation.js +4 -4
  91. package/dist/nitro.js +4 -3
  92. package/dist/{oauth-callback-server-PO3M5JMG.js → oauth-callback-server-MAQI43LX.js} +26 -18
  93. package/dist/{runner-QHQYZYJA.js → runner-PIUQEXKE.js} +26 -14
  94. package/dist/{skills-KXMT3DRA.js → skills-4ARJADHQ.js} +6 -6
  95. package/dist/spawn-G2AWPMCT.js +38 -0
  96. package/dist/{validation-Y42ULTT6.js → validation-S3EE3HWL.js} +6 -6
  97. package/dist/version.js +1 -1
  98. package/dist/work-UARRUAW3.js +46 -0
  99. package/dist/worker-DOCIRVD3.js +24 -0
  100. package/migrations/0021_first_warhawk.sql +35 -0
  101. package/migrations/meta/0021_snapshot.json +2176 -0
  102. package/migrations/meta/_journal.json +8 -1
  103. package/package.json +6 -5
@@ -1,19 +1,21 @@
1
1
  import {
2
2
  SANDBOX_WORKSPACE_ROOT,
3
- getStateAdapter,
4
3
  sleep
5
- } from "./chunk-4YQ6I6VF.js";
4
+ } from "./chunk-EM225ITJ.js";
5
+ import {
6
+ getStateAdapter
7
+ } from "./chunk-BOLJOV5T.js";
6
8
  import {
7
9
  toOptionalTrimmed
8
- } from "./chunk-XCZ6COFO.js";
10
+ } from "./chunk-BYW4B4PR.js";
9
11
  import {
10
12
  pluginCatalogRuntime
11
- } from "./chunk-3QNJOHKG.js";
13
+ } from "./chunk-QS527AV5.js";
12
14
  import {
13
15
  setSpanAttributes,
14
16
  setSpanStatus,
15
17
  withSpan
16
- } from "./chunk-XWPA5KZF.js";
18
+ } from "./chunk-JNNJZURV.js";
17
19
 
18
20
  // src/chat/sandbox/resources.ts
19
21
  var configuredResources;
@@ -50,12 +52,181 @@ function getSandboxResources() {
50
52
  // src/chat/sandbox/snapshot/profile.ts
51
53
  import { createHash } from "crypto";
52
54
 
55
+ // src/chat/sandbox/noninteractive-command.ts
56
+ var NON_INTERACTIVE_ENV = {
57
+ CI: "1",
58
+ TERM: "dumb",
59
+ NO_COLOR: "1",
60
+ PAGER: "cat",
61
+ GIT_PAGER: "cat",
62
+ GH_PROMPT_DISABLED: "1",
63
+ GH_NO_UPDATE_NOTIFIER: "1",
64
+ GH_NO_EXTENSION_UPDATE_NOTIFIER: "1",
65
+ GH_SPINNER_DISABLED: "1",
66
+ GIT_TERMINAL_PROMPT: "0",
67
+ GCM_INTERACTIVE: "never",
68
+ DEBIAN_FRONTEND: "noninteractive",
69
+ // Git credential isolation: prevent git from sending its own auth so the
70
+ // sandbox egress proxy's header transforms are the sole credential source.
71
+ GIT_ASKPASS: "/bin/true",
72
+ GIT_CONFIG_NOSYSTEM: "1",
73
+ GIT_CONFIG_COUNT: "2",
74
+ GIT_CONFIG_KEY_0: "credential.helper",
75
+ GIT_CONFIG_VALUE_0: "",
76
+ GIT_CONFIG_KEY_1: "http.emptyAuth",
77
+ GIT_CONFIG_VALUE_1: "true"
78
+ };
79
+ function shellQuote(value) {
80
+ return `'${value.replace(/'/g, "'\\''")}'`;
81
+ }
82
+ function buildEnvExports(options) {
83
+ const lines = [];
84
+ if (options.pathPrefix) {
85
+ lines.push(`export PATH="${options.pathPrefix}"`);
86
+ }
87
+ for (const [key, value] of Object.entries(NON_INTERACTIVE_ENV)) {
88
+ lines.push(`export ${key}=${shellQuote(value)}`);
89
+ }
90
+ for (const [key, value] of Object.entries(options.env ?? {})) {
91
+ lines.push(`export ${key}=${shellQuote(value)}`);
92
+ }
93
+ return lines;
94
+ }
95
+ function buildCommandScript(input) {
96
+ return [shellQuote(input.cmd), ...(input.args ?? []).map(shellQuote)].join(
97
+ " "
98
+ );
99
+ }
100
+ function buildNonInteractiveShellScript(script, options = {}) {
101
+ return [...buildEnvExports(options), "exec </dev/null", script].join(" && ");
102
+ }
103
+ function buildNonInteractiveCommand(input) {
104
+ return {
105
+ cmd: "bash",
106
+ args: [
107
+ input.login ? "-lc" : "-c",
108
+ buildNonInteractiveShellScript(buildCommandScript(input), {
109
+ env: input.env,
110
+ pathPrefix: input.pathPrefix
111
+ })
112
+ ]
113
+ };
114
+ }
115
+ async function runNonInteractiveCommand(sandbox, input) {
116
+ const command = {
117
+ ...buildNonInteractiveCommand(input),
118
+ ...input.cwd ? { cwd: input.cwd } : {},
119
+ ...input.signal ? { signal: input.signal } : {},
120
+ ...input.sudo !== void 0 ? { sudo: input.sudo } : {}
121
+ };
122
+ return await sandbox.runCommand(command);
123
+ }
124
+
125
+ // src/chat/sandbox/docker.ts
126
+ var DOCKER_DAEMON_JSON = `{
127
+ "storage-driver": "overlay2",
128
+ "live-restore": false
129
+ }
130
+ `;
131
+ var DOCKER_ENSURE_SCRIPT = `#!/bin/sh
132
+ set -eu
133
+
134
+ if [ "$(id -u)" -ne 0 ]; then
135
+ exec sudo -n "$0" "$@"
136
+ fi
137
+
138
+ SOCK=/var/run/docker.sock
139
+ PIDFILE=/var/run/docker.pid
140
+ LOG=/var/log/junior-dockerd.log
141
+
142
+ is_ready() {
143
+ [ -S "$SOCK" ] && /usr/bin/docker info >/dev/null 2>&1
144
+ }
145
+
146
+ if is_ready; then
147
+ chmod 666 "$SOCK" 2>/dev/null || true
148
+ exit 0
149
+ fi
150
+
151
+ mkdir -p /etc/docker /var/lib/docker /var/run /var/log
152
+ if [ ! -f /etc/docker/daemon.json ]; then
153
+ cat > /etc/docker/daemon.json <<'EOF'
154
+ {
155
+ "storage-driver": "overlay2",
156
+ "live-restore": false
157
+ }
158
+ EOF
159
+ fi
160
+
161
+ if [ -f "$PIDFILE" ]; then
162
+ oldpid="$(cat "$PIDFILE" 2>/dev/null || true)"
163
+ if [ -n "\${oldpid:-}" ] && ! kill -0 "$oldpid" 2>/dev/null; then
164
+ rm -f "$PIDFILE"
165
+ fi
166
+ fi
167
+
168
+ if [ ! -f "$PIDFILE" ] || ! kill -0 "$(cat "$PIDFILE" 2>/dev/null)" 2>/dev/null; then
169
+ # dockerd must outlive this helper; nohup + background is intentional.
170
+ nohup dockerd --host="unix://$SOCK" --pidfile="$PIDFILE" >"$LOG" 2>&1 &
171
+ fi
172
+
173
+ i=0
174
+ while [ "$i" -lt 50 ]; do
175
+ if is_ready; then
176
+ chmod 666 "$SOCK" 2>/dev/null || true
177
+ exit 0
178
+ fi
179
+ i=$((i + 1))
180
+ sleep 0.1
181
+ done
182
+
183
+ echo "junior-ensure-docker: dockerd failed to become ready" >&2
184
+ if [ -f "$LOG" ]; then
185
+ tail -n 50 "$LOG" >&2 || true
186
+ fi
187
+ exit 1
188
+ `;
189
+ var DOCKER_CLI_WRAPPER_SCRIPT = `#!/bin/sh
190
+ set -eu
191
+ if command -v junior-ensure-docker >/dev/null 2>&1; then
192
+ junior-ensure-docker
193
+ fi
194
+ exec /usr/bin/docker "$@"
195
+ `;
196
+ var DOCKER_COMPOSE_CLI_WRAPPER_SCRIPT = `#!/bin/sh
197
+ set -eu
198
+ if command -v junior-ensure-docker >/dev/null 2>&1; then
199
+ junior-ensure-docker
200
+ fi
201
+ exec /usr/local/libexec/junior-docker-compose "$@"
202
+ `;
203
+ async function ensureDockerDaemon(sandbox, signal) {
204
+ await runNonInteractiveCommand(sandbox, {
205
+ cmd: "sh",
206
+ args: [
207
+ "-c",
208
+ "command -v junior-ensure-docker >/dev/null 2>&1 && junior-ensure-docker || true"
209
+ ],
210
+ signal
211
+ });
212
+ }
213
+
53
214
  // src/chat/sandbox/runtime-dependencies.ts
54
215
  var GLOBAL_RUNTIME_DEPENDENCIES = [
55
216
  { type: "system", package: "docker" },
56
217
  { type: "system", package: "spal-release" },
57
218
  { type: "system", package: "ripgrep" }
58
219
  ];
220
+ function writeFileCommand(path, contents, mode = "0644") {
221
+ const payload = Buffer.from(contents, "utf8").toString("base64");
222
+ return [
223
+ `printf '%s' '${payload}' | base64 -d > ${path}`,
224
+ `chmod ${mode} ${path}`
225
+ ].join("\n");
226
+ }
227
+ function writeExecutableCommand(path, contents) {
228
+ return writeFileCommand(path, contents, "0755");
229
+ }
59
230
  var GLOBAL_RUNTIME_POSTINSTALL = [
60
231
  {
61
232
  cmd: "sh",
@@ -72,9 +243,35 @@ var GLOBAL_RUNTIME_POSTINSTALL = [
72
243
  `trap 'rm -f "$tmp"' EXIT`,
73
244
  'curl --fail --location --silent --show-error "https://github.com/docker/compose/releases/download/v2.39.4/docker-compose-linux-${asset}" --output "$tmp"',
74
245
  'echo "${sha256} ${tmp}" | sha256sum --check --status',
75
- 'install -D -m 0755 "$tmp" /usr/local/bin/docker-compose',
76
- "mkdir -p /usr/local/lib/docker/cli-plugins",
77
- "ln -sf /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose"
246
+ // Keep the real Compose binary off PATH; the wrapper below starts dockerd.
247
+ 'install -D -m 0755 "$tmp" /usr/local/libexec/junior-docker-compose',
248
+ "mkdir -p /usr/local/lib/docker/cli-plugins /usr/local/libexec /etc/docker /usr/local/bin",
249
+ `mkdir -p ${SANDBOX_WORKSPACE_ROOT}/.junior/bin`,
250
+ writeFileCommand("/etc/docker/daemon.json", DOCKER_DAEMON_JSON),
251
+ writeExecutableCommand(
252
+ "/usr/local/bin/junior-ensure-docker",
253
+ DOCKER_ENSURE_SCRIPT
254
+ ),
255
+ // docker compose plugin delegates to the real Compose binary.
256
+ "ln -sfn /usr/local/libexec/junior-docker-compose /usr/local/lib/docker/cli-plugins/docker-compose",
257
+ // PATH wrappers auto-start dockerd for both CLI entrypoints.
258
+ writeExecutableCommand(
259
+ "/usr/local/bin/docker-compose",
260
+ DOCKER_COMPOSE_CLI_WRAPPER_SCRIPT
261
+ ),
262
+ writeExecutableCommand(
263
+ `${SANDBOX_WORKSPACE_ROOT}/.junior/bin/docker`,
264
+ DOCKER_CLI_WRAPPER_SCRIPT
265
+ ),
266
+ writeExecutableCommand(
267
+ `${SANDBOX_WORKSPACE_ROOT}/.junior/bin/docker-compose`,
268
+ DOCKER_COMPOSE_CLI_WRAPPER_SCRIPT
269
+ ),
270
+ // Prefer the wrapper over /usr/bin/docker for non-login shells too.
271
+ writeExecutableCommand(
272
+ "/usr/local/bin/docker",
273
+ DOCKER_CLI_WRAPPER_SCRIPT
274
+ )
78
275
  ].join("\n")
79
276
  ],
80
277
  sudo: true
@@ -176,76 +373,6 @@ function getVercelSandboxCredentials() {
176
373
  return void 0;
177
374
  }
178
375
 
179
- // src/chat/sandbox/noninteractive-command.ts
180
- var NON_INTERACTIVE_ENV = {
181
- CI: "1",
182
- TERM: "dumb",
183
- NO_COLOR: "1",
184
- PAGER: "cat",
185
- GIT_PAGER: "cat",
186
- GH_PROMPT_DISABLED: "1",
187
- GH_NO_UPDATE_NOTIFIER: "1",
188
- GH_NO_EXTENSION_UPDATE_NOTIFIER: "1",
189
- GH_SPINNER_DISABLED: "1",
190
- GIT_TERMINAL_PROMPT: "0",
191
- GCM_INTERACTIVE: "never",
192
- DEBIAN_FRONTEND: "noninteractive",
193
- // Git credential isolation: prevent git from sending its own auth so the
194
- // sandbox egress proxy's header transforms are the sole credential source.
195
- GIT_ASKPASS: "/bin/true",
196
- GIT_CONFIG_NOSYSTEM: "1",
197
- GIT_CONFIG_COUNT: "2",
198
- GIT_CONFIG_KEY_0: "credential.helper",
199
- GIT_CONFIG_VALUE_0: "",
200
- GIT_CONFIG_KEY_1: "http.emptyAuth",
201
- GIT_CONFIG_VALUE_1: "true"
202
- };
203
- function shellQuote(value) {
204
- return `'${value.replace(/'/g, "'\\''")}'`;
205
- }
206
- function buildEnvExports(options) {
207
- const lines = [];
208
- if (options.pathPrefix) {
209
- lines.push(`export PATH="${options.pathPrefix}"`);
210
- }
211
- for (const [key, value] of Object.entries(NON_INTERACTIVE_ENV)) {
212
- lines.push(`export ${key}=${shellQuote(value)}`);
213
- }
214
- for (const [key, value] of Object.entries(options.env ?? {})) {
215
- lines.push(`export ${key}=${shellQuote(value)}`);
216
- }
217
- return lines;
218
- }
219
- function buildCommandScript(input) {
220
- return [shellQuote(input.cmd), ...(input.args ?? []).map(shellQuote)].join(
221
- " "
222
- );
223
- }
224
- function buildNonInteractiveShellScript(script, options = {}) {
225
- return [...buildEnvExports(options), "exec </dev/null", script].join(" && ");
226
- }
227
- function buildNonInteractiveCommand(input) {
228
- return {
229
- cmd: "bash",
230
- args: [
231
- input.login ? "-lc" : "-c",
232
- buildNonInteractiveShellScript(buildCommandScript(input), {
233
- env: input.env,
234
- pathPrefix: input.pathPrefix
235
- })
236
- ]
237
- };
238
- }
239
- async function runNonInteractiveCommand(sandbox, input) {
240
- const command = {
241
- ...buildNonInteractiveCommand(input),
242
- ...input.cwd ? { cwd: input.cwd } : {},
243
- ...input.signal ? { signal: input.signal } : {},
244
- ...input.sudo !== void 0 ? { sudo: input.sudo } : {}
245
- };
246
- return await sandbox.runCommand(command);
247
- }
248
-
249
376
  // src/chat/sandbox/snapshot/span.ts
250
377
  async function trace(name, op, attributes, callback) {
251
378
  return await withSpan(name, op, {}, callback, attributes);
@@ -1076,6 +1203,7 @@ export {
1076
1203
  wrapSandboxSetupError,
1077
1204
  throwSandboxOperationError,
1078
1205
  getVercelSandboxCredentials,
1206
+ ensureDockerDaemon,
1079
1207
  getSandboxResourceConfig,
1080
1208
  setSandboxResourceConfig,
1081
1209
  getSandboxResources,
@@ -1,31 +1,6 @@
1
1
  import {
2
2
  getChatConfig
3
- } from "./chunk-XCZ6COFO.js";
4
-
5
- // src/chat/sandbox/paths.ts
6
- function normalizeWorkspaceRoot(input) {
7
- const candidate = (input ?? "").trim();
8
- if (!candidate) {
9
- return "/vercel/sandbox";
10
- }
11
- const normalized = candidate.replace(/\/+$/, "");
12
- return normalized.startsWith("/") ? normalized : `/${normalized}`;
13
- }
14
- var SANDBOX_WORKSPACE_ROOT = normalizeWorkspaceRoot(
15
- process.env.VERCEL_SANDBOX_WORKSPACE_DIR
16
- );
17
- var SANDBOX_SKILLS_ROOT = `${SANDBOX_WORKSPACE_ROOT}/skills`;
18
- var SANDBOX_DATA_ROOT = `${SANDBOX_WORKSPACE_ROOT}/data`;
19
- function sandboxSkillDir(skillName) {
20
- return `${SANDBOX_SKILLS_ROOT}/${skillName}`;
21
- }
22
- function sandboxSkillFile(skillName) {
23
- return `${sandboxSkillDir(skillName)}/SKILL.md`;
24
- }
25
- function sandboxSkillPathResolution(skillName) {
26
- const skillDir = sandboxSkillDir(skillName);
27
- return `Resolve relative paths in this skill against ${skillDir}. For bash commands from this skill, cd to ${skillDir} first or use absolute paths.`;
28
- }
3
+ } from "./chunk-BYW4B4PR.js";
29
4
 
30
5
  // src/chat/state/adapter.ts
31
6
  import { createMemoryState } from "@chat-adapter/state-memory";
@@ -296,38 +271,9 @@ async function disconnectStateAdapter() {
296
271
  }
297
272
  }
298
273
 
299
- // src/chat/sleep.ts
300
- function sleep(ms, signal) {
301
- if (!signal) {
302
- return new Promise((resolve) => setTimeout(resolve, ms));
303
- }
304
- return new Promise((resolve, reject) => {
305
- if (signal.aborted) {
306
- reject(signal.reason);
307
- return;
308
- }
309
- const timeoutId = setTimeout(() => {
310
- signal.removeEventListener("abort", onAbort);
311
- resolve();
312
- }, ms);
313
- const onAbort = () => {
314
- clearTimeout(timeoutId);
315
- reject(signal.reason);
316
- };
317
- signal.addEventListener("abort", onAbort, { once: true });
318
- });
319
- }
320
-
321
274
  export {
322
- SANDBOX_WORKSPACE_ROOT,
323
- SANDBOX_SKILLS_ROOT,
324
- SANDBOX_DATA_ROOT,
325
- sandboxSkillDir,
326
- sandboxSkillFile,
327
- sandboxSkillPathResolution,
328
275
  acquireActiveLock,
329
276
  getDefaultRedisStateAdapterFor,
330
277
  getStateAdapter,
331
- disconnectStateAdapter,
332
- sleep
278
+ disconnectStateAdapter
333
279
  };
@@ -3,7 +3,7 @@ import {
3
3
  toCanonicalInputMessage,
4
4
  toCanonicalOutputMessage,
5
5
  toGenAiMessagesTraceAttributes
6
- } from "./chunk-22Z6MGMK.js";
6
+ } from "./chunk-VPZFVJND.js";
7
7
  import {
8
8
  extractGenAiUsageAttributes,
9
9
  logException,
@@ -11,42 +11,7 @@ import {
11
11
  normalizeGenAiFinishReason,
12
12
  serializeGenAiAttribute,
13
13
  withSpan
14
- } from "./chunk-XWPA5KZF.js";
15
-
16
- // src/chat/config.ts
17
- import { getModel as getModel2 } from "@earendil-works/pi-ai/compat";
18
-
19
- // src/chat/optional-string.ts
20
- function toOptionalTrimmed(value) {
21
- if (!value) {
22
- return void 0;
23
- }
24
- const trimmed = value.trim();
25
- return trimmed.length > 0 ? trimmed : void 0;
26
- }
27
-
28
- // src/chat/pi/sdk.ts
29
- import {
30
- calculateCost,
31
- completeSimple,
32
- getEnvApiKey,
33
- getModel,
34
- getModels,
35
- isRetryableAssistantError,
36
- registerApiProvider
37
- } from "@earendil-works/pi-ai/compat";
38
- import {
39
- stream,
40
- streamSimple
41
- } from "@earendil-works/pi-ai/api/anthropic-messages";
42
-
43
- // src/chat/pi/client.ts
44
- import { createGatewayProvider } from "@ai-sdk/gateway";
45
- import {
46
- embedMany,
47
- generateObject,
48
- NoObjectGeneratedError
49
- } from "ai";
14
+ } from "./chunk-JNNJZURV.js";
50
15
 
51
16
  // src/chat/services/provider-error.ts
52
17
  var ProviderError = class extends Error {
@@ -230,6 +195,64 @@ function getProviderErrorAttributes(error) {
230
195
  };
231
196
  }
232
197
 
198
+ // src/chat/config.ts
199
+ import { getModel as getModel2 } from "@earendil-works/pi-ai/compat";
200
+
201
+ // src/chat/optional-string.ts
202
+ function toOptionalTrimmed(value) {
203
+ if (!value) {
204
+ return void 0;
205
+ }
206
+ const trimmed = value.trim();
207
+ return trimmed.length > 0 ? trimmed : void 0;
208
+ }
209
+
210
+ // src/chat/pi/sdk.ts
211
+ import {
212
+ calculateCost,
213
+ completeSimple,
214
+ getEnvApiKey,
215
+ getModel,
216
+ getModels,
217
+ isRetryableAssistantError,
218
+ registerApiProvider
219
+ } from "@earendil-works/pi-ai/compat";
220
+ import {
221
+ stream,
222
+ streamSimple
223
+ } from "@earendil-works/pi-ai/api/anthropic-messages";
224
+
225
+ // src/chat/pi/client.ts
226
+ import { createGatewayProvider } from "@ai-sdk/gateway";
227
+
228
+ // src/chat/pi/gateway-auth.ts
229
+ import { getVercelOidcToken } from "@vercel/oidc";
230
+ var MISSING_GATEWAY_CREDENTIALS_ERROR = "Missing AI gateway credentials (enable Vercel OIDC or set AI_GATEWAY_API_KEY)";
231
+ async function resolveGatewayCredential() {
232
+ try {
233
+ const oidcToken = toOptionalTrimmed(await getVercelOidcToken());
234
+ if (oidcToken) {
235
+ return { mode: "oidc", token: oidcToken };
236
+ }
237
+ } catch {
238
+ }
239
+ const apiKey = toOptionalTrimmed(getEnvApiKey("vercel-ai-gateway"));
240
+ if (apiKey) {
241
+ return { mode: "api_key", token: apiKey };
242
+ }
243
+ return void 0;
244
+ }
245
+ async function getGatewayApiKey() {
246
+ return (await resolveGatewayCredential())?.token;
247
+ }
248
+
249
+ // src/chat/pi/client.ts
250
+ import {
251
+ embedMany,
252
+ generateObject,
253
+ NoObjectGeneratedError
254
+ } from "ai";
255
+
233
256
  // src/chat/xml.ts
234
257
  function escapeXml(value) {
235
258
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -332,17 +355,10 @@ var EMBEDDING_INPUT_COST_USD_PER_MILLION_TOKENS = {
332
355
  "voyage/voyage-3.5": 0.06,
333
356
  "voyage/voyage-3.5-lite": 0.02
334
357
  };
335
- var MISSING_GATEWAY_CREDENTIALS_ERROR = "Missing AI gateway credentials (AI_GATEWAY_API_KEY or VERCEL_OIDC_TOKEN)";
336
358
  function embeddingCostUsd(modelId, inputTokens) {
337
359
  const costPerMillionTokens = EMBEDDING_INPUT_COST_USD_PER_MILLION_TOKENS[modelId];
338
360
  return costPerMillionTokens === void 0 ? void 0 : inputTokens * costPerMillionTokens / 1e6;
339
361
  }
340
- function getGatewayApiKey() {
341
- return toOptionalTrimmed(getEnvApiKey("vercel-ai-gateway")) ?? toOptionalTrimmed(process.env.VERCEL_OIDC_TOKEN);
342
- }
343
- function getPiGatewayApiKey() {
344
- return getGatewayApiKey();
345
- }
346
362
  function extractText(message) {
347
363
  return (message.content ?? []).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text ?? "").join("").trim();
348
364
  }
@@ -357,8 +373,9 @@ function resolveGatewayModel(modelId) {
357
373
  }
358
374
  async function completeText(params) {
359
375
  const model = resolveGatewayModel(params.modelId);
360
- const apiKey = getPiGatewayApiKey();
361
- const authMode = toOptionalTrimmed(process.env.AI_GATEWAY_API_KEY) ? "api_key" : toOptionalTrimmed(process.env.VERCEL_OIDC_TOKEN) ? "oidc" : "api_key";
376
+ const credential = await resolveGatewayCredential();
377
+ const apiKey = credential?.token;
378
+ const authMode = credential?.mode ?? "api_key";
362
379
  const effectivePrivacy = getCurrentConversationPrivacy() ?? "private";
363
380
  const messageAttributeMode = params.messageAttributeMode ?? (effectivePrivacy === "public" ? "content" : "metadata");
364
381
  const requestMessagesAttribute = messageAttributeMode === "content" ? serializeGenAiAttribute(params.messages.map(toCanonicalInputMessage)) : void 0;
@@ -490,8 +507,10 @@ function bestEffortObjectCompletionCost(modelId, usage) {
490
507
  }
491
508
  }
492
509
  async function completeObject(params) {
493
- const apiKey = getGatewayApiKey();
494
- const provider = createGatewayProvider(apiKey ? { apiKey } : {});
510
+ const credential = await resolveGatewayCredential();
511
+ const provider = createGatewayProvider(
512
+ credential ? { apiKey: credential.token } : {}
513
+ );
495
514
  let result;
496
515
  try {
497
516
  result = await withSpan(
@@ -528,6 +547,7 @@ async function completeObject(params) {
528
547
  "gen_ai.output.type": "json",
529
548
  "server.address": GEN_AI_SERVER_ADDRESS,
530
549
  "server.port": GEN_AI_SERVER_PORT,
550
+ "gen_ai.provider.auth_mode": credential?.mode ?? "api_key",
531
551
  ...params.thinkingLevel ? { "gen_ai.request.reasoning.level": params.thinkingLevel } : {},
532
552
  ...params.temperature !== void 0 ? { "gen_ai.request.temperature": params.temperature } : {},
533
553
  ...params.maxTokens !== void 0 ? { "gen_ai.request.max_tokens": params.maxTokens } : {}
@@ -551,8 +571,10 @@ async function embedTexts(params) {
551
571
  if (texts.length === 0 || texts.some((text) => text.length === 0)) {
552
572
  throw new Error("Embedding text is required.");
553
573
  }
554
- const apiKey = getGatewayApiKey();
555
- const provider = createGatewayProvider(apiKey ? { apiKey } : {});
574
+ const credential = await resolveGatewayCredential();
575
+ const provider = createGatewayProvider(
576
+ credential ? { apiKey: credential.token } : {}
577
+ );
556
578
  try {
557
579
  const result = await withSpan(
558
580
  `${GEN_AI_OPERATION_EMBEDDINGS} ${params.modelId}`,
@@ -591,7 +613,8 @@ async function embedTexts(params) {
591
613
  "gen_ai.operation.name": GEN_AI_OPERATION_EMBEDDINGS,
592
614
  "gen_ai.request.model": params.modelId,
593
615
  "server.address": GEN_AI_SERVER_ADDRESS,
594
- "server.port": GEN_AI_SERVER_PORT
616
+ "server.port": GEN_AI_SERVER_PORT,
617
+ "gen_ai.provider.auth_mode": credential?.mode ?? "api_key"
595
618
  }
596
619
  );
597
620
  return {
@@ -756,6 +779,16 @@ function parseSlashCommand(rawValue) {
756
779
  }
757
780
  return command;
758
781
  }
782
+ function parseConversationWorkEnabled(rawValue) {
783
+ const value = toOptionalTrimmed(rawValue)?.toLowerCase();
784
+ if (value === void 0 || value === "true") {
785
+ return true;
786
+ }
787
+ if (value === "false") {
788
+ return false;
789
+ }
790
+ throw new Error("JUNIOR_CONVERSATION_WORK_ENABLED must be true or false");
791
+ }
759
792
  function parseCrossActorMidRunMode(rawValue) {
760
793
  const value = toOptionalTrimmed(rawValue) ?? "follow_up";
761
794
  if (value === "follow_up" || value === "steer") {
@@ -926,6 +959,9 @@ function readChatConfig(env = process.env, functionMaxDurationSeconds = DEFAULT_
926
959
  return {
927
960
  bot: readBotConfig(env, resolvedFunctionMaxDurationSeconds),
928
961
  functionMaxDurationSeconds: resolvedFunctionMaxDurationSeconds,
962
+ conversationWorkEnabled: parseConversationWorkEnabled(
963
+ env.JUNIOR_CONVERSATION_WORK_ENABLED
964
+ ),
929
965
  conversationWorkSoftYieldAfterMs: resolveConversationWorkSoftYieldAfterMs(
930
966
  resolvedFunctionMaxDurationSeconds
931
967
  ),
@@ -1008,6 +1044,9 @@ function setSlackReactionConfig(overrides) {
1008
1044
 
1009
1045
  export {
1010
1046
  toOptionalTrimmed,
1047
+ MISSING_GATEWAY_CREDENTIALS_ERROR,
1048
+ resolveGatewayCredential,
1049
+ getGatewayApiKey,
1011
1050
  ProviderError,
1012
1051
  createProviderError,
1013
1052
  isProviderRetryError,
@@ -1025,9 +1064,6 @@ export {
1025
1064
  GEN_AI_PROVIDER_NAME,
1026
1065
  GEN_AI_SERVER_ADDRESS,
1027
1066
  GEN_AI_SERVER_PORT,
1028
- MISSING_GATEWAY_CREDENTIALS_ERROR,
1029
- getGatewayApiKey,
1030
- getPiGatewayApiKey,
1031
1067
  resolveGatewayModel,
1032
1068
  completeText,
1033
1069
  completeObject,
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@sentry/junior",
4
- version: "0.136.1",
4
+ version: "0.138.0",
5
5
  private: false,
6
6
  publishConfig: {
7
7
  access: "public"
@@ -81,6 +81,7 @@ var package_default = {
81
81
  "@sinclair/typebox": "^0.34.49",
82
82
  "@slack/web-api": "^7.16.0",
83
83
  "@vercel/functions": "^3.6.0",
84
+ "@vercel/oidc": "^3.4.1",
84
85
  "@vercel/queue": "^0.2.0",
85
86
  "@vercel/sandbox": "2.8.0",
86
87
  ai: "^6.0.190",