Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions .forge/executions/18bdd766-de87-4aea-a95e-65b08636d21a.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[2026-04-20T13:45:28.457860900+00:00] Started execution for plan: 2d054b74-476c-4350-9b0d-01fe30d3dea3
[2026-04-20T13:45:28.532783200+00:00] [Provider] Refining step: Analyze workspace context
[2026-04-20T13:45:29.666195600+00:00] Resolved action: InspectFiles against src
4 changes: 4 additions & 0 deletions .forge/executions/1d3f6f74-62a1-4546-9546-440bc9eec176.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[2026-04-20T14:01:25.320370100+00:00] Started execution for plan: d0c3c8e7-00bc-46e9-a4dc-650684f9a2ff
[2026-04-20T14:01:25.392901100+00:00] [Provider] Refining step: Analyze workspace context
[2026-04-20T14:01:51.628467+00:00] [Provider] Refinement failed: Request failed: error sending request for url (https://api.mistral.ai/v1/chat/completions). Using fallback.
[2026-04-20T14:01:51.629282600+00:00] Resolved action: InspectFiles against
3 changes: 3 additions & 0 deletions .forge/executions/23c8bec4-f82e-4857-a6de-67f3b8a60eec.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[2026-04-20T13:44:37.566968200+00:00] Started execution for plan: 2d054b74-476c-4350-9b0d-01fe30d3dea3
[2026-04-20T13:44:37.662824400+00:00] [Provider] Refining step: Analyze workspace context
[2026-04-20T13:44:39.095675800+00:00] Resolved action: InspectFiles against src
3 changes: 3 additions & 0 deletions .forge/executions/c68159c7-9e6e-4271-90b6-73a6414bfba0.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[2026-04-20T14:33:38.557977700+00:00] Started execution for plan: d0c3c8e7-00bc-46e9-a4dc-650684f9a2ff
[2026-04-20T14:33:38.637442100+00:00] [Provider] Refining step: Analyze workspace context
[2026-04-20T14:33:40.691084300+00:00] Resolved action: InspectFiles against src
7 changes: 7 additions & 0 deletions .forge/executions/state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"id": "c68159c7-9e6e-4271-90b6-73a6414bfba0",
"planId": "d0c3c8e7-00bc-46e9-a4dc-650684f9a2ff",
"status": "running",
"mode": "step_by_step",
"currentStepId": "step_1"
}
42 changes: 42 additions & 0 deletions .forge/plans/2d054b74-476c-4350-9b0d-01fe30d3dea3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": "2d054b74-476c-4350-9b0d-01fe30d3dea3",
"taskId": "7fbdc7ca-d44b-47ca-9db1-30ad5c19b87c",
"status": "approved",
"title": "Plan for: what is this project about?",
"objective": "what is this project about?",
"steps": [
{
"id": "step_1",
"kind": "inspect",
"title": "Analyze workspace context",
"objective": "Assess current state of relevant files.",
"status": "pending",
"filesLikelyInvolved": [],
"requiredTools": [
"fs_list"
]
},
{
"id": "step_2",
"kind": "edit",
"title": "Implement changes",
"objective": "```json\n{\n \"plan\": {\n \"id\": \"plan_1\",\n \"taskId\": \"task_1\",\n \"status\": \"draft\",\n \"title\": \"Analyze Tera Project\",\n \"objective\": \"Understand the purpose and structure of the Tera project",
"status": "pending",
"filesLikelyInvolved": [
"src/main.rs"
],
"requiredTools": [
"fs_write"
]
}
],
"dependencies": [
{
"stepId": "step_2",
"dependsOn": "step_1"
}
],
"assumptions": [],
"risks": [],
"architectureProposal": null
}
42 changes: 42 additions & 0 deletions .forge/plans/d0c3c8e7-00bc-46e9-a4dc-650684f9a2ff.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": "d0c3c8e7-00bc-46e9-a4dc-650684f9a2ff",
"taskId": "2c368bff-7a21-47c5-8640-dc0f68bd74b1",
"status": "approved",
"title": "Plan for: tell me what this project is about",
"objective": "tell me what this project is about",
"steps": [
{
"id": "step_1",
"kind": "inspect",
"title": "Analyze workspace context",
"objective": "Assess current state of relevant files.",
"status": "pending",
"filesLikelyInvolved": [],
"requiredTools": [
"fs_list"
]
},
{
"id": "step_2",
"kind": "edit",
"title": "Implement changes",
"objective": "```json\n{\n \"plan\": {\n \"id\": \"3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d\",\n \"taskId\": \"project_analysis\",\n \"status\": \"draft\",\n \"title\": \"Analyze Tera Project\",\n \"objective\": \"Determine what t",
"status": "pending",
"filesLikelyInvolved": [
"src/main.rs"
],
"requiredTools": [
"fs_write"
]
}
],
"dependencies": [
{
"stepId": "step_2",
"dependsOn": "step_1"
}
],
"assumptions": [],
"risks": [],
"architectureProposal": null
}
42 changes: 42 additions & 0 deletions .forge/plans/e44ed371-65d0-4399-97a1-fd2bbf46de00.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": "e44ed371-65d0-4399-97a1-fd2bbf46de00",
"taskId": "5b12269e-62c9-41d1-af4d-a9d06bc811d5",
"status": "ready_for_review",
"title": "Plan for: what is Tera about",
"objective": "what is Tera about",
"steps": [
{
"id": "step_1",
"kind": "inspect",
"title": "Analyze workspace context",
"objective": "Assess current state of relevant files.",
"status": "pending",
"filesLikelyInvolved": [],
"requiredTools": [
"fs_list"
]
},
{
"id": "step_2",
"kind": "edit",
"title": "Implement changes",
"objective": "```json\n{\n \"plan\": {\n \"id\": \"c0f7b5e8-1234-5678-9abc-def123456789\",\n \"taskId\": \"what_is_tera_about\",\n \"status\": \"draft\",\n \"title\": \"Investigate Tera project to understand its purpose\",\n ",
"status": "pending",
"filesLikelyInvolved": [
"src/main.rs"
],
"requiredTools": [
"fs_write"
]
}
],
"dependencies": [
{
"stepId": "step_2",
"dependsOn": "step_1"
}
],
"assumptions": [],
"risks": [],
"architectureProposal": null
}
6 changes: 6 additions & 0 deletions .forge/provider_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"kind": "openai_compatible",
"baseUrl": "https://api.mistral.ai",
"modelId": "mistral-small-latest",
"apiKeySet": true
}
1 change: 1 addition & 0 deletions .forge/provider_secret.key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v1Vphvx1drTK9OdsQBv1lsTVr4bsaBrv
55 changes: 44 additions & 11 deletions app/actions/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ function isMissingColumnError(error: unknown, columnName: string) {
return details.includes(columnName.toLowerCase()) && details.includes('column')
}

function omitField<T extends Record<string, any>, K extends keyof T>(payload: T, key: K): Omit<T, K> {
const { [key]: _removed, ...rest } = payload
return rest
}

export async function generateAnswer({ prompt, tool, authorId, authorEmail, attachments = [], sessionId, chatId, enableWebSearch = false, researchMode = false }: GenerateProps) {
// Get user profile and check limits
let userProfile = await getUserProfileServer(authorId)
Expand Down Expand Up @@ -234,33 +239,61 @@ export async function generateAnswer({ prompt, tool, authorId, authorEmail, atta
title: title
}

let { data, error } = await supabaseServer.from('chat_sessions').insert({
let insertPayload: Record<string, any> = {
...baseInsertPayload,
token_usage: tokenCost,
})
.select('id')
.single()
}
let data: { id: string } | null = null
let error: any = null

if (error && isMissingColumnError(error, 'token_usage')) {
const retryResult = await supabaseServer.from('chat_sessions').insert(baseInsertPayload)
for (let attempt = 0; attempt < 4; attempt += 1) {
const result = await supabaseServer
.from('chat_sessions')
.insert(insertPayload)
.select('id')
.single()

data = retryResult.data
error = retryResult.error
data = result.data
error = result.error

if (!error) break

if (isMissingColumnError(error, 'token_usage') && 'token_usage' in insertPayload) {
insertPayload = omitField(insertPayload, 'token_usage')
continue
}

if (isMissingColumnError(error, 'session_id') && 'session_id' in insertPayload) {
insertPayload = omitField(insertPayload, 'session_id')
continue
}

if (isMissingColumnError(error, 'title') && 'title' in insertPayload) {
insertPayload = omitField(insertPayload, 'title')
continue
}

break
}

if (error) {
console.error('[chat_insert_failed]', { userId: authorId, sessionId: currentSessionId, error })
console.error('[chat_insert_failed]', {
userId: authorId,
sessionId: currentSessionId,
error,
attemptedPayloadKeys: Object.keys(insertPayload)
})
persistenceWarning = 'We generated your response, but could not save this chat message.'
} else if (data?.id) {
savedChatId = data.id
chatPersisted = true
}
}

// Increment chat counter after successful generation
await incrementChatsServer(authorId)
// Increment chat counter only after successful persistence to avoid analytics drift.
if (chatPersisted) {
await incrementChatsServer(authorId)
}

// Increment web search counter if enabled
if (enableWebSearch) {
Expand Down
Loading