@sentry/junior 0.71.2 → 0.72.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 (57) hide show
  1. package/bin/junior.mjs +10 -0
  2. package/dist/api-reference.d.ts +2 -0
  3. package/dist/app.d.ts +5 -5
  4. package/dist/app.js +1039 -1971
  5. package/dist/chat/agent-dispatch/heartbeat.d.ts +0 -6
  6. package/dist/chat/mcp/errors.d.ts +3 -0
  7. package/dist/chat/mcp/tool-manager.d.ts +5 -1
  8. package/dist/chat/plugins/agent-hooks.d.ts +3 -2
  9. package/dist/chat/requester.d.ts +60 -0
  10. package/dist/chat/respond.d.ts +2 -6
  11. package/dist/chat/runtime/agent-continue-runner.d.ts +25 -0
  12. package/dist/chat/runtime/reply-executor.d.ts +4 -4
  13. package/dist/chat/runtime/turn.d.ts +2 -2
  14. package/dist/chat/services/agent-continue.d.ts +27 -0
  15. package/dist/chat/services/message-actor-identity.d.ts +12 -4
  16. package/dist/chat/services/turn-session-record.d.ts +10 -7
  17. package/dist/chat/slack/user.d.ts +4 -4
  18. package/dist/chat/state/adapter.d.ts +2 -0
  19. package/dist/chat/state/conversation-details.d.ts +4 -3
  20. package/dist/chat/state/session-log.d.ts +43 -0
  21. package/dist/chat/state/turn-session.d.ts +7 -10
  22. package/dist/chat/task-execution/queue.d.ts +1 -1
  23. package/dist/chat/task-execution/slack-work.d.ts +5 -5
  24. package/dist/chat/task-execution/store.d.ts +83 -48
  25. package/dist/chat/task-execution/worker.d.ts +3 -3
  26. package/dist/chat/tools/definition.d.ts +3 -0
  27. package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -1
  28. package/dist/chat/tools/types.d.ts +2 -5
  29. package/dist/{chunk-R62YWUNO.js → chunk-3FYPXHPL.js} +10 -28
  30. package/dist/chunk-4JXCSGSA.js +212 -0
  31. package/dist/{chunk-GT67ZWZQ.js → chunk-55XEZFGD.js} +5 -3
  32. package/dist/{chunk-BBXYXOJW.js → chunk-6GEYPE6T.js} +18 -523
  33. package/dist/chunk-G3E7SCME.js +28 -0
  34. package/dist/{chunk-UXG6TU2U.js → chunk-GB3AL54K.js} +8 -93
  35. package/dist/chunk-HNMUVGSR.js +1119 -0
  36. package/dist/{chunk-XE2VFQQN.js → chunk-ICKIDP7G.js} +1 -1
  37. package/dist/chunk-KVZL5NZS.js +519 -0
  38. package/dist/chunk-PP7AGSBU.js +185 -0
  39. package/dist/{chunk-B5HKWWQB.js → chunk-VLIO6RQR.js} +8 -6
  40. package/dist/{chunk-HOGQL2H6.js → chunk-VSNA5KAB.js} +177 -101
  41. package/dist/{chunk-76YMBKW7.js → chunk-XC33FJZN.js} +4 -12
  42. package/dist/{chunk-JS4HURDT.js → chunk-ZJQPA67D.js} +25 -25
  43. package/dist/cli/check.js +10 -8
  44. package/dist/cli/run.js +9 -1
  45. package/dist/cli/snapshot-warmup.js +10 -7
  46. package/dist/cli/upgrade.js +599 -0
  47. package/dist/nitro.d.ts +1 -1
  48. package/dist/nitro.js +5 -4
  49. package/dist/plugins.d.ts +1 -1
  50. package/dist/reporting/conversations.d.ts +116 -0
  51. package/dist/reporting.d.ts +24 -129
  52. package/dist/reporting.js +310 -158
  53. package/package.json +3 -3
  54. package/dist/chat/runtime/timeout-resume-runner.d.ts +0 -19
  55. package/dist/chat/services/requester-identity.d.ts +0 -19
  56. package/dist/chat/services/timeout-resume.d.ts +0 -23
  57. package/dist/handlers/turn-resume.d.ts +0 -4
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  destinationKey,
3
3
  parseDestination
4
- } from "./chunk-76YMBKW7.js";
4
+ } from "./chunk-XC33FJZN.js";
5
5
 
6
6
  // src/plugins.ts
7
7
  function cloneManifests(manifests) {
@@ -0,0 +1,519 @@
1
+ // src/chat/discovery.ts
2
+ import fs, { statSync } from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ function isDirectory(targetPath) {
6
+ try {
7
+ return statSync(targetPath).isDirectory();
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ function isFile(targetPath) {
13
+ try {
14
+ return statSync(targetPath).isFile();
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+ function normalizePath(targetPath) {
20
+ return path.resolve(targetPath);
21
+ }
22
+ function uniqueResolvedPathsInOrder(values) {
23
+ const seen = /* @__PURE__ */ new Set();
24
+ const resolved = [];
25
+ for (const value of values) {
26
+ const normalized = normalizePath(value);
27
+ if (seen.has(normalized)) {
28
+ continue;
29
+ }
30
+ seen.add(normalized);
31
+ resolved.push(normalized);
32
+ }
33
+ return resolved;
34
+ }
35
+ function isNodeModulesPath(candidatePath) {
36
+ return path.basename(candidatePath) === "node_modules";
37
+ }
38
+ function isInsidePnpmStore(candidatePath) {
39
+ return candidatePath.split(path.sep).includes(".pnpm");
40
+ }
41
+ function runningFromInstalledPackage() {
42
+ const currentFile = fileURLToPath(import.meta.url);
43
+ const marker = `${path.sep}node_modules${path.sep}@sentry${path.sep}junior${path.sep}`;
44
+ return currentFile.includes(marker);
45
+ }
46
+ function listInstalledPackageNodeModulesDirs() {
47
+ if (!runningFromInstalledPackage()) {
48
+ return [];
49
+ }
50
+ const dirs = [];
51
+ let current = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
52
+ while (true) {
53
+ if (isNodeModulesPath(current) && !isInsidePnpmStore(current) && isDirectory(current)) {
54
+ dirs.push(current);
55
+ }
56
+ const parent = path.dirname(current);
57
+ if (parent === current) {
58
+ break;
59
+ }
60
+ current = parent;
61
+ }
62
+ return dirs;
63
+ }
64
+ function listCwdAncestorNodeModulesDirs(cwd) {
65
+ const resolvedCwd = normalizePath(cwd);
66
+ const dirs = [];
67
+ let current = resolvedCwd;
68
+ while (true) {
69
+ const nodeModulesDir = path.join(current, "node_modules");
70
+ if (isDirectory(nodeModulesDir)) {
71
+ dirs.push(nodeModulesDir);
72
+ }
73
+ if (isFile(path.join(current, "package.json"))) {
74
+ break;
75
+ }
76
+ const parent = path.dirname(current);
77
+ if (parent === current) {
78
+ break;
79
+ }
80
+ current = parent;
81
+ }
82
+ return dirs;
83
+ }
84
+ function discoverNodeModulesDirs(cwd = process.cwd(), options) {
85
+ const explicit = options?.candidateDirs?.filter((dir) => isDirectory(dir)) ?? [];
86
+ if (explicit.length > 0) {
87
+ return uniqueResolvedPathsInOrder(explicit);
88
+ }
89
+ return uniqueResolvedPathsInOrder([
90
+ ...listInstalledPackageNodeModulesDirs(),
91
+ ...listCwdAncestorNodeModulesDirs(cwd)
92
+ ]);
93
+ }
94
+ function discoverProjectRoots(cwd = process.cwd(), options) {
95
+ const roots = discoverNodeModulesDirs(
96
+ cwd,
97
+ options?.nodeModulesDirs ? { candidateDirs: options.nodeModulesDirs } : void 0
98
+ ).map((nodeModulesDir) => path.dirname(nodeModulesDir));
99
+ return uniqueResolvedPathsInOrder([cwd, ...roots]);
100
+ }
101
+ function unique(values) {
102
+ return [...new Set(values)];
103
+ }
104
+ function pathExists(targetPath) {
105
+ try {
106
+ fs.accessSync(targetPath);
107
+ return true;
108
+ } catch {
109
+ return false;
110
+ }
111
+ }
112
+ function hasAnyDataMarkers(appDir) {
113
+ return pathExists(path.join(appDir, "SOUL.md")) || pathExists(path.join(appDir, "WORLD.md"));
114
+ }
115
+ function scoreAppCandidate(appDir) {
116
+ let score = 0;
117
+ if (pathExists(path.join(appDir, "SOUL.md"))) {
118
+ score += 4;
119
+ }
120
+ if (pathExists(path.join(appDir, "WORLD.md"))) {
121
+ score += 2;
122
+ }
123
+ if (pathExists(path.join(appDir, "skills"))) {
124
+ score += 1;
125
+ }
126
+ if (pathExists(path.join(appDir, "plugins"))) {
127
+ score += 1;
128
+ }
129
+ return score;
130
+ }
131
+ function resolveCandidateAppDirs(cwd, projectRoots) {
132
+ const roots = projectRoots ?? discoverProjectRoots(cwd);
133
+ const resolved = [];
134
+ const seen = /* @__PURE__ */ new Set();
135
+ for (const root of roots) {
136
+ const appDir = path.resolve(root, "app");
137
+ if (!pathExists(appDir)) {
138
+ continue;
139
+ }
140
+ if (seen.has(appDir)) {
141
+ continue;
142
+ }
143
+ seen.add(appDir);
144
+ resolved.push(appDir);
145
+ }
146
+ return resolved;
147
+ }
148
+ function homeDir() {
149
+ return resolveHomeDir();
150
+ }
151
+ function resolveHomeDir(cwd = process.cwd(), options) {
152
+ const resolvedCwd = path.resolve(cwd);
153
+ const directApp = path.resolve(resolvedCwd, "app");
154
+ if (pathExists(directApp) && hasAnyDataMarkers(directApp)) {
155
+ return directApp;
156
+ }
157
+ const candidates = resolveCandidateAppDirs(
158
+ resolvedCwd,
159
+ options?.projectRoots
160
+ );
161
+ if (candidates.length === 0) {
162
+ return directApp;
163
+ }
164
+ candidates.sort((left, right) => {
165
+ const leftScore = scoreAppCandidate(left);
166
+ const rightScore = scoreAppCandidate(right);
167
+ if (leftScore !== rightScore) {
168
+ return rightScore - leftScore;
169
+ }
170
+ const leftDistance = path.relative(resolvedCwd, left).split(path.sep).length;
171
+ const rightDistance = path.relative(resolvedCwd, right).split(path.sep).length;
172
+ if (leftDistance !== rightDistance) {
173
+ return leftDistance - rightDistance;
174
+ }
175
+ return left.localeCompare(right);
176
+ });
177
+ return candidates[0];
178
+ }
179
+ function resolveContentRoots(subdir) {
180
+ if (subdir === "data") {
181
+ return [homeDir()];
182
+ }
183
+ return [path.join(homeDir(), subdir)];
184
+ }
185
+ function dataRoots() {
186
+ return unique(resolveContentRoots("data"));
187
+ }
188
+ function skillRoots() {
189
+ return unique(resolveContentRoots("skills"));
190
+ }
191
+ function pluginRoots() {
192
+ return unique(resolveContentRoots("plugins"));
193
+ }
194
+ function soulPathCandidates() {
195
+ const candidates = dataRoots().map((root) => path.join(root, "SOUL.md"));
196
+ return unique(candidates);
197
+ }
198
+ function worldPathCandidates() {
199
+ const candidates = dataRoots().map((root) => path.join(root, "WORLD.md"));
200
+ return unique(candidates);
201
+ }
202
+ var RESERVED_APP_FILES = /* @__PURE__ */ new Set([
203
+ "SOUL.md",
204
+ "WORLD.md",
205
+ "DESCRIPTION.md",
206
+ "ABOUT.md"
207
+ ]);
208
+ function listReferenceFiles() {
209
+ const appDir = homeDir();
210
+ try {
211
+ const entries = fs.readdirSync(appDir, { withFileTypes: true });
212
+ return entries.filter(
213
+ (entry) => entry.isFile() && entry.name.endsWith(".md") && !RESERVED_APP_FILES.has(entry.name)
214
+ ).map((entry) => path.join(appDir, entry.name)).sort();
215
+ } catch {
216
+ return [];
217
+ }
218
+ }
219
+
220
+ // src/package-resolution.ts
221
+ import { statSync as statSync2 } from "fs";
222
+ import { createRequire } from "module";
223
+ import path2 from "path";
224
+ function isDirectory2(targetPath) {
225
+ try {
226
+ return statSync2(targetPath).isDirectory();
227
+ } catch {
228
+ return false;
229
+ }
230
+ }
231
+ function isFile2(targetPath) {
232
+ try {
233
+ return statSync2(targetPath).isFile();
234
+ } catch {
235
+ return false;
236
+ }
237
+ }
238
+ function uniqueResolvedPathsInOrder2(values) {
239
+ const seen = /* @__PURE__ */ new Set();
240
+ const resolved = [];
241
+ for (const value of values) {
242
+ const normalized = path2.resolve(value);
243
+ if (seen.has(normalized)) {
244
+ continue;
245
+ }
246
+ seen.add(normalized);
247
+ resolved.push(normalized);
248
+ }
249
+ return resolved;
250
+ }
251
+ function ancestorNodeModulesDirs(cwd) {
252
+ const dirs = [];
253
+ let current = path2.resolve(cwd);
254
+ while (true) {
255
+ const nodeModulesDir = path2.join(current, "node_modules");
256
+ if (isDirectory2(nodeModulesDir)) {
257
+ dirs.push(nodeModulesDir);
258
+ }
259
+ const parent = path2.dirname(current);
260
+ if (parent === current) {
261
+ break;
262
+ }
263
+ current = parent;
264
+ }
265
+ return dirs;
266
+ }
267
+ function packageDirInNodeModules(nodeModulesDir, packageName) {
268
+ const packageDir = path2.join(nodeModulesDir, ...packageName.split("/"));
269
+ return isDirectory2(packageDir) ? path2.resolve(packageDir) : void 0;
270
+ }
271
+ function isValidPackageSegment(segment) {
272
+ return Boolean(segment) && segment !== "." && segment !== ".." && !segment.startsWith(".") && /^[A-Za-z0-9._~-]+$/.test(segment);
273
+ }
274
+ function isValidPackageName(packageName) {
275
+ if (!packageName || packageName.includes("\\") || path2.isAbsolute(packageName)) {
276
+ return false;
277
+ }
278
+ const parts = packageName.split("/");
279
+ if (parts[0].startsWith("@")) {
280
+ return parts.length === 2 && parts[0].length > 1 && isValidPackageSegment(parts[0].slice(1)) && isValidPackageSegment(parts[1]);
281
+ }
282
+ return parts.length === 1 && isValidPackageSegment(parts[0]);
283
+ }
284
+ function findPackageRoot(entryPath) {
285
+ let dir = path2.dirname(entryPath);
286
+ while (dir !== path2.dirname(dir)) {
287
+ if (isFile2(path2.join(dir, "package.json"))) {
288
+ return path2.resolve(dir);
289
+ }
290
+ dir = path2.dirname(dir);
291
+ }
292
+ return void 0;
293
+ }
294
+ function findPackageNodeModulesDir(packageDir, packageName) {
295
+ const parts = path2.resolve(packageDir).split(path2.sep);
296
+ const packageParts = packageName.split("/");
297
+ for (let index = parts.length - 1; index >= 0; index -= 1) {
298
+ if (parts[index] !== "node_modules") {
299
+ continue;
300
+ }
301
+ const candidatePackageParts = parts.slice(
302
+ index + 1,
303
+ index + 1 + packageParts.length
304
+ );
305
+ if (candidatePackageParts.join("/") !== packageParts.join("/")) {
306
+ continue;
307
+ }
308
+ return path2.resolve(parts.slice(0, index + 1).join(path2.sep) || path2.sep);
309
+ }
310
+ return void 0;
311
+ }
312
+ function resolvePackageWithNode(cwd, packageName) {
313
+ let requireFromCwd;
314
+ try {
315
+ requireFromCwd = createRequire(path2.join(cwd, "package.json"));
316
+ } catch {
317
+ return void 0;
318
+ }
319
+ for (const specifier of [`${packageName}/package.json`, packageName]) {
320
+ try {
321
+ const resolved = requireFromCwd.resolve(specifier);
322
+ const dir = specifier.endsWith("/package.json") ? path2.dirname(resolved) : findPackageRoot(resolved);
323
+ if (!dir) {
324
+ continue;
325
+ }
326
+ const nodeModulesDir = findPackageNodeModulesDir(dir, packageName);
327
+ return {
328
+ dir,
329
+ ...nodeModulesDir ? { nodeModulesDir } : {}
330
+ };
331
+ } catch {
332
+ }
333
+ }
334
+ return void 0;
335
+ }
336
+ function resolvePackageLocation(cwd, packageName, options) {
337
+ if (!isValidPackageName(packageName)) {
338
+ return void 0;
339
+ }
340
+ const nodeModulesDirs = uniqueResolvedPathsInOrder2([
341
+ ...options?.nodeModulesDirs ?? [],
342
+ ...ancestorNodeModulesDirs(cwd)
343
+ ]);
344
+ for (const nodeModulesDir of nodeModulesDirs) {
345
+ const dir = packageDirInNodeModules(nodeModulesDir, packageName);
346
+ if (dir) {
347
+ return { dir, nodeModulesDir };
348
+ }
349
+ }
350
+ return resolvePackageWithNode(cwd, packageName);
351
+ }
352
+ function resolvePackageDir(cwd, packageName) {
353
+ return resolvePackageLocation(cwd, packageName)?.dir;
354
+ }
355
+
356
+ // src/chat/plugins/package-discovery.ts
357
+ import path3 from "path";
358
+ function normalizeForGlob(targetPath) {
359
+ return targetPath.split(path3.sep).join("/");
360
+ }
361
+ function uniqueStringsInOrder(values) {
362
+ const seen = /* @__PURE__ */ new Set();
363
+ const resolved = [];
364
+ for (const value of values) {
365
+ if (seen.has(value)) {
366
+ continue;
367
+ }
368
+ seen.add(value);
369
+ resolved.push(value);
370
+ }
371
+ return resolved;
372
+ }
373
+ function pathForTracingInclude(cwd, targetPath) {
374
+ const relative = path3.relative(cwd, targetPath);
375
+ if (!relative || path3.isAbsolute(relative) || relative === ".." || relative.startsWith(`..${path3.sep}`)) {
376
+ return null;
377
+ }
378
+ const normalized = normalizeForGlob(relative);
379
+ return normalized.startsWith(".") ? normalized : `./${normalized}`;
380
+ }
381
+ function normalizePluginPackageNames(packageNames) {
382
+ if (packageNames === void 0) {
383
+ return [];
384
+ }
385
+ if (!Array.isArray(packageNames)) {
386
+ throw new Error("Plugin package names must be an array");
387
+ }
388
+ const normalized = [];
389
+ const seen = /* @__PURE__ */ new Set();
390
+ for (const packageName of packageNames) {
391
+ const normalizedPackageName = typeof packageName === "string" ? packageName.trim() : "";
392
+ if (!normalizedPackageName || !isValidPackageName(normalizedPackageName)) {
393
+ throw new Error("Plugin package names must be valid npm package names");
394
+ }
395
+ if (seen.has(normalizedPackageName)) {
396
+ continue;
397
+ }
398
+ seen.add(normalizedPackageName);
399
+ normalized.push(normalizedPackageName);
400
+ }
401
+ return normalized;
402
+ }
403
+ function formatNodeModulesDirs(candidateNodeModulesDirs) {
404
+ return candidateNodeModulesDirs.length > 0 ? candidateNodeModulesDirs.join(", ") : "none found";
405
+ }
406
+ function resolvePackageDirFromName(cwd, packageName, candidateNodeModulesDirs) {
407
+ return resolvePackageLocation(cwd, packageName, {
408
+ nodeModulesDirs: candidateNodeModulesDirs
409
+ }) ?? null;
410
+ }
411
+ function readPluginPackageFlags(dir) {
412
+ const hasRootPluginManifest = isFile(path3.join(dir, "plugin.yaml"));
413
+ const hasPluginsDir = isDirectory(path3.join(dir, "plugins"));
414
+ const hasSkillsDir = isDirectory(path3.join(dir, "skills"));
415
+ if (!hasRootPluginManifest && !hasPluginsDir && !hasSkillsDir) {
416
+ return null;
417
+ }
418
+ return {
419
+ hasRootPluginManifest,
420
+ hasPluginsDir,
421
+ hasSkillsDir
422
+ };
423
+ }
424
+ function discoverDeclaredPackages(packageNames, candidateNodeModulesDirs, cwd) {
425
+ const discovered = [];
426
+ const seenPackageDirs = /* @__PURE__ */ new Set();
427
+ for (const packageName of packageNames) {
428
+ const resolved = resolvePackageDirFromName(
429
+ cwd,
430
+ packageName,
431
+ candidateNodeModulesDirs
432
+ );
433
+ if (!resolved) {
434
+ throw new Error(
435
+ `Plugin package "${packageName}" was configured but could not be resolved from node_modules or package resolution (${formatNodeModulesDirs(candidateNodeModulesDirs)})`
436
+ );
437
+ }
438
+ if (seenPackageDirs.has(resolved.dir)) {
439
+ continue;
440
+ }
441
+ const pluginFlags = readPluginPackageFlags(resolved.dir);
442
+ if (!pluginFlags) {
443
+ throw new Error(
444
+ `Plugin package "${packageName}" was configured but does not contain plugin content; expected plugin.yaml, plugins/, or skills/ in ${resolved.dir}`
445
+ );
446
+ }
447
+ seenPackageDirs.add(resolved.dir);
448
+ discovered.push({
449
+ name: packageName,
450
+ dir: resolved.dir,
451
+ nodeModulesDir: resolved.nodeModulesDir,
452
+ ...pluginFlags
453
+ });
454
+ }
455
+ return discovered;
456
+ }
457
+ function discoverInstalledPluginPackageContent(cwd = process.cwd(), options) {
458
+ const resolvedCwd = path3.resolve(cwd);
459
+ const packageNames = normalizePluginPackageNames(options?.packageNames);
460
+ const nodeModulesDirs = options?.nodeModulesDirs ?? discoverNodeModulesDirs(resolvedCwd);
461
+ const discoveredPackages = discoverDeclaredPackages(
462
+ packageNames,
463
+ nodeModulesDirs,
464
+ resolvedCwd
465
+ );
466
+ const manifestRoots = [];
467
+ const skillRoots2 = [];
468
+ const tracingIncludes = [];
469
+ for (const pkg of discoveredPackages) {
470
+ const tracingBasePath = pkg.nodeModulesDir ? pathForTracingInclude(
471
+ resolvedCwd,
472
+ path3.join(pkg.nodeModulesDir, ...pkg.name.split("/"))
473
+ ) : pathForTracingInclude(resolvedCwd, pkg.dir);
474
+ if (pkg.hasRootPluginManifest) {
475
+ manifestRoots.push(pkg.dir);
476
+ if (tracingBasePath) {
477
+ tracingIncludes.push(`${tracingBasePath}/plugin.yaml`);
478
+ }
479
+ }
480
+ if (pkg.hasPluginsDir) {
481
+ manifestRoots.push(path3.join(pkg.dir, "plugins"));
482
+ if (tracingBasePath) {
483
+ tracingIncludes.push(`${tracingBasePath}/plugins/**/*`);
484
+ }
485
+ }
486
+ if (pkg.hasSkillsDir) {
487
+ skillRoots2.push(path3.join(pkg.dir, "skills"));
488
+ if (tracingBasePath) {
489
+ tracingIncludes.push(`${tracingBasePath}/skills/**/*`);
490
+ }
491
+ }
492
+ }
493
+ return {
494
+ packageNames: uniqueStringsInOrder(
495
+ discoveredPackages.map((pkg) => pkg.name)
496
+ ),
497
+ packages: discoveredPackages.map((pkg) => ({
498
+ dir: pkg.dir,
499
+ hasSkillsDir: pkg.hasSkillsDir,
500
+ name: pkg.name
501
+ })),
502
+ manifestRoots: uniqueStringsInOrder(manifestRoots),
503
+ skillRoots: uniqueStringsInOrder(skillRoots2),
504
+ tracingIncludes: uniqueStringsInOrder(tracingIncludes)
505
+ };
506
+ }
507
+
508
+ export {
509
+ homeDir,
510
+ skillRoots,
511
+ pluginRoots,
512
+ soulPathCandidates,
513
+ worldPathCandidates,
514
+ listReferenceFiles,
515
+ isValidPackageName,
516
+ resolvePackageDir,
517
+ normalizePluginPackageNames,
518
+ discoverInstalledPluginPackageContent
519
+ };
@@ -0,0 +1,185 @@
1
+ import {
2
+ isSlackTeamId
3
+ } from "./chunk-6GEYPE6T.js";
4
+
5
+ // src/chat/requester.ts
6
+ import { z } from "zod";
7
+ var SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{5,}$/;
8
+ var EMAIL_PATTERN = /^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/;
9
+ var exactStoredStringSchema = z.string().min(1).refine((value) => value === value.trim());
10
+ var storedSlackRequesterSchema = z.object({
11
+ email: exactStoredStringSchema.optional(),
12
+ fullName: exactStoredStringSchema.optional(),
13
+ platform: z.literal("slack").optional(),
14
+ slackUserId: exactStoredStringSchema.optional(),
15
+ slackUserName: exactStoredStringSchema.optional(),
16
+ teamId: exactStoredStringSchema.optional()
17
+ }).strict();
18
+ function clean(value) {
19
+ const trimmed = value?.trim();
20
+ return trimmed ? trimmed : void 0;
21
+ }
22
+ function isSyntheticActorUserId(value) {
23
+ return value.toLowerCase() === "unknown";
24
+ }
25
+ function isSlackUserId(value) {
26
+ return SLACK_USER_ID_PATTERN.test(value);
27
+ }
28
+ function parseSlackTeamId(value) {
29
+ return typeof value === "string" && isSlackTeamId(value) ? value : void 0;
30
+ }
31
+ function cleanRequesterDisplayName(value, userId) {
32
+ const displayName = clean(value);
33
+ if (!displayName) {
34
+ return void 0;
35
+ }
36
+ if (displayName.toLowerCase() === "unknown") {
37
+ return void 0;
38
+ }
39
+ if (userId && displayName === userId) {
40
+ return void 0;
41
+ }
42
+ return isSlackUserId(displayName) ? void 0 : displayName;
43
+ }
44
+ function cleanRequesterEmail(value) {
45
+ const email = clean(value);
46
+ return email && EMAIL_PATTERN.test(email) ? email : void 0;
47
+ }
48
+ function parseActorUserId(value) {
49
+ if (typeof value !== "string" || value.length === 0) {
50
+ return void 0;
51
+ }
52
+ if (value !== value.trim() || isSyntheticActorUserId(value)) {
53
+ return void 0;
54
+ }
55
+ return value;
56
+ }
57
+ function isActorUserId(value) {
58
+ return parseActorUserId(value) === value;
59
+ }
60
+ function createRequester(input, context) {
61
+ const contextUserId = parseActorUserId(context.userId);
62
+ if (context.userId !== void 0 && !contextUserId) {
63
+ return void 0;
64
+ }
65
+ const inputUserId = parseActorUserId(input?.userId);
66
+ if (input?.userId !== void 0 && !inputUserId) {
67
+ return void 0;
68
+ }
69
+ const contextTeamId = parseSlackTeamId(context.teamId);
70
+ if (context.teamId !== void 0 && !contextTeamId) {
71
+ return void 0;
72
+ }
73
+ const inputTeamId = parseSlackTeamId(input?.teamId);
74
+ if (input?.teamId !== void 0 && !inputTeamId) {
75
+ return void 0;
76
+ }
77
+ const requesterUserId = contextUserId ?? inputUserId;
78
+ const requesterTeamId = contextTeamId ?? inputTeamId;
79
+ if (!requesterUserId || !requesterTeamId) {
80
+ return void 0;
81
+ }
82
+ const canUseInputProfile = (!contextUserId || !inputUserId || contextUserId === inputUserId) && (!contextTeamId || !inputTeamId || contextTeamId === inputTeamId);
83
+ return {
84
+ ...canUseInputProfile && cleanRequesterEmail(input?.email) ? { email: cleanRequesterEmail(input?.email) } : {},
85
+ ...canUseInputProfile && cleanRequesterDisplayName(input?.fullName, requesterUserId) ? {
86
+ fullName: cleanRequesterDisplayName(input?.fullName, requesterUserId)
87
+ } : {},
88
+ platform: "slack",
89
+ teamId: requesterTeamId,
90
+ userId: requesterUserId,
91
+ ...canUseInputProfile && cleanRequesterDisplayName(input?.userName, requesterUserId) ? {
92
+ userName: cleanRequesterDisplayName(input?.userName, requesterUserId)
93
+ } : {}
94
+ };
95
+ }
96
+ function createSlackRequester(teamId, userId, profile) {
97
+ const actorUserId = parseActorUserId(userId);
98
+ const actorTeamId = parseSlackTeamId(teamId);
99
+ if (!actorTeamId || !actorUserId) {
100
+ throw new Error("Slack requester requires team and user ids");
101
+ }
102
+ const requester = createRequester(
103
+ {
104
+ email: profile?.email,
105
+ fullName: profile?.fullName,
106
+ platform: "slack",
107
+ teamId: actorTeamId,
108
+ userId: actorUserId,
109
+ userName: profile?.userName
110
+ },
111
+ { teamId: actorTeamId, userId: actorUserId }
112
+ );
113
+ if (!requester) {
114
+ throw new Error("Slack requester requires team and user ids");
115
+ }
116
+ return requester;
117
+ }
118
+ function parseStoredSlackRequester(value) {
119
+ const parsed = storedSlackRequesterSchema.safeParse(value);
120
+ if (!parsed.success) {
121
+ return void 0;
122
+ }
123
+ if (parsed.data.slackUserId !== void 0 && !parseActorUserId(parsed.data.slackUserId)) {
124
+ return void 0;
125
+ }
126
+ if (parsed.data.teamId !== void 0 && !parseSlackTeamId(parsed.data.teamId)) {
127
+ return void 0;
128
+ }
129
+ if ((parsed.data.platform !== void 0 || parsed.data.teamId !== void 0) && (!parsed.data.platform || !parsed.data.teamId)) {
130
+ return void 0;
131
+ }
132
+ return parsed.data;
133
+ }
134
+ function toStoredSlackRequester(requester) {
135
+ return {
136
+ ...requester.email ? { email: requester.email } : {},
137
+ ...requester.fullName ? { fullName: requester.fullName } : {},
138
+ platform: requester.platform,
139
+ slackUserId: requester.userId,
140
+ ...requester.userName ? { slackUserName: requester.userName } : {},
141
+ teamId: requester.teamId
142
+ };
143
+ }
144
+ function createRequesterFromStoredSlackRequester(args) {
145
+ const actorUserId = parseActorUserId(args.userId);
146
+ const actorTeamId = parseSlackTeamId(args.teamId);
147
+ if (!actorTeamId || !actorUserId) {
148
+ throw new Error("Slack requester requires team and user ids");
149
+ }
150
+ const storedUserId = args.requester?.slackUserId === void 0 ? void 0 : parseActorUserId(args.requester.slackUserId);
151
+ const storedTeamId = args.requester?.teamId === void 0 ? void 0 : parseSlackTeamId(args.requester.teamId);
152
+ if (args.requester?.slackUserId !== void 0 && !storedUserId) {
153
+ throw new Error("Stored Slack requester requires a user id");
154
+ }
155
+ if (args.requester?.teamId !== void 0 && !storedTeamId) {
156
+ throw new Error("Stored Slack requester requires a team id");
157
+ }
158
+ if (storedUserId && storedUserId !== actorUserId) {
159
+ throw new Error("Stored Slack requester must match actor user id");
160
+ }
161
+ if (storedTeamId && storedTeamId !== actorTeamId) {
162
+ throw new Error("Stored Slack requester must match actor team id");
163
+ }
164
+ const canUseStoredProfile = Boolean(storedUserId);
165
+ return createSlackRequester(
166
+ actorTeamId,
167
+ actorUserId,
168
+ canUseStoredProfile ? {
169
+ email: args.requester?.email,
170
+ fullName: args.requester?.fullName,
171
+ userName: args.requester?.slackUserName
172
+ } : void 0
173
+ );
174
+ }
175
+
176
+ export {
177
+ storedSlackRequesterSchema,
178
+ parseActorUserId,
179
+ isActorUserId,
180
+ createRequester,
181
+ createSlackRequester,
182
+ parseStoredSlackRequester,
183
+ toStoredSlackRequester,
184
+ createRequesterFromStoredSlackRequester
185
+ };