feat(api): expose REST-only agent routes
Agent CI/CD / docker-image (push) Failing after 35s
Agent CI/CD / deploy-fallback-log (push) Successful in 1s

This commit is contained in:
2026-07-30 20:38:52 +08:00
parent 2415f75841
commit 94529cb141
29 changed files with 3525 additions and 378 deletions
+38 -30
View File
@@ -131,7 +131,7 @@ export const buildChatRouter = (
});
});
chatRouter.post("/session", async (req, res) => {
chatRouter.post("/sessions", async (req, res) => {
const parsed = createSessionPayloadSchema.safeParse(req.body ?? {});
if (!parsed.success) {
res.status(400).json({
@@ -194,7 +194,7 @@ export const buildChatRouter = (
});
});
chatRouter.get("/session/:session_id", async (req, res) => {
chatRouter.get("/sessions/:session_id", async (req, res) => {
const sessionId = req.params.session_id?.trim();
const authContext = getAgentAuthContext(req);
const projectId = authContext.projectId;
@@ -238,7 +238,7 @@ export const buildChatRouter = (
});
});
chatRouter.get("/session/:session_id/stream", async (req, res) => {
chatRouter.get("/sessions/:session_id/runs/current/events", async (req, res) => {
const sessionId = req.params.session_id?.trim();
const authContext = getAgentAuthContext(req);
const projectId = authContext.projectId;
@@ -303,7 +303,7 @@ export const buildChatRouter = (
res.on("close", cleanup);
});
chatRouter.patch("/session/:session_id/title", async (req, res) => {
chatRouter.patch("/sessions/:session_id", async (req, res) => {
const sessionId = req.params.session_id?.trim();
const title =
typeof req.body?.title === "string" ? req.body.title.trim() : "";
@@ -349,7 +349,7 @@ export const buildChatRouter = (
});
});
chatRouter.delete("/session/:session_id", async (req, res) => {
chatRouter.delete("/sessions/:session_id", async (req, res) => {
const sessionId = req.params.session_id?.trim();
const authContext = getAgentAuthContext(req);
const projectId = authContext.projectId;
@@ -395,8 +395,11 @@ export const buildChatRouter = (
sessionUiStateStore,
});
chatRouter.post("/fork", async (req, res) => {
const parsed = forkPayloadSchema.safeParse(req.body);
chatRouter.post("/sessions/:session_id/forks", async (req, res) => {
const parsed = forkPayloadSchema.safeParse({
...req.body,
session_id: req.params.session_id,
});
if (!parsed.success) {
res.status(400).json({
message: "invalid request payload",
@@ -425,6 +428,10 @@ export const buildChatRouter = (
sourceSessionId,
)
: null;
if (!sourceSessionId || !sourceSessionRecord) {
res.status(404).json({ message: "source session not found" });
return;
}
const forkSession = await runtime.createSession();
const { record: targetSessionRecord } = await sessionMetadataStore.ensure({
actorKey,
@@ -436,27 +443,25 @@ export const buildChatRouter = (
});
const nextSessionId = targetSessionRecord.sessionId;
if (sourceSessionId) {
await sessionTranscriptStore.cloneThread(
{
actorKey,
clientSessionId: sourceSessionId,
projectKey,
sessionId: sourceSessionId,
},
{
actorKey,
clientSessionId: nextSessionId,
projectKey,
sessionId: nextSessionId,
},
parsed.data.keep_message_count,
);
}
const sourceState = sourceSessionRecord
? await sessionUiStateStore.read(toSessionUiStateContext(sourceSessionRecord))
: null;
const forkTitle = sourceSessionRecord?.title
await sessionTranscriptStore.cloneThread(
{
actorKey,
clientSessionId: sourceSessionId,
projectKey,
sessionId: sourceSessionId,
},
{
actorKey,
clientSessionId: nextSessionId,
projectKey,
sessionId: nextSessionId,
},
parsed.data.keep_message_count,
);
const sourceState = await sessionUiStateStore.read(
toSessionUiStateContext(sourceSessionRecord),
);
const forkTitle = sourceSessionRecord.title
? `${sourceSessionRecord.title} 副本`
: "新对话副本";
const titledTargetSessionRecord = await sessionMetadataStore.touch(
@@ -495,8 +500,11 @@ export const buildChatRouter = (
}
});
chatRouter.post("/stream", async (req, res) => {
const parsed = payloadSchema.safeParse(req.body);
chatRouter.post("/sessions/:session_id/runs", async (req, res) => {
const parsed = payloadSchema.safeParse({
...req.body,
session_id: req.params.session_id,
});
if (!parsed.success) {
res.status(400).json({
message: "invalid request payload",