@sentry/junior 0.107.1 → 0.109.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 (68) hide show
  1. package/dist/{agent-hooks-ICPIJAFY.js → agent-hooks-FHHVLNPA.js} +12 -12
  2. package/dist/api/conversations/events.d.ts +1 -1
  3. package/dist/api/conversations/list.d.ts +1 -0
  4. package/dist/api/conversations/schema.d.ts +57 -6
  5. package/dist/api/schema.js +1 -1
  6. package/dist/api.js +116 -27
  7. package/dist/app.d.ts +1 -0
  8. package/dist/app.js +1741 -458
  9. package/dist/{catalog-runtime-FOFNPR3P.js → catalog-runtime-DMGJSLV2.js} +6 -4
  10. package/dist/chat/conversations/history.d.ts +16 -5
  11. package/dist/chat/conversations/message-projection.d.ts +3 -5
  12. package/dist/chat/conversations/sql/store.d.ts +0 -7
  13. package/dist/chat/log-context.d.ts +40 -0
  14. package/dist/chat/logging.d.ts +3 -26
  15. package/dist/chat/resource-events/store.d.ts +6 -0
  16. package/dist/chat/runtime/slack-resume.d.ts +2 -2
  17. package/dist/chat/runtime/slack-runtime.d.ts +3 -0
  18. package/dist/chat/services/turn-session-record.d.ts +0 -2
  19. package/dist/chat/slack/reply.d.ts +7 -19
  20. package/dist/chat/state/conversation.d.ts +1 -0
  21. package/dist/chat/task-execution/slack-work.d.ts +237 -10
  22. package/dist/chat/tool-support/turn-deadline-result.d.ts +3 -0
  23. package/dist/chunk-3SXUV423.js +10 -0
  24. package/dist/{chunk-YFQ7CQDE.js → chunk-72OMGPDS.js} +1017 -39
  25. package/dist/{chunk-2XXEKR44.js → chunk-7Q6WCISF.js} +1 -1
  26. package/dist/{chunk-NVOTGWYX.js → chunk-FENLIFJD.js} +97 -601
  27. package/dist/{chunk-IGHMVDWI.js → chunk-FWJRXN4F.js} +3 -3
  28. package/dist/{chunk-PUAMO4PI.js → chunk-HHVY4SMP.js} +41 -7
  29. package/dist/{chunk-SPUAJVVH.js → chunk-HO5NT6OE.js} +5 -7
  30. package/dist/{chunk-O24R4DCK.js → chunk-ISMWX44P.js} +93 -55
  31. package/dist/{chunk-7FBGKXPE.js → chunk-IVVGFRQQ.js} +5 -0
  32. package/dist/{chunk-EDLNHZH3.js → chunk-IXKSQGIO.js} +226 -191
  33. package/dist/{chunk-SS67LUOK.js → chunk-JNAVF45E.js} +6 -7
  34. package/dist/{chunk-DY7TRYB5.js → chunk-MGUMR35T.js} +1 -1
  35. package/dist/{chunk-CQ7KSO2B.js → chunk-MXW4GL53.js} +11 -15
  36. package/dist/{chunk-RT5BUHR5.js → chunk-O3JMSZLI.js} +1 -1
  37. package/dist/chunk-OCD3OZRK.js +125 -0
  38. package/dist/{chunk-B2Z2H66D.js → chunk-OUHNWH46.js} +60 -5
  39. package/dist/{chunk-VIXFG2VC.js → chunk-PLB7MRCQ.js} +1 -2
  40. package/dist/{chunk-RMVOAJRL.js → chunk-QY636HZU.js} +114 -12
  41. package/dist/{chunk-VH6KWKG2.js → chunk-RGX4V75M.js} +3 -3
  42. package/dist/{chunk-B7PUBQQM.js → chunk-SYAQIR5Z.js} +1 -1
  43. package/dist/chunk-TMBRFULF.js +471 -0
  44. package/dist/{chunk-YIPD3L6L.js → chunk-TT6GMXNA.js} +8 -10
  45. package/dist/{chunk-YT72TOEK.js → chunk-WHMOBKT7.js} +2 -2
  46. package/dist/cli/chat.js +23 -23
  47. package/dist/cli/check.js +8 -6
  48. package/dist/cli/plugins.js +16 -16
  49. package/dist/cli/snapshot-warmup.js +10 -9
  50. package/dist/cli/upgrade.js +314 -3505
  51. package/dist/db/db.d.ts +1 -1
  52. package/dist/{db-DIGO4TGW.js → db-V3NU72O2.js} +8 -6
  53. package/dist/instrumentation.js +3 -2
  54. package/dist/nitro.js +5 -4
  55. package/dist/{runner-ACR2HAIC.js → runner-JYBCQBLK.js} +17 -20
  56. package/dist/{skills-ITNHBARB.js → skills-U6MDAST7.js} +7 -5
  57. package/dist/{validation-AGQ46ZGV.js → validation-72N3JVRU.js} +7 -5
  58. package/dist/version.d.ts +2 -0
  59. package/dist/version.js +7 -0
  60. package/migrations/0006_drop_legacy_conversation_messages.sql +1 -0
  61. package/migrations/README.md +12 -9
  62. package/migrations/meta/0006_snapshot.json +948 -0
  63. package/migrations/meta/_journal.json +7 -0
  64. package/package.json +11 -7
  65. package/dist/chunk-4YF7Z6IA.js +0 -1061
  66. package/dist/chunk-AUUOHQAT.js +0 -115
  67. package/dist/chunk-G3E7SCME.js +0 -28
  68. package/dist/chunk-YNP2ATQX.js +0 -1282
@@ -4,7 +4,7 @@ import {
4
4
  toCanonicalInputMessage,
5
5
  toCanonicalOutputMessage,
6
6
  toGenAiMessagesTraceAttributes
7
- } from "./chunk-RT5BUHR5.js";
7
+ } from "./chunk-O3JMSZLI.js";
8
8
  import {
9
9
  extractGenAiUsageAttributes,
10
10
  logException,
@@ -12,7 +12,7 @@ import {
12
12
  normalizeGenAiFinishReason,
13
13
  serializeGenAiAttribute,
14
14
  withSpan
15
- } from "./chunk-O24R4DCK.js";
15
+ } from "./chunk-ISMWX44P.js";
16
16
 
17
17
  // src/chat/xml.ts
18
18
  function escapeXml(value) {
@@ -403,14 +403,14 @@ async function completeText(params) {
403
403
  }
404
404
  function logContextFromMetadata(modelId, metadata) {
405
405
  const conversationId = typeof metadata?.conversationId === "string" ? metadata.conversationId : typeof metadata?.threadId === "string" ? metadata.threadId : void 0;
406
- const slackThreadId = typeof metadata?.threadId === "string" ? metadata.threadId : void 0;
407
- const slackChannelId = typeof metadata?.channelId === "string" ? metadata.channelId : void 0;
406
+ const messageConversationId = typeof metadata?.threadId === "string" ? metadata.threadId : void 0;
407
+ const destinationName = typeof metadata?.channelId === "string" ? metadata.channelId : void 0;
408
408
  const runId = typeof metadata?.runId === "string" ? metadata.runId : void 0;
409
409
  return {
410
410
  modelId,
411
411
  ...conversationId ? { conversationId } : {},
412
- ...slackThreadId ? { slackThreadId } : {},
413
- ...slackChannelId ? { slackChannelId } : {},
412
+ ...messageConversationId ? { messageConversationId } : {},
413
+ ...destinationName ? { destinationName } : {},
414
414
  ...runId ? { runId } : {}
415
415
  };
416
416
  }
@@ -869,7 +869,6 @@ function setSlackReactionConfig(overrides) {
869
869
  export {
870
870
  toOptionalTrimmed,
871
871
  escapeXml,
872
- unescapeXml,
873
872
  renderCurrentInstruction,
874
873
  unwrapCurrentInstruction,
875
874
  TURN_CONTEXT_TAG,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-YIPD3L6L.js";
3
+ } from "./chunk-3SXUV423.js";
4
4
 
5
5
  // src/chat/plugins/validation.ts
6
6
  import { isDeepStrictEqual } from "util";
@@ -5,6 +5,8 @@ import {
5
5
  } from "./chunk-KNFROR7R.js";
6
6
  import {
7
7
  clearPendingAuth,
8
+ coerceThreadConversationState,
9
+ getAgentTurnSessionRecord,
8
10
  getInterruptionMarker,
9
11
  getPersistedThreadState,
10
12
  hydrateConversationMessages,
@@ -12,26 +14,20 @@ import {
12
14
  markTurnCompleted,
13
15
  mergeArtifactsState,
14
16
  updateConversationStats
15
- } from "./chunk-YFQ7CQDE.js";
16
- import {
17
- coerceThreadConversationState,
18
- getAgentTurnSessionRecord
19
- } from "./chunk-4YF7Z6IA.js";
17
+ } from "./chunk-72OMGPDS.js";
20
18
  import {
21
19
  createPluginEmbedder,
20
+ createPluginLogger,
22
21
  createPluginModel,
22
+ createPluginState,
23
23
  getPlugins
24
- } from "./chunk-RMVOAJRL.js";
25
- import {
26
- createPluginLogger,
27
- createPluginState
28
- } from "./chunk-AUUOHQAT.js";
24
+ } from "./chunk-QY636HZU.js";
29
25
  import {
30
26
  getStateAdapter
31
- } from "./chunk-B2Z2H66D.js";
27
+ } from "./chunk-OUHNWH46.js";
32
28
  import {
33
29
  getDb
34
- } from "./chunk-NVOTGWYX.js";
30
+ } from "./chunk-FENLIFJD.js";
35
31
  import {
36
32
  getPiMessageRole,
37
33
  instructionTextForProjection,
@@ -39,13 +35,13 @@ import {
39
35
  isToolResultMessage,
40
36
  normalizeToolNameFromResult,
41
37
  stripRuntimeTurnContext
42
- } from "./chunk-SS67LUOK.js";
38
+ } from "./chunk-JNAVF45E.js";
43
39
  import {
44
40
  buildTurnFailureResponse
45
- } from "./chunk-O24R4DCK.js";
41
+ } from "./chunk-ISMWX44P.js";
46
42
  import {
47
43
  parseSlackMessageTs
48
- } from "./chunk-7FBGKXPE.js";
44
+ } from "./chunk-IVVGFRQQ.js";
49
45
 
50
46
  // src/chat/services/turn-failure-response.ts
51
47
  function requireTurnFailureEventId(eventId, eventName) {
@@ -5,7 +5,7 @@ import {
5
5
  parseSlackChannelId,
6
6
  parseSlackMessageTs,
7
7
  parseSlackTeamId
8
- } from "./chunk-7FBGKXPE.js";
8
+ } from "./chunk-IVVGFRQQ.js";
9
9
 
10
10
  // src/chat/conversation-privacy.ts
11
11
  import { AsyncLocalStorage } from "async_hooks";
@@ -0,0 +1,125 @@
1
+ // package.json
2
+ var package_default = {
3
+ name: "@sentry/junior",
4
+ version: "0.109.0",
5
+ private: false,
6
+ publishConfig: {
7
+ access: "public"
8
+ },
9
+ type: "module",
10
+ types: "./dist/app.d.ts",
11
+ repository: {
12
+ type: "git",
13
+ url: "git+https://github.com/getsentry/junior.git",
14
+ directory: "packages/junior"
15
+ },
16
+ bin: {
17
+ junior: "bin/junior.mjs"
18
+ },
19
+ exports: {
20
+ ".": {
21
+ types: "./dist/app.d.ts",
22
+ default: "./dist/app.js"
23
+ },
24
+ "./instrumentation": {
25
+ types: "./dist/instrumentation.d.ts",
26
+ default: "./dist/instrumentation.js"
27
+ },
28
+ "./nitro": {
29
+ types: "./dist/nitro.d.ts",
30
+ default: "./dist/nitro.js"
31
+ },
32
+ "./api": {
33
+ types: "./dist/api.d.ts",
34
+ default: "./dist/api.js"
35
+ },
36
+ "./api/schema": {
37
+ types: "./dist/api/schema.d.ts",
38
+ default: "./dist/api/schema.js"
39
+ },
40
+ "./vercel": {
41
+ types: "./dist/vercel.d.ts",
42
+ default: "./dist/vercel.js"
43
+ },
44
+ "./version": {
45
+ types: "./dist/version.d.ts",
46
+ default: "./dist/version.js"
47
+ }
48
+ },
49
+ files: [
50
+ "dist",
51
+ "bin",
52
+ "migrations"
53
+ ],
54
+ scripts: {
55
+ prepare: "pnpm run build",
56
+ prepack: "pnpm run build",
57
+ build: "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
58
+ "db:generate": "pnpm exec drizzle-kit generate --config drizzle.config.ts",
59
+ lint: "oxlint --config .oxlintrc.json --deny-warnings src tests scripts bin tsup.config.ts && depcruise --config .dependency-cruiser.mjs src/chat",
60
+ "lint:fix": "oxlint --config .oxlintrc.json --deny-warnings --fix src tests scripts bin tsup.config.ts",
61
+ test: "vitest run --maxWorkers=4",
62
+ "test:watch": "vitest",
63
+ typecheck: "tsc --noEmit",
64
+ "skills:check": "node scripts/check-skills.mjs",
65
+ "test:coverage": "vitest run --maxWorkers=4 --coverage --reporter=default --reporter=junit --outputFile.junit=coverage/results.junit.xml"
66
+ },
67
+ dependencies: {
68
+ "@ai-sdk/gateway": "^3.0.119",
69
+ "@chat-adapter/slack": "4.29.0",
70
+ "@chat-adapter/state-memory": "4.29.0",
71
+ "@chat-adapter/state-redis": "4.29.0",
72
+ "@earendil-works/pi-agent-core": "0.80.6",
73
+ "@earendil-works/pi-ai": "0.80.6",
74
+ "@logtape/logtape": "^2.1.1",
75
+ "@modelcontextprotocol/sdk": "1.29.0",
76
+ "@neondatabase/serverless": "^1.1.0",
77
+ "@sentry/junior-plugin-api": "workspace:*",
78
+ "@sentry/node": "catalog:",
79
+ "@sinclair/typebox": "^0.34.49",
80
+ "@slack/web-api": "^7.16.0",
81
+ "@vercel/functions": "^3.6.0",
82
+ "@vercel/queue": "^0.2.0",
83
+ "@vercel/sandbox": "2.8.0",
84
+ ai: "^6.0.190",
85
+ "bash-tool": "^1.3.16",
86
+ chat: "4.29.0",
87
+ commander: "^14.0.3",
88
+ "drizzle-orm": "catalog:",
89
+ hono: "^4.12.22",
90
+ jiti: "^2.7.0",
91
+ jose: "^6.2.3",
92
+ "just-bash": "3.0.1",
93
+ "node-html-markdown": "^2.0.0",
94
+ pg: "^8.16.3",
95
+ yaml: "^2.9.0",
96
+ zod: "catalog:"
97
+ },
98
+ devDependencies: {
99
+ "@emnapi/core": "^1.10.0",
100
+ "@emnapi/runtime": "^1.10.0",
101
+ "@sentry/junior-github": "workspace:*",
102
+ "@sentry/junior-memory": "workspace:*",
103
+ "@sentry/junior-scheduler": "workspace:*",
104
+ "@sentry/junior-testing": "workspace:*",
105
+ "@types/node": "^25.9.1",
106
+ "@types/pg": "^8.15.6",
107
+ "@vitest/coverage-v8": "4.1.7",
108
+ "dependency-cruiser": "^17.4.0",
109
+ "drizzle-kit": "catalog:",
110
+ msw: "^2.14.6",
111
+ nitro: "3.0.260522-beta",
112
+ oxlint: "^1.66.0",
113
+ tsup: "^8.5.1",
114
+ typescript: "^6.0.3",
115
+ vercel: "^54.4.0",
116
+ vitest: "^4.1.7"
117
+ }
118
+ };
119
+
120
+ // src/version.ts
121
+ var JUNIOR_VERSION = typeof package_default.version === "string" && package_default.version.trim() ? package_default.version : "unknown";
122
+
123
+ export {
124
+ JUNIOR_VERSION
125
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getChatConfig
3
- } from "./chunk-SS67LUOK.js";
3
+ } from "./chunk-JNAVF45E.js";
4
4
 
5
5
  // src/chat/state/adapter.ts
6
6
  import { createMemoryState } from "@chat-adapter/state-memory";
@@ -16,6 +16,32 @@ async function acquireActiveLock(state, threadId) {
16
16
  var ACTIVE_LOCK_HEARTBEAT_MS = 3e4;
17
17
  var stateAdapter;
18
18
  var redisStateAdapter;
19
+ function createConnectingStateAdapter(base) {
20
+ const connected = async (operation) => {
21
+ await base.connect();
22
+ return await operation();
23
+ };
24
+ return {
25
+ appendToList: (key, value, options) => connected(() => base.appendToList(key, value, options)),
26
+ connect: () => base.connect(),
27
+ disconnect: () => base.disconnect(),
28
+ subscribe: (threadId) => connected(() => base.subscribe(threadId)),
29
+ unsubscribe: (threadId) => connected(() => base.unsubscribe(threadId)),
30
+ isSubscribed: (threadId) => connected(() => base.isSubscribed(threadId)),
31
+ acquireLock: (threadId, ttlMs) => connected(() => base.acquireLock(threadId, ttlMs)),
32
+ releaseLock: (lock) => connected(() => base.releaseLock(lock)),
33
+ extendLock: (lock, ttlMs) => connected(() => base.extendLock(lock, ttlMs)),
34
+ forceReleaseLock: (threadId) => connected(() => base.forceReleaseLock(threadId)),
35
+ enqueue: (threadId, entry, maxSize) => connected(() => base.enqueue(threadId, entry, maxSize)),
36
+ dequeue: (threadId) => connected(() => base.dequeue(threadId)),
37
+ queueDepth: (threadId) => connected(() => base.queueDepth(threadId)),
38
+ get: (key) => connected(() => base.get(key)),
39
+ getList: (key) => connected(() => base.getList(key)),
40
+ set: (key, value, ttlMs) => connected(() => base.set(key, value, ttlMs)),
41
+ setIfNotExists: (key, value, ttlMs) => connected(() => base.setIfNotExists(key, value, ttlMs)),
42
+ delete: (key) => connected(() => base.delete(key))
43
+ };
44
+ }
19
45
  function createPrefixedStateAdapter(base, prefix) {
20
46
  const prefixed = (value) => `${prefix}:${value}`;
21
47
  const unprefixed = (value) => value.startsWith(`${prefix}:`) ? value.slice(prefix.length + 1) : value;
@@ -188,7 +214,9 @@ function createStateAdapter() {
188
214
  if (config.state.adapter === "memory") {
189
215
  redisStateAdapter = void 0;
190
216
  return createQueuedStateAdapter(
191
- withOptionalPrefix(createMemoryState(), config.state.keyPrefix),
217
+ createConnectingStateAdapter(
218
+ withOptionalPrefix(createMemoryState(), config.state.keyPrefix)
219
+ ),
192
220
  { activeLockMaxAgeMs }
193
221
  );
194
222
  }
@@ -200,7 +228,9 @@ function createStateAdapter() {
200
228
  });
201
229
  redisStateAdapter = redisState;
202
230
  return createQueuedStateAdapter(
203
- withOptionalPrefix(redisState, config.state.keyPrefix),
231
+ createConnectingStateAdapter(
232
+ withOptionalPrefix(redisState, config.state.keyPrefix)
233
+ ),
204
234
  { activeLockMaxAgeMs }
205
235
  );
206
236
  }
@@ -241,10 +271,35 @@ async function disconnectStateAdapter() {
241
271
  }
242
272
  }
243
273
 
274
+ // src/chat/sandbox/paths.ts
275
+ function normalizeWorkspaceRoot(input) {
276
+ const candidate = (input ?? "").trim();
277
+ if (!candidate) {
278
+ return "/vercel/sandbox";
279
+ }
280
+ const normalized = candidate.replace(/\/+$/, "");
281
+ return normalized.startsWith("/") ? normalized : `/${normalized}`;
282
+ }
283
+ var SANDBOX_WORKSPACE_ROOT = normalizeWorkspaceRoot(
284
+ process.env.VERCEL_SANDBOX_WORKSPACE_DIR
285
+ );
286
+ var SANDBOX_SKILLS_ROOT = `${SANDBOX_WORKSPACE_ROOT}/skills`;
287
+ var SANDBOX_DATA_ROOT = `${SANDBOX_WORKSPACE_ROOT}/data`;
288
+ function sandboxSkillDir(skillName) {
289
+ return `${SANDBOX_SKILLS_ROOT}/${skillName}`;
290
+ }
291
+ function sandboxSkillFile(skillName) {
292
+ return `${sandboxSkillDir(skillName)}/SKILL.md`;
293
+ }
294
+
244
295
  export {
245
296
  acquireActiveLock,
246
- getConnectedStateContext,
247
297
  getDefaultRedisStateAdapterFor,
248
298
  getStateAdapter,
249
- disconnectStateAdapter
299
+ disconnectStateAdapter,
300
+ SANDBOX_WORKSPACE_ROOT,
301
+ SANDBOX_SKILLS_ROOT,
302
+ SANDBOX_DATA_ROOT,
303
+ sandboxSkillDir,
304
+ sandboxSkillFile
250
305
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseSlackTeamId
3
- } from "./chunk-7FBGKXPE.js";
3
+ } from "./chunk-IVVGFRQQ.js";
4
4
 
5
5
  // src/chat/actor.ts
6
6
  import { z } from "zod";
@@ -170,7 +170,6 @@ function createSlackResumeActor(args) {
170
170
  }
171
171
 
172
172
  export {
173
- storedSlackActorSchema,
174
173
  isUserActor,
175
174
  parseActorUserId,
176
175
  isActorUserId,
@@ -1,38 +1,36 @@
1
1
  import {
2
- createPluginLogger,
3
- createPluginState
4
- } from "./chunk-AUUOHQAT.js";
5
- import {
6
- SANDBOX_WORKSPACE_ROOT
7
- } from "./chunk-G3E7SCME.js";
2
+ SANDBOX_WORKSPACE_ROOT,
3
+ getStateAdapter
4
+ } from "./chunk-OUHNWH46.js";
8
5
  import {
9
6
  isConversationChannel,
10
7
  isConversationScopedChannel,
11
8
  isDmChannel,
12
9
  normalizeSlackConversationId
13
- } from "./chunk-VH6KWKG2.js";
10
+ } from "./chunk-RGX4V75M.js";
14
11
  import {
15
12
  getDb
16
- } from "./chunk-NVOTGWYX.js";
13
+ } from "./chunk-FENLIFJD.js";
17
14
  import {
18
15
  botConfig,
19
16
  completeObject,
20
17
  embedTexts,
21
18
  standardModelId
22
- } from "./chunk-SS67LUOK.js";
19
+ } from "./chunk-JNAVF45E.js";
23
20
  import {
24
21
  isActorUserId,
25
22
  parseActorUserId
26
- } from "./chunk-VIXFG2VC.js";
23
+ } from "./chunk-PLB7MRCQ.js";
27
24
  import {
25
+ logException,
28
26
  logInfo,
29
27
  logWarn
30
- } from "./chunk-O24R4DCK.js";
28
+ } from "./chunk-ISMWX44P.js";
31
29
  import {
32
30
  parseSlackChannelReferenceId,
33
31
  parseSlackMessageTs,
34
32
  parseSlackTeamId
35
- } from "./chunk-7FBGKXPE.js";
33
+ } from "./chunk-IVVGFRQQ.js";
36
34
 
37
35
  // src/chat/plugins/agent-hooks.ts
38
36
  import {
@@ -40,6 +38,37 @@ import {
40
38
  resourceEventSchema
41
39
  } from "@sentry/junior-plugin-api";
42
40
 
41
+ // src/chat/plugins/logging.ts
42
+ function createPluginLogger(plugin) {
43
+ return {
44
+ info(message, metadata) {
45
+ logInfo(
46
+ "agent_plugin_log_info",
47
+ {},
48
+ { "app.plugin.name": plugin, ...metadata },
49
+ message
50
+ );
51
+ },
52
+ warn(message, metadata) {
53
+ logWarn(
54
+ "agent_plugin_log_warn",
55
+ {},
56
+ { "app.plugin.name": plugin, ...metadata },
57
+ message
58
+ );
59
+ },
60
+ error(message, metadata) {
61
+ logException(
62
+ new Error(message),
63
+ "agent_plugin_log_error",
64
+ {},
65
+ { "app.plugin.name": plugin, ...metadata },
66
+ message
67
+ );
68
+ }
69
+ };
70
+ }
71
+
43
72
  // src/chat/plugins/model.ts
44
73
  function createPluginModel(pluginName, options = {}, runtime = {}) {
45
74
  return {
@@ -77,6 +106,77 @@ function createPluginEmbedder(pluginName, runtime = {}) {
77
106
  };
78
107
  }
79
108
 
109
+ // src/chat/plugins/state.ts
110
+ import { createHash } from "crypto";
111
+ var MAX_PLUGIN_STATE_KEY_LENGTH = 512;
112
+ function hashKeyPart(value) {
113
+ return createHash("sha256").update(value).digest("hex").slice(0, 32);
114
+ }
115
+ function pluginStateKey(plugin, key) {
116
+ const pluginPrefix = `junior:${plugin}`;
117
+ if (key === pluginPrefix || key.startsWith(`${pluginPrefix}:`)) {
118
+ return key;
119
+ }
120
+ return `junior:plugin_state:${hashKeyPart(plugin)}:${hashKeyPart(key)}`;
121
+ }
122
+ function validatePluginStateKey(key) {
123
+ if (!key.trim()) {
124
+ throw new Error("Plugin state key is required");
125
+ }
126
+ if (key.length > MAX_PLUGIN_STATE_KEY_LENGTH) {
127
+ throw new Error("Plugin state key exceeds the maximum length");
128
+ }
129
+ }
130
+ function createPluginState(plugin, adapter) {
131
+ const getAdapter = () => adapter ?? getStateAdapter();
132
+ return {
133
+ async delete(key) {
134
+ validatePluginStateKey(key);
135
+ const state = getAdapter();
136
+ await state.connect();
137
+ await state.delete(pluginStateKey(plugin, key));
138
+ },
139
+ async get(key) {
140
+ validatePluginStateKey(key);
141
+ const state = getAdapter();
142
+ await state.connect();
143
+ const value = await state.get(pluginStateKey(plugin, key));
144
+ return value ?? void 0;
145
+ },
146
+ async set(key, value, ttlMs) {
147
+ validatePluginStateKey(key);
148
+ const state = getAdapter();
149
+ await state.connect();
150
+ await state.set(pluginStateKey(plugin, key), value, ttlMs);
151
+ },
152
+ async setIfNotExists(key, value, ttlMs) {
153
+ validatePluginStateKey(key);
154
+ const state = getAdapter();
155
+ await state.connect();
156
+ return await state.setIfNotExists(
157
+ pluginStateKey(plugin, key),
158
+ value,
159
+ ttlMs
160
+ );
161
+ },
162
+ async withLock(key, ttlMs, callback) {
163
+ validatePluginStateKey(key);
164
+ const state = getAdapter();
165
+ await state.connect();
166
+ const lockKey = pluginStateKey(plugin, key);
167
+ const lock = await state.acquireLock(lockKey, ttlMs);
168
+ if (!lock) {
169
+ throw new Error(`Could not acquire plugin state lock for ${key}`);
170
+ }
171
+ try {
172
+ return await callback();
173
+ } finally {
174
+ await state.releaseLock(lock);
175
+ }
176
+ }
177
+ };
178
+ }
179
+
80
180
  // src/chat/slack/dashboard-link.ts
81
181
  var dashboardConversationLinkOptions;
82
182
  function withHttps(host) {
@@ -1105,8 +1205,10 @@ function createPluginHookRunner(input = {}) {
1105
1205
  }
1106
1206
 
1107
1207
  export {
1208
+ createPluginLogger,
1108
1209
  createPluginModel,
1109
1210
  createPluginEmbedder,
1211
+ createPluginState,
1110
1212
  setDashboardConversationLinkOptions,
1111
1213
  getDashboardConversationLink,
1112
1214
  getSlackToolContext,
@@ -3,16 +3,16 @@ import {
3
3
  } from "./chunk-4ZNGQH7C.js";
4
4
  import {
5
5
  getSlackBotToken
6
- } from "./chunk-SS67LUOK.js";
6
+ } from "./chunk-JNAVF45E.js";
7
7
  import {
8
8
  logWarn,
9
9
  setSpanAttributes,
10
10
  setSpanStatus,
11
11
  withSpan
12
- } from "./chunk-O24R4DCK.js";
12
+ } from "./chunk-ISMWX44P.js";
13
13
  import {
14
14
  parseSlackChannelReferenceId
15
- } from "./chunk-7FBGKXPE.js";
15
+ } from "./chunk-IVVGFRQQ.js";
16
16
 
17
17
  // src/chat/slack/client.ts
18
18
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  parseSlackChannelReferenceId,
3
3
  parseSlackTeamId
4
- } from "./chunk-7FBGKXPE.js";
4
+ } from "./chunk-IVVGFRQQ.js";
5
5
 
6
6
  // src/chat/destination.ts
7
7
  import {