fix(hub): resume Claude SDK sessions

This commit is contained in:
2026-07-08 11:48:20 +08:00
parent 012c8a7d89
commit c73b41e1da
5 changed files with 108 additions and 50 deletions
+2 -2
View File
@@ -29,8 +29,8 @@ export interface RoleEntry {
readonly defaultModel: string | undefined;
/**
* System prompt seeding the agent's persona/instructions. Prepended to the
* run's messages only at session start (resume reads it from the transcript,
* see runner.ts). `undefined` ⇒ no system prompt (bare run).
* run's messages only at session start; Claude SDK resume restores later
* turns from the provider session. `undefined` ⇒ no system prompt (bare run).
*/
readonly systemPrompt?: string | undefined;
/**
+10 -1
View File
@@ -17,7 +17,7 @@
* message streaming, and a battle-tested agent loop — capabilities we'd have
* to build ourselves with a generic provider.
*/
import { query, type SDKMessage, type SDKAssistantMessage, type SDKResultMessage, type SDKPartialAssistantMessage } from "@anthropic-ai/claude-agent-sdk";
import { query, type McpServerConfig, type SDKMessage, type SDKAssistantMessage, type SDKResultMessage, type SDKPartialAssistantMessage } from "@anthropic-ai/claude-agent-sdk";
import type { PrismaClient } from "@prisma/client";
export interface ProjectContext {
@@ -39,6 +39,8 @@ export interface RunRequest {
readonly model: string | undefined;
readonly project: ProjectContext;
readonly systemPrompt: string | undefined;
readonly resumeSessionId?: string | undefined;
readonly mcpServers?: Record<string, McpServerConfig> | undefined;
readonly maxTurns?: number;
readonly runId: string;
readonly sessionId: string;
@@ -53,6 +55,7 @@ export interface RunResult {
readonly text: string;
readonly usage: { inputTokens: number; outputTokens: number };
readonly numTurns: number;
readonly sdkSessionId?: string | undefined;
readonly error?: string;
}
@@ -75,6 +78,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
let fullText = "";
let usage = { inputTokens: 0, outputTokens: 0 };
let numTurns = 0;
let sdkSessionId: string | undefined;
let error: string | undefined;
try {
const options: Parameters<typeof query>[0]["options"] = {
@@ -86,6 +90,8 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
};
if (req.systemPrompt !== undefined) options.systemPrompt = req.systemPrompt;
if (req.model !== undefined) options.model = req.model;
if (req.resumeSessionId !== undefined) options.resume = req.resumeSessionId;
if (req.mcpServers !== undefined) options.mcpServers = req.mcpServers;
const conversation = query({
prompt: req.prompt,
@@ -130,6 +136,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
}
case "result": {
const result = message as SDKResultMessage;
sdkSessionId = result.session_id;
if (result.subtype !== "success") {
error = `result_${result.subtype}`;
}
@@ -144,6 +151,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
text: fullText,
usage,
numTurns,
sdkSessionId,
...(error !== undefined ? { error } : {}),
};
} catch (e) {
@@ -152,6 +160,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
text: fullText,
usage,
numTurns,
sdkSessionId,
error: e instanceof Error ? e.message : String(e),
};
}