@sentry/junior 0.62.0 → 0.64.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/README.md +5 -1
- package/dist/api-reference.d.ts +2 -0
- package/dist/app.d.ts +5 -10
- package/dist/app.js +348 -874
- package/dist/build/virtual-config.d.ts +18 -2
- package/dist/chat/logging.d.ts +12 -2
- package/dist/chat/plugins/agent-hooks.d.ts +11 -4
- package/dist/chat/plugins/inline-manifest-source.d.ts +5 -0
- package/dist/chat/plugins/manifest.d.ts +5 -3
- package/dist/chat/plugins/package-discovery.d.ts +5 -0
- package/dist/chat/plugins/registry.d.ts +2 -2
- package/dist/chat/plugins/types.d.ts +8 -3
- package/dist/chat/prompt.d.ts +0 -1
- package/dist/chat/state/turn-session.d.ts +1 -1
- package/dist/{chunk-I4FDGMFI.js → chunk-4CRYMG7M.js} +787 -31
- package/dist/chunk-5VDO6LSG.js +104 -0
- package/dist/{chunk-ITOW4DED.js → chunk-D23WCM66.js} +2 -2
- package/dist/{chunk-FKEKRBUB.js → chunk-IGVHCX2U.js} +28 -2
- package/dist/{chunk-5LUISFEY.js → chunk-KVZL5NZS.js} +6 -1
- package/dist/{chunk-H652GMDH.js → chunk-WDPWFMCE.js} +297 -84
- package/dist/{chunk-QDGD5WVN.js → chunk-WZFQQ6SP.js} +3 -28
- package/dist/cli/check.js +9 -4
- package/dist/cli/snapshot-warmup.js +4 -4
- package/dist/nitro.d.ts +10 -3
- package/dist/nitro.js +161 -6
- package/dist/plugins.d.ts +22 -0
- package/dist/reporting.d.ts +26 -11
- package/dist/reporting.js +62 -25
- package/package.json +3 -3
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
SANDBOX_WORKSPACE_ROOT,
|
|
2
3
|
getStateAdapter,
|
|
3
4
|
toOptionalTrimmed
|
|
4
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-IGVHCX2U.js";
|
|
5
6
|
import {
|
|
6
7
|
getPluginRuntimeDependencies,
|
|
7
8
|
getPluginRuntimePostinstall,
|
|
8
9
|
withSpan
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WDPWFMCE.js";
|
|
10
11
|
|
|
11
12
|
// src/chat/sandbox/runtime-dependency-snapshots.ts
|
|
12
13
|
import { createHash } from "crypto";
|
|
@@ -128,27 +129,6 @@ function createSandboxInstance(sandbox) {
|
|
|
128
129
|
};
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
// src/chat/sandbox/paths.ts
|
|
132
|
-
function normalizeWorkspaceRoot(input) {
|
|
133
|
-
const candidate = (input ?? "").trim();
|
|
134
|
-
if (!candidate) {
|
|
135
|
-
return "/vercel/sandbox";
|
|
136
|
-
}
|
|
137
|
-
const normalized = candidate.replace(/\/+$/, "");
|
|
138
|
-
return normalized.startsWith("/") ? normalized : `/${normalized}`;
|
|
139
|
-
}
|
|
140
|
-
var SANDBOX_WORKSPACE_ROOT = normalizeWorkspaceRoot(
|
|
141
|
-
process.env.VERCEL_SANDBOX_WORKSPACE_DIR
|
|
142
|
-
);
|
|
143
|
-
var SANDBOX_SKILLS_ROOT = `${SANDBOX_WORKSPACE_ROOT}/skills`;
|
|
144
|
-
var SANDBOX_DATA_ROOT = `${SANDBOX_WORKSPACE_ROOT}/data`;
|
|
145
|
-
function sandboxSkillDir(skillName) {
|
|
146
|
-
return `${SANDBOX_SKILLS_ROOT}/${skillName}`;
|
|
147
|
-
}
|
|
148
|
-
function sandboxSkillFile(skillName) {
|
|
149
|
-
return `${sandboxSkillDir(skillName)}/SKILL.md`;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
132
|
// src/chat/sandbox/runtime-dependency-snapshots.ts
|
|
153
133
|
var SNAPSHOT_CACHE_PREFIX = "junior:sandbox_snapshot_profile";
|
|
154
134
|
var SNAPSHOT_LOCK_PREFIX = "junior:sandbox_snapshot_lock";
|
|
@@ -693,11 +673,6 @@ function isSnapshotMissingError(error) {
|
|
|
693
673
|
}
|
|
694
674
|
|
|
695
675
|
export {
|
|
696
|
-
SANDBOX_WORKSPACE_ROOT,
|
|
697
|
-
SANDBOX_SKILLS_ROOT,
|
|
698
|
-
SANDBOX_DATA_ROOT,
|
|
699
|
-
sandboxSkillDir,
|
|
700
|
-
sandboxSkillFile,
|
|
701
676
|
buildNonInteractiveShellScript,
|
|
702
677
|
runNonInteractiveCommand,
|
|
703
678
|
getVercelSandboxCredentials,
|
package/dist/cli/check.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseSkillFile
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-D23WCM66.js";
|
|
4
4
|
import {
|
|
5
5
|
parsePluginManifest
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-WDPWFMCE.js";
|
|
7
7
|
import "../chunk-Z3YD6NHK.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-KVZL5NZS.js";
|
|
9
9
|
import "../chunk-2KG3PWR4.js";
|
|
10
10
|
|
|
11
11
|
// src/cli/check.ts
|
|
@@ -396,7 +396,12 @@ async function validateAppSourceFiles(rootDir, registeredConfigKeys) {
|
|
|
396
396
|
}
|
|
397
397
|
if (/\bpluginPackages\s*:/.test(source)) {
|
|
398
398
|
errors.push(
|
|
399
|
-
`${sourcePath}: pluginPackages is no longer supported.
|
|
399
|
+
`${sourcePath}: pluginPackages is no longer supported. Export a defineJuniorPlugins(...) set and point juniorNitro({ plugins: "./plugins" }) at it.`
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
if (/\bplugins\s*:\s*\{\s*packages\s*:/.test(source)) {
|
|
403
|
+
errors.push(
|
|
404
|
+
`${sourcePath}: plugins.packages is no longer supported. Export a defineJuniorPlugins(...) set and point juniorNitro({ plugins: "./plugins" }) at it.`
|
|
400
405
|
);
|
|
401
406
|
}
|
|
402
407
|
for (const defaultsBlock of source.matchAll(
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveRuntimeDependencySnapshot
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-WZFQQ6SP.js";
|
|
4
4
|
import {
|
|
5
5
|
disconnectStateAdapter
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-IGVHCX2U.js";
|
|
7
7
|
import {
|
|
8
8
|
getPluginProviders,
|
|
9
9
|
getPluginRuntimeDependencies,
|
|
10
10
|
getPluginRuntimePostinstall
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-WDPWFMCE.js";
|
|
12
12
|
import "../chunk-Z3YD6NHK.js";
|
|
13
|
-
import "../chunk-
|
|
13
|
+
import "../chunk-KVZL5NZS.js";
|
|
14
14
|
import "../chunk-2KG3PWR4.js";
|
|
15
15
|
|
|
16
16
|
// src/cli/snapshot-warmup.ts
|
package/dist/nitro.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type JuniorPluginSet } from "@/plugins";
|
|
2
|
+
export interface JuniorPluginModuleReference {
|
|
3
|
+
/** Runtime-safe module that exports a `defineJuniorPlugins(...)` set. */
|
|
4
|
+
module: string;
|
|
5
|
+
/** Named export to import from `module`. Defaults to `plugins`. */
|
|
6
|
+
exportName?: string;
|
|
7
|
+
}
|
|
8
|
+
export type JuniorNitroPluginSource = JuniorPluginModuleReference | JuniorPluginSet | string;
|
|
2
9
|
export interface JuniorNitroOptions {
|
|
3
10
|
cwd?: string;
|
|
4
11
|
maxDuration?: number;
|
|
5
|
-
/** Plugin
|
|
6
|
-
plugins?:
|
|
12
|
+
/** Plugin catalog set or runtime-safe plugin module. Direct sets must not include trusted hooks. */
|
|
13
|
+
plugins?: JuniorNitroPluginSource;
|
|
7
14
|
/**
|
|
8
15
|
* Extra file patterns to copy into the server output for files that the
|
|
9
16
|
* bundler cannot trace (e.g. dynamically imported providers).
|
package/dist/nitro.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pluginCatalogConfigFromPluginSet,
|
|
3
|
+
trustedPluginRegistrationsFromPluginSet
|
|
4
|
+
} from "./chunk-5VDO6LSG.js";
|
|
1
5
|
import {
|
|
2
6
|
discoverInstalledPluginPackageContent,
|
|
3
7
|
isValidPackageName,
|
|
4
8
|
resolvePackageDir
|
|
5
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KVZL5NZS.js";
|
|
6
10
|
import "./chunk-2KG3PWR4.js";
|
|
7
11
|
|
|
8
12
|
// src/nitro.ts
|
|
9
13
|
import path2 from "path";
|
|
14
|
+
import { statSync as statSync2 } from "fs";
|
|
15
|
+
import { createRequire } from "module";
|
|
16
|
+
import { pathToFileURL } from "url";
|
|
10
17
|
|
|
11
18
|
// src/build/rolldown-workarounds.ts
|
|
12
19
|
function applyRolldownTreeshakeWorkaround(nitro) {
|
|
@@ -166,11 +173,135 @@ function nodeModulesRelativePath(sourcePath) {
|
|
|
166
173
|
}
|
|
167
174
|
|
|
168
175
|
// src/build/virtual-config.ts
|
|
169
|
-
function
|
|
170
|
-
|
|
176
|
+
function renderRuntimePluginImport(module) {
|
|
177
|
+
if (module.exportName === "default") {
|
|
178
|
+
return `import juniorRuntimePluginSet from ${JSON.stringify(module.specifier)};`;
|
|
179
|
+
}
|
|
180
|
+
return `import { ${module.exportName} as juniorRuntimePluginSet } from ${JSON.stringify(module.specifier)};`;
|
|
181
|
+
}
|
|
182
|
+
function renderVirtualConfig(options) {
|
|
183
|
+
const lines = [
|
|
184
|
+
...options.pluginModule ? [
|
|
185
|
+
renderRuntimePluginImport(options.pluginModule),
|
|
186
|
+
"export const pluginSet = juniorRuntimePluginSet;"
|
|
187
|
+
] : ["export const pluginSet = undefined;"],
|
|
188
|
+
`export const plugins = ${JSON.stringify(options.plugins ?? { packages: [] })};`,
|
|
189
|
+
`export const trustedPluginRegistrations = ${JSON.stringify(options.trustedPluginRegistrations ?? [])};`
|
|
190
|
+
];
|
|
191
|
+
return lines.join("\n");
|
|
192
|
+
}
|
|
193
|
+
function injectVirtualConfig(nitro, options = {}) {
|
|
194
|
+
nitro.options.virtual["#junior/config"] = async () => {
|
|
195
|
+
if (!options.loadPluginSet) {
|
|
196
|
+
return renderVirtualConfig(options);
|
|
197
|
+
}
|
|
198
|
+
const pluginSet = await options.loadPluginSet();
|
|
199
|
+
return renderVirtualConfig({
|
|
200
|
+
pluginModule: options.pluginModule,
|
|
201
|
+
plugins: pluginCatalogConfigFromPluginSet(pluginSet),
|
|
202
|
+
trustedPluginRegistrations: trustedPluginRegistrationsFromPluginSet(
|
|
203
|
+
pluginSet
|
|
204
|
+
).map((plugin) => plugin.name)
|
|
205
|
+
});
|
|
206
|
+
};
|
|
171
207
|
}
|
|
172
208
|
|
|
173
209
|
// src/nitro.ts
|
|
210
|
+
var PLUGIN_MODULE_EXTENSIONS = [
|
|
211
|
+
"",
|
|
212
|
+
".ts",
|
|
213
|
+
".tsx",
|
|
214
|
+
".mts",
|
|
215
|
+
".mjs",
|
|
216
|
+
".js",
|
|
217
|
+
".cjs"
|
|
218
|
+
];
|
|
219
|
+
function isPluginModuleReference(value) {
|
|
220
|
+
return typeof value === "string" || Boolean(value && "module" in value);
|
|
221
|
+
}
|
|
222
|
+
function isPluginSet(value) {
|
|
223
|
+
if (!value || typeof value !== "object") {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
return "packageNames" in value && "registrations" in value;
|
|
227
|
+
}
|
|
228
|
+
function resolveRelativePluginModule(cwd, specifier) {
|
|
229
|
+
const basePath = path2.resolve(cwd, specifier);
|
|
230
|
+
for (const extension of PLUGIN_MODULE_EXTENSIONS) {
|
|
231
|
+
const candidate = `${basePath}${extension}`;
|
|
232
|
+
try {
|
|
233
|
+
if (statSync2(candidate).isFile()) {
|
|
234
|
+
return candidate;
|
|
235
|
+
}
|
|
236
|
+
} catch {
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
for (const extension of PLUGIN_MODULE_EXTENSIONS) {
|
|
240
|
+
const candidate = path2.join(basePath, `index${extension}`);
|
|
241
|
+
try {
|
|
242
|
+
if (statSync2(candidate).isFile()) {
|
|
243
|
+
return candidate;
|
|
244
|
+
}
|
|
245
|
+
} catch {
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
throw new Error(`Plugin module "${specifier}" could not be resolved`);
|
|
249
|
+
}
|
|
250
|
+
function resolvePluginModule(cwd, input) {
|
|
251
|
+
const moduleSpecifier = typeof input === "string" ? input : input.module;
|
|
252
|
+
const exportName = typeof input === "string" ? "plugins" : input.exportName ?? "plugins";
|
|
253
|
+
if (!moduleSpecifier.trim()) {
|
|
254
|
+
throw new Error("Plugin module specifier must not be empty");
|
|
255
|
+
}
|
|
256
|
+
if (moduleSpecifier.startsWith(".") || path2.isAbsolute(moduleSpecifier)) {
|
|
257
|
+
const resolvedPath2 = resolveRelativePluginModule(cwd, moduleSpecifier);
|
|
258
|
+
return {
|
|
259
|
+
exportName,
|
|
260
|
+
importUrl: pathToFileURL(resolvedPath2).href,
|
|
261
|
+
runtimeModule: {
|
|
262
|
+
exportName,
|
|
263
|
+
specifier: resolvedPath2.split(path2.sep).join("/")
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
const requireFromApp = createRequire(path2.join(cwd, "package.json"));
|
|
268
|
+
const resolvedPath = requireFromApp.resolve(moduleSpecifier);
|
|
269
|
+
return {
|
|
270
|
+
exportName,
|
|
271
|
+
importUrl: pathToFileURL(resolvedPath).href,
|
|
272
|
+
runtimeModule: {
|
|
273
|
+
exportName,
|
|
274
|
+
specifier: moduleSpecifier
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function assertPluginSet(value, source) {
|
|
279
|
+
if (!value || typeof value !== "object" || !Array.isArray(value.packageNames) || !Array.isArray(value.registrations)) {
|
|
280
|
+
throw new Error(
|
|
281
|
+
`Plugin module ${source} must export a defineJuniorPlugins(...) set`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
return value;
|
|
285
|
+
}
|
|
286
|
+
async function loadPluginSetFromModule(moduleRef) {
|
|
287
|
+
const mod = await import(moduleRef.importUrl);
|
|
288
|
+
const value = moduleRef.exportName === "default" ? mod.default : mod[moduleRef.exportName];
|
|
289
|
+
return assertPluginSet(
|
|
290
|
+
value,
|
|
291
|
+
`${moduleRef.importUrl}#${moduleRef.exportName}`
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
function assertSerializableDirectPluginSet(pluginSet) {
|
|
295
|
+
const trustedPluginNames = trustedPluginRegistrationsFromPluginSet(
|
|
296
|
+
pluginSet
|
|
297
|
+
).map((plugin) => plugin.name);
|
|
298
|
+
if (trustedPluginNames.length === 0) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
throw new Error(
|
|
302
|
+
`juniorNitro({ plugins }) cannot receive a direct defineJuniorPlugins(...) set with trusted plugin registration(s): ${trustedPluginNames.join(", ")}. Export the set from a runtime-safe plugin module and pass juniorNitro({ plugins: "./plugins" }) so createApp() can import the same hooks at runtime.`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
174
305
|
function juniorNitro(options = {}) {
|
|
175
306
|
return {
|
|
176
307
|
nitro: {
|
|
@@ -182,12 +313,36 @@ function juniorNitro(options = {}) {
|
|
|
182
313
|
nitro.options.vercel.functions ??= {};
|
|
183
314
|
nitro.options.vercel.functions.maxDuration ??= options.maxDuration ?? 800;
|
|
184
315
|
applyRolldownTreeshakeWorkaround(nitro);
|
|
185
|
-
|
|
186
|
-
|
|
316
|
+
const pluginSource = options.plugins;
|
|
317
|
+
const pluginModule = isPluginModuleReference(pluginSource) ? resolvePluginModule(cwd, pluginSource) : void 0;
|
|
318
|
+
const directPluginSet = isPluginSet(pluginSource) ? pluginSource : void 0;
|
|
319
|
+
if (directPluginSet) {
|
|
320
|
+
assertSerializableDirectPluginSet(directPluginSet);
|
|
321
|
+
}
|
|
322
|
+
let pluginSetPromise;
|
|
323
|
+
const loadConfiguredPluginSet = () => {
|
|
324
|
+
pluginSetPromise ??= pluginModule ? loadPluginSetFromModule(pluginModule) : Promise.resolve(directPluginSet);
|
|
325
|
+
return pluginSetPromise;
|
|
326
|
+
};
|
|
327
|
+
const pluginCatalogConfig = pluginCatalogConfigFromPluginSet(directPluginSet);
|
|
328
|
+
const trustedPluginRegistrations = trustedPluginRegistrationsFromPluginSet(directPluginSet).map(
|
|
329
|
+
(plugin) => plugin.name
|
|
330
|
+
);
|
|
331
|
+
injectVirtualConfig(nitro, {
|
|
332
|
+
...pluginModule ? {
|
|
333
|
+
loadPluginSet: loadConfiguredPluginSet,
|
|
334
|
+
pluginModule: pluginModule.runtimeModule
|
|
335
|
+
} : {},
|
|
336
|
+
plugins: pluginCatalogConfig,
|
|
337
|
+
trustedPluginRegistrations
|
|
338
|
+
});
|
|
339
|
+
nitro.hooks.hook("compiled", async () => {
|
|
340
|
+
const pluginSet = await loadConfiguredPluginSet();
|
|
341
|
+
const compiledPluginCatalogConfig = pluginCatalogConfigFromPluginSet(pluginSet);
|
|
187
342
|
copyAppAndPluginContent(
|
|
188
343
|
cwd,
|
|
189
344
|
nitro.options.output.serverDir,
|
|
190
|
-
|
|
345
|
+
compiledPluginCatalogConfig?.packages
|
|
191
346
|
);
|
|
192
347
|
copyIncludedFiles(
|
|
193
348
|
cwd,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { JuniorPluginRegistration } from "@sentry/junior-plugin-api";
|
|
2
|
+
import type { PluginCatalogConfig, PluginManifestConfig } from "@/chat/plugins/types";
|
|
3
|
+
export type JuniorPluginInput = JuniorPluginRegistration | string;
|
|
4
|
+
export interface JuniorPluginSetOptions {
|
|
5
|
+
/** Install-level manifest overrides applied before validation. */
|
|
6
|
+
manifests?: Record<string, PluginManifestConfig>;
|
|
7
|
+
}
|
|
8
|
+
/** Reusable plugin registrations and manifest overrides. */
|
|
9
|
+
export interface JuniorPluginSet {
|
|
10
|
+
/** Install-level manifest overrides applied before validation. */
|
|
11
|
+
manifests?: Record<string, PluginManifestConfig>;
|
|
12
|
+
/** Manifest-only plugin packages included by package name. */
|
|
13
|
+
packageNames: string[];
|
|
14
|
+
/** JavaScript plugin definitions included by package factories. */
|
|
15
|
+
registrations: JuniorPluginRegistration[];
|
|
16
|
+
}
|
|
17
|
+
/** Define package-name plugins and JS plugin definitions for one app. */
|
|
18
|
+
export declare function defineJuniorPlugins(inputs: JuniorPluginInput[], options?: JuniorPluginSetOptions): JuniorPluginSet;
|
|
19
|
+
/** Build the manifest catalog config implied by one plugin set. */
|
|
20
|
+
export declare function pluginCatalogConfigFromPluginSet(pluginSet: JuniorPluginSet | undefined): PluginCatalogConfig | undefined;
|
|
21
|
+
/** Return registrations that expose trusted in-process runtime behavior. */
|
|
22
|
+
export declare function trustedPluginRegistrationsFromPluginSet(pluginSet: JuniorPluginSet | undefined): JuniorPluginRegistration[];
|
package/dist/reporting.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { AgentTurnUsage } from "@/chat/usage";
|
|
2
1
|
import { getPluginPackageContent } from "@/chat/plugins/registry";
|
|
3
|
-
import { type AgentTurnRequester } from "@/chat/state/turn-session";
|
|
4
2
|
export interface HealthReport {
|
|
5
3
|
status: "ok";
|
|
6
4
|
service: string;
|
|
@@ -21,27 +19,42 @@ export interface RuntimeInfoReport {
|
|
|
21
19
|
skills: SkillReport[];
|
|
22
20
|
packagedContent: ReturnType<typeof getPluginPackageContent>;
|
|
23
21
|
}
|
|
22
|
+
export type DashboardSessionStatus = "active" | "completed" | "failed" | "hung" | "superseded";
|
|
23
|
+
export type DashboardSurface = "slack" | "api" | "scheduler" | "internal";
|
|
24
|
+
export interface DashboardTurnUsage {
|
|
25
|
+
inputTokens?: number;
|
|
26
|
+
outputTokens?: number;
|
|
27
|
+
cachedInputTokens?: number;
|
|
28
|
+
cacheCreationTokens?: number;
|
|
29
|
+
totalTokens?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface DashboardRequesterIdentity {
|
|
32
|
+
email?: string;
|
|
33
|
+
fullName?: string;
|
|
34
|
+
slackUserId?: string;
|
|
35
|
+
slackUserName?: string;
|
|
36
|
+
}
|
|
24
37
|
export interface DashboardSessionReport {
|
|
25
38
|
conversationTitle?: string;
|
|
26
|
-
cumulativeDurationMs
|
|
27
|
-
cumulativeUsage?:
|
|
39
|
+
cumulativeDurationMs: number;
|
|
40
|
+
cumulativeUsage?: DashboardTurnUsage;
|
|
28
41
|
conversationId: string;
|
|
29
42
|
id: string;
|
|
30
|
-
status:
|
|
43
|
+
status: DashboardSessionStatus;
|
|
31
44
|
startedAt: string;
|
|
32
45
|
lastSeenAt: string;
|
|
33
46
|
lastProgressAt: string;
|
|
34
47
|
completedAt?: string;
|
|
35
|
-
surface
|
|
36
|
-
title
|
|
37
|
-
|
|
38
|
-
requesterIdentity?: AgentTurnRequester;
|
|
48
|
+
surface: DashboardSurface;
|
|
49
|
+
title: string;
|
|
50
|
+
requesterIdentity?: DashboardRequesterIdentity;
|
|
39
51
|
channel?: string;
|
|
40
52
|
channelName?: string;
|
|
41
53
|
sentryConversationUrl?: string;
|
|
42
54
|
sentryTraceUrl?: string;
|
|
43
55
|
traceId?: string;
|
|
44
56
|
}
|
|
57
|
+
export type DashboardTranscriptPartType = "text" | "thinking" | "tool_call" | "tool_result" | "unknown";
|
|
45
58
|
export interface DashboardTranscriptPart {
|
|
46
59
|
bytes?: number;
|
|
47
60
|
chars?: number;
|
|
@@ -58,12 +71,14 @@ export interface DashboardTranscriptPart {
|
|
|
58
71
|
outputSizeChars?: number;
|
|
59
72
|
outputType?: string;
|
|
60
73
|
redacted?: boolean;
|
|
74
|
+
sourceType?: string;
|
|
61
75
|
text?: string;
|
|
62
|
-
type:
|
|
76
|
+
type: DashboardTranscriptPartType;
|
|
63
77
|
}
|
|
78
|
+
export type DashboardTranscriptRole = "assistant" | "system" | "tool" | "toolResult" | "unknown" | "user";
|
|
64
79
|
export interface DashboardTranscriptMessage {
|
|
65
80
|
parts: DashboardTranscriptPart[];
|
|
66
|
-
role:
|
|
81
|
+
role: DashboardTranscriptRole;
|
|
67
82
|
timestamp?: number;
|
|
68
83
|
}
|
|
69
84
|
export interface DashboardTurnReport extends DashboardSessionReport {
|
package/dist/reporting.js
CHANGED
|
@@ -2,27 +2,28 @@ import {
|
|
|
2
2
|
GET,
|
|
3
3
|
buildSentryConversationUrl,
|
|
4
4
|
buildSentryTraceUrl,
|
|
5
|
+
buildSystemPrompt,
|
|
5
6
|
getAgentTurnSessionRecord,
|
|
6
7
|
listAgentTurnSessionSummaries,
|
|
7
8
|
listAgentTurnSessionSummariesForConversation
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4CRYMG7M.js";
|
|
9
10
|
import {
|
|
10
11
|
discoverSkills
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-D23WCM66.js";
|
|
12
13
|
import {
|
|
13
14
|
canExposeConversationPayload,
|
|
14
15
|
parseSlackThreadId,
|
|
15
16
|
resolveConversationPrivacy
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IGVHCX2U.js";
|
|
17
18
|
import {
|
|
18
19
|
getPluginPackageContent,
|
|
19
20
|
getPluginProviders,
|
|
20
21
|
isRecord
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-WDPWFMCE.js";
|
|
22
23
|
import "./chunk-Z3YD6NHK.js";
|
|
23
24
|
import {
|
|
24
25
|
homeDir
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-KVZL5NZS.js";
|
|
26
27
|
import "./chunk-2KG3PWR4.js";
|
|
27
28
|
|
|
28
29
|
// src/reporting.ts
|
|
@@ -79,10 +80,6 @@ function titleFromSummary(summary) {
|
|
|
79
80
|
}
|
|
80
81
|
return `Turn ${summary.sessionId}`;
|
|
81
82
|
}
|
|
82
|
-
function requesterLabel(requester) {
|
|
83
|
-
if (!requester) return void 0;
|
|
84
|
-
return requester.email ?? requester.slackUserName ?? requester.fullName ?? requester.slackUserId;
|
|
85
|
-
}
|
|
86
83
|
function safePrivateLabel(summary) {
|
|
87
84
|
const slackThread = parseSlackThreadId(summary.conversationId);
|
|
88
85
|
if (slackThread?.channelId.startsWith("D")) {
|
|
@@ -93,6 +90,27 @@ function safePrivateLabel(summary) {
|
|
|
93
90
|
}
|
|
94
91
|
return "Private Channel";
|
|
95
92
|
}
|
|
93
|
+
function requesterIdentityReport(requester) {
|
|
94
|
+
if (!requester) return void 0;
|
|
95
|
+
const identity = {
|
|
96
|
+
...requester.email !== void 0 ? { email: requester.email } : {},
|
|
97
|
+
...requester.fullName !== void 0 ? { fullName: requester.fullName } : {},
|
|
98
|
+
...requester.slackUserId !== void 0 ? { slackUserId: requester.slackUserId } : {},
|
|
99
|
+
...requester.slackUserName !== void 0 ? { slackUserName: requester.slackUserName } : {}
|
|
100
|
+
};
|
|
101
|
+
return Object.keys(identity).length > 0 ? identity : void 0;
|
|
102
|
+
}
|
|
103
|
+
function turnUsageReport(usage) {
|
|
104
|
+
if (!usage) return void 0;
|
|
105
|
+
const report = {
|
|
106
|
+
...usage.inputTokens !== void 0 ? { inputTokens: usage.inputTokens } : {},
|
|
107
|
+
...usage.outputTokens !== void 0 ? { outputTokens: usage.outputTokens } : {},
|
|
108
|
+
...usage.cachedInputTokens !== void 0 ? { cachedInputTokens: usage.cachedInputTokens } : {},
|
|
109
|
+
...usage.cacheCreationTokens !== void 0 ? { cacheCreationTokens: usage.cacheCreationTokens } : {},
|
|
110
|
+
...usage.totalTokens !== void 0 ? { totalTokens: usage.totalTokens } : {}
|
|
111
|
+
};
|
|
112
|
+
return Object.keys(report).length > 0 ? report : void 0;
|
|
113
|
+
}
|
|
96
114
|
function sessionReportFromSummary(summary) {
|
|
97
115
|
const slackThread = parseSlackThreadId(summary.conversationId);
|
|
98
116
|
const privacy = resolveConversationPrivacy({
|
|
@@ -101,11 +119,12 @@ function sessionReportFromSummary(summary) {
|
|
|
101
119
|
const privateLabel = privacy !== "public" ? safePrivateLabel(summary) : void 0;
|
|
102
120
|
const conversationTitle = privateLabel ?? summary.conversationTitle;
|
|
103
121
|
const channelName = privateLabel ?? summary.channelName;
|
|
104
|
-
const requester = requesterLabel(summary.requester);
|
|
105
122
|
const sentryConversationUrl = buildSentryConversationUrl(
|
|
106
123
|
summary.conversationId
|
|
107
124
|
);
|
|
108
125
|
const sentryTraceUrl = summary.traceId ? buildSentryTraceUrl(summary.traceId) : void 0;
|
|
126
|
+
const requesterIdentity = requesterIdentityReport(summary.requester);
|
|
127
|
+
const cumulativeUsage = turnUsageReport(summary.cumulativeUsage);
|
|
109
128
|
return {
|
|
110
129
|
conversationId: summary.conversationId,
|
|
111
130
|
...conversationTitle ? { conversationTitle } : {},
|
|
@@ -115,12 +134,11 @@ function sessionReportFromSummary(summary) {
|
|
|
115
134
|
lastProgressAt: new Date(summary.lastProgressAtMs).toISOString(),
|
|
116
135
|
lastSeenAt: new Date(summary.updatedAtMs).toISOString(),
|
|
117
136
|
...summary.state === "completed" ? { completedAt: new Date(summary.updatedAtMs).toISOString() } : {},
|
|
118
|
-
|
|
119
|
-
...
|
|
137
|
+
cumulativeDurationMs: summary.cumulativeDurationMs,
|
|
138
|
+
...cumulativeUsage ? { cumulativeUsage } : {},
|
|
120
139
|
surface: surfaceFromConversationId(summary.conversationId),
|
|
121
140
|
title: titleFromSummary(summary),
|
|
122
|
-
...
|
|
123
|
-
...summary.requester ? { requesterIdentity: summary.requester } : {},
|
|
141
|
+
...requesterIdentity ? { requesterIdentity } : {},
|
|
124
142
|
...slackThread ? { channel: slackThread.channelId } : {},
|
|
125
143
|
...channelName ? { channelName } : {},
|
|
126
144
|
...sentryConversationUrl ? { sentryConversationUrl } : {},
|
|
@@ -181,7 +199,8 @@ function normalizeTranscriptPart(part) {
|
|
|
181
199
|
};
|
|
182
200
|
}
|
|
183
201
|
return {
|
|
184
|
-
type:
|
|
202
|
+
type: "unknown",
|
|
203
|
+
...rawType !== "unknown" ? { sourceType: rawType } : {},
|
|
185
204
|
output: part
|
|
186
205
|
};
|
|
187
206
|
}
|
|
@@ -207,13 +226,16 @@ function normalizeToolResultMessage(record) {
|
|
|
207
226
|
function normalizeTranscriptMessage(message) {
|
|
208
227
|
const record = message;
|
|
209
228
|
const content = record.content;
|
|
210
|
-
const role =
|
|
229
|
+
const role = transcriptRole(record.role);
|
|
211
230
|
return {
|
|
212
231
|
role,
|
|
213
232
|
...typeof record.timestamp === "number" ? { timestamp: record.timestamp } : {},
|
|
214
233
|
parts: role === "toolResult" ? [normalizeToolResultMessage(record)] : Array.isArray(content) ? content.map(normalizeTranscriptPart) : [normalizeTranscriptPart(content)]
|
|
215
234
|
};
|
|
216
235
|
}
|
|
236
|
+
function transcriptRole(role) {
|
|
237
|
+
return role === "assistant" || role === "system" || role === "tool" || role === "toolResult" || role === "user" ? role : "unknown";
|
|
238
|
+
}
|
|
217
239
|
function serializedChars(value) {
|
|
218
240
|
if (typeof value === "string") return value.length;
|
|
219
241
|
return JSON.stringify(value)?.length ?? 0;
|
|
@@ -279,8 +301,9 @@ function redactTranscriptPart(part) {
|
|
|
279
301
|
};
|
|
280
302
|
}
|
|
281
303
|
return {
|
|
282
|
-
type:
|
|
304
|
+
type: "unknown",
|
|
283
305
|
redacted: true,
|
|
306
|
+
...part.sourceType ? { sourceType: part.sourceType } : {},
|
|
284
307
|
...redactedPayloadFields("output", part.output ?? part.input ?? part.text)
|
|
285
308
|
};
|
|
286
309
|
}
|
|
@@ -292,8 +315,7 @@ function redactTranscriptMessage(message) {
|
|
|
292
315
|
};
|
|
293
316
|
}
|
|
294
317
|
function isConversationMessageRole(role) {
|
|
295
|
-
|
|
296
|
-
return normalized === "user" || normalized === "assistant";
|
|
318
|
+
return role === "user" || role === "assistant";
|
|
297
319
|
}
|
|
298
320
|
function hasTextPart(message) {
|
|
299
321
|
return message.parts.some((part) => {
|
|
@@ -304,20 +326,32 @@ function hasTextPart(message) {
|
|
|
304
326
|
}
|
|
305
327
|
function isConversationMessage(message) {
|
|
306
328
|
if (!isConversationMessageRole(message.role)) return false;
|
|
307
|
-
if (message.role
|
|
329
|
+
if (message.role === "assistant") return hasTextPart(message);
|
|
308
330
|
return message.parts.length > 0;
|
|
309
331
|
}
|
|
310
332
|
function countConversationMessages(transcript) {
|
|
311
333
|
return transcript.filter(isConversationMessage).length;
|
|
312
334
|
}
|
|
335
|
+
function systemPromptMessage() {
|
|
336
|
+
return {
|
|
337
|
+
role: "system",
|
|
338
|
+
parts: [{ type: "text", text: buildSystemPrompt() }]
|
|
339
|
+
};
|
|
340
|
+
}
|
|
313
341
|
function turnScopedMessages(messages) {
|
|
314
342
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
315
343
|
const record = messages[index];
|
|
316
344
|
if (record.role === "user") {
|
|
317
|
-
return
|
|
345
|
+
return {
|
|
346
|
+
messages: messages.slice(index),
|
|
347
|
+
startsAtRunBoundary: index === 0
|
|
348
|
+
};
|
|
318
349
|
}
|
|
319
350
|
}
|
|
320
|
-
return
|
|
351
|
+
return {
|
|
352
|
+
messages,
|
|
353
|
+
startsAtRunBoundary: messages.length > 0
|
|
354
|
+
};
|
|
321
355
|
}
|
|
322
356
|
function traceIdFromTranscript(transcript) {
|
|
323
357
|
for (const message of transcript) {
|
|
@@ -351,13 +385,16 @@ async function readConversation(conversationId) {
|
|
|
351
385
|
summary.conversationId,
|
|
352
386
|
summary.sessionId
|
|
353
387
|
);
|
|
354
|
-
const scopedMessages = sessionRecord?.piMessages ? turnScopedMessages(sessionRecord.piMessages) : [];
|
|
388
|
+
const scopedMessages = sessionRecord?.piMessages ? turnScopedMessages(sessionRecord.piMessages) : { messages: [], startsAtRunBoundary: false };
|
|
355
389
|
const canExposeTranscript = canExposeConversationTranscript(summary);
|
|
356
|
-
const normalizedTranscript = scopedMessages.map(
|
|
390
|
+
const normalizedTranscript = scopedMessages.messages.map(
|
|
357
391
|
normalizeTranscriptMessage
|
|
358
392
|
);
|
|
359
393
|
const transcriptMessageCount = countConversationMessages(normalizedTranscript);
|
|
360
|
-
const transcript = canExposeTranscript ?
|
|
394
|
+
const transcript = canExposeTranscript ? [
|
|
395
|
+
...scopedMessages.startsAtRunBoundary && normalizedTranscript.length > 0 ? [systemPromptMessage()] : [],
|
|
396
|
+
...normalizedTranscript
|
|
397
|
+
] : [];
|
|
361
398
|
const transcriptMetadata = canExposeTranscript ? void 0 : normalizedTranscript.map(redactTranscriptMessage);
|
|
362
399
|
const traceId = summary.traceId ?? sessionRecord?.traceId ?? (canExposeTranscript ? traceIdFromTranscript(transcript) : void 0);
|
|
363
400
|
const sentryTraceUrl = traceId ? buildSentryTraceUrl(traceId) : void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"node-html-markdown": "^2.0.0",
|
|
65
65
|
"yaml": "^2.9.0",
|
|
66
66
|
"zod": "^4.4.3",
|
|
67
|
-
"@sentry/junior-plugin-api": "0.
|
|
67
|
+
"@sentry/junior-plugin-api": "0.64.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@types/node": "^25.9.1",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"typescript": "^6.0.3",
|
|
77
77
|
"vercel": "^54.4.0",
|
|
78
78
|
"vitest": "^4.1.7",
|
|
79
|
-
"@sentry/junior-scheduler": "0.
|
|
79
|
+
"@sentry/junior-scheduler": "0.64.0"
|
|
80
80
|
},
|
|
81
81
|
"scripts": {
|
|
82
82
|
"build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
|