新增调用前端分区渲染功能,节点通过 ref 文件传输,并增加简单认证
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
import { tool } from "@opencode-ai/plugin";
|
||||
|
||||
export default tool({
|
||||
description: "在前端地图上对 junctions 图层应用分区渲染。",
|
||||
args: {
|
||||
reason: tool.schema
|
||||
.string()
|
||||
.describe("Why this junction rendering action is needed for the user request."),
|
||||
render_ref: tool.schema
|
||||
.string()
|
||||
.describe("Reference to a stored junction rendering payload resolved by the Agent service."),
|
||||
},
|
||||
async execute() {
|
||||
return "已在地图上应用节点分区渲染。";
|
||||
},
|
||||
});
|
||||
+25
-3
@@ -45,6 +45,7 @@ export type StoreResultInput = {
|
||||
|
||||
export type RetrievalContext = {
|
||||
actorKey: string;
|
||||
clientSessionId?: string;
|
||||
maxItems?: number;
|
||||
projectId?: string;
|
||||
};
|
||||
@@ -105,18 +106,33 @@ export class ResultReferenceStore {
|
||||
return record;
|
||||
}
|
||||
|
||||
async getAuthorized(resultRef: string, context: RetrievalContext) {
|
||||
async getAuthorized(resultRef: string, context: RetrievalContext) {
|
||||
const record = await this.readAuthorizedRecord(resultRef, context);
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
const data = projectData(record.data, context.maxItems ?? config.RESULT_REF_MAX_RETRIEVAL_ITEMS);
|
||||
return {
|
||||
ok: true,
|
||||
result_ref: record.resultRef,
|
||||
result_size_bytes: record.sizeBytes,
|
||||
stored_at: record.createdAt,
|
||||
data,
|
||||
preview: record.preview,
|
||||
};
|
||||
}
|
||||
|
||||
async getFullAuthorized(resultRef: string, context: RetrievalContext) {
|
||||
const record = await this.readAuthorizedRecord(resultRef, context);
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
const data = projectData(record.data, context.maxItems ?? config.RESULT_REF_MAX_RETRIEVAL_ITEMS);
|
||||
return {
|
||||
ok: true,
|
||||
result_ref: record.resultRef,
|
||||
result_size_bytes: record.sizeBytes,
|
||||
stored_at: record.createdAt,
|
||||
data,
|
||||
data: record.data,
|
||||
preview: record.preview,
|
||||
};
|
||||
}
|
||||
@@ -173,6 +189,12 @@ export class ResultReferenceStore {
|
||||
if ((record.projectId ?? "") !== (context.projectId ?? "")) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
context.clientSessionId &&
|
||||
record.clientSessionId !== context.clientSessionId
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return record;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import { z } from "zod";
|
||||
import { type LearningOrchestrator } from "../learning/orchestrator.js";
|
||||
import { logger } from "../logger.js";
|
||||
import { MemoryStore } from "../memory/store.js";
|
||||
import { type ResultReferenceStore } from "../results/store.js";
|
||||
import { type OpencodeRuntimeAdapter } from "../runtime/opencode.js";
|
||||
import { type ChatSessionBridge } from "../chat/sessionBridge.js";
|
||||
import { writeLlmRequestAuditLog } from "../audit/llmRequestAudit.js";
|
||||
import { toActorKey } from "../utils/fileStore.js";
|
||||
|
||||
const supportedModels = [
|
||||
"deepseek/deepseek-v4-flash",
|
||||
@@ -36,9 +38,47 @@ export const buildChatRouter = (
|
||||
runtime: OpencodeRuntimeAdapter,
|
||||
memoryStore: MemoryStore,
|
||||
learningOrchestrator: LearningOrchestrator,
|
||||
resultReferenceStore: ResultReferenceStore,
|
||||
) => {
|
||||
const chatRouter = Router();
|
||||
|
||||
chatRouter.get("/render-ref/:renderRef", async (req, res) => {
|
||||
const renderRef = req.params.renderRef?.trim();
|
||||
const userId = req.header("x-user-id")?.trim();
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const clientSessionId =
|
||||
typeof req.query.session_id === "string"
|
||||
? req.query.session_id.trim()
|
||||
: undefined;
|
||||
|
||||
if (!userId) {
|
||||
res.status(400).json({
|
||||
message: "x-user-id is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!renderRef) {
|
||||
res.status(400).json({
|
||||
message: "render_ref is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await resultReferenceStore.getFullAuthorized(renderRef, {
|
||||
actorKey: toActorKey(userId),
|
||||
clientSessionId,
|
||||
projectId,
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
res.status(404).json({ message: "render_ref not found" });
|
||||
return;
|
||||
}
|
||||
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
chatRouter.post("/abort", async (req, res) => {
|
||||
const parsed = abortPayloadSchema.safeParse(req.body);
|
||||
if (!parsed.success) {
|
||||
@@ -1037,6 +1077,7 @@ const toolLabels: Record<string, string> = {
|
||||
view_history: "历史数据面板",
|
||||
view_scada: "SCADA 面板",
|
||||
show_chart: "图表渲染",
|
||||
render_junctions: "节点渲染",
|
||||
};
|
||||
|
||||
const buildPromptWithLearningContext = async (
|
||||
|
||||
+7
-1
@@ -172,7 +172,13 @@ app.post("/internal/tools/session-search", async (req, res) => {
|
||||
|
||||
app.use(
|
||||
"/api/v1/agent/chat",
|
||||
buildChatRouter(sessionBridge, opencodeRuntime, memoryStore, learningOrchestrator),
|
||||
buildChatRouter(
|
||||
sessionBridge,
|
||||
opencodeRuntime,
|
||||
memoryStore,
|
||||
learningOrchestrator,
|
||||
resultReferenceStore,
|
||||
),
|
||||
);
|
||||
|
||||
const bootstrap = async () => {
|
||||
|
||||
Reference in New Issue
Block a user