@sentry/junior 0.146.0 → 0.147.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 (155) hide show
  1. package/dist/{agent-hooks-SLJADYE5.js → agent-hooks-HS6VGUPM.js} +10 -10
  2. package/dist/api/conversations/detail.d.ts +1 -0
  3. package/dist/api/conversations/event-list.d.ts +1 -0
  4. package/dist/api/schema/conversation.d.ts +4 -0
  5. package/dist/api/schema.js +1 -1
  6. package/dist/api.js +26 -22
  7. package/dist/app.js +220 -238
  8. package/dist/{catalog-runtime-RQIMSDPR.js → catalog-runtime-M6ZTPYRV.js} +5 -5
  9. package/dist/chat/agent/prompt.d.ts +0 -2
  10. package/dist/chat/agent/request.d.ts +2 -5
  11. package/dist/chat/agent/sandbox.d.ts +2 -2
  12. package/dist/chat/agent/tools.d.ts +0 -2
  13. package/dist/chat/agent-dispatch/types.d.ts +2 -2
  14. package/dist/chat/capabilities/jr-rpc-command.d.ts +2 -2
  15. package/dist/chat/configuration/service.d.ts +5 -2
  16. package/dist/chat/configuration/sql.d.ts +9 -0
  17. package/dist/chat/configuration/types.d.ts +17 -13
  18. package/dist/chat/conversations/history.d.ts +3 -0
  19. package/dist/chat/conversations/projection.d.ts +10 -0
  20. package/dist/chat/credentials/unlink-provider.d.ts +2 -1
  21. package/dist/chat/credentials/user-token-store.d.ts +2 -0
  22. package/dist/chat/event-tasks/tool-support.d.ts +2 -0
  23. package/dist/chat/identities/sql.d.ts +8 -0
  24. package/dist/chat/logging.d.ts +2 -0
  25. package/dist/chat/mcp/auth-store.d.ts +0 -2
  26. package/dist/chat/mcp/oauth.d.ts +0 -2
  27. package/dist/chat/oauth-flow.d.ts +3 -1
  28. package/dist/chat/pi/client.d.ts +2 -0
  29. package/dist/chat/plugins/credential-hooks.d.ts +2 -0
  30. package/dist/chat/prompt.d.ts +0 -2
  31. package/dist/chat/resource-events/notification.d.ts +2 -1
  32. package/dist/chat/runtime/delivered-turn-state.d.ts +1 -4
  33. package/dist/chat/runtime/thread-state.d.ts +8 -11
  34. package/dist/chat/runtime/turn-input.d.ts +4 -2
  35. package/dist/chat/runtime/turn-preparation.d.ts +2 -4
  36. package/dist/chat/sandbox/command-result.d.ts +2 -0
  37. package/dist/chat/sandbox/egress/schemas.d.ts +6 -0
  38. package/dist/chat/scheduled-tasks/tool-support.d.ts +2 -0
  39. package/dist/chat/scheduled-tasks/tools/create.d.ts +2 -0
  40. package/dist/chat/scheduled-tasks/tools/delete.d.ts +2 -0
  41. package/dist/chat/scheduled-tasks/tools/list.d.ts +2 -0
  42. package/dist/chat/scheduled-tasks/tools/run-now.d.ts +2 -0
  43. package/dist/chat/scheduled-tasks/tools/update.d.ts +2 -0
  44. package/dist/chat/services/mcp-auth-orchestration.d.ts +0 -3
  45. package/dist/chat/services/plugin-auth-orchestration.d.ts +2 -1
  46. package/dist/chat/services/provider-default-config.d.ts +2 -2
  47. package/dist/chat/services/subscribed-decision.d.ts +3 -0
  48. package/dist/chat/services/subscribed-reply-policy.d.ts +1 -0
  49. package/dist/chat/services/turn-result.d.ts +0 -3
  50. package/dist/chat/services/turn-router.d.ts +3 -0
  51. package/dist/chat/slack/assistant-thread/lifecycle.d.ts +0 -1
  52. package/dist/chat/slack/assistant-thread/title.d.ts +0 -3
  53. package/dist/chat/slack/dispatch-turn.d.ts +1 -1
  54. package/dist/chat/slack/tools/canvas/context.d.ts +0 -10
  55. package/dist/chat/slack/tools/canvas/create.d.ts +2 -0
  56. package/dist/chat/slack/tools/canvas/edit.d.ts +2 -0
  57. package/dist/chat/slack/tools/canvas/read.d.ts +2 -0
  58. package/dist/chat/slack/tools/canvas/write.d.ts +2 -0
  59. package/dist/chat/slack/tools/channel-list-messages.d.ts +2 -0
  60. package/dist/chat/slack/tools/conversation-message-search.d.ts +2 -0
  61. package/dist/chat/slack/tools/list/add-items.d.ts +4 -1
  62. package/dist/chat/slack/tools/list/api.d.ts +8 -1
  63. package/dist/chat/slack/tools/list/create.d.ts +2 -0
  64. package/dist/chat/slack/tools/list/get-items.d.ts +5 -3
  65. package/dist/chat/slack/tools/list/update-item.d.ts +5 -1
  66. package/dist/chat/slack/tools/message-add-reaction.d.ts +2 -0
  67. package/dist/chat/slack/tools/public-search.d.ts +2 -0
  68. package/dist/chat/slack/tools/send-files.d.ts +2 -0
  69. package/dist/chat/slack/tools/thread-read.d.ts +2 -0
  70. package/dist/chat/slack/vision-cache.d.ts +5 -0
  71. package/dist/chat/state/conversation.d.ts +4 -5
  72. package/dist/chat/tool-support/structured-result.d.ts +1 -0
  73. package/dist/chat/tool-support/timed-out-tool-result.d.ts +11 -0
  74. package/dist/chat/tools/create-event-task.d.ts +2 -0
  75. package/dist/chat/tools/delete-event-task.d.ts +2 -0
  76. package/dist/chat/tools/handoff/tool.d.ts +2 -0
  77. package/dist/chat/tools/list-event-tasks.d.ts +2 -0
  78. package/dist/chat/tools/list-resource-event-subscriptions.d.ts +2 -0
  79. package/dist/chat/tools/runtime/report-progress.d.ts +2 -0
  80. package/dist/chat/tools/runtime/spawn-agent.d.ts +2 -0
  81. package/dist/chat/tools/search-conversation-events.d.ts +2 -0
  82. package/dist/chat/tools/search-resource-event-types.d.ts +2 -0
  83. package/dist/chat/tools/search-tools.d.ts +2 -0
  84. package/dist/chat/tools/skill/load-skill.d.ts +2 -0
  85. package/dist/chat/tools/skill/search-mcp-tools.d.ts +2 -0
  86. package/dist/chat/tools/stop-watching-resources.d.ts +2 -0
  87. package/dist/chat/tools/system-time.d.ts +2 -0
  88. package/dist/chat/tools/types.d.ts +0 -6
  89. package/dist/chat/tools/update-event-task.d.ts +2 -0
  90. package/dist/chat/tools/user-lookup.d.ts +29 -0
  91. package/dist/chat/tools/watch-resource-events.d.ts +2 -0
  92. package/dist/chat/tools/web/fetch-tool.d.ts +2 -0
  93. package/dist/chat/tools/web/image-generate.d.ts +2 -0
  94. package/dist/chat/tools/web/search.d.ts +2 -0
  95. package/dist/{chunk-LVW7BLLT.js → chunk-34GS7B6L.js} +2 -2
  96. package/dist/{chunk-B63BF443.js → chunk-4LJO56OJ.js} +9 -1
  97. package/dist/{chunk-H6U2U3EP.js → chunk-6H5SZR24.js} +16 -20
  98. package/dist/{chunk-M6ZWP4RI.js → chunk-745QJ3ZA.js} +1 -1
  99. package/dist/{chunk-BLETMLRX.js → chunk-7A4M7PCV.js} +231 -472
  100. package/dist/{chunk-MKRIZ4VG.js → chunk-7NVJVJID.js} +4 -2
  101. package/dist/{chunk-ZDGHGY74.js → chunk-7UQIVT6G.js} +13 -6
  102. package/dist/{chunk-GDQEU4I7.js → chunk-AIOK6LAG.js} +28 -489
  103. package/dist/{chunk-QSXZ42KX.js → chunk-AVOCH2Z5.js} +3 -3
  104. package/dist/{chunk-FXDDDSPL.js → chunk-AVZDSUFB.js} +4 -4
  105. package/dist/{chunk-OFPYOC3M.js → chunk-AYU72WO7.js} +102 -72
  106. package/dist/chunk-AZ7EAOBE.js +566 -0
  107. package/dist/{chunk-PH4Q3A6W.js → chunk-CSZINQJ2.js} +1 -1
  108. package/dist/{chunk-X2WMBTS3.js → chunk-CWP5RHVX.js} +4 -4
  109. package/dist/{chunk-HQE6EJS5.js → chunk-DLDRQHG5.js} +1 -1
  110. package/dist/{chunk-MCFIXAV5.js → chunk-DU74WPIC.js} +55 -37
  111. package/dist/{chunk-X22KCSCO.js → chunk-EFLJ2WJH.js} +6 -4
  112. package/dist/{chunk-37JJDS4H.js → chunk-GGB4WL5A.js} +1 -1
  113. package/dist/{chunk-F7REGDKO.js → chunk-IIOOO4FQ.js} +1 -1
  114. package/dist/{chunk-PB222GIA.js → chunk-JUUKWRBE.js} +1 -1
  115. package/dist/{chunk-T5GXFFLA.js → chunk-K4SZAP3K.js} +1 -1
  116. package/dist/{chunk-GYEKOX7N.js → chunk-ORO3PWKQ.js} +1 -1
  117. package/dist/{chunk-AISNSNDV.js → chunk-PVNG6UMU.js} +3 -3
  118. package/dist/{chunk-47OSH2ZO.js → chunk-Q4R73I43.js} +365 -206
  119. package/dist/{chunk-QG7OOKIN.js → chunk-RXBVB2JM.js} +1 -1
  120. package/dist/{chunk-V6SRLKUB.js → chunk-SGZO7UWH.js} +2 -2
  121. package/dist/{chunk-JLMVCNXL.js → chunk-SVHUEHUL.js} +1 -0
  122. package/dist/{chunk-FEKQHPVA.js → chunk-X5UY34KT.js} +6 -5
  123. package/dist/{chunk-FGHADGIC.js → chunk-YBVXBNSV.js} +2 -2
  124. package/dist/{chunk-JUA6VU2Z.js → chunk-YEO3VX72.js} +10 -23
  125. package/dist/{chunk-SCGVWUZX.js → chunk-YHDERDRO.js} +7 -6
  126. package/dist/{chunk-TCEJ7XXM.js → chunk-YNTTROJT.js} +1 -1
  127. package/dist/{chunk-37EVZP66.js → chunk-YSB2N563.js} +49 -8
  128. package/dist/{chunk-W65V465O.js → chunk-Z4YU7Z4L.js} +3 -2
  129. package/dist/cli/chat.js +32 -32
  130. package/dist/cli/check.js +6 -6
  131. package/dist/cli/plugins.js +13 -13
  132. package/dist/cli/snapshot-create.js +9 -9
  133. package/dist/cli/upgrade.js +7 -7
  134. package/dist/db/schema/location-configurations.d.ts +127 -0
  135. package/dist/db/schema.d.ts +128 -1
  136. package/dist/{db-WWOMXWTT.js → db-CSEW4RII.js} +7 -7
  137. package/dist/instrumentation.js +4 -4
  138. package/dist/nitro.js +2 -2
  139. package/dist/{oauth-callback-server-A6ZZX74U.js → oauth-callback-server-FUEV5HNG.js} +24 -24
  140. package/dist/{runner-KSGB2UAV.js → runner-U3XHSKSH.js} +21 -39
  141. package/dist/{skills-26QPWKVS.js → skills-AKE6W3WI.js} +6 -6
  142. package/dist/spawn-B6GDTWJ4.js +39 -0
  143. package/dist/{validation-OPSRGFGH.js → validation-WDTAULUF.js} +6 -6
  144. package/dist/version.js +1 -1
  145. package/dist/{work-VMSW7STJ.js → work-C3HAO2BG.js} +17 -17
  146. package/dist/{worker-2JNFB7C7.js → worker-LNP4YKBM.js} +10 -10
  147. package/migrations/0024_misty_typhoid_mary.sql +12 -0
  148. package/migrations/meta/0024_snapshot.json +2275 -0
  149. package/migrations/meta/_journal.json +7 -0
  150. package/package.json +5 -5
  151. package/dist/chat/slack/tools/user-lookup.d.ts +0 -27
  152. package/dist/chat/state/artifacts.d.ts +0 -30
  153. package/dist/chat/tool-support/turn-deadline-result.d.ts +0 -3
  154. package/dist/chunk-Q6QZTTLS.js +0 -55
  155. package/dist/spawn-5LAJXZ2P.js +0 -39
@@ -7,7 +7,7 @@ import {
7
7
  PluginCredentialFailureError,
8
8
  agentNameSchema,
9
9
  createPluginAuthOrchestration
10
- } from "./chunk-FEKQHPVA.js";
10
+ } from "./chunk-X5UY34KT.js";
11
11
  import {
12
12
  authorizationId
13
13
  } from "./chunk-DIB4GX3G.js";
@@ -21,14 +21,18 @@ import {
21
21
  getMcpAwareErrorType,
22
22
  getMcpAwareTelemetryMessage,
23
23
  getMcpProviderErrorAttributes,
24
+ getOAuthAccountProviders,
24
25
  hasEgressCredentialHooks,
25
26
  issuePluginCredential,
26
27
  issueProviderCredentialLease,
28
+ lookupSlackUserByEmail,
29
+ lookupSlackUserProfile,
27
30
  onPluginEgressResponse,
28
31
  patchMcpAuthSession,
32
+ searchSlackUsers,
29
33
  selectPluginGrant,
30
34
  toMcpProviderError
31
- } from "./chunk-47OSH2ZO.js";
35
+ } from "./chunk-Q4R73I43.js";
32
36
  import {
33
37
  RetryableDeliveryError,
34
38
  actorFromRouting,
@@ -44,12 +48,12 @@ import {
44
48
  getSlackMessagePermalink,
45
49
  resolveBaseUrl,
46
50
  uploadFilesToConversation
47
- } from "./chunk-ZDGHGY74.js";
51
+ } from "./chunk-7UQIVT6G.js";
48
52
  import {
49
53
  estimateTextTokens,
50
54
  getAgentContextCompactionTriggerTokens,
51
55
  getAgentContextInputLimitTokens
52
- } from "./chunk-T5GXFFLA.js";
56
+ } from "./chunk-K4SZAP3K.js";
53
57
  import {
54
58
  AGENTS_REMOVAL_NOTICE,
55
59
  AGENTS_REPLACEMENT_NOTICE,
@@ -89,7 +93,6 @@ import {
89
93
  loadConversationProjection,
90
94
  loadTurnCheckpoint,
91
95
  loadTurnRoute,
92
- mergeArtifactsState,
93
96
  missingPathSearchResult,
94
97
  normalizeToLf,
95
98
  normalizeToolNameFromResult,
@@ -111,7 +114,7 @@ import {
111
114
  stripRuntimeTurnContext,
112
115
  trimTrailingAssistantMessages,
113
116
  truncateText
114
- } from "./chunk-GDQEU4I7.js";
117
+ } from "./chunk-AIOK6LAG.js";
115
118
  import {
116
119
  JUNIOR_THREAD_STATE_TTL_MS
117
120
  } from "./chunk-3Y47VMHV.js";
@@ -143,7 +146,7 @@ import {
143
146
  runNonInteractiveCommand,
144
147
  throwSandboxOperationError,
145
148
  wrapSandboxSetupError
146
- } from "./chunk-FXDDDSPL.js";
149
+ } from "./chunk-AVZDSUFB.js";
147
150
  import {
148
151
  SCHEDULED_TASK_SYSTEM_ACTOR,
149
152
  compactEventTask,
@@ -175,15 +178,15 @@ import {
175
178
  saveEventTask,
176
179
  scheduledTaskAttributes,
177
180
  writableEventTask
178
- } from "./chunk-X22KCSCO.js";
181
+ } from "./chunk-EFLJ2WJH.js";
179
182
  import {
180
183
  parseSlackThreadId
181
- } from "./chunk-PH4Q3A6W.js";
184
+ } from "./chunk-CSZINQJ2.js";
182
185
  import {
183
186
  SHORT_TITLE_MAX_LENGTH,
184
187
  generateShortTitle,
185
188
  resolveTaskTitle
186
- } from "./chunk-W65V465O.js";
189
+ } from "./chunk-Z4YU7Z4L.js";
187
190
  import {
188
191
  ToolInputError,
189
192
  addAgentTurnUsage,
@@ -201,7 +204,7 @@ import {
201
204
  getSlackToolContext,
202
205
  readActorIdentity,
203
206
  resolveChannelCapabilities
204
- } from "./chunk-SCGVWUZX.js";
207
+ } from "./chunk-YHDERDRO.js";
205
208
  import {
206
209
  SlackActionError,
207
210
  downloadPrivateSlackFile,
@@ -210,7 +213,7 @@ import {
210
213
  isConversationScopedChannel,
211
214
  normalizeSlackConversationId,
212
215
  withSlackRetries
213
- } from "./chunk-V6SRLKUB.js";
216
+ } from "./chunk-SGZO7UWH.js";
214
217
  import {
215
218
  KNOWN_CONVERSATION_EVENT_TYPES,
216
219
  contextProvenance,
@@ -221,12 +224,11 @@ import {
221
224
  getSqlExecutor,
222
225
  instructionActors,
223
226
  instructionProvenanceFor,
224
- sameActorIdentity,
225
- upsertIdentity
226
- } from "./chunk-37EVZP66.js";
227
+ sameActorIdentity
228
+ } from "./chunk-YSB2N563.js";
227
229
  import {
228
230
  juniorIdentities
229
- } from "./chunk-MCFIXAV5.js";
231
+ } from "./chunk-DU74WPIC.js";
230
232
  import {
231
233
  SANDBOX_DATA_ROOT,
232
234
  SANDBOX_SKILLS_ROOT,
@@ -238,7 +240,7 @@ import {
238
240
  } from "./chunk-EM225ITJ.js";
239
241
  import {
240
242
  getStateAdapter
241
- } from "./chunk-GYEKOX7N.js";
243
+ } from "./chunk-ORO3PWKQ.js";
242
244
  import {
243
245
  ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
244
246
  COMPACTION_SUMMARY_PREFIX,
@@ -271,7 +273,7 @@ import {
271
273
  resolveGatewayCredential,
272
274
  resolveGatewayModel,
273
275
  unwrapCurrentInstruction
274
- } from "./chunk-MKRIZ4VG.js";
276
+ } from "./chunk-7NVJVJID.js";
275
277
  import {
276
278
  canExposeConversationPayload,
277
279
  resolveConversationPrivacy,
@@ -281,16 +283,16 @@ import {
281
283
  toGenAiMessagesTraceAttributes,
282
284
  toGenAiPayloadMetadata,
283
285
  toGenAiPayloadTraceAttributes
284
- } from "./chunk-QG7OOKIN.js";
286
+ } from "./chunk-RXBVB2JM.js";
285
287
  import {
286
288
  discoverSkills,
287
289
  findSkillByName,
288
290
  loadSkillsByName,
289
291
  parseSkillInvocation
290
- } from "./chunk-FGHADGIC.js";
292
+ } from "./chunk-YBVXBNSV.js";
291
293
  import {
292
294
  pluginCatalogRuntime
293
- } from "./chunk-PB222GIA.js";
295
+ } from "./chunk-JUUKWRBE.js";
294
296
  import {
295
297
  CredentialUnavailableError,
296
298
  OAuthProviderError,
@@ -298,7 +300,7 @@ import {
298
300
  getOAuthProviderErrorAttributes,
299
301
  resolveAuthTokenPlaceholder,
300
302
  resolvePluginCommandEnv
301
- } from "./chunk-37JJDS4H.js";
303
+ } from "./chunk-GGB4WL5A.js";
302
304
  import {
303
305
  credentialUserSubjectId
304
306
  } from "./chunk-RUIXF3YQ.js";
@@ -328,7 +330,7 @@ import {
328
330
  summarizeMessageText,
329
331
  withLogContext,
330
332
  withSpan
331
- } from "./chunk-B63BF443.js";
333
+ } from "./chunk-4LJO56OJ.js";
332
334
  import {
333
335
  startInactiveSpan,
334
336
  withActiveSpan
@@ -810,7 +812,6 @@ import { isRetryableAssistantError } from "@earendil-works/pi-ai";
810
812
  function buildTurnResult(input) {
811
813
  const {
812
814
  newMessages,
813
- artifactStatePatch,
814
815
  toolCalls,
815
816
  sandboxRef,
816
817
  durationMs,
@@ -906,7 +907,6 @@ function buildTurnResult(input) {
906
907
  };
907
908
  return {
908
909
  text: primaryText,
909
- artifactStatePatch: Object.keys(artifactStatePatch).length > 0 ? artifactStatePatch : void 0,
910
910
  sandboxRef,
911
911
  piMessages: input.piMessages,
912
912
  diagnostics: resolvedDiagnostics
@@ -986,27 +986,22 @@ function getDiscardedRetryUsage(messages, retryMessages) {
986
986
  return hasAgentTurnUsage(usage) ? usage : void 0;
987
987
  }
988
988
 
989
- // src/chat/tool-support/turn-deadline-result.ts
990
- var TURN_DEADLINE_INTERRUPTION = {
991
- cause: "turn_deadline",
992
- scope: "execution_slice",
993
- task_status: "active"
994
- };
995
- function annotateTurnDeadlineToolResult(result) {
996
- if (!result.details || typeof result.details !== "object" || Array.isArray(result.details) || !("aborted" in result.details) || result.details.aborted !== true) {
989
+ // src/chat/tool-support/timed-out-tool-result.ts
990
+ function projectTimedOutToolResult(result) {
991
+ const details = result.details;
992
+ if (!details || typeof details !== "object" || Array.isArray(details) || !("aborted" in details) || details.aborted !== true) {
997
993
  return void 0;
998
994
  }
999
- const details = {
1000
- ...result.details,
1001
- interruption: TURN_DEADLINE_INTERRUPTION
1002
- };
1003
- const envelope = makeStructuredToolOutput(details, {
1004
- content: result.content.slice(1)
995
+ const record2 = details;
996
+ const target = typeof record2.target === "string" && record2.target.length > 0 ? record2.target : void 0;
997
+ const envelope = makeStructuredToolOutput({
998
+ ...target ? { target } : {},
999
+ timed_out: true
1005
1000
  });
1006
1001
  return {
1007
1002
  content: envelope.content,
1008
1003
  details: envelope.details,
1009
- isError: true
1004
+ isError: false
1010
1005
  };
1011
1006
  }
1012
1007
 
@@ -1227,13 +1222,15 @@ async function classifyTurn(args) {
1227
1222
  prompt: args.prompt,
1228
1223
  thinkingLevel: "low",
1229
1224
  system: buildClassifierSystemPrompt(Object.keys(args.profiles)),
1230
- temperature: 0
1225
+ temperature: 0,
1226
+ promptName: "junior.thinking_route"
1231
1227
  });
1232
1228
  const parsed = schema.parse(result.object);
1233
1229
  const reason = parsed.reason.trim();
1234
1230
  if (parsed.confidence < CLASSIFIER_CONFIDENCE_THRESHOLD) {
1235
1231
  return {
1236
1232
  confidence: parsed.confidence,
1233
+ ...result.costUsd !== void 0 ? { costUsd: result.costUsd } : {},
1237
1234
  profile: STANDARD_MODEL_PROFILE,
1238
1235
  reasoningLevel: CLASSIFIER_FALLBACK_REASONING_LEVEL,
1239
1236
  reason: `low_confidence_medium_default:${reason}`,
@@ -1242,6 +1239,7 @@ async function classifyTurn(args) {
1242
1239
  }
1243
1240
  return {
1244
1241
  confidence: parsed.confidence,
1242
+ ...result.costUsd !== void 0 ? { costUsd: result.costUsd } : {},
1245
1243
  profile: parsed.profile,
1246
1244
  reasoningLevel: parsed.reasoning_level,
1247
1245
  reason,
@@ -1764,34 +1762,6 @@ function formatReferenceFilesLines() {
1764
1762
  return `- ${escapeXml(name)} (${escapeXml(`${SANDBOX_DATA_ROOT}/${name}`)})`;
1765
1763
  });
1766
1764
  }
1767
- function formatArtifactsLines(artifactState) {
1768
- if (!artifactState) return null;
1769
- const lines = [];
1770
- if (artifactState.lastCanvasId) {
1771
- lines.push(`- last_canvas_id: ${escapeXml(artifactState.lastCanvasId)}`);
1772
- }
1773
- if (artifactState.lastCanvasUrl) {
1774
- lines.push(`- last_canvas_url: ${escapeXml(artifactState.lastCanvasUrl)}`);
1775
- }
1776
- if (artifactState.recentCanvases && artifactState.recentCanvases.length > 0) {
1777
- lines.push("- recent_canvases:");
1778
- for (const canvas of artifactState.recentCanvases) {
1779
- lines.push(` - id: ${escapeXml(canvas.id)}`);
1780
- if (canvas.title) lines.push(` title: ${escapeXml(canvas.title)}`);
1781
- if (canvas.url) lines.push(` url: ${escapeXml(canvas.url)}`);
1782
- if (canvas.createdAt) {
1783
- lines.push(` created_at: ${escapeXml(canvas.createdAt)}`);
1784
- }
1785
- }
1786
- }
1787
- if (artifactState.lastListId) {
1788
- lines.push(`- last_list_id: ${escapeXml(artifactState.lastListId)}`);
1789
- }
1790
- if (artifactState.lastListUrl) {
1791
- lines.push(`- last_list_url: ${escapeXml(artifactState.lastListUrl)}`);
1792
- }
1793
- return lines.length > 0 ? lines : null;
1794
- }
1795
1765
  function formatConfigurationLines(configuration) {
1796
1766
  const keys = Object.keys(configuration ?? {}).sort(
1797
1767
  (a, b) => a.localeCompare(b)
@@ -1842,7 +1812,7 @@ var EXECUTION_CONTRACT_RULES = [
1842
1812
  "- Ask the user only for missing access, approval, or a decision that blocks safe progress. Ask one focused question; otherwise infer conservatively and continue.",
1843
1813
  "- For conflicting evidence, compare sources and state which source is authoritative for the answer.",
1844
1814
  "- 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.",
1845
- "- 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."
1815
+ "- A tool result with `timed_out: true` means that attempt did not finish. Continue the active task. Before retrying work that may have side effects, inspect authoritative state and do not repeat a mutation that already applied."
1846
1816
  ];
1847
1817
  var CONVERSATION_RULES = [
1848
1818
  "- In thread follow-ups, answer from prior thread context; do not repeat resolved clarifying questions.",
@@ -2004,10 +1974,6 @@ function buildContextSection(params) {
2004
1974
  if (dispatchLines) {
2005
1975
  blocks.push(dispatchLines);
2006
1976
  }
2007
- const artifactLines = formatArtifactsLines(params.artifactState);
2008
- if (artifactLines) {
2009
- blocks.push(renderTag("artifacts", artifactLines));
2010
- }
2011
1977
  const configLines = formatConfigurationLines(params.configuration);
2012
1978
  if (configLines) {
2013
1979
  blocks.push(
@@ -2112,7 +2078,6 @@ function buildTurnContextPrompt(params) {
2112
2078
  pluginPromptContributions,
2113
2079
  includeSessionContext ? buildContextSection({
2114
2080
  actor: params.actor,
2115
- artifactState: params.artifactState,
2116
2081
  configuration: params.configuration,
2117
2082
  dispatch: params.dispatch
2118
2083
  }) : null,
@@ -2410,7 +2375,6 @@ async function assemblePrompt(args) {
2410
2375
  source
2411
2376
  } : void 0,
2412
2377
  actor: isUserActor(args.currentActor) ? args.currentActor : void 0,
2413
- artifactState: args.artifactState,
2414
2378
  configuration: args.configurationValues
2415
2379
  }) : null;
2416
2380
  const turnContextParts = turnContextPrompt ? [{ type: "text", text: turnContextPrompt }] : [];
@@ -2496,9 +2460,9 @@ function commandResult(input) {
2496
2460
  exitCode: input.exitCode
2497
2461
  };
2498
2462
  }
2499
- function requireChannelConfiguration(deps) {
2500
- if (deps.channelConfiguration) {
2501
- return { ok: true, configuration: deps.channelConfiguration };
2463
+ function requireLocationConfiguration(deps) {
2464
+ if (deps.locationConfiguration) {
2465
+ return { ok: true, configuration: deps.locationConfiguration };
2502
2466
  }
2503
2467
  return {
2504
2468
  ok: false,
@@ -2544,7 +2508,7 @@ async function handleConfigCommand(args, deps) {
2544
2508
  "jr-rpc config list [--prefix <value>]"
2545
2509
  ].join("\n");
2546
2510
  const subverb = (args[0] ?? "").trim();
2547
- const configurationResult = requireChannelConfiguration(deps);
2511
+ const configurationResult = requireLocationConfiguration(deps);
2548
2512
  if (!configurationResult.ok) {
2549
2513
  return configurationResult.result;
2550
2514
  }
@@ -6039,7 +6003,7 @@ function createAgentSandbox(options) {
6039
6003
  if (command) {
6040
6004
  const result = await maybeExecuteJrRpcCustomCommand(command, {
6041
6005
  activeSkill: options.getActiveSkill(),
6042
- channelConfiguration: options.channelConfiguration,
6006
+ locationConfiguration: options.locationConfiguration,
6043
6007
  actorId: isUserActor(options.actor) ? options.actor.userId : void 0,
6044
6008
  onConfigurationValueChanged: (key, value) => {
6045
6009
  if (value === void 0) {
@@ -6924,7 +6888,8 @@ async function enrichImagePrompt(rawPrompt) {
6924
6888
  modelId: botConfig.fastModelId,
6925
6889
  system: ENRICHMENT_SYSTEM_PROMPT,
6926
6890
  messages: [{ role: "user", content: rawPrompt, timestamp: Date.now() }],
6927
- maxTokens: 1024
6891
+ maxTokens: 1024,
6892
+ promptName: "junior.image_prompt_enrichment"
6928
6893
  });
6929
6894
  if (text && text.trim().length > 0) {
6930
6895
  logInfo("image.prompt.enriched", {
@@ -10564,45 +10529,6 @@ async function readCanvas(canvasIdOrUrl) {
10564
10529
  };
10565
10530
  }
10566
10531
 
10567
- // src/chat/slack/tools/canvas/context.ts
10568
- var MAX_RECENT_CANVASES = 5;
10569
- function mergeRecentCanvases(existing, created) {
10570
- const nextEntry = {
10571
- id: created.id,
10572
- title: created.title,
10573
- url: created.url,
10574
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
10575
- };
10576
- const prior = existing ?? [];
10577
- const deduped = prior.filter((entry) => entry.id !== created.id);
10578
- return [nextEntry, ...deduped].slice(0, MAX_RECENT_CANVASES);
10579
- }
10580
- function resolveCanvasTarget(canvas) {
10581
- const canvasId = extractCanvasId(canvas);
10582
- if (!canvasId) {
10583
- return {
10584
- ok: false,
10585
- error: "Could not parse a Slack canvas/file ID from input. Provide an F-prefixed ID or a Slack canvas/docs URL."
10586
- };
10587
- }
10588
- return { ok: true, canvasId };
10589
- }
10590
- function storedCanvasUrl(state, canvasId) {
10591
- const lastCanvasUrl = state.artifactState.lastCanvasUrl;
10592
- if (lastCanvasUrl && extractCanvasId(lastCanvasUrl) === canvasId) {
10593
- return lastCanvasUrl;
10594
- }
10595
- for (const canvas of state.artifactState.recentCanvases ?? []) {
10596
- if (extractCanvasId(canvas.id) === canvasId) {
10597
- return canvas.url;
10598
- }
10599
- if (canvas.url && extractCanvasId(canvas.url) === canvasId) {
10600
- return canvas.url;
10601
- }
10602
- }
10603
- return void 0;
10604
- }
10605
-
10606
10532
  // src/chat/slack/tools/canvas/create.ts
10607
10533
  import { z as z41 } from "zod";
10608
10534
  function createSlackCanvasCreateTool(context, state) {
@@ -10648,18 +10574,6 @@ function createSlackCanvasCreateTool(context, state) {
10648
10574
  markdown,
10649
10575
  channelId: targetChannelId
10650
10576
  });
10651
- await state.patchArtifactState({
10652
- lastCanvasId: created.canvasId,
10653
- lastCanvasUrl: created.permalink,
10654
- recentCanvases: mergeRecentCanvases(
10655
- state.artifactState.recentCanvases,
10656
- {
10657
- id: created.canvasId,
10658
- title,
10659
- url: created.permalink
10660
- }
10661
- )
10662
- });
10663
10577
  const response = {
10664
10578
  canvas_id: created.canvasId,
10665
10579
  permalink: created.permalink,
@@ -10671,6 +10585,18 @@ function createSlackCanvasCreateTool(context, state) {
10671
10585
  });
10672
10586
  }
10673
10587
 
10588
+ // src/chat/slack/tools/canvas/context.ts
10589
+ function resolveCanvasTarget(canvas) {
10590
+ const canvasId = extractCanvasId(canvas);
10591
+ if (!canvasId) {
10592
+ return {
10593
+ ok: false,
10594
+ error: "Could not parse a Slack canvas/file ID from input. Provide an F-prefixed ID or a Slack canvas/docs URL."
10595
+ };
10596
+ }
10597
+ return { ok: true, canvasId };
10598
+ }
10599
+
10674
10600
  // src/chat/slack/tools/canvas/edit.ts
10675
10601
  import { z as z42 } from "zod";
10676
10602
  function prepareCanvasEditArguments(input) {
@@ -10738,10 +10664,6 @@ function createSlackCanvasEditTool(state) {
10738
10664
  canvasId: target.canvasId,
10739
10665
  markdown: newContent
10740
10666
  });
10741
- await state.patchArtifactState({
10742
- lastCanvasId: target.canvasId,
10743
- lastCanvasUrl: current.permalink ?? state.artifactState.lastCanvasUrl
10744
- });
10745
10667
  const diff = buildCompactDiff(
10746
10668
  normalizeCanvasMarkdown(baseContent).markdown,
10747
10669
  written.markdown
@@ -10862,10 +10784,6 @@ function createSlackCanvasWriteTool(state) {
10862
10784
  canvasId: target.canvasId,
10863
10785
  markdown: content
10864
10786
  });
10865
- await state.patchArtifactState({
10866
- lastCanvasId: target.canvasId,
10867
- lastCanvasUrl: storedCanvasUrl(state, target.canvasId)
10868
- });
10869
10787
  const response = {
10870
10788
  canvas_id: target.canvasId,
10871
10789
  normalized_heading_count: written.normalizedHeadingCount,
@@ -10950,9 +10868,19 @@ async function createTodoList(name) {
10950
10868
  permalink
10951
10869
  };
10952
10870
  }
10871
+ async function getListColumnMap(listId) {
10872
+ const client = getSlackClient();
10873
+ const response = await withSlackRetries(
10874
+ () => client.files.info({ file: listId }),
10875
+ 3,
10876
+ { action: "files.info", idempotent: true }
10877
+ );
10878
+ const file = response.file;
10879
+ return inferListColumnMap(file?.list_metadata?.schema ?? []);
10880
+ }
10953
10881
  async function addListItems(input) {
10954
10882
  const client = getSlackClient();
10955
- const listColumnMap = input.listColumnMap ?? {};
10883
+ const listColumnMap = input.listColumnMap ?? await getListColumnMap(input.listId);
10956
10884
  if (!listColumnMap.titleColumnId) {
10957
10885
  throw new Error(
10958
10886
  "Cannot add list items because title column could not be inferred"
@@ -11021,19 +10949,20 @@ async function listItems(listId, limit = 100) {
11021
10949
  }
11022
10950
  async function updateListItem(input) {
11023
10951
  const client = getSlackClient();
10952
+ const listColumnMap = Object.keys(input.listColumnMap).length > 0 ? input.listColumnMap : await getListColumnMap(input.listId);
11024
10953
  const cells = [];
11025
- if (typeof input.completed === "boolean" && input.listColumnMap.completedColumnId) {
10954
+ if (typeof input.completed === "boolean" && listColumnMap.completedColumnId) {
11026
10955
  cells.push({
11027
10956
  row_id: input.itemId,
11028
- column_id: input.listColumnMap.completedColumnId,
10957
+ column_id: listColumnMap.completedColumnId,
11029
10958
  checkbox: input.completed
11030
10959
  });
11031
10960
  }
11032
- if (typeof input.title === "string" && input.title.trim() && input.listColumnMap.titleColumnId) {
10961
+ if (typeof input.title === "string" && input.title.trim() && listColumnMap.titleColumnId) {
11033
10962
  cells.push({
11034
10963
  row_id: input.itemId,
11035
10964
  ...richTextField(
11036
- input.listColumnMap.titleColumnId,
10965
+ listColumnMap.titleColumnId,
11037
10966
  input.title
11038
10967
  )
11039
10968
  });
@@ -11063,8 +10992,9 @@ function createSlackListAddItemsTool(state) {
11063
10992
  openWorldHint: true,
11064
10993
  readOnlyHint: false
11065
10994
  },
11066
- description: "Add tasks to the active Slack list tracked in artifact context. Use when the user wants actionable items recorded in the current thread list. Do not use when no list exists and list creation was not requested.",
10995
+ description: "Add tasks to a Slack list. Use the list_id from the list create result or conversation history.",
11067
10996
  inputSchema: z45.object({
10997
+ list_id: z45.string().min(1).describe("ID of the Slack list to update."),
11068
10998
  items: z45.array(z45.string().min(1)).min(1).max(25).describe("List item titles to create."),
11069
10999
  assignee_user_id: slackUserIdParam(
11070
11000
  "Optional Slack user ID assigned to all created items."
@@ -11072,17 +11002,13 @@ function createSlackListAddItemsTool(state) {
11072
11002
  due_date: z45.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Optional due date in YYYY-MM-DD format.").optional()
11073
11003
  }),
11074
11004
  outputSchema: juniorToolOutputSchema,
11075
- execute: async ({ items, assignee_user_id, due_date }) => {
11076
- const targetListId = state.getCurrentListId();
11077
- if (!targetListId) {
11078
- throw new ToolInputError("No active list found in artifact context");
11079
- }
11005
+ execute: async ({ list_id, items, assignee_user_id, due_date }) => {
11080
11006
  const parsedAssigneeUserId = assignee_user_id === void 0 ? void 0 : parseRequiredSlackUserIdParam("assignee_user_id", assignee_user_id);
11081
11007
  if (parsedAssigneeUserId?.ok === false) {
11082
11008
  throw new ToolInputError(parsedAssigneeUserId.error);
11083
11009
  }
11084
11010
  const operationKey = createOperationKey("slackListAddItems", {
11085
- list_id: targetListId,
11011
+ list_id,
11086
11012
  items,
11087
11013
  assignee_user_id: parsedAssigneeUserId?.value ?? null,
11088
11014
  due_date: due_date ?? null
@@ -11095,18 +11021,13 @@ function createSlackListAddItemsTool(state) {
11095
11021
  };
11096
11022
  }
11097
11023
  const result = await addListItems({
11098
- listId: targetListId,
11024
+ listId: list_id,
11099
11025
  titles: items,
11100
- listColumnMap: state.artifactState.listColumnMap,
11101
11026
  assigneeUserId: parsedAssigneeUserId?.value,
11102
11027
  dueDate: due_date
11103
11028
  });
11104
- await state.patchArtifactState({
11105
- lastListId: targetListId,
11106
- listColumnMap: result.listColumnMap
11107
- });
11108
11029
  const response = {
11109
- list_id: targetListId,
11030
+ list_id,
11110
11031
  created_item_ids: result.createdItemIds,
11111
11032
  created_count: result.createdItemIds.length
11112
11033
  };
@@ -11141,11 +11062,6 @@ function createSlackListCreateTool(state) {
11141
11062
  };
11142
11063
  }
11143
11064
  const list = await createTodoList(name);
11144
- await state.patchArtifactState({
11145
- lastListId: list.listId,
11146
- lastListUrl: list.permalink,
11147
- listColumnMap: list.listColumnMap
11148
- });
11149
11065
  const response = {
11150
11066
  list_id: list.listId,
11151
11067
  permalink: list.permalink,
@@ -11159,9 +11075,9 @@ function createSlackListCreateTool(state) {
11159
11075
 
11160
11076
  // src/chat/slack/tools/list/get-items.ts
11161
11077
  import { z as z47 } from "zod";
11162
- function createSlackListGetItemsTool(state) {
11078
+ function createSlackListGetItemsTool() {
11163
11079
  return zodTool({
11164
- description: "Read items from the active Slack list tracked in artifact context. Use when the user asks for task status, open items, or list contents. Do not use when list state is already known from the immediately prior result.",
11080
+ description: "Read items from a Slack list. Use the list_id from a prior tool result or conversation history.",
11165
11081
  annotations: {
11166
11082
  destructiveHint: false,
11167
11083
  idempotentHint: true,
@@ -11169,18 +11085,15 @@ function createSlackListGetItemsTool(state) {
11169
11085
  readOnlyHint: true
11170
11086
  },
11171
11087
  inputSchema: z47.object({
11088
+ list_id: z47.string().min(1).describe("ID of the Slack list to read."),
11172
11089
  limit: z47.coerce.number().int().min(1).max(200).describe("Maximum number of list items to return.").optional()
11173
11090
  }),
11174
11091
  outputSchema: juniorToolOutputSchema,
11175
- execute: async ({ limit }) => {
11176
- const targetListId = state.getCurrentListId();
11092
+ execute: async ({ list_id, limit }) => {
11177
11093
  const resolvedLimit = limit ?? 100;
11178
- if (!targetListId) {
11179
- throw new ToolInputError("No active list found in artifact context");
11180
- }
11181
- const items = await listItems(targetListId, resolvedLimit);
11094
+ const items = await listItems(list_id, resolvedLimit);
11182
11095
  return {
11183
- list_id: targetListId,
11096
+ list_id,
11184
11097
  items: items.map((item) => ({ id: item.id, fields: item.fields }))
11185
11098
  };
11186
11099
  }
@@ -11195,11 +11108,13 @@ var booleanInput3 = (description) => z48.preprocess(
11195
11108
  ).describe(description);
11196
11109
  var updateListItemInputSchema = z48.union([
11197
11110
  z48.object({
11111
+ list_id: z48.string().min(1).describe("ID of the Slack list to update."),
11198
11112
  item_id: z48.string().min(1).describe("ID of the Slack list item to update."),
11199
11113
  completed: booleanInput3("Optional completion status update."),
11200
11114
  title: z48.string().min(1).describe("Optional new item title.").optional()
11201
11115
  }),
11202
11116
  z48.object({
11117
+ list_id: z48.string().min(1).describe("ID of the Slack list to update."),
11203
11118
  item_id: z48.string().min(1).describe("ID of the Slack list item to update."),
11204
11119
  completed: booleanInput3("Optional completion status update.").optional(),
11205
11120
  title: z48.string().min(1).describe("Optional new item title.")
@@ -11213,16 +11128,12 @@ function createSlackListUpdateItemTool(state) {
11213
11128
  openWorldHint: true,
11214
11129
  readOnlyHint: false
11215
11130
  },
11216
- description: "Update an item in the active Slack list tracked in artifact context (title/completion). Use when the user asks to mark progress or rename a tracked task. Do not use to add new tasks.",
11131
+ description: "Update an item in a Slack list. Use list_id and item_id from prior tool results or conversation history.",
11217
11132
  inputSchema: updateListItemInputSchema,
11218
11133
  outputSchema: juniorToolOutputSchema,
11219
- execute: async ({ item_id, completed, title }) => {
11220
- const targetListId = state.getCurrentListId();
11221
- if (!targetListId) {
11222
- throw new ToolInputError("No active list found in artifact context");
11223
- }
11134
+ execute: async ({ list_id, item_id, completed, title }) => {
11224
11135
  const operationKey = createOperationKey("slackListUpdateItem", {
11225
- list_id: targetListId,
11136
+ list_id,
11226
11137
  item_id,
11227
11138
  completed: completed ?? null,
11228
11139
  title: title ?? null
@@ -11235,15 +11146,14 @@ function createSlackListUpdateItemTool(state) {
11235
11146
  };
11236
11147
  }
11237
11148
  await updateListItem({
11238
- listId: targetListId,
11149
+ listId: list_id,
11239
11150
  itemId: item_id,
11240
11151
  completed,
11241
11152
  title,
11242
- listColumnMap: state.artifactState.listColumnMap ?? {}
11153
+ listColumnMap: {}
11243
11154
  });
11244
- await state.patchArtifactState({ lastListId: targetListId });
11245
11155
  const response = {
11246
- list_id: targetListId,
11156
+ list_id,
11247
11157
  item_id,
11248
11158
  completed,
11249
11159
  title
@@ -11643,183 +11553,70 @@ function createSlackThreadReadTool(context, deps = {}) {
11643
11553
  });
11644
11554
  }
11645
11555
 
11646
- // src/chat/slack/tools/user-lookup.ts
11647
- import { and, eq } from "drizzle-orm";
11556
+ // src/chat/tools/user-lookup.ts
11557
+ import { and, eq, or, sql } from "drizzle-orm";
11558
+ import { alias } from "drizzle-orm/pg-core";
11648
11559
  import { z as z50 } from "zod";
11649
-
11650
- // src/chat/slack/users.ts
11651
- function normalizeUser(raw) {
11652
- const rawFields = raw.profile?.fields;
11653
- const profileFields = [];
11654
- if (rawFields && typeof rawFields === "object") {
11655
- for (const [id, field] of Object.entries(rawFields)) {
11656
- if (!field) continue;
11657
- profileFields.push({
11658
- id,
11659
- label: field.label || void 0,
11660
- value: field.value || void 0,
11661
- alt: field.alt || void 0
11662
- });
11663
- }
11664
- }
11665
- return {
11666
- id: raw.id ?? "",
11667
- team_id: raw.team_id || void 0,
11668
- name: raw.name || void 0,
11669
- real_name: raw.real_name || raw.profile?.real_name || void 0,
11670
- display_name: raw.profile?.display_name || void 0,
11671
- title: raw.profile?.title || void 0,
11672
- email: raw.profile?.email || void 0,
11673
- status_text: raw.profile?.status_text ?? void 0,
11674
- status_emoji: raw.profile?.status_emoji ?? void 0,
11675
- is_bot: raw.is_bot ?? false,
11676
- is_deleted: raw.deleted ?? false,
11677
- timezone: raw.tz || void 0,
11678
- ...profileFields.length > 0 ? { profile_fields: profileFields } : {}
11679
- };
11680
- }
11681
- async function lookupSlackUserProfile(userId) {
11682
- const client = getSlackClient();
11683
- const result = await withSlackRetries(
11684
- () => client.users.info({ user: userId }),
11685
- 3,
11686
- { action: "users.info" }
11687
- );
11688
- const user = result.user;
11689
- if (!user) {
11690
- throw new Error(`Slack users.info returned no user for ${userId}`);
11691
- }
11692
- return normalizeUser(user);
11693
- }
11694
- async function lookupSlackUserByEmail(email) {
11695
- const client = getSlackClient();
11696
- let result;
11697
- try {
11698
- result = await withSlackRetries(
11699
- () => client.users.lookupByEmail({ email }),
11700
- 3,
11701
- { action: "users.lookupByEmail" }
11702
- );
11703
- } catch (error) {
11704
- const apiError = error.apiError;
11705
- if (apiError === "users_not_found") {
11706
- return null;
11707
- }
11708
- throw error;
11709
- }
11710
- const user = result.user;
11711
- if (!user) {
11712
- return null;
11713
- }
11714
- return normalizeUser(user);
11715
- }
11716
- function scoreMatch(user, queryLower) {
11717
- const name = (user.name ?? "").toLowerCase();
11718
- const realName = (user.real_name ?? user.profile?.real_name ?? "").toLowerCase();
11719
- const displayName = (user.profile?.display_name ?? "").toLowerCase();
11720
- if (name === queryLower || displayName === queryLower) return 100;
11721
- if (realName === queryLower) return 90;
11722
- if (name.startsWith(queryLower) || displayName.startsWith(queryLower))
11723
- return 70;
11724
- if (realName.startsWith(queryLower)) return 60;
11725
- const realNameWords = realName.split(/\s+/);
11726
- if (realNameWords.some((w) => w === queryLower)) return 55;
11727
- if (realNameWords.some((w) => w.startsWith(queryLower))) return 50;
11728
- if (name.includes(queryLower) || displayName.includes(queryLower)) return 30;
11729
- if (realName.includes(queryLower)) return 20;
11730
- return 0;
11731
- }
11732
- async function searchSlackUsers(options) {
11733
- const {
11734
- query,
11735
- limit = 10,
11736
- maxPages = 3,
11737
- includeDeleted = false,
11738
- includeBots = false
11739
- } = options;
11740
- const queryLower = query.toLowerCase().trim();
11741
- const client = getSlackClient();
11742
- const matches = [];
11743
- let cursor;
11744
- let pages = 0;
11745
- let totalScanned = 0;
11746
- let truncated = false;
11747
- while (pages < maxPages) {
11748
- pages++;
11749
- const result = await withSlackRetries(
11750
- () => client.users.list({
11751
- limit: 200,
11752
- ...cursor ? { cursor } : {}
11753
- }),
11754
- 3,
11755
- { action: "users.list" }
11756
- );
11757
- const members = result.members ?? [];
11758
- totalScanned += members.length;
11759
- for (const member of members) {
11760
- if (!includeDeleted && member.deleted) continue;
11761
- if (!includeBots && member.is_bot) continue;
11762
- if (member.id === "USLACKBOT") continue;
11763
- const score = scoreMatch(member, queryLower);
11764
- if (score > 0) {
11765
- matches.push({ user: member, score });
11766
- }
11767
- }
11768
- const nextCursor = result.response_metadata?.next_cursor;
11769
- if (!nextCursor) {
11770
- break;
11771
- }
11772
- cursor = nextCursor;
11773
- }
11774
- if (pages >= maxPages && cursor) {
11775
- truncated = true;
11776
- }
11777
- matches.sort((a, b) => {
11778
- if (b.score !== a.score) return b.score - a.score;
11779
- return (a.user.name ?? "").localeCompare(b.user.name ?? "");
11780
- });
11781
- return {
11782
- users: matches.slice(0, limit).map((m) => normalizeUser(m.user)),
11783
- searched_pages: pages,
11784
- searched_user_count: totalScanned,
11785
- truncated
11786
- };
11787
- }
11788
-
11789
- // src/chat/slack/tools/user-lookup.ts
11560
+ var linkedSlackIdentity = alias(juniorIdentities, "user_lookup_slack_identity");
11790
11561
  function explicitUserLookupError(error) {
11791
- if (error.apiError === "user_not_found") {
11562
+ if (error.apiError === "user_not_found" || error.code === "not_found") {
11792
11563
  return "No Slack user found for the supplied user ID.";
11793
11564
  }
11794
11565
  if (error.code === "missing_scope") {
11795
- return error.needed ? `Slack user lookup is unavailable because this installation is missing the \`${error.needed}\` scope.` : "Slack user lookup is unavailable because this installation is missing a required Slack scope.";
11796
- }
11797
- if (error.code === "not_found") {
11798
- return "No Slack user found for the supplied user ID.";
11566
+ return error.needed ? `User lookup is unavailable because this installation is missing the \`${error.needed}\` scope.` : "User lookup is unavailable because this installation is missing a required Slack scope.";
11799
11567
  }
11800
11568
  if (error.code === "invalid_arguments") {
11801
11569
  return `Slack rejected the user lookup arguments (${error.apiError ?? error.code}).`;
11802
11570
  }
11803
11571
  if (error.code === "feature_unavailable") {
11804
- return "Slack user lookup is not available for this workspace or app installation.";
11572
+ return "User lookup is not available for this workspace or app installation.";
11805
11573
  }
11806
11574
  return void 0;
11807
11575
  }
11808
11576
  function slackMention(userId) {
11809
11577
  return `<@${userId}>`;
11810
11578
  }
11811
- async function storeProfile(teamId, profile) {
11812
- await upsertIdentity(getSqlExecutor(), {
11813
- kind: profile.is_bot ? "service" : "user",
11814
- provider: "slack",
11815
- providerTenantId: teamId,
11816
- providerSubjectId: profile.id,
11817
- ...profile.real_name || profile.display_name ? { displayName: profile.real_name || profile.display_name } : {},
11818
- ...profile.name ? { handle: profile.name } : {},
11819
- ...profile.email ? { email: profile.email, emailVerified: true } : {}
11820
- });
11579
+ function asMatch(user) {
11580
+ return { ...user, mention: slackMention(user.id) };
11581
+ }
11582
+ function lookupResult(args) {
11583
+ const users = args.users.map(asMatch);
11584
+ if (users.length === 1) {
11585
+ return {
11586
+ provider: args.provider,
11587
+ query: args.query,
11588
+ count: 1,
11589
+ mention: users[0].mention,
11590
+ user: users[0],
11591
+ ...args.search
11592
+ };
11593
+ }
11594
+ return {
11595
+ provider: args.provider,
11596
+ query: args.query,
11597
+ count: users.length,
11598
+ users,
11599
+ ...args.search
11600
+ };
11821
11601
  }
11822
- async function storedUserByEmail(teamId, email) {
11602
+ function slackProfileFromIdentity(identity) {
11603
+ return {
11604
+ id: identity.providerSubjectId,
11605
+ name: identity.handle ?? void 0,
11606
+ real_name: identity.displayName ?? void 0,
11607
+ display_name: identity.displayName ?? void 0,
11608
+ email: identity.email ?? void 0,
11609
+ is_bot: false,
11610
+ is_deleted: false
11611
+ };
11612
+ }
11613
+ function slackMentionProfileFromIdentity(identity) {
11614
+ return {
11615
+ id: identity.providerSubjectId,
11616
+ name: identity.handle ?? void 0
11617
+ };
11618
+ }
11619
+ async function storedSlackUserByEmail(teamId, email) {
11823
11620
  const emailNormalized = normalizeIdentityEmail(email);
11824
11621
  if (!emailNormalized) return void 0;
11825
11622
  const identities = await getSqlExecutor().db().select().from(juniorIdentities).where(
@@ -11836,21 +11633,72 @@ async function storedUserByEmail(teamId, email) {
11836
11633
  `Multiple Slack users share verified email ${emailNormalized} in workspace ${teamId}`
11837
11634
  );
11838
11635
  }
11839
- const identity = identities[0];
11840
- if (!identity) return void 0;
11841
- return {
11842
- id: identity.providerSubjectId,
11843
- ...identity.handle ? { name: identity.handle } : {},
11844
- ...identity.displayName ? { real_name: identity.displayName } : {},
11845
- ...identity.displayName ? { display_name: identity.displayName } : {},
11846
- ...identity.email ? { email: identity.email } : {},
11847
- is_bot: false,
11848
- is_deleted: false
11849
- };
11636
+ return identities[0] ? slackProfileFromIdentity(identities[0]) : void 0;
11637
+ }
11638
+ function looksLikeEmail(query) {
11639
+ return /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(query);
11640
+ }
11641
+ async function resolveSlack(teamId, query) {
11642
+ const userId = parseSlackUserId(query);
11643
+ if (userId) {
11644
+ const user = await lookupSlackUserProfile(userId);
11645
+ return lookupResult({ provider: "slack", query, users: [user] });
11646
+ }
11647
+ if (looksLikeEmail(query)) {
11648
+ const stored = await storedSlackUserByEmail(teamId, query);
11649
+ if (stored) {
11650
+ return lookupResult({ provider: "slack", query, users: [stored] });
11651
+ }
11652
+ const profile = await lookupSlackUserByEmail(query);
11653
+ if (!profile) {
11654
+ throw new ToolInputError(
11655
+ `No Slack user found with email address ${query}.`
11656
+ );
11657
+ }
11658
+ return lookupResult({ provider: "slack", query, users: [profile] });
11659
+ }
11660
+ const result = await searchSlackUsers({
11661
+ query,
11662
+ limit: 10,
11663
+ maxPages: 3,
11664
+ includeBots: false
11665
+ });
11666
+ return lookupResult({
11667
+ provider: "slack",
11668
+ query,
11669
+ users: result.users,
11670
+ search: {
11671
+ searched_pages: result.searched_pages,
11672
+ searched_user_count: result.searched_user_count,
11673
+ truncated: result.truncated
11674
+ }
11675
+ });
11850
11676
  }
11851
- function createSlackUserLookupTool(teamId) {
11677
+ async function resolveStoredProvider(teamId, provider, query) {
11678
+ const rows = await getSqlExecutor().db().select({ slack: linkedSlackIdentity }).from(juniorIdentities).innerJoin(
11679
+ linkedSlackIdentity,
11680
+ and(
11681
+ eq(linkedSlackIdentity.userId, juniorIdentities.userId),
11682
+ eq(linkedSlackIdentity.kind, "user"),
11683
+ eq(linkedSlackIdentity.provider, "slack"),
11684
+ eq(linkedSlackIdentity.providerTenantId, teamId)
11685
+ )
11686
+ ).where(
11687
+ and(
11688
+ eq(juniorIdentities.kind, "user"),
11689
+ eq(juniorIdentities.provider, provider),
11690
+ or(
11691
+ eq(juniorIdentities.providerSubjectId, query),
11692
+ sql`lower(${juniorIdentities.handle}) = lower(${query})`
11693
+ )
11694
+ )
11695
+ ).limit(11);
11696
+ const users = rows.slice(0, 10).map((row) => slackMentionProfileFromIdentity(row.slack));
11697
+ return lookupResult({ provider, query, users });
11698
+ }
11699
+ function createUserLookupTool(teamId, providers) {
11852
11700
  return zodTool({
11853
- description: "Look up Slack user profiles by user ID, email, or name search. Returns Slack `mention` values (`<@U\u2026>`). Use a mention only when one person clearly matches; otherwise ask which person the user means.",
11701
+ description: "Look up people by identity provider and query. Pass an enabled `provider` and its provider subject ID or handle. The `slack` provider also accepts email and name searches. Returns Slack `mention` values (`<@U\u2026>`) for the current workspace. Use a mention only when one person clearly matches; otherwise ask which person the user means.",
11854
11702
  annotations: {
11855
11703
  destructiveHint: false,
11856
11704
  idempotentHint: true,
@@ -11858,72 +11706,13 @@ function createSlackUserLookupTool(teamId) {
11858
11706
  readOnlyHint: true
11859
11707
  },
11860
11708
  inputSchema: z50.object({
11861
- mode: z50.enum(["user_id", "email", "query"]).describe(
11862
- "Lookup method: user_id for Slack IDs, email for email addresses, or query for name searches."
11863
- ),
11864
- value: z50.string().trim().min(2).describe(
11865
- "The Slack user ID, email address, or name to look up, interpreted according to mode."
11866
- )
11709
+ provider: z50.enum(providers).describe("Enabled identity provider to query."),
11710
+ query: z50.string().trim().min(1).describe("Provider subject ID, handle, Slack email, or Slack name.")
11867
11711
  }).strict(),
11868
11712
  outputSchema: juniorToolOutputSchema,
11869
- execute: async ({ mode, value }) => {
11713
+ execute: async ({ provider, query }) => {
11870
11714
  try {
11871
- if (mode === "user_id") {
11872
- const parsedUserId = parseRequiredSlackUserIdParam("value", value);
11873
- if (!parsedUserId.ok) {
11874
- throw new ToolInputError(parsedUserId.error);
11875
- }
11876
- const user = await lookupSlackUserProfile(parsedUserId.value);
11877
- await storeProfile(teamId, user);
11878
- return {
11879
- mode: "user_id",
11880
- mention: slackMention(user.id),
11881
- user
11882
- };
11883
- }
11884
- if (mode === "email") {
11885
- const stored = await storedUserByEmail(teamId, value);
11886
- if (stored) {
11887
- return {
11888
- mode: "email",
11889
- mention: slackMention(stored.id),
11890
- user: stored
11891
- };
11892
- }
11893
- const profile = await lookupSlackUserByEmail(value);
11894
- if (!profile) {
11895
- throw new ToolInputError(
11896
- `No Slack user found with email address ${value}.`
11897
- );
11898
- }
11899
- await storeProfile(teamId, profile);
11900
- return {
11901
- mode: "email",
11902
- mention: slackMention(profile.id),
11903
- user: profile
11904
- };
11905
- }
11906
- const result = await searchSlackUsers({
11907
- query: value,
11908
- limit: 10,
11909
- maxPages: 3,
11910
- includeBots: false
11911
- });
11912
- if (result.users.length === 1) {
11913
- await storeProfile(teamId, result.users[0]);
11914
- }
11915
- return {
11916
- mode: "query",
11917
- query: value,
11918
- count: result.users.length,
11919
- searched_pages: result.searched_pages,
11920
- searched_user_count: result.searched_user_count,
11921
- truncated: result.truncated,
11922
- users: result.users.map((user) => ({
11923
- ...user,
11924
- mention: slackMention(user.id)
11925
- }))
11926
- };
11715
+ return provider === "slack" ? await resolveSlack(teamId, query) : await resolveStoredProvider(teamId, provider, query);
11927
11716
  } catch (error) {
11928
11717
  if (error instanceof SlackActionError) {
11929
11718
  const message = explicitUserLookupError(error);
@@ -12956,28 +12745,9 @@ function createWriteFileTool() {
12956
12745
  }
12957
12746
 
12958
12747
  // src/chat/tools/index.ts
12959
- function createToolState(hooks, context) {
12748
+ function createToolState() {
12960
12749
  const operationResultCache = /* @__PURE__ */ new Map();
12961
- const artifactState = {
12962
- ...context.artifactState ?? {},
12963
- listColumnMap: {
12964
- ...context.artifactState?.listColumnMap ?? {}
12965
- }
12966
- };
12967
- const patchArtifactState = async (patch) => {
12968
- Object.assign(artifactState, patch);
12969
- if (patch.listColumnMap) {
12970
- artifactState.listColumnMap = {
12971
- ...artifactState.listColumnMap ?? {},
12972
- ...patch.listColumnMap
12973
- };
12974
- }
12975
- await hooks.onArtifactStatePatch?.(patch);
12976
- };
12977
12750
  return {
12978
- artifactState,
12979
- patchArtifactState,
12980
- getCurrentListId: () => artifactState.lastListId,
12981
12751
  getOperationResult: (operationKey) => operationResultCache.get(operationKey),
12982
12752
  setOperationResult: (operationKey, result) => {
12983
12753
  operationResultCache.set(operationKey, result);
@@ -12985,7 +12755,7 @@ function createToolState(hooks, context) {
12985
12755
  };
12986
12756
  }
12987
12757
  function createTools(availableSkills, hooks = {}, context, options = {}) {
12988
- const state = createToolState(hooks, context);
12758
+ const state = createToolState();
12989
12759
  const slackContext = getSlackToolContext(context);
12990
12760
  const slackSourceCapabilities = slackContext ? resolveChannelCapabilities(slackContext.sourceChannelId) : void 0;
12991
12761
  const canSendFilesToActiveConversation = Boolean(
@@ -13070,10 +12840,17 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
13070
12840
  context.slackActionToken
13071
12841
  );
13072
12842
  }
13073
- tools.slackUserLookup = createSlackUserLookupTool(slackContext.teamId);
12843
+ const identityProviders = [
12844
+ "slack",
12845
+ ...getOAuthAccountProviders().filter((provider) => provider !== "slack")
12846
+ ];
12847
+ tools.userLookup = createUserLookupTool(
12848
+ slackContext.teamId,
12849
+ identityProviders
12850
+ );
13074
12851
  tools.slackListCreate = createSlackListCreateTool(state);
13075
12852
  tools.slackListAddItems = createSlackListAddItemsTool(state);
13076
- tools.slackListGetItems = createSlackListGetItemsTool(state);
12853
+ tools.slackListGetItems = createSlackListGetItemsTool();
13077
12854
  tools.slackListUpdateItem = createSlackListUpdateItemTool(state);
13078
12855
  const outputChannelId = slackContext.destinationChannelId;
13079
12856
  const outputCapabilities = outputChannelId ? resolveChannelCapabilities(outputChannelId) : void 0;
@@ -14327,7 +14104,6 @@ function createMcpAuthOrchestration(input) {
14327
14104
  ...input.threadTs ? { threadTs: input.threadTs } : {},
14328
14105
  ...input.toolChannelId ? { toolChannelId: input.toolChannelId } : {},
14329
14106
  configuration: input.getConfiguration(),
14330
- artifactState: input.getArtifactState(),
14331
14107
  createAuthorizationState: input.authorization?.createState
14332
14108
  });
14333
14109
  authSessionIdsByProvider.set(plugin.manifest.name, provider.authSessionId);
@@ -14365,11 +14141,9 @@ function createMcpAuthOrchestration(input) {
14365
14141
  });
14366
14142
  const reusedAuthSessionId = reusingPendingLink && input.pendingAuth?.kind === "mcp" ? input.pendingAuth.authSessionId : void 0;
14367
14143
  const activeAuthSessionId = reusedAuthSessionId ?? authSessionId;
14368
- const latestArtifactState = input.getMergedArtifactState();
14369
14144
  await patchMcpAuthSession(activeAuthSessionId, {
14370
14145
  configuration: { ...input.getConfiguration() },
14371
- artifactState: latestArtifactState,
14372
- toolChannelId: input.toolChannelId ?? latestArtifactState.assistantContextChannelId ?? input.channelId
14146
+ toolChannelId: input.toolChannelId ?? input.channelId
14373
14147
  });
14374
14148
  const providerLabel = formatProviderLabel(provider);
14375
14149
  const nextPendingAuth = {
@@ -15346,6 +15120,7 @@ function createGuardianActionReviewer(options) {
15346
15120
  maxTokens: GUARDIAN_REVIEW_MAX_TOKENS,
15347
15121
  recordTelemetryPayloads: false,
15348
15122
  temperature: 0,
15123
+ promptName: "junior.guardian_action_review",
15349
15124
  signal,
15350
15125
  metadata: {
15351
15126
  conversationId: proposal.context.conversationId,
@@ -15578,7 +15353,7 @@ async function wireAgentTools(args) {
15578
15353
  egressSignals: args.policy.sandboxEgressSignals,
15579
15354
  credentialEgress: args.routing.credentialContext,
15580
15355
  actor: args.currentActor,
15581
- channelConfiguration: args.policy.channelConfiguration,
15356
+ locationConfiguration: args.policy.locationConfiguration,
15582
15357
  configurationValues: args.configurationValues,
15583
15358
  getActiveSkill: () => args.skillSandbox.getActiveSkill(),
15584
15359
  prepareSandbox: pluginHooks.prepareSandbox,
@@ -15600,11 +15375,6 @@ async function wireAgentTools(args) {
15600
15375
  userMessage: args.userInput,
15601
15376
  pendingAuth: args.state.pendingAuth,
15602
15377
  getConfiguration: () => args.configurationValues,
15603
- getArtifactState: () => args.state.artifactState,
15604
- getMergedArtifactState: () => mergeArtifactsState(
15605
- args.state.artifactState ?? {},
15606
- args.artifactStatePatch
15607
- ),
15608
15378
  recordPendingAuth: args.durability.recordPendingAuth,
15609
15379
  interactiveAuthEnabled: !isAgentRunFeatureDisabled(
15610
15380
  args.policy,
@@ -15617,6 +15387,7 @@ async function wireAgentTools(args) {
15617
15387
  conversationId: args.conversationId,
15618
15388
  sessionId: args.turnId,
15619
15389
  actorId: credentialUserId,
15390
+ actor: args.currentActor,
15620
15391
  channelId: slackChannelId,
15621
15392
  destination: args.routing.destination,
15622
15393
  source: runSource,
@@ -15654,7 +15425,6 @@ async function wireAgentTools(args) {
15654
15425
  const commonToolRuntimeContext = {
15655
15426
  conversationId: args.conversationId,
15656
15427
  userText: args.userInput,
15657
- artifactState: args.state.artifactState,
15658
15428
  configuration: args.configurationValues,
15659
15429
  egress: createPluginEgress({
15660
15430
  credentialContext: args.routing.credentialContext,
@@ -15742,15 +15512,6 @@ async function wireAgentTools(args) {
15742
15512
  args.generatedFiles.push(...files);
15743
15513
  return refs;
15744
15514
  },
15745
- onArtifactStatePatch: async (patch) => {
15746
- Object.assign(args.artifactStatePatch, patch);
15747
- await args.durability.onArtifactStateUpdated?.(
15748
- mergeArtifactsState(
15749
- args.state.artifactState ?? {},
15750
- args.artifactStatePatch
15751
- )
15752
- );
15753
- },
15754
15515
  toolOverrides: args.policy.toolOverrides,
15755
15516
  onSkillLoaded: async (loadedSkill) => {
15756
15517
  const resolvedSkill = await args.skillSandbox.loadSkill(
@@ -16329,6 +16090,7 @@ async function summarizeContext(args, deps) {
16329
16090
  messageAttributeMode: "metadata",
16330
16091
  temperature: 0,
16331
16092
  signal: args.signal,
16093
+ promptName: "junior.context_compaction",
16332
16094
  messages: [
16333
16095
  {
16334
16096
  role: "user",
@@ -16851,7 +16613,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
16851
16613
  });
16852
16614
  }
16853
16615
  };
16854
- const persistedConfigurationValues = policy.channelConfiguration ? await policy.channelConfiguration.resolveValues() : {};
16616
+ const persistedConfigurationValues = policy.locationConfiguration ? await policy.locationConfiguration.resolveValues() : {};
16855
16617
  const configurationValues = {
16856
16618
  ...getConfigDefaults(),
16857
16619
  ...policy.configuration ?? {},
@@ -16946,6 +16708,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
16946
16708
  turnId,
16947
16709
  modelProfile: routedModelProfile,
16948
16710
  modelId: routedModelId,
16711
+ ...turnRoute.costUsd !== void 0 ? { costUsd: turnRoute.costUsd } : {},
16949
16712
  reasoningLevel: turnRoute.reasoningLevel,
16950
16713
  ...turnRoute.confidence !== void 0 ? { confidence: turnRoute.confidence } : {},
16951
16714
  source: turnRoute.source ?? "configured"
@@ -16954,7 +16717,6 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
16954
16717
  activeModelProfile = routedModelProfile;
16955
16718
  activeModelId = routedModelId;
16956
16719
  const generatedFiles = [];
16957
- const artifactStatePatch = {};
16958
16720
  const toolCalls = [];
16959
16721
  let agent;
16960
16722
  let pendingPiHookError;
@@ -17060,7 +16822,6 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
17060
16822
  currentAgentMessages,
17061
16823
  currentTurnMessages,
17062
16824
  currentUserIntent,
17063
- artifactStatePatch,
17064
16825
  availableSkills,
17065
16826
  configurationValues,
17066
16827
  connectedMcpProviders,
@@ -17149,7 +16910,6 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
17149
16910
  } = await assemblePrompt({
17150
16911
  activeMcpCatalogs: wiring.activeMcpCatalogs,
17151
16912
  currentActor: actor,
17152
- artifactState: state.artifactState,
17153
16913
  availableSkills,
17154
16914
  configurationValues,
17155
16915
  contextContentParts: [
@@ -17359,13 +17119,13 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
17359
17119
  return void 0;
17360
17120
  },
17361
17121
  afterToolCall: async ({ result: result2, toolCall }, signal2) => {
17362
- const deadlineResult = runResume.timedOut && signal2?.aborted ? annotateTurnDeadlineToolResult(result2) : void 0;
17363
- const sourceResult = deadlineResult ?? result2;
17122
+ const timedOutResult = runResume.timedOut && signal2?.aborted ? projectTimedOutToolResult(result2) : void 0;
17123
+ const sourceResult = timedOutResult ?? result2;
17364
17124
  const projectedResult = wiring.projectActionReviewResult(
17365
17125
  toolCall.id,
17366
17126
  sourceResult
17367
17127
  );
17368
- return deadlineResult || projectedResult !== result2 ? projectedResult : void 0;
17128
+ return timedOutResult || projectedResult !== result2 ? projectedResult : void 0;
17369
17129
  },
17370
17130
  prepareNextTurnWithContext: async (nextTurn, hookSignal) => {
17371
17131
  try {
@@ -17735,7 +17495,6 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy, run
17735
17495
  const result = buildTurnResult({
17736
17496
  newMessages,
17737
17497
  userInput,
17738
- artifactStatePatch,
17739
17498
  toolCalls,
17740
17499
  sandboxRef: wiring.getSandboxRef(),
17741
17500
  piMessages: [...agent.state.messages],