feat: publish Agent Studio integrations and setup guide

This commit is contained in:
Wenxin Duan
2026-09-16 16:32:16 +08:00
parent 2ad089d68a
commit 05e6060490
106 changed files with 4942 additions and 198 deletions
+56 -1
View File
@@ -1,4 +1,4 @@
import { access, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
import { access, mkdir, mkdtemp, readFile, rm, symlink, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { delimiter, join } from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
@@ -52,6 +52,61 @@ function catalogConstructor(): CatalogConstructor {
}
describe("SkillCatalog", () => {
it("keeps the editor's new content-review reference readable in the isolated Skill snapshot", async () => {
const original = await createSkill(".agents/skills", "swads-short-drama-editor");
const baseDir = join(root, ".agents/skills/swads-short-drama-editor");
await mkdir(join(baseDir, "references"));
await mkdir(join(baseDir, "scripts"));
for (const resource of harness.EDITOR_RESOURCES) await writeFile(join(baseDir, resource), "fixture resource");
await writeFile(join(baseDir, "references/tiktok-adult-content-policy.md"), "fixture selection and final review gate");
const catalog = new harness.SkillCatalog({ cwd: root, agentDir, resources: { [original]: [...harness.EDITOR_RESOURCES] } });
await catalog.reload();
const sessionRoot = join(root, "session");
await mkdir(sessionRoot);
const snapshot = await catalog.createSessionSnapshot(sessionRoot);
const editor = snapshot.skills.find((skill) => skill.name === "swads-short-drama-editor")!;
const workspace = await harness.SafeWorkspace.create(sessionRoot);
const policy = await workspace.resolveReadable(join(editor.baseDir, "references/tiktok-adult-content-policy.md"));
expect(await readFile(policy, "utf8")).toBe("fixture selection and final review gate");
});
it("copies only approved resources with relative links intact and rejects escaped resources", async () => {
const original = await createSkill(".agents/skills", "diagnosis");
const baseDir = join(root, ".agents/skills/diagnosis");
await mkdir(join(baseDir, "references"));
await writeFile(join(baseDir, "references/metrics.md"), "metric contract");
await writeFile(join(baseDir, ".env"), "do not copy");
const catalog = new harness.SkillCatalog({ cwd: root, agentDir,
resources: { [original]: ["references/metrics.md"] },
});
await catalog.reload();
const sessionRoot = join(root, "session");
await mkdir(sessionRoot);
const snapshot = await catalog.createSessionSnapshot(sessionRoot);
const copied = snapshot.skills.find((skill) => skill.name === "diagnosis")!;
expect(await readFile(join(copied.baseDir, "references/metrics.md"), "utf8")).toBe("metric contract");
await expect(access(join(copied.baseDir, ".env"))).rejects.toThrow();
await rm(join(baseDir, "references/metrics.md"));
await symlink(join(baseDir, ".env"), join(baseDir, "references/metrics.md"));
await expect(catalog.createSessionSnapshot(sessionRoot)).rejects.toThrow();
});
it("makes discovered Skill bodies readable inside the Session without admitting project paths", async () => {
const original = await createSkill(".agents/skills", "ads-analysis");
const sessionRoot = join(root, "session");
await mkdir(sessionRoot);
const catalog = new harness.SkillCatalog({ cwd: root, agentDir });
await catalog.reload();
const snapshot = await catalog.createSessionSnapshot(sessionRoot);
const workspace = await harness.SafeWorkspace.create(sessionRoot);
const copied = snapshot.skills.find((skill) => skill.name === "ads-analysis")!;
await expect(workspace.resolveReadable(copied.filePath)).resolves.toBe(copied.filePath);
expect(await readFile(copied.filePath, "utf8")).toContain("Full secret skill body.");
expect(snapshot.index.find(copied.filePath)?.name).toBe("ads-analysis");
expect(snapshot.index.find(original)).toBeUndefined();
await expect(workspace.resolveReadable(original)).rejects.toThrow();
});
it("discovers .agents, .pi, and delimiter-separated extra roots through Pi", async () => {
await createSkill(".agents/skills", "ads-analysis");
await createSkill(".pi/skills", "report-writer");