|
|
@@ -2,7 +2,7 @@ import type { AutomationMode } from "./modes.js";
|
|
|
import { routeInteractionRequest } from "./request-router.js";
|
|
|
import type { InteractionRequest } from "./intents.js";
|
|
|
import type { InteractionSession } from "./session.js";
|
|
|
-import { bindActiveBook, updateAutomationMode } from "./session.js";
|
|
|
+import { appendInteractionEvent, bindActiveBook, updateAutomationMode } from "./session.js";
|
|
|
|
|
|
type ReviseMode = "local-fix" | "rewrite";
|
|
|
|
|
|
@@ -15,6 +15,7 @@ export interface InteractionRuntimeTools {
|
|
|
|
|
|
export interface InteractionRuntimeResult {
|
|
|
readonly session: InteractionSession;
|
|
|
+ readonly responseText?: string;
|
|
|
}
|
|
|
|
|
|
export async function runInteractionRequest(params: {
|
|
|
@@ -24,6 +25,19 @@ export async function runInteractionRequest(params: {
|
|
|
}): Promise<InteractionRuntimeResult> {
|
|
|
const request = routeInteractionRequest(params.request);
|
|
|
let session = params.session;
|
|
|
+ const addEvent = (
|
|
|
+ nextSession: InteractionSession,
|
|
|
+ kind: string,
|
|
|
+ status: "completed" | "blocked",
|
|
|
+ detail: string,
|
|
|
+ ): InteractionSession => appendInteractionEvent(nextSession, {
|
|
|
+ kind,
|
|
|
+ timestamp: Date.now(),
|
|
|
+ status,
|
|
|
+ bookId: nextSession.activeBookId,
|
|
|
+ chapterNumber: nextSession.activeChapterNumber,
|
|
|
+ detail,
|
|
|
+ });
|
|
|
|
|
|
if (request.mode) {
|
|
|
session = updateAutomationMode(session, request.mode as AutomationMode);
|
|
|
@@ -48,7 +62,11 @@ export async function runInteractionRequest(params: {
|
|
|
}
|
|
|
await params.tools.writeNextChapter(bookId);
|
|
|
session = bindActiveBook(session, bookId);
|
|
|
- return { session: markCompleted(session) };
|
|
|
+ const completed = markCompleted(session);
|
|
|
+ return {
|
|
|
+ session: addEvent(completed, "task.completed", "completed", `Completed write_next for ${bookId}.`),
|
|
|
+ responseText: `Completed write_next for ${bookId}.`,
|
|
|
+ };
|
|
|
}
|
|
|
case "revise_chapter":
|
|
|
case "rewrite_chapter": {
|
|
|
@@ -62,7 +80,11 @@ export async function runInteractionRequest(params: {
|
|
|
const mode: ReviseMode = request.intent === "rewrite_chapter" ? "rewrite" : "local-fix";
|
|
|
await params.tools.reviseDraft(bookId, request.chapterNumber, mode);
|
|
|
session = bindActiveBook(session, bookId, request.chapterNumber);
|
|
|
- return { session: markCompleted(session) };
|
|
|
+ const completed = markCompleted(session);
|
|
|
+ return {
|
|
|
+ session: addEvent(completed, "task.completed", "completed", `Completed ${request.intent} for ${bookId}.`),
|
|
|
+ responseText: `Completed ${request.intent} for ${bookId}.`,
|
|
|
+ };
|
|
|
}
|
|
|
case "update_focus": {
|
|
|
const bookId = request.bookId ?? session.activeBookId;
|
|
|
@@ -74,7 +96,11 @@ export async function runInteractionRequest(params: {
|
|
|
}
|
|
|
await params.tools.updateCurrentFocus(bookId, request.instruction);
|
|
|
session = bindActiveBook(session, bookId);
|
|
|
- return { session: markCompleted(session) };
|
|
|
+ const completed = markCompleted(session);
|
|
|
+ return {
|
|
|
+ session: addEvent(completed, "task.completed", "completed", `Updated current focus for ${bookId}.`),
|
|
|
+ responseText: `Updated current focus for ${bookId}.`,
|
|
|
+ };
|
|
|
}
|
|
|
case "update_author_intent": {
|
|
|
const bookId = request.bookId ?? session.activeBookId;
|
|
|
@@ -86,12 +112,63 @@ export async function runInteractionRequest(params: {
|
|
|
}
|
|
|
await params.tools.updateAuthorIntent(bookId, request.instruction);
|
|
|
session = bindActiveBook(session, bookId);
|
|
|
- return { session: markCompleted(session) };
|
|
|
+ const completed = markCompleted(session);
|
|
|
+ return {
|
|
|
+ session: addEvent(completed, "task.completed", "completed", `Updated author intent for ${bookId}.`),
|
|
|
+ responseText: `Updated author intent for ${bookId}.`,
|
|
|
+ };
|
|
|
}
|
|
|
case "switch_mode":
|
|
|
+ session = markCompleted(session);
|
|
|
return {
|
|
|
- session: markCompleted(session),
|
|
|
+ session: addEvent(session, "task.completed", "completed", `Switched mode to ${session.automationMode}.`),
|
|
|
+ responseText: `Switched mode to ${session.automationMode}.`,
|
|
|
};
|
|
|
+ case "pause_book": {
|
|
|
+ const bookId = request.bookId ?? session.activeBookId;
|
|
|
+ const paused = {
|
|
|
+ ...session,
|
|
|
+ currentExecution: {
|
|
|
+ status: "blocked" as const,
|
|
|
+ bookId,
|
|
|
+ chapterNumber: session.activeChapterNumber,
|
|
|
+ stageLabel: "paused by user",
|
|
|
+ },
|
|
|
+ };
|
|
|
+ return {
|
|
|
+ session: addEvent(paused, "task.completed", "blocked", `Paused ${bookId ?? "current book"}.`),
|
|
|
+ responseText: `Paused ${bookId ?? "current book"}.`,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ case "resume_book": {
|
|
|
+ const bookId = request.bookId ?? session.activeBookId;
|
|
|
+ const resumed = {
|
|
|
+ ...session,
|
|
|
+ currentExecution: {
|
|
|
+ status: "completed" as const,
|
|
|
+ bookId,
|
|
|
+ chapterNumber: session.activeChapterNumber,
|
|
|
+ stageLabel: "ready to continue",
|
|
|
+ },
|
|
|
+ };
|
|
|
+ return {
|
|
|
+ session: addEvent(resumed, "task.completed", "completed", `Resumed ${bookId ?? "current book"}.`),
|
|
|
+ responseText: `Resumed ${bookId ?? "current book"}.`,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ case "explain_status":
|
|
|
+ case "explain_failure": {
|
|
|
+ const bookId = request.bookId ?? session.activeBookId;
|
|
|
+ const stage = session.currentExecution?.stageLabel ?? session.currentExecution?.status ?? "idle";
|
|
|
+ const summary = request.intent === "explain_failure"
|
|
|
+ ? `Current failure context: ${bookId ?? "no active book"} is at ${stage}.`
|
|
|
+ : `Current status: ${bookId ?? "no active book"} is at ${stage}.`;
|
|
|
+ const completed = markCompleted(session);
|
|
|
+ return {
|
|
|
+ session: addEvent(completed, "task.completed", "completed", summary),
|
|
|
+ responseText: summary,
|
|
|
+ };
|
|
|
+ }
|
|
|
default:
|
|
|
throw new Error(`Intent "${request.intent}" is not implemented in the interaction runtime yet.`);
|
|
|
}
|