@sentry/junior 0.119.0 → 0.121.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.
- package/dist/{agent-hooks-NZSV4QQR.js → agent-hooks-CQDGDBCP.js} +7 -7
- package/dist/api.js +58 -79
- package/dist/app.js +21 -21
- package/dist/build/copy-build-content.d.ts +2 -2
- package/dist/{catalog-runtime-TAOYIZIZ.js → catalog-runtime-AD3YNTTM.js} +7 -7
- package/dist/chat/discovery.d.ts +2 -0
- package/dist/chat/mcp/tool-manager.d.ts +14 -1
- package/dist/chat/plugins/types.d.ts +3 -9
- package/dist/chat/plugins/user-pages.d.ts +2 -1
- package/dist/chat/sandbox/noninteractive-command.d.ts +1 -0
- package/dist/chat/sandbox/session.d.ts +2 -2
- package/dist/chat/sandbox/snapshot/install.d.ts +2 -2
- package/dist/chat/sandbox/snapshot/resolve.d.ts +1 -0
- package/dist/chat/sandbox/workspace.d.ts +3 -1
- package/dist/{chunk-D3N4BPSL.js → chunk-254MFDOF.js} +2 -2
- package/dist/{chunk-4UIUDOOV.js → chunk-3DBMANUI.js} +7 -7
- package/dist/{chunk-BLQZACHV.js → chunk-7HYV7KFM.js} +92 -6
- package/dist/{chunk-JLJLZS2N.js → chunk-D2EMOH3N.js} +4 -3
- package/dist/{chunk-R53UT2OI.js → chunk-ET2SDCNV.js} +9 -5
- package/dist/chunk-H4HBKISO.js +417 -0
- package/dist/{chunk-VLTWQQKH.js → chunk-IDXLBKPS.js} +1 -1
- package/dist/{chunk-NUENIPQL.js → chunk-IK4QSS5H.js} +1 -1
- package/dist/{chunk-GKFDU3ZI.js → chunk-ITMEXX5H.js} +44 -23
- package/dist/{chunk-ZFX4M743.js → chunk-JYDIBXFY.js} +6 -6
- package/dist/{chunk-ZJ6IVZVO.js → chunk-JZ47AFSH.js} +1 -1
- package/dist/{chunk-YLYJIQRX.js → chunk-KLUMVJRQ.js} +12 -12
- package/dist/{chunk-TAGV4Z3J.js → chunk-LE77HHF3.js} +1 -1
- package/dist/{chunk-B3IT5END.js → chunk-OOUNJNMR.js} +16 -152
- package/dist/{chunk-QZ7XRJDB.js → chunk-TRECK7RV.js} +3 -3
- package/dist/{chunk-VJTWKJWQ.js → chunk-UURFXX66.js} +1 -1
- package/dist/{chunk-6ZR455DC.js → chunk-UXQ5XSA2.js} +1 -1
- package/dist/{chunk-TGIQN7QW.js → chunk-VWBKDPMQ.js} +242 -69
- package/dist/{chunk-JSTGI7TX.js → chunk-WUP7NWMP.js} +1 -1
- package/dist/{chunk-JXRAOOXQ.js → chunk-XDRGYDED.js} +1 -1
- package/dist/{chunk-BNJEPYTC.js → chunk-Z2XXPUZG.js} +4 -4
- package/dist/cli/chat.js +23 -23
- package/dist/cli/check.js +8 -8
- package/dist/cli/plugins.js +12 -12
- package/dist/cli/snapshot-create.js +10 -10
- package/dist/cli/upgrade.js +7 -7
- package/dist/{db-FWGP5CKY.js → db-7HQT2SXQ.js} +5 -5
- package/dist/{discovery-RMHYSRL7.js → discovery-GUFTFBTL.js} +3 -1
- package/dist/instrumentation.js +2 -2
- package/dist/nitro.js +24 -7
- package/dist/{oauth-callback-server-PM3QNXJQ.js → oauth-callback-server-VHTUCNHK.js} +16 -16
- package/dist/{runner-DV55N6ZB.js → runner-3ONPZRED.js} +9 -9
- package/dist/{skills-MANV5ZK6.js → skills-WGAYGGPA.js} +8 -8
- package/dist/{validation-QGB4INTI.js → validation-ZIWNBG4D.js} +8 -8
- package/dist/version.js +1 -1
- package/package.json +8 -7
- package/skills/jr-rpc/SKILL.md +40 -0
- package/dist/chunk-3V7OFJZC.js +0 -264
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getDb
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-254MFDOF.js";
|
|
4
4
|
import {
|
|
5
|
-
juniorConversationAnnotations
|
|
5
|
+
juniorConversationAnnotations,
|
|
6
|
+
juniorIdentities,
|
|
7
|
+
juniorUsers
|
|
6
8
|
} from "./chunk-GCGJGSQL.js";
|
|
7
9
|
import {
|
|
8
10
|
SANDBOX_WORKSPACE_ROOT,
|
|
9
11
|
getStateAdapter,
|
|
10
12
|
sleep
|
|
11
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-UURFXX66.js";
|
|
12
14
|
import {
|
|
13
15
|
botConfig,
|
|
14
16
|
completeObject,
|
|
15
17
|
embedTexts,
|
|
16
18
|
getSlackBotToken,
|
|
17
19
|
standardModelId
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-IDXLBKPS.js";
|
|
19
21
|
import {
|
|
20
22
|
isActorUserId,
|
|
21
23
|
parseActorUserId
|
|
@@ -24,10 +26,11 @@ import {
|
|
|
24
26
|
logException,
|
|
25
27
|
logInfo,
|
|
26
28
|
logWarn,
|
|
29
|
+
normalizeIdentityEmail,
|
|
27
30
|
setSpanAttributes,
|
|
28
31
|
setSpanStatus,
|
|
29
32
|
withSpan
|
|
30
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-JZ47AFSH.js";
|
|
31
34
|
import {
|
|
32
35
|
parseSlackChannelReferenceId,
|
|
33
36
|
parseSlackMessageTs,
|
|
@@ -321,6 +324,55 @@ function getSlackToolContext(context) {
|
|
|
321
324
|
};
|
|
322
325
|
}
|
|
323
326
|
|
|
327
|
+
// src/chat/plugins/viewer-actors.ts
|
|
328
|
+
import { and as and2, eq as eq2 } from "drizzle-orm";
|
|
329
|
+
import {
|
|
330
|
+
actorSchema
|
|
331
|
+
} from "@sentry/junior-plugin-api";
|
|
332
|
+
async function readViewerActorsFromSql(db, email) {
|
|
333
|
+
const normalizedEmail = normalizeIdentityEmail(email);
|
|
334
|
+
if (!normalizedEmail) return [];
|
|
335
|
+
const rows = await db.select({
|
|
336
|
+
displayName: juniorIdentities.displayName,
|
|
337
|
+
email: juniorUsers.primaryEmail,
|
|
338
|
+
handle: juniorIdentities.handle,
|
|
339
|
+
provider: juniorIdentities.provider,
|
|
340
|
+
providerSubjectId: juniorIdentities.providerSubjectId,
|
|
341
|
+
providerTenantId: juniorIdentities.providerTenantId
|
|
342
|
+
}).from(juniorIdentities).innerJoin(juniorUsers, eq2(juniorUsers.id, juniorIdentities.userId)).where(
|
|
343
|
+
and2(
|
|
344
|
+
eq2(juniorUsers.primaryEmailNormalized, normalizedEmail),
|
|
345
|
+
eq2(juniorIdentities.kind, "user")
|
|
346
|
+
)
|
|
347
|
+
);
|
|
348
|
+
const actors = [];
|
|
349
|
+
for (const row of rows) {
|
|
350
|
+
const candidate = row.provider === "slack" ? {
|
|
351
|
+
platform: "slack",
|
|
352
|
+
teamId: row.providerTenantId,
|
|
353
|
+
userId: row.providerSubjectId,
|
|
354
|
+
email: row.email,
|
|
355
|
+
...row.displayName ? { fullName: row.displayName } : {},
|
|
356
|
+
...row.handle ? { userName: row.handle } : {}
|
|
357
|
+
} : row.provider === "local" ? {
|
|
358
|
+
platform: "local",
|
|
359
|
+
userId: row.providerSubjectId,
|
|
360
|
+
email: row.email,
|
|
361
|
+
...row.displayName ? { fullName: row.displayName } : {},
|
|
362
|
+
...row.handle ? { userName: row.handle } : {}
|
|
363
|
+
} : void 0;
|
|
364
|
+
if (!candidate) continue;
|
|
365
|
+
const parsed = actorSchema.safeParse(candidate);
|
|
366
|
+
if (parsed.success && parsed.data.platform !== "system") {
|
|
367
|
+
actors.push(parsed.data);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return actors;
|
|
371
|
+
}
|
|
372
|
+
async function readViewerActors(email) {
|
|
373
|
+
return await readViewerActorsFromSql(getDb(), email);
|
|
374
|
+
}
|
|
375
|
+
|
|
324
376
|
// src/chat/credentials/subject.ts
|
|
325
377
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
326
378
|
|
|
@@ -941,6 +993,7 @@ function invocationPluginContext(plugin, context) {
|
|
|
941
993
|
...base,
|
|
942
994
|
conversationId: context.conversationId,
|
|
943
995
|
embedder: createPluginEmbedder(plugin.manifest.name),
|
|
996
|
+
model: createPluginModel(plugin.manifest.name, plugin.model),
|
|
944
997
|
source: context.source,
|
|
945
998
|
text: context.userText ?? "",
|
|
946
999
|
state: createPluginState(plugin.manifest.name)
|
|
@@ -968,6 +1021,32 @@ function invocationPluginContext(plugin, context) {
|
|
|
968
1021
|
actor: context.actor?.platform === "local" ? context.actor : void 0
|
|
969
1022
|
};
|
|
970
1023
|
}
|
|
1024
|
+
function pluginMcpContext(plugin, context) {
|
|
1025
|
+
const manager = context.mcpToolManager;
|
|
1026
|
+
const wrappedTools = new Set(plugin.manifest.mcp?.wrappedTools ?? []);
|
|
1027
|
+
if (!manager || wrappedTools.size === 0) {
|
|
1028
|
+
return void 0;
|
|
1029
|
+
}
|
|
1030
|
+
const provider = plugin.manifest.name;
|
|
1031
|
+
const prepare = async () => {
|
|
1032
|
+
await manager.activateProvider(provider);
|
|
1033
|
+
return manager.getActiveProviders().includes(provider) ? "ready" : "authorization_pending";
|
|
1034
|
+
};
|
|
1035
|
+
return {
|
|
1036
|
+
prepare,
|
|
1037
|
+
async callTool(input) {
|
|
1038
|
+
if (await prepare() === "authorization_pending") {
|
|
1039
|
+
return { status: "authorization_pending" };
|
|
1040
|
+
}
|
|
1041
|
+
return await manager.callWrappedTool(
|
|
1042
|
+
provider,
|
|
1043
|
+
input.name,
|
|
1044
|
+
input.arguments ?? {},
|
|
1045
|
+
input.toolCallId ? { toolCallId: input.toolCallId } : void 0
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
971
1050
|
function safeErrorMessage(error) {
|
|
972
1051
|
return error instanceof Error ? error.message : String(error);
|
|
973
1052
|
}
|
|
@@ -1239,6 +1318,7 @@ function getPluginTools(context) {
|
|
|
1239
1318
|
db: getDb(),
|
|
1240
1319
|
plugin: pluginName
|
|
1241
1320
|
}) : void 0;
|
|
1321
|
+
const mcp = pluginMcpContext(plugin, context);
|
|
1242
1322
|
let pluginContext;
|
|
1243
1323
|
if (context.source.platform === "slack") {
|
|
1244
1324
|
if (context.destination.platform !== "slack") {
|
|
@@ -1257,6 +1337,7 @@ function getPluginTools(context) {
|
|
|
1257
1337
|
userText: context.userText,
|
|
1258
1338
|
embedder: createPluginEmbedder(pluginName),
|
|
1259
1339
|
egress: context.egress,
|
|
1340
|
+
...mcp ? { mcp } : {},
|
|
1260
1341
|
model: createPluginModel(pluginName, plugin.model),
|
|
1261
1342
|
state: createPluginState(pluginName)
|
|
1262
1343
|
};
|
|
@@ -1276,6 +1357,7 @@ function getPluginTools(context) {
|
|
|
1276
1357
|
userText: context.userText,
|
|
1277
1358
|
embedder: createPluginEmbedder(pluginName),
|
|
1278
1359
|
egress: context.egress,
|
|
1360
|
+
...mcp ? { mcp } : {},
|
|
1279
1361
|
model: createPluginModel(pluginName, plugin.model),
|
|
1280
1362
|
state: createPluginState(pluginName)
|
|
1281
1363
|
};
|
|
@@ -1416,7 +1498,10 @@ function getPluginApiRoutes() {
|
|
|
1416
1498
|
continue;
|
|
1417
1499
|
}
|
|
1418
1500
|
const app = hook({
|
|
1419
|
-
...basePluginContext(plugin)
|
|
1501
|
+
...basePluginContext(plugin),
|
|
1502
|
+
viewer: {
|
|
1503
|
+
actors: readViewerActors
|
|
1504
|
+
}
|
|
1420
1505
|
});
|
|
1421
1506
|
if (app === void 0) {
|
|
1422
1507
|
continue;
|
|
@@ -1853,6 +1938,7 @@ export {
|
|
|
1853
1938
|
setDashboardConversationLinkOptions,
|
|
1854
1939
|
getDashboardConversationLink,
|
|
1855
1940
|
getSlackToolContext,
|
|
1941
|
+
readViewerActors,
|
|
1856
1942
|
runWithWorkspaceTeamId,
|
|
1857
1943
|
getWorkspaceTeamId,
|
|
1858
1944
|
SlackActionError,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@sentry/junior",
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "0.121.0",
|
|
5
5
|
private: false,
|
|
6
6
|
publishConfig: {
|
|
7
7
|
access: "public"
|
|
@@ -49,7 +49,8 @@ var package_default = {
|
|
|
49
49
|
files: [
|
|
50
50
|
"dist",
|
|
51
51
|
"bin",
|
|
52
|
-
"migrations"
|
|
52
|
+
"migrations",
|
|
53
|
+
"skills"
|
|
53
54
|
],
|
|
54
55
|
scripts: {
|
|
55
56
|
prepare: "pnpm run build",
|
|
@@ -61,7 +62,7 @@ var package_default = {
|
|
|
61
62
|
test: "vitest run --maxWorkers=4",
|
|
62
63
|
"test:watch": "vitest",
|
|
63
64
|
typecheck: "tsc --noEmit",
|
|
64
|
-
"skills:check": "node scripts/check-skills.mjs",
|
|
65
|
+
"skills:check": "node --test scripts/check-skills.test.mjs && node scripts/check-skills.mjs",
|
|
65
66
|
"test:coverage": "vitest run --maxWorkers=4 --coverage --reporter=default --reporter=junit --outputFile.junit=coverage/results.junit.xml"
|
|
66
67
|
},
|
|
67
68
|
dependencies: {
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
logInfo,
|
|
6
6
|
logWarn,
|
|
7
7
|
setSpanAttributes
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JZ47AFSH.js";
|
|
9
9
|
import {
|
|
10
10
|
discoverInstalledPluginPackageContent,
|
|
11
11
|
normalizePluginPackageNames
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-OOUNJNMR.js";
|
|
13
13
|
import {
|
|
14
14
|
pluginRoots
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-H4HBKISO.js";
|
|
16
16
|
|
|
17
17
|
// src/chat/plugins/manifest.ts
|
|
18
18
|
import { z } from "zod";
|
|
@@ -64,6 +64,7 @@ function inlineMcpSource(mcp) {
|
|
|
64
64
|
setDefined(result, "url", mcp.url);
|
|
65
65
|
setDefined(result, "headers", mcp.headers);
|
|
66
66
|
setDefined(result, "allowed-tools", mcp.allowedTools);
|
|
67
|
+
setDefined(result, "wrapped-tools", mcp.wrappedTools);
|
|
67
68
|
return result;
|
|
68
69
|
}
|
|
69
70
|
function inlineOauthSource(oauth) {
|
|
@@ -300,7 +301,8 @@ var mcpSourceSchema = z.object({
|
|
|
300
301
|
}).optional(),
|
|
301
302
|
url: httpsUrlString,
|
|
302
303
|
headers: stringMapSchema.optional(),
|
|
303
|
-
"allowed-tools": nonEmptyStringArraySchema("allowed-tools").optional()
|
|
304
|
+
"allowed-tools": nonEmptyStringArraySchema("allowed-tools").optional(),
|
|
305
|
+
"wrapped-tools": nonEmptyStringArraySchema("wrapped-tools").optional()
|
|
304
306
|
}).passthrough();
|
|
305
307
|
var targetSourceSchema = z.object({
|
|
306
308
|
type: nonEmptyTrimmedString.refine((value) => PLUGIN_NAME_RE.test(value), {
|
|
@@ -389,6 +391,7 @@ function manifestConfigPatch(config) {
|
|
|
389
391
|
setDefined2(mcp, "url", config.mcp.url);
|
|
390
392
|
setDefined2(mcp, "headers", config.mcp.headers);
|
|
391
393
|
setDefined2(mcp, "allowed-tools", config.mcp.allowedTools);
|
|
394
|
+
setDefined2(mcp, "wrapped-tools", config.mcp.wrappedTools);
|
|
392
395
|
result.mcp = mcp;
|
|
393
396
|
}
|
|
394
397
|
}
|
|
@@ -829,7 +832,8 @@ function normalizeMcp(data, envVars, name) {
|
|
|
829
832
|
transport: "http",
|
|
830
833
|
url: result.data.url,
|
|
831
834
|
...headers ? { headers } : {},
|
|
832
|
-
...result.data["allowed-tools"] ? { allowedTools: result.data["allowed-tools"] } : {}
|
|
835
|
+
...result.data["allowed-tools"] ? { allowedTools: result.data["allowed-tools"] } : {},
|
|
836
|
+
...result.data["wrapped-tools"] ? { wrappedTools: result.data["wrapped-tools"] } : {}
|
|
833
837
|
};
|
|
834
838
|
}
|
|
835
839
|
function parseManifestSource(parsedSource, dir, config, options) {
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
// src/chat/discovery.ts
|
|
2
|
+
import fs, { statSync as statSync2 } from "fs";
|
|
3
|
+
import path2 from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
// src/package-resolution.ts
|
|
7
|
+
import { statSync } from "fs";
|
|
8
|
+
import { createRequire } from "module";
|
|
9
|
+
import path from "path";
|
|
10
|
+
function isDirectory(targetPath) {
|
|
11
|
+
try {
|
|
12
|
+
return statSync(targetPath).isDirectory();
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function isFile(targetPath) {
|
|
18
|
+
try {
|
|
19
|
+
return statSync(targetPath).isFile();
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function uniqueResolvedPathsInOrder(values) {
|
|
25
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26
|
+
const resolved = [];
|
|
27
|
+
for (const value of values) {
|
|
28
|
+
const normalized = path.resolve(value);
|
|
29
|
+
if (seen.has(normalized)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
seen.add(normalized);
|
|
33
|
+
resolved.push(normalized);
|
|
34
|
+
}
|
|
35
|
+
return resolved;
|
|
36
|
+
}
|
|
37
|
+
function ancestorNodeModulesDirs(cwd) {
|
|
38
|
+
const dirs = [];
|
|
39
|
+
let current = path.resolve(cwd);
|
|
40
|
+
while (true) {
|
|
41
|
+
const nodeModulesDir = path.join(current, "node_modules");
|
|
42
|
+
if (isDirectory(nodeModulesDir)) {
|
|
43
|
+
dirs.push(nodeModulesDir);
|
|
44
|
+
}
|
|
45
|
+
const parent = path.dirname(current);
|
|
46
|
+
if (parent === current) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
current = parent;
|
|
50
|
+
}
|
|
51
|
+
return dirs;
|
|
52
|
+
}
|
|
53
|
+
function packageDirInNodeModules(nodeModulesDir, packageName) {
|
|
54
|
+
const packageDir = path.join(nodeModulesDir, ...packageName.split("/"));
|
|
55
|
+
return isDirectory(packageDir) ? path.resolve(packageDir) : void 0;
|
|
56
|
+
}
|
|
57
|
+
function isValidPackageSegment(segment) {
|
|
58
|
+
return Boolean(segment) && segment !== "." && segment !== ".." && !segment.startsWith(".") && /^[A-Za-z0-9._~-]+$/.test(segment);
|
|
59
|
+
}
|
|
60
|
+
function isValidPackageName(packageName) {
|
|
61
|
+
if (!packageName || packageName.includes("\\") || path.isAbsolute(packageName)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const parts = packageName.split("/");
|
|
65
|
+
if (parts[0].startsWith("@")) {
|
|
66
|
+
return parts.length === 2 && parts[0].length > 1 && isValidPackageSegment(parts[0].slice(1)) && isValidPackageSegment(parts[1]);
|
|
67
|
+
}
|
|
68
|
+
return parts.length === 1 && isValidPackageSegment(parts[0]);
|
|
69
|
+
}
|
|
70
|
+
function findPackageRoot(entryPath) {
|
|
71
|
+
let dir = path.dirname(entryPath);
|
|
72
|
+
while (dir !== path.dirname(dir)) {
|
|
73
|
+
if (isFile(path.join(dir, "package.json"))) {
|
|
74
|
+
return path.resolve(dir);
|
|
75
|
+
}
|
|
76
|
+
dir = path.dirname(dir);
|
|
77
|
+
}
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
function findPackageNodeModulesDir(packageDir, packageName) {
|
|
81
|
+
const parts = path.resolve(packageDir).split(path.sep);
|
|
82
|
+
const packageParts = packageName.split("/");
|
|
83
|
+
for (let index = parts.length - 1; index >= 0; index -= 1) {
|
|
84
|
+
if (parts[index] !== "node_modules") {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const candidatePackageParts = parts.slice(
|
|
88
|
+
index + 1,
|
|
89
|
+
index + 1 + packageParts.length
|
|
90
|
+
);
|
|
91
|
+
if (candidatePackageParts.join("/") !== packageParts.join("/")) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
return path.resolve(parts.slice(0, index + 1).join(path.sep) || path.sep);
|
|
95
|
+
}
|
|
96
|
+
return void 0;
|
|
97
|
+
}
|
|
98
|
+
function resolvePackageWithNode(cwd, packageName) {
|
|
99
|
+
let requireFromCwd;
|
|
100
|
+
try {
|
|
101
|
+
requireFromCwd = createRequire(path.join(cwd, "package.json"));
|
|
102
|
+
} catch {
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
for (const specifier of [`${packageName}/package.json`, packageName]) {
|
|
106
|
+
try {
|
|
107
|
+
const resolved = requireFromCwd.resolve(specifier);
|
|
108
|
+
const dir = specifier.endsWith("/package.json") ? path.dirname(resolved) : findPackageRoot(resolved);
|
|
109
|
+
if (!dir) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const nodeModulesDir = findPackageNodeModulesDir(dir, packageName);
|
|
113
|
+
return {
|
|
114
|
+
dir,
|
|
115
|
+
...nodeModulesDir ? { nodeModulesDir } : {}
|
|
116
|
+
};
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
function resolvePackageLocation(cwd, packageName, options) {
|
|
123
|
+
if (!isValidPackageName(packageName)) {
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
const nodeModulesDirs = uniqueResolvedPathsInOrder([
|
|
127
|
+
...options?.nodeModulesDirs ?? [],
|
|
128
|
+
...ancestorNodeModulesDirs(cwd)
|
|
129
|
+
]);
|
|
130
|
+
for (const nodeModulesDir of nodeModulesDirs) {
|
|
131
|
+
const dir = packageDirInNodeModules(nodeModulesDir, packageName);
|
|
132
|
+
if (dir) {
|
|
133
|
+
return { dir, nodeModulesDir };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return resolvePackageWithNode(cwd, packageName);
|
|
137
|
+
}
|
|
138
|
+
function resolvePackageDir(cwd, packageName) {
|
|
139
|
+
return resolvePackageLocation(cwd, packageName)?.dir;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/chat/discovery.ts
|
|
143
|
+
function isDirectory2(targetPath) {
|
|
144
|
+
try {
|
|
145
|
+
return statSync2(targetPath).isDirectory();
|
|
146
|
+
} catch {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function isFile2(targetPath) {
|
|
151
|
+
try {
|
|
152
|
+
return statSync2(targetPath).isFile();
|
|
153
|
+
} catch {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function normalizePath(targetPath) {
|
|
158
|
+
return path2.resolve(targetPath);
|
|
159
|
+
}
|
|
160
|
+
function uniqueResolvedPathsInOrder2(values) {
|
|
161
|
+
const seen = /* @__PURE__ */ new Set();
|
|
162
|
+
const resolved = [];
|
|
163
|
+
for (const value of values) {
|
|
164
|
+
const normalized = normalizePath(value);
|
|
165
|
+
if (seen.has(normalized)) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
seen.add(normalized);
|
|
169
|
+
resolved.push(normalized);
|
|
170
|
+
}
|
|
171
|
+
return resolved;
|
|
172
|
+
}
|
|
173
|
+
function isNodeModulesPath(candidatePath) {
|
|
174
|
+
return path2.basename(candidatePath) === "node_modules";
|
|
175
|
+
}
|
|
176
|
+
function isInsidePnpmStore(candidatePath) {
|
|
177
|
+
return candidatePath.split(path2.sep).includes(".pnpm");
|
|
178
|
+
}
|
|
179
|
+
function runningFromInstalledPackage() {
|
|
180
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
181
|
+
const marker = `${path2.sep}node_modules${path2.sep}@sentry${path2.sep}junior${path2.sep}`;
|
|
182
|
+
return currentFile.includes(marker);
|
|
183
|
+
}
|
|
184
|
+
function listInstalledPackageNodeModulesDirs() {
|
|
185
|
+
if (!runningFromInstalledPackage()) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
const dirs = [];
|
|
189
|
+
let current = path2.resolve(path2.dirname(fileURLToPath(import.meta.url)));
|
|
190
|
+
while (true) {
|
|
191
|
+
if (isNodeModulesPath(current) && !isInsidePnpmStore(current) && isDirectory2(current)) {
|
|
192
|
+
dirs.push(current);
|
|
193
|
+
}
|
|
194
|
+
const parent = path2.dirname(current);
|
|
195
|
+
if (parent === current) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
current = parent;
|
|
199
|
+
}
|
|
200
|
+
return dirs;
|
|
201
|
+
}
|
|
202
|
+
function listCwdAncestorNodeModulesDirs(cwd) {
|
|
203
|
+
const resolvedCwd = normalizePath(cwd);
|
|
204
|
+
const dirs = [];
|
|
205
|
+
let current = resolvedCwd;
|
|
206
|
+
while (true) {
|
|
207
|
+
const nodeModulesDir = path2.join(current, "node_modules");
|
|
208
|
+
if (isDirectory2(nodeModulesDir)) {
|
|
209
|
+
dirs.push(nodeModulesDir);
|
|
210
|
+
}
|
|
211
|
+
if (isFile2(path2.join(current, "package.json"))) {
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
const parent = path2.dirname(current);
|
|
215
|
+
if (parent === current) {
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
current = parent;
|
|
219
|
+
}
|
|
220
|
+
return dirs;
|
|
221
|
+
}
|
|
222
|
+
function discoverNodeModulesDirs(cwd = process.cwd(), options) {
|
|
223
|
+
const explicit = options?.candidateDirs?.filter((dir) => isDirectory2(dir)) ?? [];
|
|
224
|
+
if (explicit.length > 0) {
|
|
225
|
+
return uniqueResolvedPathsInOrder2(explicit);
|
|
226
|
+
}
|
|
227
|
+
return uniqueResolvedPathsInOrder2([
|
|
228
|
+
...listInstalledPackageNodeModulesDirs(),
|
|
229
|
+
...listCwdAncestorNodeModulesDirs(cwd)
|
|
230
|
+
]);
|
|
231
|
+
}
|
|
232
|
+
function discoverProjectRoots(cwd = process.cwd(), options) {
|
|
233
|
+
const roots = discoverNodeModulesDirs(
|
|
234
|
+
cwd,
|
|
235
|
+
options?.nodeModulesDirs ? { candidateDirs: options.nodeModulesDirs } : void 0
|
|
236
|
+
).map((nodeModulesDir) => path2.dirname(nodeModulesDir));
|
|
237
|
+
return uniqueResolvedPathsInOrder2([cwd, ...roots]);
|
|
238
|
+
}
|
|
239
|
+
function unique(values) {
|
|
240
|
+
return [...new Set(values)];
|
|
241
|
+
}
|
|
242
|
+
function pathExists(targetPath) {
|
|
243
|
+
try {
|
|
244
|
+
fs.accessSync(targetPath);
|
|
245
|
+
return true;
|
|
246
|
+
} catch {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function hasAnyDataMarkers(appDir) {
|
|
251
|
+
return pathExists(path2.join(appDir, "SOUL.md")) || pathExists(path2.join(appDir, "WORLD.md"));
|
|
252
|
+
}
|
|
253
|
+
function scoreAppCandidate(appDir) {
|
|
254
|
+
let score = 0;
|
|
255
|
+
if (pathExists(path2.join(appDir, "SOUL.md"))) {
|
|
256
|
+
score += 4;
|
|
257
|
+
}
|
|
258
|
+
if (pathExists(path2.join(appDir, "WORLD.md"))) {
|
|
259
|
+
score += 2;
|
|
260
|
+
}
|
|
261
|
+
if (pathExists(path2.join(appDir, "skills"))) {
|
|
262
|
+
score += 1;
|
|
263
|
+
}
|
|
264
|
+
if (pathExists(path2.join(appDir, "plugins"))) {
|
|
265
|
+
score += 1;
|
|
266
|
+
}
|
|
267
|
+
return score;
|
|
268
|
+
}
|
|
269
|
+
function resolveCandidateAppDirs(cwd, projectRoots) {
|
|
270
|
+
const roots = projectRoots ?? discoverProjectRoots(cwd);
|
|
271
|
+
const resolved = [];
|
|
272
|
+
const seen = /* @__PURE__ */ new Set();
|
|
273
|
+
for (const root of roots) {
|
|
274
|
+
const appDir = path2.resolve(root, "app");
|
|
275
|
+
if (!pathExists(appDir)) {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (seen.has(appDir)) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
seen.add(appDir);
|
|
282
|
+
resolved.push(appDir);
|
|
283
|
+
}
|
|
284
|
+
return resolved;
|
|
285
|
+
}
|
|
286
|
+
function homeDir() {
|
|
287
|
+
return resolveHomeDir();
|
|
288
|
+
}
|
|
289
|
+
function resolveHomeDir(cwd = process.cwd(), options) {
|
|
290
|
+
const resolvedCwd = path2.resolve(cwd);
|
|
291
|
+
const directApp = path2.resolve(resolvedCwd, "app");
|
|
292
|
+
if (pathExists(directApp) && hasAnyDataMarkers(directApp)) {
|
|
293
|
+
return directApp;
|
|
294
|
+
}
|
|
295
|
+
const candidates = resolveCandidateAppDirs(
|
|
296
|
+
resolvedCwd,
|
|
297
|
+
options?.projectRoots
|
|
298
|
+
);
|
|
299
|
+
if (candidates.length === 0) {
|
|
300
|
+
return directApp;
|
|
301
|
+
}
|
|
302
|
+
candidates.sort((left, right) => {
|
|
303
|
+
const leftScore = scoreAppCandidate(left);
|
|
304
|
+
const rightScore = scoreAppCandidate(right);
|
|
305
|
+
if (leftScore !== rightScore) {
|
|
306
|
+
return rightScore - leftScore;
|
|
307
|
+
}
|
|
308
|
+
const leftDistance = path2.relative(resolvedCwd, left).split(path2.sep).length;
|
|
309
|
+
const rightDistance = path2.relative(resolvedCwd, right).split(path2.sep).length;
|
|
310
|
+
if (leftDistance !== rightDistance) {
|
|
311
|
+
return leftDistance - rightDistance;
|
|
312
|
+
}
|
|
313
|
+
return left.localeCompare(right);
|
|
314
|
+
});
|
|
315
|
+
return candidates[0];
|
|
316
|
+
}
|
|
317
|
+
function resolveContentRoots(subdir) {
|
|
318
|
+
if (subdir === "data") {
|
|
319
|
+
return [homeDir()];
|
|
320
|
+
}
|
|
321
|
+
return [path2.join(homeDir(), subdir)];
|
|
322
|
+
}
|
|
323
|
+
function builtInSkillsDir() {
|
|
324
|
+
const moduleDir = path2.dirname(fileURLToPath(import.meta.url));
|
|
325
|
+
if (path2.basename(moduleDir) === "dist") {
|
|
326
|
+
return path2.join(path2.dirname(moduleDir), "skills");
|
|
327
|
+
}
|
|
328
|
+
if (path2.basename(moduleDir) === "chat" && path2.basename(path2.dirname(moduleDir)) === "src") {
|
|
329
|
+
return path2.resolve(moduleDir, "../../skills");
|
|
330
|
+
}
|
|
331
|
+
const packageDir = resolvePackageDir(process.cwd(), "@sentry/junior");
|
|
332
|
+
return path2.join(packageDir ?? moduleDir, "skills");
|
|
333
|
+
}
|
|
334
|
+
function dataDir() {
|
|
335
|
+
return resolveContentRoots("data")[0];
|
|
336
|
+
}
|
|
337
|
+
function soulPath() {
|
|
338
|
+
return path2.join(dataDir(), "SOUL.md");
|
|
339
|
+
}
|
|
340
|
+
function worldPath() {
|
|
341
|
+
return path2.join(dataDir(), "WORLD.md");
|
|
342
|
+
}
|
|
343
|
+
function descriptionPath() {
|
|
344
|
+
return path2.join(dataDir(), "DESCRIPTION.md");
|
|
345
|
+
}
|
|
346
|
+
function skillsDir() {
|
|
347
|
+
return resolveContentRoots("skills")[0];
|
|
348
|
+
}
|
|
349
|
+
function pluginsDir() {
|
|
350
|
+
return resolveContentRoots("plugins")[0];
|
|
351
|
+
}
|
|
352
|
+
function dataRoots() {
|
|
353
|
+
return unique(resolveContentRoots("data"));
|
|
354
|
+
}
|
|
355
|
+
function skillRoots() {
|
|
356
|
+
return unique([builtInSkillsDir(), ...resolveContentRoots("skills")]);
|
|
357
|
+
}
|
|
358
|
+
function pluginRoots() {
|
|
359
|
+
return unique(resolveContentRoots("plugins"));
|
|
360
|
+
}
|
|
361
|
+
function soulPathCandidates() {
|
|
362
|
+
const candidates = dataRoots().map((root) => path2.join(root, "SOUL.md"));
|
|
363
|
+
return unique(candidates);
|
|
364
|
+
}
|
|
365
|
+
function worldPathCandidates() {
|
|
366
|
+
const candidates = dataRoots().map((root) => path2.join(root, "WORLD.md"));
|
|
367
|
+
return unique(candidates);
|
|
368
|
+
}
|
|
369
|
+
function descriptionPathCandidates() {
|
|
370
|
+
const candidates = dataRoots().map(
|
|
371
|
+
(root) => path2.join(root, "DESCRIPTION.md")
|
|
372
|
+
);
|
|
373
|
+
return unique(candidates);
|
|
374
|
+
}
|
|
375
|
+
var RESERVED_APP_FILES = /* @__PURE__ */ new Set([
|
|
376
|
+
"SOUL.md",
|
|
377
|
+
"WORLD.md",
|
|
378
|
+
"DESCRIPTION.md",
|
|
379
|
+
"ABOUT.md"
|
|
380
|
+
]);
|
|
381
|
+
function listReferenceFiles() {
|
|
382
|
+
const appDir = homeDir();
|
|
383
|
+
try {
|
|
384
|
+
const entries = fs.readdirSync(appDir, { withFileTypes: true });
|
|
385
|
+
return entries.filter(
|
|
386
|
+
(entry) => entry.isFile() && entry.name.endsWith(".md") && !RESERVED_APP_FILES.has(entry.name)
|
|
387
|
+
).map((entry) => path2.join(appDir, entry.name)).sort();
|
|
388
|
+
} catch {
|
|
389
|
+
return [];
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export {
|
|
394
|
+
isValidPackageName,
|
|
395
|
+
resolvePackageLocation,
|
|
396
|
+
resolvePackageDir,
|
|
397
|
+
isDirectory2 as isDirectory,
|
|
398
|
+
isFile2 as isFile,
|
|
399
|
+
discoverNodeModulesDirs,
|
|
400
|
+
discoverProjectRoots,
|
|
401
|
+
homeDir,
|
|
402
|
+
resolveHomeDir,
|
|
403
|
+
builtInSkillsDir,
|
|
404
|
+
dataDir,
|
|
405
|
+
soulPath,
|
|
406
|
+
worldPath,
|
|
407
|
+
descriptionPath,
|
|
408
|
+
skillsDir,
|
|
409
|
+
pluginsDir,
|
|
410
|
+
dataRoots,
|
|
411
|
+
skillRoots,
|
|
412
|
+
pluginRoots,
|
|
413
|
+
soulPathCandidates,
|
|
414
|
+
worldPathCandidates,
|
|
415
|
+
descriptionPathCandidates,
|
|
416
|
+
listReferenceFiles
|
|
417
|
+
};
|