Enable Gemini thinking stream
This commit is contained in:
@@ -114,6 +114,12 @@ export async function callGeminiChat(opts: {
|
|||||||
maxOutputTokens: 8192,
|
maxOutputTokens: 8192,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (GEMINI_MODEL.includes("thinking") || GEMINI_MODEL.includes("pro")) {
|
||||||
|
config.thinkingConfig = {
|
||||||
|
thinkingBudget: 1024, includeThoughts: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (opts.systemPrompt) {
|
if (opts.systemPrompt) {
|
||||||
config.systemInstruction = opts.systemPrompt;
|
config.systemInstruction = opts.systemPrompt;
|
||||||
}
|
}
|
||||||
@@ -197,6 +203,12 @@ export async function* streamGeminiChat(opts: {
|
|||||||
maxOutputTokens: 8192,
|
maxOutputTokens: 8192,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (GEMINI_MODEL.includes("thinking") || GEMINI_MODEL.includes("pro")) {
|
||||||
|
config.thinkingConfig = {
|
||||||
|
thinkingBudget: 1024, includeThoughts: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (opts.systemPrompt) {
|
if (opts.systemPrompt) {
|
||||||
config.systemInstruction = opts.systemPrompt;
|
config.systemInstruction = opts.systemPrompt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,12 @@ export default function PreviewTab() {
|
|||||||
if (loading || !anatomy) return;
|
if (loading || !anatomy) return;
|
||||||
ensureCalledRef.current = true;
|
ensureCalledRef.current = true;
|
||||||
|
|
||||||
fetch(`/api/projects/${projectId}/dev-server/ensure`, {
|
let url = `/api/projects/${projectId}/dev-server/ensure`;
|
||||||
|
if (selectedPort) {
|
||||||
|
url += `?port=${selectedPort}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
})
|
})
|
||||||
@@ -238,7 +243,9 @@ export default function PreviewTab() {
|
|||||||
onStart={() => {
|
onStart={() => {
|
||||||
setIsForceStarting(true);
|
setIsForceStarting(true);
|
||||||
fetch(
|
fetch(
|
||||||
`/api/projects/${projectId}/dev-server/ensure?forceStart=true`,
|
`/api/projects/${projectId}/dev-server/ensure?forceStart=true${
|
||||||
|
selectedPort ? `&port=${selectedPort}` : ""
|
||||||
|
}`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -56,7 +56,18 @@ export async function POST(
|
|||||||
const projectSlug = (project.data?.slug as string) || project.id;
|
const projectSlug = (project.data?.slug as string) || project.id;
|
||||||
const projectName = (project.data?.name as string) || "Project";
|
const projectName = (project.data?.name as string) || "Project";
|
||||||
|
|
||||||
// 1. Is a dev server already active on the primary port?
|
const url = new URL(request.url);
|
||||||
|
const requestedPortStr = url.searchParams.get("port");
|
||||||
|
const forceStart = url.searchParams.get("forceStart") === "true";
|
||||||
|
|
||||||
|
// 1. Is a dev server already active on the requested port (or most recent port)?
|
||||||
|
let portFilterSql = "";
|
||||||
|
const queryParams: any[] = [projectId];
|
||||||
|
if (requestedPortStr) {
|
||||||
|
portFilterSql = "AND port = $2";
|
||||||
|
queryParams.push(parseInt(requestedPortStr, 10));
|
||||||
|
}
|
||||||
|
|
||||||
const active = await queryOne<{
|
const active = await queryOne<{
|
||||||
id: string;
|
id: string;
|
||||||
state: string;
|
state: string;
|
||||||
@@ -67,13 +78,13 @@ export async function POST(
|
|||||||
`SELECT id, state, preview_url, command, port
|
`SELECT id, state, preview_url, command, port
|
||||||
FROM fs_dev_servers
|
FROM fs_dev_servers
|
||||||
WHERE project_id = $1
|
WHERE project_id = $1
|
||||||
AND port = 3000
|
${portFilterSql}
|
||||||
AND (
|
AND (
|
||||||
state = 'running' OR
|
state = 'running' OR
|
||||||
(state = 'starting' AND started_at > NOW() - INTERVAL '15 minutes')
|
(state = 'starting' AND started_at > NOW() - INTERVAL '15 minutes')
|
||||||
)
|
)
|
||||||
ORDER BY started_at DESC LIMIT 1`,
|
ORDER BY started_at DESC LIMIT 1`,
|
||||||
[projectId],
|
queryParams,
|
||||||
);
|
);
|
||||||
|
|
||||||
// A `starting` row is mid cold-boot; the readiness probe will promote it to
|
// A `starting` row is mid cold-boot; the readiness probe will promote it to
|
||||||
@@ -124,7 +135,17 @@ export async function POST(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Do we have a previous config to restart from?
|
// 2. Do we have a previous config to restart from?
|
||||||
// (Limit to port 3000 since that's what the preview pane embeds)
|
// (Limit to requested port or most recent)
|
||||||
|
let lastPortFilterSql = "";
|
||||||
|
const lastQueryParams: any[] = [projectId];
|
||||||
|
if (requestedPortStr) {
|
||||||
|
lastPortFilterSql = "AND port = $2";
|
||||||
|
lastQueryParams.push(parseInt(requestedPortStr, 10));
|
||||||
|
} else if (active?.port) {
|
||||||
|
lastPortFilterSql = "AND port = $2";
|
||||||
|
lastQueryParams.push(active.port);
|
||||||
|
}
|
||||||
|
|
||||||
const last = await queryOne<{
|
const last = await queryOne<{
|
||||||
command: string;
|
command: string;
|
||||||
port: number;
|
port: number;
|
||||||
@@ -132,13 +153,12 @@ export async function POST(
|
|||||||
}>(
|
}>(
|
||||||
`SELECT command, port, preview_url
|
`SELECT command, port, preview_url
|
||||||
FROM fs_dev_servers
|
FROM fs_dev_servers
|
||||||
WHERE project_id = $1 AND port = 3000
|
WHERE project_id = $1 ${lastPortFilterSql}
|
||||||
ORDER BY started_at DESC LIMIT 1`,
|
ORDER BY started_at DESC LIMIT 1`,
|
||||||
[projectId],
|
lastQueryParams,
|
||||||
);
|
);
|
||||||
|
|
||||||
const forceStart =
|
const forceStartQuery = forceStart; // we already parsed this above
|
||||||
new URL(request.url).searchParams.get("forceStart") === "true";
|
|
||||||
|
|
||||||
// If there's no history, we STILL want to auto-start! We just assume it's a standard
|
// If there's no history, we STILL want to auto-start! We just assume it's a standard
|
||||||
// Next.js app on port 3000. Forcing the user to hit "Start Preview" on a new project
|
// Next.js app on port 3000. Forcing the user to hit "Start Preview" on a new project
|
||||||
|
|||||||
@@ -635,9 +635,23 @@ function Timeline({ entries }: { entries: TimelineEntry[] }) {
|
|||||||
<div style={{ marginBottom: 6 }}>
|
<div style={{ marginBottom: 6 }}>
|
||||||
{items.map((item, i) => {
|
{items.map((item, i) => {
|
||||||
if (item.kind === "thought") {
|
if (item.kind === "thought") {
|
||||||
// Reasoning/thought bubbles are intentionally not rendered — they're
|
return (
|
||||||
// internal and add noise to the chat.
|
<div
|
||||||
return null;
|
key={i}
|
||||||
|
style={{
|
||||||
|
fontSize: "0.85rem",
|
||||||
|
color: "#6b7280",
|
||||||
|
fontStyle: "italic",
|
||||||
|
padding: "8px 12px",
|
||||||
|
background: "#f9fafb",
|
||||||
|
borderLeft: "2px solid #d1d5db",
|
||||||
|
marginBottom: 8,
|
||||||
|
whiteSpace: "pre-wrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Thinking: {item.text}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (item.kind === "text") {
|
if (item.kind === "text") {
|
||||||
return <TimelineText key={i} text={item.text} />;
|
return <TimelineText key={i} text={item.text} />;
|
||||||
|
|||||||
@@ -413,9 +413,9 @@ export async function suspendDevContainer(projectId: string): Promise<void> {
|
|||||||
[projectId],
|
[projectId],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Also mark the fixed port-3000 app as stopped so the UI knows
|
// Also mark ALL preview servers as stopped so the UI knows
|
||||||
await query(
|
await query(
|
||||||
`UPDATE fs_dev_servers SET state = 'stopped' WHERE project_id = $1 AND port = 3000`,
|
`UPDATE fs_dev_servers SET state = 'stopped' WHERE project_id = $1 AND state != 'stopped'`,
|
||||||
[projectId],
|
[projectId],
|
||||||
).catch(() => {});
|
).catch(() => {});
|
||||||
}
|
}
|
||||||
@@ -435,9 +435,9 @@ export async function resumeDevContainer(projectId: string): Promise<void> {
|
|||||||
[projectId],
|
[projectId],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mark the fixed port-3000 app as running again since the container boots it
|
// Mark the last run preview server as starting again since we may need to boot it
|
||||||
await query(
|
await query(
|
||||||
`UPDATE fs_dev_servers SET state = 'running' WHERE project_id = $1 AND port = 3000`,
|
`UPDATE fs_dev_servers SET state = 'starting' WHERE project_id = $1 AND state = 'stopped' AND id = (SELECT id FROM fs_dev_servers WHERE project_id = $1 ORDER BY started_at DESC LIMIT 1)`,
|
||||||
[projectId],
|
[projectId],
|
||||||
).catch(() => {});
|
).catch(() => {});
|
||||||
}
|
}
|
||||||
@@ -1065,10 +1065,12 @@ export async function startDevServer(
|
|||||||
const logFile = `/var/log/vibn-dev/${id}.log`;
|
const logFile = `/var/log/vibn-dev/${id}.log`;
|
||||||
const listenSafeCommand = ensurePreviewListenAllInterfaces(opts.command);
|
const listenSafeCommand = ensurePreviewListenAllInterfaces(opts.command);
|
||||||
|
|
||||||
|
const secret = devAuthSecret(opts.projectId);
|
||||||
const launch =
|
const launch =
|
||||||
`mkdir -p /var/log/vibn-dev && ` +
|
`mkdir -p /var/log/vibn-dev && ` +
|
||||||
`cd /workspace && ` +
|
`cd /workspace && ` +
|
||||||
`nohup env PORT=${opts.port} VIBN_DEV_SERVER_ID=${id} ` +
|
`nohup env PORT=${opts.port} VIBN_DEV_SERVER_ID=${id} ` +
|
||||||
|
`AUTH_SECRET=${secret} NEXTAUTH_SECRET=${secret} AUTH_TRUST_HOST=true ` +
|
||||||
`bash -lc ${shellEscape(listenSafeCommand)} > ${logFile} 2>&1 & ` +
|
`bash -lc ${shellEscape(listenSafeCommand)} > ${logFile} 2>&1 & ` +
|
||||||
`echo $!`;
|
`echo $!`;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user