niceeval 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "niceeval",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Agent-native eval tool — eval agents, services, functions, and coding-agent fixtures",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,6 +1,17 @@
1
- // artifact fetch 的 URL:相对路径 `artifact/<rel>`。
1
+ // artifact fetch 的 URL:以「页面所在目录」为基底的路径 `<页面目录>/artifact/<rel>`。
2
2
  // 本地 dev server(server.ts 的 /artifact/ 路由)和目录式静态导出(buildView 拷到 <out>/artifact/)
3
- // 共用同一布局,前端不需要知道自己被谁托管。相对路径也保证子路径部署(如 host/foo/)不断链。
3
+ // 共用同一布局:artifact/ 恒为 index.html 的同级目录。基底不能交给浏览器的相对解析——
4
+ // 静态托管常把 <dir>/index.html 服务在无尾斜杠的 <dir> 路径上(反代 rewrite、cleanUrls),
5
+ // 此时相对路径 `artifact/...` 会解析到上一级目录断链。这里自己算目录:pathname 末段带 `.`
6
+ // 视为文件名去掉(直接打开 .../index.html),否则整个 pathname 就是目录(含无尾斜杠形态)。
4
7
  export function artifactUrl(rel: string): string {
5
- return "artifact/" + rel.split("/").map(encodeURIComponent).join("/");
8
+ const tail = "artifact/" + rel.split("/").map(encodeURIComponent).join("/");
9
+ if (typeof location === "undefined") return tail; // 非浏览器环境(测试直调)保持相对形态
10
+ return pageDir(location.pathname) + tail;
11
+ }
12
+
13
+ /** 页面 pathname → 它所在目录(恒以 `/` 结尾)。 */
14
+ export function pageDir(pathname: string): string {
15
+ if (/\.[^/]*$/.test(pathname)) return pathname.replace(/[^/]*$/, "");
16
+ return pathname.endsWith("/") ? pathname : pathname + "/";
6
17
  }
@@ -14,7 +14,7 @@
14
14
  import { mkdtemp, readFile, readdir, rm } from "node:fs/promises";
15
15
  import { tmpdir } from "node:os";
16
16
  import { join } from "node:path";
17
- import { afterEach, describe, expect, it } from "vitest";
17
+ import { afterEach, describe, expect, it, vi } from "vitest";
18
18
  import { createResultsWriter } from "../results/index.ts";
19
19
  import { loadViewScan } from "./data.ts";
20
20
  import { buildView } from "./index.ts";
@@ -135,3 +135,23 @@ describe("index.ts · copyFetchedArtifacts(--out 静态导出)对 sources.json
135
135
  expect(exportedEvents).toEqual([{ type: "message", role: "user", text: "hi" }]);
136
136
  });
137
137
  });
138
+
139
+ describe("artifact-url.ts · fetch 基底 = 页面所在目录(无尾斜杠托管不断链)", () => {
140
+ // bug: memory/showcase-subpath-no-trailing-slash-breaks-artifact-fetch.md
141
+ afterEach(() => vi.unstubAllGlobals());
142
+
143
+ it("页面服务在无尾斜杠子路径(反代 rewrite)时,fetch 拼在该路径目录下", () => {
144
+ vi.stubGlobal("location", { pathname: "/showcase/memory" });
145
+ expect(artifactUrl("e/run/a0/sources.json")).toBe("/showcase/memory/artifact/e/run/a0/sources.json");
146
+ });
147
+
148
+ it("直接打开 <dir>/index.html 时末段按文件名去掉,fetch 落在 <dir>/ 下", () => {
149
+ vi.stubGlobal("location", { pathname: "/foo/index.html" });
150
+ expect(artifactUrl("e/run/a0/trace.json")).toBe("/foo/artifact/e/run/a0/trace.json");
151
+ });
152
+
153
+ it("站点根路径不产生双斜杠", () => {
154
+ vi.stubGlobal("location", { pathname: "/" });
155
+ expect(artifactUrl("e/run/a0/events.json")).toBe("/artifact/e/run/a0/events.json");
156
+ });
157
+ });