@sentry/junior 0.72.0 → 0.73.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/bin/junior.mjs +12 -10
- package/dist/app.d.ts +11 -2
- package/dist/app.js +936 -13042
- package/dist/chat/agent-dispatch/runner.d.ts +2 -0
- package/dist/chat/agent-dispatch/store.d.ts +2 -2
- package/dist/chat/agent-dispatch/types.d.ts +6 -3
- package/dist/chat/agent-dispatch/validation.d.ts +2 -3
- package/dist/chat/app/production.d.ts +8 -1
- package/dist/chat/app/services.d.ts +7 -0
- package/dist/chat/destination.d.ts +3 -1
- package/dist/chat/logging.d.ts +3 -0
- package/dist/chat/oauth-flow.d.ts +1 -1
- package/dist/chat/plugins/registry.d.ts +2 -0
- package/dist/chat/plugins/types.d.ts +2 -0
- package/dist/chat/prompt.d.ts +4 -1
- package/dist/chat/requester.d.ts +19 -12
- package/dist/chat/respond.d.ts +6 -2
- package/dist/chat/runtime/agent-continue-runner.d.ts +1 -1
- package/dist/chat/runtime/reply-executor.d.ts +3 -1
- package/dist/chat/runtime/slack-resume.d.ts +3 -3
- package/dist/chat/runtime/slack-runtime.d.ts +13 -3
- package/dist/chat/runtime/turn.d.ts +15 -1
- package/dist/chat/sandbox/egress-credentials.d.ts +5 -2
- package/dist/chat/sandbox/egress-policy.d.ts +5 -1
- package/dist/chat/sandbox/egress-proxy.d.ts +2 -0
- package/dist/chat/sandbox/egress-schemas.d.ts +4 -0
- package/dist/chat/sandbox/egress-session.d.ts +3 -1
- package/dist/chat/sandbox/egress-tracing.d.ts +7 -0
- package/dist/chat/sandbox/sandbox.d.ts +2 -0
- package/dist/chat/sandbox/session.d.ts +3 -2
- package/dist/chat/services/auth-pause-response.d.ts +1 -1
- package/dist/chat/services/auth-pause.d.ts +2 -1
- package/dist/chat/services/mcp-auth-orchestration.d.ts +1 -1
- package/dist/chat/services/message-actor-identity.d.ts +2 -2
- package/dist/chat/services/plugin-auth-orchestration.d.ts +9 -8
- package/dist/chat/services/turn-result.d.ts +3 -0
- package/dist/chat/slack/user.d.ts +2 -2
- package/dist/chat/task-execution/store.d.ts +1 -1
- package/dist/chat/tools/slack/canvas-tools.d.ts +3 -2
- package/dist/chat/tools/slack/channel-list-messages.d.ts +2 -2
- package/dist/chat/tools/slack/channel-post-message.d.ts +3 -2
- package/dist/chat/tools/slack/context.d.ts +15 -2
- package/dist/chat/tools/slack/message-add-reaction.d.ts +3 -2
- package/dist/chat/tools/slack/thread-read.d.ts +2 -2
- package/dist/chat/tools/types.d.ts +19 -19
- package/dist/{chunk-6GEYPE6T.js → chunk-3BYAPS6B.js} +30 -6
- package/dist/{chunk-GB3AL54K.js → chunk-7Q5YOUUT.js} +10 -2
- package/dist/{chunk-HNMUVGSR.js → chunk-AL5T52ZD.js} +6 -6
- package/dist/{chunk-PP7AGSBU.js → chunk-CYUI7JU5.js} +18 -8
- package/dist/{chunk-3FYPXHPL.js → chunk-DIMX5F3T.js} +1 -1
- package/dist/{chunk-4JXCSGSA.js → chunk-M4FLLXXD.js} +1 -1
- package/dist/chunk-OQSYYOLM.js +12787 -0
- package/dist/{chunk-55XEZFGD.js → chunk-OR6NQJ5E.js} +2 -2
- package/dist/{chunk-VLIO6RQR.js → chunk-RY6AL5C7.js} +4 -4
- package/dist/chunk-SJHUF3DP.js +43 -0
- package/dist/{chunk-ICKIDP7G.js → chunk-UOTZ3EEQ.js} +1 -1
- package/dist/{chunk-VSNA5KAB.js → chunk-UZVHXZ7V.js} +1276 -1481
- package/dist/{chunk-XC33FJZN.js → chunk-V4VYUY4A.js} +25 -4
- package/dist/{chunk-ZJQPA67D.js → chunk-WS2EG3GW.js} +224 -224
- package/dist/chunk-ZDA2HYX5.js +275 -0
- package/dist/cli/chat.js +205 -0
- package/dist/cli/check.js +9 -10
- package/dist/cli/run.js +10 -2
- package/dist/cli/snapshot-warmup.js +7 -7
- package/dist/cli/upgrade.js +8 -8
- package/dist/deployment.d.ts +4 -0
- package/dist/handlers/agent-dispatch.d.ts +6 -1
- package/dist/handlers/mcp-oauth-callback.d.ts +6 -1
- package/dist/handlers/oauth-callback.d.ts +6 -1
- package/dist/handlers/sandbox-egress-proxy.d.ts +2 -0
- package/dist/handlers/webhooks.d.ts +4 -2
- package/dist/instrumentation.js +17 -2
- package/dist/nitro.js +9 -10
- package/dist/reporting.js +19 -17
- package/dist/runner-LMAM4OGD.js +259 -0
- package/package.json +3 -3
- package/dist/chunk-6YY4Q3D4.js +0 -12
- package/dist/chunk-Z3YD6NHK.js +0 -12
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeSlackConversationId
|
|
3
|
+
} from "./chunk-V4VYUY4A.js";
|
|
4
|
+
import {
|
|
5
|
+
getStateAdapter
|
|
6
|
+
} from "./chunk-DIMX5F3T.js";
|
|
7
|
+
import {
|
|
8
|
+
parseSlackThreadId
|
|
9
|
+
} from "./chunk-WS2EG3GW.js";
|
|
10
|
+
import {
|
|
11
|
+
parseStoredSlackRequester
|
|
12
|
+
} from "./chunk-CYUI7JU5.js";
|
|
13
|
+
import {
|
|
14
|
+
isRecord,
|
|
15
|
+
toOptionalNumber
|
|
16
|
+
} from "./chunk-3BYAPS6B.js";
|
|
17
|
+
import {
|
|
18
|
+
sentry_exports
|
|
19
|
+
} from "./chunk-SJHUF3DP.js";
|
|
20
|
+
|
|
21
|
+
// src/handlers/health.ts
|
|
22
|
+
function GET() {
|
|
23
|
+
return Response.json({
|
|
24
|
+
status: "ok",
|
|
25
|
+
service: "junior",
|
|
26
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/chat/sentry-links.ts
|
|
31
|
+
function getSentryOrgSlug() {
|
|
32
|
+
const slug = process.env.SENTRY_ORG_SLUG?.trim();
|
|
33
|
+
return slug || void 0;
|
|
34
|
+
}
|
|
35
|
+
function isSentrySaasDsnHost(host) {
|
|
36
|
+
return host === "sentry.io" || host.endsWith(".sentry.io");
|
|
37
|
+
}
|
|
38
|
+
function buildSentryWebBaseUrl(dsn) {
|
|
39
|
+
if (isSentrySaasDsnHost(dsn.host)) {
|
|
40
|
+
return "https://sentry.io";
|
|
41
|
+
}
|
|
42
|
+
const port = dsn.port ? `:${dsn.port}` : "";
|
|
43
|
+
const path = dsn.path ? `/${dsn.path}` : "";
|
|
44
|
+
return `${dsn.protocol}://${dsn.host}${port}${path}`;
|
|
45
|
+
}
|
|
46
|
+
function buildSentryConversationUrl(conversationId) {
|
|
47
|
+
const client = sentry_exports.getClient();
|
|
48
|
+
const dsn = client?.getDsn();
|
|
49
|
+
if (!dsn?.host || !dsn.projectId) {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
const orgSlug = getSentryOrgSlug();
|
|
53
|
+
if (!orgSlug) {
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
56
|
+
const encodedId = encodeURIComponent(conversationId);
|
|
57
|
+
const params = new URLSearchParams();
|
|
58
|
+
params.set("project", dsn.projectId);
|
|
59
|
+
const path = `explore/conversations/${encodedId}/?${params.toString()}`;
|
|
60
|
+
if (isSentrySaasDsnHost(dsn.host)) {
|
|
61
|
+
return `https://${orgSlug}.sentry.io/${path}`;
|
|
62
|
+
}
|
|
63
|
+
return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
|
|
64
|
+
}
|
|
65
|
+
function buildSentryTraceUrl(traceId) {
|
|
66
|
+
const client = sentry_exports.getClient();
|
|
67
|
+
const dsn = client?.getDsn();
|
|
68
|
+
if (!dsn?.host || !dsn.projectId) {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
const orgSlug = getSentryOrgSlug();
|
|
72
|
+
if (!orgSlug) {
|
|
73
|
+
return void 0;
|
|
74
|
+
}
|
|
75
|
+
const encodedTraceId = encodeURIComponent(traceId);
|
|
76
|
+
const params = new URLSearchParams();
|
|
77
|
+
params.set("project", dsn.projectId);
|
|
78
|
+
const path = `performance/trace/${encodedTraceId}/?${params.toString()}`;
|
|
79
|
+
if (isSentrySaasDsnHost(dsn.host)) {
|
|
80
|
+
return `https://${orgSlug}.sentry.io/${path}`;
|
|
81
|
+
}
|
|
82
|
+
return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/chat/slack/conversation-context.ts
|
|
86
|
+
function normalizeConversationName(type, channelName) {
|
|
87
|
+
const trimmed = channelName?.trim();
|
|
88
|
+
if (!trimmed) return void 0;
|
|
89
|
+
if (type === "public_channel" || type === "private_channel" || type === "private_channel_or_group_dm") {
|
|
90
|
+
return trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
|
|
91
|
+
}
|
|
92
|
+
return trimmed;
|
|
93
|
+
}
|
|
94
|
+
function typeFromSlackChannelType(channelType) {
|
|
95
|
+
if (channelType === "channel") return "public_channel";
|
|
96
|
+
if (channelType === "group") return "private_channel";
|
|
97
|
+
if (channelType === "mpim") return "group_dm";
|
|
98
|
+
if (channelType === "im") return "direct_message";
|
|
99
|
+
return void 0;
|
|
100
|
+
}
|
|
101
|
+
function typeFromChannelId(channelId, channelName) {
|
|
102
|
+
const normalized = normalizeSlackConversationId(channelId);
|
|
103
|
+
if (!normalized) return void 0;
|
|
104
|
+
if (normalized.startsWith("C")) return "public_channel";
|
|
105
|
+
if (normalized.startsWith("D")) return "direct_message";
|
|
106
|
+
if (normalized.startsWith("G")) {
|
|
107
|
+
return channelName?.trim().startsWith("mpdm-") ? "group_dm" : "private_channel_or_group_dm";
|
|
108
|
+
}
|
|
109
|
+
return void 0;
|
|
110
|
+
}
|
|
111
|
+
function toSlackEventChannelType(channelType) {
|
|
112
|
+
if (channelType === "channel" || channelType === "group" || channelType === "mpim" || channelType === "im") {
|
|
113
|
+
return channelType;
|
|
114
|
+
}
|
|
115
|
+
return void 0;
|
|
116
|
+
}
|
|
117
|
+
function resolveSlackChannelTypeFromMessage(message) {
|
|
118
|
+
const raw = message.raw;
|
|
119
|
+
if (!raw || typeof raw !== "object") {
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
const channelType = raw.channel_type;
|
|
123
|
+
return typeof channelType === "string" ? toSlackEventChannelType(channelType.trim()) : void 0;
|
|
124
|
+
}
|
|
125
|
+
function resolveSlackConversationContext(input) {
|
|
126
|
+
const type = typeFromSlackChannelType(input.channelType) ?? typeFromChannelId(input.channelId, input.channelName);
|
|
127
|
+
if (!type) return void 0;
|
|
128
|
+
const name = normalizeConversationName(type, input.channelName);
|
|
129
|
+
return {
|
|
130
|
+
type,
|
|
131
|
+
...name ? { name } : {}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function resolveSlackConversationContextFromThreadId(input) {
|
|
135
|
+
const slackThread = parseSlackThreadId(input.threadId);
|
|
136
|
+
return resolveSlackConversationContext({
|
|
137
|
+
channelId: slackThread?.channelId,
|
|
138
|
+
channelName: input.channelName
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function formatSlackConversationTypeLabel(type) {
|
|
142
|
+
if (type === "public_channel") return "Public Channel";
|
|
143
|
+
if (type === "private_channel") return "Private Channel";
|
|
144
|
+
if (type === "group_dm") return "Group DM";
|
|
145
|
+
if (type === "direct_message") return "Direct Message";
|
|
146
|
+
return "Private Channel or Group DM";
|
|
147
|
+
}
|
|
148
|
+
function formatSlackConversationRedactedLabel(context) {
|
|
149
|
+
if (!context) return void 0;
|
|
150
|
+
return formatSlackConversationTypeLabel(context.type);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/chat/state/conversation-details.ts
|
|
154
|
+
import { THREAD_STATE_TTL_MS } from "chat";
|
|
155
|
+
var CONVERSATION_PREFIX = "junior:conversation";
|
|
156
|
+
var CONVERSATION_DETAILS_TTL_MS = THREAD_STATE_TTL_MS;
|
|
157
|
+
function conversationContextKey(conversationId) {
|
|
158
|
+
return `${CONVERSATION_PREFIX}:${conversationId}:context`;
|
|
159
|
+
}
|
|
160
|
+
function conversationTitleKey(conversationId) {
|
|
161
|
+
return `${CONVERSATION_PREFIX}:${conversationId}:title`;
|
|
162
|
+
}
|
|
163
|
+
function parseOriginRequester(value) {
|
|
164
|
+
return parseStoredSlackRequester(value);
|
|
165
|
+
}
|
|
166
|
+
function parseOriginSurface(value) {
|
|
167
|
+
if (value === "slack" || value === "api" || value === "scheduler" || value === "internal") {
|
|
168
|
+
return value;
|
|
169
|
+
}
|
|
170
|
+
return void 0;
|
|
171
|
+
}
|
|
172
|
+
function storedContextFromInput(context) {
|
|
173
|
+
return {
|
|
174
|
+
...context.channelName ? { channelName: context.channelName } : {},
|
|
175
|
+
...context.originSurface ? { originSurface: context.originSurface } : {},
|
|
176
|
+
...context.originRequester ? { originRequester: context.originRequester } : {},
|
|
177
|
+
startedAtMs: context.startedAtMs
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function parseContext(value) {
|
|
181
|
+
if (!isRecord(value)) return void 0;
|
|
182
|
+
const startedAtMs = toOptionalNumber(value.startedAtMs);
|
|
183
|
+
if (startedAtMs === void 0) return void 0;
|
|
184
|
+
return {
|
|
185
|
+
...typeof value.channelName === "string" && value.channelName.trim() ? { channelName: value.channelName.trim() } : {},
|
|
186
|
+
...parseOriginSurface(value.originSurface) ? { originSurface: parseOriginSurface(value.originSurface) } : {},
|
|
187
|
+
...parseOriginRequester(value.originRequester) ? { originRequester: parseOriginRequester(value.originRequester) } : {},
|
|
188
|
+
startedAtMs
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function parseTitle(value) {
|
|
192
|
+
if (!isRecord(value)) return void 0;
|
|
193
|
+
const displayTitle = typeof value.displayTitle === "string" && value.displayTitle.trim() ? value.displayTitle.trim() : void 0;
|
|
194
|
+
if (!displayTitle) return void 0;
|
|
195
|
+
return {
|
|
196
|
+
displayTitle,
|
|
197
|
+
...typeof value.titleSourceMessageId === "string" ? { titleSourceMessageId: value.titleSourceMessageId } : {}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
async function initConversationContext(conversationId, context) {
|
|
201
|
+
const stateAdapter = getStateAdapter();
|
|
202
|
+
await stateAdapter.connect();
|
|
203
|
+
const key = conversationContextKey(conversationId);
|
|
204
|
+
const inserted = await stateAdapter.setIfNotExists(
|
|
205
|
+
key,
|
|
206
|
+
storedContextFromInput(context),
|
|
207
|
+
CONVERSATION_DETAILS_TTL_MS
|
|
208
|
+
);
|
|
209
|
+
if (inserted) return;
|
|
210
|
+
const existing = parseContext(await stateAdapter.get(key));
|
|
211
|
+
if (!existing) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
await stateAdapter.set(key, existing, CONVERSATION_DETAILS_TTL_MS);
|
|
215
|
+
}
|
|
216
|
+
async function setConversationTitle(conversationId, title) {
|
|
217
|
+
const stateAdapter = getStateAdapter();
|
|
218
|
+
await stateAdapter.connect();
|
|
219
|
+
await stateAdapter.set(
|
|
220
|
+
conversationTitleKey(conversationId),
|
|
221
|
+
{
|
|
222
|
+
displayTitle: title.displayTitle,
|
|
223
|
+
...title.titleSourceMessageId ? { titleSourceMessageId: title.titleSourceMessageId } : {}
|
|
224
|
+
},
|
|
225
|
+
CONVERSATION_DETAILS_TTL_MS
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
async function getConversationDetails(conversationId) {
|
|
229
|
+
const stateAdapter = getStateAdapter();
|
|
230
|
+
await stateAdapter.connect();
|
|
231
|
+
const [rawContext, rawTitle] = await Promise.all([
|
|
232
|
+
stateAdapter.get(conversationContextKey(conversationId)),
|
|
233
|
+
stateAdapter.get(conversationTitleKey(conversationId))
|
|
234
|
+
]);
|
|
235
|
+
const context = parseContext(rawContext);
|
|
236
|
+
const title = parseTitle(rawTitle);
|
|
237
|
+
if (!context && !title) return void 0;
|
|
238
|
+
return {
|
|
239
|
+
conversationId,
|
|
240
|
+
...title?.displayTitle ? { displayTitle: title.displayTitle } : {},
|
|
241
|
+
...title?.titleSourceMessageId ? { titleSourceMessageId: title.titleSourceMessageId } : {},
|
|
242
|
+
...context?.channelName ? { channelName: context.channelName } : {},
|
|
243
|
+
...context?.originSurface ? { originSurface: context.originSurface } : {},
|
|
244
|
+
...context?.originRequester ? { originRequester: context.originRequester } : {},
|
|
245
|
+
...context?.startedAtMs !== void 0 ? { startedAtMs: context.startedAtMs } : {}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
async function getConversationDetailsForIds(conversationIds) {
|
|
249
|
+
const uniqueIds = [...new Set(conversationIds)].filter(Boolean);
|
|
250
|
+
const entries = await Promise.all(
|
|
251
|
+
uniqueIds.map(async (id) => {
|
|
252
|
+
const details = await getConversationDetails(id);
|
|
253
|
+
return details ? [id, details] : void 0;
|
|
254
|
+
})
|
|
255
|
+
);
|
|
256
|
+
const result = /* @__PURE__ */ new Map();
|
|
257
|
+
for (const entry of entries) {
|
|
258
|
+
if (entry) result.set(entry[0], entry[1]);
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export {
|
|
264
|
+
GET,
|
|
265
|
+
buildSentryConversationUrl,
|
|
266
|
+
buildSentryTraceUrl,
|
|
267
|
+
resolveSlackChannelTypeFromMessage,
|
|
268
|
+
resolveSlackConversationContext,
|
|
269
|
+
resolveSlackConversationContextFromThreadId,
|
|
270
|
+
formatSlackConversationRedactedLabel,
|
|
271
|
+
initConversationContext,
|
|
272
|
+
setConversationTitle,
|
|
273
|
+
getConversationDetails,
|
|
274
|
+
getConversationDetailsForIds
|
|
275
|
+
};
|
package/dist/cli/chat.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import "../chunk-2KG3PWR4.js";
|
|
2
|
+
|
|
3
|
+
// src/cli/chat.ts
|
|
4
|
+
import {
|
|
5
|
+
stdin as defaultStdin,
|
|
6
|
+
stderr as defaultStderr,
|
|
7
|
+
stdout as defaultStdout
|
|
8
|
+
} from "process";
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
10
|
+
import * as readline from "readline/promises";
|
|
11
|
+
|
|
12
|
+
// src/chat/local/conversation.ts
|
|
13
|
+
import { createHash } from "crypto";
|
|
14
|
+
import path from "path";
|
|
15
|
+
var LOCAL_CONVERSATION_ALIAS_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
16
|
+
function slugifyConversationAlias(alias) {
|
|
17
|
+
const trimmed = alias.trim();
|
|
18
|
+
if (!LOCAL_CONVERSATION_ALIAS_PATTERN.test(trimmed)) {
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
return trimmed.toLowerCase().replaceAll(".", "-");
|
|
22
|
+
}
|
|
23
|
+
function workspaceKey(cwd) {
|
|
24
|
+
return createHash("sha256").update(path.resolve(cwd)).digest("hex").slice(0, 12);
|
|
25
|
+
}
|
|
26
|
+
function normalizeLocalConversationId(input) {
|
|
27
|
+
const slug = slugifyConversationAlias(input.alias);
|
|
28
|
+
if (!slug) {
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
return `local:${workspaceKey(input.cwd ?? process.cwd())}:${slug}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/cli/chat.ts
|
|
35
|
+
var CHAT_USAGE = "usage: junior chat\n junior chat -p <message>";
|
|
36
|
+
var DEFAULT_IO = {
|
|
37
|
+
error: (line) => writeStream(defaultStderr, `${line}
|
|
38
|
+
`),
|
|
39
|
+
input: defaultStdin,
|
|
40
|
+
output: defaultStdout,
|
|
41
|
+
write: (text) => writeStream(defaultStdout, text)
|
|
42
|
+
};
|
|
43
|
+
var ChatOutputError = class extends Error {
|
|
44
|
+
constructor(error) {
|
|
45
|
+
super(errorMessage(error));
|
|
46
|
+
this.name = "ChatOutputError";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function errorMessage(error) {
|
|
50
|
+
return error instanceof Error ? error.message : String(error);
|
|
51
|
+
}
|
|
52
|
+
async function deliverReply(io, reply) {
|
|
53
|
+
try {
|
|
54
|
+
const files = reply.files ?? [];
|
|
55
|
+
if (files.length > 0) {
|
|
56
|
+
const names = files.map(
|
|
57
|
+
(file) => typeof file.filename === "string" && file.filename.trim() ? file.filename : "generated file"
|
|
58
|
+
).join(", ");
|
|
59
|
+
throw new Error(`Local chat cannot deliver files yet: ${names}`);
|
|
60
|
+
}
|
|
61
|
+
await io.write(formatReply(reply));
|
|
62
|
+
} catch (error) {
|
|
63
|
+
throw new ChatOutputError(error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function reportStatus(io, status) {
|
|
67
|
+
try {
|
|
68
|
+
await io.error(status);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
throw new ChatOutputError(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function writeStream(stream, text) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
stream.write(text, (error) => {
|
|
76
|
+
if (error) {
|
|
77
|
+
reject(error);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
resolve();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function defaultStateAdapterForLocalChat() {
|
|
85
|
+
if (process.env.JUNIOR_STATE_ADAPTER) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
process.env.JUNIOR_STATE_ADAPTER = "memory";
|
|
89
|
+
}
|
|
90
|
+
function parseChatArgs(argv) {
|
|
91
|
+
if (argv.length === 0) {
|
|
92
|
+
return { mode: "interactive" };
|
|
93
|
+
}
|
|
94
|
+
if (argv[0] !== "-p") {
|
|
95
|
+
return void 0;
|
|
96
|
+
}
|
|
97
|
+
const message = argv.slice(1).join(" ").trim();
|
|
98
|
+
if (!message) {
|
|
99
|
+
return void 0;
|
|
100
|
+
}
|
|
101
|
+
return { message, mode: "prompt" };
|
|
102
|
+
}
|
|
103
|
+
function formatReply(reply) {
|
|
104
|
+
const lines = [];
|
|
105
|
+
const text = reply.text.trim();
|
|
106
|
+
if (text) {
|
|
107
|
+
lines.push(text);
|
|
108
|
+
}
|
|
109
|
+
return `${lines.join("\n") || "[empty response]"}
|
|
110
|
+
`;
|
|
111
|
+
}
|
|
112
|
+
function newRunConversationId() {
|
|
113
|
+
const conversationId = normalizeLocalConversationId({
|
|
114
|
+
alias: `run-${randomUUID()}`
|
|
115
|
+
});
|
|
116
|
+
if (!conversationId) {
|
|
117
|
+
throw new Error("Invalid local conversation name");
|
|
118
|
+
}
|
|
119
|
+
return conversationId;
|
|
120
|
+
}
|
|
121
|
+
async function runPrompt(options, io) {
|
|
122
|
+
defaultStateAdapterForLocalChat();
|
|
123
|
+
const conversationId = newRunConversationId();
|
|
124
|
+
const { runLocalAgentTurn } = await import("../runner-LMAM4OGD.js");
|
|
125
|
+
const result = await runLocalAgentTurn(
|
|
126
|
+
{
|
|
127
|
+
conversationId,
|
|
128
|
+
message: options.message
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
deliverReply: async (reply) => {
|
|
132
|
+
await deliverReply(io, reply);
|
|
133
|
+
},
|
|
134
|
+
onStatus: async (status) => {
|
|
135
|
+
await reportStatus(io, status);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
return result.outcome === "success" ? 0 : 1;
|
|
140
|
+
}
|
|
141
|
+
async function runInteractive(io) {
|
|
142
|
+
defaultStateAdapterForLocalChat();
|
|
143
|
+
const conversationId = newRunConversationId();
|
|
144
|
+
const { runLocalAgentTurn } = await import("../runner-LMAM4OGD.js");
|
|
145
|
+
const rl = readline.createInterface({
|
|
146
|
+
input: io.input,
|
|
147
|
+
output: io.output,
|
|
148
|
+
terminal: true
|
|
149
|
+
});
|
|
150
|
+
try {
|
|
151
|
+
while (true) {
|
|
152
|
+
const message = (await rl.question("junior> ")).trim();
|
|
153
|
+
if (!message) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (message === "/exit" || message === "/quit") {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
await runLocalAgentTurn(
|
|
161
|
+
{
|
|
162
|
+
conversationId,
|
|
163
|
+
message
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
deliverReply: async (reply) => {
|
|
167
|
+
await deliverReply(io, reply);
|
|
168
|
+
},
|
|
169
|
+
onStatus: async (status) => {
|
|
170
|
+
await reportStatus(io, status);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (error instanceof ChatOutputError) {
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
await reportStatus(io, errorMessage(error));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
} finally {
|
|
182
|
+
rl.close();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async function runChat(argv, io = DEFAULT_IO) {
|
|
186
|
+
const options = parseChatArgs(argv);
|
|
187
|
+
if (!options) {
|
|
188
|
+
await io.error(CHAT_USAGE);
|
|
189
|
+
return 1;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
if (options.mode === "prompt") {
|
|
193
|
+
return await runPrompt(options, io);
|
|
194
|
+
}
|
|
195
|
+
await runInteractive(io);
|
|
196
|
+
return 0;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
await io.error(errorMessage(error));
|
|
199
|
+
return 1;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export {
|
|
203
|
+
CHAT_USAGE,
|
|
204
|
+
runChat
|
|
205
|
+
};
|
package/dist/cli/check.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
|
|
3
|
-
JUNIOR_HEARTBEAT_ROUTE,
|
|
4
|
-
LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION
|
|
5
|
-
} from "../chunk-6YY4Q3D4.js";
|
|
6
1
|
import {
|
|
7
2
|
parseSkillFile
|
|
8
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-OR6NQJ5E.js";
|
|
9
4
|
import {
|
|
10
5
|
parseInlinePluginManifest,
|
|
11
6
|
parsePluginManifest
|
|
12
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-7Q5YOUUT.js";
|
|
13
8
|
import "../chunk-KVZL5NZS.js";
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import
|
|
9
|
+
import "../chunk-CYUI7JU5.js";
|
|
10
|
+
import "../chunk-3BYAPS6B.js";
|
|
11
|
+
import {
|
|
12
|
+
JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
|
|
13
|
+
JUNIOR_HEARTBEAT_ROUTE,
|
|
14
|
+
LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION
|
|
15
|
+
} from "../chunk-SJHUF3DP.js";
|
|
17
16
|
import "../chunk-2KG3PWR4.js";
|
|
18
17
|
|
|
19
18
|
// src/cli/check.ts
|
package/dist/cli/run.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import "../chunk-2KG3PWR4.js";
|
|
2
2
|
|
|
3
3
|
// src/cli/run.ts
|
|
4
|
-
var CLI_USAGE = "usage: junior init <dir>\n junior snapshot create\n junior check [dir]\n junior upgrade";
|
|
4
|
+
var CLI_USAGE = "usage: junior init <dir>\n junior snapshot create\n junior check [dir]\n junior upgrade\n junior chat\n junior chat -p <message>";
|
|
5
5
|
var DEFAULT_IO = {
|
|
6
6
|
error: console.error
|
|
7
7
|
};
|
|
8
|
+
function normalizeCliArgv(argv) {
|
|
9
|
+
return argv[0] === "--" ? argv.slice(1) : argv;
|
|
10
|
+
}
|
|
8
11
|
async function runCli(argv, handlers, io = DEFAULT_IO) {
|
|
9
|
-
const [command, subcommand, ...rest] = argv;
|
|
12
|
+
const [command, subcommand, ...rest] = normalizeCliArgv(argv);
|
|
13
|
+
if (command === "chat") {
|
|
14
|
+
return await handlers.runChat(
|
|
15
|
+
subcommand === void 0 ? [] : [subcommand, ...rest]
|
|
16
|
+
);
|
|
17
|
+
}
|
|
10
18
|
if (command === "init") {
|
|
11
19
|
if (!subcommand || rest.length > 0) {
|
|
12
20
|
io.error(CLI_USAGE);
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveRuntimeDependencySnapshot
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-RY6AL5C7.js";
|
|
4
4
|
import "../chunk-G3E7SCME.js";
|
|
5
5
|
import {
|
|
6
6
|
getPluginProviders,
|
|
7
7
|
getPluginRuntimeDependencies,
|
|
8
8
|
getPluginRuntimePostinstall
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-7Q5YOUUT.js";
|
|
10
10
|
import "../chunk-KVZL5NZS.js";
|
|
11
11
|
import {
|
|
12
12
|
disconnectStateAdapter
|
|
13
|
-
} from "../chunk-
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
13
|
+
} from "../chunk-DIMX5F3T.js";
|
|
14
|
+
import "../chunk-WS2EG3GW.js";
|
|
15
|
+
import "../chunk-CYUI7JU5.js";
|
|
16
|
+
import "../chunk-3BYAPS6B.js";
|
|
17
|
+
import "../chunk-SJHUF3DP.js";
|
|
18
18
|
import "../chunk-2KG3PWR4.js";
|
|
19
19
|
|
|
20
20
|
// src/cli/snapshot-warmup.ts
|
package/dist/cli/upgrade.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
coerceThreadConversationState
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-M4FLLXXD.js";
|
|
4
4
|
import {
|
|
5
5
|
JUNIOR_THREAD_STATE_TTL_MS,
|
|
6
6
|
getConversation,
|
|
7
7
|
requestConversationWork
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-AL5T52ZD.js";
|
|
9
9
|
import {
|
|
10
10
|
parseDestination,
|
|
11
11
|
sameDestination
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-V4VYUY4A.js";
|
|
13
13
|
import {
|
|
14
14
|
disconnectStateAdapter,
|
|
15
15
|
getConnectedStateContext
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-DIMX5F3T.js";
|
|
17
17
|
import {
|
|
18
18
|
getChatConfig
|
|
19
|
-
} from "../chunk-
|
|
20
|
-
import "../chunk-
|
|
19
|
+
} from "../chunk-WS2EG3GW.js";
|
|
20
|
+
import "../chunk-CYUI7JU5.js";
|
|
21
21
|
import {
|
|
22
22
|
isRecord,
|
|
23
23
|
toOptionalNumber,
|
|
24
24
|
toOptionalString
|
|
25
|
-
} from "../chunk-
|
|
26
|
-
import "../chunk-
|
|
25
|
+
} from "../chunk-3BYAPS6B.js";
|
|
26
|
+
import "../chunk-SJHUF3DP.js";
|
|
27
27
|
import "../chunk-2KG3PWR4.js";
|
|
28
28
|
|
|
29
29
|
// src/cli/upgrade/migrations/redis-conversation-state.ts
|
package/dist/deployment.d.ts
CHANGED
|
@@ -2,3 +2,7 @@ export declare const JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
|
|
|
2
2
|
export declare const JUNIOR_HEARTBEAT_CRON_SCHEDULE = "* * * * *";
|
|
3
3
|
export declare const JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE = "/api/internal/agent/continue";
|
|
4
4
|
export declare const LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION = "api/internal/agent/continue.ts";
|
|
5
|
+
/** Resolve the deployment version used for release and telemetry correlation. */
|
|
6
|
+
export declare function getDeploymentServiceVersion(): string | undefined;
|
|
7
|
+
/** Resolve deployment-scoped telemetry attributes from host environment. */
|
|
8
|
+
export declare function getDeploymentTelemetryAttributes(): Record<string, string>;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress-tracing";
|
|
1
2
|
import type { WaitUntilFn } from "@/handlers/types";
|
|
3
|
+
interface AgentDispatchHandlerOptions {
|
|
4
|
+
tracePropagation?: SandboxEgressTracePropagationConfig;
|
|
5
|
+
}
|
|
2
6
|
/** Handle the authenticated internal agent-dispatch callback. */
|
|
3
|
-
export declare function POST(request: Request, waitUntil: WaitUntilFn): Promise<Response>;
|
|
7
|
+
export declare function POST(request: Request, waitUntil: WaitUntilFn, options?: AgentDispatchHandlerOptions): Promise<Response>;
|
|
8
|
+
export {};
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
import type { generateAssistantReply } from "@/chat/respond";
|
|
1
2
|
import type { WaitUntilFn } from "@/handlers/types";
|
|
2
|
-
|
|
3
|
+
interface McpOAuthCallbackOptions {
|
|
4
|
+
generateReply?: typeof generateAssistantReply;
|
|
5
|
+
}
|
|
6
|
+
export declare function GET(request: Request, provider: string, waitUntil: WaitUntilFn, options?: McpOAuthCallbackOptions): Promise<Response>;
|
|
7
|
+
export {};
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
import type { WaitUntilFn } from "@/handlers/types";
|
|
2
|
-
|
|
2
|
+
import type { generateAssistantReply } from "@/chat/respond";
|
|
3
|
+
interface OAuthCallbackOptions {
|
|
4
|
+
generateReply?: typeof generateAssistantReply;
|
|
5
|
+
}
|
|
6
|
+
export declare function GET(request: Request, provider: string, waitUntil: WaitUntilFn, options?: OAuthCallbackOptions): Promise<Response>;
|
|
7
|
+
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type SandboxEgressHttpInterceptor } from "@/chat/sandbox/egress-proxy";
|
|
2
|
+
import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress-tracing";
|
|
2
3
|
interface SandboxEgressProxyOptions {
|
|
3
4
|
interceptHttp?: SandboxEgressHttpInterceptor;
|
|
5
|
+
tracePropagation?: SandboxEgressTracePropagationConfig;
|
|
4
6
|
}
|
|
5
7
|
/** Handles Vercel Sandbox firewall egress proxy requests. */
|
|
6
8
|
export declare function ALL(request: Request, options?: SandboxEgressProxyOptions): Promise<Response>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SlackAdapter } from "@chat-adapter/slack";
|
|
2
|
+
import { type SlackWebhookServices } from "@/chat/ingress/slack-webhook";
|
|
2
3
|
import { JuniorChat } from "@/chat/ingress/junior-chat";
|
|
3
4
|
import type { WaitUntilFn } from "@/handlers/types";
|
|
4
5
|
type LegacyChatSdkBot = JuniorChat<{
|
|
@@ -10,8 +11,9 @@ type LegacyChatSdkBot = JuniorChat<{
|
|
|
10
11
|
* Slack production ingress persists messages into the durable conversation
|
|
11
12
|
* mailbox and wakes the queue worker. The optional `legacyBot` parameter is
|
|
12
13
|
* kept for integration tests that still exercise Chat SDK fixtures directly.
|
|
14
|
+
* The optional `services` parameter carries app-scoped runtime services.
|
|
13
15
|
*/
|
|
14
|
-
export declare function handlePlatformWebhook(request: Request, platform: string, waitUntil: WaitUntilFn, legacyBot?: LegacyChatSdkBot): Promise<Response>;
|
|
16
|
+
export declare function handlePlatformWebhook(request: Request, platform: string, waitUntil: WaitUntilFn, legacyBot?: LegacyChatSdkBot, services?: SlackWebhookServices): Promise<Response>;
|
|
15
17
|
/** Handle a platform webhook request from the app route. */
|
|
16
|
-
export declare function POST(request: Request, platform: string, waitUntil: WaitUntilFn): Promise<Response>;
|
|
18
|
+
export declare function POST(request: Request, platform: string, waitUntil: WaitUntilFn, services?: SlackWebhookServices): Promise<Response>;
|
|
17
19
|
export {};
|