| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- import type { AutomationMode } from "./modes.js";
- import { routeInteractionRequest } from "./request-router.js";
- import type { InteractionRequest } from "./intents.js";
- import type { ExecutionState, InteractionEvent } from "./events.js";
- import type { PendingDecision, InteractionSession } from "./session.js";
- import {
- appendInteractionEvent,
- bindActiveBook,
- clearPendingDecision,
- updateAutomationMode,
- } from "./session.js";
- type ReviseMode = "local-fix" | "rewrite";
- export interface InteractionRuntimeTools {
- readonly listBooks: () => Promise<ReadonlyArray<string>>;
- readonly createBook?: (input: {
- readonly title: string;
- readonly genre?: string;
- readonly platform?: string;
- readonly language?: "zh" | "en";
- readonly chapterWordCount?: number;
- readonly targetChapters?: number;
- }) => Promise<unknown>;
- readonly exportBook?: (bookId: string, options: {
- readonly format?: "txt" | "md" | "epub";
- readonly approvedOnly?: boolean;
- readonly outputPath?: string;
- }) => Promise<unknown>;
- readonly chat?: (
- input: string,
- options: {
- readonly bookId?: string;
- readonly automationMode: AutomationMode;
- },
- ) => Promise<unknown>;
- readonly writeNextChapter: (bookId: string) => Promise<unknown>;
- readonly reviseDraft: (bookId: string, chapterNumber: number, mode: ReviseMode) => Promise<unknown>;
- readonly patchChapterText: (
- bookId: string,
- chapterNumber: number,
- targetText: string,
- replacementText: string,
- ) => Promise<unknown>;
- readonly renameEntity: (
- bookId: string,
- oldValue: string,
- newValue: string,
- ) => Promise<unknown>;
- readonly updateCurrentFocus: (bookId: string, content: string) => Promise<unknown>;
- readonly updateAuthorIntent: (bookId: string, content: string) => Promise<unknown>;
- readonly writeTruthFile: (bookId: string, fileName: string, content: string) => Promise<unknown>;
- }
- export interface InteractionRuntimeResult {
- readonly session: InteractionSession;
- readonly responseText?: string;
- readonly details?: Readonly<Record<string, unknown>>;
- }
- interface InteractionToolMetadata {
- readonly events?: ReadonlyArray<InteractionEvent>;
- readonly activeChapterNumber?: number;
- readonly currentExecution?: ExecutionState;
- readonly pendingDecision?: PendingDecision;
- readonly responseText?: string;
- readonly details?: Readonly<Record<string, unknown>>;
- }
- function extractToolMetadata(value: unknown): InteractionToolMetadata {
- const chapterNumber = typeof value === "object" && value !== null && "chapterNumber" in value
- && typeof (value as { chapterNumber?: unknown }).chapterNumber === "number"
- ? (value as { chapterNumber: number }).chapterNumber
- : undefined;
- if (!value || typeof value !== "object" || !("__interaction" in value)) {
- return {
- ...(chapterNumber !== undefined ? { activeChapterNumber: chapterNumber } : {}),
- };
- }
- const interaction = (value as {
- readonly __interaction?: InteractionToolMetadata;
- }).__interaction;
- return {
- ...interaction,
- ...(interaction?.activeChapterNumber === undefined && chapterNumber !== undefined
- ? { activeChapterNumber: chapterNumber }
- : {}),
- };
- }
- function buildTaskStartedState(
- session: InteractionSession,
- request: InteractionRequest,
- ): ExecutionState {
- switch (request.intent) {
- case "write_next":
- case "continue_book":
- return {
- status: "planning",
- bookId: request.bookId ?? session.activeBookId,
- chapterNumber: session.activeChapterNumber,
- stageLabel: "preparing chapter inputs",
- };
- case "create_book":
- return {
- status: "planning",
- bookId: request.bookId ?? session.activeBookId,
- stageLabel: "creating book foundation",
- };
- case "export_book":
- return {
- status: "persisting",
- bookId: request.bookId ?? session.activeBookId,
- chapterNumber: session.activeChapterNumber,
- stageLabel: "exporting book artifacts",
- };
- case "revise_chapter":
- case "rewrite_chapter":
- return {
- status: "repairing",
- bookId: request.bookId ?? session.activeBookId,
- chapterNumber: request.chapterNumber ?? session.activeChapterNumber,
- stageLabel: request.intent === "rewrite_chapter" ? "rewriting chapter" : "revising chapter",
- };
- case "update_focus":
- case "update_author_intent":
- case "edit_truth":
- return {
- status: "persisting",
- bookId: request.bookId ?? session.activeBookId,
- chapterNumber: session.activeChapterNumber,
- stageLabel: "applying project edit",
- };
- case "pause_book":
- return {
- status: "blocked",
- bookId: request.bookId ?? session.activeBookId,
- chapterNumber: session.activeChapterNumber,
- stageLabel: "paused by user",
- };
- default:
- return {
- status: "planning",
- bookId: request.bookId ?? session.activeBookId,
- chapterNumber: session.activeChapterNumber,
- stageLabel: `handling ${request.intent}`,
- };
- }
- }
- function shouldWaitForHuman(
- automationMode: AutomationMode,
- request: InteractionRequest,
- ): boolean {
- const contentIntent = request.intent === "write_next"
- || request.intent === "continue_book"
- || request.intent === "revise_chapter"
- || request.intent === "rewrite_chapter"
- || request.intent === "patch_chapter_text";
- const editIntent = request.intent === "update_focus"
- || request.intent === "update_author_intent"
- || request.intent === "edit_truth"
- || request.intent === "rename_entity";
- if (automationMode === "auto") {
- return false;
- }
- if (automationMode === "semi") {
- return contentIntent;
- }
- return contentIntent || editIntent;
- }
- function buildPendingDecision(
- session: InteractionSession,
- request: InteractionRequest,
- chapterNumber?: number,
- ): PendingDecision | undefined {
- if (!shouldWaitForHuman(session.automationMode, request)) {
- return undefined;
- }
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- return undefined;
- }
- return {
- kind: "review-next-step",
- bookId,
- ...(chapterNumber !== undefined ? { chapterNumber } : {}),
- summary: session.automationMode === "manual"
- ? "Execution finished. Choose the next action explicitly."
- : "Execution finished. Waiting for your next decision.",
- };
- }
- function buildWaitingExecution(
- session: InteractionSession,
- request: InteractionRequest,
- chapterNumber?: number,
- ): ExecutionState {
- return {
- status: "waiting_human",
- bookId: request.bookId ?? session.activeBookId,
- ...(chapterNumber !== undefined ? { chapterNumber } : {}),
- stageLabel: "waiting for your next decision",
- };
- }
- function appendToolEvents(
- session: InteractionSession,
- events: ReadonlyArray<InteractionEvent> | undefined,
- ): InteractionSession {
- if (!events || events.length === 0) {
- return session;
- }
- const baseTimestamp = Date.now();
- return events.reduce((nextSession, event, index) => appendInteractionEvent(nextSession, {
- ...event,
- timestamp: baseTimestamp - events.length + index,
- }), session);
- }
- export async function runInteractionRequest(params: {
- readonly session: InteractionSession;
- readonly request: InteractionRequest;
- readonly tools: InteractionRuntimeTools;
- }): Promise<InteractionRuntimeResult> {
- const request = routeInteractionRequest(params.request);
- let session = params.session;
- const addEvent = (
- nextSession: InteractionSession,
- kind: string,
- status: InteractionEvent["status"],
- 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);
- }
- session = clearPendingDecision({
- ...session,
- currentExecution: buildTaskStartedState(session, request),
- });
- session = addEvent(session, "task.started", session.currentExecution!.status, `Started ${request.intent}.`);
- const markCompleted = (nextSession: InteractionSession): InteractionSession => ({
- ...nextSession,
- currentExecution: {
- status: "completed",
- bookId: nextSession.activeBookId,
- chapterNumber: nextSession.activeChapterNumber,
- stageLabel: "completed",
- },
- });
- switch (request.intent) {
- case "create_book": {
- if (!params.tools.createBook) {
- throw new Error("Book creation is not implemented in the interaction runtime yet.");
- }
- if (!request.title) {
- throw new Error("Book creation requires a title.");
- }
- const toolResult = await params.tools.createBook({
- title: request.title,
- genre: request.genre,
- platform: request.platform,
- language: request.language,
- chapterWordCount: request.chapterWordCount,
- targetChapters: request.targetChapters,
- });
- const metadata = extractToolMetadata(toolResult);
- const createdBookId = typeof toolResult === "object" && toolResult !== null && "bookId" in toolResult
- && typeof (toolResult as { bookId?: unknown }).bookId === "string"
- ? (toolResult as { bookId: string }).bookId
- : undefined;
- if (!createdBookId) {
- throw new Error("Create-book tool did not return a book id.");
- }
- session = bindActiveBook(session, createdBookId);
- session = appendToolEvents(session, metadata.events);
- const completed = {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Created ${createdBookId}.`),
- responseText: metadata.responseText ?? `Created ${createdBookId}.`,
- details: metadata.details,
- };
- }
- case "write_next":
- case "continue_book": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- const toolResult = await params.tools.writeNextChapter(bookId);
- const metadata = extractToolMetadata(toolResult);
- session = bindActiveBook(session, bookId, metadata.activeChapterNumber);
- session = appendToolEvents(session, metadata.events);
- const pendingDecision = metadata.pendingDecision ?? buildPendingDecision(
- session,
- request,
- metadata.activeChapterNumber,
- );
- const completed = pendingDecision
- ? {
- ...session,
- pendingDecision,
- currentExecution: metadata.currentExecution ?? buildWaitingExecution(session, request, metadata.activeChapterNumber),
- }
- : {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Completed write_next for ${bookId}.`),
- responseText: metadata.responseText ?? (
- pendingDecision
- ? `Completed write_next for ${bookId}; waiting for your next decision.`
- : `Completed write_next for ${bookId}.`
- ),
- };
- }
- case "list_books": {
- const books = await params.tools.listBooks();
- const completed = markCompleted(session);
- return {
- session: addEvent(completed, "task.completed", "completed", `Listed ${books.length} book(s).`),
- responseText: books.length > 0
- ? `Books: ${books.join(", ")}`
- : "No books found in this project.",
- };
- }
- case "select_book": {
- if (!request.bookId) {
- throw new Error("Book selection requires a book id.");
- }
- const books = await params.tools.listBooks();
- if (!books.includes(request.bookId)) {
- throw new Error(`Book "${request.bookId}" not found in this project.`);
- }
- const completed = markCompleted(bindActiveBook(session, request.bookId));
- return {
- session: addEvent(completed, "task.completed", "completed", `Bound active book to ${request.bookId}.`),
- responseText: `Opened ${request.bookId}.`,
- };
- }
- case "revise_chapter":
- case "rewrite_chapter": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- if (!request.chapterNumber) {
- throw new Error("Chapter number is required for chapter revision.");
- }
- const mode: ReviseMode = request.intent === "rewrite_chapter" ? "rewrite" : "local-fix";
- const toolResult = await params.tools.reviseDraft(bookId, request.chapterNumber, mode);
- const metadata = extractToolMetadata(toolResult);
- const chapterNumber = metadata.activeChapterNumber ?? request.chapterNumber;
- session = bindActiveBook(session, bookId, chapterNumber);
- session = appendToolEvents(session, metadata.events);
- const pendingDecision = metadata.pendingDecision ?? buildPendingDecision(
- session,
- request,
- chapterNumber,
- );
- const completed = pendingDecision
- ? {
- ...session,
- pendingDecision,
- currentExecution: metadata.currentExecution ?? buildWaitingExecution(session, request, chapterNumber),
- }
- : {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Completed ${request.intent} for ${bookId}.`),
- responseText: metadata.responseText ?? (
- pendingDecision
- ? `Completed ${request.intent} for ${bookId}; waiting for your next decision.`
- : `Completed ${request.intent} for ${bookId}.`
- ),
- };
- }
- case "patch_chapter_text": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- if (!request.chapterNumber || !request.targetText || !request.replacementText) {
- throw new Error("Chapter patch requires chapter number, target text, and replacement text.");
- }
- const toolResult = await params.tools.patchChapterText(
- bookId,
- request.chapterNumber,
- request.targetText,
- request.replacementText,
- );
- const metadata = extractToolMetadata(toolResult);
- const chapterNumber = metadata.activeChapterNumber ?? request.chapterNumber;
- session = bindActiveBook(session, bookId, chapterNumber);
- session = appendToolEvents(session, metadata.events);
- const pendingDecision = metadata.pendingDecision ?? buildPendingDecision(
- session,
- request,
- chapterNumber,
- );
- const completed = pendingDecision
- ? {
- ...session,
- pendingDecision,
- currentExecution: metadata.currentExecution ?? buildWaitingExecution(session, request, chapterNumber),
- }
- : {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Patched chapter ${chapterNumber} for ${bookId}.`),
- responseText: metadata.responseText ?? (
- pendingDecision
- ? `Patched chapter ${chapterNumber} for ${bookId}; waiting for your next decision.`
- : `Patched chapter ${chapterNumber} for ${bookId}.`
- ),
- };
- }
- case "rename_entity": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- if (!request.oldValue || !request.newValue) {
- throw new Error("Entity rename requires old and new values.");
- }
- const toolResult = await params.tools.renameEntity(bookId, request.oldValue, request.newValue);
- const metadata = extractToolMetadata(toolResult);
- session = bindActiveBook(session, bookId, metadata.activeChapterNumber);
- session = appendToolEvents(session, metadata.events);
- const pendingDecision = metadata.pendingDecision ?? buildPendingDecision(
- session,
- request,
- metadata.activeChapterNumber,
- );
- const completed = pendingDecision
- ? {
- ...session,
- pendingDecision,
- currentExecution: metadata.currentExecution ?? buildWaitingExecution(session, request, metadata.activeChapterNumber),
- }
- : {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Renamed ${request.oldValue} to ${request.newValue} in ${bookId}.`),
- responseText: metadata.responseText ?? (
- pendingDecision
- ? `Renamed ${request.oldValue} to ${request.newValue} in ${bookId}; waiting for your next decision.`
- : `Renamed ${request.oldValue} to ${request.newValue} in ${bookId}.`
- ),
- };
- }
- case "update_focus": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- if (!request.instruction) {
- throw new Error("Focus update requires instruction content.");
- }
- const toolResult = await params.tools.updateCurrentFocus(bookId, request.instruction);
- const metadata = extractToolMetadata(toolResult);
- session = bindActiveBook(session, bookId);
- session = appendToolEvents(session, metadata.events);
- const pendingDecision = metadata.pendingDecision ?? buildPendingDecision(session, request);
- const completed = pendingDecision
- ? {
- ...session,
- pendingDecision,
- currentExecution: metadata.currentExecution ?? buildWaitingExecution(session, request),
- }
- : {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Updated current focus for ${bookId}.`),
- responseText: metadata.responseText ?? (
- pendingDecision
- ? `Updated current focus for ${bookId}; waiting for your next decision.`
- : `Updated current focus for ${bookId}.`
- ),
- };
- }
- case "update_author_intent": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- if (!request.instruction) {
- throw new Error("Author intent update requires instruction content.");
- }
- const toolResult = await params.tools.updateAuthorIntent(bookId, request.instruction);
- const metadata = extractToolMetadata(toolResult);
- session = bindActiveBook(session, bookId);
- session = appendToolEvents(session, metadata.events);
- const pendingDecision = metadata.pendingDecision ?? buildPendingDecision(session, request);
- const completed = pendingDecision
- ? {
- ...session,
- pendingDecision,
- currentExecution: metadata.currentExecution ?? buildWaitingExecution(session, request),
- }
- : {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Updated author intent for ${bookId}.`),
- responseText: metadata.responseText ?? (
- pendingDecision
- ? `Updated author intent for ${bookId}; waiting for your next decision.`
- : `Updated author intent for ${bookId}.`
- ),
- };
- }
- case "edit_truth": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- if (!request.fileName || !request.instruction) {
- throw new Error("Truth-file edit requires a file name and content.");
- }
- const toolResult = await params.tools.writeTruthFile(bookId, request.fileName, request.instruction);
- const metadata = extractToolMetadata(toolResult);
- session = bindActiveBook(session, bookId);
- session = appendToolEvents(session, metadata.events);
- const pendingDecision = metadata.pendingDecision ?? buildPendingDecision(session, request);
- const completed = pendingDecision
- ? {
- ...session,
- pendingDecision,
- currentExecution: metadata.currentExecution ?? buildWaitingExecution(session, request),
- }
- : {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Updated ${request.fileName} for ${bookId}.`),
- responseText: metadata.responseText ?? (
- pendingDecision
- ? `Updated ${request.fileName} for ${bookId}; waiting for your next decision.`
- : `Updated ${request.fileName} for ${bookId}.`
- ),
- };
- }
- case "export_book": {
- const bookId = request.bookId ?? session.activeBookId;
- if (!params.tools.exportBook) {
- throw new Error("Book export is not implemented in the interaction runtime yet.");
- }
- if (!bookId) {
- throw new Error("No active book is bound to the interaction session.");
- }
- const toolResult = await params.tools.exportBook(bookId, {
- format: request.format,
- approvedOnly: request.approvedOnly,
- outputPath: request.outputPath,
- });
- const metadata = extractToolMetadata(toolResult);
- session = bindActiveBook(session, bookId, metadata.activeChapterNumber);
- session = appendToolEvents(session, metadata.events);
- const completed = {
- ...markCompleted(session),
- currentExecution: metadata.currentExecution ?? markCompleted(session).currentExecution,
- };
- return {
- session: addEvent(completed, "task.completed", "completed", `Exported ${bookId}.`),
- responseText: metadata.responseText ?? `Exported ${bookId}.`,
- details: metadata.details,
- };
- }
- case "switch_mode":
- session = markCompleted(session);
- return {
- 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 "chat": {
- const bookId = request.bookId ?? session.activeBookId;
- const prompt = request.instruction?.trim().toLowerCase() ?? "";
- const toolResult = params.tools.chat
- ? await params.tools.chat(request.instruction ?? "", {
- bookId,
- automationMode: session.automationMode,
- })
- : undefined;
- const metadata = extractToolMetadata(toolResult);
- const responseText = metadata.responseText ?? (
- /^(hi|hello|hey|你好|嗨|哈喽)$/i.test(prompt)
- ? (bookId
- ? `Hi. Active book is ${bookId}. Ask me to continue, revise a chapter, or explain what is blocked.`
- : "Hi. No active book yet. Open a book, list books, or tell me what you want to write.")
- : (bookId
- ? `I’m here. Active book is ${bookId}. You can ask me to continue, revise a chapter, rewrite, change focus, or inspect why the pipeline stopped.`
- : "I’m here. No active book is bound yet. Open a book, list books, or describe what you want to write.")
- );
- const completed = markCompleted(session);
- return {
- session: addEvent(completed, "task.completed", "completed", responseText),
- responseText,
- };
- }
- case "explain_status":
- case "explain_failure": {
- const bookId = request.bookId ?? session.activeBookId;
- const baselineExecution = params.session.currentExecution;
- const stage = baselineExecution?.stageLabel ?? baselineExecution?.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.`);
- }
- }
|