@sentry/junior 0.204.0 → 0.206.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 → agent-C9yuiZUF.js} +277 -85
- package/dist/{agent-hooks-Bbcp9e33.js → agent-hooks-DNjlz2A-.js} +1084 -16
- package/dist/{agent-runner-DNb1A49M.js → agent-runner-E67lFrDG.js} +5 -5
- package/dist/api/schema.d.ts +85 -0
- package/dist/api/schema.js +2 -2
- package/dist/api.js +44 -511
- package/dist/{app-B1TOqBI8.d.ts → app-AxGmJHwK.d.ts} +8 -0
- package/dist/app.d.ts +1 -1
- package/dist/app.js +56 -84
- package/dist/{auth-pause-state-DosEalIG.js → auth-pause-state-MVZ6xvEK.js} +6 -6
- package/dist/briefs-CvJFQvhJ.js +398 -0
- package/dist/{catalog-runtime-BReos-D4.js → catalog-runtime-TBR8n4e1.js} +1 -1
- package/dist/{checkpoint-CNrPyRJN.js → checkpoint-BY47jJCB.js} +7 -6
- package/dist/cli/chat.js +14 -12
- package/dist/cli/check.js +3 -3
- package/dist/cli/init.js +1 -0
- package/dist/cli/main.js +5 -1
- package/dist/cli/plugins.js +3 -3
- package/dist/cli/run.d.ts +2 -1
- package/dist/cli/run.js +2 -1
- package/dist/cli/snapshot-create.js +3 -3
- package/dist/cli/upgrade.js +3 -3
- package/dist/{config-nGCW1OTG.js → client-ceE7NtvC.js} +4 -367
- package/dist/config-CIE83sR2.js +386 -0
- package/dist/{schema-Rn8-XEaN.js → conversation-AA4R1VUn.js} +580 -558
- package/dist/{conversation-privacy-B4voFRSm.js → conversation-privacy-Auyq26XQ.js} +1 -1
- package/dist/{credential-sync-kXr1hvO1.js → credential-sync-BO33aNQd.js} +22 -20
- package/dist/{execution-stats-DWfSihcH.js → execution-stats-SiS2FLcv.js} +4 -4
- package/dist/{executor-DcMSlI5c.js → executor-BfbYPW63.js} +31 -3
- package/dist/instrumentation.js +2 -2
- package/dist/{job-queue-Drn_LXlM.js → job-queue-CyTc24Es.js} +1 -1
- package/dist/{logging-BzAk1S_s.js → logging-D37bayDc.js} +1 -1
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +3 -3
- package/dist/{oauth-callback-server-JiftokvA.js → oauth-callback-server-BtfOeHTZ.js} +2 -2
- package/dist/{pending-auth-CWmSdZVg.js → pending-auth-BPUzcs7n.js} +2 -2
- package/dist/{profile-CrT5nXbw.js → profile-CSixooTi.js} +4 -3
- package/dist/prompt-3gqNY1Ka.js +552 -0
- package/dist/{registry-DH1xUo2N.js → registry-DiR0-xRg.js} +1 -1
- package/dist/{resolve-CZHnfxaS.js → resolve-Bn5q__9b.js} +2 -2
- package/dist/{runner-CZV2sC46.js → runner-DFx3dIJH.js} +9 -9
- package/dist/{sandbox-egress-signals-bHZfmhbd.js → sandbox-egress-signals-bwvjihxA.js} +1 -1
- package/dist/schema-8GXFfclK.js +559 -0
- package/dist/{skills-CIcDQSgM.js → skills-BhM5qyCF.js} +2 -2
- package/dist/{spawn-DdkUFRmq.js → spawn-Dk0PqdH6.js} +2 -2
- package/dist/{stats-DTUbAb88.js → stats-DKRP4rsY.js} +26 -12
- package/dist/{task-queue-CJIR4RF7.js → task-queue-CdpTvu4R.js} +3 -3
- package/dist/{task-runner-D-O3A-Cp.js → task-runner-alpjVSxQ.js} +10 -10
- package/dist/{thread-state-CRc9jTJS.js → thread-state-CRK7aA41.js} +5 -5
- package/dist/{turn-execution-BkinIdJF.js → turn-execution-XtyzIHog.js} +3 -3
- package/dist/{turn-lifecycle-DQV19VTW.js → turn-lifecycle-VbwZLfBv.js} +1 -1
- package/dist/{usage-D3EbSO7w.js → usage-D4A48Bdl.js} +4 -125
- package/dist/{validation-C2CR-OX3.js → validation-jn_46o4U.js} +1 -1
- package/dist/{version-DxcWdoKa.js → version-DcfJxB4z.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/web-authorization-CsfLSfEs.js +38 -0
- package/dist/{web-input-3EPfpf55.js → web-input-BPp_sc7t.js} +6 -6
- package/dist/{work-fGofI7Op.js → work-Di-ubSGg.js} +9 -9
- package/dist/{worker-CsOLq-mR.js → worker-Cu_D5Mr8.js} +5 -4
- package/migrations/0040_conversation_briefs.sql +17 -0
- package/migrations/meta/0040_snapshot.json +3516 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +4 -4
- package/dist/history-CqTuSAdI.js +0 -441
- package/dist/usage-schema-CKaDkH_j.js +0 -20
- package/dist/web-authorization-RMBxAR_t.js +0 -76
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { r as completeObject } from "./client-ceE7NtvC.js";
|
|
2
|
+
import { n as defaultModelId } from "./model-profile-CZmVoGdX.js";
|
|
3
|
+
import { N as parseBriefInput, d as conversationDetailReportSchema, k as briefCodeChangeSchema, p as conversationEventPageSchema } from "./conversation-AA4R1VUn.js";
|
|
4
|
+
import { n as briefEntriesFromReportEvents, s as generateBrief, t as BRIEF_PROMPT } from "./prompt-3gqNY1Ka.js";
|
|
5
|
+
import { CLI_USAGE } from "./cli/run.js";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
9
|
+
//#region src/chat/briefs/render.ts
|
|
10
|
+
function list(items, empty) {
|
|
11
|
+
return items.length > 0 ? items.map((item) => `- ${item}`).join("\n") : empty;
|
|
12
|
+
}
|
|
13
|
+
function escapeLabel(label) {
|
|
14
|
+
return label.replaceAll("[", "\\[").replaceAll("]", "\\]");
|
|
15
|
+
}
|
|
16
|
+
function formatCost(costUsd) {
|
|
17
|
+
return costUsd === void 0 ? "not reported" : `$${costUsd.toFixed(6)}`;
|
|
18
|
+
}
|
|
19
|
+
function formatCount(count, noun) {
|
|
20
|
+
return `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
21
|
+
}
|
|
22
|
+
function formatRecordCodeChange(change) {
|
|
23
|
+
const dates = [
|
|
24
|
+
change.openedAt ? `opened ${change.openedAt}` : void 0,
|
|
25
|
+
change.mergedAt ? `merged ${change.mergedAt}` : void 0,
|
|
26
|
+
change.closedAt ? `closed ${change.closedAt}` : void 0
|
|
27
|
+
].filter((value) => Boolean(value));
|
|
28
|
+
return `[${escapeLabel(`${change.repository}#${change.number}${change.title ? ` · ${change.title}` : ""}`)}](${change.url}) · ${change.state}${dates.length ? ` · ${dates.join(" · ")}` : ""}`;
|
|
29
|
+
}
|
|
30
|
+
/** Render the final Brief and its local evidence check as readable Markdown. */
|
|
31
|
+
function renderBriefMarkdown(args) {
|
|
32
|
+
const { brief, evidence } = args.generation;
|
|
33
|
+
const links = brief.links.map((link) => `[${escapeLabel(link.label)}](${link.url}) · ${link.kind}${link.status ? ` · ${link.status}` : ""}`);
|
|
34
|
+
const dropped = evidence.droppedUrls.length ? evidence.droppedUrls.map((url) => `raw \`${url.raw}\` · normalized \`${url.normalized}\``) : ["None"];
|
|
35
|
+
const record = brief.record;
|
|
36
|
+
const location = record.location ? `${record.location.provider}${record.location.channelName ? ` · ${record.location.channelName}` : ""}` : "None";
|
|
37
|
+
return [
|
|
38
|
+
`# ${args.input.title ?? `Brief ${args.input.conversationId}`}`,
|
|
39
|
+
"",
|
|
40
|
+
"## Record",
|
|
41
|
+
"",
|
|
42
|
+
`- Started: ${record.startedAt}`,
|
|
43
|
+
`- Last activity: ${record.lastActivityAt}`,
|
|
44
|
+
`- Duration: ${record.durationMs} ms`,
|
|
45
|
+
`- Location: ${location}`,
|
|
46
|
+
`- Messages: ${formatCount(record.userMessages, "user message")} · ${formatCount(record.assistantMessages, "assistant message")} · ${formatCount(record.toolResults, "tool result")}`,
|
|
47
|
+
`- Events: ${record.events}`,
|
|
48
|
+
`- Turns: ${record.turns ?? "not reported"}`,
|
|
49
|
+
"- Participants:",
|
|
50
|
+
...list(record.participants.map((participant) => `${participant.name} · ${participant.messages} message${participant.messages === 1 ? "" : "s"}`), "None.").split("\n").map((line) => ` ${line}`),
|
|
51
|
+
"- Code changes:",
|
|
52
|
+
...list(record.codeChanges.map(formatRecordCodeChange), "None.").split("\n").map((line) => ` ${line}`),
|
|
53
|
+
"",
|
|
54
|
+
"## Summary",
|
|
55
|
+
"",
|
|
56
|
+
brief.summary,
|
|
57
|
+
"",
|
|
58
|
+
"## Intent",
|
|
59
|
+
"",
|
|
60
|
+
brief.intent,
|
|
61
|
+
"",
|
|
62
|
+
`## Outcome · ${brief.outcome.status}`,
|
|
63
|
+
"",
|
|
64
|
+
brief.outcome.text,
|
|
65
|
+
"",
|
|
66
|
+
"## Decisions",
|
|
67
|
+
"",
|
|
68
|
+
"### Stated",
|
|
69
|
+
"",
|
|
70
|
+
list(brief.decisions.filter((decision) => decision.kind === "stated").map((decision) => `${decision.text}${decision.by ? ` — ${decision.by}` : ""}`), "None."),
|
|
71
|
+
"",
|
|
72
|
+
"### Confirmed",
|
|
73
|
+
"",
|
|
74
|
+
list(brief.decisions.filter((decision) => decision.kind === "confirmed").map((decision) => `${decision.text}${decision.by ? ` — ${decision.by}` : ""}`), "None."),
|
|
75
|
+
"",
|
|
76
|
+
"### Assumed by Junior (not confirmed)",
|
|
77
|
+
"",
|
|
78
|
+
list(brief.decisions.filter((decision) => decision.kind === "assumed").map((decision) => `${decision.text}${decision.by ? ` — ${decision.by}` : ""}`), "None."),
|
|
79
|
+
"",
|
|
80
|
+
"## Open decisions",
|
|
81
|
+
"",
|
|
82
|
+
list(brief.openDecisions.map((decision) => `${decision.text}${decision.owner ? ` — ${decision.owner}` : ""}`), "None."),
|
|
83
|
+
"",
|
|
84
|
+
"## Facts",
|
|
85
|
+
"",
|
|
86
|
+
list(brief.facts, "None."),
|
|
87
|
+
"",
|
|
88
|
+
"## Links",
|
|
89
|
+
"",
|
|
90
|
+
list(links, "None."),
|
|
91
|
+
"",
|
|
92
|
+
"## Keywords",
|
|
93
|
+
"",
|
|
94
|
+
brief.keywords.join(", ") || "None.",
|
|
95
|
+
"",
|
|
96
|
+
"---",
|
|
97
|
+
"",
|
|
98
|
+
"### Evidence check",
|
|
99
|
+
"",
|
|
100
|
+
`- Conversation: \`${args.input.conversationId}\``,
|
|
101
|
+
`- Through index: ${args.generation.throughIndex}`,
|
|
102
|
+
`- Versions generated: ${args.versionCount}`,
|
|
103
|
+
`- Model: \`${args.model}\``,
|
|
104
|
+
`- Code changes: ${evidence.codeChangeCount}`,
|
|
105
|
+
`- Resources: ${evidence.resourceCount}`,
|
|
106
|
+
`- Model URLs: ${evidence.keptUrlCount} kept of ${evidence.citedUrlCount}`,
|
|
107
|
+
`- Coerced decision kinds: ${evidence.coercedDecisionKinds}`,
|
|
108
|
+
`- Dropped attributions: ${evidence.droppedAttributionCount}`,
|
|
109
|
+
`- Dropped runtime-marker items: ${evidence.droppedRuntimeMarkerCount}`,
|
|
110
|
+
`- Merged claim without evidence: ${evidence.mergedClaimWithoutEvidence ? "yes" : "no"}`,
|
|
111
|
+
`- Cost: ${formatCost(args.totalCostUsd)}`,
|
|
112
|
+
"- Dropped URLs:",
|
|
113
|
+
...dropped.map((url) => ` - ${url}`),
|
|
114
|
+
""
|
|
115
|
+
].join("\n");
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/chat/briefs/snapshot.ts
|
|
119
|
+
const conversationSnapshotSchema = z.object({
|
|
120
|
+
schemaVersion: z.literal(1),
|
|
121
|
+
pulledAt: z.string().datetime(),
|
|
122
|
+
detail: conversationDetailReportSchema,
|
|
123
|
+
eventPages: z.array(conversationEventPageSchema),
|
|
124
|
+
codeChanges: z.array(briefCodeChangeSchema)
|
|
125
|
+
}).strict();
|
|
126
|
+
/** Create the self-contained wire snapshot used for local Brief replay. */
|
|
127
|
+
function createConversationSnapshot(args) {
|
|
128
|
+
return conversationSnapshotSchema.parse({
|
|
129
|
+
schemaVersion: 1,
|
|
130
|
+
pulledAt: args.pulledAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
131
|
+
detail: args.detail,
|
|
132
|
+
eventPages: args.eventPages,
|
|
133
|
+
codeChanges: args.codeChanges ?? []
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function allEvents(snapshot) {
|
|
137
|
+
const bySequence = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const event of [...snapshot.eventPages.flatMap((page) => page.events), ...snapshot.detail.events]) bySequence.set(event.seq, event);
|
|
139
|
+
return [...bySequence.values()].sort((left, right) => left.seq - right.seq);
|
|
140
|
+
}
|
|
141
|
+
function assertAvailableHistory(snapshot) {
|
|
142
|
+
if ([snapshot.detail.eventHistory, ...snapshot.eventPages.map((page) => page.eventHistory)].some((history) => history.status !== "available")) throw new Error("A Brief snapshot requires available event history");
|
|
143
|
+
}
|
|
144
|
+
function codeChangeAt(change, boundaryMs) {
|
|
145
|
+
if (change.openedAt && Date.parse(change.openedAt) > boundaryMs) return;
|
|
146
|
+
const mergedAt = change.mergedAt && Date.parse(change.mergedAt) <= boundaryMs ? change.mergedAt : void 0;
|
|
147
|
+
const closedAt = change.closedAt && Date.parse(change.closedAt) <= boundaryMs ? change.closedAt : void 0;
|
|
148
|
+
const { mergedAt: _mergedAt, closedAt: _closedAt, ...rest } = change;
|
|
149
|
+
return {
|
|
150
|
+
...rest,
|
|
151
|
+
state: mergedAt ? "merged" : closedAt ? "closed" : "open",
|
|
152
|
+
...mergedAt ? { mergedAt } : void 0,
|
|
153
|
+
...closedAt ? { closedAt } : void 0
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Project a downloaded conversation snapshot into generator input. Evidence
|
|
158
|
+
* is limited to what existed at the `throughIndex` event, so a replayed
|
|
159
|
+
* earlier version cannot cite a later pull request or resource.
|
|
160
|
+
*/
|
|
161
|
+
function briefInputFromSnapshot(snapshot, throughIndex) {
|
|
162
|
+
assertAvailableHistory(snapshot);
|
|
163
|
+
const detail = snapshot.detail;
|
|
164
|
+
const boundary = allEvents(snapshot).filter((event) => event.seq <= throughIndex).at(-1);
|
|
165
|
+
if (!boundary) throw new Error(`Snapshot has no event at or before index ${throughIndex}`);
|
|
166
|
+
const boundaryMs = Date.parse(boundary.createdAt);
|
|
167
|
+
const channelName = detail.channelName?.trim() || detail.channel?.trim();
|
|
168
|
+
const hasLocation = Boolean(channelName || detail.locationId);
|
|
169
|
+
return parseBriefInput({
|
|
170
|
+
conversationId: detail.conversationId,
|
|
171
|
+
...detail.displayTitle.trim() ? { title: detail.displayTitle.trim() } : void 0,
|
|
172
|
+
visibility: detail.visibility ?? "public",
|
|
173
|
+
...hasLocation ? { location: {
|
|
174
|
+
provider: "slack",
|
|
175
|
+
...channelName ? { channelName } : void 0
|
|
176
|
+
} } : void 0,
|
|
177
|
+
entries: briefEntriesFromReportEvents(allEvents(snapshot)),
|
|
178
|
+
codeChanges: snapshot.codeChanges.flatMap((change) => {
|
|
179
|
+
const bounded = codeChangeAt(change, boundaryMs);
|
|
180
|
+
return bounded ? [bounded] : [];
|
|
181
|
+
}),
|
|
182
|
+
resources: (detail.annotations ?? []).filter((annotation) => Date.parse(annotation.createdAt) <= boundaryMs).map((annotation) => ({
|
|
183
|
+
label: annotation.label,
|
|
184
|
+
url: annotation.url,
|
|
185
|
+
...annotation.status ? { status: annotation.status } : void 0
|
|
186
|
+
}))
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/** Return the last event index included in a conversation snapshot. */
|
|
190
|
+
function throughIndexFromSnapshot(snapshot) {
|
|
191
|
+
return allEvents(snapshot).at(-1)?.seq;
|
|
192
|
+
}
|
|
193
|
+
/** Return event indexes for turns that reached a successful terminal state. */
|
|
194
|
+
function completedTurnIndexesFromSnapshot(snapshot) {
|
|
195
|
+
return allEvents(snapshot).filter((event) => event.data.type === "turn_lifecycle" && (event.data.state === "succeeded" || event.data.state === "no_reply")).map((event) => event.seq);
|
|
196
|
+
}
|
|
197
|
+
//#endregion
|
|
198
|
+
//#region src/cli/briefs.ts
|
|
199
|
+
/**
|
|
200
|
+
* Local Brief snapshot and replay CLI.
|
|
201
|
+
*
|
|
202
|
+
* This module owns dashboard download pagination and local files. The Brief
|
|
203
|
+
* module owns projection, generation, evidence checks, and rendering.
|
|
204
|
+
*/
|
|
205
|
+
function optionValue(argv, index, option) {
|
|
206
|
+
const value = argv[index + 1];
|
|
207
|
+
if (!value || value.startsWith("--")) throw new Error(`${option} requires a value`);
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
function parsePullOptions(argv) {
|
|
211
|
+
const conversationIds = [];
|
|
212
|
+
let baseUrl;
|
|
213
|
+
let token = process.env.JUNIOR_API_TOKEN?.trim();
|
|
214
|
+
let out;
|
|
215
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
216
|
+
const argument = argv[index];
|
|
217
|
+
if (argument === "--base-url") {
|
|
218
|
+
baseUrl = optionValue(argv, index, argument);
|
|
219
|
+
index += 1;
|
|
220
|
+
} else if (argument === "--token") {
|
|
221
|
+
token = optionValue(argv, index, argument);
|
|
222
|
+
index += 1;
|
|
223
|
+
} else if (argument === "--out") {
|
|
224
|
+
out = optionValue(argv, index, argument);
|
|
225
|
+
index += 1;
|
|
226
|
+
} else if (argument.startsWith("-")) throw new Error(`Unknown option: ${argument}`);
|
|
227
|
+
else conversationIds.push(argument);
|
|
228
|
+
}
|
|
229
|
+
if (!baseUrl || !token || !out || conversationIds.length === 0) throw new Error(CLI_USAGE);
|
|
230
|
+
return {
|
|
231
|
+
baseUrl,
|
|
232
|
+
conversationIds,
|
|
233
|
+
out,
|
|
234
|
+
token
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
async function parseRunOptions(argv) {
|
|
238
|
+
const snapshots = [];
|
|
239
|
+
let model;
|
|
240
|
+
let promptFile;
|
|
241
|
+
let out = process.cwd();
|
|
242
|
+
let turnByTurn = false;
|
|
243
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
244
|
+
const argument = argv[index];
|
|
245
|
+
if (argument === "--model") {
|
|
246
|
+
model = optionValue(argv, index, argument);
|
|
247
|
+
index += 1;
|
|
248
|
+
} else if (argument === "--prompt") {
|
|
249
|
+
promptFile = optionValue(argv, index, argument);
|
|
250
|
+
index += 1;
|
|
251
|
+
} else if (argument === "--out") {
|
|
252
|
+
out = optionValue(argv, index, argument);
|
|
253
|
+
index += 1;
|
|
254
|
+
} else if (argument === "--turn-by-turn") turnByTurn = true;
|
|
255
|
+
else if (argument.startsWith("-")) throw new Error(`Unknown option: ${argument}`);
|
|
256
|
+
else snapshots.push(argument);
|
|
257
|
+
}
|
|
258
|
+
if (snapshots.length === 0) throw new Error(CLI_USAGE);
|
|
259
|
+
return {
|
|
260
|
+
model: model ?? await configuredDefaultModelId(),
|
|
261
|
+
out,
|
|
262
|
+
promptFile,
|
|
263
|
+
snapshots,
|
|
264
|
+
turnByTurn
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Read the app default model only when a run needs it. `chat/config` reads
|
|
269
|
+
* `DATABASE_URL` at import, and `briefs pull` must work with only a token.
|
|
270
|
+
*/
|
|
271
|
+
async function configuredDefaultModelId() {
|
|
272
|
+
const { botConfig } = await import("./config-CIE83sR2.js").then((n) => n.r);
|
|
273
|
+
return defaultModelId(botConfig);
|
|
274
|
+
}
|
|
275
|
+
function apiUrl(baseUrl, pathname) {
|
|
276
|
+
const base = new URL(baseUrl);
|
|
277
|
+
base.pathname = `${base.pathname.replace(/\/*$/, "")}/`;
|
|
278
|
+
base.search = "";
|
|
279
|
+
base.hash = "";
|
|
280
|
+
return new URL(pathname.replace(/^\//, ""), base);
|
|
281
|
+
}
|
|
282
|
+
async function fetchJson(url, token) {
|
|
283
|
+
const response = await fetch(url, { headers: {
|
|
284
|
+
accept: "application/json",
|
|
285
|
+
authorization: `Bearer ${token}`
|
|
286
|
+
} });
|
|
287
|
+
if (!response.ok) {
|
|
288
|
+
const body = (await response.text()).trim().slice(0, 500);
|
|
289
|
+
throw new Error(`Dashboard request failed (${response.status} ${response.statusText})${body ? `: ${body}` : ""}`);
|
|
290
|
+
}
|
|
291
|
+
return await response.json();
|
|
292
|
+
}
|
|
293
|
+
async function pullSnapshot(options, conversationId) {
|
|
294
|
+
const detailUrl = apiUrl(options.baseUrl, `api/conversations/${encodeURIComponent(conversationId)}`);
|
|
295
|
+
detailUrl.searchParams.set("limit", "1000");
|
|
296
|
+
const detail = conversationDetailReportSchema.parse(await fetchJson(detailUrl, options.token));
|
|
297
|
+
const eventPages = [];
|
|
298
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
299
|
+
let cursor = detail.previousCursor;
|
|
300
|
+
while (cursor) {
|
|
301
|
+
if (seenCursors.has(cursor)) throw new Error(`Conversation ${conversationId} repeated an event cursor`);
|
|
302
|
+
seenCursors.add(cursor);
|
|
303
|
+
const eventsUrl = apiUrl(options.baseUrl, `api/conversations/${encodeURIComponent(conversationId)}/events`);
|
|
304
|
+
eventsUrl.searchParams.set("before", cursor);
|
|
305
|
+
eventsUrl.searchParams.set("limit", "1000");
|
|
306
|
+
const page = conversationEventPageSchema.parse(await fetchJson(eventsUrl, options.token));
|
|
307
|
+
eventPages.push(page);
|
|
308
|
+
cursor = page.previousCursor;
|
|
309
|
+
}
|
|
310
|
+
return createConversationSnapshot({
|
|
311
|
+
detail,
|
|
312
|
+
eventPages
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
function fileStem(conversationId) {
|
|
316
|
+
const stem = conversationId.replaceAll(/[\\/\0]/g, "_");
|
|
317
|
+
if (!stem || stem === "." || stem === "..") throw new Error("Conversation id cannot be used as a file name");
|
|
318
|
+
return stem;
|
|
319
|
+
}
|
|
320
|
+
async function pullAll(options) {
|
|
321
|
+
await mkdir(options.out, { recursive: true });
|
|
322
|
+
for (const conversationId of options.conversationIds) {
|
|
323
|
+
const snapshot = await pullSnapshot(options, conversationId);
|
|
324
|
+
const output = path.join(options.out, `${fileStem(snapshot.detail.conversationId)}.snapshot.json`);
|
|
325
|
+
await writeFile(output, `${JSON.stringify(snapshot, void 0, 2)}\n`);
|
|
326
|
+
console.log(output);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function generationIndexes(snapshot, turnByTurn, throughIndex) {
|
|
330
|
+
if (!turnByTurn) return [throughIndex];
|
|
331
|
+
const indexes = completedTurnIndexesFromSnapshot(snapshot);
|
|
332
|
+
if (indexes.length === 0) throw new Error("Snapshot has no completed turns");
|
|
333
|
+
return indexes;
|
|
334
|
+
}
|
|
335
|
+
async function runSnapshot(snapshotPath, options, prompt) {
|
|
336
|
+
const snapshot = conversationSnapshotSchema.parse(JSON.parse(await readFile(snapshotPath, "utf8")));
|
|
337
|
+
const finalThroughIndex = throughIndexFromSnapshot(snapshot);
|
|
338
|
+
if (finalThroughIndex === void 0) throw new Error(`Snapshot ${snapshotPath} has no Conversation events`);
|
|
339
|
+
const input = briefInputFromSnapshot(snapshot, finalThroughIndex);
|
|
340
|
+
const versions = [];
|
|
341
|
+
for (const throughIndex of generationIndexes(snapshot, options.turnByTurn, finalThroughIndex)) versions.push(await generateBrief({
|
|
342
|
+
completeObject: (request) => completeObject({
|
|
343
|
+
...request,
|
|
344
|
+
modelId: options.model
|
|
345
|
+
}),
|
|
346
|
+
input: briefInputFromSnapshot(snapshot, throughIndex),
|
|
347
|
+
previous: versions.at(-1)?.brief,
|
|
348
|
+
prompt,
|
|
349
|
+
throughIndex
|
|
350
|
+
}));
|
|
351
|
+
const costs = versions.flatMap((version) => version.costUsd === void 0 ? [] : [version.costUsd]);
|
|
352
|
+
const totalCostUsd = costs.length > 0 ? costs.reduce((sum, cost) => sum + cost, 0) : void 0;
|
|
353
|
+
const stem = fileStem(input.conversationId);
|
|
354
|
+
const jsonPath = path.join(options.out, `${stem}.brief.json`);
|
|
355
|
+
const markdownPath = path.join(options.out, `${stem}.brief.md`);
|
|
356
|
+
const report = {
|
|
357
|
+
schemaVersion: 1,
|
|
358
|
+
conversationId: input.conversationId,
|
|
359
|
+
model: options.model,
|
|
360
|
+
versions,
|
|
361
|
+
...totalCostUsd !== void 0 ? { totalCostUsd } : void 0
|
|
362
|
+
};
|
|
363
|
+
await Promise.all([writeFile(jsonPath, `${JSON.stringify(report, void 0, 2)}\n`), writeFile(markdownPath, renderBriefMarkdown({
|
|
364
|
+
generation: versions.at(-1),
|
|
365
|
+
input,
|
|
366
|
+
model: options.model,
|
|
367
|
+
totalCostUsd,
|
|
368
|
+
versionCount: versions.length
|
|
369
|
+
}))]);
|
|
370
|
+
console.log(jsonPath);
|
|
371
|
+
console.log(markdownPath);
|
|
372
|
+
}
|
|
373
|
+
async function runAll(options) {
|
|
374
|
+
const prompt = options.promptFile ? await readFile(options.promptFile, "utf8") : BRIEF_PROMPT;
|
|
375
|
+
if (!prompt.trim()) throw new Error("Brief prompt must not be empty");
|
|
376
|
+
await mkdir(options.out, { recursive: true });
|
|
377
|
+
for (const snapshot of options.snapshots) await runSnapshot(snapshot, options, prompt);
|
|
378
|
+
}
|
|
379
|
+
/** Run `junior briefs pull` or `junior briefs run`. */
|
|
380
|
+
async function runBriefs(argv) {
|
|
381
|
+
try {
|
|
382
|
+
const [subcommand, ...rest] = argv;
|
|
383
|
+
if (subcommand === "pull") {
|
|
384
|
+
await pullAll(parsePullOptions(rest));
|
|
385
|
+
return 0;
|
|
386
|
+
}
|
|
387
|
+
if (subcommand === "run") {
|
|
388
|
+
await runAll(await parseRunOptions(rest));
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
391
|
+
throw new Error(CLI_USAGE);
|
|
392
|
+
} catch (error) {
|
|
393
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
394
|
+
return 1;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
//#endregion
|
|
398
|
+
export { runBriefs };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
|
|
2
|
-
import { t as createPluginCatalogRuntime } from "./registry-
|
|
2
|
+
import { t as createPluginCatalogRuntime } from "./registry-DiR0-xRg.js";
|
|
3
3
|
//#region src/chat/plugins/catalog-runtime.ts
|
|
4
4
|
var catalog_runtime_exports = /* @__PURE__ */ __exportAll({ pluginCatalogRuntime: () => pluginCatalogRuntime });
|
|
5
5
|
const pluginCatalogRuntime = createPluginCatalogRuntime();
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as setSpanAttributes, f as logWarn, o as getActiveTraceId, t as buildTurnFailureResponse, u as logException } from "./logging-
|
|
1
|
+
import { i as completeText, m as escapeXml, o as resolveGatewayModel, p as unwrapCurrentInstruction } from "./client-ceE7NtvC.js";
|
|
2
|
+
import { _ as setSpanAttributes, f as logWarn, o as getActiveTraceId, t as buildTurnFailureResponse, u as logException } from "./logging-D37bayDc.js";
|
|
3
|
+
import { n as botConfig } from "./config-CIE83sR2.js";
|
|
3
4
|
import { _ as parseSlackMessageTs, f as toStoredSlackActor } from "./context-B45_WqVX.js";
|
|
4
|
-
import { At as sanitizePostgresJson,
|
|
5
|
-
import {
|
|
6
|
-
import { c as generateShortTitle,
|
|
7
|
-
import { A as sleep, D as fenceLock, M as SANDBOX_REPOS_ROOT, P as SANDBOX_WORKSPACE_ROOT, T as MUTATION_LOCK_TTL_MS, k as withLock, w as getStateAdapter } from "./profile-
|
|
5
|
+
import { At as authenticationLinkedEvent, Bt as sanitizePostgresJson, Ft as getConversationStore, Lt as getSqlExecutor, Nt as getConversationEventStore, Ot as JUNIOR_NATIVE_EVENT_NAMESPACE, Rt as createSqlConversationEventStore, Ut as bindProviderConversation, jt as authenticationUnlinkedEvent, kt as agentsInstructionsUpdatedEvent, zt as withConversationEventLock } from "./agent-hooks-DNjlz2A-.js";
|
|
6
|
+
import { G as instructionProvenanceFor, I as agentHistoryItemSchema, U as contextProvenance, W as instructionActors } from "./conversation-AA4R1VUn.js";
|
|
7
|
+
import { c as generateShortTitle, o as ToolInputError, s as fallbackShortTitle, t as addAgentTurnUsage } from "./usage-D4A48Bdl.js";
|
|
8
|
+
import { A as sleep, D as fenceLock, M as SANDBOX_REPOS_ROOT, P as SANDBOX_WORKSPACE_ROOT, T as MUTATION_LOCK_TTL_MS, k as withLock, w as getStateAdapter } from "./profile-CSixooTi.js";
|
|
8
9
|
import path from "node:path";
|
|
9
10
|
import { isDeepStrictEqual } from "node:util";
|
|
10
11
|
import { z } from "zod";
|
package/dist/cli/chat.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as executeAgentRun } from "../agent-
|
|
2
|
-
import { t as createAgentRunner } from "../agent-runner-
|
|
1
|
+
import { t as executeAgentRun } from "../agent-C9yuiZUF.js";
|
|
2
|
+
import { t as createAgentRunner } from "../agent-runner-E67lFrDG.js";
|
|
3
3
|
import { t as loadAppPluginSet } from "../plugin-module-BKGOXca2.js";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -101,10 +101,10 @@ async function loadLocalPluginSet() {
|
|
|
101
101
|
async function configureLocalChatPlugins(pluginSet) {
|
|
102
102
|
const [pluginsModule, agentHooksModule, catalogRuntimeModule, validationModule, databaseModule] = await Promise.all([
|
|
103
103
|
import("../plugins-egKWjgue.js").then((n) => n.o),
|
|
104
|
-
import("../agent-hooks-
|
|
105
|
-
import("../catalog-runtime-
|
|
106
|
-
import("../validation-
|
|
107
|
-
import("../agent-hooks-
|
|
104
|
+
import("../agent-hooks-DNjlz2A-.js").then((n) => n.t),
|
|
105
|
+
import("../catalog-runtime-TBR8n4e1.js").then((n) => n.t),
|
|
106
|
+
import("../validation-jn_46o4U.js").then((n) => n.r),
|
|
107
|
+
import("../agent-hooks-DNjlz2A-.js").then((n) => n.Mt)
|
|
108
108
|
]);
|
|
109
109
|
const resolvedPluginSet = pluginSet === void 0 ? await loadLocalPluginSet() : pluginSet ?? void 0;
|
|
110
110
|
const plugins = pluginsModule.pluginRuntimeRegistrationsFromPluginSet(resolvedPluginSet);
|
|
@@ -156,14 +156,16 @@ async function prepareLocalChatRun(io, pluginSet) {
|
|
|
156
156
|
await configureLocalChatPlugins(pluginSet);
|
|
157
157
|
const { setExperimentalFeatures } = await import("../experimental-CIXf7Uye.js").then((n) => n.t);
|
|
158
158
|
setExperimentalFeatures({ subagents: true });
|
|
159
|
-
const {
|
|
160
|
-
|
|
159
|
+
const { setBriefsConfig } = await import("../agent-hooks-DNjlz2A-.js").then((n) => n.m);
|
|
160
|
+
setBriefsConfig({ enabled: true });
|
|
161
|
+
const { runLocalAgentTurn } = await import("../runner-DFx3dIJH.js");
|
|
162
|
+
const { startLocalOAuthCallbackServer } = await import("../oauth-callback-server-BtfOeHTZ.js");
|
|
161
163
|
const { createLocalOAuthState } = await import("../oauth-relay-CdCnu80W.js").then((n) => n.t);
|
|
162
|
-
const { createLocalSandboxEgressSignalTransport } = await import("../sandbox-egress-signals-
|
|
163
|
-
const { bindSpawnAgent } = await import("../spawn-
|
|
164
|
-
const { createAgentInvocationWorker, routeAgentInvocationWork } = await import("../work-
|
|
164
|
+
const { createLocalSandboxEgressSignalTransport } = await import("../sandbox-egress-signals-bwvjihxA.js");
|
|
165
|
+
const { bindSpawnAgent } = await import("../spawn-Dk0PqdH6.js").then((n) => n.n);
|
|
166
|
+
const { createAgentInvocationWorker, routeAgentInvocationWork } = await import("../work-Di-ubSGg.js").then((n) => n.a);
|
|
165
167
|
const { createLocalConversationWork } = await import("../conversation-work-C6y3T5Hx.js");
|
|
166
|
-
const { processConversationWork } = await import("../worker-
|
|
168
|
+
const { processConversationWork } = await import("../worker-Cu_D5Mr8.js").then((n) => n.n);
|
|
167
169
|
let agentRunner;
|
|
168
170
|
const localConversationWork = createLocalConversationWork(async (message) => {
|
|
169
171
|
if (!agentRunner) throw new Error("Local agent runner is not ready");
|
package/dist/cli/check.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { E as JUNIOR_HEARTBEAT_ROUTE, j as LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION, w as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE } from "../logging-
|
|
2
|
-
import { d as parseInlinePluginManifest, f as parsePluginManifest } from "../registry-
|
|
3
|
-
import { i as parseSkillFile } from "../skills-
|
|
1
|
+
import { E as JUNIOR_HEARTBEAT_ROUTE, j as LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION, w as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE } from "../logging-D37bayDc.js";
|
|
2
|
+
import { d as parseInlinePluginManifest, f as parsePluginManifest } from "../registry-DiR0-xRg.js";
|
|
3
|
+
import { i as parseSkillFile } from "../skills-BhM5qyCF.js";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import fs from "node:fs/promises";
|
package/dist/cli/init.js
CHANGED
package/dist/cli/main.js
CHANGED
|
@@ -24,6 +24,9 @@ async function runUpgrade(pluginSet) {
|
|
|
24
24
|
async function runChat(argv, pluginSet) {
|
|
25
25
|
return await (await import("./chat.js")).runChat(argv, void 0, { pluginSet });
|
|
26
26
|
}
|
|
27
|
+
async function runBriefs(argv) {
|
|
28
|
+
return await (await import("../briefs-CvJFQvhJ.js")).runBriefs(argv);
|
|
29
|
+
}
|
|
27
30
|
function topLevelCommand(argv) {
|
|
28
31
|
return (argv[0] === "--" ? argv.slice(1) : argv)[0];
|
|
29
32
|
}
|
|
@@ -33,10 +36,11 @@ async function runMain(argv, options = {}) {
|
|
|
33
36
|
const instrument = options.instrument ?? true;
|
|
34
37
|
if (instrument) await initSentry();
|
|
35
38
|
const command = topLevelCommand(argv);
|
|
36
|
-
const cliPluginsModule = command && command !== "init" ? await import("./plugins.js") : void 0;
|
|
39
|
+
const cliPluginsModule = command && command !== "init" && command !== "briefs" ? await import("./plugins.js") : void 0;
|
|
37
40
|
const pluginSet = cliPluginsModule ? await cliPluginsModule.loadCliPluginSet() ?? null : void 0;
|
|
38
41
|
const pluginCommands = cliPluginsModule ? await cliPluginsModule.loadCliPluginCommands(pluginSet) : void 0;
|
|
39
42
|
const exitCode = await runCli(argv, {
|
|
43
|
+
runBriefs,
|
|
40
44
|
runChat: async (chatArgv) => await runChat(chatArgv, pluginSet),
|
|
41
45
|
runInit,
|
|
42
46
|
runSnapshotCreate,
|
package/dist/cli/plugins.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as pluginCatalogRuntime } from "../catalog-runtime-
|
|
3
|
-
import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-
|
|
1
|
+
import { It as getDb, bt as createPluginLogger, d as setPlugins, f as validatePlugins } from "../agent-hooks-DNjlz2A-.js";
|
|
2
|
+
import { n as pluginCatalogRuntime } from "../catalog-runtime-TBR8n4e1.js";
|
|
3
|
+
import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-jn_46o4U.js";
|
|
4
4
|
import { a as pluginRuntimeRegistrationsFromPluginSet, i as pluginCliRegistrationsFromPluginSet, r as pluginCatalogConfigFromPluginSet } from "../plugins-egKWjgue.js";
|
|
5
5
|
import { t as loadAppPluginSet } from "../plugin-module-BKGOXca2.js";
|
|
6
6
|
import { stderr, stdout } from "node:process";
|
package/dist/cli/run.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/cli/run.d.ts
|
|
2
|
-
export declare const 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>";
|
|
2
|
+
export declare const 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>\n junior briefs pull <conversationId...> --base-url <url> [--token <token>] --out <dir>\n junior briefs run <snapshot...> [--model <id>] [--prompt <file>] [--turn-by-turn] [--out <dir>]";
|
|
3
3
|
interface CliHandlers {
|
|
4
|
+
runBriefs: (argv: string[]) => Promise<number>;
|
|
4
5
|
runChat: (argv: string[]) => Promise<number>;
|
|
5
6
|
runInit: (dir: string) => Promise<void>;
|
|
6
7
|
runSnapshotCreate: () => Promise<void>;
|
package/dist/cli/run.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/cli/run.ts
|
|
2
|
-
const 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>";
|
|
2
|
+
const 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>\n junior briefs pull <conversationId...> --base-url <url> [--token <token>] --out <dir>\n junior briefs run <snapshot...> [--model <id>] [--prompt <file>] [--turn-by-turn] [--out <dir>]";
|
|
3
3
|
const DEFAULT_IO = { error: console.error };
|
|
4
4
|
/** Strip Node's leading argv separator while preserving command-level flags. */
|
|
5
5
|
function normalizeCliArgv(argv) {
|
|
@@ -9,6 +9,7 @@ function normalizeCliArgv(argv) {
|
|
|
9
9
|
async function runCli(argv, handlers, io = DEFAULT_IO) {
|
|
10
10
|
const [command, subcommand, ...rest] = normalizeCliArgv(argv);
|
|
11
11
|
if (command === "chat") return await handlers.runChat(subcommand === void 0 ? [] : [subcommand, ...rest]);
|
|
12
|
+
if (command === "briefs") return await handlers.runBriefs(subcommand === void 0 ? [] : [subcommand, ...rest]);
|
|
12
13
|
if (command === "init") {
|
|
13
14
|
if (!subcommand || rest.length > 0) {
|
|
14
15
|
io.error(CLI_USAGE);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as pluginCatalogRuntime } from "../catalog-runtime-
|
|
2
|
-
import { S as disconnectStateAdapter, t as create } from "../profile-
|
|
3
|
-
import { r as resolve } from "../resolve-
|
|
1
|
+
import { n as pluginCatalogRuntime } from "../catalog-runtime-TBR8n4e1.js";
|
|
2
|
+
import { S as disconnectStateAdapter, t as create } from "../profile-CSixooTi.js";
|
|
3
|
+
import { r as resolve } from "../resolve-Bn5q__9b.js";
|
|
4
4
|
//#region src/cli/snapshot-create.ts
|
|
5
5
|
const DEFAULT_RUNTIME = "node22";
|
|
6
6
|
const DEFAULT_TIMEOUT_MS = 6e5;
|
package/dist/cli/upgrade.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as createJuniorSqlExecutor } from "../executor-
|
|
3
|
-
import { t as createPluginCatalogRuntime } from "../registry-
|
|
1
|
+
import { a as getChatConfig } from "../config-CIE83sR2.js";
|
|
2
|
+
import { t as createJuniorSqlExecutor } from "../executor-BfbYPW63.js";
|
|
3
|
+
import { t as createPluginCatalogRuntime } from "../registry-DiR0-xRg.js";
|
|
4
4
|
import { n as pluginCatalogConfigFromEnv, r as pluginCatalogConfigFromPluginSet, t as defineJuniorPlugins } from "../plugins-egKWjgue.js";
|
|
5
5
|
import { t as loadAppPluginSet } from "../plugin-module-BKGOXca2.js";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|