atom-agent 1.5.0 → 1.5.1
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/CHANGELOG.md +30 -0
- package/README.md +1 -0
- package/dist/adapters.js +376 -8
- package/dist/agent/loop.js +39 -4
- package/dist/providers.js +11 -3
- package/dist/telemetry.js +53 -4
- package/dist/zen.js +417 -30
- package/package.json +1 -1
package/dist/telemetry.js
CHANGED
|
@@ -55,7 +55,7 @@ import { randomUUID } from "node:crypto";
|
|
|
55
55
|
import { fileURLToPath } from "node:url";
|
|
56
56
|
import { scrubSecrets } from "./policy.js";
|
|
57
57
|
import { atomDir } from "./auth.js";
|
|
58
|
-
export const TELEMETRY_VERSION =
|
|
58
|
+
export const TELEMETRY_VERSION = 2;
|
|
59
59
|
export const TELEMETRY_DIRNAME = "telemetry";
|
|
60
60
|
export const TELEMETRY_SESSIONS_DIRNAME = "sessions";
|
|
61
61
|
export const TELEMETRY_DASHBOARD_FILENAME = "dashboard.html";
|
|
@@ -414,7 +414,8 @@ function isRecord(value) {
|
|
|
414
414
|
function validateTelemetrySession(data) {
|
|
415
415
|
if (!isRecord(data))
|
|
416
416
|
return null;
|
|
417
|
-
|
|
417
|
+
const ver = data["version"];
|
|
418
|
+
if (ver !== TELEMETRY_VERSION && ver !== 1)
|
|
418
419
|
return null;
|
|
419
420
|
const sessionId = data["sessionId"];
|
|
420
421
|
const startedAt = data["startedAt"];
|
|
@@ -427,6 +428,17 @@ function validateTelemetrySession(data) {
|
|
|
427
428
|
return null;
|
|
428
429
|
const subagents = Array.isArray(data["subagents"]) ? data["subagents"] : [];
|
|
429
430
|
const events = Array.isArray(data["events"]) ? data["events"] : [];
|
|
431
|
+
// v1 → v2 migration: inputTruncated defaults from preview length, loop
|
|
432
|
+
// gains additive phase fields only when the writer reported them.
|
|
433
|
+
const migratedTurns = turns.map((t) => {
|
|
434
|
+
const rec = t;
|
|
435
|
+
if (typeof rec["inputTruncated"] !== "boolean") {
|
|
436
|
+
const preview = typeof rec["inputPreview"] === "string" ? rec["inputPreview"] : "";
|
|
437
|
+
const chars = typeof rec["inputChars"] === "number" ? rec["inputChars"] : preview.length;
|
|
438
|
+
rec["inputTruncated"] = chars > preview.length;
|
|
439
|
+
}
|
|
440
|
+
return t;
|
|
441
|
+
});
|
|
430
442
|
return {
|
|
431
443
|
version: TELEMETRY_VERSION,
|
|
432
444
|
sessionId,
|
|
@@ -436,7 +448,7 @@ function validateTelemetrySession(data) {
|
|
|
436
448
|
project: typeof data["project"] === "string" ? data["project"] : null,
|
|
437
449
|
provider: typeof data["provider"] === "string" ? data["provider"] : "unknown",
|
|
438
450
|
model: typeof data["model"] === "string" ? data["model"] : "unknown",
|
|
439
|
-
turns:
|
|
451
|
+
turns: migratedTurns,
|
|
440
452
|
subagents,
|
|
441
453
|
events,
|
|
442
454
|
compactionUsage: isRecord(data["compactionUsage"]) ? data["compactionUsage"] : {},
|
|
@@ -704,6 +716,7 @@ export class TelemetryRecorder {
|
|
|
704
716
|
durationMs: null,
|
|
705
717
|
inputPreview: preview.preview,
|
|
706
718
|
inputChars: typeof input === "string" ? input.length : 0,
|
|
719
|
+
inputTruncated: preview.truncated,
|
|
707
720
|
provider: meta.provider,
|
|
708
721
|
model: meta.model,
|
|
709
722
|
effort: meta.effort,
|
|
@@ -798,7 +811,9 @@ export class TelemetryRecorder {
|
|
|
798
811
|
: 0,
|
|
799
812
|
usage: clean,
|
|
800
813
|
usageReported: info.usageReported === true && clean !== undefined,
|
|
801
|
-
reasoningLabel: typeof info.reasoningLabel === "string"
|
|
814
|
+
reasoningLabel: typeof info.reasoningLabel === "string" && info.reasoningLabel.trim().length > 2
|
|
815
|
+
? info.reasoningLabel
|
|
816
|
+
: undefined,
|
|
802
817
|
toolCallCount: typeof info.toolCallCount === "number" ? info.toolCallCount : 0,
|
|
803
818
|
finishReason: info.finishReason === "tool_calls" || info.finishReason === "error" ? info.finishReason : "final",
|
|
804
819
|
error: typeof info.error === "string" ? info.error.slice(0, 500) : undefined,
|
|
@@ -895,6 +910,26 @@ export class TelemetryRecorder {
|
|
|
895
910
|
if (bMs !== undefined)
|
|
896
911
|
loop.bottleneckMs = bMs;
|
|
897
912
|
}
|
|
913
|
+
const slowest = s["slowestModel"];
|
|
914
|
+
const sName = typeof slowest?.["id"] === "string" ? slowest["id"] : undefined;
|
|
915
|
+
const sMs = num(slowest?.["durationMs"]) ?? undefined;
|
|
916
|
+
if (sName && sName.length > 0) {
|
|
917
|
+
loop.slowestModelName = sName.slice(0, 80);
|
|
918
|
+
if (sMs !== undefined)
|
|
919
|
+
loop.slowestModelMs = sMs;
|
|
920
|
+
}
|
|
921
|
+
const modelTotal = num(s["modelTotalMs"]) ?? undefined;
|
|
922
|
+
if (modelTotal !== undefined)
|
|
923
|
+
loop.modelTotalMs = modelTotal;
|
|
924
|
+
const toolTotal = num(s["toolTotalMs"]) ?? undefined;
|
|
925
|
+
if (toolTotal !== undefined)
|
|
926
|
+
loop.toolTotalMs = toolTotal;
|
|
927
|
+
const dom = s["dominantPhase"];
|
|
928
|
+
if (dom === "model" || dom === "tool")
|
|
929
|
+
loop.dominantPhase = dom;
|
|
930
|
+
else if (modelTotal !== undefined || toolTotal !== undefined) {
|
|
931
|
+
loop.dominantPhase = (modelTotal ?? 0) >= (toolTotal ?? 0) ? "model" : "tool";
|
|
932
|
+
}
|
|
898
933
|
turn.loop = loop;
|
|
899
934
|
}
|
|
900
935
|
catch {
|
|
@@ -1031,7 +1066,21 @@ export class TelemetryRecorder {
|
|
|
1031
1066
|
: outcome === "cancelled"
|
|
1032
1067
|
? "(cancelled)"
|
|
1033
1068
|
: "(failed)";
|
|
1069
|
+
// Preserve any streamed partial for post-mortem instead of nulling
|
|
1070
|
+
// the reply outright; dashboard renders partial distinctly.
|
|
1071
|
+
if (typeof replyOrError === "string" && replyOrError.length > 0) {
|
|
1072
|
+
const scrubbed = this.scrub(replyOrError);
|
|
1073
|
+
turn.partialReplyPreview = truncatePreview(scrubbed, TELEMETRY_INPUT_PREVIEW_CHARS).preview;
|
|
1074
|
+
}
|
|
1075
|
+
else {
|
|
1076
|
+
turn.partialReplyPreview = null;
|
|
1077
|
+
}
|
|
1034
1078
|
turn.replyPreview = null;
|
|
1079
|
+
// Timeline entry for failed turns only: cancellations are
|
|
1080
|
+
// user-initiated noise, and the turn record already keeps the error.
|
|
1081
|
+
if (outcome === "failed") {
|
|
1082
|
+
this.recordEvent("info", `turn ${turn.id} ${outcome}: ${(turn.error ?? "").slice(0, 200)}`);
|
|
1083
|
+
}
|
|
1035
1084
|
}
|
|
1036
1085
|
else {
|
|
1037
1086
|
const scrubbed = this.scrub(typeof replyOrError === "string" ? replyOrError : "");
|