@sentry/junior 0.202.0 → 0.204.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-CMyTD4DD.js +17509 -0
- package/dist/agent-hooks-Bbcp9e33.js +4040 -0
- package/dist/agent-runner-DNb1A49M.js +678 -0
- package/dist/api/schema.d.ts +2728 -2639
- package/dist/api/schema.js +4 -169
- package/dist/api.d.ts +23 -17
- package/dist/api.js +3881 -5326
- package/dist/app-B1TOqBI8.d.ts +246 -0
- package/dist/app.d.ts +4 -520
- package/dist/app.js +9522 -11875
- package/dist/auth-pause-state-DosEalIG.js +168 -0
- package/dist/catalog-runtime-BReos-D4.js +7 -0
- package/dist/checkpoint-CNrPyRJN.js +2450 -0
- package/dist/cli/chat.d.ts +20 -0
- package/dist/cli/chat.js +229 -336
- package/dist/cli/check.d.ts +8 -0
- package/dist/cli/check.js +513 -806
- package/dist/cli/env.d.ts +13 -0
- package/dist/cli/env.js +63 -12
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.js +90 -159
- package/dist/cli/main.d.ts +6 -0
- package/dist/cli/main.js +43 -64
- package/dist/cli/plugins.d.ts +13 -0
- package/dist/cli/plugins.js +148 -227
- package/dist/cli/run.d.ts +16 -0
- package/dist/cli/run.js +52 -8
- package/dist/cli/snapshot-create.d.ts +4 -0
- package/dist/cli/snapshot-create.js +71 -125
- package/dist/cli/upgrade.d.ts +15 -0
- package/dist/cli/upgrade.js +232 -335
- package/dist/config-nGCW1OTG.js +941 -0
- package/dist/context-B45_WqVX.js +298 -0
- package/dist/conversation-privacy-B4voFRSm.js +182 -0
- package/dist/conversation-work-C6y3T5Hx.js +51 -0
- package/dist/credential-sync-kXr1hvO1.js +2660 -0
- package/dist/db-BeyXKJOI.d.ts +5 -0
- package/dist/destinations-BeBiJeEM.js +29 -0
- package/dist/execution-stats-DWfSihcH.js +373 -0
- package/dist/executor-DcMSlI5c.js +721 -0
- package/dist/experimental-CIXf7Uye.js +46 -0
- package/dist/history-ClE4toxe.d.ts +32 -0
- package/dist/history-CqTuSAdI.js +441 -0
- package/dist/instrumentation.d.ts +3 -3
- package/dist/instrumentation.js +130 -176
- package/dist/job-queue-Drn_LXlM.js +63 -0
- package/dist/logging-BzAk1S_s.js +1210 -0
- package/dist/model-profile-CZmVoGdX.js +49 -0
- package/dist/nitro.d.ts +31 -36
- package/dist/nitro.js +275 -456
- package/dist/oauth-callback-server-JiftokvA.js +130 -0
- package/dist/oauth-relay-CdCnu80W.js +62 -0
- package/dist/package-discovery-7a9YqLhE.js +455 -0
- package/dist/pending-auth-CWmSdZVg.js +185 -0
- package/dist/plugin-module-BKGOXca2.js +81 -0
- package/dist/plugins-BI9A1vKA.d.ts +95 -0
- package/dist/plugins-egKWjgue.js +99 -0
- package/dist/private-trace-result-BLvBjy_e.js +16 -0
- package/dist/profile-CrT5nXbw.js +861 -0
- package/dist/registry-DH1xUo2N.js +1419 -0
- package/dist/reporting-schema-DosTN__Q.js +105 -0
- package/dist/resolve-CZHnfxaS.js +546 -0
- package/dist/rolldown-runtime-B4FMCO8f.js +28 -0
- package/dist/runner-CZV2sC46.js +392 -0
- package/dist/sandbox-egress-signals-bHZfmhbd.js +46 -0
- package/dist/schema-Rn8-XEaN.js +1140 -0
- package/dist/sentry-CD3SdJl-.js +26 -0
- package/dist/skills-CIcDQSgM.js +316 -0
- package/dist/spawn-DdkUFRmq.js +29 -0
- package/dist/stats-DTUbAb88.js +2634 -0
- package/dist/store-C5qxF2ac.d.ts +208 -0
- package/dist/task-queue-CJIR4RF7.js +136 -0
- package/dist/task-runner-D-O3A-Cp.js +639 -0
- package/dist/thread-state-CRc9jTJS.js +431 -0
- package/dist/turn-execution-BkinIdJF.js +47 -0
- package/dist/turn-lifecycle-DQV19VTW.js +54 -0
- package/dist/usage-D3EbSO7w.js +296 -0
- package/dist/usage-schema-CKaDkH_j.js +20 -0
- package/dist/validation-C2CR-OX3.js +40 -0
- package/dist/vercel-queue-DIkVcfK4.js +167 -0
- package/dist/vercel.d.ts +6 -6
- package/dist/vercel.js +14 -6
- package/dist/version-CnXZ614E.d.ts +5 -0
- package/dist/version-DxcWdoKa.js +8 -0
- package/dist/version.d.ts +2 -4
- package/dist/version.js +2 -6
- package/dist/web-authorization-RMBxAR_t.js +76 -0
- package/dist/web-input-3EPfpf55.js +494 -0
- package/dist/work-fGofI7Op.js +509 -0
- package/dist/worker-CsOLq-mR.js +625 -0
- package/package.json +9 -9
- package/dist/agent-hooks-UXITLYOK.js +0 -51
- package/dist/catalog-runtime-BG3JLLK2.js +0 -14
- package/dist/chunk-2LYHWMR4.js +0 -46
- package/dist/chunk-2MK3QBGA.js +0 -321
- package/dist/chunk-3PGQSKJV.js +0 -692
- package/dist/chunk-3UI3WFTX.js +0 -519
- package/dist/chunk-3Y47VMHV.js +0 -6
- package/dist/chunk-4UO6FK4G.js +0 -64
- package/dist/chunk-5NOPO64K.js +0 -198
- package/dist/chunk-5PKWYPFT.js +0 -2943
- package/dist/chunk-63NKKFJL.js +0 -1228
- package/dist/chunk-6AYH6252.js +0 -787
- package/dist/chunk-6Y5B5PEX.js +0 -80
- package/dist/chunk-7DHZP5KJ.js +0 -333
- package/dist/chunk-7H2VZTWN.js +0 -103
- package/dist/chunk-7NL7T6VU.js +0 -406
- package/dist/chunk-A76OIMYN.js +0 -102
- package/dist/chunk-AWMS3SPP.js +0 -58
- package/dist/chunk-B3LY5RCL.js +0 -229
- package/dist/chunk-BD2KT3OB.js +0 -36
- package/dist/chunk-BXCX5QKA.js +0 -2086
- package/dist/chunk-C6VVF43U.js +0 -81
- package/dist/chunk-CEMMLV5L.js +0 -98
- package/dist/chunk-CM5HNV2W.js +0 -131
- package/dist/chunk-DA2KGZZI.js +0 -13
- package/dist/chunk-DBVY6HLX.js +0 -64
- package/dist/chunk-DIB4GX3G.js +0 -8
- package/dist/chunk-DKIJ2RP5.js +0 -68
- package/dist/chunk-DL2KLKVH.js +0 -931
- package/dist/chunk-DWPN6SCH.js +0 -172
- package/dist/chunk-ELWOYVOY.js +0 -206
- package/dist/chunk-EWT7H65X.js +0 -506
- package/dist/chunk-FA6POGLH.js +0 -70
- package/dist/chunk-HMREVIO2.js +0 -135
- package/dist/chunk-IIWUT4FO.js +0 -820
- package/dist/chunk-JAL3CH4G.js +0 -27
- package/dist/chunk-JSJQEWBJ.js +0 -3295
- package/dist/chunk-KHKKHDLD.js +0 -387
- package/dist/chunk-LA6R4A7Q.js +0 -706
- package/dist/chunk-LOOU2DUR.js +0 -20428
- package/dist/chunk-M6FHWXE3.js +0 -700
- package/dist/chunk-M76HMB7M.js +0 -1856
- package/dist/chunk-MAGNK5J4.js +0 -1520
- package/dist/chunk-MTM5IFCY.js +0 -1190
- package/dist/chunk-N7TMSOZH.js +0 -235
- package/dist/chunk-NHJU2ZAL.js +0 -56
- package/dist/chunk-NSXKRGRT.js +0 -717
- package/dist/chunk-OWMPFXJA.js +0 -1764
- package/dist/chunk-PDO5BLNM.js +0 -22
- package/dist/chunk-PEQXYSSE.js +0 -45
- package/dist/chunk-PW4P4JYF.js +0 -1135
- package/dist/chunk-QB54UQUS.js +0 -320
- package/dist/chunk-QP3OGJXF.js +0 -105
- package/dist/chunk-RC745GGZ.js +0 -122
- package/dist/chunk-REOIRYPR.js +0 -37
- package/dist/chunk-SCOZRLZ4.js +0 -164
- package/dist/chunk-TXJSXBV5.js +0 -1433
- package/dist/chunk-TXKUKMVO.js +0 -417
- package/dist/chunk-U2GPUYAL.js +0 -3656
- package/dist/chunk-UIE3R5XU.js +0 -17
- package/dist/chunk-UXPG6ZIN.js +0 -84
- package/dist/chunk-VFUK3X5B.js +0 -50
- package/dist/chunk-WQSHDTTI.js +0 -1163
- package/dist/chunk-X6GDDWQH.js +0 -60
- package/dist/chunk-Y2CM7HXH.js +0 -111
- package/dist/chunk-Y7X25LFY.js +0 -15
- package/dist/chunk-YDUR3ZYW.js +0 -10
- package/dist/conversation-work-VIOQ5ZF3.js +0 -54
- package/dist/db-3L2MCVRI.js +0 -26
- package/dist/discovery-DWVDM7UK.js +0 -44
- package/dist/experimental-P5FZM4CU.js +0 -12
- package/dist/oauth-callback-server-YVV6C6T2.js +0 -243
- package/dist/oauth-relay-5XPVRPYB.js +0 -8
- package/dist/plugins-YTYJMMJF.js +0 -14
- package/dist/runner-LQ7RETDP.js +0 -522
- package/dist/sandbox-egress-signals-FIL7EGPR.js +0 -73
- package/dist/sentry-MB3NL3IR.js +0 -42
- package/dist/skills-XRWYEDCD.js +0 -27
- package/dist/spawn-RC6SJUAI.js +0 -42
- package/dist/task-runner-7DY7ARYH.js +0 -36
- package/dist/validation-7MNQGCJA.js +0 -17
- package/dist/work-COALHUCG.js +0 -51
- package/dist/worker-6MURZIPD.js +0 -24
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Q as createUserTokenStore } from "./agent-CMyTD4DD.js";
|
|
2
|
+
import { a as GET, n as syncLocalOAuthCredential, r as GET$1 } from "./credential-sync-kXr1hvO1.js";
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
//#region src/chat/local/oauth-callback-server.ts
|
|
5
|
+
const LOCAL_OAUTH_TIMEOUT_MS = 6e5;
|
|
6
|
+
const LOCAL_OAUTH_CALLBACK_TIMEOUT_MS = 6e4;
|
|
7
|
+
function decodeProvider(value) {
|
|
8
|
+
if (!value) return;
|
|
9
|
+
try {
|
|
10
|
+
const provider = decodeURIComponent(value);
|
|
11
|
+
return /^[a-z][a-z0-9-]*$/.test(provider) ? provider : void 0;
|
|
12
|
+
} catch {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Start the loopback callback that completes OAuth in the local CLI process. */
|
|
17
|
+
async function startLocalOAuthCallbackServer(agentRunner) {
|
|
18
|
+
let pendingAuthorization;
|
|
19
|
+
const completeAuthorization = (authorization, result) => {
|
|
20
|
+
if (authorization.settled) return;
|
|
21
|
+
authorization.settled = true;
|
|
22
|
+
clearTimeout(authorization.timeout);
|
|
23
|
+
authorization.finish(result);
|
|
24
|
+
};
|
|
25
|
+
const cancelAuthorization = () => {
|
|
26
|
+
const authorization = pendingAuthorization;
|
|
27
|
+
if (!authorization) return;
|
|
28
|
+
pendingAuthorization = void 0;
|
|
29
|
+
completeAuthorization(authorization, /* @__PURE__ */ new Error("Local OAuth authorization canceled"));
|
|
30
|
+
};
|
|
31
|
+
const server = createServer(async (incoming, outgoing) => {
|
|
32
|
+
const host = incoming.headers.host ?? "127.0.0.1";
|
|
33
|
+
let requestUrl;
|
|
34
|
+
try {
|
|
35
|
+
requestUrl = new URL(incoming.url ?? "/", `http://${host}`);
|
|
36
|
+
} catch {
|
|
37
|
+
outgoing.writeHead(400).end("Invalid callback request");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const mcpMatch = requestUrl.pathname.match(/^\/api\/oauth\/callback\/mcp\/([^/]+)$/);
|
|
41
|
+
const pluginMatch = requestUrl.pathname.match(/^\/api\/oauth\/callback\/([^/]+)$/);
|
|
42
|
+
const provider = decodeProvider(mcpMatch?.[1] ?? pluginMatch?.[1]);
|
|
43
|
+
if (!provider) {
|
|
44
|
+
outgoing.writeHead(404).end("Not found");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const authorization = pendingAuthorization;
|
|
48
|
+
if (!authorization || authorization.callbackStarted || authorization.settled || requestUrl.searchParams.get("state") !== authorization.state) {
|
|
49
|
+
outgoing.writeHead(409).end("No matching authorization request");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
authorization.callbackStarted = true;
|
|
53
|
+
clearTimeout(authorization.timeout);
|
|
54
|
+
authorization.timeout = setTimeout(() => {
|
|
55
|
+
if (!outgoing.headersSent) outgoing.writeHead(504).end("Authorization callback timed out");
|
|
56
|
+
completeAuthorization(authorization, /* @__PURE__ */ new Error("Timed out completing OAuth authorization"));
|
|
57
|
+
}, LOCAL_OAUTH_CALLBACK_TIMEOUT_MS);
|
|
58
|
+
const backgroundTasks = [];
|
|
59
|
+
const waitUntil = (task) => {
|
|
60
|
+
backgroundTasks.push(typeof task === "function" ? Promise.resolve().then(task) : task);
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
const request = new Request(requestUrl, { method: "GET" });
|
|
64
|
+
const response = mcpMatch ? await GET(request, provider, waitUntil, { agentRunner }) : await GET$1(request, provider, waitUntil, { agentRunner });
|
|
65
|
+
const body = Buffer.from(await response.arrayBuffer());
|
|
66
|
+
await Promise.all(backgroundTasks);
|
|
67
|
+
if (response.ok) {
|
|
68
|
+
if (!mcpMatch) {
|
|
69
|
+
const tokens = await createUserTokenStore().get("local-cli", provider);
|
|
70
|
+
if (!tokens) throw new Error(`${provider} authorization completed without a stored credential`);
|
|
71
|
+
await syncLocalOAuthCredential(provider, tokens);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (authorization.settled) return;
|
|
75
|
+
if (response.ok) completeAuthorization(authorization, true);
|
|
76
|
+
else completeAuthorization(authorization, /* @__PURE__ */ new Error(`${provider} authorization callback failed with HTTP ${response.status}`));
|
|
77
|
+
outgoing.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
78
|
+
outgoing.end(body);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
if (!outgoing.headersSent) outgoing.writeHead(500).end("Authorization callback failed");
|
|
81
|
+
completeAuthorization(authorization, error instanceof Error ? error : new Error(String(error)));
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
await new Promise((resolve, reject) => {
|
|
85
|
+
server.once("error", reject);
|
|
86
|
+
server.listen(0, "127.0.0.1", () => {
|
|
87
|
+
server.off("error", reject);
|
|
88
|
+
resolve();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
beginAuthorization: (authorizationUrl) => {
|
|
93
|
+
if (pendingAuthorization) throw new Error("Local OAuth already has an active authorization");
|
|
94
|
+
const state = new URL(authorizationUrl).searchParams.get("state");
|
|
95
|
+
if (!state) throw new Error("Local OAuth authorization URL is missing state");
|
|
96
|
+
let finish = () => void 0;
|
|
97
|
+
const result = new Promise((resolve) => {
|
|
98
|
+
finish = resolve;
|
|
99
|
+
});
|
|
100
|
+
const authorization = {
|
|
101
|
+
callbackStarted: false,
|
|
102
|
+
finish,
|
|
103
|
+
result,
|
|
104
|
+
settled: false,
|
|
105
|
+
state,
|
|
106
|
+
timeout: setTimeout(() => {
|
|
107
|
+
completeAuthorization(authorization, /* @__PURE__ */ new Error("Timed out waiting for OAuth authorization"));
|
|
108
|
+
}, LOCAL_OAUTH_TIMEOUT_MS)
|
|
109
|
+
};
|
|
110
|
+
pendingAuthorization = authorization;
|
|
111
|
+
},
|
|
112
|
+
cancelAuthorization,
|
|
113
|
+
port: server.address().port,
|
|
114
|
+
waitForAuthorization: async () => {
|
|
115
|
+
const authorization = pendingAuthorization;
|
|
116
|
+
if (!authorization) throw new Error("Local OAuth has no active authorization");
|
|
117
|
+
const result = await authorization.result;
|
|
118
|
+
if (pendingAuthorization === authorization) pendingAuthorization = void 0;
|
|
119
|
+
if (result instanceof Error) throw result;
|
|
120
|
+
},
|
|
121
|
+
close: async () => {
|
|
122
|
+
cancelAuthorization();
|
|
123
|
+
await new Promise((resolve, reject) => {
|
|
124
|
+
server.close((error) => error ? reject(error) : resolve());
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
export { startLocalOAuthCallbackServer };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { randomBytes } from "node:crypto";
|
|
4
|
+
import { SignJWT, jwtVerify } from "jose";
|
|
5
|
+
//#region src/chat/local/oauth-relay.ts
|
|
6
|
+
var oauth_relay_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
createLocalOAuthState: () => createLocalOAuthState,
|
|
8
|
+
relayLocalOAuthCallback: () => relayLocalOAuthCallback
|
|
9
|
+
});
|
|
10
|
+
const LOCAL_OAUTH_STATE_PREFIX = "jr-local";
|
|
11
|
+
const LOCAL_OAUTH_TOKEN_CONTEXT = "junior.local-oauth-relay.v1";
|
|
12
|
+
const LOCAL_OAUTH_TOKEN_TTL = "10m";
|
|
13
|
+
const localOAuthRelayPayloadSchema = z.object({
|
|
14
|
+
aud: z.literal(LOCAL_OAUTH_TOKEN_CONTEXT),
|
|
15
|
+
exp: z.number().int(),
|
|
16
|
+
iss: z.literal(LOCAL_OAUTH_TOKEN_CONTEXT),
|
|
17
|
+
jti: z.string().min(1),
|
|
18
|
+
port: z.number().int().min(1).max(65535)
|
|
19
|
+
}).strict();
|
|
20
|
+
/** Derive the HMAC key used only for signed local OAuth relay state. */
|
|
21
|
+
function relayKey() {
|
|
22
|
+
const secret = process.env.JUNIOR_SECRET?.trim();
|
|
23
|
+
if (!secret) throw new Error("Local OAuth requires JUNIOR_SECRET");
|
|
24
|
+
return new TextEncoder().encode(secret);
|
|
25
|
+
}
|
|
26
|
+
/** Create an OAuth state value that can be safely relayed to a local CLI callback. */
|
|
27
|
+
async function createLocalOAuthState(port) {
|
|
28
|
+
if (!Number.isSafeInteger(port) || port < 1 || port > 65535) throw new Error("Local OAuth callback port is invalid");
|
|
29
|
+
const token = await new SignJWT({ port }).setProtectedHeader({ alg: "HS256" }).setIssuer(LOCAL_OAUTH_TOKEN_CONTEXT).setAudience(LOCAL_OAUTH_TOKEN_CONTEXT).setJti(randomBytes(24).toString("base64url")).setExpirationTime(LOCAL_OAUTH_TOKEN_TTL).sign(relayKey());
|
|
30
|
+
return `${LOCAL_OAUTH_STATE_PREFIX}.${token}`;
|
|
31
|
+
}
|
|
32
|
+
/** Resolve a signed local OAuth state to its loopback callback port. */
|
|
33
|
+
async function localOAuthRelayPort(state) {
|
|
34
|
+
const prefix = `${LOCAL_OAUTH_STATE_PREFIX}.`;
|
|
35
|
+
if (!state.startsWith(prefix)) return;
|
|
36
|
+
try {
|
|
37
|
+
const { payload } = await jwtVerify(state.slice(prefix.length), relayKey(), {
|
|
38
|
+
algorithms: ["HS256"],
|
|
39
|
+
issuer: LOCAL_OAUTH_TOKEN_CONTEXT,
|
|
40
|
+
audience: LOCAL_OAUTH_TOKEN_CONTEXT
|
|
41
|
+
});
|
|
42
|
+
const parsed = localOAuthRelayPayloadSchema.safeParse(payload);
|
|
43
|
+
return parsed.success ? parsed.data.port : void 0;
|
|
44
|
+
} catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Redirect a provider callback from the public dev URL to the owning local CLI. */
|
|
49
|
+
async function relayLocalOAuthCallback(request) {
|
|
50
|
+
const url = new URL(request.url);
|
|
51
|
+
if (url.searchParams.get("jr_local_relay") === "complete") return;
|
|
52
|
+
const state = url.searchParams.get("state");
|
|
53
|
+
const port = state ? await localOAuthRelayPort(state) : void 0;
|
|
54
|
+
if (!port) return;
|
|
55
|
+
url.protocol = "http:";
|
|
56
|
+
url.hostname = "127.0.0.1";
|
|
57
|
+
url.port = String(port);
|
|
58
|
+
url.searchParams.set("jr_local_relay", "complete");
|
|
59
|
+
return Response.redirect(url, 302);
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { relayLocalOAuthCallback as n, oauth_relay_exports as t };
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import fs, { statSync } from "node:fs";
|
|
6
|
+
//#region src/package-resolution.ts
|
|
7
|
+
function isDirectory$1(targetPath) {
|
|
8
|
+
try {
|
|
9
|
+
return statSync(targetPath).isDirectory();
|
|
10
|
+
} catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function isFile$1(targetPath) {
|
|
15
|
+
try {
|
|
16
|
+
return statSync(targetPath).isFile();
|
|
17
|
+
} catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function uniqueResolvedPathsInOrder$1(values) {
|
|
22
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23
|
+
const resolved = [];
|
|
24
|
+
for (const value of values) {
|
|
25
|
+
const normalized = path.resolve(value);
|
|
26
|
+
if (seen.has(normalized)) continue;
|
|
27
|
+
seen.add(normalized);
|
|
28
|
+
resolved.push(normalized);
|
|
29
|
+
}
|
|
30
|
+
return resolved;
|
|
31
|
+
}
|
|
32
|
+
function ancestorNodeModulesDirs(cwd) {
|
|
33
|
+
const dirs = [];
|
|
34
|
+
let current = path.resolve(cwd);
|
|
35
|
+
while (true) {
|
|
36
|
+
const nodeModulesDir = path.join(current, "node_modules");
|
|
37
|
+
if (isDirectory$1(nodeModulesDir)) dirs.push(nodeModulesDir);
|
|
38
|
+
const parent = path.dirname(current);
|
|
39
|
+
if (parent === current) break;
|
|
40
|
+
current = parent;
|
|
41
|
+
}
|
|
42
|
+
return dirs;
|
|
43
|
+
}
|
|
44
|
+
function packageDirInNodeModules(nodeModulesDir, packageName) {
|
|
45
|
+
const packageDir = path.join(nodeModulesDir, ...packageName.split("/"));
|
|
46
|
+
return isDirectory$1(packageDir) ? path.resolve(packageDir) : void 0;
|
|
47
|
+
}
|
|
48
|
+
function isValidPackageSegment(segment) {
|
|
49
|
+
return Boolean(segment) && segment !== "." && segment !== ".." && !segment.startsWith(".") && /^[A-Za-z0-9._~-]+$/.test(segment);
|
|
50
|
+
}
|
|
51
|
+
/** Return whether a string is shaped like an npm package name. */
|
|
52
|
+
function isValidPackageName(packageName) {
|
|
53
|
+
if (!packageName || packageName.includes("\\") || path.isAbsolute(packageName)) return false;
|
|
54
|
+
const parts = packageName.split("/");
|
|
55
|
+
if (parts[0].startsWith("@")) return parts.length === 2 && parts[0].length > 1 && isValidPackageSegment(parts[0].slice(1)) && isValidPackageSegment(parts[1]);
|
|
56
|
+
return parts.length === 1 && isValidPackageSegment(parts[0]);
|
|
57
|
+
}
|
|
58
|
+
function findPackageRoot(entryPath) {
|
|
59
|
+
let dir = path.dirname(entryPath);
|
|
60
|
+
while (dir !== path.dirname(dir)) {
|
|
61
|
+
if (isFile$1(path.join(dir, "package.json"))) return path.resolve(dir);
|
|
62
|
+
dir = path.dirname(dir);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function findPackageNodeModulesDir(packageDir, packageName) {
|
|
66
|
+
const parts = path.resolve(packageDir).split(path.sep);
|
|
67
|
+
const packageParts = packageName.split("/");
|
|
68
|
+
for (let index = parts.length - 1; index >= 0; index -= 1) {
|
|
69
|
+
if (parts[index] !== "node_modules") continue;
|
|
70
|
+
if (parts.slice(index + 1, index + 1 + packageParts.length).join("/") !== packageParts.join("/")) continue;
|
|
71
|
+
return path.resolve(parts.slice(0, index + 1).join(path.sep) || path.sep);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function resolvePackageWithNode(cwd, packageName) {
|
|
75
|
+
let requireFromCwd;
|
|
76
|
+
try {
|
|
77
|
+
requireFromCwd = createRequire(path.join(cwd, "package.json"));
|
|
78
|
+
} catch {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
for (const specifier of [`${packageName}/package.json`, packageName]) try {
|
|
82
|
+
const resolved = requireFromCwd.resolve(specifier);
|
|
83
|
+
const dir = specifier.endsWith("/package.json") ? path.dirname(resolved) : findPackageRoot(resolved);
|
|
84
|
+
if (!dir) continue;
|
|
85
|
+
const nodeModulesDir = findPackageNodeModulesDir(dir, packageName);
|
|
86
|
+
return {
|
|
87
|
+
dir,
|
|
88
|
+
...nodeModulesDir ? { nodeModulesDir } : void 0
|
|
89
|
+
};
|
|
90
|
+
} catch {}
|
|
91
|
+
}
|
|
92
|
+
/** Resolve a package root from an app cwd without requiring the package to expose a JS entry point. */
|
|
93
|
+
function resolvePackageLocation(cwd, packageName, options) {
|
|
94
|
+
if (!isValidPackageName(packageName)) return;
|
|
95
|
+
const nodeModulesDirs = uniqueResolvedPathsInOrder$1([...options?.nodeModulesDirs ?? [], ...ancestorNodeModulesDirs(cwd)]);
|
|
96
|
+
for (const nodeModulesDir of nodeModulesDirs) {
|
|
97
|
+
const dir = packageDirInNodeModules(nodeModulesDir, packageName);
|
|
98
|
+
if (dir) return {
|
|
99
|
+
dir,
|
|
100
|
+
nodeModulesDir
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return resolvePackageWithNode(cwd, packageName);
|
|
104
|
+
}
|
|
105
|
+
/** Resolve a package root directory from an app cwd. */
|
|
106
|
+
function resolvePackageDir(cwd, packageName) {
|
|
107
|
+
return resolvePackageLocation(cwd, packageName)?.dir;
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/chat/discovery.ts
|
|
111
|
+
var discovery_exports = /* @__PURE__ */ __exportAll({
|
|
112
|
+
builtInSkillsDir: () => builtInSkillsDir,
|
|
113
|
+
dataDir: () => dataDir,
|
|
114
|
+
dataRoots: () => dataRoots,
|
|
115
|
+
descriptionPath: () => descriptionPath,
|
|
116
|
+
descriptionPathCandidates: () => descriptionPathCandidates,
|
|
117
|
+
discoverNodeModulesDirs: () => discoverNodeModulesDirs,
|
|
118
|
+
discoverProjectRoots: () => discoverProjectRoots,
|
|
119
|
+
homeDir: () => homeDir,
|
|
120
|
+
isDirectory: () => isDirectory,
|
|
121
|
+
isFile: () => isFile,
|
|
122
|
+
listReferenceFiles: () => listReferenceFiles,
|
|
123
|
+
pluginRoots: () => pluginRoots,
|
|
124
|
+
pluginsDir: () => pluginsDir,
|
|
125
|
+
resolveHomeDir: () => resolveHomeDir,
|
|
126
|
+
skillRoots: () => skillRoots,
|
|
127
|
+
skillsDir: () => skillsDir,
|
|
128
|
+
soulPath: () => soulPath,
|
|
129
|
+
soulPathCandidates: () => soulPathCandidates,
|
|
130
|
+
worldPath: () => worldPath,
|
|
131
|
+
worldPathCandidates: () => worldPathCandidates
|
|
132
|
+
});
|
|
133
|
+
/** Check whether a path exists and is a directory. */
|
|
134
|
+
function isDirectory(targetPath) {
|
|
135
|
+
try {
|
|
136
|
+
return statSync(targetPath).isDirectory();
|
|
137
|
+
} catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** Check whether a path exists and is a regular file. */
|
|
142
|
+
function isFile(targetPath) {
|
|
143
|
+
try {
|
|
144
|
+
return statSync(targetPath).isFile();
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function normalizePath(targetPath) {
|
|
150
|
+
return path.resolve(targetPath);
|
|
151
|
+
}
|
|
152
|
+
function uniqueResolvedPathsInOrder(values) {
|
|
153
|
+
const seen = /* @__PURE__ */ new Set();
|
|
154
|
+
const resolved = [];
|
|
155
|
+
for (const value of values) {
|
|
156
|
+
const normalized = normalizePath(value);
|
|
157
|
+
if (seen.has(normalized)) continue;
|
|
158
|
+
seen.add(normalized);
|
|
159
|
+
resolved.push(normalized);
|
|
160
|
+
}
|
|
161
|
+
return resolved;
|
|
162
|
+
}
|
|
163
|
+
function isNodeModulesPath(candidatePath) {
|
|
164
|
+
return path.basename(candidatePath) === "node_modules";
|
|
165
|
+
}
|
|
166
|
+
function isInsidePnpmStore(candidatePath) {
|
|
167
|
+
return candidatePath.split(path.sep).includes(".pnpm");
|
|
168
|
+
}
|
|
169
|
+
function runningFromInstalledPackage() {
|
|
170
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
171
|
+
const marker = `${path.sep}node_modules${path.sep}@sentry${path.sep}junior${path.sep}`;
|
|
172
|
+
return currentFile.includes(marker);
|
|
173
|
+
}
|
|
174
|
+
function listInstalledPackageNodeModulesDirs() {
|
|
175
|
+
if (!runningFromInstalledPackage()) return [];
|
|
176
|
+
const dirs = [];
|
|
177
|
+
let current = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
|
|
178
|
+
while (true) {
|
|
179
|
+
if (isNodeModulesPath(current) && !isInsidePnpmStore(current) && isDirectory(current)) dirs.push(current);
|
|
180
|
+
const parent = path.dirname(current);
|
|
181
|
+
if (parent === current) break;
|
|
182
|
+
current = parent;
|
|
183
|
+
}
|
|
184
|
+
return dirs;
|
|
185
|
+
}
|
|
186
|
+
function listCwdAncestorNodeModulesDirs(cwd) {
|
|
187
|
+
const resolvedCwd = normalizePath(cwd);
|
|
188
|
+
const dirs = [];
|
|
189
|
+
let current = resolvedCwd;
|
|
190
|
+
while (true) {
|
|
191
|
+
const nodeModulesDir = path.join(current, "node_modules");
|
|
192
|
+
if (isDirectory(nodeModulesDir)) dirs.push(nodeModulesDir);
|
|
193
|
+
if (isFile(path.join(current, "package.json"))) break;
|
|
194
|
+
const parent = path.dirname(current);
|
|
195
|
+
if (parent === current) break;
|
|
196
|
+
current = parent;
|
|
197
|
+
}
|
|
198
|
+
return dirs;
|
|
199
|
+
}
|
|
200
|
+
/** Discover node_modules directories reachable from the current working directory. */
|
|
201
|
+
function discoverNodeModulesDirs(cwd = process.cwd(), options) {
|
|
202
|
+
const explicit = options?.candidateDirs?.filter((dir) => isDirectory(dir)) ?? [];
|
|
203
|
+
if (explicit.length > 0) return uniqueResolvedPathsInOrder(explicit);
|
|
204
|
+
return uniqueResolvedPathsInOrder([...listInstalledPackageNodeModulesDirs(), ...listCwdAncestorNodeModulesDirs(cwd)]);
|
|
205
|
+
}
|
|
206
|
+
/** Discover project root directories by walking up from cwd and checking node_modules parents. */
|
|
207
|
+
function discoverProjectRoots(cwd = process.cwd(), options) {
|
|
208
|
+
return uniqueResolvedPathsInOrder([cwd, ...discoverNodeModulesDirs(cwd, options?.nodeModulesDirs ? { candidateDirs: options.nodeModulesDirs } : void 0).map((nodeModulesDir) => path.dirname(nodeModulesDir))]);
|
|
209
|
+
}
|
|
210
|
+
function unique(values) {
|
|
211
|
+
return [...new Set(values)];
|
|
212
|
+
}
|
|
213
|
+
function pathExists(targetPath) {
|
|
214
|
+
try {
|
|
215
|
+
fs.accessSync(targetPath);
|
|
216
|
+
return true;
|
|
217
|
+
} catch {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function hasAnyDataMarkers(appDir) {
|
|
222
|
+
return pathExists(path.join(appDir, "SOUL.md")) || pathExists(path.join(appDir, "WORLD.md"));
|
|
223
|
+
}
|
|
224
|
+
function scoreAppCandidate(appDir) {
|
|
225
|
+
let score = 0;
|
|
226
|
+
if (pathExists(path.join(appDir, "SOUL.md"))) score += 4;
|
|
227
|
+
if (pathExists(path.join(appDir, "WORLD.md"))) score += 2;
|
|
228
|
+
if (pathExists(path.join(appDir, "skills"))) score += 1;
|
|
229
|
+
if (pathExists(path.join(appDir, "plugins"))) score += 1;
|
|
230
|
+
return score;
|
|
231
|
+
}
|
|
232
|
+
function resolveCandidateAppDirs(cwd, projectRoots) {
|
|
233
|
+
const roots = projectRoots ?? discoverProjectRoots(cwd);
|
|
234
|
+
const resolved = [];
|
|
235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
236
|
+
for (const root of roots) {
|
|
237
|
+
const appDir = path.resolve(root, "app");
|
|
238
|
+
if (!pathExists(appDir)) continue;
|
|
239
|
+
if (seen.has(appDir)) continue;
|
|
240
|
+
seen.add(appDir);
|
|
241
|
+
resolved.push(appDir);
|
|
242
|
+
}
|
|
243
|
+
return resolved;
|
|
244
|
+
}
|
|
245
|
+
/** Return the resolved app home directory for the current working directory. */
|
|
246
|
+
function homeDir() {
|
|
247
|
+
return resolveHomeDir();
|
|
248
|
+
}
|
|
249
|
+
/** Resolve the app home directory by scoring candidate `app/` directories. */
|
|
250
|
+
function resolveHomeDir(cwd = process.cwd(), options) {
|
|
251
|
+
const resolvedCwd = path.resolve(cwd);
|
|
252
|
+
const directApp = path.resolve(resolvedCwd, "app");
|
|
253
|
+
if (pathExists(directApp) && hasAnyDataMarkers(directApp)) return directApp;
|
|
254
|
+
const candidates = resolveCandidateAppDirs(resolvedCwd, options?.projectRoots);
|
|
255
|
+
if (candidates.length === 0) return directApp;
|
|
256
|
+
candidates.sort((left, right) => {
|
|
257
|
+
const leftScore = scoreAppCandidate(left);
|
|
258
|
+
const rightScore = scoreAppCandidate(right);
|
|
259
|
+
if (leftScore !== rightScore) return rightScore - leftScore;
|
|
260
|
+
const leftDistance = path.relative(resolvedCwd, left).split(path.sep).length;
|
|
261
|
+
const rightDistance = path.relative(resolvedCwd, right).split(path.sep).length;
|
|
262
|
+
if (leftDistance !== rightDistance) return leftDistance - rightDistance;
|
|
263
|
+
return left.localeCompare(right);
|
|
264
|
+
});
|
|
265
|
+
return candidates[0];
|
|
266
|
+
}
|
|
267
|
+
function resolveContentRoots(subdir) {
|
|
268
|
+
if (subdir === "data") return [homeDir()];
|
|
269
|
+
return [path.join(homeDir(), subdir)];
|
|
270
|
+
}
|
|
271
|
+
/** Return the built-in skills directory in source and packaged builds. */
|
|
272
|
+
function builtInSkillsDir() {
|
|
273
|
+
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
274
|
+
if (path.basename(moduleDir) === "dist") return path.join(path.dirname(moduleDir), "skills");
|
|
275
|
+
if (path.basename(moduleDir) === "chat" && path.basename(path.dirname(moduleDir)) === "src") return path.resolve(moduleDir, "../../skills");
|
|
276
|
+
const packageDir = resolvePackageDir(process.cwd(), "@sentry/junior");
|
|
277
|
+
return path.join(packageDir ?? moduleDir, "skills");
|
|
278
|
+
}
|
|
279
|
+
/** Return the data directory (same as homeDir). */
|
|
280
|
+
function dataDir() {
|
|
281
|
+
return resolveContentRoots("data")[0];
|
|
282
|
+
}
|
|
283
|
+
/** Return the path to the SOUL.md file. */
|
|
284
|
+
function soulPath() {
|
|
285
|
+
return path.join(dataDir(), "SOUL.md");
|
|
286
|
+
}
|
|
287
|
+
/** Return the path to the WORLD.md file. */
|
|
288
|
+
function worldPath() {
|
|
289
|
+
return path.join(dataDir(), "WORLD.md");
|
|
290
|
+
}
|
|
291
|
+
/** Return the path to the DESCRIPTION.md file. */
|
|
292
|
+
function descriptionPath() {
|
|
293
|
+
return path.join(dataDir(), "DESCRIPTION.md");
|
|
294
|
+
}
|
|
295
|
+
/** Return the skills directory path. */
|
|
296
|
+
function skillsDir() {
|
|
297
|
+
return resolveContentRoots("skills")[0];
|
|
298
|
+
}
|
|
299
|
+
/** Return the plugins directory path. */
|
|
300
|
+
function pluginsDir() {
|
|
301
|
+
return resolveContentRoots("plugins")[0];
|
|
302
|
+
}
|
|
303
|
+
/** Return all unique data root directories. */
|
|
304
|
+
function dataRoots() {
|
|
305
|
+
return unique(resolveContentRoots("data"));
|
|
306
|
+
}
|
|
307
|
+
/** Return all unique skill root directories. */
|
|
308
|
+
function skillRoots() {
|
|
309
|
+
return unique([builtInSkillsDir(), ...resolveContentRoots("skills")]);
|
|
310
|
+
}
|
|
311
|
+
/** Return all unique plugin root directories. */
|
|
312
|
+
function pluginRoots() {
|
|
313
|
+
return unique(resolveContentRoots("plugins"));
|
|
314
|
+
}
|
|
315
|
+
/** Return candidate paths where SOUL.md might be found. */
|
|
316
|
+
function soulPathCandidates() {
|
|
317
|
+
return unique(dataRoots().map((root) => path.join(root, "SOUL.md")));
|
|
318
|
+
}
|
|
319
|
+
/** Return candidate paths where WORLD.md might be found. */
|
|
320
|
+
function worldPathCandidates() {
|
|
321
|
+
return unique(dataRoots().map((root) => path.join(root, "WORLD.md")));
|
|
322
|
+
}
|
|
323
|
+
/** Return candidate paths where DESCRIPTION.md might be found. */
|
|
324
|
+
function descriptionPathCandidates() {
|
|
325
|
+
return unique(dataRoots().map((root) => path.join(root, "DESCRIPTION.md")));
|
|
326
|
+
}
|
|
327
|
+
const RESERVED_APP_FILES = /* @__PURE__ */ new Set([
|
|
328
|
+
"SOUL.md",
|
|
329
|
+
"WORLD.md",
|
|
330
|
+
"DESCRIPTION.md",
|
|
331
|
+
"ABOUT.md"
|
|
332
|
+
]);
|
|
333
|
+
/** List non-reserved .md files in the app root for sandbox reference syncing. */
|
|
334
|
+
function listReferenceFiles() {
|
|
335
|
+
const appDir = homeDir();
|
|
336
|
+
try {
|
|
337
|
+
return fs.readdirSync(appDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md") && !RESERVED_APP_FILES.has(entry.name)).map((entry) => path.join(appDir, entry.name)).sort();
|
|
338
|
+
} catch {
|
|
339
|
+
return [];
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region src/chat/plugins/package-discovery.ts
|
|
344
|
+
function normalizeForGlob(targetPath) {
|
|
345
|
+
return targetPath.split(path.sep).join("/");
|
|
346
|
+
}
|
|
347
|
+
function uniqueStringsInOrder(values) {
|
|
348
|
+
const seen = /* @__PURE__ */ new Set();
|
|
349
|
+
const resolved = [];
|
|
350
|
+
for (const value of values) {
|
|
351
|
+
if (seen.has(value)) continue;
|
|
352
|
+
seen.add(value);
|
|
353
|
+
resolved.push(value);
|
|
354
|
+
}
|
|
355
|
+
return resolved;
|
|
356
|
+
}
|
|
357
|
+
function pathForTracingInclude(cwd, targetPath) {
|
|
358
|
+
const relative = path.relative(cwd, targetPath);
|
|
359
|
+
if (!relative || path.isAbsolute(relative) || relative === ".." || relative.startsWith(`..${path.sep}`)) return null;
|
|
360
|
+
const normalized = normalizeForGlob(relative);
|
|
361
|
+
return normalized.startsWith(".") ? normalized : `./${normalized}`;
|
|
362
|
+
}
|
|
363
|
+
/** Normalize and validate configured plugin package names. */
|
|
364
|
+
function normalizePluginPackageNames(packageNames) {
|
|
365
|
+
if (packageNames === void 0) return [];
|
|
366
|
+
if (!Array.isArray(packageNames)) throw new Error("Plugin package names must be an array");
|
|
367
|
+
const normalized = [];
|
|
368
|
+
const seen = /* @__PURE__ */ new Set();
|
|
369
|
+
for (const packageName of packageNames) {
|
|
370
|
+
const normalizedPackageName = typeof packageName === "string" ? packageName.trim() : "";
|
|
371
|
+
if (!normalizedPackageName || !isValidPackageName(normalizedPackageName)) throw new Error("Plugin package names must be valid npm package names");
|
|
372
|
+
if (seen.has(normalizedPackageName)) continue;
|
|
373
|
+
seen.add(normalizedPackageName);
|
|
374
|
+
normalized.push(normalizedPackageName);
|
|
375
|
+
}
|
|
376
|
+
return normalized;
|
|
377
|
+
}
|
|
378
|
+
function formatNodeModulesDirs(candidateNodeModulesDirs) {
|
|
379
|
+
return candidateNodeModulesDirs.length > 0 ? candidateNodeModulesDirs.join(", ") : "none found";
|
|
380
|
+
}
|
|
381
|
+
function resolvePackageDirFromName(cwd, packageName, candidateNodeModulesDirs) {
|
|
382
|
+
return resolvePackageLocation(cwd, packageName, { nodeModulesDirs: candidateNodeModulesDirs }) ?? null;
|
|
383
|
+
}
|
|
384
|
+
function readPluginPackageFlags(dir) {
|
|
385
|
+
const hasRootPluginManifest = isFile(path.join(dir, "plugin.yaml"));
|
|
386
|
+
const hasMigrationsDir = isDirectory(path.join(dir, "migrations"));
|
|
387
|
+
const hasPluginsDir = isDirectory(path.join(dir, "plugins"));
|
|
388
|
+
const hasSkillsDir = isDirectory(path.join(dir, "skills"));
|
|
389
|
+
if (!hasRootPluginManifest && !hasMigrationsDir && !hasPluginsDir && !hasSkillsDir) return null;
|
|
390
|
+
return {
|
|
391
|
+
hasRootPluginManifest,
|
|
392
|
+
hasMigrationsDir,
|
|
393
|
+
hasPluginsDir,
|
|
394
|
+
hasSkillsDir
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function discoverDeclaredPackages(packageNames, candidateNodeModulesDirs, cwd) {
|
|
398
|
+
const discovered = [];
|
|
399
|
+
const seenPackageDirs = /* @__PURE__ */ new Set();
|
|
400
|
+
for (const packageName of packageNames) {
|
|
401
|
+
const resolved = resolvePackageDirFromName(cwd, packageName, candidateNodeModulesDirs);
|
|
402
|
+
if (!resolved) throw new Error(`Plugin package "${packageName}" was configured but could not be resolved from node_modules or package resolution (${formatNodeModulesDirs(candidateNodeModulesDirs)})`);
|
|
403
|
+
if (seenPackageDirs.has(resolved.dir)) continue;
|
|
404
|
+
const pluginFlags = readPluginPackageFlags(resolved.dir);
|
|
405
|
+
if (!pluginFlags) throw new Error(`Plugin package "${packageName}" was configured but does not contain plugin content; expected plugin.yaml, migrations/, plugins/, or skills/ in ${resolved.dir}`);
|
|
406
|
+
seenPackageDirs.add(resolved.dir);
|
|
407
|
+
discovered.push({
|
|
408
|
+
dir: resolved.dir,
|
|
409
|
+
nodeModulesDir: resolved.nodeModulesDir,
|
|
410
|
+
packageName,
|
|
411
|
+
...pluginFlags
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
return discovered;
|
|
415
|
+
}
|
|
416
|
+
/** Discover plugin package content from explicitly declared package names. */
|
|
417
|
+
function discoverInstalledPluginPackageContent(cwd = process.cwd(), options) {
|
|
418
|
+
const resolvedCwd = path.resolve(cwd);
|
|
419
|
+
const discoveredPackages = discoverDeclaredPackages(normalizePluginPackageNames(options?.packageNames), options?.nodeModulesDirs ?? discoverNodeModulesDirs(resolvedCwd), resolvedCwd);
|
|
420
|
+
const manifestRoots = [];
|
|
421
|
+
const skillRoots = [];
|
|
422
|
+
const tracingIncludes = [];
|
|
423
|
+
for (const pkg of discoveredPackages) {
|
|
424
|
+
const tracingBasePath = pkg.nodeModulesDir ? pathForTracingInclude(resolvedCwd, path.join(pkg.nodeModulesDir, ...pkg.packageName.split("/"))) : pathForTracingInclude(resolvedCwd, pkg.dir);
|
|
425
|
+
if (pkg.hasRootPluginManifest) {
|
|
426
|
+
manifestRoots.push(pkg.dir);
|
|
427
|
+
if (tracingBasePath) tracingIncludes.push(`${tracingBasePath}/plugin.yaml`);
|
|
428
|
+
}
|
|
429
|
+
if (pkg.hasMigrationsDir) {
|
|
430
|
+
if (tracingBasePath) tracingIncludes.push(`${tracingBasePath}/migrations/**/*`);
|
|
431
|
+
}
|
|
432
|
+
if (pkg.hasPluginsDir) {
|
|
433
|
+
manifestRoots.push(path.join(pkg.dir, "plugins"));
|
|
434
|
+
if (tracingBasePath) tracingIncludes.push(`${tracingBasePath}/plugins/**/*`);
|
|
435
|
+
}
|
|
436
|
+
if (pkg.hasSkillsDir) {
|
|
437
|
+
skillRoots.push(path.join(pkg.dir, "skills"));
|
|
438
|
+
if (tracingBasePath) tracingIncludes.push(`${tracingBasePath}/skills/**/*`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
packageNames: uniqueStringsInOrder(discoveredPackages.map((pkg) => pkg.packageName)),
|
|
443
|
+
packages: discoveredPackages.map((pkg) => ({
|
|
444
|
+
dir: pkg.dir,
|
|
445
|
+
hasMigrationsDir: pkg.hasMigrationsDir,
|
|
446
|
+
hasSkillsDir: pkg.hasSkillsDir,
|
|
447
|
+
packageName: pkg.packageName
|
|
448
|
+
})),
|
|
449
|
+
manifestRoots: uniqueStringsInOrder(manifestRoots),
|
|
450
|
+
skillRoots: uniqueStringsInOrder(skillRoots),
|
|
451
|
+
tracingIncludes: uniqueStringsInOrder(tracingIncludes)
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
//#endregion
|
|
455
|
+
export { listReferenceFiles as a, soulPathCandidates as c, resolvePackageDir as d, homeDir as i, worldPathCandidates as l, normalizePluginPackageNames as n, pluginRoots as o, discovery_exports as r, skillRoots as s, discoverInstalledPluginPackageContent as t, isValidPackageName as u };
|