@piagent/platform 1.5.5 → 1.6.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/CHANGELOG.md +117 -0
- package/README.md +9 -8
- package/README.vi.md +9 -5
- package/adapters/web-frontend/profile.json +2 -4
- package/architecture/layers.json +18 -3
- package/benchmarks/deep-logic-v1/SPECIALIST_PROTOCOL.vi.md +122 -0
- package/benchmarks/deep-logic-v1/grade.mjs +272 -10
- package/benchmarks/deep-logic-v1/project/apps/admin/src/billing-summary.js +3 -0
- package/benchmarks/deep-logic-v1/project/benchmark-contract/public-smoke.test.js +166 -0
- package/benchmarks/deep-logic-v1/project/package.json +1 -1
- package/benchmarks/deep-logic-v1/project/packages/billing/src/close-period.js +3 -0
- package/benchmarks/deep-logic-v1/project/packages/billing/src/plan-timeline.js +3 -0
- package/benchmarks/deep-logic-v1/project/test/smoke.test.js +7 -1
- package/benchmarks/deep-logic-v1/prompts/budgeted-context-graph.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/fair-dependency-scheduler.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/layered-policy-resolution.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/resumable-stream-assembly.md +3 -1
- package/benchmarks/deep-logic-v1/prompts/revision-event-reconciliation.md +2 -0
- package/benchmarks/deep-logic-v1/prompts/temporal-usage-billing-close.md +123 -0
- package/benchmarks/deep-logic-v1/prompts/transactional-config-merge.md +2 -0
- package/benchmarks/deep-logic-v1/suite.json +51 -3
- package/benchmarks/deep-logic-v1/variant.mjs +22 -1
- package/benchmarks/production-v1/spend-control.v1.json +68 -0
- package/benchmarks/production-v1/suite.json +42 -3
- package/catalog/capabilities.json +6 -6
- package/docs/command-reference-vietnamese.md +6 -6
- package/docs/context-engine.md +7 -1
- package/docs/distribution-standard.md +7 -7
- package/docs/en/architecture.md +1 -0
- package/docs/languages.json +4 -4
- package/docs/model-options.md +8 -5
- package/docs/operator-manual-vietnamese.md +13 -11
- package/docs/project-adapters.md +2 -2
- package/docs/publishing-for-teams.md +5 -0
- package/docs/quality-benchmark.md +271 -62
- package/docs/release-install-policy.md +10 -9
- package/docs/runtime-policy-design.md +4 -4
- package/docs/runtime-quality-baseline.md +13 -6
- package/docs/security-threat-model.md +2 -2
- package/docs/task-lifecycle-vietnamese.md +2 -2
- package/docs/team-onboarding.md +2 -2
- package/docs/usage-observability.md +7 -2
- package/docs/vi/architecture.md +1 -0
- package/docs-site/architecture.html +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/context-engine.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/index.html +1 -1
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +1 -1
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/whats-new.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +1 -1
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/whats-new.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
- package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
- package/evals/fixtures/piagent-webui/session-live-state-v1.invalid.json +18 -0
- package/evals/fixtures/piagent-webui/session-live-state-v1.valid.json +27 -0
- package/evals/fs4-readiness-matrix.v1.json +2 -2
- package/evals/fs5-causal-arm.v1.json +2 -2
- package/evals/fs5-pilot-protocol.v1.json +2 -2
- package/evals/fs5-pilot-protocol.v4.json +6 -5
- package/evals/fs5-pilot-protocol.v5.json +7 -6
- package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
- package/package.json +3 -1
- package/packages/piagent-core/benchmark/benchmark-assurance.js +4 -1
- package/packages/piagent-core/benchmark/benchmark-bootstrap.js +91 -9
- package/packages/piagent-core/benchmark/benchmark-claim-restrictions.js +38 -7
- package/packages/piagent-core/benchmark/benchmark-cli.js +7 -7
- package/packages/piagent-core/benchmark/benchmark-codex.js +3 -1
- package/packages/piagent-core/benchmark/benchmark-comparison.js +271 -2
- package/packages/piagent-core/benchmark/benchmark-core.js +732 -661
- package/packages/piagent-core/benchmark/benchmark-execution-guard.js +7 -5
- package/packages/piagent-core/benchmark/benchmark-forensics.js +439 -4
- package/packages/piagent-core/benchmark/benchmark-host-readiness.js +639 -0
- package/packages/piagent-core/benchmark/benchmark-matrix.js +22 -4
- package/packages/piagent-core/benchmark/benchmark-normalized-cost.js +317 -0
- package/packages/piagent-core/benchmark/benchmark-preflight.js +3 -1
- package/packages/piagent-core/benchmark/benchmark-process.js +6 -5
- package/packages/piagent-core/benchmark/benchmark-provider-wire.js +126 -0
- package/packages/piagent-core/benchmark/benchmark-record-validation.js +183 -0
- package/packages/piagent-core/benchmark/benchmark-report.js +116 -12
- package/packages/piagent-core/benchmark/benchmark-resume-recovery.js +14 -0
- package/packages/piagent-core/benchmark/benchmark-runner-policy.js +26 -0
- package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +782 -0
- package/packages/piagent-core/benchmark/benchmark-statistics.js +64 -0
- package/packages/piagent-core/benchmark/benchmark-stop-policy.js +8 -5
- package/packages/piagent-core/benchmark/benchmark-suite-identity.js +31 -0
- package/packages/piagent-core/benchmark/benchmark-suite-runtime.js +13 -9
- package/packages/piagent-core/benchmark/benchmark-suite.js +128 -2
- package/packages/piagent-core/benchmark/benchmark-summary-support.js +376 -0
- package/packages/piagent-core/benchmark/benchmark-timing-diagnostics.js +971 -0
- package/packages/piagent-core/benchmark/benchmark-usage.js +311 -0
- package/packages/piagent-core/benchmark/benchmark-workflow.js +166 -0
- package/packages/piagent-core/docs/context-efficiency-improvement-plan.md +1080 -0
- package/packages/piagent-core/extensions/acceptance-contract-semantics.js +83 -69
- package/packages/piagent-core/extensions/acceptance-error-classes.js +160 -0
- package/packages/piagent-core/extensions/acceptance-executable-evidence.js +12 -9
- package/packages/piagent-core/extensions/acceptance-receipt.js +34 -11
- package/packages/piagent-core/extensions/acceptance-state-machine-evidence.js +518 -0
- package/packages/piagent-core/extensions/acceptance-test-binding-evidence.js +60 -0
- package/packages/piagent-core/extensions/context-efficiency-metrics.js +302 -0
- package/packages/piagent-core/extensions/context-efficiency-report.js +167 -0
- package/packages/piagent-core/extensions/context-engine.js +148 -145
- package/packages/piagent-core/extensions/context-evidence.js +48 -0
- package/packages/piagent-core/extensions/context-import-links.js +296 -0
- package/packages/piagent-core/extensions/context-telemetry-integrity.js +65 -0
- package/packages/piagent-core/extensions/criterion-context-pack.js +422 -7
- package/packages/piagent-core/extensions/criterion-graph.js +78 -8
- package/packages/piagent-core/extensions/guard-types.ts +2 -0
- package/packages/piagent-core/extensions/javascript-regex-evidence.js +32 -0
- package/packages/piagent-core/extensions/piagent-guard.ts +233 -41
- package/packages/piagent-core/extensions/task-contract-view.js +17 -3
- package/packages/piagent-core/extensions/task-lifecycle.js +7 -2
- package/packages/piagent-core/extensions/task-state.js +40 -134
- package/packages/piagent-core/extensions/verification-intelligence.js +3 -1
- package/packages/piagent-core/extensions/workspace-evidence-roots.js +157 -0
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/policies/base-policy.json +2 -0
- package/packages/piagent-core/runtime/context/context-delivery.ts +103 -0
- package/packages/piagent-core/runtime/context/context-delta-shadow.ts +53 -0
- package/packages/piagent-core/runtime/context/context-efficiency-format.ts +47 -0
- package/packages/piagent-core/runtime/context/context-evidence-qualification.ts +32 -0
- package/packages/piagent-core/runtime/context/prefix-telemetry.ts +47 -0
- package/packages/piagent-core/runtime/context/repository-memory-hints.ts +27 -0
- package/packages/piagent-core/runtime/hooks/agent-prompt-telemetry.ts +56 -0
- package/packages/piagent-core/runtime/hooks/agent-start-hook.ts +162 -102
- package/packages/piagent-core/runtime/hooks/completion-hook.ts +5 -6
- package/packages/piagent-core/runtime/hooks/input-hook.ts +11 -1
- package/packages/piagent-core/runtime/hooks/session-hooks.ts +22 -2
- package/packages/piagent-core/runtime/hooks/session-start-hook.ts +7 -2
- package/packages/piagent-core/runtime/hooks/tool-result-content-guards.ts +95 -0
- package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +84 -102
- package/packages/piagent-core/runtime/inspection/activity-event-adapter.ts +4 -2
- package/packages/piagent-core/runtime/inspection/activity-recovery.ts +104 -0
- package/packages/piagent-core/runtime/inspection/task-compaction-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/task-handoff-history.ts +1 -1
- package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +53 -0
- package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +34 -6
- package/packages/piagent-core/runtime/model/authenticated-catalog.ts +17 -9
- package/packages/piagent-core/runtime/model/openai-codex-reasoning.ts +83 -0
- package/packages/piagent-core/runtime/model/provider-wire-fingerprint.ts +238 -0
- package/packages/piagent-core/runtime/orchestration/role-policy.ts +1 -1
- package/packages/piagent-core/runtime/product/activity-inspector.ts +7 -2
- package/packages/piagent-core/runtime/product/efficiency-metrics.ts +4 -2
- package/packages/piagent-core/runtime/quality/exact-output-contract.ts +2 -1
- package/packages/piagent-core/runtime/quality/performance-assurance-signals.ts +23 -0
- package/packages/piagent-core/runtime/quality/performance-assurance.ts +6 -2
- package/packages/piagent-core/runtime/recovery/edit-recovery-context.ts +113 -0
- package/packages/piagent-core/runtime/recovery/edit-recovery-delivery.ts +42 -0
- package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +55 -2
- package/packages/piagent-core/runtime/recovery/semantic-repair-runtime.ts +55 -2
- package/packages/piagent-core/runtime/registration/context-commands.ts +66 -5
- package/packages/piagent-core/runtime/registration/policy-tools.ts +46 -11
- package/packages/piagent-core/runtime/registration/task-completion-tools.ts +49 -16
- package/packages/piagent-core/runtime/registration/task-start-guidance.ts +163 -0
- package/packages/piagent-core/runtime/registration/task-start-retry-helpers.ts +37 -0
- package/packages/piagent-core/runtime/registration/task-start-tool.ts +67 -62
- package/packages/piagent-core/runtime/session/runtime-state.ts +154 -2
- package/packages/piagent-core/runtime/session/system-prompt.ts +4 -4
- package/packages/piagent-core/runtime/tools/apply-patch-tool.ts +500 -0
- package/packages/piagent-core/runtime/trajectory/trajectory-runtime.ts +2 -1
- package/packages/piagent-core/runtime/workflows/task-intake.ts +43 -2
- package/packages/piagent-core/security/sensitive-data.js +13 -218
- package/packages/piagent-core/security/sensitive-project-file.js +42 -0
- package/packages/piagent-core/security/sensitive-source-expression.js +330 -0
- package/packages/piagent-core/security/sensitive-source-formats.js +394 -0
- package/packages/piagent-core/security/sensitive-text.js +234 -0
- package/packages/piagent-core/subagents/piagent-worker.md +1 -1
- package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-rD9WJKxs.js → MarkdownMessage-CxeZqTte.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/index-DynIMe8I.js +176 -0
- package/packages/piagent-webui/dist/client/index.html +1 -1
- package/packages/piagent-webui/gateway/gateway-events.ts +109 -5
- package/packages/piagent-webui/gateway/gateway-service.ts +3 -0
- package/packages/piagent-webui/gateway/gateway-session-stream.ts +93 -7
- package/packages/piagent-webui/gateway/session-command-controller.ts +18 -3
- package/packages/piagent-webui/gateway/session-effective-options.ts +47 -0
- package/packages/piagent-webui/gateway/session-live-state.ts +21 -0
- package/packages/piagent-webui/gateway/session-operation-start.ts +5 -1
- package/packages/piagent-webui/gateway/session-operation-watchdog.ts +158 -0
- package/packages/piagent-webui/gateway/session-runtime-factory.ts +45 -0
- package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +139 -124
- package/packages/piagent-webui/server/loopback-server.ts +8 -0
- package/packages/piagent-webui/server/transcript-projection.ts +22 -4
- package/packages/piagent-webui/shared/text-visibility.ts +10 -0
- package/schemas/piagent-webui/catalog-v1.json +9 -0
- package/schemas/piagent-webui/gateway-protocol-v1.schema.json +53 -3
- package/schemas/piagent-webui/session-live-state-v1.schema.json +76 -0
- package/schemas/task-contract.schema.json +12 -1
- package/scripts/benchmark-runner-core.mjs +355 -359
- package/scripts/benchmark-runner-finalization.mjs +309 -0
- package/scripts/benchmark-runner-host-readiness.mjs +94 -0
- package/scripts/benchmark-runner-support.mjs +200 -0
- package/scripts/benchmark-session.mjs +95 -41
- package/scripts/configure-model-scope.sh +4 -3
- package/scripts/helper-evaluation.mjs +1 -1
- package/scripts/install-global.sh +2 -2
- package/scripts/pi-usage-history.mjs +37 -10
- package/scripts/setup.sh +2 -2
- package/scripts/verify-local.sh +5 -1
- package/templates/global/settings.json +2 -1
- package/packages/piagent-webui/dist/client/assets/index-BZRFw1u6.js +0 -174
|
@@ -25,7 +25,7 @@ function assetError(stage, asset, cause) {
|
|
|
25
25
|
return error;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export function createBenchmarkExecutionGuard({ candidateGuard, suiteRoot, suiteIdentity, piAgentHome, codexCredential, runtimeDependencies, commands }) {
|
|
28
|
+
export function createBenchmarkExecutionGuard({ candidateGuard, suiteRoot, suiteIdentity, piAgentHome, codexCredential, runtimeDependencies, commands, verifyCommandAssets = true }) {
|
|
29
29
|
const observeAssets = (stage, runtimeHomes = []) => {
|
|
30
30
|
try {
|
|
31
31
|
const suite = benchmarkTreeIdentity(suiteRoot, { rejectSymlinks: true });
|
|
@@ -61,10 +61,12 @@ export function createBenchmarkExecutionGuard({ candidateGuard, suiteRoot, suite
|
|
|
61
61
|
throw assetError(stage, "codex-credential", error);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
if (verifyCommandAssets) {
|
|
65
|
+
for (const [label, identity] of Object.entries(commands ?? {})) {
|
|
66
|
+
if (!identity) continue;
|
|
67
|
+
try { verifyBenchmarkCommandIdentity(identity, label, { fullPackageClosure: stage === "finalization" || stage === "prepublish" }); }
|
|
68
|
+
catch (error) { throw assetError(stage, `command:${label}`, error); }
|
|
69
|
+
}
|
|
68
70
|
}
|
|
69
71
|
};
|
|
70
72
|
const receipt = (stage, runtimeHomes = []) => {
|
|
@@ -329,6 +329,437 @@ export function benchmarkOperationalEvidence(events) {
|
|
|
329
329
|
};
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
const causalContextReadTools = new Set(["read", "grep", "find", "ls"]);
|
|
333
|
+
const causalContextShellTools = new Set(["bash", "shell", "exec"]);
|
|
334
|
+
const causalContextCoverageLanesV1 = Object.freeze([
|
|
335
|
+
"telemetry-window",
|
|
336
|
+
"session-lifecycle",
|
|
337
|
+
"criterion-initial-pack",
|
|
338
|
+
"pack-lifecycle",
|
|
339
|
+
"direct-fallback-rereads",
|
|
340
|
+
"managed-prefix"
|
|
341
|
+
]);
|
|
342
|
+
const causalContextCoverageLanes = Object.freeze([
|
|
343
|
+
...causalContextCoverageLanesV1,
|
|
344
|
+
"edit-recovery-context"
|
|
345
|
+
]);
|
|
346
|
+
const causalContextCriterionReasons = new Set([
|
|
347
|
+
"selected",
|
|
348
|
+
"auto-context-disabled",
|
|
349
|
+
"criterion-graph-unavailable",
|
|
350
|
+
"no-candidates",
|
|
351
|
+
"no-readable-selection"
|
|
352
|
+
]);
|
|
353
|
+
const causalContextMaximumAggregate = 1_000_000_000;
|
|
354
|
+
|
|
355
|
+
function boundedCausalInteger(value) {
|
|
356
|
+
return Number.isSafeInteger(value) && value >= 0 && value <= causalContextMaximumAggregate;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function boundedCausalSum(values) {
|
|
360
|
+
let total = 0;
|
|
361
|
+
for (const value of values) {
|
|
362
|
+
if (!boundedCausalInteger(value) || total + value > causalContextMaximumAggregate) return null;
|
|
363
|
+
total += value;
|
|
364
|
+
}
|
|
365
|
+
return total;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function normalizeCausalPath(value) {
|
|
369
|
+
if (typeof value !== "string" || !value || value.length > 4_096) return null;
|
|
370
|
+
const normalized = path.posix.normalize(value.replaceAll("\\", "/").replace(/^\.\/+/, "").replace(/\/+/g, "/"));
|
|
371
|
+
if (!normalized || normalized === "." || path.posix.isAbsolute(normalized)
|
|
372
|
+
|| normalized === ".." || normalized.startsWith("../")) return null;
|
|
373
|
+
return normalized;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function causalContextPackEvent(event, idField) {
|
|
377
|
+
const id = event?.[idField];
|
|
378
|
+
if (typeof id !== "string" || !id || id.length > 200 || !Array.isArray(event.selectedItems)
|
|
379
|
+
|| event.selectedItems.length > 10_000 || !boundedCausalInteger(event.estimatedTokens)
|
|
380
|
+
|| typeof event.source !== "string" || !event.source || event.source.length > 100) return null;
|
|
381
|
+
const paths = event.selectedItems.map((item) => normalizeCausalPath(item?.path));
|
|
382
|
+
if (paths.some((item) => item === null)) return null;
|
|
383
|
+
const selectedItemEstimatedTokens = boundedCausalSum(event.selectedItems.map((item) => item?.estimatedTokens));
|
|
384
|
+
if (selectedItemEstimatedTokens === null) return null;
|
|
385
|
+
let binding;
|
|
386
|
+
try {
|
|
387
|
+
binding = JSON.stringify([event.source, event.queryHash ?? null, event.confidence ?? null,
|
|
388
|
+
event.estimatedTokens, event.selectedItems]);
|
|
389
|
+
} catch {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
id,
|
|
394
|
+
estimatedTokens: event.estimatedTokens,
|
|
395
|
+
selectedItems: event.selectedItems.length,
|
|
396
|
+
selectedItemEstimatedTokens,
|
|
397
|
+
criterion: event.source === "criterion-pack",
|
|
398
|
+
paths,
|
|
399
|
+
binding
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function causalContextTask(event, taskByTurn) {
|
|
404
|
+
if (typeof event?.taskRunId === "string" && event.taskRunId) return event.taskRunId;
|
|
405
|
+
if (typeof event?.turnId !== "string" || !event.turnId) return "";
|
|
406
|
+
return taskByTurn.get(event.turnId) ?? "";
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function causalEditRecoveryEvent(event) {
|
|
410
|
+
const toolCallId = event?.toolCallId;
|
|
411
|
+
const targetPath = normalizeCausalPath(event.targetPath);
|
|
412
|
+
if (typeof toolCallId !== "string" || !toolCallId || toolCallId.length > 200
|
|
413
|
+
|| targetPath === null
|
|
414
|
+
|| !/^[a-f0-9]{64}$/.test(String(event.contentHash ?? ""))
|
|
415
|
+
|| !boundedCausalInteger(event.originalChars)
|
|
416
|
+
|| !boundedCausalInteger(event.injectedChars) || event.injectedChars === 0
|
|
417
|
+
|| event.injectedChars <= event.originalChars
|
|
418
|
+
|| !boundedCausalInteger(event.injectedEstimatedTokens) || event.injectedEstimatedTokens === 0
|
|
419
|
+
|| event.sensitiveContentRedacted !== false) return null;
|
|
420
|
+
return {
|
|
421
|
+
toolCallId,
|
|
422
|
+
targetPath,
|
|
423
|
+
taskRunId: typeof event.taskRunId === "string" ? event.taskRunId : "",
|
|
424
|
+
injectedChars: event.injectedChars,
|
|
425
|
+
injectedEstimatedTokens: event.injectedEstimatedTokens
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Persistable causal context evidence for one benchmark session. The projection
|
|
431
|
+
* deliberately drops every path, prompt, hash, identifier and timestamp. Any
|
|
432
|
+
* incomplete lane nulls the aggregate payload so missing telemetry cannot be
|
|
433
|
+
* interpreted as zero context work.
|
|
434
|
+
*/
|
|
435
|
+
export function benchmarkCausalContextReceipt(events, {
|
|
436
|
+
surface,
|
|
437
|
+
sessionId,
|
|
438
|
+
criterionExpected = true,
|
|
439
|
+
telemetryTruncated = false,
|
|
440
|
+
telemetryExists = true,
|
|
441
|
+
telemetryIntegrityFailures = 0,
|
|
442
|
+
recoverableTailBytes = 0
|
|
443
|
+
} = {}) {
|
|
444
|
+
if (surface !== "piagent") return {
|
|
445
|
+
schemaVersion: 1,
|
|
446
|
+
evidenceSource: "not-applicable",
|
|
447
|
+
applicability: "not-applicable",
|
|
448
|
+
available: false,
|
|
449
|
+
coverage: {
|
|
450
|
+
status: "not-applicable",
|
|
451
|
+
telemetryTruncated: false,
|
|
452
|
+
telemetryIntegrityFailures: 0,
|
|
453
|
+
recoverableTailBytes: 0,
|
|
454
|
+
criterionExpected: false,
|
|
455
|
+
sessionEventsObserved: 0,
|
|
456
|
+
observedLanes: 0,
|
|
457
|
+
requiredLanes: 0,
|
|
458
|
+
missingLanes: []
|
|
459
|
+
},
|
|
460
|
+
aggregates: null
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const visible = Array.isArray(events) && typeof sessionId === "string" && sessionId
|
|
464
|
+
? events.filter((event) => event && typeof event === "object" && event.sessionId === sessionId)
|
|
465
|
+
: [];
|
|
466
|
+
const envelopeFailures = visible.filter((event) => event.schemaVersion !== 2 || event.telemetrySource !== "piagent").length;
|
|
467
|
+
const suppliedIntegrityFailures = boundedCausalInteger(telemetryIntegrityFailures)
|
|
468
|
+
? telemetryIntegrityFailures
|
|
469
|
+
: causalContextMaximumAggregate;
|
|
470
|
+
const totalIntegrityFailures = boundedCausalSum([suppliedIntegrityFailures, envelopeFailures])
|
|
471
|
+
?? causalContextMaximumAggregate;
|
|
472
|
+
const promptIndexByTurn = new Map();
|
|
473
|
+
for (const [index, event] of visible.entries()) {
|
|
474
|
+
if (event.event !== "agent_prompt" || typeof event.turnId !== "string" || !event.turnId) continue;
|
|
475
|
+
if (promptIndexByTurn.has(event.turnId)) promptIndexByTurn.set(event.turnId, null);
|
|
476
|
+
else promptIndexByTurn.set(event.turnId, index);
|
|
477
|
+
}
|
|
478
|
+
const offered = new Map(), delivered = new Map(), injected = new Map();
|
|
479
|
+
const criterion = {
|
|
480
|
+
attempts: 0,
|
|
481
|
+
selectedAttempts: 0,
|
|
482
|
+
candidates: 0,
|
|
483
|
+
selectedItems: 0,
|
|
484
|
+
estimatedTokens: 0,
|
|
485
|
+
zeroSelectionReasonCounts: {
|
|
486
|
+
autoContextDisabled: 0,
|
|
487
|
+
criterionGraphUnavailable: 0,
|
|
488
|
+
noCandidates: 0,
|
|
489
|
+
noReadableSelection: 0
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
let criterionEvidenceComplete = true, packLifecycleComplete = true;
|
|
493
|
+
for (const [index, event] of visible.entries()) {
|
|
494
|
+
if (event.event === "criterion_context_pack") {
|
|
495
|
+
const promptIndex = promptIndexByTurn.get(event.turnId);
|
|
496
|
+
const valid = boundedCausalInteger(event.selected) && boundedCausalInteger(event.candidates)
|
|
497
|
+
&& boundedCausalInteger(event.estimatedTokens) && causalContextCriterionReasons.has(event.reasonCode)
|
|
498
|
+
&& event.candidates >= event.selected
|
|
499
|
+
&& Number.isInteger(promptIndex) && promptIndex < index
|
|
500
|
+
&& ((event.selected > 0 && event.reasonCode === "selected") || (event.selected === 0 && event.reasonCode !== "selected"));
|
|
501
|
+
if (!valid) {
|
|
502
|
+
criterionEvidenceComplete = false;
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
criterion.attempts += 1;
|
|
506
|
+
criterion.selectedAttempts += event.selected > 0 ? 1 : 0;
|
|
507
|
+
criterion.candidates += event.candidates;
|
|
508
|
+
criterion.selectedItems += event.selected;
|
|
509
|
+
criterion.estimatedTokens += event.estimatedTokens;
|
|
510
|
+
if (event.selected === 0) {
|
|
511
|
+
const key = {
|
|
512
|
+
"auto-context-disabled": "autoContextDisabled",
|
|
513
|
+
"criterion-graph-unavailable": "criterionGraphUnavailable",
|
|
514
|
+
"no-candidates": "noCandidates",
|
|
515
|
+
"no-readable-selection": "noReadableSelection"
|
|
516
|
+
}[event.reasonCode];
|
|
517
|
+
criterion.zeroSelectionReasonCounts[key] += 1;
|
|
518
|
+
}
|
|
519
|
+
if (![criterion.attempts, criterion.selectedAttempts, criterion.candidates, criterion.selectedItems, criterion.estimatedTokens]
|
|
520
|
+
.every(boundedCausalInteger)) criterionEvidenceComplete = false;
|
|
521
|
+
} else if (event.event === "context_pack_offered") {
|
|
522
|
+
const value = causalContextPackEvent(event, "deliveryId");
|
|
523
|
+
if (!value || offered.has(value.id)) packLifecycleComplete = false;
|
|
524
|
+
else offered.set(value.id, { ...value, index });
|
|
525
|
+
} else if (event.event === "context_delivery_confirmed") {
|
|
526
|
+
const id = event.deliveryId;
|
|
527
|
+
if (typeof id !== "string" || !id || id.length > 200 || !boundedCausalInteger(event.selected) || delivered.has(id)) {
|
|
528
|
+
packLifecycleComplete = false;
|
|
529
|
+
} else delivered.set(id, { id, selectedItems: event.selected, index });
|
|
530
|
+
} else if (event.event === "context_pack_injected") {
|
|
531
|
+
const value = causalContextPackEvent(event, "injectionId");
|
|
532
|
+
if (!value || injected.has(value.id)) packLifecycleComplete = false;
|
|
533
|
+
else injected.set(value.id, { ...value, index });
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
for (const [id, delivery] of delivered) {
|
|
537
|
+
const offer = offered.get(id), injection = injected.get(id);
|
|
538
|
+
if (!offer || !injection || offer.index >= delivery.index || delivery.index >= injection.index
|
|
539
|
+
|| offer.selectedItems !== delivery.selectedItems || delivery.selectedItems !== injection.selectedItems
|
|
540
|
+
|| offer.estimatedTokens !== injection.estimatedTokens
|
|
541
|
+
|| offer.selectedItemEstimatedTokens !== injection.selectedItemEstimatedTokens
|
|
542
|
+
|| offer.binding !== injection.binding) packLifecycleComplete = false;
|
|
543
|
+
}
|
|
544
|
+
for (const id of offered.keys()) if (!delivered.has(id) || !injected.has(id)) packLifecycleComplete = false;
|
|
545
|
+
for (const id of delivered.keys()) if (!offered.has(id) || !injected.has(id)) packLifecycleComplete = false;
|
|
546
|
+
for (const id of injected.keys()) if (!delivered.has(id)) packLifecycleComplete = false;
|
|
547
|
+
const criterionOffered = [...offered.values()].filter((item) => item.criterion);
|
|
548
|
+
const criterionDelivered = [...delivered.keys()].filter((id) => offered.get(id)?.criterion);
|
|
549
|
+
const criterionInjected = [...injected.values()].filter((item) => item.criterion);
|
|
550
|
+
if (criterionExpected === true && criterion.attempts === 0) criterionEvidenceComplete = false;
|
|
551
|
+
if (criterion.selectedAttempts !== criterionOffered.length
|
|
552
|
+
|| criterion.selectedItems !== boundedCausalSum(criterionOffered.map((item) => item.selectedItems))
|
|
553
|
+
|| criterion.estimatedTokens !== boundedCausalSum(criterionOffered.map((item) => item.estimatedTokens))
|
|
554
|
+
|| criterionOffered.length !== criterionDelivered.length
|
|
555
|
+
|| criterionDelivered.length !== criterionInjected.length) criterionEvidenceComplete = false;
|
|
556
|
+
|
|
557
|
+
const taskByTurn = new Map(visible
|
|
558
|
+
.filter((event) => event.event === "turn_task_bound" && typeof event.turnId === "string"
|
|
559
|
+
&& event.turnId && typeof event.taskRunId === "string" && event.taskRunId)
|
|
560
|
+
.map((event) => [event.turnId, event.taskRunId]));
|
|
561
|
+
const activePackByTask = new Map();
|
|
562
|
+
const pendingDirectReads = new Map(), seenDirectReadIds = new Set();
|
|
563
|
+
let directFallbackRereadCalls = 0, shellToolCallsObserved = 0;
|
|
564
|
+
let fallbackEvidenceComplete = packLifecycleComplete;
|
|
565
|
+
for (const event of visible) {
|
|
566
|
+
if (event.event === "context_pack_injected") {
|
|
567
|
+
const taskRunId = causalContextTask(event, taskByTurn);
|
|
568
|
+
const paths = injected.get(event.injectionId)?.paths;
|
|
569
|
+
if (!taskRunId || !paths) {
|
|
570
|
+
fallbackEvidenceComplete = false;
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
const selected = activePackByTask.get(taskRunId) ?? new Set();
|
|
574
|
+
for (const selectedPath of paths) selected.add(selectedPath);
|
|
575
|
+
activePackByTask.set(taskRunId, selected);
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
if (event.event === "tool_call") {
|
|
579
|
+
const toolName = String(event.toolName ?? "").toLowerCase();
|
|
580
|
+
const taskRunId = causalContextTask(event, taskByTurn);
|
|
581
|
+
const selected = activePackByTask.get(taskRunId);
|
|
582
|
+
if (selected && causalContextShellTools.has(toolName)) shellToolCallsObserved += 1;
|
|
583
|
+
if (!selected || !causalContextReadTools.has(toolName)) continue;
|
|
584
|
+
const target = normalizeCausalPath(event.targetPath);
|
|
585
|
+
if (!target || typeof event.toolCallId !== "string" || !event.toolCallId || event.toolCallId.length > 200) {
|
|
586
|
+
fallbackEvidenceComplete = false;
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
if (!selected.has(target)) continue;
|
|
590
|
+
if (seenDirectReadIds.has(event.toolCallId)) fallbackEvidenceComplete = false;
|
|
591
|
+
else {
|
|
592
|
+
seenDirectReadIds.add(event.toolCallId);
|
|
593
|
+
pendingDirectReads.set(event.toolCallId, target);
|
|
594
|
+
}
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
const toolCallId = typeof event.toolCallId === "string" ? event.toolCallId : "";
|
|
598
|
+
if (!toolCallId || !pendingDirectReads.has(toolCallId)) continue;
|
|
599
|
+
if (event.event === "tool_decision" && event.decision === "blocked") {
|
|
600
|
+
pendingDirectReads.delete(toolCallId);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
if (event.event === "tool_result") {
|
|
604
|
+
if (event.isError !== true) directFallbackRereadCalls += 1;
|
|
605
|
+
pendingDirectReads.delete(toolCallId);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
if (pendingDirectReads.size > 0) fallbackEvidenceComplete = false;
|
|
609
|
+
|
|
610
|
+
const recoverySessionStarts = visible.filter((event) => event.event === "session_start");
|
|
611
|
+
const firstRecoverySessionStart = visible.findIndex((event) => event.event === "session_start");
|
|
612
|
+
const recoveryCapabilityComplete = recoverySessionStarts.length > 0
|
|
613
|
+
&& recoverySessionStarts.every((event) => event.editRecoveryContextTelemetryVersion === 1);
|
|
614
|
+
const editRecoveryReceipts = new Map(), editRecoveryResults = new Map();
|
|
615
|
+
let editRecoveryEvidenceComplete = recoveryCapabilityComplete;
|
|
616
|
+
for (const [index, event] of visible.entries()) {
|
|
617
|
+
if (event.event === "edit_recovery_context") {
|
|
618
|
+
const value = causalEditRecoveryEvent(event);
|
|
619
|
+
if (!value || index <= firstRecoverySessionStart || editRecoveryReceipts.has(value.toolCallId)) editRecoveryEvidenceComplete = false;
|
|
620
|
+
else editRecoveryReceipts.set(value.toolCallId, { ...value, index });
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
if (event.event !== "tool_result") continue;
|
|
624
|
+
const recoveryFailure = ["edit-anchor-not-unique", "edit-anchor-stale"].includes(event.reasonCode);
|
|
625
|
+
if (!recoveryFailure) {
|
|
626
|
+
if (event.editRecoveryContext !== undefined) editRecoveryEvidenceComplete = false;
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
const toolCallId = event.toolCallId;
|
|
630
|
+
if (typeof toolCallId !== "string" || !toolCallId || toolCallId.length > 200
|
|
631
|
+
|| editRecoveryResults.has(toolCallId)
|
|
632
|
+
|| index <= firstRecoverySessionStart
|
|
633
|
+
|| String(event.toolName ?? "").toLowerCase() !== "edit"
|
|
634
|
+
|| event.isError !== true
|
|
635
|
+
|| typeof event.editRecoveryContext !== "boolean"
|
|
636
|
+
|| normalizeCausalPath(event.targetPath) === null
|
|
637
|
+
|| (event.editRecoveryContext === true
|
|
638
|
+
&& (!boundedCausalInteger(event.editRecoveryInjectedChars) || event.editRecoveryInjectedChars === 0
|
|
639
|
+
|| !boundedCausalInteger(event.editRecoveryEstimatedTokens) || event.editRecoveryEstimatedTokens === 0))
|
|
640
|
+
|| (event.editRecoveryContext === false
|
|
641
|
+
&& (event.editRecoveryInjectedChars !== undefined || event.editRecoveryEstimatedTokens !== undefined))) {
|
|
642
|
+
editRecoveryEvidenceComplete = false;
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
editRecoveryResults.set(toolCallId, {
|
|
646
|
+
index,
|
|
647
|
+
injected: event.editRecoveryContext,
|
|
648
|
+
targetPath: normalizeCausalPath(event.targetPath),
|
|
649
|
+
taskRunId: typeof event.taskRunId === "string" ? event.taskRunId : "",
|
|
650
|
+
injectedChars: event.editRecoveryInjectedChars,
|
|
651
|
+
injectedEstimatedTokens: event.editRecoveryEstimatedTokens
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
for (const [toolCallId, receipt] of editRecoveryReceipts) {
|
|
655
|
+
const result = editRecoveryResults.get(toolCallId);
|
|
656
|
+
if (!result || result.injected !== true || receipt.index >= result.index
|
|
657
|
+
|| receipt.targetPath !== result.targetPath
|
|
658
|
+
|| receipt.taskRunId !== result.taskRunId
|
|
659
|
+
|| receipt.injectedChars !== result.injectedChars
|
|
660
|
+
|| receipt.injectedEstimatedTokens !== result.injectedEstimatedTokens) editRecoveryEvidenceComplete = false;
|
|
661
|
+
}
|
|
662
|
+
for (const [toolCallId, result] of editRecoveryResults) {
|
|
663
|
+
if (result.injected !== editRecoveryReceipts.has(toolCallId)) editRecoveryEvidenceComplete = false;
|
|
664
|
+
}
|
|
665
|
+
const editRecoveryInjectedChars = boundedCausalSum([...editRecoveryReceipts.values()].map((item) => item.injectedChars));
|
|
666
|
+
const editRecoveryEstimatedTokens = boundedCausalSum([...editRecoveryReceipts.values()].map((item) => item.injectedEstimatedTokens));
|
|
667
|
+
editRecoveryEvidenceComplete &&= editRecoveryInjectedChars !== null && editRecoveryEstimatedTokens !== null;
|
|
668
|
+
|
|
669
|
+
const prompts = visible.map((event, index) => ({ event, index }))
|
|
670
|
+
.filter((item) => item.event.event === "agent_prompt");
|
|
671
|
+
const managedPrefixComplete = prompts.length > 0
|
|
672
|
+
&& prompts.every((item) => typeof item.event.managedInstructionsCompacted === "boolean");
|
|
673
|
+
const compactedPrompts = prompts.filter((item) => item.event.managedInstructionsCompacted === true).length;
|
|
674
|
+
const lastPromptIndex = prompts.at(-1)?.index ?? -1;
|
|
675
|
+
const lifecycleComplete = prompts.length > 0
|
|
676
|
+
&& visible.some((event, index) => index > lastPromptIndex
|
|
677
|
+
&& (event.event === "agent_settled" || event.event === "session_shutdown"));
|
|
678
|
+
const offeredTokens = boundedCausalSum([...offered.values()].map((item) => item.estimatedTokens));
|
|
679
|
+
const deliveredTokens = boundedCausalSum([...delivered.keys()].map((id) => offered.get(id)?.estimatedTokens));
|
|
680
|
+
const injectedTokens = boundedCausalSum([...injected.values()].map((item) => item.estimatedTokens));
|
|
681
|
+
const offeredItemTokens = boundedCausalSum([...offered.values()].map((item) => item.selectedItemEstimatedTokens));
|
|
682
|
+
const deliveredItemTokens = boundedCausalSum([...delivered.keys()].map((id) => offered.get(id)?.selectedItemEstimatedTokens));
|
|
683
|
+
const injectedItemTokens = boundedCausalSum([...injected.values()].map((item) => item.selectedItemEstimatedTokens));
|
|
684
|
+
const offeredItems = boundedCausalSum([...offered.values()].map((item) => item.selectedItems));
|
|
685
|
+
const deliveredItems = boundedCausalSum([...delivered.values()].map((item) => item.selectedItems));
|
|
686
|
+
const injectedItems = boundedCausalSum([...injected.values()].map((item) => item.selectedItems));
|
|
687
|
+
const aggregateBoundsComplete = [offeredTokens, deliveredTokens, injectedTokens, offeredItemTokens, deliveredItemTokens,
|
|
688
|
+
injectedItemTokens, offeredItems, deliveredItems, injectedItems]
|
|
689
|
+
.every((value) => value !== null) && boundedCausalInteger(directFallbackRereadCalls)
|
|
690
|
+
&& boundedCausalInteger(shellToolCallsObserved);
|
|
691
|
+
packLifecycleComplete &&= aggregateBoundsComplete;
|
|
692
|
+
fallbackEvidenceComplete &&= aggregateBoundsComplete;
|
|
693
|
+
|
|
694
|
+
const lanes = {
|
|
695
|
+
"telemetry-window": telemetryExists === true && telemetryTruncated !== true
|
|
696
|
+
&& totalIntegrityFailures === 0 && recoverableTailBytes === 0,
|
|
697
|
+
"session-lifecycle": lifecycleComplete,
|
|
698
|
+
"criterion-initial-pack": criterionEvidenceComplete,
|
|
699
|
+
"pack-lifecycle": packLifecycleComplete,
|
|
700
|
+
"direct-fallback-rereads": fallbackEvidenceComplete,
|
|
701
|
+
"managed-prefix": managedPrefixComplete,
|
|
702
|
+
"edit-recovery-context": editRecoveryEvidenceComplete
|
|
703
|
+
};
|
|
704
|
+
const missingLanes = causalContextCoverageLanes.filter((lane) => lanes[lane] !== true);
|
|
705
|
+
const observedLanes = causalContextCoverageLanes.length - missingLanes.length;
|
|
706
|
+
const available = missingLanes.length === 0;
|
|
707
|
+
const compactions = visible.filter((event) => event.event === "session_compact").length;
|
|
708
|
+
const managedPrefixState = compactedPrompts === 0
|
|
709
|
+
? "uncompacted"
|
|
710
|
+
: compactedPrompts === prompts.length ? "compacted" : "mixed";
|
|
711
|
+
return {
|
|
712
|
+
schemaVersion: 2,
|
|
713
|
+
evidenceSource: "context-telemetry-closed-aggregate-v2",
|
|
714
|
+
applicability: "piagent",
|
|
715
|
+
available,
|
|
716
|
+
coverage: {
|
|
717
|
+
status: available ? "complete" : visible.length === 0 || !lifecycleComplete ? "unavailable" : "partial",
|
|
718
|
+
telemetryTruncated: telemetryTruncated === true,
|
|
719
|
+
telemetryIntegrityFailures: totalIntegrityFailures,
|
|
720
|
+
recoverableTailBytes: boundedCausalInteger(recoverableTailBytes) ? recoverableTailBytes : causalContextMaximumAggregate,
|
|
721
|
+
criterionExpected: criterionExpected === true,
|
|
722
|
+
sessionEventsObserved: visible.length,
|
|
723
|
+
observedLanes,
|
|
724
|
+
requiredLanes: causalContextCoverageLanes.length,
|
|
725
|
+
missingLanes
|
|
726
|
+
},
|
|
727
|
+
aggregates: available ? {
|
|
728
|
+
packCounts: { offered: offered.size, delivered: delivered.size, injected: injected.size },
|
|
729
|
+
estimatedTokens: { offered: offeredTokens, delivered: deliveredTokens, injected: injectedTokens },
|
|
730
|
+
selectedItemEstimatedTokens: { offered: offeredItemTokens, delivered: deliveredItemTokens, injected: injectedItemTokens },
|
|
731
|
+
selectedItemCounts: { offered: offeredItems, delivered: deliveredItems, injected: injectedItems },
|
|
732
|
+
criterionInitialPack: {
|
|
733
|
+
...criterion,
|
|
734
|
+
offered: criterionOffered.length,
|
|
735
|
+
delivered: criterionDelivered.length,
|
|
736
|
+
injected: criterionInjected.length
|
|
737
|
+
},
|
|
738
|
+
directFallbackRereads: {
|
|
739
|
+
successfulCalls: directFallbackRereadCalls,
|
|
740
|
+
shellToolCallsObserved,
|
|
741
|
+
definition: "successful-direct-path-tool-call-v1"
|
|
742
|
+
},
|
|
743
|
+
editRecoveryContext: {
|
|
744
|
+
count: editRecoveryReceipts.size,
|
|
745
|
+
failuresObserved: editRecoveryResults.size,
|
|
746
|
+
suppressedFailures: [...editRecoveryResults.values()].filter((item) => item.injected === false).length,
|
|
747
|
+
injectedChars: editRecoveryInjectedChars,
|
|
748
|
+
injectedEstimatedTokens: editRecoveryEstimatedTokens,
|
|
749
|
+
evidenceCoverage: {
|
|
750
|
+
status: "complete",
|
|
751
|
+
observed: editRecoveryReceipts.size,
|
|
752
|
+
comparable: editRecoveryReceipts.size,
|
|
753
|
+
rate: 1
|
|
754
|
+
},
|
|
755
|
+
definition: "matched-edit-recovery-context-receipt-v1"
|
|
756
|
+
},
|
|
757
|
+
compaction: { eventsObserved: compactions, state: compactions > 0 ? "observed" : "not-observed" },
|
|
758
|
+
managedPrefix: { promptsObserved: prompts.length, compactedPrompts, state: managedPrefixState }
|
|
759
|
+
} : null
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
|
|
332
763
|
export function loadReplayFailurePlan(reportPath) {
|
|
333
764
|
let report;
|
|
334
765
|
try {
|
|
@@ -440,12 +871,13 @@ export function classifyPreUsageFailure(agent, usage, diagnosticInput, { termina
|
|
|
440
871
|
const measuredUsage = Number.isInteger(usage?.sessions) && usage.sessions > 0
|
|
441
872
|
&& ["input", "output", "cacheRead", "cacheWrite", "reasoning", "total", "fresh"]
|
|
442
873
|
.every((field) => Number.isFinite(usage?.[field]) && Number(usage[field]) >= 0)
|
|
443
|
-
&&
|
|
874
|
+
&& usage.fresh === usage.input + usage.output
|
|
875
|
+
&& usage.total === usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
444
876
|
const measuredZeroUsage = measuredUsage
|
|
445
|
-
&& ["input", "output", "cacheRead", "cacheWrite", "reasoning", "total", "fresh"
|
|
877
|
+
&& ["input", "output", "cacheRead", "cacheWrite", "reasoning", "total", "fresh"]
|
|
446
878
|
.every((field) => Number(usage[field]) === 0);
|
|
447
879
|
const providerUnavailable = /\b(?:server(?:s)? (?:are )?(?:currently )?overloaded|temporarily unavailable|service unavailable|try again later)\b/.test(diagnostic);
|
|
448
|
-
if (agent.code
|
|
880
|
+
if ((terminalProviderError || agent.code !== 0) && measuredUsage && providerUnavailable) {
|
|
449
881
|
const afterUsage = Number(usage.fresh) > 0;
|
|
450
882
|
return {
|
|
451
883
|
failure: afterUsage
|
|
@@ -467,7 +899,10 @@ export function classifyPreUsageFailure(agent, usage, diagnosticInput, { termina
|
|
|
467
899
|
}
|
|
468
900
|
if (agent.code === 0) return undefined;
|
|
469
901
|
if (/\b(?:provider|safety|policy|refus(?:al|ed|e)|disallowed|not allowed|cannot assist|can't assist|cyber safety)\b/.test(diagnostic)) {
|
|
470
|
-
return
|
|
902
|
+
return measuredUsage
|
|
903
|
+
? { failure: "provider-policy-refusal-after-measured-usage", class: "provider-policy", usageStatus: "measured-but-unaccepted", retryable: false }
|
|
904
|
+
: { failure: "provider-policy-refusal-with-usage-unavailable", class: "provider-policy", usageStatus: "unknown-after-provider-start", retryable: false };
|
|
471
905
|
}
|
|
906
|
+
if (measuredUsage) return { failure: `agent-exit-${agent.code}-after-measured-usage`, class: "agent-process", usageStatus: "measured-but-unaccepted", retryable: false };
|
|
472
907
|
return { failure: `agent-exit-${agent.code}-with-usage-unavailable`, class: "unknown-cost", usageStatus: "unknown-after-provider-start", retryable: true };
|
|
473
908
|
}
|