niceeval 0.11.4-canary.21 → 0.12.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/dist/report/assets/series-encoding.d.ts +36 -0
- package/dist/report/assets/series-encoding.js +104 -0
- package/dist/report/components/entity-lists/compute.js +5 -17
- package/dist/report/components/entity-lists/content.d.ts +2 -0
- package/dist/report/components/entity-lists/content.js +22 -7
- package/dist/report/definition/cell.d.ts +4 -0
- package/dist/report/definition/cell.js +5 -1
- package/dist/report/definition/primitives/chart.js +125 -25
- package/dist/report/definition/primitives.js +3 -2
- package/dist/report/definition/tree.d.ts +5 -2
- package/dist/report/definition/tree.js +1 -0
- package/dist/report/index.d.ts +1 -1
- package/dist/report/model/aggregate.d.ts +10 -1
- package/dist/report/model/aggregate.js +24 -0
- package/dist/report/model/locale.d.ts +0 -1
- package/dist/report/model/locale.js +0 -2
- package/dist/report/model/types.d.ts +8 -0
- package/dist/report/presentation.d.ts +53 -6
- package/dist/report/presentation.js +40 -5
- package/dist/report/react/index.d.ts +1 -1
- package/dist/report/slices/compute.js +52 -4
- package/dist/report/slices/content.d.ts +2 -1
- package/dist/report/slices/content.js +48 -15
- package/dist/report/slices/validate.js +23 -0
- package/package.json +1 -1
- package/src/report/assets/series-encoding.tsx +177 -0
- package/src/report/assets/styles.css +47 -5
- package/src/report/components/compute.test.ts +15 -9
- package/src/report/components/entity-lists/compute.ts +5 -19
- package/src/report/components/entity-lists/content.test.ts +13 -8
- package/src/report/components/entity-lists/content.ts +24 -7
- package/src/report/definition/cell.ts +8 -1
- package/src/report/definition/primitives/chart.tsx +197 -32
- package/src/report/definition/primitives.tsx +8 -3
- package/src/report/definition/tree.ts +6 -2
- package/src/report/index.ts +11 -1
- package/src/report/model/aggregate.ts +26 -0
- package/src/report/model/locale.ts +0 -2
- package/src/report/model/types.ts +8 -0
- package/src/report/presentation.test.tsx +179 -19
- package/src/report/presentation.ts +114 -11
- package/src/report/react/index.tsx +11 -1
- package/src/report/slices/compute.ts +59 -4
- package/src/report/slices/content.ts +55 -16
- package/src/report/slices/delta-table.test.ts +138 -3
- package/src/report/slices/validate.test.ts +29 -0
- package/src/report/slices/validate.ts +16 -0
- package/src/runner/gate-lease.test.ts +38 -14
- package/src/runner/lock.test.ts +40 -16
- package/src/sandbox/compose.ts +3 -1
- package/src/sandbox/dockerfile-build.ts +4 -1
- package/src/sandbox/runtime.ts +4 -1
- package/src/sandbox/vercel.test.ts +12 -3
- package/src/show/index.ts +10 -9
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// download-directory.test.ts;这里只证明 vercel provider 自己的接线,不重新验证模板本身的
|
|
4
4
|
// ignore/剥离/写盘逻辑)。fake `vsb.runCommand` / `vsb.readFileToBuffer`,不连真实 Vercel
|
|
5
5
|
// API——真实 Vercel Sandbox 行为归 E2E(../../docs/engineering/testing/e2e/README.md)。
|
|
6
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
6
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
7
7
|
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { join } from "node:path";
|
|
@@ -11,6 +11,7 @@ import { VercelSandbox } from "./vercel.ts";
|
|
|
11
11
|
|
|
12
12
|
let roots: string[] = [];
|
|
13
13
|
afterEach(async () => {
|
|
14
|
+
vi.useRealTimers();
|
|
14
15
|
await Promise.all(roots.map((r) => rm(r, { recursive: true, force: true })));
|
|
15
16
|
roots = [];
|
|
16
17
|
});
|
|
@@ -124,6 +125,8 @@ describe("VercelSandbox.runCommand · 执行身份", () => {
|
|
|
124
125
|
// cases: docs/engineering/testing/unit/sandbox.md「Sandbox 复用」——能力归属。
|
|
125
126
|
// 寿命只从当前 session 的远端元数据读(createdAt + timeout),续期走 SDK 的 extendTimeout;
|
|
126
127
|
// plan 上限拒绝续期时如实报 ready:false,不把请求值当成已生效(见 vercel.ts 的注释)。
|
|
128
|
+
// remainingMs = createdAt + timeout - Date.now();CI 并行下 wall clock 在 before/after 两次
|
|
129
|
+
// 读数之间只要前进就会把刚好够的续期压到 ready:false——用假时钟固定 Date.now。
|
|
127
130
|
describe("VercelSandbox.ensureLifetime", () => {
|
|
128
131
|
function sessionFake(opts: { timeout: number; createdAtOffsetMs?: number; extend?: (ms: number) => void }) {
|
|
129
132
|
const session = { createdAt: new Date(Date.now() - (opts.createdAtOffsetMs ?? 0)), timeout: opts.timeout };
|
|
@@ -138,6 +141,8 @@ describe("VercelSandbox.ensureLifetime", () => {
|
|
|
138
141
|
}
|
|
139
142
|
|
|
140
143
|
it("当前 session 的远端剩余时间够时直接确认,不调 extendTimeout", async () => {
|
|
144
|
+
vi.useFakeTimers();
|
|
145
|
+
vi.setSystemTime(new Date("2026-01-01T00:00:00.000Z"));
|
|
141
146
|
let extended = 0;
|
|
142
147
|
const sandbox = makeSandbox(sessionFake({ timeout: 1_200_000, extend: () => (extended += 1) }));
|
|
143
148
|
|
|
@@ -148,7 +153,10 @@ describe("VercelSandbox.ensureLifetime", () => {
|
|
|
148
153
|
});
|
|
149
154
|
|
|
150
155
|
it("剩余不够时按缺口续期,续到够就确认", async () => {
|
|
156
|
+
vi.useFakeTimers();
|
|
157
|
+
vi.setSystemTime(new Date("2026-01-01T00:00:00.000Z"));
|
|
151
158
|
const asked: number[] = [];
|
|
159
|
+
// timeout 10min,已活 9min → 剩余 1min;要 2min → 按缺口续 1min。
|
|
152
160
|
const sandbox = makeSandbox(
|
|
153
161
|
sessionFake({ timeout: 600_000, createdAtOffsetMs: 540_000, extend: (ms) => asked.push(ms) }),
|
|
154
162
|
);
|
|
@@ -156,11 +164,12 @@ describe("VercelSandbox.ensureLifetime", () => {
|
|
|
156
164
|
const result = await sandbox.ensureLifetime(120_000);
|
|
157
165
|
|
|
158
166
|
expect(result.ready).toBe(true);
|
|
159
|
-
expect(asked).
|
|
160
|
-
expect(asked[0]).toBeGreaterThan(0);
|
|
167
|
+
expect(asked).toEqual([60_000]);
|
|
161
168
|
});
|
|
162
169
|
|
|
163
170
|
it("plan 拒绝续期(HTTP 400)时报 ready:false 并带上 provider 理由", async () => {
|
|
171
|
+
vi.useFakeTimers();
|
|
172
|
+
vi.setSystemTime(new Date("2026-01-01T00:00:00.000Z"));
|
|
164
173
|
const sandbox = makeSandbox(sessionFake({ timeout: 600_000, createdAtOffsetMs: 590_000 }));
|
|
165
174
|
|
|
166
175
|
const result = await sandbox.ensureLifetime(1_800_000);
|
package/src/show/index.ts
CHANGED
|
@@ -38,7 +38,7 @@ import { detectLocale, t } from "../i18n/index.ts";
|
|
|
38
38
|
import { currentSample, filterExperiments } from "../sample/index.ts";
|
|
39
39
|
import { matchExperimentSelector } from "../shared/aggregate.ts";
|
|
40
40
|
import { panelCapabilityOf } from "../report/model/panel.ts";
|
|
41
|
-
import { formatMetricValue, formatUSD, verdictMark } from "../report/model/format.ts";
|
|
41
|
+
import { formatMetricValue, formatTimeDistance, formatUSD, verdictMark } from "../report/model/format.ts";
|
|
42
42
|
import { renderAlignedRows, type ColumnAlign } from "../report/model/text-layout.ts";
|
|
43
43
|
import {
|
|
44
44
|
annotatedSourceResult,
|
|
@@ -396,7 +396,7 @@ async function renderCompareSlice(
|
|
|
396
396
|
id: "compare",
|
|
397
397
|
title: "Compare",
|
|
398
398
|
navigation: true,
|
|
399
|
-
render: () => ({ type: Table, props: { data: deltaTableContent(data) } }),
|
|
399
|
+
render: () => ({ type: Table, props: { data: deltaTableContent(data, io.locale) } }),
|
|
400
400
|
};
|
|
401
401
|
const table = await renderHostPageText(
|
|
402
402
|
page,
|
|
@@ -570,9 +570,10 @@ function usageMatrixCellOf(rows: readonly UsageResult[]): UsageMatrixCell {
|
|
|
570
570
|
};
|
|
571
571
|
}
|
|
572
572
|
|
|
573
|
-
/** 一格的 7 列文案;`
|
|
574
|
-
*
|
|
575
|
-
|
|
573
|
+
/** 一格的 7 列文案;`staleSinceMs` 在场时在最后一列(成本)追加相对时距(experiment-table.md
|
|
574
|
+
* 「时效不写字」——时距是这一格的数据,不是叠加的装饰符号),与 `DeltaTable` 的历史执行标注
|
|
575
|
+
* 同一条排版纪律、同一份 `formatTimeDistance` 入口。 */
|
|
576
|
+
function usageMatrixCellText(cell: UsageMatrixCell, staleSinceMs: number | undefined): string[] {
|
|
576
577
|
const cost = cell.costUSD !== undefined ? formatUSD(cell.costUSD) : MISSING_MARK;
|
|
577
578
|
return [
|
|
578
579
|
cell.turns !== undefined ? String(cell.turns) : MISSING_MARK,
|
|
@@ -581,15 +582,15 @@ function usageMatrixCellText(cell: UsageMatrixCell, historical: boolean): string
|
|
|
581
582
|
cell.cacheRead !== undefined ? formatMetricValue(cell.cacheRead) : MISSING_MARK,
|
|
582
583
|
cell.out !== undefined ? formatMetricValue(cell.out) : MISSING_MARK,
|
|
583
584
|
cell.requests !== undefined ? String(cell.requests) : MISSING_MARK,
|
|
584
|
-
|
|
585
|
+
staleSinceMs !== undefined ? `${cost} ${formatTimeDistance(staleSinceMs)}` : cost,
|
|
585
586
|
];
|
|
586
587
|
}
|
|
587
588
|
|
|
588
589
|
/**
|
|
589
590
|
* `--usage` 在对照范围(`--exp` 出现两次以上)下的逐 eval 用量矩阵
|
|
590
591
|
* (docs/feature/reports/show/usage.md「范围化的用量表」)。配对身份、缺席占位、跨快照携带的
|
|
591
|
-
*
|
|
592
|
-
* 计算(条件解析、eval id 配对、watermark/carried 派生的 `historical`),不重新实现一遍;这个
|
|
592
|
+
* 相对时距标注,复用 `deltaTableData` 已经算好的这份判定——与 `renderCompareSlice` 消费同一次
|
|
593
|
+
* 计算(条件解析、eval id 配对、watermark/carried 派生的 `historical`/`staleSinceMs`),不重新实现一遍;这个
|
|
593
594
|
* pivot 只在它之上叠一层用量字段的逐条件合计,数据源是 `usageRowsOf` 已有的逐 attempt 行,按
|
|
594
595
|
* experimentId + evalId 分组求和。每个条件一组 7 列(`USAGE_MATRIX_METRIC_COLUMNS`),缺席
|
|
595
596
|
* 条件整组落 `—`。
|
|
@@ -618,7 +619,7 @@ async function renderUsageCompareSlice(
|
|
|
618
619
|
const deltaCell = row.cells[condition];
|
|
619
620
|
if (!deltaCell) return USAGE_MATRIX_METRIC_COLUMNS.map(() => MISSING_MARK);
|
|
620
621
|
const usageCell = usageMatrixCellOf(byConditionByEval.get(`${condition}\u0000${row.key}`) ?? []);
|
|
621
|
-
return usageMatrixCellText(usageCell, deltaCell.historical);
|
|
622
|
+
return usageMatrixCellText(usageCell, deltaCell.historical ? deltaCell.staleSinceMs : undefined);
|
|
622
623
|
});
|
|
623
624
|
return [row.key, ...cellsText];
|
|
624
625
|
});
|