@sentry/junior 0.203.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 +8 -8
- package/dist/agent-hooks-GB2VPTNA.js +0 -51
- package/dist/catalog-runtime-UBLIWD3O.js +0 -14
- package/dist/chunk-2LYHWMR4.js +0 -46
- package/dist/chunk-352OWAZH.js +0 -320
- package/dist/chunk-3Y47VMHV.js +0 -6
- package/dist/chunk-3YJSKOWF.js +0 -164
- package/dist/chunk-4KSSKTQ5.js +0 -229
- package/dist/chunk-4UO6FK4G.js +0 -64
- package/dist/chunk-5AHX53NQ.js +0 -717
- package/dist/chunk-5J3E5FWA.js +0 -700
- package/dist/chunk-5PDAG6O3.js +0 -206
- package/dist/chunk-6Y5B5PEX.js +0 -80
- package/dist/chunk-7GWQ5S5R.js +0 -2086
- package/dist/chunk-7H2VZTWN.js +0 -103
- package/dist/chunk-7NL7T6VU.js +0 -406
- package/dist/chunk-A5L27LE4.js +0 -387
- package/dist/chunk-ADIAWL34.js +0 -81
- package/dist/chunk-ASTEMBKJ.js +0 -519
- package/dist/chunk-CEMMLV5L.js +0 -98
- package/dist/chunk-CM5HNV2W.js +0 -131
- package/dist/chunk-CRTRBBRI.js +0 -105
- package/dist/chunk-DA2KGZZI.js +0 -13
- package/dist/chunk-DIB4GX3G.js +0 -8
- package/dist/chunk-DKIJ2RP5.js +0 -68
- package/dist/chunk-DWPN6SCH.js +0 -172
- package/dist/chunk-EDKUFGPL.js +0 -64
- package/dist/chunk-ENY6SKIU.js +0 -1228
- package/dist/chunk-F4MGCZOX.js +0 -2943
- package/dist/chunk-FA6POGLH.js +0 -70
- package/dist/chunk-FSUR7GTG.js +0 -20475
- package/dist/chunk-GKEOHJL5.js +0 -1856
- package/dist/chunk-GMCB6W5Y.js +0 -333
- package/dist/chunk-IE2VPG7O.js +0 -1135
- package/dist/chunk-IZ5B5IHQ.js +0 -3656
- package/dist/chunk-JAL3CH4G.js +0 -27
- package/dist/chunk-KIIEUXD3.js +0 -1764
- package/dist/chunk-KXU4NIL7.js +0 -692
- package/dist/chunk-MTM5IFCY.js +0 -1190
- package/dist/chunk-N7TMSOZH.js +0 -235
- package/dist/chunk-NCEBK6PH.js +0 -36
- package/dist/chunk-NHJU2ZAL.js +0 -56
- package/dist/chunk-P6KTRNVC.js +0 -321
- package/dist/chunk-PDO5BLNM.js +0 -22
- package/dist/chunk-PDRNLLFT.js +0 -3295
- package/dist/chunk-PEQXYSSE.js +0 -45
- package/dist/chunk-PKEX2AQX.js +0 -198
- package/dist/chunk-PSJCGIGO.js +0 -1163
- package/dist/chunk-PZUSUL55.js +0 -506
- package/dist/chunk-R45M4TUS.js +0 -37
- package/dist/chunk-RC745GGZ.js +0 -122
- package/dist/chunk-SP3QKZXJ.js +0 -820
- package/dist/chunk-TXKUKMVO.js +0 -417
- package/dist/chunk-UE4GPWSD.js +0 -931
- package/dist/chunk-UIE3R5XU.js +0 -17
- package/dist/chunk-UXPG6ZIN.js +0 -84
- package/dist/chunk-VFUK3X5B.js +0 -50
- package/dist/chunk-VNMJWREK.js +0 -787
- package/dist/chunk-VZ7CSOX2.js +0 -706
- package/dist/chunk-WCNQJKFT.js +0 -10
- package/dist/chunk-WDZR3QQM.js +0 -135
- package/dist/chunk-WLYVJCHV.js +0 -1433
- package/dist/chunk-WS7NAFTM.js +0 -1520
- package/dist/chunk-X6GDDWQH.js +0 -60
- package/dist/chunk-XPDEYNQI.js +0 -102
- package/dist/chunk-XRW44VGM.js +0 -58
- package/dist/chunk-Y2CM7HXH.js +0 -111
- package/dist/chunk-Y7X25LFY.js +0 -15
- package/dist/conversation-work-VIOQ5ZF3.js +0 -54
- package/dist/db-NGDJV7YH.js +0 -26
- package/dist/discovery-DWVDM7UK.js +0 -44
- package/dist/experimental-P5FZM4CU.js +0 -12
- package/dist/oauth-callback-server-YFY7YEGK.js +0 -243
- package/dist/oauth-relay-5XPVRPYB.js +0 -8
- package/dist/plugins-YTYJMMJF.js +0 -14
- package/dist/runner-ORTNSB2Q.js +0 -522
- package/dist/sandbox-egress-signals-FIL7EGPR.js +0 -73
- package/dist/sentry-MB3NL3IR.js +0 -42
- package/dist/skills-H376WQOH.js +0 -27
- package/dist/spawn-T43WHLOS.js +0 -42
- package/dist/task-runner-LBZWF32V.js +0 -36
- package/dist/validation-REJLRKI6.js +0 -17
- package/dist/work-3KJ3RE76.js +0 -51
- package/dist/worker-QFEBU72E.js +0 -24
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { i as abandonTurnRecord, yt as extractAssistantText } from "./checkpoint-CNrPyRJN.js";
|
|
2
|
+
import { Gt as buildDeterministicTurnId } from "./stats-DTUbAb88.js";
|
|
3
|
+
//#region src/chat/runtime/turn.ts
|
|
4
|
+
/** Classified Slack turn failure carrying the owning Sentry capture outward. */
|
|
5
|
+
var ConversationTurnBoundaryError = class extends Error {
|
|
6
|
+
eventId;
|
|
7
|
+
failureCode;
|
|
8
|
+
constructor(args) {
|
|
9
|
+
super(args.cause instanceof Error ? args.cause.message : String(args.cause), { cause: args.cause });
|
|
10
|
+
this.name = "ConversationTurnBoundaryError";
|
|
11
|
+
this.eventId = args.eventId;
|
|
12
|
+
this.failureCode = args.failureCode;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
/** Return a classified Slack boundary failure without erasing its cause. */
|
|
16
|
+
function getConversationTurnBoundaryError(error) {
|
|
17
|
+
return error instanceof ConversationTurnBoundaryError ? error : void 0;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Queue-worker yield routing: respond.ts returns a suspended AgentRunOutcome
|
|
21
|
+
* and the Slack executor raises this at the worker boundary so the lease owner
|
|
22
|
+
* requeues the conversation.
|
|
23
|
+
*/
|
|
24
|
+
var CooperativeTurnYieldError = class extends Error {
|
|
25
|
+
code = "cooperative_turn_yield";
|
|
26
|
+
constructor(message = "Agent turn yielded at a safe boundary") {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "CooperativeTurnYieldError";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function isCooperativeTurnYieldError(error) {
|
|
32
|
+
return error instanceof CooperativeTurnYieldError;
|
|
33
|
+
}
|
|
34
|
+
/** Error indicating durable turn input could not be committed by the worker owner. */
|
|
35
|
+
var TurnInputCommitLostError = class extends Error {
|
|
36
|
+
code = "turn_input_commit_lost";
|
|
37
|
+
constructor(message = "Turn input commit lost its durable owner") {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "TurnInputCommitLostError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
/** Return whether an error means the durable worker lost input ownership. */
|
|
43
|
+
function isTurnInputCommitLostError(error) {
|
|
44
|
+
return error instanceof TurnInputCommitLostError;
|
|
45
|
+
}
|
|
46
|
+
/** Error indicating durable turn input should stay pending for a later worker. */
|
|
47
|
+
var TurnInputDeferredError = class extends Error {
|
|
48
|
+
code = "turn_input_deferred";
|
|
49
|
+
constructor(message = "Turn input is deferred until the active resume ends") {
|
|
50
|
+
super(message);
|
|
51
|
+
this.name = "TurnInputDeferredError";
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
/** Return whether an error means the durable worker should redeliver input later. */
|
|
55
|
+
function isTurnInputDeferredError(error) {
|
|
56
|
+
return error instanceof TurnInputDeferredError;
|
|
57
|
+
}
|
|
58
|
+
/** Mark a turn as the active turn in conversation state. */
|
|
59
|
+
function startActiveTurn(args) {
|
|
60
|
+
args.conversation.processing.activeTurnId = args.nextTurnId;
|
|
61
|
+
}
|
|
62
|
+
function clearActiveTurn(conversation, sessionId) {
|
|
63
|
+
if (!sessionId || conversation.processing.activeTurnId === sessionId) conversation.processing.activeTurnId = void 0;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Close the active turn without marking a Pi session reusable for future
|
|
67
|
+
* history. Use this for auth handoffs and recovery replies that end the live
|
|
68
|
+
* turn but do not produce a completed Pi session.
|
|
69
|
+
*/
|
|
70
|
+
function markTurnClosed(args) {
|
|
71
|
+
clearActiveTurn(args.conversation, args.sessionId);
|
|
72
|
+
args.conversation.processing.lastCompletedAtMs = args.nowMs;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Mark a turn as completed after its assistant output has been handled.
|
|
76
|
+
*/
|
|
77
|
+
function markTurnCompleted(args) {
|
|
78
|
+
clearActiveTurn(args.conversation, args.sessionId);
|
|
79
|
+
args.conversation.processing.lastCompletedAtMs = args.nowMs;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Mark a turn as failed when execution or final user-visible reply delivery
|
|
83
|
+
* cannot be completed. If `sessionId` is provided, `activeTurnId` is only
|
|
84
|
+
* cleared when it still matches the failing turn.
|
|
85
|
+
*/
|
|
86
|
+
function markTurnFailed(args) {
|
|
87
|
+
clearActiveTurn(args.conversation, args.sessionId);
|
|
88
|
+
args.conversation.processing.lastCompletedAtMs = args.nowMs;
|
|
89
|
+
args.markConversationMessage(args.conversation, args.userMessageId, {
|
|
90
|
+
replied: false,
|
|
91
|
+
skippedReason: "reply failed"
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/chat/no-reply.ts
|
|
96
|
+
const NO_REPLY_MARKER = "[[NO_REPLY]]";
|
|
97
|
+
/**
|
|
98
|
+
* True when one assistant message ends with the silence marker.
|
|
99
|
+
* Mid-sentence mentions do not match. Detection is per message only.
|
|
100
|
+
*/
|
|
101
|
+
function isNoReplyMarker(text) {
|
|
102
|
+
return text.trimEnd().endsWith(NO_REPLY_MARKER);
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/chat/services/assistant-reply.ts
|
|
106
|
+
const THINKING_XML_BLOCK_PATTERN = /[ \t]*<thinking\b[^>]*>[\s\S]*?<\/thinking>[ \t]*(?:\r?\n)?/gi;
|
|
107
|
+
const FENCED_CODE_BLOCK_PATTERN = /```[\s\S]*?```/g;
|
|
108
|
+
/** Remove provider reasoning wrappers while preserving fenced code examples. */
|
|
109
|
+
function sanitizeAssistantText(text) {
|
|
110
|
+
let result = "";
|
|
111
|
+
let cursor = 0;
|
|
112
|
+
for (const match of text.matchAll(FENCED_CODE_BLOCK_PATTERN)) {
|
|
113
|
+
const start = match.index;
|
|
114
|
+
if (start === void 0) continue;
|
|
115
|
+
result += text.slice(cursor, start).replace(THINKING_XML_BLOCK_PATTERN, "");
|
|
116
|
+
result += match[0];
|
|
117
|
+
cursor = start + match[0].length;
|
|
118
|
+
}
|
|
119
|
+
return (result + text.slice(cursor).replace(THINKING_XML_BLOCK_PATTERN, "")).trim();
|
|
120
|
+
}
|
|
121
|
+
/** Decide whether one completed assistant message becomes a reply. */
|
|
122
|
+
function decideReply(message) {
|
|
123
|
+
if (message.content.some((part) => part.type === "toolCall")) return { kind: "suppress" };
|
|
124
|
+
const text = sanitizeAssistantText(extractAssistantText(message));
|
|
125
|
+
if (!text) return { kind: "empty" };
|
|
126
|
+
if (isNoReplyMarker(text)) return { kind: "suppress" };
|
|
127
|
+
return {
|
|
128
|
+
kind: "deliver",
|
|
129
|
+
text
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Return destination-visible reply text when the message is deliverable. */
|
|
133
|
+
function getAssistantReplyText(message) {
|
|
134
|
+
const decision = decideReply(message);
|
|
135
|
+
return decision.kind === "deliver" ? decision.text : void 0;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/chat/services/pending-auth.ts
|
|
139
|
+
const AUTH_LINK_REUSE_WINDOW_MS = 6e5;
|
|
140
|
+
const NON_REQUEST_SKIPPED_REASON_PREFIXES = ["directed_to_other_party:", "side_conversation:"];
|
|
141
|
+
function isSkippedNonRequest(reason) {
|
|
142
|
+
return NON_REQUEST_SKIPPED_REASON_PREFIXES.some((prefix) => reason?.startsWith(prefix));
|
|
143
|
+
}
|
|
144
|
+
/** Decide whether the same agent-run session can reuse its fresh auth link. */
|
|
145
|
+
function canReusePendingAuthLink(args) {
|
|
146
|
+
const { pendingAuth } = args;
|
|
147
|
+
if (!pendingAuth) return false;
|
|
148
|
+
return pendingAuth.kind === args.kind && pendingAuth.provider === args.provider && pendingAuth.actorId === args.actorId && pendingAuth.scope === args.scope && pendingAuth.sessionId === args.sessionId && pendingAuth.linkSentAtMs + AUTH_LINK_REUSE_WINDOW_MS > (args.nowMs ?? Date.now());
|
|
149
|
+
}
|
|
150
|
+
function getConversationPendingAuth(args) {
|
|
151
|
+
const pendingAuth = args.conversation.processing.pendingAuth;
|
|
152
|
+
if (!pendingAuth) return;
|
|
153
|
+
if (pendingAuth.kind !== args.kind || pendingAuth.provider !== args.provider || pendingAuth.actorId !== args.actorId || pendingAuth.scope !== args.scope) return;
|
|
154
|
+
return pendingAuth;
|
|
155
|
+
}
|
|
156
|
+
function clearPendingAuth(conversation, sessionId) {
|
|
157
|
+
if (!conversation.processing.pendingAuth) return;
|
|
158
|
+
if (sessionId && conversation.processing.pendingAuth.sessionId !== sessionId) return;
|
|
159
|
+
conversation.processing.pendingAuth = void 0;
|
|
160
|
+
}
|
|
161
|
+
/** Mark the prior blocked turn abandoned after a new auth attempt replaces it. */
|
|
162
|
+
async function abandonReplacedPendingAuth(args) {
|
|
163
|
+
if (args.previousPendingAuth && args.previousPendingAuth.sessionId !== args.nextPendingAuth.sessionId && args.conversationId) await abandonTurnRecord({
|
|
164
|
+
conversationId: args.conversationId,
|
|
165
|
+
turnId: args.previousPendingAuth.sessionId,
|
|
166
|
+
errorMessage: "Abandoned by a newer auth-blocked request in the same conversation."
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Decide whether an auth callback still belongs to the latest real human
|
|
171
|
+
* request, ignoring bot-authored and passive bystander rows while treating
|
|
172
|
+
* failed human turns and opt-outs as newer freshness blockers.
|
|
173
|
+
*/
|
|
174
|
+
function isPendingAuthLatestRequest(conversation, pendingAuth) {
|
|
175
|
+
for (let index = conversation.messages.length - 1; index >= 0; index -= 1) {
|
|
176
|
+
const message = conversation.messages[index];
|
|
177
|
+
if (message?.role !== "user") continue;
|
|
178
|
+
if (message.author?.isBot) continue;
|
|
179
|
+
if (isSkippedNonRequest(message.meta?.skippedReason)) continue;
|
|
180
|
+
return buildDeterministicTurnId(message.id) === pendingAuth.sessionId;
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
//#endregion
|
|
185
|
+
export { startActiveTurn as S, isTurnInputCommitLostError as _, isPendingAuthLatestRequest as a, markTurnCompleted as b, sanitizeAssistantText as c, ConversationTurnBoundaryError as d, CooperativeTurnYieldError as f, isCooperativeTurnYieldError as g, getConversationTurnBoundaryError as h, getConversationPendingAuth as i, NO_REPLY_MARKER as l, TurnInputDeferredError as m, canReusePendingAuthLink as n, decideReply as o, TurnInputCommitLostError as p, clearPendingAuth as r, getAssistantReplyText as s, abandonReplacedPendingAuth as t, isNoReplyMarker as u, isTurnInputDeferredError as v, markTurnFailed as x, markTurnClosed as y };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { statSync } from "node:fs";
|
|
5
|
+
//#region src/plugin-module.ts
|
|
6
|
+
const PLUGIN_MODULE_EXTENSIONS = [
|
|
7
|
+
"",
|
|
8
|
+
".ts",
|
|
9
|
+
".tsx",
|
|
10
|
+
".mts",
|
|
11
|
+
".mjs",
|
|
12
|
+
".js",
|
|
13
|
+
".cjs"
|
|
14
|
+
];
|
|
15
|
+
/** Resolve a relative plugin module path using Junior's supported extension order. */
|
|
16
|
+
function resolveRelativePluginModule(cwd, specifier) {
|
|
17
|
+
const basePath = path.resolve(cwd, specifier);
|
|
18
|
+
for (const extension of PLUGIN_MODULE_EXTENSIONS) {
|
|
19
|
+
const candidate = `${basePath}${extension}`;
|
|
20
|
+
try {
|
|
21
|
+
if (statSync(candidate).isFile()) return candidate;
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
for (const extension of PLUGIN_MODULE_EXTENSIONS) {
|
|
25
|
+
const candidate = path.join(basePath, `index${extension}`);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(candidate).isFile()) return candidate;
|
|
28
|
+
} catch {}
|
|
29
|
+
}
|
|
30
|
+
throw new Error(`Plugin module "${specifier}" could not be resolved`);
|
|
31
|
+
}
|
|
32
|
+
/** Resolve the runtime-safe plugin module used by Junior app wiring. */
|
|
33
|
+
function resolvePluginModule(cwd, input) {
|
|
34
|
+
const moduleSpecifier = typeof input === "string" ? input : input.module;
|
|
35
|
+
const exportName = typeof input === "string" ? "plugins" : input.exportName ?? "plugins";
|
|
36
|
+
if (!moduleSpecifier.trim()) throw new Error("Plugin module specifier must not be empty");
|
|
37
|
+
if (moduleSpecifier.startsWith(".") || path.isAbsolute(moduleSpecifier)) {
|
|
38
|
+
const resolvedPath = resolveRelativePluginModule(cwd, moduleSpecifier);
|
|
39
|
+
return {
|
|
40
|
+
exportName,
|
|
41
|
+
importPath: resolvedPath,
|
|
42
|
+
importUrl: pathToFileURL(resolvedPath).href,
|
|
43
|
+
kind: "file",
|
|
44
|
+
sourceSpecifier: moduleSpecifier
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const resolvedPath = createRequire(path.join(cwd, "package.json")).resolve(moduleSpecifier);
|
|
48
|
+
return {
|
|
49
|
+
exportName,
|
|
50
|
+
importPath: resolvedPath,
|
|
51
|
+
importUrl: pathToFileURL(resolvedPath).href,
|
|
52
|
+
kind: "package",
|
|
53
|
+
sourceSpecifier: moduleSpecifier
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Assert that a module export is a Junior plugin set. */
|
|
57
|
+
function assertPluginSet(value, source) {
|
|
58
|
+
if (!value || typeof value !== "object" || !Array.isArray(value.packageNames) || !Array.isArray(value.registrations)) throw new Error(`Plugin module ${source} must export a defineJuniorPlugins(...) set`);
|
|
59
|
+
const pluginSet = value;
|
|
60
|
+
if (pluginSet.packageNames?.find((packageName) => typeof packageName !== "string") !== void 0) throw new Error(`Plugin module ${source} must export string package names`);
|
|
61
|
+
if (pluginSet.registrations?.find((registration) => !registration || typeof registration !== "object" || !("manifest" in registration) || !registration.manifest || typeof registration.manifest !== "object" || !("name" in registration.manifest) || typeof registration.manifest.name !== "string")) throw new Error(`Plugin module ${source} must export plugin registrations with manifest names`);
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
/** Load a resolved plugin module and return its configured plugin set. */
|
|
65
|
+
async function loadPluginSetFromModule(moduleRef, importModule = async (ref) => await import(ref.importUrl)) {
|
|
66
|
+
const mod = await importModule(moduleRef);
|
|
67
|
+
return assertPluginSet(moduleRef.exportName === "default" ? mod.default : mod[moduleRef.exportName], `${moduleRef.importUrl}#${moduleRef.exportName}`);
|
|
68
|
+
}
|
|
69
|
+
/** Load an app-local `./plugins` module when one exists. */
|
|
70
|
+
async function loadAppPluginSet(cwd, importModule) {
|
|
71
|
+
let pluginModule;
|
|
72
|
+
try {
|
|
73
|
+
pluginModule = resolvePluginModule(cwd, "./plugins");
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error instanceof Error && error.message === "Plugin module \"./plugins\" could not be resolved") return;
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
return await loadPluginSetFromModule(pluginModule, importModule);
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { loadPluginSetFromModule as n, resolvePluginModule as r, loadAppPluginSet as t };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { PluginRegistration, PluginRuntimePostinstallCommand } from "@sentry/junior-plugin-api";
|
|
2
|
+
//#region src/chat/plugins/types.d.ts
|
|
3
|
+
interface PluginOAuthConfig {
|
|
4
|
+
clientIdEnv: string;
|
|
5
|
+
clientSecretEnv: string;
|
|
6
|
+
authorizeEndpoint: string;
|
|
7
|
+
tokenEndpoint: string;
|
|
8
|
+
scope?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Set true when the provider returns an empty scope string even for authorized
|
|
11
|
+
* grants (e.g. GitHub App user-to-server tokens always return `scope: ""`
|
|
12
|
+
* regardless of what was requested). When enabled, an empty response scope
|
|
13
|
+
* uses the configured `scope` value instead of being treated as
|
|
14
|
+
* "no scopes granted".
|
|
15
|
+
*/
|
|
16
|
+
treatEmptyScopeAsUnreported?: boolean;
|
|
17
|
+
authorizeParams?: Record<string, string>;
|
|
18
|
+
tokenAuthMethod?: "body" | "basic";
|
|
19
|
+
tokenExtraHeaders?: Record<string, string>;
|
|
20
|
+
}
|
|
21
|
+
interface PluginEnvVarDeclaration {
|
|
22
|
+
default?: string;
|
|
23
|
+
exposeToCommandEnv?: boolean;
|
|
24
|
+
}
|
|
25
|
+
type PluginRuntimeDependencyConfig = {
|
|
26
|
+
type: "npm";
|
|
27
|
+
package: string;
|
|
28
|
+
version?: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: "system";
|
|
31
|
+
package: string;
|
|
32
|
+
} | {
|
|
33
|
+
type: "system";
|
|
34
|
+
url: string;
|
|
35
|
+
sha256: string;
|
|
36
|
+
};
|
|
37
|
+
interface PluginOAuthConfigPatch extends Omit<Partial<PluginOAuthConfig>, "authorizeParams" | "tokenExtraHeaders"> {
|
|
38
|
+
authorizeParams?: Record<string, string | null> | null;
|
|
39
|
+
tokenExtraHeaders?: Record<string, string | null> | null;
|
|
40
|
+
}
|
|
41
|
+
type PluginCredentialConfigBase = {
|
|
42
|
+
domains?: string[];
|
|
43
|
+
authTokenEnv?: string;
|
|
44
|
+
authTokenPlaceholder?: string | null;
|
|
45
|
+
};
|
|
46
|
+
type PluginCredentialConfig = PluginCredentialConfigBase & {
|
|
47
|
+
apiHeaders?: Record<string, string | null> | null;
|
|
48
|
+
type?: "oauth-bearer";
|
|
49
|
+
};
|
|
50
|
+
/** Install-level changes applied to one plugin manifest before validation. */
|
|
51
|
+
interface PluginManifestConfig {
|
|
52
|
+
displayName?: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
configKeys?: string[];
|
|
55
|
+
domains?: string[] | null;
|
|
56
|
+
apiHeaders?: Record<string, string | null> | null;
|
|
57
|
+
commandEnv?: Record<string, string | null> | null;
|
|
58
|
+
envVars?: Record<string, PluginEnvVarDeclaration | null> | null;
|
|
59
|
+
credentials?: PluginCredentialConfig | null;
|
|
60
|
+
runtimeDependencies?: PluginRuntimeDependencyConfig[] | null;
|
|
61
|
+
runtimePostinstall?: PluginRuntimePostinstallCommand[] | null;
|
|
62
|
+
mcp?: {
|
|
63
|
+
transport?: "http";
|
|
64
|
+
url?: string;
|
|
65
|
+
headers?: Record<string, string | null> | null;
|
|
66
|
+
allowedTools?: string[] | null;
|
|
67
|
+
wrappedTools?: string[] | null;
|
|
68
|
+
} | null;
|
|
69
|
+
oauth?: PluginOAuthConfigPatch | null;
|
|
70
|
+
target?: {
|
|
71
|
+
type?: string;
|
|
72
|
+
configKey?: string;
|
|
73
|
+
commandFlags?: string[] | null;
|
|
74
|
+
} | null;
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/plugins.d.ts
|
|
78
|
+
type JuniorPluginInput = PluginRegistration | string;
|
|
79
|
+
interface JuniorPluginSetOptions {
|
|
80
|
+
/** Install-level manifest overrides applied before validation. */
|
|
81
|
+
manifests?: Record<string, PluginManifestConfig>;
|
|
82
|
+
}
|
|
83
|
+
/** Reusable plugin registrations and manifest overrides. */
|
|
84
|
+
interface JuniorPluginSet {
|
|
85
|
+
/** Install-level manifest overrides applied before validation. */
|
|
86
|
+
manifests?: Record<string, PluginManifestConfig>;
|
|
87
|
+
/** Manifest-only plugin packages included by package name. */
|
|
88
|
+
packageNames: string[];
|
|
89
|
+
/** JavaScript plugin definitions included by package factories. */
|
|
90
|
+
registrations: PluginRegistration[];
|
|
91
|
+
}
|
|
92
|
+
/** Define package-name plugins and JS plugin definitions for one app. */
|
|
93
|
+
declare function defineJuniorPlugins(inputs: JuniorPluginInput[], options?: JuniorPluginSetOptions): JuniorPluginSet;
|
|
94
|
+
//#endregion
|
|
95
|
+
export { defineJuniorPlugins as i, JuniorPluginSet as n, JuniorPluginSetOptions as r, JuniorPluginInput as t };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
|
|
2
|
+
//#region src/plugins.ts
|
|
3
|
+
var plugins_exports = /* @__PURE__ */ __exportAll({
|
|
4
|
+
defineJuniorPlugins: () => defineJuniorPlugins,
|
|
5
|
+
pluginCatalogConfigFromEnv: () => pluginCatalogConfigFromEnv,
|
|
6
|
+
pluginCatalogConfigFromPluginSet: () => pluginCatalogConfigFromPluginSet,
|
|
7
|
+
pluginCliRegistrationsFromPluginSet: () => pluginCliRegistrationsFromPluginSet,
|
|
8
|
+
pluginRuntimeRegistrationsFromPluginSet: () => pluginRuntimeRegistrationsFromPluginSet
|
|
9
|
+
});
|
|
10
|
+
function cloneManifests(manifests) {
|
|
11
|
+
return manifests ? structuredClone(manifests) : void 0;
|
|
12
|
+
}
|
|
13
|
+
function cloneInlineManifests(registrations) {
|
|
14
|
+
const inlineManifests = registrations.flatMap((plugin) => plugin.manifest ? [{
|
|
15
|
+
manifest: {
|
|
16
|
+
...structuredClone(plugin.manifest),
|
|
17
|
+
configKeys: plugin.manifest.configKeys?.map((key) => key.includes(".") ? key : `${plugin.manifest.name}.${key}`) ?? [],
|
|
18
|
+
...plugin.manifest.target ? { target: {
|
|
19
|
+
...plugin.manifest.target,
|
|
20
|
+
configKey: plugin.manifest.target.configKey.includes(".") ? plugin.manifest.target.configKey : `${plugin.manifest.name}.${plugin.manifest.target.configKey}`
|
|
21
|
+
} } : void 0
|
|
22
|
+
},
|
|
23
|
+
...plugin.packageName ? { packageName: plugin.packageName } : void 0
|
|
24
|
+
}] : []);
|
|
25
|
+
return inlineManifests.length > 0 ? inlineManifests : void 0;
|
|
26
|
+
}
|
|
27
|
+
function assertUniquePluginNames(registrations) {
|
|
28
|
+
const seen = /* @__PURE__ */ new Set();
|
|
29
|
+
for (const plugin of registrations) {
|
|
30
|
+
const name = plugin.manifest.name;
|
|
31
|
+
if (seen.has(name)) throw new Error(`Duplicate plugin registration name "${name}"`);
|
|
32
|
+
seen.add(name);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function assertUniquePackageNames(packageNames) {
|
|
36
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37
|
+
for (const packageName of packageNames) {
|
|
38
|
+
if (seen.has(packageName)) throw new Error(`Duplicate plugin package name "${packageName}"`);
|
|
39
|
+
seen.add(packageName);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function normalizePluginInput(input) {
|
|
43
|
+
if (typeof input === "string") return { packageName: input };
|
|
44
|
+
return { registration: input };
|
|
45
|
+
}
|
|
46
|
+
/** Define package-name plugins and JS plugin definitions for one app. */
|
|
47
|
+
function defineJuniorPlugins(inputs, options = {}) {
|
|
48
|
+
const normalized = inputs.map(normalizePluginInput);
|
|
49
|
+
const packageNames = normalized.flatMap((input) => input.packageName ? [input.packageName] : []);
|
|
50
|
+
const registrations = normalized.flatMap((input) => input.registration ? [input.registration] : []);
|
|
51
|
+
assertUniquePackageNames(packageNames);
|
|
52
|
+
assertUniquePluginNames(registrations);
|
|
53
|
+
const manifests = cloneManifests(options.manifests);
|
|
54
|
+
return {
|
|
55
|
+
packageNames,
|
|
56
|
+
registrations: registrations.map((plugin) => ({ ...plugin })),
|
|
57
|
+
...manifests ? { manifests } : void 0
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Build the manifest catalog config implied by one plugin set. */
|
|
61
|
+
function pluginCatalogConfigFromPluginSet(pluginSet) {
|
|
62
|
+
if (!pluginSet) return;
|
|
63
|
+
const packages = [.../* @__PURE__ */ new Set([...pluginSet.packageNames, ...pluginSet.registrations.flatMap((plugin) => plugin.packageName ? [plugin.packageName] : [])])];
|
|
64
|
+
const manifests = cloneManifests(pluginSet.manifests);
|
|
65
|
+
const inlineManifests = cloneInlineManifests(pluginSet.registrations);
|
|
66
|
+
if (packages.length === 0 && !manifests && !inlineManifests) return;
|
|
67
|
+
return {
|
|
68
|
+
...inlineManifests ? { inlineManifests } : void 0,
|
|
69
|
+
...packages.length > 0 ? { packages } : void 0,
|
|
70
|
+
...manifests ? { manifests } : void 0
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function readEnvPluginPackages(env = process.env) {
|
|
74
|
+
const value = env.JUNIOR_PLUGIN_PACKAGES;
|
|
75
|
+
if (!value) return;
|
|
76
|
+
let parsed;
|
|
77
|
+
try {
|
|
78
|
+
parsed = JSON.parse(value);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw new Error("JUNIOR_PLUGIN_PACKAGES must be valid JSON", { cause: error });
|
|
81
|
+
}
|
|
82
|
+
if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "string" || !item.trim())) throw new Error("JUNIOR_PLUGIN_PACKAGES must be a JSON array of package names");
|
|
83
|
+
return parsed;
|
|
84
|
+
}
|
|
85
|
+
/** Build the manifest catalog config implied by plugin package env. */
|
|
86
|
+
function pluginCatalogConfigFromEnv(env = process.env) {
|
|
87
|
+
const packages = readEnvPluginPackages(env);
|
|
88
|
+
return packages ? { packages } : void 0;
|
|
89
|
+
}
|
|
90
|
+
/** Return registrations that expose in-process runtime code. */
|
|
91
|
+
function pluginRuntimeRegistrationsFromPluginSet(pluginSet) {
|
|
92
|
+
return pluginSet?.registrations.filter((plugin) => plugin.hooks || plugin.tasks || plugin.userPages?.length) ?? [];
|
|
93
|
+
}
|
|
94
|
+
/** Return registrations that expose host CLI commands. */
|
|
95
|
+
function pluginCliRegistrationsFromPluginSet(pluginSet) {
|
|
96
|
+
return pluginSet?.registrations.filter((plugin) => plugin.cli) ?? [];
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
export { pluginRuntimeRegistrationsFromPluginSet as a, pluginCliRegistrationsFromPluginSet as i, pluginCatalogConfigFromEnv as n, plugins_exports as o, pluginCatalogConfigFromPluginSet as r, defineJuniorPlugins as t };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
//#region src/chat/tool-support/private-trace-result.ts
|
|
3
|
+
const PRIVATE_TRACE_RESULT_ATTRIBUTE = "gen_ai.tool.call.result.exposure";
|
|
4
|
+
const privateTraceResultToken = randomUUID();
|
|
5
|
+
/** Mark one tool result as an adapter-approved private trace projection. */
|
|
6
|
+
function privateTraceResultAttributes() {
|
|
7
|
+
return { [PRIVATE_TRACE_RESULT_ATTRIBUTE]: privateTraceResultToken };
|
|
8
|
+
}
|
|
9
|
+
/** Consume and remove the adapter-owned private trace projection marker. */
|
|
10
|
+
function consumePrivateTraceResultMarker(attributes) {
|
|
11
|
+
const projected = attributes[PRIVATE_TRACE_RESULT_ATTRIBUTE] === privateTraceResultToken;
|
|
12
|
+
delete attributes[PRIVATE_TRACE_RESULT_ATTRIBUTE];
|
|
13
|
+
return projected;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { privateTraceResultAttributes as n, consumePrivateTraceResultMarker as t };
|