@mono-agent/agent-app 0.3.0 → 0.4.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 +9 -5
- package/dist/adapter-send-tools-main.d.ts +3 -0
- package/dist/adapter-send-tools-main.d.ts.map +1 -0
- package/dist/adapter-send-tools-main.js +20 -0
- package/dist/adapter-send-tools-main.js.map +1 -0
- package/dist/adapter-send-tools.d.ts +59 -0
- package/dist/adapter-send-tools.d.ts.map +1 -0
- package/dist/adapter-send-tools.js +254 -0
- package/dist/adapter-send-tools.js.map +1 -0
- package/dist/app-config.d.ts +40 -17
- package/dist/app-config.d.ts.map +1 -1
- package/dist/app-config.js +188 -68
- package/dist/app-config.js.map +1 -1
- package/dist/app.d.ts +41 -20
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +250 -91
- package/dist/app.js.map +1 -1
- package/dist/backfill.d.ts +79 -0
- package/dist/backfill.d.ts.map +1 -0
- package/dist/backfill.js +246 -0
- package/dist/backfill.js.map +1 -0
- package/dist/background.d.ts +0 -4
- package/dist/background.d.ts.map +1 -1
- package/dist/background.js +78 -50
- package/dist/background.js.map +1 -1
- package/dist/channels.d.ts +7 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +26 -3
- package/dist/channels.js.map +1 -1
- package/dist/cli.d.ts +52 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +315 -111
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +8 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +148 -48
- package/dist/doctor.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/launchd.d.ts +0 -2
- package/dist/launchd.d.ts.map +1 -1
- package/dist/launchd.js +0 -2
- package/dist/launchd.js.map +1 -1
- package/dist/memory-recall-main.d.ts +3 -0
- package/dist/memory-recall-main.d.ts.map +1 -0
- package/dist/memory-recall-main.js +30 -0
- package/dist/memory-recall-main.js.map +1 -0
- package/dist/memory-recall.d.ts +111 -0
- package/dist/memory-recall.d.ts.map +1 -0
- package/dist/memory-recall.js +275 -0
- package/dist/memory-recall.js.map +1 -0
- package/dist/sessions.d.ts +21 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +45 -0
- package/dist/sessions.js.map +1 -0
- package/dist/ui.d.ts +54 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +153 -0
- package/dist/ui.js.map +1 -0
- package/package.json +22 -17
- package/skills/mono-agent-composer/SKILL.md +6 -5
- package/skills/mono-agent-composer/references/config-blueprint.md +37 -18
- package/skills/mono-agent-composer/references/discovery-questions.md +38 -23
- package/skills/mono-agent-composer/references/feature-coverage.md +12 -9
- package/skills/mono-agent-composer/references/package-map.md +5 -5
- package/skills/mono-agent-composer/references/validation.md +5 -4
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { RunSummary, RuntimeEventLike } from "@mono-agent/observability";
|
|
2
|
+
import type { MonoAgentAppConfigInput } from "./app-config.js";
|
|
3
|
+
/** True for a thrown OTLP error whose status is transient (5xx/429/408) or a non-HTTP (network) error. */
|
|
4
|
+
export declare function isRetryable(error: unknown): boolean;
|
|
5
|
+
export interface BackfillOptions {
|
|
6
|
+
/** Export exactly this run id; mutually exclusive with `all`. */
|
|
7
|
+
readonly run?: string;
|
|
8
|
+
/** Export every run found in the artifact dir. */
|
|
9
|
+
readonly all?: boolean;
|
|
10
|
+
/** Only runs whose `startedAt` is >= this ISO instant. */
|
|
11
|
+
readonly since?: string;
|
|
12
|
+
/** Only runs whose `startedAt` is <= this ISO instant. */
|
|
13
|
+
readonly until?: string;
|
|
14
|
+
/** Map + serialize but do not POST; report span counts and byte sizes. */
|
|
15
|
+
readonly dryRun?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface BackfillRunArtifacts {
|
|
18
|
+
readonly summary: RunSummary;
|
|
19
|
+
readonly events: RuntimeEventLike[];
|
|
20
|
+
readonly warnings: readonly string[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Read a run's on-disk artifacts directly into the shapes the OTLP mapping
|
|
24
|
+
* needs. Deliberately bypasses `readRecordedRun` (which returns the classified
|
|
25
|
+
* `RecordedRunEvent` shape and caps events at a maximum) so backfill exports a
|
|
26
|
+
* faithful, uncapped copy: `summary.json` parses straight to `RunSummary`, and
|
|
27
|
+
* each `events.jsonl` line is a raw `RuntimeEventLike`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function readRunArtifacts(artifactDir: string, runId: string): Promise<BackfillRunArtifacts>;
|
|
30
|
+
/**
|
|
31
|
+
* Derive the run's [start, end] in epoch nanoseconds from the recorded summary.
|
|
32
|
+
* Unlike the live exporter (which stamps wall-clock `now()`), backfill must use
|
|
33
|
+
* the historical timestamps so Phoenix shows the run on its real time axis.
|
|
34
|
+
* `endedAt` is missing for runs that never finished (≈crashed/running) — fall
|
|
35
|
+
* back to `startedAt + durationMs`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function runStartEndNanos(summary: RunSummary): {
|
|
38
|
+
start: bigint;
|
|
39
|
+
end: bigint;
|
|
40
|
+
};
|
|
41
|
+
type RunOutcome = {
|
|
42
|
+
readonly runId: string;
|
|
43
|
+
readonly status: "ok";
|
|
44
|
+
readonly spanCount: number;
|
|
45
|
+
readonly bytes: number;
|
|
46
|
+
readonly dryRun: boolean;
|
|
47
|
+
} | {
|
|
48
|
+
readonly runId: string;
|
|
49
|
+
readonly status: "skip";
|
|
50
|
+
readonly reason: string;
|
|
51
|
+
} | {
|
|
52
|
+
readonly runId: string;
|
|
53
|
+
readonly status: "fail";
|
|
54
|
+
readonly reason: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Export already-recorded runs to the configured Phoenix exporter. Returns one
|
|
58
|
+
* outcome per attempted run; a single run's network failure is non-fatal (it
|
|
59
|
+
* becomes a `fail` outcome) so a partial backfill still reports. Trace/span ids
|
|
60
|
+
* are deterministic (keyed on run id) so re-running is idempotent: Phoenix
|
|
61
|
+
* overwrites rather than duplicating.
|
|
62
|
+
*/
|
|
63
|
+
export declare function backfillRuns(input: MonoAgentAppConfigInput, options: BackfillOptions): Promise<{
|
|
64
|
+
readonly artifactDir: string;
|
|
65
|
+
readonly endpoint: string;
|
|
66
|
+
readonly outcomes: RunOutcome[];
|
|
67
|
+
}>;
|
|
68
|
+
export interface RunBackfillArgs {
|
|
69
|
+
readonly configPath?: string;
|
|
70
|
+
readonly run?: string;
|
|
71
|
+
readonly all: boolean;
|
|
72
|
+
readonly since?: string;
|
|
73
|
+
readonly until?: string;
|
|
74
|
+
readonly dryRun: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** CLI entry: resolve config, run the backfill, and print a per-run report. */
|
|
77
|
+
export declare function runBackfill(args: RunBackfillArgs): Promise<number>;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=backfill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backfill.d.ts","sourceRoot":"","sources":["../src/backfill.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,UAAU,EACV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAQnC,OAAO,KAAK,EAAE,uBAAuB,EAAoB,MAAM,iBAAiB,CAAC;AAsBjF,0GAA0G;AAC1G,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOnD;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAaxG;AAmBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CASpF;AAuDD,KAAK,UAAU,GACX;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/H;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,uBAAuB,EAC9B,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,CAuDvG;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,+EAA+E;AAC/E,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDxE"}
|
package/dist/backfill.js
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { buildRunReadableSpans, createDeterministicIdFactory, postOtlpProtobuf, serializeTraceSpans, } from "@mono-agent/observability-otel";
|
|
5
|
+
import { resolveAppArtifactDir, resolveAppObservabilityExporters, resolveAppTraceSourceId, resolveAppTraceSourceLabel, } from "./app-config.js";
|
|
6
|
+
const SUMMARY_SUFFIX = ".summary.json";
|
|
7
|
+
const EVENTS_SUFFIX = ".events.jsonl";
|
|
8
|
+
// Backfill is a deliberate foreground batch (not the live best-effort path), so
|
|
9
|
+
// a single very large run gets a generous POST budget regardless of the live
|
|
10
|
+
// exporter's small default timeout.
|
|
11
|
+
const BACKFILL_TIMEOUT_MS = 60_000;
|
|
12
|
+
// Phoenix has a bounded span-ingestion queue and returns 503 under backpressure
|
|
13
|
+
// when a large batch arrives faster than it drains. Retry transient failures
|
|
14
|
+
// with exponential backoff so a full backfill completes instead of dropping
|
|
15
|
+
// runs; deterministic ids make every retry idempotent.
|
|
16
|
+
const BACKFILL_MAX_ATTEMPTS = 6;
|
|
17
|
+
const BACKFILL_BASE_BACKOFF_MS = 500;
|
|
18
|
+
const RETRYABLE_STATUSES = new Set([408, 429, 500, 502, 503, 504]);
|
|
19
|
+
function delay(ms) {
|
|
20
|
+
return new Promise((resolveDelay) => {
|
|
21
|
+
setTimeout(resolveDelay, ms);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** True for a thrown OTLP error whose status is transient (5xx/429/408) or a non-HTTP (network) error. */
|
|
25
|
+
export function isRetryable(error) {
|
|
26
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
+
const match = /responded (\d{3})/u.exec(message);
|
|
28
|
+
if (match === null) {
|
|
29
|
+
return true; // network/timeout/abort — worth a retry
|
|
30
|
+
}
|
|
31
|
+
return RETRYABLE_STATUSES.has(Number(match[1]));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read a run's on-disk artifacts directly into the shapes the OTLP mapping
|
|
35
|
+
* needs. Deliberately bypasses `readRecordedRun` (which returns the classified
|
|
36
|
+
* `RecordedRunEvent` shape and caps events at a maximum) so backfill exports a
|
|
37
|
+
* faithful, uncapped copy: `summary.json` parses straight to `RunSummary`, and
|
|
38
|
+
* each `events.jsonl` line is a raw `RuntimeEventLike`.
|
|
39
|
+
*/
|
|
40
|
+
export async function readRunArtifacts(artifactDir, runId) {
|
|
41
|
+
const warnings = [];
|
|
42
|
+
const summaryRaw = await readFile(join(artifactDir, `${runId}${SUMMARY_SUFFIX}`), "utf8");
|
|
43
|
+
const summary = JSON.parse(summaryRaw);
|
|
44
|
+
let events = [];
|
|
45
|
+
try {
|
|
46
|
+
const eventsRaw = await readFile(join(artifactDir, `${runId}${EVENTS_SUFFIX}`), "utf8");
|
|
47
|
+
events = parseEventsJsonl(eventsRaw, warnings);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
warnings.push(`No ${EVENTS_SUFFIX} for ${runId}; exporting a root-span-only trace.`);
|
|
51
|
+
}
|
|
52
|
+
return { summary, events, warnings };
|
|
53
|
+
}
|
|
54
|
+
function parseEventsJsonl(raw, warnings) {
|
|
55
|
+
const events = [];
|
|
56
|
+
const lines = raw.split("\n");
|
|
57
|
+
lines.forEach((line, index) => {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
if (trimmed.length === 0) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
events.push(JSON.parse(trimmed));
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
warnings.push(`Skipped malformed event line ${index + 1}.`);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return events;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Derive the run's [start, end] in epoch nanoseconds from the recorded summary.
|
|
73
|
+
* Unlike the live exporter (which stamps wall-clock `now()`), backfill must use
|
|
74
|
+
* the historical timestamps so Phoenix shows the run on its real time axis.
|
|
75
|
+
* `endedAt` is missing for runs that never finished (≈crashed/running) — fall
|
|
76
|
+
* back to `startedAt + durationMs`.
|
|
77
|
+
*/
|
|
78
|
+
export function runStartEndNanos(summary) {
|
|
79
|
+
const startMs = summary.startedAt !== undefined ? Date.parse(summary.startedAt) : Number.NaN;
|
|
80
|
+
const safeStartMs = Number.isNaN(startMs) ? 0 : startMs;
|
|
81
|
+
const endMsRaw = summary.endedAt !== undefined ? Date.parse(summary.endedAt) : Number.NaN;
|
|
82
|
+
const endMs = Number.isNaN(endMsRaw) ? safeStartMs + (summary.durationMs ?? 0) : endMsRaw;
|
|
83
|
+
return {
|
|
84
|
+
start: BigInt(Math.trunc(safeStartMs)) * 1000000n,
|
|
85
|
+
end: BigInt(Math.trunc(endMs < safeStartMs ? safeStartMs : endMs)) * 1000000n,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function resolveProjectName(exporter, sourceLabel, sourceId) {
|
|
89
|
+
return exporter.projectName ?? sourceLabel ?? sourceId ?? "default";
|
|
90
|
+
}
|
|
91
|
+
/** POST one run's protobuf body, retrying transient failures (e.g. Phoenix 503 backpressure) with backoff. */
|
|
92
|
+
async function postWithRetry(exporter, projectName, body) {
|
|
93
|
+
let lastError;
|
|
94
|
+
for (let attempt = 1; attempt <= BACKFILL_MAX_ATTEMPTS; attempt += 1) {
|
|
95
|
+
try {
|
|
96
|
+
await postOtlpProtobuf({
|
|
97
|
+
endpoint: exporter.endpoint,
|
|
98
|
+
headers: { "x-project-name": projectName, ...(exporter.headers ?? {}) },
|
|
99
|
+
body,
|
|
100
|
+
timeoutMs: BACKFILL_TIMEOUT_MS,
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
lastError = error;
|
|
106
|
+
if (attempt === BACKFILL_MAX_ATTEMPTS || !isRetryable(error)) {
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
await delay(BACKFILL_BASE_BACKOFF_MS * 2 ** (attempt - 1));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
throw lastError;
|
|
113
|
+
}
|
|
114
|
+
/** List run ids (base names) present in an artifact dir, sorted oldest-first by id. */
|
|
115
|
+
async function listRunIds(artifactDir) {
|
|
116
|
+
const entries = await readdir(artifactDir, { withFileTypes: true });
|
|
117
|
+
return entries
|
|
118
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith(SUMMARY_SUFFIX))
|
|
119
|
+
.map((entry) => entry.name.slice(0, -SUMMARY_SUFFIX.length))
|
|
120
|
+
.sort();
|
|
121
|
+
}
|
|
122
|
+
function withinWindow(summary, since, until) {
|
|
123
|
+
if (since === undefined && until === undefined) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
const startedMs = summary.startedAt !== undefined ? Date.parse(summary.startedAt) : Number.NaN;
|
|
127
|
+
if (Number.isNaN(startedMs)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
if (since !== undefined && startedMs < Date.parse(since)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
if (until !== undefined && startedMs > Date.parse(until)) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Export already-recorded runs to the configured Phoenix exporter. Returns one
|
|
140
|
+
* outcome per attempted run; a single run's network failure is non-fatal (it
|
|
141
|
+
* becomes a `fail` outcome) so a partial backfill still reports. Trace/span ids
|
|
142
|
+
* are deterministic (keyed on run id) so re-running is idempotent: Phoenix
|
|
143
|
+
* overwrites rather than duplicating.
|
|
144
|
+
*/
|
|
145
|
+
export async function backfillRuns(input, options) {
|
|
146
|
+
const exporters = await resolveAppObservabilityExporters(input);
|
|
147
|
+
const exporter = exporters[0];
|
|
148
|
+
if (exporter === undefined) {
|
|
149
|
+
throw new Error("No observability exporter configured; add an observability.exporters phoenix entry.");
|
|
150
|
+
}
|
|
151
|
+
const artifactDir = await resolveAppArtifactDir(input);
|
|
152
|
+
const sourceId = await resolveAppTraceSourceId(input);
|
|
153
|
+
const sourceLabel = await resolveAppTraceSourceLabel(input);
|
|
154
|
+
const projectName = resolveProjectName(exporter, sourceLabel, sourceId);
|
|
155
|
+
const includeSensitiveData = exporter.includeSensitiveData ?? false;
|
|
156
|
+
const runIds = options.run !== undefined ? [options.run] : await listRunIds(artifactDir);
|
|
157
|
+
const outcomes = [];
|
|
158
|
+
for (const runId of runIds) {
|
|
159
|
+
try {
|
|
160
|
+
const { summary, events } = await readRunArtifacts(artifactDir, runId);
|
|
161
|
+
if (!withinWindow(summary, options.since, options.until)) {
|
|
162
|
+
outcomes.push({ runId, status: "skip", reason: "outside --since/--until window" });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const context = {
|
|
166
|
+
runId: summary.runId,
|
|
167
|
+
conversationId: summary.conversationId,
|
|
168
|
+
sourceId,
|
|
169
|
+
sourceLabel,
|
|
170
|
+
configPath: input.configPath,
|
|
171
|
+
artifactDir,
|
|
172
|
+
includeSensitiveData,
|
|
173
|
+
// Recorded since this feature shipped; absent for older runs (input then
|
|
174
|
+
// falls back to the run descriptor on the root span).
|
|
175
|
+
...(typeof summary.userInput === "string" ? { userInput: summary.userInput } : {}),
|
|
176
|
+
};
|
|
177
|
+
const { start, end } = runStartEndNanos(summary);
|
|
178
|
+
const spans = buildRunReadableSpans({
|
|
179
|
+
summary,
|
|
180
|
+
events,
|
|
181
|
+
context,
|
|
182
|
+
projectName,
|
|
183
|
+
startTimeUnixNanos: start,
|
|
184
|
+
endTimeUnixNanos: end,
|
|
185
|
+
idFactory: createDeterministicIdFactory(summary.runId),
|
|
186
|
+
});
|
|
187
|
+
const body = serializeTraceSpans(spans);
|
|
188
|
+
if (options.dryRun !== true) {
|
|
189
|
+
await postWithRetry(exporter, projectName, body);
|
|
190
|
+
}
|
|
191
|
+
outcomes.push({ runId, status: "ok", spanCount: spans.length, bytes: body.length, dryRun: options.dryRun === true });
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
outcomes.push({ runId, status: "fail", reason: error instanceof Error ? error.message : String(error) });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return { artifactDir, endpoint: exporter.endpoint, outcomes };
|
|
198
|
+
}
|
|
199
|
+
/** CLI entry: resolve config, run the backfill, and print a per-run report. */
|
|
200
|
+
export async function runBackfill(args) {
|
|
201
|
+
if (args.run === undefined && !args.all) {
|
|
202
|
+
process.stderr.write("mono-agent backfill requires --run <id> or --all.\n");
|
|
203
|
+
return 2;
|
|
204
|
+
}
|
|
205
|
+
const cwd = process.cwd();
|
|
206
|
+
const input = {
|
|
207
|
+
env: process.env,
|
|
208
|
+
cwd,
|
|
209
|
+
configPath: resolve(cwd, args.configPath ?? "mono-agent.config.json"),
|
|
210
|
+
};
|
|
211
|
+
let result;
|
|
212
|
+
try {
|
|
213
|
+
result = await backfillRuns(input, {
|
|
214
|
+
...(args.run === undefined ? {} : { run: args.run }),
|
|
215
|
+
all: args.all,
|
|
216
|
+
...(args.since === undefined ? {} : { since: args.since }),
|
|
217
|
+
...(args.until === undefined ? {} : { until: args.until }),
|
|
218
|
+
dryRun: args.dryRun,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
223
|
+
return 1;
|
|
224
|
+
}
|
|
225
|
+
process.stdout.write(`Backfilling from ${result.artifactDir} -> ${result.endpoint}${args.dryRun ? " (dry run)" : ""}\n`);
|
|
226
|
+
let ok = 0;
|
|
227
|
+
let failed = 0;
|
|
228
|
+
let totalBytes = 0;
|
|
229
|
+
for (const outcome of result.outcomes) {
|
|
230
|
+
if (outcome.status === "ok") {
|
|
231
|
+
ok += 1;
|
|
232
|
+
totalBytes += outcome.bytes;
|
|
233
|
+
process.stdout.write(` [ok] ${outcome.runId} (${outcome.spanCount} spans, ${outcome.bytes} bytes)${outcome.dryRun ? " [not sent]" : ""}\n`);
|
|
234
|
+
}
|
|
235
|
+
else if (outcome.status === "skip") {
|
|
236
|
+
process.stdout.write(` [skip] ${outcome.runId} (${outcome.reason})\n`);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
failed += 1;
|
|
240
|
+
process.stdout.write(` [fail] ${outcome.runId} (${outcome.reason})\n`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
process.stdout.write(`\n${ok} run(s) exported, ${failed} failed, ${totalBytes} bytes total.\n`);
|
|
244
|
+
return failed > 0 ? 1 : 0;
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backfill.js","sourceRoot":"","sources":["../src/backfill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC5B,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AAOxC,OAAO,EACL,qBAAqB,EACrB,gCAAgC,EAChC,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAGzB,MAAM,cAAc,GAAG,eAAe,CAAC;AACvC,MAAM,aAAa,GAAG,eAAe,CAAC;AACtC,gFAAgF;AAChF,6EAA6E;AAC7E,oCAAoC;AACpC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,gFAAgF;AAChF,6EAA6E;AAC7E,4EAA4E;AAC5E,uDAAuD;AACvD,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAChC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AACrC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEnE,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE;QAClC,UAAU,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,CAAC,wCAAwC;IACvD,CAAC;IACD,OAAO,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAqBD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB,EAAE,KAAa;IACvE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,KAAK,GAAG,cAAc,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAe,CAAC;IAErD,IAAI,MAAM,GAAuB,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,KAAK,GAAG,aAAa,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACxF,MAAM,GAAG,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,MAAM,aAAa,QAAQ,KAAK,qCAAqC,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW,EAAE,QAAkB;IACvD,MAAM,MAAM,GAAuB,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAqB,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,gCAAgC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAmB;IAClD,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAC7F,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAC1F,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC1F,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,QAAU;QACnD,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,QAAU;KAChF,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAA0B,EAAE,WAAmB,EAAE,QAAgB;IAC3F,OAAO,QAAQ,CAAC,WAAW,IAAI,WAAW,IAAI,QAAQ,IAAI,SAAS,CAAC;AACtE,CAAC;AAED,8GAA8G;AAC9G,KAAK,UAAU,aAAa,CAAC,QAA0B,EAAE,WAAmB,EAAE,IAAgB;IAC5F,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,qBAAqB,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACrE,IAAI,CAAC;YACH,MAAM,gBAAgB,CAAC;gBACrB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,OAAO,EAAE,EAAE,gBAAgB,EAAE,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;gBACvE,IAAI;gBACJ,SAAS,EAAE,mBAAmB;aAC/B,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAC;YAClB,IAAI,OAAO,KAAK,qBAAqB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7D,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,KAAK,CAAC,wBAAwB,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,uFAAuF;AACvF,KAAK,UAAU,UAAU,CAAC,WAAmB;IAC3C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;SACxE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;SAC3D,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,YAAY,CAAC,OAAmB,EAAE,KAAc,EAAE,KAAc;IACvE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAC/F,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAA8B,EAC9B,OAAwB;IAExB,MAAM,SAAS,GAAG,MAAM,gCAAgC,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,MAAM,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IACxE,MAAM,oBAAoB,GAAG,QAAQ,CAAC,oBAAoB,IAAI,KAAK,CAAC;IAEpE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;IAEzF,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YACvE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gCAAgC,EAAE,CAAC,CAAC;gBACnF,SAAS;YACX,CAAC;YACD,MAAM,OAAO,GAAqB;gBAChC,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,QAAQ;gBACR,WAAW;gBACX,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,WAAW;gBACX,oBAAoB;gBACpB,yEAAyE;gBACzE,sDAAsD;gBACtD,GAAG,CAAC,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACnF,CAAC;YACF,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACjD,MAAM,KAAK,GAAG,qBAAqB,CAAC;gBAClC,OAAO;gBACP,MAAM;gBACN,OAAO;gBACP,WAAW;gBACX,kBAAkB,EAAE,KAAK;gBACzB,gBAAgB,EAAE,GAAG;gBACrB,SAAS,EAAE,4BAA4B,CAAC,OAAO,CAAC,KAAK,CAAC;aACvD,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YACxC,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC5B,MAAM,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;YACnD,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACvH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3G,CAAC;IACH,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChE,CAAC;AAWD,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAqB;IACrD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QAC5E,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,KAAK,GAA4B;QACrC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG;QACH,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,IAAI,wBAAwB,CAAC;KACtE,CAAC;IAEF,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE;YACjC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;YACpD,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YAC1D,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YAC1D,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,MAAM,CAAC,WAAW,OAAO,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,CACnG,CAAC;IACF,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC5B,EAAE,IAAI,CAAC,CAAC;YACR,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,YAAY,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,SAAS,WAAW,OAAO,CAAC,KAAK,UAAU,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CACzH,CAAC;QACJ,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;QAC1E,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,qBAAqB,MAAM,YAAY,UAAU,iBAAiB,CAAC,CAAC;IAChG,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5B,CAAC"}
|
package/dist/background.d.ts
CHANGED
|
@@ -11,8 +11,6 @@ import type { LaunchctlRunner, LaunchdPaths } from "./launchd.js";
|
|
|
11
11
|
export interface BackgroundCliArgs {
|
|
12
12
|
readonly configPath?: string;
|
|
13
13
|
readonly envFile?: string;
|
|
14
|
-
readonly port?: number;
|
|
15
|
-
readonly noConsole: boolean;
|
|
16
14
|
}
|
|
17
15
|
export interface InstanceTarget {
|
|
18
16
|
readonly cwd: string;
|
|
@@ -24,8 +22,6 @@ export interface InstanceTarget {
|
|
|
24
22
|
readonly nodePath: string;
|
|
25
23
|
readonly cliPath: string;
|
|
26
24
|
readonly envFile?: string;
|
|
27
|
-
readonly port?: number;
|
|
28
|
-
readonly noConsole: boolean;
|
|
29
25
|
readonly pathEnv: string;
|
|
30
26
|
}
|
|
31
27
|
export interface ResolveInstanceTargetInput {
|
package/dist/background.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../src/background.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAcrE,OAAO,KAAK,EAAmB,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../src/background.ts"],"names":[],"mappings":"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"}
|
package/dist/background.js
CHANGED
|
@@ -3,8 +3,9 @@ import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { listTraceSources } from "@mono-agent/observability";
|
|
6
|
-
import { resolveAppTraceRegistryDir, resolveAppTraceStaleAfterMs } from "./app-config.js";
|
|
6
|
+
import { phoenixAppBaseUrl, resolveAppTraceRegistryDir, resolveAppTraceStaleAfterMs } from "./app-config.js";
|
|
7
7
|
import { bootout, bootstrap, buildPlistXml, defaultPathEnv, deriveLaunchdLabel, isLoaded, kickstartRestart, launchdPathsFor, makeLaunchctlRunner, } from "./launchd.js";
|
|
8
|
+
import * as ui from "./ui.js";
|
|
8
9
|
/**
|
|
9
10
|
* Resolve everything the control commands need from CLI args. The registry dir
|
|
10
11
|
* and config path are resolved exactly as the worker will resolve them, so the
|
|
@@ -31,8 +32,6 @@ export async function resolveInstanceTarget(input) {
|
|
|
31
32
|
// Bake an explicit --env-file (resolved absolute) into the plist so the
|
|
32
33
|
// launchd worker loads the same env file the launcher did.
|
|
33
34
|
...(input.args.envFile === undefined ? {} : { envFile: resolve(cwd, input.args.envFile) }),
|
|
34
|
-
...(input.args.port === undefined ? {} : { port: input.args.port }),
|
|
35
|
-
noConsole: input.args.noConsole,
|
|
36
35
|
pathEnv: defaultPathEnv(input.env),
|
|
37
36
|
};
|
|
38
37
|
}
|
|
@@ -82,6 +81,7 @@ async function launchBackground(target, deps, poll) {
|
|
|
82
81
|
if (!outcome.ok) {
|
|
83
82
|
return failLaunch(target, deps, outcome.restarted ? "restart" : "start", outcome.failure);
|
|
84
83
|
}
|
|
84
|
+
deps.stdout(ui.hint("Waiting for the worker to report ready…"));
|
|
85
85
|
const ready = await pollInstanceReady(target, deps, { ...poll, sinceMs });
|
|
86
86
|
if (ready === undefined) {
|
|
87
87
|
return reportTimeout(target, deps);
|
|
@@ -101,8 +101,6 @@ async function writePlist(target, deps) {
|
|
|
101
101
|
configPath: target.configPath,
|
|
102
102
|
cwd: target.cwd,
|
|
103
103
|
...(target.envFile === undefined ? {} : { envFile: target.envFile }),
|
|
104
|
-
...(target.port === undefined ? {} : { port: target.port }),
|
|
105
|
-
noConsole: target.noConsole,
|
|
106
104
|
stdoutPath: target.paths.stdoutPath,
|
|
107
105
|
stderrPath: target.paths.stderrPath,
|
|
108
106
|
pathEnv: target.pathEnv,
|
|
@@ -146,26 +144,26 @@ export async function stopBackground(target, deps) {
|
|
|
146
144
|
// fine. A non-zero exit is only a real failure if the service is still loaded
|
|
147
145
|
// afterwards — otherwise we'd silently swallow genuine stop failures.
|
|
148
146
|
if (result.code !== 0 && (await isLoaded(deps.runner, target.label, uid))) {
|
|
149
|
-
deps.stderr(`Failed to stop ${target.label}: launchctl bootout exited ${result.code}
|
|
147
|
+
deps.stderr(ui.errorLine(`Failed to stop ${target.label}: launchctl bootout exited ${result.code}.`));
|
|
150
148
|
const detail = (result.stderr || result.stdout).trim();
|
|
151
149
|
if (detail.length > 0) {
|
|
152
|
-
deps.stderr(
|
|
150
|
+
deps.stderr(ui.style.dim(detail) + "\n");
|
|
153
151
|
}
|
|
154
|
-
deps.stderr(
|
|
152
|
+
deps.stderr(ui.hint("The plist was removed, but the service is still running."));
|
|
155
153
|
return 1;
|
|
156
154
|
}
|
|
157
155
|
deps.stdout(wasLoaded
|
|
158
|
-
? `Stopped ${target.label} and removed its LaunchAgent.\n`
|
|
159
|
-
: `${target.label} was not running; removed its LaunchAgent if present
|
|
160
|
-
deps.stdout(
|
|
156
|
+
? `${ui.badge("ok")}${ui.style.bold(`Stopped ${target.label}`)} and removed its LaunchAgent.\n`
|
|
157
|
+
: `${ui.style.dim(`${target.label} was not running; removed its LaunchAgent if present.`)}\n`);
|
|
158
|
+
deps.stdout(ui.keyValue([["config", target.configPath]]));
|
|
161
159
|
return 0;
|
|
162
160
|
}
|
|
163
161
|
export async function statusBackground(target, deps) {
|
|
164
162
|
const result = await deps.listTraceSources({ registryDir: target.registryDir, staleAfterMs: target.staleAfterMs });
|
|
165
163
|
const current = result.sources.find((source) => matchesConfig(source, target.configPath));
|
|
166
164
|
if (current === undefined) {
|
|
167
|
-
deps.stdout(`No running mono-agent instance for ${target.configPath}
|
|
168
|
-
deps.stdout(`Start it with: mono-agent start${configFlag(target)}
|
|
165
|
+
deps.stdout(ui.style.dim(`No running mono-agent instance for ${target.configPath}.`) + "\n");
|
|
166
|
+
deps.stdout(ui.hint(`Start it with: mono-agent start${configFlag(target)}`));
|
|
169
167
|
}
|
|
170
168
|
else {
|
|
171
169
|
writeInstanceDetail(current, target, deps);
|
|
@@ -174,9 +172,9 @@ export async function statusBackground(target, deps) {
|
|
|
174
172
|
// manifests linger in the registry and would just be noise.
|
|
175
173
|
const others = result.sources.filter((source) => !matchesConfig(source, target.configPath) && source.health !== "stopped");
|
|
176
174
|
if (others.length > 0) {
|
|
177
|
-
deps.stdout(
|
|
175
|
+
deps.stdout("\n" + ui.rule("Other mono-agent instances"));
|
|
178
176
|
for (const source of others) {
|
|
179
|
-
deps.stdout(
|
|
177
|
+
deps.stdout(`${formatOtherInstance(source)}\n`);
|
|
180
178
|
}
|
|
181
179
|
}
|
|
182
180
|
return current?.health === "running" ? 0 : 1;
|
|
@@ -207,9 +205,9 @@ export async function pollInstanceReady(target, deps, options) {
|
|
|
207
205
|
}
|
|
208
206
|
export function printInstanceInfo(source, target, deps, verb) {
|
|
209
207
|
const flag = configFlag(target);
|
|
210
|
-
deps.stdout(`mono-agent ${verb} in the background
|
|
208
|
+
deps.stdout(`${ui.badge("ok")}${ui.style.bold(`mono-agent ${verb} in the background.`)}\n\n`);
|
|
211
209
|
writeInstanceDetail(source, target, deps);
|
|
212
|
-
deps.stdout(
|
|
210
|
+
deps.stdout("\n" + ui.hint(`Stop with: mono-agent stop${flag} · Logs: mono-agent logs${flag} --follow`));
|
|
213
211
|
}
|
|
214
212
|
async function findInstance(target, deps) {
|
|
215
213
|
const result = await deps.listTraceSources({ registryDir: target.registryDir, staleAfterMs: target.staleAfterMs });
|
|
@@ -224,42 +222,44 @@ async function maybeUnlinkDeadManifest(target, deps, existing) {
|
|
|
224
222
|
await deps.rm(resolve(target.registryDir, `${existing.sourceId}.json`));
|
|
225
223
|
}
|
|
226
224
|
function failLaunch(target, deps, verb, result) {
|
|
227
|
-
deps.stderr(`Failed to ${verb} ${target.label} via launchctl${result === undefined ? "" : ` (exit ${result.code})`}
|
|
225
|
+
deps.stderr(ui.errorLine(`Failed to ${verb} ${target.label} via launchctl${result === undefined ? "" : ` (exit ${result.code})`}.`));
|
|
228
226
|
const detail = (result?.stderr || result?.stdout || "").trim();
|
|
229
227
|
if (detail.length > 0) {
|
|
230
|
-
deps.stderr(
|
|
228
|
+
deps.stderr(ui.style.dim(detail) + "\n");
|
|
231
229
|
}
|
|
232
|
-
deps.stderr(`Logs: ${target.paths.stderrPath}
|
|
230
|
+
deps.stderr(ui.hint(`Logs: ${target.paths.stderrPath}`));
|
|
233
231
|
return 1;
|
|
234
232
|
}
|
|
235
233
|
function reportTimeout(target, deps) {
|
|
236
234
|
const flag = configFlag(target);
|
|
237
|
-
deps.stderr("mono-agent did not report ready within the timeout
|
|
238
|
-
|
|
239
|
-
|
|
235
|
+
deps.stderr(ui.errorLine("mono-agent did not report ready within the timeout."));
|
|
236
|
+
deps.stderr(ui.style.dim("It may still be starting, or it may have failed. Inspect:") + "\n");
|
|
237
|
+
deps.stderr(` ${ui.style.gray("logs: ")} ${target.paths.stderrPath}\n` +
|
|
240
238
|
` ${target.paths.stdoutPath}\n` +
|
|
241
|
-
` follow: mono-agent logs${flag} --follow\n` +
|
|
242
|
-
` status: mono-agent status${flag}\n` +
|
|
243
|
-
` stop:
|
|
239
|
+
` ${ui.style.gray("follow:")} mono-agent logs${flag} --follow\n` +
|
|
240
|
+
` ${ui.style.gray("status:")} mono-agent status${flag}\n` +
|
|
241
|
+
` ${ui.style.gray("stop: ")} mono-agent stop${flag}\n`);
|
|
244
242
|
return 1;
|
|
245
243
|
}
|
|
246
244
|
function writeInstanceDetail(source, target, deps) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
245
|
+
deps.stdout(ui.rule("instance"));
|
|
246
|
+
deps.stdout(ui.keyValue([
|
|
247
|
+
["pid", String(source.pid ?? "unknown")],
|
|
248
|
+
["health", `${ui.healthBadge(source.health)}${source.health}`],
|
|
249
|
+
["config", target.configPath],
|
|
250
|
+
["label", target.label],
|
|
251
|
+
["started", source.startedAt],
|
|
252
|
+
["logs", target.paths.stdoutPath],
|
|
253
|
+
["", target.paths.stderrPath],
|
|
254
|
+
], 2));
|
|
255
|
+
const observability = describeObservabilityMetadata(source);
|
|
256
|
+
if (observability !== undefined) {
|
|
257
|
+
deps.stdout(ui.rule("observability"));
|
|
258
|
+
deps.stdout(` ${observability}\n`);
|
|
252
259
|
}
|
|
253
|
-
deps.stdout(`config ${target.configPath}\n`);
|
|
254
|
-
deps.stdout(`label ${target.label}\n`);
|
|
255
|
-
deps.stdout(`pid ${source.pid ?? "unknown"}\n`);
|
|
256
|
-
deps.stdout(`health ${source.health}\n`);
|
|
257
|
-
deps.stdout(`started ${source.startedAt}\n`);
|
|
258
|
-
deps.stdout(`logs ${target.paths.stdoutPath}\n`);
|
|
259
|
-
deps.stdout(` ${target.paths.stderrPath}\n`);
|
|
260
260
|
const channelLines = formatChannels(source);
|
|
261
261
|
if (channelLines.length > 0) {
|
|
262
|
-
deps.stdout("channels
|
|
262
|
+
deps.stdout(ui.rule("channels"));
|
|
263
263
|
for (const line of channelLines) {
|
|
264
264
|
deps.stdout(`${line}\n`);
|
|
265
265
|
}
|
|
@@ -268,7 +268,7 @@ function writeInstanceDetail(source, target, deps) {
|
|
|
268
268
|
function formatOtherInstance(source) {
|
|
269
269
|
const pid = source.pid === undefined ? "?" : String(source.pid);
|
|
270
270
|
const config = source.configPath ?? "(unknown config)";
|
|
271
|
-
return
|
|
271
|
+
return ` ${ui.healthBadge(source.health)}${source.health.padEnd(8)} pid ${pid.padEnd(7)} ${source.sourceId} ${config}`;
|
|
272
272
|
}
|
|
273
273
|
function matchesConfig(source, configPath) {
|
|
274
274
|
return source.configPath !== undefined && resolve(source.configPath) === configPath;
|
|
@@ -284,13 +284,38 @@ function startedAtMs(source) {
|
|
|
284
284
|
const parsed = Date.parse(source.startedAt);
|
|
285
285
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
286
286
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
287
|
+
/**
|
|
288
|
+
* Format the persisted observability exporter metadata for the detached
|
|
289
|
+
* `status` reader. Reads defensively (the worker persists only endpoint +
|
|
290
|
+
* warning/error strings, never headers/secrets) and always notes that JSONL
|
|
291
|
+
* artifacts remain local.
|
|
292
|
+
*/
|
|
293
|
+
function describeObservabilityMetadata(source) {
|
|
294
|
+
const observability = source.metadata?.observability;
|
|
295
|
+
if (observability === null || typeof observability !== "object") {
|
|
290
296
|
return undefined;
|
|
291
297
|
}
|
|
292
|
-
const
|
|
293
|
-
|
|
298
|
+
const record = observability;
|
|
299
|
+
const endpoint = record.endpoint;
|
|
300
|
+
if (typeof endpoint !== "string" || endpoint.length === 0) {
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
const parts = [`phoenix ${endpoint}`];
|
|
304
|
+
const appUrl = phoenixAppBaseUrl(endpoint);
|
|
305
|
+
if (appUrl !== undefined) {
|
|
306
|
+
parts.push(`app ${appUrl}`);
|
|
307
|
+
}
|
|
308
|
+
if (record.includeSensitiveData === true) {
|
|
309
|
+
parts.push("includeSensitiveData=true");
|
|
310
|
+
}
|
|
311
|
+
if (typeof record.lastWarning === "string" && record.lastWarning.length > 0) {
|
|
312
|
+
parts.push(`last warning: ${record.lastWarning}`);
|
|
313
|
+
}
|
|
314
|
+
if (typeof record.lastError === "string" && record.lastError.length > 0) {
|
|
315
|
+
parts.push(`last error: ${record.lastError}`);
|
|
316
|
+
}
|
|
317
|
+
parts.push("JSONL artifacts remain local");
|
|
318
|
+
return parts.join("; ");
|
|
294
319
|
}
|
|
295
320
|
/** ` --config <path>` when a non-default config is in play, else empty. */
|
|
296
321
|
function configFlag(target) {
|
|
@@ -302,11 +327,14 @@ function formatChannels(source) {
|
|
|
302
327
|
if (channels === null || typeof channels !== "object") {
|
|
303
328
|
return [];
|
|
304
329
|
}
|
|
305
|
-
return Object.entries(channels).map(([id, value]) =>
|
|
330
|
+
return Object.entries(channels).map(([id, value]) => {
|
|
331
|
+
const { kind, text } = describeChannel(value);
|
|
332
|
+
return ` ${ui.channelBadge(kind)}${ui.style.bold(id.padEnd(11))} ${text}`;
|
|
333
|
+
});
|
|
306
334
|
}
|
|
307
|
-
function
|
|
335
|
+
function describeChannel(value) {
|
|
308
336
|
if (value === null || typeof value !== "object") {
|
|
309
|
-
return String(value);
|
|
337
|
+
return { kind: "unknown", text: String(value) };
|
|
310
338
|
}
|
|
311
339
|
const record = value;
|
|
312
340
|
const kind = typeof record.kind === "string" ? record.kind : "unknown";
|
|
@@ -315,10 +343,10 @@ function describeChannelMetadata(value) {
|
|
|
315
343
|
.filter(([key]) => key !== "kind")
|
|
316
344
|
.map(([key, fact]) => `${key}=${String(fact)}`)
|
|
317
345
|
.join(" ");
|
|
318
|
-
return facts.length === 0 ? "running" : `running (${facts})
|
|
346
|
+
return { kind, text: facts.length === 0 ? "running" : `running (${facts})` };
|
|
319
347
|
}
|
|
320
348
|
const reason = typeof record.reason === "string" ? record.reason : "";
|
|
321
|
-
return reason.length === 0 ? kind : `${kind}: ${reason}
|
|
349
|
+
return { kind, text: reason.length === 0 ? kind : `${kind}: ${reason}` };
|
|
322
350
|
}
|
|
323
351
|
function isErrno(error, code) {
|
|
324
352
|
return typeof error === "object" && error !== null && error.code === code;
|