Files
curriculum-project-hub/hub/prisma/migrations/20260707210000_structured_history/migration.sql
T
hongjr03 e7924f78d5 feat(hub): 结构化运行历史(A-3) + lock 心跳(A-5)
A-3 结构化历史:
- 新增 AgentMessage 表(每条消息的 queryable 投影,transcript 文件仍是 agent 读回记忆)
- 新增 AgentFileChange 表(run 期间文件变更 before/after hash + operation)
- runner.ts: generateText 后 persistAgentMessages 落库 result.responseMessages
- workspace.ts writeFileTool: 写前算 beforeHash(SHA-256),写后算 afterHash,通过 ctx.onFileChange sink 记录
- runner.ts flushFileChanges: 收集 sink 的变更批量写入 AgentFileChange
- ToolContext 加 onFileChange sink 字段
- trigger.ts 接线 runId/sessionId/prisma 到 RunRequest

A-5 lock 心跳:
- ProjectAgentLock 加 heartbeatAt 列
- runner.ts onStepFinish 回调:每步 model step 后更新 heartbeatAt(吞错,lock 可能被 force-release)

60 tests 全过(tsc 干净)。
2026-07-07 22:20:30 +08:00

46 lines
2.1 KiB
SQL

-- AgentMessage: per-message record of the agent loop (queryable projection
-- alongside the transcript JSONL file, which remains the agent's read-back memory).
CREATE TABLE "AgentMessage" (
"id" TEXT NOT NULL,
"sessionId" TEXT NOT NULL,
"runId" TEXT,
"role" TEXT NOT NULL,
"content" TEXT NOT NULL,
"attachments" JSONB NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "AgentMessage_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "AgentMessage_sessionId_createdAt_idx" ON "AgentMessage"("sessionId", "createdAt");
CREATE INDEX "AgentMessage_runId_idx" ON "AgentMessage"("runId");
ALTER TABLE "AgentMessage" ADD CONSTRAINT "AgentMessage_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "AgentSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "AgentMessage" ADD CONSTRAINT "AgentMessage_runId_fkey" FOREIGN KEY ("runId") REFERENCES "AgentRun"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AgentFileChange: file change captured during a run (write/rename/delete).
CREATE TABLE "AgentFileChange" (
"id" TEXT NOT NULL,
"runId" TEXT NOT NULL,
"projectId" TEXT NOT NULL,
"path" TEXT NOT NULL,
"operation" TEXT NOT NULL,
"beforeHash" TEXT,
"afterHash" TEXT,
"diff" TEXT,
"metadata" JSONB NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "AgentFileChange_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "AgentFileChange_runId_idx" ON "AgentFileChange"("runId");
CREATE INDEX "AgentFileChange_projectId_idx" ON "AgentFileChange"("projectId");
CREATE INDEX "AgentFileChange_path_idx" ON "AgentFileChange"("path");
ALTER TABLE "AgentFileChange" ADD CONSTRAINT "AgentFileChange_runId_fkey" FOREIGN KEY ("runId") REFERENCES "AgentRun"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "AgentFileChange" ADD CONSTRAINT "AgentFileChange_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- ProjectAgentLock: add heartbeatAt for liveness (A-5).
ALTER TABLE "ProjectAgentLock" ADD COLUMN "heartbeatAt" TIMESTAMP(3);