@f-o-h/cli 0.1.73 → 0.1.74
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/foh.js +186 -31
- package/package.json +1 -1
package/dist/foh.js
CHANGED
|
@@ -32790,7 +32790,7 @@ var StdioServerTransport = class {
|
|
|
32790
32790
|
};
|
|
32791
32791
|
|
|
32792
32792
|
// src/lib/cli-version.ts
|
|
32793
|
-
var CLI_VERSION = "0.1.
|
|
32793
|
+
var CLI_VERSION = "0.1.74";
|
|
32794
32794
|
|
|
32795
32795
|
// src/commands/mcp-serve.ts
|
|
32796
32796
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -35480,9 +35480,11 @@ function registerCertify(program3) {
|
|
|
35480
35480
|
const certify = program3.command("certify").description("Produce release certification evidence for an agent");
|
|
35481
35481
|
certify.command("run").description("Run certification for an exact agent draft/profile and emit release evidence").requiredOption("--agent <id>", "Agent ID to certify").option("--profile <profile>", "Certification profile: smoke, release, or stress", "release").option("--adaptive-runs <n>", "Adaptive runs override; release defaults to a budget-safe 5").option("--journeys <list>", "Comma-separated journey allowlist").option("--scenario-ids <list>", "Comma-separated scenario ID allowlist").option("--channel <channel>", "Channel filter: chat, voice, or mixed", "mixed").option("--out <path>", "Write certification run JSON to this file path").option("--api-url <url>", "API base URL override").option("--json", "Output as machine-readable JSON").action(async (opts) => {
|
|
35482
35482
|
try {
|
|
35483
|
+
const totalStarted = Date.now();
|
|
35483
35484
|
const profile = normalizeProfile(opts.profile);
|
|
35484
35485
|
const mode = modeForProfile(profile);
|
|
35485
35486
|
const adaptiveRuns = Math.max(1, Math.min(120, Number(opts.adaptiveRuns ?? defaultAdaptiveRuns(profile)) || defaultAdaptiveRuns(profile)));
|
|
35487
|
+
const apiStarted = Date.now();
|
|
35486
35488
|
const response = await apiFetch(
|
|
35487
35489
|
`/v1/console/agents/${opts.agent}/sim-certify`,
|
|
35488
35490
|
{
|
|
@@ -35497,6 +35499,7 @@ function registerCertify(program3) {
|
|
|
35497
35499
|
apiUrlOverride: opts.apiUrl
|
|
35498
35500
|
}
|
|
35499
35501
|
);
|
|
35502
|
+
const apiMs = Math.max(0, Date.now() - apiStarted);
|
|
35500
35503
|
if (!response.ok || !response.certificate) {
|
|
35501
35504
|
throw new FohError({
|
|
35502
35505
|
step: "certify.run",
|
|
@@ -35512,6 +35515,10 @@ function registerCertify(program3) {
|
|
|
35512
35515
|
reason_code: passed ? "certification_passed" : "certification_failed",
|
|
35513
35516
|
profile,
|
|
35514
35517
|
mode,
|
|
35518
|
+
timing: {
|
|
35519
|
+
api_ms: apiMs,
|
|
35520
|
+
total_ms: Math.max(0, Date.now() - totalStarted)
|
|
35521
|
+
},
|
|
35515
35522
|
certificate: response.certificate,
|
|
35516
35523
|
next_commands: passed ? [`foh agent publish --agent ${opts.agent} --json`] : [`foh certify run --agent ${opts.agent} --profile ${profile} --json`]
|
|
35517
35524
|
};
|
|
@@ -37507,8 +37514,10 @@ function readFreshCache(filePath, maxAgeMs) {
|
|
|
37507
37514
|
const payload = JSON.parse((0, import_node_fs3.readFileSync)(filePath, "utf8"));
|
|
37508
37515
|
const createdAt = Date.parse(String(payload.created_at || ""));
|
|
37509
37516
|
if (!Number.isFinite(createdAt)) return null;
|
|
37510
|
-
|
|
37511
|
-
|
|
37517
|
+
const ageMs = Date.now() - createdAt;
|
|
37518
|
+
if (ageMs > maxAgeMs) return null;
|
|
37519
|
+
if (payload.value === void 0) return null;
|
|
37520
|
+
return { value: payload.value, ageMs };
|
|
37512
37521
|
} catch {
|
|
37513
37522
|
return null;
|
|
37514
37523
|
}
|
|
@@ -37532,7 +37541,16 @@ async function withProofCache(options, run) {
|
|
|
37532
37541
|
if (!resolvedDir) {
|
|
37533
37542
|
return {
|
|
37534
37543
|
value: await run(),
|
|
37535
|
-
metadata: {
|
|
37544
|
+
metadata: {
|
|
37545
|
+
hit: false,
|
|
37546
|
+
miss: true,
|
|
37547
|
+
key: "disabled",
|
|
37548
|
+
cache_path: "",
|
|
37549
|
+
waited_ms: 0,
|
|
37550
|
+
waited_for_peer: false,
|
|
37551
|
+
source: "disabled",
|
|
37552
|
+
age_ms: null
|
|
37553
|
+
}
|
|
37536
37554
|
};
|
|
37537
37555
|
}
|
|
37538
37556
|
const key = cacheKey2(options.kind, options.keyParts);
|
|
@@ -37545,8 +37563,17 @@ async function withProofCache(options, run) {
|
|
|
37545
37563
|
const existing = readFreshCache(cachePath, maxAgeMs);
|
|
37546
37564
|
if (existing) {
|
|
37547
37565
|
return {
|
|
37548
|
-
value: existing,
|
|
37549
|
-
metadata: {
|
|
37566
|
+
value: existing.value,
|
|
37567
|
+
metadata: {
|
|
37568
|
+
hit: true,
|
|
37569
|
+
miss: false,
|
|
37570
|
+
key,
|
|
37571
|
+
cache_path: publicPath(cachePath),
|
|
37572
|
+
waited_ms: 0,
|
|
37573
|
+
waited_for_peer: false,
|
|
37574
|
+
source: "cache",
|
|
37575
|
+
age_ms: existing.ageMs
|
|
37576
|
+
}
|
|
37550
37577
|
};
|
|
37551
37578
|
}
|
|
37552
37579
|
let lockOwner = false;
|
|
@@ -37560,8 +37587,17 @@ async function withProofCache(options, run) {
|
|
|
37560
37587
|
const waitedValue = readFreshCache(cachePath, maxAgeMs);
|
|
37561
37588
|
if (waitedValue) {
|
|
37562
37589
|
return {
|
|
37563
|
-
value: waitedValue,
|
|
37564
|
-
metadata: {
|
|
37590
|
+
value: waitedValue.value,
|
|
37591
|
+
metadata: {
|
|
37592
|
+
hit: true,
|
|
37593
|
+
miss: false,
|
|
37594
|
+
key,
|
|
37595
|
+
cache_path: publicPath(cachePath),
|
|
37596
|
+
waited_ms: Date.now() - started,
|
|
37597
|
+
waited_for_peer: true,
|
|
37598
|
+
source: "cache",
|
|
37599
|
+
age_ms: waitedValue.ageMs
|
|
37600
|
+
}
|
|
37565
37601
|
};
|
|
37566
37602
|
}
|
|
37567
37603
|
}
|
|
@@ -37571,7 +37607,16 @@ async function withProofCache(options, run) {
|
|
|
37571
37607
|
writeCache(cachePath, value);
|
|
37572
37608
|
return {
|
|
37573
37609
|
value,
|
|
37574
|
-
metadata: {
|
|
37610
|
+
metadata: {
|
|
37611
|
+
hit: false,
|
|
37612
|
+
miss: true,
|
|
37613
|
+
key,
|
|
37614
|
+
cache_path: publicPath(cachePath),
|
|
37615
|
+
waited_ms: 0,
|
|
37616
|
+
waited_for_peer: false,
|
|
37617
|
+
source: "fresh_run",
|
|
37618
|
+
age_ms: null
|
|
37619
|
+
}
|
|
37575
37620
|
};
|
|
37576
37621
|
} finally {
|
|
37577
37622
|
if (lockOwner) (0, import_node_fs3.rmSync)(lockPath, { recursive: true, force: true });
|
|
@@ -37579,6 +37624,37 @@ async function withProofCache(options, run) {
|
|
|
37579
37624
|
}
|
|
37580
37625
|
|
|
37581
37626
|
// src/commands/prove.ts
|
|
37627
|
+
function addTiming(timings, name, startedMs) {
|
|
37628
|
+
timings.set(name, (timings.get(name) ?? 0) + Math.max(0, Date.now() - startedMs));
|
|
37629
|
+
}
|
|
37630
|
+
async function timedCheck(timings, name, fn) {
|
|
37631
|
+
const startedMs = Date.now();
|
|
37632
|
+
try {
|
|
37633
|
+
return await fn();
|
|
37634
|
+
} finally {
|
|
37635
|
+
addTiming(timings, name, startedMs);
|
|
37636
|
+
}
|
|
37637
|
+
}
|
|
37638
|
+
function enrichCheckTimings(checks, timings) {
|
|
37639
|
+
return checks.map((check2) => ({
|
|
37640
|
+
...check2,
|
|
37641
|
+
duration_ms: Math.max(0, timings.get(check2.name) ?? check2.duration_ms ?? 0)
|
|
37642
|
+
}));
|
|
37643
|
+
}
|
|
37644
|
+
function proofTimingSummary(checks, commandStartedMs) {
|
|
37645
|
+
const totalCheckDurationMs = checks.reduce((sum, check2) => sum + (check2.duration_ms ?? 0), 0);
|
|
37646
|
+
return {
|
|
37647
|
+
total_ms: Math.max(0, Date.now() - commandStartedMs),
|
|
37648
|
+
total_check_duration_ms: totalCheckDurationMs,
|
|
37649
|
+
slow_checks: checks.filter((check2) => (check2.duration_ms ?? 0) > 0).map((check2) => ({
|
|
37650
|
+
name: check2.name,
|
|
37651
|
+
category: check2.category,
|
|
37652
|
+
status: check2.status,
|
|
37653
|
+
reason_code: check2.reason_code,
|
|
37654
|
+
duration_ms: check2.duration_ms ?? 0
|
|
37655
|
+
})).sort((a, b) => b.duration_ms - a.duration_ms).slice(0, 10)
|
|
37656
|
+
};
|
|
37657
|
+
}
|
|
37582
37658
|
function categoryForCheck(name) {
|
|
37583
37659
|
if (name === "auth") return "auth";
|
|
37584
37660
|
if (name === "contact_channel" || name === "voice_realtime_health") return "voice";
|
|
@@ -37674,7 +37750,9 @@ function isProviderCapacityBlocked(onboarding) {
|
|
|
37674
37750
|
}
|
|
37675
37751
|
function registerProve(program3) {
|
|
37676
37752
|
program3.command("prove").description("Produce one setup/runtime proof bundle for an agent").option("--agent <id>", "Agent ID to prove").option("--org <id>", "Org ID (default: stored org from foh org use)").option("--include-certification", "Run explicit simulation certification check (slow)").option("--cert-mode <m>", "Simulation cert mode when --include-certification is set: quick, full, stress", "quick").option("--cert-adaptive-runs <n>", "Adaptive runs for full/stress certification when included", "30").option("--cert-max-improvement-rounds <n>", "Max prompt improvement rounds in included cert loop (0-5)", "1").option("--mission <mission>", "Proof mission: setup, widget, voice, publish", "setup").option("--contact-path <mode>", "Voice contact path: auto, managed, or byon", "auto").option("--mutation-mode <mode>", "Proof mutation mode: read-only or ensure", "read-only").option("--repair", "Alias for --mutation-mode ensure").option("--require-phone", "Hold proof if no phone/contact number is provisioned").option("--skip-cert", "Deprecated compatibility flag; certification is skipped unless --include-certification is set").option("--skip-smoke", "Skip widget runtime smoke check").option("--skip-voice-health", "Skip realtime voice provider health check").option("--proof-cache-dir <path>", "Optional local proof cache directory for shared certification results").option("--out <path>", "Write signed proof report JSON to this path").option("--strict", "Exit non-zero unless all non-skipped checks pass").option("--api-url <url>", "API base URL override").option("--json", "Output as JSON").action(async (opts) => withCommandErrorHandling(async () => {
|
|
37753
|
+
const commandStartedMs = Date.now();
|
|
37677
37754
|
const checks = [];
|
|
37755
|
+
const checkTimings = /* @__PURE__ */ new Map();
|
|
37678
37756
|
const mission = normalizeMission(opts.mission);
|
|
37679
37757
|
const contactPath = normalizeContactPath(opts.contactPath);
|
|
37680
37758
|
const mutationMode = normalizeMutationMode(opts.mutationMode, Boolean(opts.repair));
|
|
@@ -37685,7 +37763,9 @@ function registerProve(program3) {
|
|
|
37685
37763
|
correlationIds: []
|
|
37686
37764
|
};
|
|
37687
37765
|
try {
|
|
37766
|
+
const authStartedMs = Date.now();
|
|
37688
37767
|
const creds = loadCredentials(opts.apiUrl);
|
|
37768
|
+
addTiming(checkTimings, "auth", authStartedMs);
|
|
37689
37769
|
ctx.apiUrl = creds.apiUrl;
|
|
37690
37770
|
ctx.tokenPresent = Boolean(creds.token);
|
|
37691
37771
|
ctx.orgId = opts.org || creds.orgId;
|
|
@@ -37694,13 +37774,14 @@ function registerProve(program3) {
|
|
|
37694
37774
|
org_id_from_credentials: creds.orgId ?? null
|
|
37695
37775
|
}));
|
|
37696
37776
|
} catch (error2) {
|
|
37777
|
+
if (!checkTimings.has("auth")) addTiming(checkTimings, "auth", commandStartedMs);
|
|
37697
37778
|
checks.push(hold("auth", "auth_missing_or_expired", "CLI is not authenticated.", "foh auth login --web", {
|
|
37698
37779
|
message: error2 instanceof Error ? error2.message : String(error2)
|
|
37699
37780
|
}));
|
|
37700
37781
|
}
|
|
37701
37782
|
if (ctx.tokenPresent && !ctx.orgId) {
|
|
37702
37783
|
try {
|
|
37703
|
-
const orgs = await apiFetch("/v1/console/auth/my-orgs", { apiUrlOverride: opts.apiUrl });
|
|
37784
|
+
const orgs = await timedCheck(checkTimings, "org", () => apiFetch("/v1/console/auth/my-orgs", { apiUrlOverride: opts.apiUrl }));
|
|
37704
37785
|
const resolved = firstUsableOrgId(orgs);
|
|
37705
37786
|
if (resolved.orgId) {
|
|
37706
37787
|
ctx.orgId = resolved.orgId;
|
|
@@ -37728,10 +37809,10 @@ function registerProve(program3) {
|
|
|
37728
37809
|
checks.push(pass("agent_selection", "Using explicitly supplied agent.", { agent_id: ctx.agentId }));
|
|
37729
37810
|
} else {
|
|
37730
37811
|
try {
|
|
37731
|
-
const list = await apiFetch("/v1/console/agents", {
|
|
37812
|
+
const list = await timedCheck(checkTimings, "agent_selection", () => apiFetch("/v1/console/agents", {
|
|
37732
37813
|
orgId: ctx.orgId,
|
|
37733
37814
|
apiUrlOverride: opts.apiUrl
|
|
37734
|
-
});
|
|
37815
|
+
}));
|
|
37735
37816
|
const resolved = agentIdFromList(list);
|
|
37736
37817
|
if (resolved.agentId) {
|
|
37737
37818
|
ctx.agentId = resolved.agentId;
|
|
@@ -37754,11 +37835,11 @@ function registerProve(program3) {
|
|
|
37754
37835
|
}
|
|
37755
37836
|
if (ctx.agentId) {
|
|
37756
37837
|
try {
|
|
37757
|
-
const validation = await apiFetch(`/v1/console/agents/${ctx.agentId}/validate`, {
|
|
37838
|
+
const validation = await timedCheck(checkTimings, "agent_validation", () => apiFetch(`/v1/console/agents/${ctx.agentId}/validate`, {
|
|
37758
37839
|
method: "POST",
|
|
37759
37840
|
orgId: ctx.orgId,
|
|
37760
37841
|
apiUrlOverride: opts.apiUrl
|
|
37761
|
-
});
|
|
37842
|
+
}));
|
|
37762
37843
|
const issues = Array.isArray(validation.issues) ? validation.issues : [];
|
|
37763
37844
|
validationFingerprint = validation;
|
|
37764
37845
|
if (validation.ok === false || issues.length > 0) {
|
|
@@ -37771,10 +37852,10 @@ function registerProve(program3) {
|
|
|
37771
37852
|
}
|
|
37772
37853
|
if (ctx.orgId) {
|
|
37773
37854
|
try {
|
|
37774
|
-
const onboarding = await apiFetch(`/v1/console/org/${ctx.orgId}/onboarding`, {
|
|
37855
|
+
const onboarding = await timedCheck(checkTimings, "contact_channel", () => apiFetch(`/v1/console/org/${ctx.orgId}/onboarding`, {
|
|
37775
37856
|
orgId: ctx.orgId,
|
|
37776
37857
|
apiUrlOverride: opts.apiUrl
|
|
37777
|
-
});
|
|
37858
|
+
}));
|
|
37778
37859
|
const phoneNumber = typeof onboarding.phone_number === "string" && onboarding.phone_number.trim() ? onboarding.phone_number.trim() : null;
|
|
37779
37860
|
const provisioningStatus = typeof onboarding.provisioning_status === "string" ? onboarding.provisioning_status : null;
|
|
37780
37861
|
if (phoneNumber) {
|
|
@@ -37838,10 +37919,10 @@ function registerProve(program3) {
|
|
|
37838
37919
|
checks.push(skipped("voice_realtime_health", "operator_skipped", "Skipped by --skip-voice-health.", "foh voice realtime-health --json"));
|
|
37839
37920
|
} else {
|
|
37840
37921
|
try {
|
|
37841
|
-
const health = await apiFetch(
|
|
37922
|
+
const health = await timedCheck(checkTimings, "voice_realtime_health", () => apiFetch(
|
|
37842
37923
|
"/v1/console/realtime/health",
|
|
37843
37924
|
{ apiUrlOverride: opts.apiUrl }
|
|
37844
|
-
);
|
|
37925
|
+
));
|
|
37845
37926
|
const providers = Array.isArray(health.providers) ? health.providers : [];
|
|
37846
37927
|
if (providers.length === 0) {
|
|
37847
37928
|
checks.push(skipped("voice_realtime_health", "voice_health_no_providers", "Realtime voice health returned no providers.", "foh voice realtime-health --json"));
|
|
@@ -37859,13 +37940,14 @@ function registerProve(program3) {
|
|
|
37859
37940
|
}
|
|
37860
37941
|
}
|
|
37861
37942
|
try {
|
|
37862
|
-
const embed = await apiFetch("/v1/console/channels/widget/embed-snippet", {
|
|
37943
|
+
const embed = await timedCheck(checkTimings, "widget_embed", () => apiFetch("/v1/console/channels/widget/embed-snippet", {
|
|
37863
37944
|
orgId: ctx.orgId,
|
|
37864
37945
|
apiUrlOverride: opts.apiUrl,
|
|
37865
|
-
headers: { "x-agent-id": ctx.agentId }
|
|
37866
|
-
});
|
|
37946
|
+
headers: { "x-agent-id": String(ctx.agentId) }
|
|
37947
|
+
}));
|
|
37867
37948
|
const publicKey = publicKeyFromEmbedResponse(embed);
|
|
37868
37949
|
if (publicKey) {
|
|
37950
|
+
checkTimings.set("widget_channel", Math.max(checkTimings.get("widget_channel") ?? 0, checkTimings.get("widget_embed") ?? 0));
|
|
37869
37951
|
ctx.widgetPublicKey = publicKey;
|
|
37870
37952
|
checks.push(pass("widget_channel", "Widget channel is available in read-only proof mode.", {
|
|
37871
37953
|
public_key_present: true,
|
|
@@ -37880,12 +37962,12 @@ function registerProve(program3) {
|
|
|
37880
37962
|
} catch (error2) {
|
|
37881
37963
|
if (mutationMode === "ensure") {
|
|
37882
37964
|
try {
|
|
37883
|
-
const ensure = await apiFetch("/v1/console/channels/widget/ensure", {
|
|
37965
|
+
const ensure = await timedCheck(checkTimings, "widget_channel", () => apiFetch("/v1/console/channels/widget/ensure", {
|
|
37884
37966
|
method: "POST",
|
|
37885
37967
|
body: JSON.stringify({ agentId: ctx.agentId }),
|
|
37886
37968
|
orgId: ctx.orgId,
|
|
37887
37969
|
apiUrlOverride: opts.apiUrl
|
|
37888
|
-
});
|
|
37970
|
+
}));
|
|
37889
37971
|
const publicKey = publicKeyFromEnsureResponse(ensure);
|
|
37890
37972
|
if (!publicKey) {
|
|
37891
37973
|
checks.push(hold("widget_channel", "widget_public_key_missing", "Widget channel ensure returned no public key.", `foh widget ensure --agent ${ctx.agentId} --json`, ensure));
|
|
@@ -37915,7 +37997,7 @@ function registerProve(program3) {
|
|
|
37915
37997
|
checks.push(skipped("widget_smoke", "widget_public_key_required", "Skipped because widget public key is unavailable.", `foh widget ensure --agent ${ctx.agentId} --json`));
|
|
37916
37998
|
} else {
|
|
37917
37999
|
try {
|
|
37918
|
-
const smoke = await runWidgetSmoke(ctx.widgetPublicKey, opts.apiUrl);
|
|
38000
|
+
const smoke = await timedCheck(checkTimings, "widget_smoke", () => runWidgetSmoke(ctx.widgetPublicKey, opts.apiUrl));
|
|
37919
38001
|
ctx.conversationId = smoke.conversation_id;
|
|
37920
38002
|
ctx.traceIds = smoke.trace_ids;
|
|
37921
38003
|
ctx.correlationIds = smoke.correlation_ids;
|
|
@@ -37943,7 +38025,7 @@ function registerProve(program3) {
|
|
|
37943
38025
|
const agentId = ctx.agentId;
|
|
37944
38026
|
const adaptiveRuns = Math.max(1, Number(opts.certAdaptiveRuns ?? 30) || 30);
|
|
37945
38027
|
const maxImprovementRounds = Math.max(0, Math.min(5, Number(opts.certMaxImprovementRounds ?? 1) || 1));
|
|
37946
|
-
const cached2 = await withProofCache({
|
|
38028
|
+
const cached2 = await timedCheck(checkTimings, "simulation_certification", () => withProofCache({
|
|
37947
38029
|
cacheDir: opts.proofCacheDir,
|
|
37948
38030
|
kind: "simulation_certification",
|
|
37949
38031
|
keyParts: {
|
|
@@ -37961,7 +38043,7 @@ function registerProve(program3) {
|
|
|
37961
38043
|
maxImprovementRounds,
|
|
37962
38044
|
orgId: ctx.orgId,
|
|
37963
38045
|
apiUrlOverride: opts.apiUrl
|
|
37964
|
-
}));
|
|
38046
|
+
})));
|
|
37965
38047
|
const loop = cached2.value;
|
|
37966
38048
|
const loopWithCache = {
|
|
37967
38049
|
...loop,
|
|
@@ -37991,8 +38073,9 @@ function registerProve(program3) {
|
|
|
37991
38073
|
checks.push(skipped("widget_smoke", "agent_required", "Skipped until an agent is selected.", "foh agent list --json"));
|
|
37992
38074
|
checks.push(skipped("simulation_certification", "agent_required", "Skipped until an agent is selected.", "foh agent list --json"));
|
|
37993
38075
|
}
|
|
37994
|
-
const
|
|
37995
|
-
const
|
|
38076
|
+
const timedChecks = enrichCheckTimings(checks, checkTimings);
|
|
38077
|
+
const status = hasBlockingChecks(timedChecks) ? "hold" : "pass";
|
|
38078
|
+
const nextCommands = Array.from(new Set(timedChecks.map((check2) => check2.next_command).filter((command) => Boolean(command))));
|
|
37996
38079
|
if (status === "pass" && ctx.agentId) {
|
|
37997
38080
|
nextCommands.push(`foh agent publish --agent ${ctx.agentId} --json`);
|
|
37998
38081
|
}
|
|
@@ -38012,10 +38095,11 @@ function registerProve(program3) {
|
|
|
38012
38095
|
trace_ids: ctx.traceIds,
|
|
38013
38096
|
correlation_ids: ctx.correlationIds
|
|
38014
38097
|
},
|
|
38015
|
-
checks,
|
|
38098
|
+
checks: timedChecks,
|
|
38016
38099
|
nextCommands,
|
|
38017
38100
|
extra: {
|
|
38018
|
-
generated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
38101
|
+
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38102
|
+
timing: proofTimingSummary(timedChecks, commandStartedMs)
|
|
38019
38103
|
}
|
|
38020
38104
|
}));
|
|
38021
38105
|
const artifactPath = opts.out ? writeSignedJsonArtifact(String(opts.out), report) : void 0;
|
|
@@ -39805,15 +39889,82 @@ function collapseCommandRecords(records) {
|
|
|
39805
39889
|
}
|
|
39806
39890
|
return order.map((id) => byId.get(id)).filter((record2) => Boolean(record2));
|
|
39807
39891
|
}
|
|
39892
|
+
function readCommandOutputJson(runDir, command) {
|
|
39893
|
+
const artifact = typeof command.output_artifact === "string" && command.output_artifact.trim() ? command.output_artifact.trim() : "";
|
|
39894
|
+
if (!artifact || artifact.includes("..") || artifact.includes("/") || artifact.includes("\\")) return null;
|
|
39895
|
+
const artifactPath = (0, import_path15.join)(runDir, artifact);
|
|
39896
|
+
if (!(0, import_fs16.existsSync)(artifactPath)) return null;
|
|
39897
|
+
try {
|
|
39898
|
+
const text = (0, import_fs16.readFileSync)(artifactPath, "utf8");
|
|
39899
|
+
const firstObject = text.indexOf("{");
|
|
39900
|
+
const lastObject = text.lastIndexOf("}");
|
|
39901
|
+
if (firstObject < 0 || lastObject <= firstObject) return null;
|
|
39902
|
+
return JSON.parse(text.slice(firstObject, lastObject + 1));
|
|
39903
|
+
} catch {
|
|
39904
|
+
return null;
|
|
39905
|
+
}
|
|
39906
|
+
}
|
|
39907
|
+
function commandTimingBreakdown(command, output) {
|
|
39908
|
+
const schemaVersion = String(output?.schema_version || "");
|
|
39909
|
+
if (schemaVersion === "foh_cli_proof_report.v1") {
|
|
39910
|
+
const timing = asObject(output?.timing) || {};
|
|
39911
|
+
const cacheSources = /* @__PURE__ */ new Map();
|
|
39912
|
+
let cacheWaitMs = 0;
|
|
39913
|
+
let cacheHitCount = 0;
|
|
39914
|
+
let cacheMissCount = 0;
|
|
39915
|
+
for (const check2 of toArray2(output?.checks)) {
|
|
39916
|
+
const detail = asObject(check2)?.detail;
|
|
39917
|
+
const proofCache = asObject(asObject(detail)?.proof_cache);
|
|
39918
|
+
if (!proofCache) continue;
|
|
39919
|
+
if (proofCache["hit"] === true) cacheHitCount += 1;
|
|
39920
|
+
if (proofCache["miss"] === true) cacheMissCount += 1;
|
|
39921
|
+
cacheWaitMs += Number(proofCache["waited_ms"] || 0);
|
|
39922
|
+
increment(cacheSources, proofCache["source"] || "unknown");
|
|
39923
|
+
}
|
|
39924
|
+
return {
|
|
39925
|
+
kind: "proof",
|
|
39926
|
+
command: command.command || "",
|
|
39927
|
+
total_ms: Number(timing.total_ms || command.duration_ms || 0),
|
|
39928
|
+
total_check_duration_ms: Number(timing.total_check_duration_ms || 0),
|
|
39929
|
+
slow_checks: toArray2(timing.slow_checks).slice(0, 5),
|
|
39930
|
+
cache_wait_ms: cacheWaitMs,
|
|
39931
|
+
cache_hit_count: cacheHitCount,
|
|
39932
|
+
cache_miss_count: cacheMissCount,
|
|
39933
|
+
cache_sources: ranked(cacheSources)
|
|
39934
|
+
};
|
|
39935
|
+
}
|
|
39936
|
+
if (schemaVersion === "foh_certification_run.v1") {
|
|
39937
|
+
const timing = asObject(output?.timing) || {};
|
|
39938
|
+
const certificate = asObject(output?.certificate) || {};
|
|
39939
|
+
return {
|
|
39940
|
+
kind: "certification",
|
|
39941
|
+
command: command.command || "",
|
|
39942
|
+
total_ms: Number(timing.total_ms || command.duration_ms || 0),
|
|
39943
|
+
api_ms: Number(timing.api_ms || 0),
|
|
39944
|
+
status: output?.status || null,
|
|
39945
|
+
reason_code: output?.reason_code || null,
|
|
39946
|
+
scenario_summary: certificate.scenario_summary || null
|
|
39947
|
+
};
|
|
39948
|
+
}
|
|
39949
|
+
return null;
|
|
39950
|
+
}
|
|
39808
39951
|
function analyzeRunArtifacts(runPath, run, cwd) {
|
|
39809
39952
|
const runDir = (0, import_path15.dirname)(runPath);
|
|
39810
39953
|
const commands = collapseCommandRecords(readNdjson((0, import_path15.join)(runDir, "commands.ndjson")));
|
|
39811
39954
|
const reasonCounts = /* @__PURE__ */ new Map();
|
|
39812
39955
|
const slowSteps = [];
|
|
39956
|
+
const timingBreakdowns = [];
|
|
39813
39957
|
let completed = 0;
|
|
39814
39958
|
let withDuration = 0;
|
|
39815
39959
|
let totalDuration = 0;
|
|
39816
39960
|
for (const command of commands) {
|
|
39961
|
+
const output = readCommandOutputJson(runDir, command);
|
|
39962
|
+
const breakdown = commandTimingBreakdown(command, output);
|
|
39963
|
+
if (breakdown) timingBreakdowns.push({
|
|
39964
|
+
run_id: run.run_id,
|
|
39965
|
+
run_path: (0, import_path15.relative)(cwd, runPath).replaceAll("\\", "/"),
|
|
39966
|
+
...breakdown
|
|
39967
|
+
});
|
|
39817
39968
|
if (command.phase === "completed" || command.completed_at) completed += 1;
|
|
39818
39969
|
if (typeof command.duration_ms === "number") {
|
|
39819
39970
|
withDuration += 1;
|
|
@@ -39858,6 +40009,7 @@ function analyzeRunArtifacts(runPath, run, cwd) {
|
|
|
39858
40009
|
total_command_duration_ms: totalDuration,
|
|
39859
40010
|
command_reason_codes: ranked(reasonCounts),
|
|
39860
40011
|
slow_steps: slowSteps.sort((a, b) => Number(b.duration_ms) - Number(a.duration_ms)).slice(0, 10),
|
|
40012
|
+
timing_breakdowns: timingBreakdowns,
|
|
39861
40013
|
docs_pages_observed: Array.from(docs).sort(),
|
|
39862
40014
|
codex_command_execution_completed_count: codexCommandExecutions,
|
|
39863
40015
|
codex_failed_exit_code_count: codexFailedExitCodes
|
|
@@ -39875,6 +40027,7 @@ function summarizeExternalAgentRuns(options) {
|
|
|
39875
40027
|
const commandReasonCounts = /* @__PURE__ */ new Map();
|
|
39876
40028
|
const docsCounts = /* @__PURE__ */ new Map();
|
|
39877
40029
|
const slowSteps = [];
|
|
40030
|
+
const timingBreakdowns = [];
|
|
39878
40031
|
let manualInterventions = 0;
|
|
39879
40032
|
let commandCount = 0;
|
|
39880
40033
|
let completedCommandCount = 0;
|
|
@@ -39900,6 +40053,7 @@ function summarizeExternalAgentRuns(options) {
|
|
|
39900
40053
|
codexCommandExecutions += Number(artifactSummary.codex_command_execution_completed_count || 0);
|
|
39901
40054
|
codexFailedExitCodes += Number(artifactSummary.codex_failed_exit_code_count || 0);
|
|
39902
40055
|
for (const row of toArray2(artifactSummary.slow_steps)) slowSteps.push(row);
|
|
40056
|
+
for (const row of toArray2(artifactSummary.timing_breakdowns)) timingBreakdowns.push(row);
|
|
39903
40057
|
for (const row of toArray2(artifactSummary.command_reason_codes)) {
|
|
39904
40058
|
const entry = asObject(row);
|
|
39905
40059
|
if (entry) increment(commandReasonCounts, entry.key, Number(entry.count || 1));
|
|
@@ -39936,7 +40090,8 @@ function summarizeExternalAgentRuns(options) {
|
|
|
39936
40090
|
commands_with_duration_count: commandsWithDurationCount,
|
|
39937
40091
|
total_command_duration_ms: totalCommandDurationMs,
|
|
39938
40092
|
command_reason_codes: commandReasonCodes2,
|
|
39939
|
-
slow_steps: slowSteps.sort((a, b) => Number(b.duration_ms || 0) - Number(a.duration_ms || 0) || String(a.command || "").localeCompare(String(b.command || ""))).slice(0, 20)
|
|
40093
|
+
slow_steps: slowSteps.sort((a, b) => Number(b.duration_ms || 0) - Number(a.duration_ms || 0) || String(a.command || "").localeCompare(String(b.command || ""))).slice(0, 20),
|
|
40094
|
+
timing_breakdowns: timingBreakdowns.sort((a, b) => Number(b.total_ms || 0) - Number(a.total_ms || 0) || String(a.command || "").localeCompare(String(b.command || ""))).slice(0, 20)
|
|
39940
40095
|
},
|
|
39941
40096
|
codex_telemetry: {
|
|
39942
40097
|
command_execution_completed_count: codexCommandExecutions,
|