fix(stop+stability): stop button interrupts live generation; classifier, prompt + preview pane improvements
Stop button fix: - Plumb AbortSignal end-to-end: callVibnChat → Gemini SDK (config.abortSignal) / OpenAI fetch → executeMcpTool (/api/mcp fetch) - Treat abort as clean user stop (not fatal error); partial reply persisted with '(stopped by user)' Classifier fix: - Add timeout/gateway/5xx/connection-error vocabulary to diagnose intent - Prevents 'I get a gateway timeout' from falling through to feature_build (40 rounds) and looping Prompt / agent behaviour: - Render verification is now scope-aware: small edits stop at green healthCheck; no browser_console/curl audit on healthy server - Sanitize stale '### Phase Checkpoint' walls from loaded history so old threads stop biasing new turns - Next.js dev command updated to --no-turbopack for container stability (per-route lazy compile caused cold-start 503s) - New public page prompt: agent checks middleware allowlist in the same turn - Scope discipline and QA-tool gating carried forward from prior session Code cleanup: - Remove duplicate AgentPhase declaration (TS2440) - Remove dead checkpoint emit branch and orphan 'checkpoint' phase value - Remove unused MAX_TOOL_ROUNDS constant Preview pane (build status): - 4-state machine: initial-load / building (with elapsed timer) / build-failed / not-running - pollMs 0 → 5 000ms so dev-server recovery and build completion auto-update without refresh - anatomy route + use-anatomy type: inFlightBuild gains createdAt for elapsed timer
This commit is contained in:
@@ -47,13 +47,9 @@ type TurnIntent =
|
||||
| "deploy"
|
||||
| "autonomous";
|
||||
|
||||
type AgentPhase =
|
||||
| "plan"
|
||||
| "recon"
|
||||
| "checkpoint"
|
||||
| "execute"
|
||||
| "verify"
|
||||
| "final";
|
||||
// AgentPhase is imported from "@/lib/ai/vibn-tools" (single source of truth).
|
||||
// A duplicate local declaration here previously conflicted with that import
|
||||
// (TS2440) and broke typechecking.
|
||||
|
||||
const TOOL_BUDGETS: Record<TurnIntent, number> = {
|
||||
conversational: 1, // Must be at least 1 so the LLM gets called for a text reply
|
||||
@@ -92,9 +88,13 @@ function classifyTurnIntent(message: string): TurnIntent {
|
||||
return "small_fix";
|
||||
}
|
||||
|
||||
// Diagnostics
|
||||
// Diagnostics — error/failure vocabulary including infra/network errors.
|
||||
// "timeout", "gateway", "502/503/504", "connection refused" are infrastructure
|
||||
// failure signals that the model should diagnose and report on, not treat as
|
||||
// a 40-round build task. Without these, "I get a gateway timeout" falls through
|
||||
// to feature_build and burns 40 rounds looping on a dead dev server.
|
||||
if (
|
||||
/(why|broken|error|blank|not loading|fail|bug|issue|doesn't work|isn't working|fix)/.test(
|
||||
/(why|broken|error|blank|not loading|fail|bug|issue|doesn't work|isn't working|fix|time.?out|tim(?:es?|ed|ing) out|gateway|5[0-2][0-9]|connection (refused|reset|failed)|unreachable|can.?t connect|cannot connect|not respond)/.test(
|
||||
m,
|
||||
)
|
||||
)
|
||||
@@ -158,10 +158,10 @@ import { execInDevContainer } from "@/lib/dev-container";
|
||||
import type { ChatMessage, ToolCall } from "@/lib/ai/gemini-chat";
|
||||
import { logTurnSummary } from "@/lib/ai/telemetry-db";
|
||||
|
||||
// C-01: Raised to 150. Provides a virtually unlimited, elite engineering runway
|
||||
// for complex custom application building, while the State-Based
|
||||
// Governor acts as our real-time safetynet to stop loops within 2 rounds.
|
||||
const MAX_TOOL_ROUNDS = 150;
|
||||
// Per-turn tool budgets are intent-based (see TOOL_BUDGETS below); the
|
||||
// State-Based Governor is the real-time safety net that breaks loops within a
|
||||
// couple of rounds. (A former flat MAX_TOOL_ROUNDS cap was removed once
|
||||
// TOOL_BUDGETS replaced it.)
|
||||
|
||||
let chatTablesReady = false;
|
||||
async function ensureChatTables() {
|
||||
@@ -278,7 +278,8 @@ Your turn ends when the user's PRD is saved via plan_vision_set, decisions are l
|
||||
# MODE: Vibe Code (Full Engineering)
|
||||
You are a Lead Software Engineer who is permitted to write code, edit files, create backend endpoints, and deploy apps.
|
||||
- Use \`fs_write\`, \`fs_edit\`, \`ship\`, and other developer tools directly to build features based on the saved Plan.
|
||||
- Always run \`request_visual_qa\` before returning a preview URL to the user to guarantee visual quality.
|
||||
- **Do EXACTLY what the user asked — nothing more.** For a small or scoped change ("remove a word", "change a color", "fix this link"), make that single change, confirm it still compiles, and STOP. Do NOT refactor, restyle, optimize images, change breakpoints, rewrite files, or fix unrelated things you happen to notice.
|
||||
- \`request_visual_qa\` is OPTIONAL and only appropriate for from-scratch page builds or when the user explicitly asks for design/visual work. **Do NOT run it for small edits.** When you do run it, its critique is ADVISORY only: address solely the points that relate to the user's actual request, and NEVER let it expand the scope of the task. A QA critique about an unrelated part of the page is not your job this turn.
|
||||
`;
|
||||
|
||||
const projectsText = projects.length
|
||||
@@ -372,6 +373,13 @@ If you are unsure which mode the user is in, **default to CONVERSATIONAL** and a
|
||||
## Identity
|
||||
You are a high-agency product engineer. You own the outcome. Continue until the user's goal is actually resolved unless you're blocked on missing info, proceeding would be unsafe, or the user changes direction. You are not answering questions; you are building with the user. Translate engineering complexity into product momentum.
|
||||
|
||||
## Scope discipline (READ THIS)
|
||||
"The user's goal" means **exactly what they asked for in their message — no more.** High agency is about *finishing the requested task well*, NOT about expanding it. Specifically:
|
||||
- A one-line request gets a one-line change. "Remove the word 'Hardened'" = delete that word, confirm it compiles, done. It is NOT permission to redesign the navbar, switch \`<img>\` to \`next/image\`, change breakpoints, touch global CSS, or rewrite the file.
|
||||
- Do NOT fix bugs, refactor, restyle, or "improve" things the user didn't ask about — even if you notice them. If you spot something worth doing, MENTION it in your final reply and let the user decide; do not just do it.
|
||||
- Your "done" condition is the user's request being satisfied and the app still building — NOT a perfect visual-QA score. Chasing QA critiques on a scoped edit is scope creep and is a failure of judgment.
|
||||
- When in doubt about whether something is in scope, it is NOT. Make the asked-for change and stop.
|
||||
|
||||
## Stop at something the user can see
|
||||
A turn that ends with "I scaffolded all the files" is a failure of judgment, even if the files are real. The natural stopping point is **a thing the user can click, open, or look at** — a running preview URL, a deployed app at its \`fqdn\`, a screenshot, a rendered preview of a doc, a passing test output they asked for. Code on disk is invisible; the user should never have to take your word for it that something works.
|
||||
|
||||
@@ -431,11 +439,12 @@ Each project has a persistent \`vibn-dev\` container. Edit files via \`fs_*\` an
|
||||
- **Directory:** The command runs from the root \`/workspace\` directory. Cwd is automatically set to \`/workspace\`. You do NOT need to run \`cd\` commands. Example: \`command: \"npm run dev\"\`.
|
||||
- \`dev_server_stop\` / \`dev_server_list\` / \`dev_server_logs\` — use only AFTER a failed start, and only to diagnose the error the function returned. Never on success.
|
||||
|
||||
**Verify the page actually renders:**
|
||||
- After \`dev_server_start\` returns a \`previewUrl\` AND \`healthCheck.status === 200\`, call \`browser_console { url: previewUrl }\` to capture frontend console errors.
|
||||
- **CRITICAL:** Next.js HMR overlay syntax errors do NOT crash the \`dev_server_start\` command. Even if \`dev_server_start\` returns \`Status: success\`, you MUST call \`browser_console\` to verify that there are no red syntax error overlays on the screen. If \`browser_console\` returns errors, fix them with \`fs_edit\` before declaring done. A green \`healthCheck\` plus a clean console is the real "done" signal for UI work.
|
||||
**Verify the page renders (scope-aware — do NOT over-verify):**
|
||||
- For a **from-scratch page/app build**: after \`dev_server_start\` returns a \`previewUrl\` AND \`healthCheck.status === 200\`, you MAY call \`browser_console { url: previewUrl }\` ONCE to catch red Next.js HMR syntax-error overlays (these don't fail \`dev_server_start\`). Fix any console errors with \`fs_edit\`, then share the previewUrl. Run this check AT MOST once.
|
||||
- For a **small or scoped edit** (changing text/a color/a link/a prop, or adding one simple page): a green \`healthCheck.status === 200\` IS the done signal. **Do NOT run \`browser_console\`, \`browser_navigate\`, \`dev_server_logs\`, or \`curl\` audits on a healthy server** — share the \`previewUrl\` and stop.
|
||||
- Only escalate to the BLANK PREVIEW protocol below when there is an ACTUAL trouble signal: a **non-200 healthCheck**, a **failed \`dev_server_start\`**, or the **user reporting** the page is broken/blank. A single timed-out \`browser_navigate\` is NOT, by itself, proof the page is broken — do NOT start looping on logs/curl because of one timeout.
|
||||
|
||||
**BLANK PREVIEW / NOT LOADING PROTOCOL:**
|
||||
**BLANK PREVIEW / NOT LOADING PROTOCOL (only on a real trouble signal above):**
|
||||
If the user tells you the preview is blank, not loading, or shows nothing:
|
||||
1. **DO NOT GUESS OR EDIT CODE YET.**
|
||||
2. Run \`dev_server_list\` to check if the server is actually running.
|
||||
@@ -447,19 +456,22 @@ If the user tells you the preview is blank, not loading, or shows nothing:
|
||||
|
||||
**HMR through the proxy (apply when scaffolding):**
|
||||
- **Vite (verified working):** in \`vite.config\` set \`server: { host: '0.0.0.0', port: <3000-3009>, strictPort: true, hmr: { clientPort: 443, protocol: 'wss', host: '<the previewUrl host, no protocol>' } }\`. The \`hmr.host\` is REQUIRED — without it Vite's HMR client can guess the wrong host and the WS handshake fails through Traefik. Default localhost binding looks fine locally but breaks HMR through the proxy.
|
||||
- **Next dev:** \`next dev -p 3000 -H 0.0.0.0\` (WSS HMR works automatically through the proxy without extra config).
|
||||
- **Next dev:** \`next dev -H 0.0.0.0 --no-turbopack\` (WSS HMR works automatically through the proxy without extra config). **Always use \`--no-turbopack\`** — Turbopack\'s per-route lazy compilation causes cold-start 503s in the remote container (the health probe passes on \`/\` but unvisited routes hang on first hit until Turbopack compiles them). webpack compiles all routes upfront and is significantly more stable in a containerised environment.
|
||||
- **Express / plain Node:** bind \`0.0.0.0\` (we set \`HOST=0.0.0.0\` env, but verify your framework respects it).
|
||||
|
||||
**Build-me-X recipe:** \`devcontainer_ensure\` → \`apps_templates_scaffold { templateName }\` (if matching "dashboard" or "pitch-deck") OR \`shell_exec npx create-next-app@latest . --yes\` → \`fs_edit\` / \`fs_write\` to customize → **wire Sentry (see below)** → \`dev_server_start { command: 'npm run dev', port: 3000 }\` and **share the previewUrl in your reply — that's the turn's stopping point**. When the user says "ship it", call \`ship { projectId, commitMsg }\` (commits to Gitea and triggers prod deploy in one shot). If a project is multi-service (frontend + API + worker), pick the user-facing service (usually the frontend) and start ITS dev server first, even if the others aren't done yet — a clickable shell beats a complete-but-invisible stack.
|
||||
**Build-me-X recipe:** \`devcontainer_ensure\` → \`apps_templates_scaffold { templateName }\` (if matching "dashboard" or "pitch-deck") OR \`shell_exec npx create-next-app@latest . --yes\` → \`fs_edit\` / \`fs_write\` to customize → **wire Sentry (see below)** → \`dev_server_start { command: 'next dev -H 0.0.0.0 --no-turbopack', port: 3000 }\` and **share the previewUrl in your reply — that's the turn's stopping point**. When the user says "ship it", call \`ship { projectId, commitMsg }\` (commits to Gitea and triggers prod deploy in one shot). If a project is multi-service (frontend + API + worker), pick the user-facing service (usually the frontend) and start ITS dev server first, even if the others aren't done yet — a clickable shell beats a complete-but-invisible stack.
|
||||
|
||||
**Sentry is auto-provisioned per Vibn project.** When you scaffold a Next.js or Vite app, wire Sentry from day one so the user gets de-minified error capture + Session Replay on first deploy. The DSN (\`NEXT_PUBLIC_SENTRY_DSN\`) and shared org auth token (\`SENTRY_AUTH_TOKEN\`) are injected into the Coolify app's env automatically by \`apps_create\` — you don't set them. Get the project's Sentry slug from \`projects_get { projectId }\` (field: \`sentry.slug\`); pass it to \`withSentryConfig({ org: "vibnai", project: "<slug>", ... })\`. The reference recipe (instrumentation.ts, instrumentation-client.ts, app/global-error.tsx, next.config.ts wrapper, Dockerfile ARG declarations) is in \`vibn-frontend/lib/scaffold/sentry-snippets.ts\` — read it once via \`fs_*\` if you're unsure, then copy the snippets into the user's project verbatim. Skip Sentry for non-app projects (CLIs, library-only repos).
|
||||
|
||||
**Testing Auth & Protected Routes:** Do NOT attempt to verify signup flows or authenticated routes by making HTTP requests (e.g. \`curl\` or \`http_fetch\`) to the dev server yourself. The app is protected by NextAuth or similar session cookies which you do not have. Just write the code, start the dev server via \`dev_server_start\`, and provide the user the clickable \`previewUrl\` so they can test it themselves in their browser. If you hit a redirect/401, do NOT assume the server is broken and loop on restarting it.
|
||||
|
||||
**New public page → check the auth middleware allowlist (do this in the SAME turn):** If the project has an auth \`middleware.ts\`/\`middleware.js\` (NextAuth or similar) that redirects unknown routes to \`/login\`, then any brand-new **publicly viewable** page you add (e.g. \`/about\`, \`/contact\`, \`/pricing\`) will silently 307-redirect to login until its path is added to that middleware's public-route allowlist. So whenever you create a page that's meant to be public, open the middleware and add the route to the allowlist in the same turn — a page the user can't actually reach is NOT done. This is a single targeted \`fs_edit\`, not a verification loop or a curl/browser audit. (Do NOT do this for pages that are intentionally behind auth, like dashboards or account settings.)
|
||||
|
||||
**Design Critique / Visual QA Tool:**
|
||||
- \`request_visual_qa { targetPath }\` runs a fast background AI agent to critique a UI file (like \`page.tsx\`, \`layout.tsx\`, or \`.css\`) against a strict 5-dimensional design rubric (Layout, Spacing, Contrast, Hierarchy, Responsiveness).
|
||||
- You MUST call this tool whenever your turn involves creating or heavily modifying visual User Interface code before you return the \`previewUrl\` to the user.
|
||||
- If the tool returns a failure with actionable issues (e.g., "missing mobile padding" or "using hardcoded colors instead of CSS variables"), you MUST use \`fs_edit\` to fix those specific issues before ending your turn.
|
||||
- \`request_visual_qa { targetPath }\` runs a fast background AI agent to critique a UI file against a 5-dimensional design rubric (Layout, Spacing, Contrast, Hierarchy, Responsiveness).
|
||||
- Use it ONLY when you are **building a new page/component from scratch, or when the user explicitly asked for design/visual/polish work.** Do NOT use it for small, scoped edits (changing text, a color, a link, a single prop). Removing a word from a logo does not warrant a design audit.
|
||||
- Its critique is **ADVISORY**. If you run it, fix ONLY the issues that are directly caused by the change you just made or that the user asked about. **Do NOT fix pre-existing, unrelated critiques** (mobile menu layout, drop shadows, image optimization, breakpoints, etc.) — those are out of scope. Mention them in your reply instead and let the user decide.
|
||||
- Never let a QA critique turn a small edit into a rewrite. If you find yourself running QA more than once, or editing files the user didn't mention, STOP — you have left the task's scope.
|
||||
- Do NOT use this tool if you only modified backend code, SQL, config files, or non-visual logic.
|
||||
|
||||
**Rules:**
|
||||
@@ -806,10 +818,28 @@ export async function POST(request: Request) {
|
||||
.replace(/<think>[\s\S]*?<\/think>/g, "")
|
||||
// Completely strip any legacy leaked "[tools executed this turn]" strings in case they exist in older messages
|
||||
.replace(/(?:\r?\n)*\[tools executed this turn:[\s\S]*?\]/g, "")
|
||||
// Strip legacy "### Phase Checkpoint" planning walls (Goal / Findings /
|
||||
// Suspected Cause / Verification Plan) from historical assistant
|
||||
// messages. That flow was removed, but old threads still contain it,
|
||||
// and replaying it as context biases the model into re-emitting the
|
||||
// same walls + verify-everything behavior. Drop from the heading to
|
||||
// the end of the message; any plain narration before it is kept.
|
||||
.replace(/(?:^|\n)\s*#{1,6}\s*Phase Checkpoint[\s\S]*$/i, "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
return msg as unknown as ChatMessage;
|
||||
})
|
||||
// Drop assistant messages that became empty after stripping the internal
|
||||
// checkpoint/QA walls so they don't inject blank turns into the context.
|
||||
.filter((msg) => {
|
||||
if (msg.role !== "assistant") return true;
|
||||
const hasText =
|
||||
typeof msg.content === "string" && msg.content.trim().length > 0;
|
||||
const hasTools =
|
||||
Array.isArray((msg as { toolCalls?: unknown[] }).toolCalls) &&
|
||||
((msg as { toolCalls?: unknown[] }).toolCalls?.length ?? 0) > 0;
|
||||
return hasText || hasTools;
|
||||
});
|
||||
|
||||
// Add user message
|
||||
@@ -1031,16 +1061,6 @@ export async function POST(request: Request) {
|
||||
phase: chunk.phase,
|
||||
label: chunk.label,
|
||||
});
|
||||
} else if (
|
||||
chunk.type === "checkpoint" &&
|
||||
"goal" in chunk &&
|
||||
"findings" in chunk
|
||||
) {
|
||||
assistantTimeline.push({
|
||||
kind: "checkpoint",
|
||||
goal: chunk.goal,
|
||||
findings: chunk.findings,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1102,13 +1122,6 @@ export async function POST(request: Request) {
|
||||
const turnIntent = classifyTurnIntent(message);
|
||||
const maxToolRounds = activeMcpToken ? TOOL_BUDGETS[turnIntent] : 0;
|
||||
let phase: AgentPhase = "recon";
|
||||
let checkpointEmitted = false;
|
||||
let verificationPassed = false;
|
||||
// When C-08 forces a "Phase Checkpoint" before a mutation, the model's
|
||||
// next reply is that internal planning block. We route it to the
|
||||
// (hidden) thinking channel instead of showing the user a wall of
|
||||
// Goal/Findings/Suspected-Cause text.
|
||||
let suppressNextTextAsCheckpoint = false;
|
||||
|
||||
// ── Server-side conversational guard (C-03 enforcement) ───────────
|
||||
// If the user's message looks conversational we withhold tools for
|
||||
@@ -1157,6 +1170,7 @@ export async function POST(request: Request) {
|
||||
tools: fixTools,
|
||||
temperature: 0.4,
|
||||
includeThoughts: true,
|
||||
signal: clientSignal,
|
||||
});
|
||||
if (r.text) {
|
||||
assistantText += (assistantText ? "\n\n" : "") + r.text;
|
||||
@@ -1180,6 +1194,7 @@ export async function POST(request: Request) {
|
||||
activeMcpToken,
|
||||
baseUrl,
|
||||
activeProject?.id,
|
||||
clientSignal,
|
||||
)
|
||||
: JSON.stringify({ error: "No MCP token" });
|
||||
emit({
|
||||
@@ -1247,52 +1262,38 @@ export async function POST(request: Request) {
|
||||
tools: toolDefs,
|
||||
temperature: 0.7,
|
||||
includeThoughts: true,
|
||||
signal: clientSignal,
|
||||
});
|
||||
|
||||
// C-08: Force Checkpoint Before Mutation
|
||||
// (Moved safely *after* callVibnChat so 'resp' is defined)
|
||||
// When the model first reaches for a mutation, advance the phase so
|
||||
// the UI reflects "Executing Code Edits". We deliberately do NOT force
|
||||
// a separate planning round or discard the edit (the old "C-08
|
||||
// checkpoint" dance) — that made the model plan, stall on an empty
|
||||
// turn, and never execute, and it seeded scope-creep via the forced
|
||||
// "verification plan". The agent edits directly; the post-loop
|
||||
// verification layer checks the result and drives any fixes.
|
||||
const requestedMutations = resp.toolCalls.filter((tc) =>
|
||||
[
|
||||
"fs_write",
|
||||
"fs_edit",
|
||||
"fs_delete",
|
||||
"dev_server_start",
|
||||
"dev_server_stop",
|
||||
"apps_deploy",
|
||||
"ship",
|
||||
].includes(tc.name),
|
||||
);
|
||||
|
||||
if (
|
||||
requestedMutations.length > 0 &&
|
||||
!checkpointEmitted &&
|
||||
phase === "recon"
|
||||
) {
|
||||
const blockMsg =
|
||||
"[PHASE CHECKPOINT REQUIRED] Before editing files or deploying, you MUST state your goal, current findings, the suspected cause of the issue, the exact file(s) to change, and your verification plan. Do not call any tools in your response.";
|
||||
messages.push({
|
||||
role: "user",
|
||||
content: blockMsg,
|
||||
});
|
||||
emit({
|
||||
type: "checkpoint",
|
||||
goal: "Awaiting checkpoint...",
|
||||
findings: "Evaluating...",
|
||||
});
|
||||
checkpointEmitted = true;
|
||||
suppressNextTextAsCheckpoint = true;
|
||||
if (requestedMutations.length > 0 && phase === "recon") {
|
||||
phase = "execute";
|
||||
emit({ type: "phase", phase, label: "Executing Code Edits" });
|
||||
continue; // Skip tool execution and re-prompt
|
||||
}
|
||||
|
||||
if (requestedMutations.length > 0) {
|
||||
phase = "verify";
|
||||
emit({
|
||||
type: "phase",
|
||||
phase,
|
||||
label: "Verifying Build & Compiling",
|
||||
});
|
||||
// A Stop click aborts the in-flight generation, which surfaces here
|
||||
// as resp.error === "aborted". Treat it as a clean user stop (break to
|
||||
// the post-loop abort handling that persists the partial reply),
|
||||
// NOT as a fatal error shown to the user.
|
||||
if (resp.error === "aborted" || aborted) {
|
||||
aborted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (resp.error) {
|
||||
@@ -1302,13 +1303,7 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
// Stream user-facing text to client.
|
||||
// If this round's text is the forced Phase Checkpoint, route it to
|
||||
// the hidden thinking channel and DON'T add it to the user-facing
|
||||
// message (so it never shows live or in the persisted thread).
|
||||
if (resp.text && suppressNextTextAsCheckpoint) {
|
||||
emit({ type: "thinking", text: resp.text });
|
||||
suppressNextTextAsCheckpoint = false;
|
||||
} else if (resp.text) {
|
||||
if (resp.text) {
|
||||
assistantText += (assistantText ? "\n\n" : "") + resp.text;
|
||||
assistantTextSegments.push(resp.text);
|
||||
emit({ type: "text", text: resp.text });
|
||||
@@ -1371,6 +1366,7 @@ export async function POST(request: Request) {
|
||||
activeMcpToken,
|
||||
baseUrl,
|
||||
activeProject?.id,
|
||||
clientSignal,
|
||||
)
|
||||
: Promise.resolve(
|
||||
JSON.stringify({ error: "No MCP token — read-only mode." }),
|
||||
@@ -1558,6 +1554,7 @@ export async function POST(request: Request) {
|
||||
activeMcpToken,
|
||||
baseUrl,
|
||||
activeProject!.id,
|
||||
clientSignal,
|
||||
);
|
||||
const vTask: VerificationTask = {
|
||||
id: thread_id,
|
||||
@@ -1638,6 +1635,7 @@ export async function POST(request: Request) {
|
||||
messages,
|
||||
tools: [],
|
||||
temperature: 0.3,
|
||||
signal: clientSignal,
|
||||
});
|
||||
if (summary.text && summary.text.trim()) {
|
||||
assistantText += (assistantText ? "\n\n" : "") + summary.text;
|
||||
@@ -1692,6 +1690,7 @@ export async function POST(request: Request) {
|
||||
messages,
|
||||
tools: [],
|
||||
temperature: 0.3,
|
||||
signal: clientSignal,
|
||||
});
|
||||
if (finalSummary.text && finalSummary.text.trim()) {
|
||||
assistantText +=
|
||||
|
||||
Reference in New Issue
Block a user