refactor(core): migrate to Bun and converge acquisition policies and Agent boundaries

This commit is contained in:
root committed 2026-10-13 14:37:03 +08:00
1 parent 3f1c6d02f6
commit 27c0f27434
268 files changed
+7468 -7852

No files matched your search

-9
View File
@@ -1,9 +0,0 @@
{
"name": "@umt/agent",
"version": "0.3.44",
"exports": { ".": "./src/index.ts" },
"tasks": {
"test": "deno run -A npm:vitest run",
"typecheck": "deno run -A npm:typescript/tsc --noEmit -p tsconfig.json"
}
}
+8
View File
@@ -4,5 +4,13 @@
"type": "module",
"exports": {
".": "./src/index.ts"
},
"version": "0.3.44",
"scripts": {
"test": "bun x --bun vitest run",
"typecheck": "bun x --bun tsc --noEmit -p tsconfig.json"
},
"dependencies": {
"@umt/contracts": "workspace:*"
}
}
@@ -0,0 +1,39 @@
---
name: release-facts
title: 资源属性补全
description: 收录规则因分辨率、编码、来源或发布组等属性未知无法判断时,查看资源详情并查证缺失事实,补齐后由原规则重新判断。
triggers:
- 资源属性(未知|缺失|补全)
- release_facts
capabilities:
- release.inspect
- release.apply_facts
- decision.list
- web.search
- web.fetch
sessions: [chat, investigate, child]
---
## 适用意图
收录规则所依赖的分辨率、编码、来源或发布组未知,资源属性事项等待查证后重评。
## 步骤
1. 查看事项与缺失字段,用 release.inspect(refreshDetail: true)读取详情、MediaInfo 和文件信息。刷新失败时说明错误,不能把旧页作为刷新成功的证据。
2. 只补齐该事项缺少且有明确证据的属性。分辨率写实际规格;编码、来源和发布组按详情记载,不从作品类型猜测。
3. 有持续授权时调用 release.apply_facts,带事项、资源、事实和具体出处。原生详情刷新已经补齐字段时可以提交空 facts,服务端核实后触发重评。
4. 无授权或证据不足时保留明确建议,交给用户协同处理。不要修改收录范围、保留目标、组合优先级,也不要直接选另一个资源替代规则判断。
5. 补齐事实不代表资源合格或已下载;最终以原规则重新评估的结果为准。
## 需要批准
`release.apply_facts` 需要覆盖本作品的专用持续授权;已有下载或身份授权不替代它。只读详情与网页查询沿用读取权限。
## 汇报模板
已查证资源编码为 H.265,依据详情页 MediaInfo;补齐后已交原收录规则重新判断。若证据不足,说明具体缺哪项资料与下一步。
## 不要做
不改允许分辨率、保留目标、组合排序、作品身份和季集映射;不覆盖已明确的解析值,不把未知当作不满足,也不把补齐等同于已经下载。
@@ -51,6 +51,7 @@ export const INTENT_ROUTES: readonly IntentRoute[] = [
{ cap: "inventory.query", note: "库里已有的文件与收录版本" },
{ cap: "release.search", note: "找可下载的资源" },
{ cap: "release.inspect", note: "看某条资源的文件清单与促销" },
{ cap: "release.apply_facts", note: "查证后补齐缺失资源属性,再由规则判断" },
{ cap: "download.plan", note: "准备下载,返回是否需要批准" },
{ cap: "download.submit", note: "提交到下载器" },
],
+4 -2
View File
@@ -17,8 +17,10 @@ import type { PromptSection, SessionKind, SkillDoc } from "./types.ts";
// pi 1.x 把 harness 移到 pi-durable 后不再提供 skills,这里只保留本项目用到的部分:
// 一层目录下的 <name>/SKILL.md,不读 .gitignore、不收根目录的散 .md、不跟随符号链接。
/** 仓库内的 Skill 目录;deno compile 用 --include 嵌入(apps/server/deno.json 的 compile 任务) */
export const SKILLS_DIR = fileURLToPath(new URL("../../skills", import.meta.url));
/** 仓库内的 Skill 目录;bun build --compile 用 --include 嵌入(apps/server/package.json 的 compile 任务) */
export const SKILLS_DIR = process.execPath.endsWith("/umt-server")
? join(process.execPath.replace(/[^/]+$/, ""), "skills")
: fileURLToPath(new URL("../../skills", import.meta.url));
const DEFAULT_SESSIONS: SessionKind[] = ["chat", "patrol", "investigate", "child"];
const SESSION_KINDS = new Set<SessionKind>(["chat", "patrol", "investigate", "child", "vision"]);
+4 -8
View File
@@ -354,14 +354,10 @@ describe("PiAgentRuntime + FakeModelProvider", () => {
it("JSONL 恢复:子进程在 download.submit 执行中被 SIGKILL,新进程 resume 得到“结果未知”且不重复提交", async () => {
const sessionDir = await tempDir();
const child = spawn(
process.execPath,
["run", "-A", join(import.meta.dirname!, "fixtures/crash-run.ts"), sessionDir],
{
cwd: join(import.meta.dirname!, ".."),
stdio: ["ignore", "pipe", "pipe"],
},
);
const child = spawn(process.execPath, [join(import.meta.dirname!, "fixtures/crash-run.ts"), sessionDir], {
cwd: join(import.meta.dirname!, ".."),
stdio: ["ignore", "pipe", "pipe"],
});
let stderr = "";
child.stderr.on("data", (d) => {
stderr += String(d);
+3 -3
View File
@@ -150,14 +150,14 @@ describe("按上游装配", () => {
it("测试补全带 sessionId:OpenCode Go 请求头有 x-opencode-session", async () => {
const seen: { url: string; headers: Headers }[] = [];
const orig = globalThis.fetch;
globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
const req = new Request(input, init);
globalThis.fetch = (async (input: string | Request | URL, init?: RequestInit) => {
const req = new Request(input instanceof Request ? input : String(input), init);
seen.push({ url: req.url, headers: req.headers });
return new Response(JSON.stringify({ error: { message: "stubbed" } }), {
status: 500,
headers: { "content-type": "application/json" },
});
}) as typeof fetch;
}) as typeof globalThis.fetch;
try {
const c = new PiUpstreamClient(
spec({ provider: "opencode-go", authKind: "api_key" }),