@sentry/junior 0.160.0 → 0.161.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-U6R3O2V4.js → agent-hooks-O75UJNC6.js} +13 -10
  2. package/dist/api/locations/detail.d.ts +17 -0
  3. package/dist/api/people/plugin-reports.d.ts +7 -0
  4. package/dist/api/schema/conversation.d.ts +77 -8
  5. package/dist/api/schema/location.d.ts +29 -0
  6. package/dist/api/schema/person.d.ts +29 -0
  7. package/dist/api/schema.js +1 -1
  8. package/dist/api.js +128 -27
  9. package/dist/app.js +73 -42
  10. package/dist/{catalog-runtime-HIDNHGOP.js → catalog-runtime-Z3FHU4ZY.js} +5 -5
  11. package/dist/chat/artifacts/store.d.ts +42 -0
  12. package/dist/chat/plugins/agent-hooks.d.ts +9 -1
  13. package/dist/chat/plugins/annotations.d.ts +3 -0
  14. package/dist/chat/plugins/conversation-sidebar.d.ts +3 -0
  15. package/dist/chat/plugins/viewer.d.ts +4 -0
  16. package/dist/chat/slack/mrkdwn.d.ts +3 -4
  17. package/dist/chat/tools/publish-image.d.ts +44 -0
  18. package/dist/chat/tools/unpublish-image.d.ts +35 -0
  19. package/dist/{chunk-MBDWMEO6.js → chunk-4WAZ6DGX.js} +10 -10
  20. package/dist/{chunk-FJR66CQT.js → chunk-6ILVZOF6.js} +4 -4
  21. package/dist/{chunk-42E7432W.js → chunk-6WTDZKFR.js} +1 -1
  22. package/dist/{chunk-2SFMRMDV.js → chunk-CGAIDDLD.js} +1 -1
  23. package/dist/{chunk-XPX3DYG7.js → chunk-DGKLYDX7.js} +2 -2
  24. package/dist/{chunk-ZNBGWMVQ.js → chunk-DNSIU27S.js} +1 -1
  25. package/dist/{chunk-TBRJGMTO.js → chunk-EAIQBR66.js} +1 -1
  26. package/dist/{chunk-4UO3UAW7.js → chunk-FLMD25Y5.js} +239 -199
  27. package/dist/{chunk-FKMWPA4A.js → chunk-G35DUPNB.js} +4 -4
  28. package/dist/{chunk-472VVYYV.js → chunk-HSFYTIS2.js} +1 -1
  29. package/dist/{chunk-LNUZXEEI.js → chunk-IRHX2S46.js} +1 -1
  30. package/dist/{chunk-TPFOVXRB.js → chunk-IW7C5C7E.js} +19 -21
  31. package/dist/{chunk-UNDTW2PY.js → chunk-IYFKONIL.js} +1 -1
  32. package/dist/{chunk-U26KRMYX.js → chunk-MNY5M7RB.js} +537 -27
  33. package/dist/{chunk-PZUJPPON.js → chunk-MVG5UPLM.js} +1 -1
  34. package/dist/{chunk-WACYTIIK.js → chunk-O7JTSJPU.js} +6 -6
  35. package/dist/{chunk-URPLKXLG.js → chunk-OPIJ6HY3.js} +9 -9
  36. package/dist/{chunk-756F567I.js → chunk-OY2DBUV4.js} +5 -5
  37. package/dist/{chunk-M5HCOMDR.js → chunk-OYQEO72I.js} +410 -108
  38. package/dist/{chunk-2MK6S2UA.js → chunk-QHXT7LLF.js} +1 -1
  39. package/dist/{chunk-3AHIB66R.js → chunk-QQ7SY5IZ.js} +5 -5
  40. package/dist/{chunk-BGVQGEKB.js → chunk-RULQD7OX.js} +4 -4
  41. package/dist/{chunk-J77DLAPE.js → chunk-RVENVPNO.js} +2 -2
  42. package/dist/{chunk-UYUS4L6F.js → chunk-SA6BEEAB.js} +16 -9
  43. package/dist/{chunk-RLOXMHLA.js → chunk-STZVUVMS.js} +4 -4
  44. package/dist/{chunk-JQZIUESN.js → chunk-U2XOBFDK.js} +3 -3
  45. package/dist/{chunk-PVIM2RWO.js → chunk-V67ORYKQ.js} +8 -10
  46. package/dist/{chunk-P7W3ZL5J.js → chunk-VXFDVY4C.js} +8 -36
  47. package/dist/{chunk-YPMDNE7R.js → chunk-WKN4ZQTZ.js} +1 -1
  48. package/dist/{chunk-HDPH4CHJ.js → chunk-WVSQ2SCS.js} +1 -1
  49. package/dist/{chunk-56TFPTZU.js → chunk-YSWHAOPQ.js} +1 -1
  50. package/dist/{chunk-RJGRXDA7.js → chunk-ZBCLWBMV.js} +5 -5
  51. package/dist/cli/chat.js +29 -30
  52. package/dist/cli/check.js +6 -6
  53. package/dist/cli/plugins.js +12 -13
  54. package/dist/cli/snapshot-create.js +9 -9
  55. package/dist/cli/upgrade.js +7 -7
  56. package/dist/db/schema/artifacts.d.ts +178 -0
  57. package/dist/db/schema.d.ts +179 -1
  58. package/dist/{db-2JKT3BB5.js → db-KKOZRE62.js} +7 -7
  59. package/dist/handlers/artifacts.d.ts +8 -0
  60. package/dist/instrumentation.js +4 -4
  61. package/dist/nitro.js +2 -2
  62. package/dist/{oauth-callback-server-7MC2UMQC.js → oauth-callback-server-5AUZDWXA.js} +22 -23
  63. package/dist/{runner-GUU4G7XO.js → runner-K5H5NDEC.js} +12 -13
  64. package/dist/{skills-7NW5N3VM.js → skills-OZGPB6G4.js} +6 -6
  65. package/dist/spawn-RCQSC2L5.js +37 -0
  66. package/dist/{validation-AQLI6N2C.js → validation-TVHCNCYL.js} +6 -6
  67. package/dist/version.js +1 -1
  68. package/dist/{work-FLFK5XNU.js → work-DXCQMJ5U.js} +17 -17
  69. package/dist/worker-24HZ5HRI.js +24 -0
  70. package/migrations/0028_artifacts.sql +16 -0
  71. package/migrations/meta/0028_snapshot.json +2685 -0
  72. package/migrations/meta/_journal.json +8 -1
  73. package/package.json +4 -4
  74. package/dist/chunk-OUAZDZTZ.js +0 -441
  75. package/dist/spawn-WGK4W3XF.js +0 -37
  76. package/dist/worker-KSJIRBQJ.js +0 -24
@@ -7,7 +7,7 @@ import {
7
7
  PluginCredentialFailureError,
8
8
  agentNameSchema,
9
9
  createPluginAuthOrchestration
10
- } from "./chunk-756F567I.js";
10
+ } from "./chunk-OY2DBUV4.js";
11
11
  import {
12
12
  authorizationId
13
13
  } from "./chunk-DIB4GX3G.js";
@@ -32,7 +32,7 @@ import {
32
32
  searchSlackUsers,
33
33
  selectPluginGrant,
34
34
  toMcpProviderError
35
- } from "./chunk-PVIM2RWO.js";
35
+ } from "./chunk-V67ORYKQ.js";
36
36
  import {
37
37
  RetryableDeliveryError,
38
38
  actorFromRun,
@@ -48,7 +48,7 @@ import {
48
48
  getSlackMessagePermalink,
49
49
  resolveBaseUrl,
50
50
  uploadFilesToConversation
51
- } from "./chunk-P7W3ZL5J.js";
51
+ } from "./chunk-VXFDVY4C.js";
52
52
  import {
53
53
  parseSandboxEgressAuthRequiredSignal,
54
54
  parseSandboxEgressPermissionDeniedSignal,
@@ -74,7 +74,7 @@ import {
74
74
  runNonInteractiveCommand,
75
75
  throwSandboxOperationError,
76
76
  wrapSandboxSetupError
77
- } from "./chunk-BGVQGEKB.js";
77
+ } from "./chunk-RULQD7OX.js";
78
78
  import {
79
79
  SCHEDULED_TASK_SYSTEM_ACTOR,
80
80
  compactEventTask,
@@ -107,10 +107,10 @@ import {
107
107
  scheduledTaskAttributes,
108
108
  storeAttachments,
109
109
  writableEventTask
110
- } from "./chunk-RJGRXDA7.js";
110
+ } from "./chunk-ZBCLWBMV.js";
111
111
  import {
112
112
  parseSlackThreadId
113
- } from "./chunk-56TFPTZU.js";
113
+ } from "./chunk-YSWHAOPQ.js";
114
114
  import {
115
115
  AGENTS_REMOVAL_NOTICE,
116
116
  AGENTS_REPLACEMENT_NOTICE,
@@ -181,7 +181,7 @@ import {
181
181
  stripRuntimeTurnContext,
182
182
  trimTrailingAssistantMessages,
183
183
  truncateText
184
- } from "./chunk-RLOXMHLA.js";
184
+ } from "./chunk-STZVUVMS.js";
185
185
  import {
186
186
  JUNIOR_THREAD_STATE_TTL_MS
187
187
  } from "./chunk-3Y47VMHV.js";
@@ -189,24 +189,22 @@ import {
189
189
  privateTraceResultAttributes
190
190
  } from "./chunk-UIE3R5XU.js";
191
191
  import {
192
+ SlackActionError,
192
193
  createPluginHookRunner,
194
+ downloadPrivateSlackFile,
193
195
  getDashboardTaskLink,
196
+ getFilePermalink,
194
197
  getPluginSystemPromptContributions,
195
198
  getPluginTools,
196
199
  getPluginUserPromptContributions,
197
- getSlackToolContext,
198
- readActorIdentity,
199
- resolveChannelCapabilities
200
- } from "./chunk-U26KRMYX.js";
201
- import {
202
- SlackActionError,
203
- downloadPrivateSlackFile,
204
- getFilePermalink,
205
200
  getSlackClient,
201
+ getSlackToolContext,
206
202
  isConversationScopedChannel,
207
203
  normalizeSlackConversationId,
204
+ readActorIdentity,
205
+ resolveChannelCapabilities,
208
206
  withSlackRetries
209
- } from "./chunk-OUAZDZTZ.js";
207
+ } from "./chunk-MNY5M7RB.js";
210
208
  import {
211
209
  KNOWN_CONVERSATION_EVENT_TYPES,
212
210
  contextProvenance,
@@ -218,10 +216,11 @@ import {
218
216
  instructionActors,
219
217
  instructionProvenanceFor,
220
218
  sameActorIdentity
221
- } from "./chunk-JQZIUESN.js";
219
+ } from "./chunk-U2XOBFDK.js";
222
220
  import {
221
+ juniorArtifacts,
223
222
  juniorIdentities
224
- } from "./chunk-4UO3UAW7.js";
223
+ } from "./chunk-FLMD25Y5.js";
225
224
  import {
226
225
  SANDBOX_DATA_ROOT,
227
226
  SANDBOX_SKILLS_ROOT,
@@ -233,7 +232,7 @@ import {
233
232
  } from "./chunk-EM225ITJ.js";
234
233
  import {
235
234
  getStateAdapter
236
- } from "./chunk-UNDTW2PY.js";
235
+ } from "./chunk-IYFKONIL.js";
237
236
  import {
238
237
  ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
239
238
  COMPACTION_SUMMARY_PREFIX,
@@ -266,7 +265,7 @@ import {
266
265
  resolveGatewayCredential,
267
266
  resolveGatewayModel,
268
267
  unwrapCurrentInstruction
269
- } from "./chunk-J77DLAPE.js";
268
+ } from "./chunk-RVENVPNO.js";
270
269
  import {
271
270
  canExposeConversationPayload,
272
271
  resolveConversationPrivacy,
@@ -276,16 +275,16 @@ import {
276
275
  toGenAiMessagesTraceAttributes,
277
276
  toGenAiPayloadMetadata,
278
277
  toGenAiPayloadTraceAttributes
279
- } from "./chunk-TBRJGMTO.js";
278
+ } from "./chunk-EAIQBR66.js";
280
279
  import {
281
280
  discoverSkills,
282
281
  findSkillByName,
283
282
  loadSkillsByName,
284
283
  parseSkillInvocation
285
- } from "./chunk-XPX3DYG7.js";
284
+ } from "./chunk-DGKLYDX7.js";
286
285
  import {
287
286
  pluginCatalogRuntime
288
- } from "./chunk-2SFMRMDV.js";
287
+ } from "./chunk-CGAIDDLD.js";
289
288
  import {
290
289
  CredentialUnavailableError,
291
290
  OAuthProviderError,
@@ -293,7 +292,7 @@ import {
293
292
  getOAuthProviderErrorAttributes,
294
293
  resolveAuthTokenPlaceholder,
295
294
  resolvePluginCommandEnv
296
- } from "./chunk-42E7432W.js";
295
+ } from "./chunk-6WTDZKFR.js";
297
296
  import {
298
297
  credentialUserSubjectId
299
298
  } from "./chunk-BDUENQD3.js";
@@ -321,7 +320,7 @@ import {
321
320
  summarizeMessageText,
322
321
  withLogContext,
323
322
  withSpan
324
- } from "./chunk-ZNBGWMVQ.js";
323
+ } from "./chunk-DNSIU27S.js";
325
324
  import {
326
325
  startInactiveSpan,
327
326
  withActiveSpan
@@ -1732,7 +1731,6 @@ function buildOutputSection(platform) {
1732
1731
  `<output format="markdown">`,
1733
1732
  "- Start with the answer or result, not internal process narration.",
1734
1733
  "- Use concise Markdown suitable for terminal output: short paragraphs, bullets, links, and fenced code blocks when helpful.",
1735
- "- When you mention a pull request, include a direct link. Prefer the full PR URL or a Markdown link; do not leave bare `PR #123` text without a URL or repo.",
1736
1734
  "- End every turn with a final user-facing response.",
1737
1735
  "</output>"
1738
1736
  ].join("\n");
@@ -1742,7 +1740,6 @@ function buildOutputSection(platform) {
1742
1740
  "- Default to the shortest complete reply\u2014usually 1\u20135 sentences and under 800 characters. Include only the outcome, decisive evidence, and any blocker or required next action. If useful detail would exceed that, put it in a Slack canvas and reply with the link. An explicit user request for detail overrides this target.",
1743
1741
  "- Start with the answer or result, not internal process narration.",
1744
1742
  "- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No hash-prefixed headings and no tables. When the answer primarily lists several URLs, show each URL bare instead of as a labeled link.",
1745
- "- When you mention a pull request, include a direct link. Prefer the full PR URL or a Markdown link; `owner/repo#number` is also accepted and is linkified on delivery. Do not leave bare `PR #123` text without a URL or repo.",
1746
1743
  "- End every turn with a final user-facing markdown response unless the Slack action rules allow a no-reply completion.",
1747
1744
  "</output>"
1748
1745
  ].join("\n");
@@ -3982,7 +3979,7 @@ function parseToolInput(schema, args) {
3982
3979
  return result.data;
3983
3980
  }
3984
3981
  function zodTool(definition) {
3985
- const { inputSchema: inputSchema2, outputSchema: outputSchema5, prepareArguments, execute, ...toolDef } = definition;
3982
+ const { inputSchema: inputSchema2, outputSchema: outputSchema7, prepareArguments, execute, ...toolDef } = definition;
3986
3983
  let modelInputSchema;
3987
3984
  try {
3988
3985
  modelInputSchema = z3.toJSONSchema(inputSchema2);
@@ -3993,9 +3990,9 @@ function zodTool(definition) {
3993
3990
  );
3994
3991
  }
3995
3992
  let modelOutputSchema;
3996
- if (outputSchema5) {
3993
+ if (outputSchema7) {
3997
3994
  try {
3998
- modelOutputSchema = z3.toJSONSchema(outputSchema5);
3995
+ modelOutputSchema = z3.toJSONSchema(outputSchema7);
3999
3996
  } catch (error) {
4000
3997
  throw new TypeError(
4001
3998
  "zodTool() outputSchema must be representable as JSON Schema.",
@@ -4019,7 +4016,7 @@ function zodTool(definition) {
4019
4016
  input,
4020
4017
  options
4021
4018
  );
4022
- if (!outputSchema5) {
4019
+ if (!outputSchema7) {
4023
4020
  if (isContentOnlyToolResult(result)) {
4024
4021
  return result;
4025
4022
  }
@@ -4030,10 +4027,10 @@ function zodTool(definition) {
4030
4027
  if (isStructuredToolResultEnvelope(result)) {
4031
4028
  return {
4032
4029
  content: parseToolContent(result.content),
4033
- details: outputSchema5.parse(result.details)
4030
+ details: outputSchema7.parse(result.details)
4034
4031
  };
4035
4032
  }
4036
- return outputSchema5.parse(result);
4033
+ return outputSchema7.parse(result);
4037
4034
  }
4038
4035
  } : {}
4039
4036
  };
@@ -6494,7 +6491,7 @@ var McpToolManager = class {
6494
6491
  return client;
6495
6492
  }
6496
6493
  toManagedTool(plugin, client, tool) {
6497
- const outputSchema5 = toOptionalRecord(tool.outputSchema);
6494
+ const outputSchema7 = toOptionalRecord(tool.outputSchema);
6498
6495
  const annotations = tool.annotations;
6499
6496
  const missingAnnotationKeys = missingToolAnnotationKeys(annotations);
6500
6497
  if (missingAnnotationKeys.length > 0) {
@@ -6511,7 +6508,7 @@ var McpToolManager = class {
6511
6508
  provider: plugin.manifest.name,
6512
6509
  rawName: tool.name,
6513
6510
  ...tool.title?.trim() ? { title: tool.title.trim() } : {},
6514
- ...outputSchema5 ? { outputSchema: outputSchema5 } : {},
6511
+ ...outputSchema7 ? { outputSchema: outputSchema7 } : {},
6515
6512
  ...annotations ? { annotations } : {},
6516
6513
  execute: async (args, options) => {
6517
6514
  const resolvedArgs = typeof args === "object" && args !== null ? args : {};
@@ -12307,28 +12304,318 @@ function getTimeZoneOffsetMinutes(timestampMs, timezone) {
12307
12304
  return Math.round((timestampMs - asUtcMs) / 6e4);
12308
12305
  }
12309
12306
 
12310
- // src/chat/tools/search-conversation-events.ts
12307
+ // src/chat/tools/publish-image.ts
12311
12308
  import { z as z56 } from "zod";
12309
+
12310
+ // src/chat/artifacts/store.ts
12311
+ import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
12312
+ import { and as and2, eq as eq2, isNull } from "drizzle-orm";
12313
+ var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
12314
+ var IMAGE_TYPES = {
12315
+ gif: "image/gif",
12316
+ jpg: "image/jpeg",
12317
+ png: "image/png",
12318
+ webp: "image/webp"
12319
+ };
12320
+ var FILENAME_RE = /^([0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\.(gif|jpg|png|webp)$/i;
12321
+ function detectImageType(data) {
12322
+ if (data.length >= 8 && data.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
12323
+ return { contentType: IMAGE_TYPES.png, extension: "png" };
12324
+ }
12325
+ if (data.length >= 3 && data[0] === 255 && data[1] === 216 && data[2] === 255) {
12326
+ return { contentType: IMAGE_TYPES.jpg, extension: "jpg" };
12327
+ }
12328
+ if (data.length >= 6 && (data.subarray(0, 6).toString("ascii") === "GIF87a" || data.subarray(0, 6).toString("ascii") === "GIF89a")) {
12329
+ return { contentType: IMAGE_TYPES.gif, extension: "gif" };
12330
+ }
12331
+ if (data.length >= 12 && data.subarray(0, 4).toString("ascii") === "RIFF" && data.subarray(8, 12).toString("ascii") === "WEBP") {
12332
+ return { contentType: IMAGE_TYPES.webp, extension: "webp" };
12333
+ }
12334
+ return null;
12335
+ }
12336
+ function artifactKey(filename) {
12337
+ return `artifacts/${filename}`;
12338
+ }
12339
+ function parseArtifactFilename(filename) {
12340
+ const match = filename.match(FILENAME_RE);
12341
+ if (!match) return null;
12342
+ return {
12343
+ id: match[1].toLowerCase(),
12344
+ ext: match[2].toLowerCase()
12345
+ };
12346
+ }
12347
+ function artifactFilenameFromRef(ref) {
12348
+ const trimmed = ref.trim();
12349
+ if (FILENAME_RE.test(trimmed)) {
12350
+ const parsed = parseArtifactFilename(trimmed);
12351
+ return parsed ? `${parsed.id}.${parsed.ext}` : null;
12352
+ }
12353
+ try {
12354
+ const url = new URL(trimmed);
12355
+ const marker = "/public/artifacts/";
12356
+ const index = url.pathname.lastIndexOf(marker);
12357
+ if (index === -1) return null;
12358
+ const filename = url.pathname.slice(index + marker.length);
12359
+ const parsed = parseArtifactFilename(filename);
12360
+ return parsed ? `${parsed.id}.${parsed.ext}` : null;
12361
+ } catch {
12362
+ return null;
12363
+ }
12364
+ }
12365
+ function resolvePublicBaseUrl(publicBaseUrl) {
12366
+ const baseUrl = publicBaseUrl.trim().replace(/\/+$/, "");
12367
+ let parsedBaseUrl;
12368
+ try {
12369
+ parsedBaseUrl = new URL(baseUrl);
12370
+ } catch {
12371
+ throw new Error("public base URL must be an absolute HTTP(S) URL");
12372
+ }
12373
+ if (parsedBaseUrl.protocol !== "http:" && parsedBaseUrl.protocol !== "https:") {
12374
+ throw new Error("public base URL must use HTTP(S)");
12375
+ }
12376
+ return baseUrl;
12377
+ }
12378
+ async function publishImage(args) {
12379
+ if (args.body.byteLength === 0) {
12380
+ throw new ToolInputError("image is empty");
12381
+ }
12382
+ if (args.body.byteLength > MAX_IMAGE_BYTES) {
12383
+ throw new ToolInputError(
12384
+ `image exceeds ${MAX_IMAGE_BYTES} bytes (${args.body.byteLength} bytes)`
12385
+ );
12386
+ }
12387
+ const imageType = detectImageType(args.body);
12388
+ if (!imageType) {
12389
+ throw new ToolInputError(
12390
+ "unsupported image format; use PNG, JPEG, GIF, or WebP"
12391
+ );
12392
+ }
12393
+ const baseUrl = resolvePublicBaseUrl(args.publicBaseUrl);
12394
+ const sha256 = createHash5("sha256").update(args.body).digest("hex");
12395
+ const now = args.now ?? /* @__PURE__ */ new Date();
12396
+ const [existing] = await args.db.db().select({
12397
+ id: juniorArtifacts.id
12398
+ }).from(juniorArtifacts).where(
12399
+ and2(
12400
+ eq2(juniorArtifacts.conversationId, args.conversationId),
12401
+ eq2(juniorArtifacts.sha256, sha256)
12402
+ )
12403
+ );
12404
+ const id = existing?.id ?? randomUUID3();
12405
+ const filename = `${id}.${imageType.extension}`;
12406
+ const storageKey = artifactKey(filename);
12407
+ await args.storage.put({
12408
+ body: args.body,
12409
+ contentType: imageType.contentType,
12410
+ key: storageKey
12411
+ });
12412
+ const [row] = await args.db.db().insert(juniorArtifacts).values({
12413
+ bytes: args.body.byteLength,
12414
+ contentType: imageType.contentType,
12415
+ conversationId: args.conversationId,
12416
+ createdAt: now,
12417
+ deleteRequestedAt: null,
12418
+ ext: imageType.extension,
12419
+ id,
12420
+ public: true,
12421
+ sha256,
12422
+ storageKey
12423
+ }).onConflictDoUpdate({
12424
+ target: [juniorArtifacts.conversationId, juniorArtifacts.sha256],
12425
+ set: {
12426
+ bytes: args.body.byteLength,
12427
+ contentType: imageType.contentType,
12428
+ deleteRequestedAt: null,
12429
+ ext: imageType.extension,
12430
+ public: true
12431
+ // Keep the winning row's id/storage key. A raced put may leave an
12432
+ // unused object; that is fine for mvp.
12433
+ }
12434
+ }).returning({
12435
+ ext: juniorArtifacts.ext,
12436
+ id: juniorArtifacts.id
12437
+ });
12438
+ if (!row) {
12439
+ throw new Error("failed to publish artifact row");
12440
+ }
12441
+ return {
12442
+ bytes: args.body.byteLength,
12443
+ contentType: imageType.contentType,
12444
+ url: `${baseUrl}/public/artifacts/${row.id}.${row.ext}`
12445
+ };
12446
+ }
12447
+ async function unpublishArtifact(args) {
12448
+ const filename = artifactFilenameFromRef(args.ref);
12449
+ if (!filename) {
12450
+ throw new ToolInputError(
12451
+ "artifact ref must be a public artifact URL or <id>.<ext> filename"
12452
+ );
12453
+ }
12454
+ const parsed = parseArtifactFilename(filename);
12455
+ if (!parsed) {
12456
+ throw new ToolInputError(
12457
+ "artifact ref must be a public artifact URL or <id>.<ext> filename"
12458
+ );
12459
+ }
12460
+ const now = args.now ?? /* @__PURE__ */ new Date();
12461
+ const updated = await args.db.db().update(juniorArtifacts).set({ deleteRequestedAt: now }).where(
12462
+ and2(
12463
+ eq2(juniorArtifacts.id, parsed.id),
12464
+ eq2(juniorArtifacts.conversationId, args.conversationId)
12465
+ )
12466
+ ).returning({ id: juniorArtifacts.id });
12467
+ if (updated.length === 0) {
12468
+ throw new ToolInputError(
12469
+ `artifact not found for this conversation: ${filename}`
12470
+ );
12471
+ }
12472
+ return { filename };
12473
+ }
12474
+ async function readPublicArtifact(args) {
12475
+ const parsed = parseArtifactFilename(args.filename);
12476
+ if (!parsed) return null;
12477
+ const [row] = await args.db.db().select({
12478
+ contentType: juniorArtifacts.contentType,
12479
+ storageKey: juniorArtifacts.storageKey
12480
+ }).from(juniorArtifacts).where(
12481
+ and2(
12482
+ eq2(juniorArtifacts.id, parsed.id),
12483
+ eq2(juniorArtifacts.public, true),
12484
+ isNull(juniorArtifacts.deleteRequestedAt)
12485
+ )
12486
+ );
12487
+ if (!row) return null;
12488
+ const body = await args.storage.get(row.storageKey);
12489
+ if (!body) return null;
12490
+ return { body, contentType: row.contentType };
12491
+ }
12492
+ function publicArtifactHeaders(contentType) {
12493
+ return new Headers({
12494
+ // Keep TTL short so unpublish can take effect. Do not mark immutable.
12495
+ "cache-control": "public, max-age=300, must-revalidate",
12496
+ "content-type": contentType,
12497
+ "x-content-type-options": "nosniff"
12498
+ });
12499
+ }
12500
+ function unpublishedArtifactHeaders() {
12501
+ return new Headers({
12502
+ "cache-control": "private, no-store",
12503
+ "x-content-type-options": "nosniff"
12504
+ });
12505
+ }
12506
+
12507
+ // src/chat/tools/publish-image.ts
12508
+ var outputSchema5 = juniorToolOutputSchema.extend({
12509
+ bytes: z56.number().int().positive(),
12510
+ content_type: z56.string().min(1),
12511
+ public: z56.literal(true),
12512
+ url: z56.string().url()
12513
+ });
12514
+ function createPublishImageTool(args) {
12515
+ return zodTool({
12516
+ annotations: {
12517
+ destructiveHint: false,
12518
+ idempotentHint: true,
12519
+ openWorldHint: true,
12520
+ readOnlyHint: false
12521
+ },
12522
+ approvalMode: "review",
12523
+ description: "Publish one sandbox image to a durable public HTTPS URL. Anyone on the internet with the URL can view the image. Use only when an external destination needs a public image URL. Do not use for private file sharing or private conversation storage. Supports PNG, JPEG, GIF, and WebP up to 10 MB.",
12524
+ describeProposal: ({ path: path8 }) => `Publish sandbox image ${path8} to a public internet URL.`,
12525
+ executionMode: "sequential",
12526
+ inputSchema: z56.object({
12527
+ path: z56.string().min(1).describe("Exact sandbox path of an existing image file.")
12528
+ }).strict(),
12529
+ outputSchema: outputSchema5,
12530
+ async execute({ path: path8 }) {
12531
+ const publicBaseUrl = (args.publicBaseUrl ?? resolveBaseUrl)()?.trim();
12532
+ if (!publicBaseUrl) {
12533
+ throw new Error(
12534
+ "publishImage requires JUNIOR_BASE_URL or a Vercel deployment URL."
12535
+ );
12536
+ }
12537
+ const targetPath = normalizeSandboxPath(path8);
12538
+ const body = await args.workspace.readFileToBuffer({ path: targetPath });
12539
+ if (!body) {
12540
+ throw new SandboxFileNotFoundError(targetPath);
12541
+ }
12542
+ const image = await publishImage({
12543
+ body,
12544
+ conversationId: args.conversationId,
12545
+ db: args.db,
12546
+ publicBaseUrl,
12547
+ storage: args.storage
12548
+ });
12549
+ return {
12550
+ bytes: image.bytes,
12551
+ content_type: image.contentType,
12552
+ public: true,
12553
+ url: image.url
12554
+ };
12555
+ }
12556
+ });
12557
+ }
12558
+
12559
+ // src/chat/tools/unpublish-image.ts
12560
+ import { z as z57 } from "zod";
12561
+ var outputSchema6 = juniorToolOutputSchema.extend({
12562
+ filename: z57.string().min(1),
12563
+ unpublished: z57.literal(true)
12564
+ });
12565
+ function createUnpublishImageTool(args) {
12566
+ return zodTool({
12567
+ annotations: {
12568
+ destructiveHint: true,
12569
+ idempotentHint: true,
12570
+ openWorldHint: false,
12571
+ readOnlyHint: false
12572
+ },
12573
+ approvalMode: "review",
12574
+ description: "Unpublish one public image previously published in this conversation so its public URL stops serving. Pass the public artifact URL or `<id>.<ext>` filename. Only images owned by this conversation can be unpublished. Republishing the same image bytes later in this conversation restores a live URL for this conversation. Does not remove copies already fetched by browsers or GitHub.",
12575
+ describeProposal: ({ ref }) => `Unpublish public image ${ref}.`,
12576
+ executionMode: "sequential",
12577
+ inputSchema: z57.object({
12578
+ ref: z57.string().min(1).describe(
12579
+ "Public artifact URL or artifact filename (`<id>.<ext>`)."
12580
+ )
12581
+ }).strict(),
12582
+ outputSchema: outputSchema6,
12583
+ async execute({ ref }) {
12584
+ const result = await unpublishArtifact({
12585
+ conversationId: args.conversationId,
12586
+ db: args.db,
12587
+ ref
12588
+ });
12589
+ return {
12590
+ filename: result.filename,
12591
+ unpublished: true
12592
+ };
12593
+ }
12594
+ });
12595
+ }
12596
+
12597
+ // src/chat/tools/search-conversation-events.ts
12598
+ import { z as z58 } from "zod";
12312
12599
  var DEFAULT_LIMIT3 = 25;
12313
12600
  var MAX_LIMIT = 100;
12314
12601
  var MAX_EVENT_DATA_BYTES = 4e3;
12315
12602
  var MAX_EVENTS_JSON_BYTES = 2e4;
12316
12603
  var MAX_IDENTITY_CHARS = 256;
12317
12604
  var textEncoder = new TextEncoder();
12318
- var knownEventTypeSchema = z56.enum(KNOWN_CONVERSATION_EVENT_TYPES);
12319
- var projectedEventSchema = z56.object({
12320
- seq: z56.number().int().nonnegative().describe("Stable event position for pagination."),
12321
- history_version: z56.number().int().nonnegative().describe("Agent history generation after replacement."),
12322
- created_at: z56.iso.datetime().describe("When the event was recorded."),
12323
- idempotency_key: z56.string().min(1).optional().describe("Retry-stable event identity, when assigned."),
12324
- data: z56.record(z56.string(), z56.unknown()).describe("Bounded event data.")
12605
+ var knownEventTypeSchema = z58.enum(KNOWN_CONVERSATION_EVENT_TYPES);
12606
+ var projectedEventSchema = z58.object({
12607
+ seq: z58.number().int().nonnegative().describe("Stable event position for pagination."),
12608
+ history_version: z58.number().int().nonnegative().describe("Agent history generation after replacement."),
12609
+ created_at: z58.iso.datetime().describe("When the event was recorded."),
12610
+ idempotency_key: z58.string().min(1).optional().describe("Retry-stable event identity, when assigned."),
12611
+ data: z58.record(z58.string(), z58.unknown()).describe("Bounded event data.")
12325
12612
  }).strict();
12326
12613
  var searchConversationEventsOutputSchema = juniorToolOutputSchema.extend({
12327
- conversation_id: z56.string().min(1),
12328
- events: z56.array(projectedEventSchema),
12329
- has_older: z56.boolean().describe("Whether matching older events exist."),
12330
- has_newer: z56.boolean().describe("Whether matching newer events exist."),
12331
- omitted_event_count: z56.number().int().nonnegative().optional().describe("Events omitted by the response byte limit.")
12614
+ conversation_id: z58.string().min(1),
12615
+ events: z58.array(projectedEventSchema),
12616
+ has_older: z58.boolean().describe("Whether matching older events exist."),
12617
+ has_newer: z58.boolean().describe("Whether matching newer events exist."),
12618
+ omitted_event_count: z58.number().int().nonnegative().optional().describe("Events omitted by the response byte limit.")
12332
12619
  });
12333
12620
  function createSearchConversationEventsTool(context) {
12334
12621
  return zodTool({
@@ -12341,16 +12628,16 @@ function createSearchConversationEventsTool(context) {
12341
12628
  openWorldHint: false,
12342
12629
  readOnlyHint: true
12343
12630
  },
12344
- inputSchema: z56.object({
12345
- conversation_id: z56.string().trim().min(1).nullable().describe(
12631
+ inputSchema: z58.object({
12632
+ conversation_id: z58.string().trim().min(1).nullable().describe(
12346
12633
  "Conversation ID to search. Omit or null for the current conversation."
12347
12634
  ).optional(),
12348
- after_seq: z56.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
12349
- before_seq: z56.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
12350
- limit: z56.number().int().min(1).max(MAX_LIMIT).nullable().describe(
12635
+ after_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence lower bound; returns ascending.").optional(),
12636
+ before_seq: z58.number().int().nonnegative().nullable().describe("Exclusive event sequence upper bound.").optional(),
12637
+ limit: z58.number().int().min(1).max(MAX_LIMIT).nullable().describe(
12351
12638
  `Maximum events. Default ${DEFAULT_LIMIT3}; max ${MAX_LIMIT}.`
12352
12639
  ).optional(),
12353
- types: z56.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
12640
+ types: z58.array(knownEventTypeSchema).min(1).nullable().describe("Event types to include; omit for all types.").optional()
12354
12641
  }).strict(),
12355
12642
  outputSchema: searchConversationEventsOutputSchema,
12356
12643
  execute: async (input) => {
@@ -12596,10 +12883,10 @@ function stripReplacementHistoryField(value) {
12596
12883
  }
12597
12884
 
12598
12885
  // src/chat/tools/handoff/tool.ts
12599
- import { z as z57 } from "zod";
12886
+ import { z as z59 } from "zod";
12600
12887
  var HANDOFF_TOOL_NAME = "handoff";
12601
12888
  function createHandoffTool(handoff) {
12602
- const profileSchema = z57.enum(handoff.profiles);
12889
+ const profileSchema = z59.enum(handoff.profiles);
12603
12890
  const handoffResultSchema = juniorToolOutputSchema.extend({
12604
12891
  model_profile: modelProfileSchema
12605
12892
  });
@@ -12613,7 +12900,7 @@ function createHandoffTool(handoff) {
12613
12900
  },
12614
12901
  description: `Switch to another execution profile and continue the same task. Profiles: ${profileNames}. Call this as the only tool.`,
12615
12902
  executionMode: "sequential",
12616
- inputSchema: z57.object({
12903
+ inputSchema: z59.object({
12617
12904
  profile: profileSchema.describe("Target execution profile")
12618
12905
  }).strict(),
12619
12906
  outputSchema: handoffResultSchema,
@@ -12634,7 +12921,7 @@ function createHandoffTool(handoff) {
12634
12921
  }
12635
12922
 
12636
12923
  // src/chat/tools/web/fetch-tool.ts
12637
- import { z as z58 } from "zod";
12924
+ import { z as z60 } from "zod";
12638
12925
 
12639
12926
  // src/chat/tools/web/constants.ts
12640
12927
  var USER_AGENT = "junior-bot/0.1";
@@ -13077,9 +13364,9 @@ function createWebFetchTool(hooks, options = {}) {
13077
13364
  openWorldHint: true,
13078
13365
  readOnlyHint: true
13079
13366
  },
13080
- inputSchema: z58.object({
13081
- url: z58.string().min(1).describe("HTTP(S) URL to fetch."),
13082
- max_chars: z58.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
13367
+ inputSchema: z60.object({
13368
+ url: z60.string().min(1).describe("HTTP(S) URL to fetch."),
13369
+ max_chars: z60.coerce.number().int().min(500).max(MAX_FETCH_CHARS).describe("Optional maximum number of extracted characters to return.").optional()
13083
13370
  }),
13084
13371
  outputSchema: juniorToolOutputSchema,
13085
13372
  execute: async ({ url, max_chars }) => {
@@ -13124,7 +13411,7 @@ function createWebFetchTool(hooks, options = {}) {
13124
13411
  }
13125
13412
 
13126
13413
  // src/chat/tools/web/search.ts
13127
- import { z as z59 } from "zod";
13414
+ import { z as z61 } from "zod";
13128
13415
  import { generateText } from "ai";
13129
13416
  import { createGatewayProvider } from "@ai-sdk/gateway";
13130
13417
  var SEARCH_TIMEOUT_MS = 6e4;
@@ -13166,9 +13453,9 @@ function createWebSearchTool(modelId, override) {
13166
13453
  openWorldHint: true,
13167
13454
  readOnlyHint: true
13168
13455
  },
13169
- inputSchema: z59.object({
13170
- query: z59.string().min(1).max(500).describe("Search query."),
13171
- max_results: z59.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
13456
+ inputSchema: z61.object({
13457
+ query: z61.string().min(1).max(500).describe("Search query."),
13458
+ max_results: z61.coerce.number().int().min(1).max(MAX_RESULTS2).describe("Max results to return.").optional()
13172
13459
  }),
13173
13460
  outputSchema: juniorToolOutputSchema,
13174
13461
  execute: async ({ query, max_results }) => {
@@ -13210,7 +13497,7 @@ function createWebSearchTool(modelId, override) {
13210
13497
  }
13211
13498
 
13212
13499
  // src/chat/tools/sandbox/write-file.ts
13213
- import { z as z60 } from "zod";
13500
+ import { z as z62 } from "zod";
13214
13501
  function createWriteFileTool() {
13215
13502
  return zodTool({
13216
13503
  annotations: {
@@ -13221,9 +13508,9 @@ function createWriteFileTool() {
13221
13508
  },
13222
13509
  description: "Write UTF-8 content to a file in the sandbox workspace. Use for intentional file creation or deliberate full-file replacement after validation; use editFile instead for targeted changes to existing files. Do not use for exploratory analysis-only turns.",
13223
13510
  executionMode: "sequential",
13224
- inputSchema: z60.object({
13225
- path: z60.string().min(1).describe("Path to write in the sandbox workspace."),
13226
- content: z60.string().describe("UTF-8 file content to write.")
13511
+ inputSchema: z62.object({
13512
+ path: z62.string().min(1).describe("Path to write in the sandbox workspace."),
13513
+ content: z62.string().describe("UTF-8 file content to write.")
13227
13514
  }),
13228
13515
  outputSchema: juniorToolOutputSchema,
13229
13516
  execute: async () => {
@@ -13300,6 +13587,18 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
13300
13587
  hooks.toolOverrides?.imageGenerate
13301
13588
  );
13302
13589
  }
13590
+ if (context.attachmentStorage && context.conversationId) {
13591
+ tools.publishImage = createPublishImageTool({
13592
+ conversationId: context.conversationId,
13593
+ db: getSqlExecutor(),
13594
+ storage: context.attachmentStorage,
13595
+ workspace: context.workspace
13596
+ });
13597
+ tools.unpublishImage = createUnpublishImageTool({
13598
+ conversationId: context.conversationId,
13599
+ db: getSqlExecutor()
13600
+ });
13601
+ }
13303
13602
  if (context.handoff) {
13304
13603
  tools.handoff = createHandoffTool(context.handoff);
13305
13604
  }
@@ -13946,7 +14245,7 @@ function handleToolExecutionError(error, toolName, toolCallId, shouldTrace, conv
13946
14245
  }
13947
14246
 
13948
14247
  // src/chat/tools/execute-tool.ts
13949
- import { z as z61 } from "zod";
14248
+ import { z as z63 } from "zod";
13950
14249
  var EXECUTE_TOOL_NAME = "executeTool";
13951
14250
  function createExecuteToolTool() {
13952
14251
  return zodTool({
@@ -13958,11 +14257,11 @@ function createExecuteToolTool() {
13958
14257
  },
13959
14258
  description: "Execute any catalog tool by exact tool_name from searchTools or a tool-result execution hint. Put tool-specific parameters inside arguments.",
13960
14259
  executionMode: "sequential",
13961
- inputSchema: z61.object({
13962
- tool_name: z61.string().min(1).describe(
14260
+ inputSchema: z63.object({
14261
+ tool_name: z63.string().min(1).describe(
13963
14262
  "Exact catalog tool_name returned by searchTools or a tool-result execution hint."
13964
14263
  ),
13965
- arguments: z61.record(z61.string(), z61.unknown()).describe(
14264
+ arguments: z63.record(z63.string(), z63.unknown()).describe(
13966
14265
  'Arguments matching the selected catalog tool schema, for example { "query": "..." }.'
13967
14266
  ).optional()
13968
14267
  }).strict(),
@@ -14002,7 +14301,7 @@ function planToolExposure(tools) {
14002
14301
  }
14003
14302
 
14004
14303
  // src/chat/tools/search-tools.ts
14005
- import { z as z62 } from "zod";
14304
+ import { z as z64 } from "zod";
14006
14305
  var SEARCH_TOOLS_NAME = "searchTools";
14007
14306
  var DEFAULT_MAX_RESULTS2 = 5;
14008
14307
  var MAX_RESULTS3 = 20;
@@ -14047,29 +14346,29 @@ var SEARCH_STOP_WORDS = /* @__PURE__ */ new Set([
14047
14346
  "you",
14048
14347
  "your"
14049
14348
  ]);
14050
- var searchToolsSourceSchema = z62.object({
14051
- id: z62.string(),
14052
- description: z62.string()
14349
+ var searchToolsSourceSchema = z64.object({
14350
+ id: z64.string(),
14351
+ description: z64.string()
14053
14352
  }).strict();
14054
- var searchToolsToolSchema = z62.object({
14055
- tool_name: z62.string(),
14056
- description: z62.string(),
14057
- exposure: z62.enum(["direct", "deferred", "modelOnly", "hidden"]),
14058
- source: z62.string().optional(),
14059
- input_schema: z62.unknown(),
14060
- call_notes: z62.array(z62.string()),
14061
- annotations: z62.record(z62.string(), z62.unknown())
14353
+ var searchToolsToolSchema = z64.object({
14354
+ tool_name: z64.string(),
14355
+ description: z64.string(),
14356
+ exposure: z64.enum(["direct", "deferred", "modelOnly", "hidden"]),
14357
+ source: z64.string().optional(),
14358
+ input_schema: z64.unknown(),
14359
+ call_notes: z64.array(z64.string()),
14360
+ annotations: z64.record(z64.string(), z64.unknown())
14062
14361
  }).strict();
14063
14362
  var searchToolsOutputSchema = juniorToolOutputSchema.extend({
14064
- query: z62.string().nullable(),
14065
- source: z62.string().nullable(),
14066
- sources: z62.array(searchToolsSourceSchema),
14067
- total_catalog_tools: z62.number().int().nonnegative(),
14068
- total_eligible_tools: z62.number().int().nonnegative(),
14069
- total_matches: z62.number().int().nonnegative(),
14070
- returned_tools: z62.number().int().nonnegative(),
14071
- execution_tool: z62.literal("executeTool"),
14072
- tools: z62.array(searchToolsToolSchema)
14363
+ query: z64.string().nullable(),
14364
+ source: z64.string().nullable(),
14365
+ sources: z64.array(searchToolsSourceSchema),
14366
+ total_catalog_tools: z64.number().int().nonnegative(),
14367
+ total_eligible_tools: z64.number().int().nonnegative(),
14368
+ total_matches: z64.number().int().nonnegative(),
14369
+ returned_tools: z64.number().int().nonnegative(),
14370
+ execution_tool: z64.literal("executeTool"),
14371
+ tools: z64.array(searchToolsToolSchema)
14073
14372
  }).strict();
14074
14373
  function terms(value) {
14075
14374
  const chunks = value.match(/[\p{L}\p{N}]+/gu) ?? [];
@@ -14280,14 +14579,14 @@ function createSearchToolsTool(catalogTools) {
14280
14579
  openWorldHint: false,
14281
14580
  readOnlyHint: true
14282
14581
  },
14283
- inputSchema: z62.object({
14284
- query: z62.string().nullable().describe(
14582
+ inputSchema: z64.object({
14583
+ query: z64.string().nullable().describe(
14285
14584
  "Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
14286
14585
  ).optional(),
14287
- source: z62.string().nullable().describe(
14586
+ source: z64.string().nullable().describe(
14288
14587
  "Optional source id to search within, such as a plugin source returned in sources."
14289
14588
  ).optional(),
14290
- max_results: z62.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
14589
+ max_results: z64.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
14291
14590
  }).strict(),
14292
14591
  outputSchema: searchToolsOutputSchema,
14293
14592
  privateTraceResult: (result) => ({
@@ -14733,7 +15032,7 @@ function createMcpAuthOrchestration(input) {
14733
15032
  }
14734
15033
 
14735
15034
  // src/chat/egress/plugin.ts
14736
- import { randomUUID as randomUUID3 } from "crypto";
15035
+ import { randomUUID as randomUUID4 } from "crypto";
14737
15036
 
14738
15037
  // src/chat/sandbox/egress/credentials.ts
14739
15038
  var HTTP_READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
@@ -15487,8 +15786,8 @@ async function executeCredentialedEgressRequest(input) {
15487
15786
  function credentialContextForPluginEgress(credentialContext) {
15488
15787
  return {
15489
15788
  credentials: credentialContext,
15490
- contextId: randomUUID3(),
15491
- egressId: `plugin-egress:${randomUUID3()}`,
15789
+ contextId: randomUUID4(),
15790
+ egressId: `plugin-egress:${randomUUID4()}`,
15492
15791
  expiresAtMs: Date.now() + 30 * 60 * 1e3
15493
15792
  };
15494
15793
  }
@@ -15546,7 +15845,7 @@ function createPluginEgress(deps) {
15546
15845
  }
15547
15846
 
15548
15847
  // src/chat/services/guardian-action-review.ts
15549
- import { z as z63 } from "zod";
15848
+ import { z as z65 } from "zod";
15550
15849
 
15551
15850
  // src/chat/services/guardian-action-policy.ts
15552
15851
  var GUARDIAN_ACTION_POLICY = `You are judging one planned Junior agent action.
@@ -15614,17 +15913,17 @@ Assess the exact action's intrinsic risk and whether the user's intent authorize
15614
15913
  - Keep the reason to one concise, specific sentence grounded in the main risk or authorization fact. For ask, name the exact action, target, and material side effects the user must confirm.`;
15615
15914
 
15616
15915
  // src/chat/services/guardian-action-review.ts
15617
- var guardianDecisionSchema = z63.object({
15618
- decision: z63.enum(["allow", "ask", "deny"]),
15619
- reason: z63.string().trim().min(1).max(500),
15620
- riskLevel: z63.enum(["low", "medium", "high", "critical"]),
15621
- userAuthorization: z63.enum(["high", "medium", "low", "unknown"])
15916
+ var guardianDecisionSchema = z65.object({
15917
+ decision: z65.enum(["allow", "ask", "deny"]),
15918
+ reason: z65.string().trim().min(1).max(500),
15919
+ riskLevel: z65.enum(["low", "medium", "high", "critical"]),
15920
+ userAuthorization: z65.enum(["high", "medium", "low", "unknown"])
15622
15921
  }).strict();
15623
15922
  var GUARDIAN_REVIEW_TIMEOUT_MS = 6e4;
15624
15923
  var GUARDIAN_REVIEW_MAX_TOKENS = 2e3;
15625
15924
  var MAX_PROPOSAL_CHARS = 192e3;
15626
15925
  function guardianPrompt(proposal) {
15627
- const proposalJson = JSON.stringify(z63.json().parse(proposal), null, 2);
15926
+ const proposalJson = JSON.stringify(z65.json().parse(proposal), null, 2);
15628
15927
  if (proposalJson.length > MAX_PROPOSAL_CHARS) {
15629
15928
  throw new Error(
15630
15929
  `Guardian action proposal exceeds ${MAX_PROPOSAL_CHARS} characters.`
@@ -18220,6 +18519,9 @@ export {
18220
18519
  listThreadReplies,
18221
18520
  renderBlockText,
18222
18521
  renderAttachmentText,
18522
+ readPublicArtifact,
18523
+ publicArtifactHeaders,
18524
+ unpublishedArtifactHeaders,
18223
18525
  latestReportedProgress,
18224
18526
  executeCredentialedEgressRequest,
18225
18527
  createContextCompactor,