|
|
@@ -64,8 +64,7 @@ export default tool({
|
|
|
conversation === "new" ? undefined : await loadConversationState(context.sessionID, conversationKey)
|
|
|
const threadID = args.thread_id?.trim() || savedConversation?.threadID || ""
|
|
|
const continueRunID =
|
|
|
- conversation === "continue" &&
|
|
|
- (!args.thread_id?.trim() || args.thread_id.trim() === savedConversation?.threadID)
|
|
|
+ conversation === "continue" && (!args.thread_id?.trim() || args.thread_id.trim() === savedConversation?.threadID)
|
|
|
? savedConversation?.runID || ""
|
|
|
: ""
|
|
|
// OpenCode 的宿主机目录不会自动挂载进 AgentPaaS Docker。只有调用方
|
|
|
@@ -406,9 +405,7 @@ async function loadAgentPaaSConfig() {
|
|
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("根节点必须是 JSON 对象")
|
|
|
saved = parsed as Record<string, unknown>
|
|
|
} catch (err) {
|
|
|
- throw new Error(
|
|
|
- `AgentPaaS 配置文件无效:${configPath}\n${err instanceof Error ? err.message : String(err)}`,
|
|
|
- )
|
|
|
+ throw new Error(`AgentPaaS 配置文件无效:${configPath}\n${err instanceof Error ? err.message : String(err)}`)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -550,29 +547,91 @@ function withStage(title: string, metadata: Record<string, unknown>): string {
|
|
|
function createResearch67Progress() {
|
|
|
const stages: ProgressStage[] = [
|
|
|
{
|
|
|
- id: "idea-analysis",
|
|
|
- label: "idea-analyst · 创意分析",
|
|
|
+ id: "ontology-seed",
|
|
|
+ label: "本体构建 · seed ontology",
|
|
|
status: "pending",
|
|
|
milestones: [
|
|
|
- { id: "plan", label: "制定分析计划", status: "pending", done: new Set(), total: 1 },
|
|
|
- { id: "directions", label: "生成检索方向", status: "pending", done: new Set(), total: 2 },
|
|
|
- { id: "report", label: "形成分析报告", status: "pending", done: new Set(), total: 2 },
|
|
|
+ { id: "parse", label: "解析问题与学科路由", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "seed", label: "生成基础本体", status: "pending", done: new Set(), total: 1 },
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
- id: "literature-review",
|
|
|
- label: "lit-searcher · 文献检索",
|
|
|
+ id: "ontology-audit",
|
|
|
+ label: "ontology-auditor · 本体审计",
|
|
|
status: "pending",
|
|
|
milestones: [
|
|
|
- { id: "plan", label: "制定检索计划", status: "pending", done: new Set(), total: 1 },
|
|
|
- { id: "search", label: "检索候选文献", status: "pending", done: new Set(), detail: "尚未开始" },
|
|
|
- { id: "select", label: "筛选入选论文", status: "pending", done: new Set(), total: 1 },
|
|
|
- { id: "report", label: "形成文献综述", status: "pending", done: new Set(), total: 2 },
|
|
|
+ { id: "schema", label: "检查 schema 和关系", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "gaps", label: "识别证据与机制缺口", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "ontology-enrichment",
|
|
|
+ label: "ontology-enricher · 知识补全",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "kb", label: "召回本地知识库与教材锚点", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "search", label: "检索与来源核验", status: "pending", done: new Set(), detail: "尚未开始" },
|
|
|
+ { id: "patch", label: "生成本体补丁", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "hypothesis-build",
|
|
|
+ label: "hypothesis-builder · 假设构建",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "hypothesis", label: "生成可证伪假设", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "falsifiers", label: "生成可证伪条件", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "research-plan",
|
|
|
+ label: "plan-builder · 研究计划",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "plan", label: "形成研究计划本体", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "dag", label: "编译 Action DAG", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "evaluation",
|
|
|
+ label: "action-reasoner · 证据评估",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "assess", label: "评估假设支持状态", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "synthesis", label: "形成边界化结论", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "experiment-design",
|
|
|
+ label: "exp-planner · 实验规划 / 授权包",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "protocol", label: "生成实验协议", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "authorization", label: "生成授权与数据回传要求", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "experiment-execution",
|
|
|
+ label: "exp-executor · 授权实验执行",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "auth", label: "确认授权与执行边界", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "run", label: "运行计算/数据实验", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "receipt", label: "保存执行日志与结果", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "result-analysis",
|
|
|
+ label: "result-analyzer · 结果分析",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "analysis", label: "分析实验或回传数据", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "patch", label: "生成 observation patch", status: "pending", done: new Set(), total: 1 },
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
id: "paper-writing",
|
|
|
- label: "paper-writer · 论文撰写",
|
|
|
+ label: "paper-writer · 论文写作",
|
|
|
status: "pending",
|
|
|
milestones: [
|
|
|
{ id: "outline", label: "写作计划与大纲", status: "pending", done: new Set(), total: 2 },
|
|
|
@@ -582,6 +641,64 @@ function createResearch67Progress() {
|
|
|
{ id: "report", label: "形成交付报告", status: "pending", done: new Set(), total: 2 },
|
|
|
],
|
|
|
},
|
|
|
+ {
|
|
|
+ id: "data-verification",
|
|
|
+ label: "data-verifier · 数据与主张核验",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "claims", label: "核验论文主张与来源", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "numbers", label: "核验数据和表述一致性", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "paper-review",
|
|
|
+ label: "paper-reviewer · 论文评审",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "rubric", label: "按科学性和可复现性评分", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "gaps", label: "输出研究缺口", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "review-feedback",
|
|
|
+ label: "review-feedback · 反馈迭代",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "compile", label: "编译评审反馈", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "next", label: "生成下一轮 action 与本体补丁", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "ontology-reaudit",
|
|
|
+ label: "ontology-auditor · 本体再审计",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "audit", label: "检查反馈后的本体", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "decision", label: "决定完成或进入下一轮", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ // 兼容旧三阶段 Lite pipeline 事件。
|
|
|
+ {
|
|
|
+ id: "idea-analysis",
|
|
|
+ label: "idea-analyst · 创意分析",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "plan", label: "制定分析计划", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "directions", label: "生成检索方向", status: "pending", done: new Set(), total: 2 },
|
|
|
+ { id: "report", label: "形成分析报告", status: "pending", done: new Set(), total: 2 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "literature-review",
|
|
|
+ label: "lit-searcher · 文献检索",
|
|
|
+ status: "pending",
|
|
|
+ milestones: [
|
|
|
+ { id: "plan", label: "制定检索计划", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "search", label: "检索候选文献", status: "pending", done: new Set(), detail: "尚未开始" },
|
|
|
+ { id: "select", label: "筛选入选论文", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "report", label: "形成文献综述", status: "pending", done: new Set(), total: 2 },
|
|
|
+ ],
|
|
|
+ },
|
|
|
]
|
|
|
let current: ProgressStage | undefined
|
|
|
let active: ProgressMilestone | undefined
|
|
|
@@ -592,6 +709,58 @@ function createResearch67Progress() {
|
|
|
let activeAttempt = 0
|
|
|
let timerRunning = false
|
|
|
|
|
|
+ const aliases: Record<string, string> = {
|
|
|
+ ontology_seed: "ontology-seed",
|
|
|
+ "seed-ontology": "ontology-seed",
|
|
|
+ "audit-ontology": "ontology-audit",
|
|
|
+ audit_ontology: "ontology-reaudit",
|
|
|
+ ontology_audit: "ontology-audit",
|
|
|
+ "ontology-enrich": "ontology-enrichment",
|
|
|
+ ontology_enrichment: "ontology-enrichment",
|
|
|
+ "enrich-evidence": "ontology-enrichment",
|
|
|
+ enrich_evidence: "ontology-enrichment",
|
|
|
+ search: "ontology-enrichment",
|
|
|
+ "build-hypothesis": "hypothesis-build",
|
|
|
+ build_hypothesis: "hypothesis-build",
|
|
|
+ "hypothesis-builder": "hypothesis-build",
|
|
|
+ "plan-build": "research-plan",
|
|
|
+ "build-research-plan": "research-plan",
|
|
|
+ build_research_plan: "research-plan",
|
|
|
+ "action-dag": "research-plan",
|
|
|
+ synthesis: "evaluation",
|
|
|
+ "falsification-assessment": "evaluation",
|
|
|
+ falsification_assessment: "evaluation",
|
|
|
+ "experiment-plan": "experiment-design",
|
|
|
+ experiment_design: "experiment-design",
|
|
|
+ experiment_execution: "experiment-execution",
|
|
|
+ result_analysis: "result-analysis",
|
|
|
+ paper_writing: "paper-writing",
|
|
|
+ data_verification: "data-verification",
|
|
|
+ paper_review: "paper-review",
|
|
|
+ review_feedback: "review-feedback",
|
|
|
+ }
|
|
|
+
|
|
|
+ const genericMilestones = (): ProgressMilestone[] => [
|
|
|
+ { id: "run", label: "远端阶段执行中", status: "pending", done: new Set(), total: 1 },
|
|
|
+ { id: "receipt", label: "等待 receipt / artifact", status: "pending", done: new Set(), total: 1 },
|
|
|
+ ]
|
|
|
+
|
|
|
+ const normalizeStageID = (stageID: string) => aliases[stageID] ?? aliases[stageID.replaceAll("_", "-")] ?? stageID
|
|
|
+
|
|
|
+ const findOrCreateStage = (stageID: string) => {
|
|
|
+ const normalized = normalizeStageID(stageID || "remote-stage")
|
|
|
+ let stage = stages.find((item) => item.id === normalized)
|
|
|
+ if (stage) return stage
|
|
|
+ stage = {
|
|
|
+ id: normalized,
|
|
|
+ label: `${stageID || "remote-stage"} · 远端阶段`,
|
|
|
+ status: "pending",
|
|
|
+ milestones: genericMilestones(),
|
|
|
+ }
|
|
|
+ stages.push(stage)
|
|
|
+ return stage
|
|
|
+ }
|
|
|
+
|
|
|
const startMilestone = (milestone: ProgressMilestone) => {
|
|
|
if (!current) return
|
|
|
if (milestone.status === "completed") return
|
|
|
@@ -609,7 +778,7 @@ function createResearch67Progress() {
|
|
|
milestone.done?.clear()
|
|
|
milestone.detail = milestone.id === "search" ? "尚未开始" : undefined
|
|
|
}
|
|
|
- if (stage.id === "literature-review") searchCalls = 0
|
|
|
+ if (["literature-review", "ontology-enrichment"].includes(stage.id)) searchCalls = 0
|
|
|
pendingArtifacts.clear()
|
|
|
}
|
|
|
|
|
|
@@ -637,10 +806,16 @@ function createResearch67Progress() {
|
|
|
if (relative === "report.json") return match("report", "report_json")
|
|
|
if (relative === "report.md") return match("report", "report_md")
|
|
|
}
|
|
|
- if (current.id === "literature-review") {
|
|
|
+ if (["literature-review", "ontology-enrichment"].includes(current.id)) {
|
|
|
if (relative === "artifacts/papers_selected.json") return match("select", "papers_selected")
|
|
|
if (relative === "report.json") return match("report", "report_json")
|
|
|
if (relative === "report.md") return match("report", "report_md")
|
|
|
+ if (relative.endsWith("search-log.jsonl")) return match("search", "search_log")
|
|
|
+ }
|
|
|
+ if (current.id === "experiment-design") {
|
|
|
+ if (relative.endsWith("experiment_protocol.json")) return match("protocol", "experiment_protocol")
|
|
|
+ if (relative.endsWith("external_authorization_package.json"))
|
|
|
+ return match("authorization", "external_authorization_package")
|
|
|
}
|
|
|
if (current.id !== "paper-writing") return undefined
|
|
|
if (relative === "artifacts/outline.json") return match("outline", "outline")
|
|
|
@@ -678,7 +853,7 @@ function createResearch67Progress() {
|
|
|
|
|
|
const completeArtifact = (item: { milestone: ProgressMilestone; key: string }) => {
|
|
|
item.milestone.done?.add(item.key)
|
|
|
- if (!item.milestone.total || item.milestone.done?.size !== item.milestone.total) return
|
|
|
+ if (!item.milestone.total || item.milestone.done?.size < item.milestone.total) return
|
|
|
item.milestone.status = "completed"
|
|
|
if (active !== item.milestone || !current) return
|
|
|
const next = current.milestones[current.milestones.indexOf(item.milestone) + 1]
|
|
|
@@ -704,22 +879,20 @@ function createResearch67Progress() {
|
|
|
|
|
|
return {
|
|
|
startStage(stageID: string, attempt: number) {
|
|
|
- const stage = stages.find((stage) => stage.id === stageID)
|
|
|
- if (!stage) return
|
|
|
+ const stage = findOrCreateStage(stageID)
|
|
|
if (stage === current && attempt <= activeAttempt) return
|
|
|
if (stage === current) resetStage(stage)
|
|
|
current = stage
|
|
|
activeAttempt = attempt
|
|
|
- for (const stage of stages) {
|
|
|
- if (stage === current) break
|
|
|
- stage.status = "completed"
|
|
|
+ for (const item of stages) {
|
|
|
+ if (item === current) break
|
|
|
+ if (item.status === "pending") item.status = "completed"
|
|
|
}
|
|
|
current.status = "running"
|
|
|
startMilestone(current.milestones[0])
|
|
|
},
|
|
|
finishStage(stageID: string, status: "completed" | "failed") {
|
|
|
- const stage = stages.find((item) => item.id === stageID)
|
|
|
- if (!stage) return
|
|
|
+ const stage = findOrCreateStage(stageID)
|
|
|
stage.status = status
|
|
|
if (status === "completed") {
|
|
|
for (const milestone of stage.milestones) milestone.status = "completed"
|
|
|
@@ -753,6 +926,14 @@ function createResearch67Progress() {
|
|
|
},
|
|
|
toolCall(toolName: string, content: string) {
|
|
|
const lower = toolName.toLowerCase()
|
|
|
+ if (
|
|
|
+ current?.id === "ontology-enrichment" &&
|
|
|
+ ["kbsearch", "websearch", "webfetch", "openalex_search", "crossref_search"].includes(lower)
|
|
|
+ ) {
|
|
|
+ const milestone = current.milestones.find((item) => item.id === "search")!
|
|
|
+ startMilestone(milestone)
|
|
|
+ return
|
|
|
+ }
|
|
|
if (current?.id === "literature-review" && ["arxiv_search", "openalex_search"].includes(lower)) {
|
|
|
const milestone = current.milestones.find((item) => item.id === "search")!
|
|
|
startMilestone(milestone)
|
|
|
@@ -784,8 +965,13 @@ function createResearch67Progress() {
|
|
|
enqueueArtifacts(lower, [])
|
|
|
return
|
|
|
}
|
|
|
- if (current?.id === "literature-review" && item.milestone.id === "select" && searchCalls) {
|
|
|
- current.milestones.find((milestone) => milestone.id === "search")!.status = "completed"
|
|
|
+ if (
|
|
|
+ ["literature-review", "ontology-enrichment"].includes(current?.id ?? "") &&
|
|
|
+ item.milestone.id === "select" &&
|
|
|
+ searchCalls
|
|
|
+ ) {
|
|
|
+ const searchMilestone = current?.milestones.find((milestone) => milestone.id === "search")
|
|
|
+ if (searchMilestone) searchMilestone.status = "completed"
|
|
|
}
|
|
|
startMilestone(item.milestone)
|
|
|
enqueueArtifacts(lower, [item])
|
|
|
@@ -795,6 +981,15 @@ function createResearch67Progress() {
|
|
|
const failed = /\[(?:tool_)?error\]|mcp_error|"status"\s*:\s*"(?:failed|error)"|"passed"\s*:\s*false/i.test(
|
|
|
content,
|
|
|
)
|
|
|
+ if (
|
|
|
+ current?.id === "ontology-enrichment" &&
|
|
|
+ ["kbsearch", "websearch", "webfetch", "openalex_search", "crossref_search"].includes(lower)
|
|
|
+ ) {
|
|
|
+ if (!failed) searchCalls++
|
|
|
+ const milestone = current.milestones.find((item) => item.id === "search")!
|
|
|
+ milestone.detail = searchCalls ? `已完成 ${searchCalls} 轮检索/核验` : "等待检索重试"
|
|
|
+ return
|
|
|
+ }
|
|
|
if (current?.id === "literature-review" && ["arxiv_search", "openalex_search"].includes(lower)) {
|
|
|
if (!failed) searchCalls++
|
|
|
const milestone = current.milestones.find((item) => item.id === "search")!
|