mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
fixes
This commit is contained in:
@@ -10,6 +10,4 @@ services:
|
||||
required: true
|
||||
environment:
|
||||
SYNAPSE_ENDPOINT: http://host.docker.internal:3001
|
||||
APPWRITE_ENDPOINT: http://host.docker.internal:80/v1
|
||||
volumes:
|
||||
- ./tmp:/app/tmp
|
||||
APPWRITE_ENDPOINT: http://host.docker.internal:80/v1
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
generateId,
|
||||
hasToolCall,
|
||||
smoothStream,
|
||||
streamObject,
|
||||
streamText,
|
||||
TextPart,
|
||||
tool
|
||||
@@ -20,9 +19,7 @@ import { anthropic } from '@ai-sdk/anthropic';
|
||||
import { getOrCreateArtifactSandbox, startDevServer } from '@/lib/daytona/daytona-sandbox';
|
||||
import { OnStepUpdateFn, workspaceStepSchema } from '@/lib/ai/custom-parts/workspace-state';
|
||||
import { getOrCreateConversation, updateConversationHistory } from './message-history';
|
||||
import { imagineToMastraToolset } from '@/lib/ai/mastra/tools/imagine-tool';
|
||||
import { fileTools } from '@/lib/ai/mastra/tools/file-tools';
|
||||
import { createSystemPrompt } from '@/lib/ai/system-prompt/create-system-prompt';
|
||||
import { GitRepositoryUtils } from '@/lib/git-utils';
|
||||
import {
|
||||
getPagesAndComponents,
|
||||
@@ -73,10 +70,14 @@ export const handleChatRequest = async (c: Context) => {
|
||||
if (trigger === 'submit-tool-result') {
|
||||
// save to file
|
||||
// return c.body(null, 200);
|
||||
return streamText({
|
||||
model: anthropic('claude-3-7-sonnet-20250219'),
|
||||
messages: convertToModelMessages(messages)
|
||||
}).toUIMessageStreamResponse();
|
||||
// return streamText({
|
||||
// model: anthropic('claude-3-7-sonnet-20250219'),
|
||||
// messages: convertToModelMessages(messages)
|
||||
// }).toUIMessageStreamResponse();
|
||||
// return c.json({
|
||||
// error: 'Not implemented'
|
||||
// }, 500);
|
||||
console.log('submit-tool-result');
|
||||
}
|
||||
|
||||
const { imagineClient, workspacesClient } = await createImagineClient({
|
||||
@@ -110,8 +111,8 @@ export const handleChatRequest = async (c: Context) => {
|
||||
|
||||
writer.write({
|
||||
type: 'start',
|
||||
messageId,
|
||||
})
|
||||
messageId
|
||||
});
|
||||
|
||||
const updateStep: OnStepUpdateFn = ({
|
||||
id,
|
||||
@@ -130,6 +131,7 @@ export const handleChatRequest = async (c: Context) => {
|
||||
if (steps.length > 0) {
|
||||
writer.write({
|
||||
type: 'data-workspace-state',
|
||||
transient: true,
|
||||
data: {
|
||||
state: 'in-progress',
|
||||
steps,
|
||||
@@ -172,7 +174,6 @@ export const handleChatRequest = async (c: Context) => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/** SYSTEM PROMPT */
|
||||
|
||||
const gitRepositoryUtils = new GitRepositoryUtils(
|
||||
@@ -201,147 +202,178 @@ export const handleChatRequest = async (c: Context) => {
|
||||
|
||||
/** */
|
||||
|
||||
const thinkingStartTime = Date.now();
|
||||
const thinkingId = createIdGenerator({ size: 10 })();
|
||||
let thoughts = '';
|
||||
// const thinkingStartTime = Date.now();
|
||||
// const thinkingId = createIdGenerator({ size: 10 })();
|
||||
// let thoughts = '';
|
||||
|
||||
const planResult = streamText({
|
||||
maxRetries: 3,
|
||||
model: anthropic('claude-sonnet-4-20250514'),
|
||||
abortSignal: signal,
|
||||
tools: {
|
||||
readFile: fileTools.readFileTool,
|
||||
listFilesInDirectory: fileTools.listFilesInDirectoryTool,
|
||||
readMultipleFilesInParallel: fileTools.readMultipleFilesInParallelTool,
|
||||
reportPlan: tool({
|
||||
name: 'reportPlan',
|
||||
description: 'You use this tool to report your final plan for implementation.',
|
||||
inputSchema: z.object({
|
||||
plan: z.string().describe('A detailed plan for implementation. Must be a few paragraphs long.'),
|
||||
}),
|
||||
execute: async ({ plan }) => {
|
||||
console.log('reportPlan', plan);
|
||||
return 'Your plan has been reported.';
|
||||
}
|
||||
})
|
||||
},
|
||||
stopWhen: hasToolCall('reportPlan'),
|
||||
activeTools: ["readFile", "listFilesInDirectory", "readMultipleFilesInParallel", "reportPlan"],
|
||||
messages: [
|
||||
{
|
||||
role: 'system',
|
||||
content: dedent(`
|
||||
You are an elite software architect.
|
||||
// console.log('[planResult] start');
|
||||
|
||||
Here is the current file layout and dependencies in the project:
|
||||
${currentCodeContext.content}
|
||||
// const planResult = streamText({
|
||||
// maxRetries: 3,
|
||||
// model: anthropic('claude-sonnet-4-20250514'),
|
||||
// abortSignal: signal,
|
||||
// tools: {
|
||||
// readFile: fileTools.readFileTool,
|
||||
// listFilesInDirectory: fileTools.listFilesInDirectoryTool,
|
||||
// readMultipleFilesInParallel: fileTools.readMultipleFilesInParallelTool,
|
||||
// reportPlan: tool({
|
||||
// name: 'reportPlan',
|
||||
// description:
|
||||
// 'You use this tool to report your final plan for implementation.',
|
||||
// inputSchema: z.object({
|
||||
// plan: z
|
||||
// .string()
|
||||
// .describe(
|
||||
// 'A detailed plan for implementation. Must be a few paragraphs long.'
|
||||
// )
|
||||
// }),
|
||||
// execute: async ({ plan }) => {
|
||||
// console.log('reportPlan', plan);
|
||||
// return 'Your plan has been reported.';
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
// stopWhen: hasToolCall('reportPlan'),
|
||||
// activeTools: [
|
||||
// 'readFile',
|
||||
// 'listFilesInDirectory',
|
||||
// 'readMultipleFilesInParallel',
|
||||
// 'reportPlan'
|
||||
// ],
|
||||
// messages: [
|
||||
// {
|
||||
// role: 'system',
|
||||
// content: dedent(`
|
||||
// You are an elite software architect.
|
||||
|
||||
// Here is the current file layout and dependencies in the project:
|
||||
// ${currentCodeContext.content}
|
||||
|
||||
|
||||
Please plan the steps to implement the user's request. You do not write any code.
|
||||
You may read files to understand the contents of files, which will help you make a better plan.
|
||||
Your plans should be concise and to the point.
|
||||
// Please plan the steps to implement the user's request. You do not write any code.
|
||||
// You may read files to understand the contents of files, which will help you make a better plan.
|
||||
// Your plans should be concise and to the point.
|
||||
|
||||
You will produce the following outputs:
|
||||
- A short and concise plan
|
||||
- Whether a UI developer is needed
|
||||
// You will produce the following outputs:
|
||||
// - A short and concise plan
|
||||
// - Whether a UI developer is needed
|
||||
|
||||
# Outputs
|
||||
// # Outputs
|
||||
|
||||
## Plan
|
||||
A short and concise plan of what exactly needs to be done to achieve the product manager's request. This should be 3-4 sentences maximum and in first person. E.g. 'I will ... and then ... '
|
||||
// ## Plan
|
||||
// A short and concise plan of what exactly needs to be done to achieve the product manager's request. This should be 3-4 sentences maximum and in first person. E.g. 'I will ... and then ... '
|
||||
|
||||
## When is a UI developer needed?
|
||||
This is important because the UI developer will be the one to implement the design.
|
||||
// ## When is a UI developer needed?
|
||||
// This is important because the UI developer will be the one to implement the design.
|
||||
|
||||
Examples of when a UI developer IS needed:
|
||||
- Create new screens
|
||||
- Modify existing screens with explicit design requests (e.g. adding elements or restructuring the layout)
|
||||
// Examples of when a UI developer IS needed:
|
||||
// - Create new screens
|
||||
// - Modify existing screens with explicit design requests (e.g. adding elements or restructuring the layout)
|
||||
|
||||
Examples of when a UI developer IS NOT needed:
|
||||
- Adding a React hook
|
||||
- Adding an endpoint
|
||||
- Pure logic changes
|
||||
- Moving files around, renaming files, etc.
|
||||
// Examples of when a UI developer IS NOT needed:
|
||||
// - Adding a React hook
|
||||
// - Adding an endpoint
|
||||
// - Pure logic changes
|
||||
// - Moving files around, renaming files, etc.
|
||||
|
||||
In termso f filesystem tool usage:
|
||||
- You ONLY have access to read-only filesystem tools
|
||||
`)
|
||||
},
|
||||
...restMessages.map((m: any) => ({
|
||||
role: m.role,
|
||||
content: m.content
|
||||
})),
|
||||
{
|
||||
role: 'user',
|
||||
content: `
|
||||
// In termso f filesystem tool usage:
|
||||
// - You ONLY have access to read-only filesystem tools
|
||||
// `)
|
||||
// },
|
||||
// ...restMessages.map((m: any) => ({
|
||||
// role: m.role,
|
||||
// content: m.content
|
||||
// })),
|
||||
// {
|
||||
// role: 'user',
|
||||
// content: `
|
||||
|
||||
Here is the product manager's request:
|
||||
<request>
|
||||
${latestMessageTextPart.text}
|
||||
</request>
|
||||
`
|
||||
}
|
||||
],
|
||||
headers: {
|
||||
'anthropic-beta': [
|
||||
'token-efficient-tools-2025-02-19',
|
||||
'fine-grained-tool-streaming-2025-05-14',
|
||||
'extended-cache-ttl-2025-04-11'
|
||||
].join(',')
|
||||
},
|
||||
experimental_transform: smoothStream({
|
||||
delayInMs: 30,
|
||||
chunking: 'word'
|
||||
}),
|
||||
onChunk: (event) => {
|
||||
if (event.chunk.type === 'text') {
|
||||
thoughts += event.chunk.text;
|
||||
// Here is the product manager's request:
|
||||
// <request>
|
||||
// ${latestMessageTextPart.text}
|
||||
// </request>
|
||||
// `
|
||||
// }
|
||||
// ],
|
||||
// headers: {
|
||||
// 'anthropic-beta': [
|
||||
// 'token-efficient-tools-2025-02-19',
|
||||
// 'fine-grained-tool-streaming-2025-05-14',
|
||||
// 'extended-cache-ttl-2025-04-11'
|
||||
// ].join(',')
|
||||
// },
|
||||
// experimental_transform: smoothStream({
|
||||
// delayInMs: 30,
|
||||
// chunking: 'word'
|
||||
// }),
|
||||
// onChunk: (event) => {
|
||||
// if (event.chunk.type === 'text') {
|
||||
// thoughts += event.chunk.text;
|
||||
|
||||
writer.write({
|
||||
type: 'data-thinking',
|
||||
id: thinkingId,
|
||||
data: {
|
||||
text: thoughts,
|
||||
durationMs: null,
|
||||
state: 'streaming'
|
||||
// writer.write({
|
||||
// type: 'data-thinking',
|
||||
// id: thinkingId,
|
||||
// data: {
|
||||
// text: thoughts,
|
||||
// durationMs: null,
|
||||
// state: 'streaming'
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// onFinish: () => {
|
||||
// console.log('[planResult] onFinish', { thoughts });
|
||||
// const thinkingEndTime = Date.now();
|
||||
// const thinkingDuration = thinkingEndTime - thinkingStartTime;
|
||||
// writer.write({
|
||||
// type: 'data-thinking',
|
||||
// id: thinkingId,
|
||||
// data: {
|
||||
// text: thoughts,
|
||||
// durationMs: thinkingDuration,
|
||||
// state: 'done'
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
// for await (const chunk of planResult.textStream) {
|
||||
// }
|
||||
|
||||
// const planToolCall = (await planResult.toolCalls).find(
|
||||
// (call) => call.toolName === 'reportPlan'
|
||||
// );
|
||||
|
||||
// // if (!planToolCall) {
|
||||
// // writer.write({
|
||||
// // type: "finish",
|
||||
// // })
|
||||
// // return;
|
||||
// // }
|
||||
|
||||
// const plan = planToolCall?.input?.plan ?? '';
|
||||
|
||||
// console.log('[plan]', plan);
|
||||
|
||||
console.log('[implementResult] start');
|
||||
|
||||
/*
|
||||
|
||||
${
|
||||
plan
|
||||
? dedent(`
|
||||
Here is the plan from the architect on how to implement it:
|
||||
<architect-plan>
|
||||
${plan}
|
||||
</architect-plan>`)
|
||||
: ''
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
onFinish: () => {
|
||||
const thinkingEndTime = Date.now();
|
||||
const thinkingDuration = thinkingEndTime - thinkingStartTime;
|
||||
writer.write({
|
||||
type: 'data-thinking',
|
||||
id: thinkingId,
|
||||
data: {
|
||||
text: thoughts,
|
||||
durationMs: thinkingDuration,
|
||||
state: 'done'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
for await (const chunk of planResult.textStream) { }
|
||||
|
||||
const planToolCall = (await planResult.toolCalls).find((call) => call.toolName === "reportPlan");
|
||||
|
||||
if (!planToolCall) {
|
||||
writer.write({
|
||||
type: "finish",
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
const plan = planToolCall.input.plan;
|
||||
|
||||
console.log('plan', plan);
|
||||
*/
|
||||
|
||||
const implementResult = streamText({
|
||||
maxOutputTokens: 52000,
|
||||
maxRetries: 5,
|
||||
model: anthropic('claude-sonnet-4-20250514'),
|
||||
model: anthropic('claude-3-7-sonnet-20250219'),
|
||||
stopWhen: hasToolCall('reportDone'),
|
||||
tools: {
|
||||
readFile: fileTools.readFileTool,
|
||||
@@ -385,11 +417,6 @@ export const handleChatRequest = async (c: Context) => {
|
||||
<product-manager-request>
|
||||
${latestMessageTextPart.text}
|
||||
</product-manager-request>
|
||||
|
||||
Here is the plan from the architect on how to implement it:
|
||||
<architect-plan>
|
||||
${plan}
|
||||
</architect-plan>
|
||||
`
|
||||
}
|
||||
],
|
||||
@@ -406,7 +433,7 @@ export const handleChatRequest = async (c: Context) => {
|
||||
}),
|
||||
onStepFinish: async (event) => {
|
||||
console.log('[implementResult onStepFinish] onStepFinish');
|
||||
|
||||
|
||||
const changedFiles = runtimeContext.get('changedFiles');
|
||||
console.log('[implementResult onStepFinish] changedFiles', changedFiles);
|
||||
|
||||
@@ -419,20 +446,23 @@ export const handleChatRequest = async (c: Context) => {
|
||||
return {
|
||||
path: f.path,
|
||||
content: content.content
|
||||
}
|
||||
};
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
await updateDependencies(
|
||||
filesWithContents
|
||||
)
|
||||
await updateDependencies(filesWithContents);
|
||||
},
|
||||
onFinish: () => {
|
||||
console.log('[implementResult] onFinish');
|
||||
}
|
||||
});
|
||||
|
||||
writer.merge(implementResult.toUIMessageStream({
|
||||
originalMessages: messages,
|
||||
sendStart: false,
|
||||
}));
|
||||
writer.merge(
|
||||
implementResult.toUIMessageStream({
|
||||
originalMessages: messages,
|
||||
sendStart: false
|
||||
})
|
||||
);
|
||||
},
|
||||
onFinish: async (event) => {
|
||||
console.log('onFinish', { didError });
|
||||
@@ -466,6 +496,6 @@ export const handleChatRequest = async (c: Context) => {
|
||||
});
|
||||
|
||||
return createUIMessageStreamResponse({
|
||||
stream,
|
||||
stream
|
||||
});
|
||||
};
|
||||
|
||||
@@ -25,9 +25,9 @@ const readMultipleFilesInParallelTool = tool({
|
||||
const runtimeContext = getContext<HonoEnv>().var.runtimeContext;
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
|
||||
writer.write({
|
||||
type: 'start-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'start-step'
|
||||
// });
|
||||
|
||||
console.log(`[TOOL - readMultipleFilesInParallel]`, { paths });
|
||||
|
||||
@@ -42,9 +42,9 @@ const readMultipleFilesInParallelTool = tool({
|
||||
})
|
||||
);
|
||||
|
||||
writer.write({
|
||||
type: 'finish-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'finish-step'
|
||||
// });
|
||||
|
||||
return { files };
|
||||
}
|
||||
@@ -74,9 +74,9 @@ const readFileTool = tool({
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const toolCallId = createIdGenerator({ size: 10 })();
|
||||
|
||||
writer.write({
|
||||
type: 'start-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'start-step'
|
||||
// });
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
@@ -92,20 +92,20 @@ const readFileTool = tool({
|
||||
const result = await readFileFn(`./${path}`);
|
||||
console.log(`[TOOL - readFile] Reading file at path: ${path}`);
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: 'tool-output-available',
|
||||
toolCallId,
|
||||
output: {
|
||||
path: result.path,
|
||||
content: result.content
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (!skipWritingToolCalls) {
|
||||
// writer.write({
|
||||
// type: 'tool-output-available',
|
||||
// toolCallId,
|
||||
// output: {
|
||||
// path: result.path,
|
||||
// content: result.content
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
writer.write({
|
||||
type: 'finish-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'finish-step'
|
||||
// });
|
||||
|
||||
return {
|
||||
path: result.path,
|
||||
@@ -140,15 +140,15 @@ const writeFilesTool = tool({
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
|
||||
writer.write({
|
||||
type: 'start-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'start-step'
|
||||
// });
|
||||
|
||||
const { successFiles, errorFiles } = await writeFiles(files, synapse);
|
||||
|
||||
writer.write({
|
||||
type: 'finish-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'finish-step'
|
||||
// });
|
||||
|
||||
return {
|
||||
successFiles,
|
||||
@@ -169,7 +169,7 @@ const writeFileTool = tool({
|
||||
success: z.boolean().describe('Whether the file was written successfully'),
|
||||
error: z
|
||||
.string()
|
||||
.optional()
|
||||
.nullable()
|
||||
.describe('The error message if the file was not written successfully')
|
||||
}),
|
||||
execute: async ({ path, content }) => {
|
||||
@@ -178,23 +178,23 @@ const writeFileTool = tool({
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
|
||||
writer.write({
|
||||
type: 'start-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'start-step'
|
||||
// });
|
||||
|
||||
const toolCallId = createIdGenerator({ size: 10 })();
|
||||
// const toolCallId = createIdGenerator({ size: 10 })();
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: 'tool-input-available',
|
||||
toolCallId,
|
||||
toolName: 'writeFile',
|
||||
input: {
|
||||
path,
|
||||
content
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (!skipWritingToolCalls) {
|
||||
// writer.write({
|
||||
// type: 'tool-input-available',
|
||||
// toolCallId,
|
||||
// toolName: 'writeFile',
|
||||
// input: {
|
||||
// path,
|
||||
// content
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
const { errorFiles, successFiles } = await writeFiles([{ path, content }], synapse);
|
||||
|
||||
@@ -204,20 +204,21 @@ const writeFileTool = tool({
|
||||
|
||||
console.log('changedFiles', newChangedFiles);
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: 'tool-output-available',
|
||||
toolCallId,
|
||||
output: {
|
||||
success: true
|
||||
}
|
||||
});
|
||||
}
|
||||
writer.write({
|
||||
type: 'finish-step'
|
||||
});
|
||||
// if (!skipWritingToolCalls) {
|
||||
// writer.write({
|
||||
// type: 'tool-output-available',
|
||||
// toolCallId,
|
||||
// output: {
|
||||
// success: true
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// writer.write({
|
||||
// type: 'finish-step'
|
||||
// });
|
||||
return {
|
||||
success: true
|
||||
success: true,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -270,9 +271,9 @@ const listFilesInDirectoryTool = tool({
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
|
||||
writer.write({
|
||||
type: 'start-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'start-step'
|
||||
// });
|
||||
|
||||
console.log(
|
||||
`[TOOL - listFilesInDirectory] Listing files in directory at path: ${path}, recursive: ${recursive}`
|
||||
@@ -288,9 +289,9 @@ const listFilesInDirectoryTool = tool({
|
||||
`[TOOL - listFilesInDirectory] Found ${files.length} files in directory at path: ${path}`
|
||||
);
|
||||
|
||||
writer.write({
|
||||
type: 'finish-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'finish-step'
|
||||
// });
|
||||
|
||||
return {
|
||||
files
|
||||
@@ -313,15 +314,15 @@ const deleteFileTool = tool({
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
|
||||
writer.write({
|
||||
type: 'start-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'start-step'
|
||||
// });
|
||||
|
||||
await synapse.deleteFile({ filepath: `./${path}` });
|
||||
|
||||
writer.write({
|
||||
type: 'finish-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'finish-step'
|
||||
// });
|
||||
|
||||
return {
|
||||
success: true
|
||||
@@ -351,15 +352,15 @@ const moveFileTool = tool({
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
|
||||
writer.write({
|
||||
type: 'start-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'start-step'
|
||||
// });
|
||||
|
||||
await synapse.updateFilePath({ filepath: `./${path}`, newPath: `./${newPath}` });
|
||||
|
||||
writer.write({
|
||||
type: 'finish-step'
|
||||
});
|
||||
// writer.write({
|
||||
// type: 'finish-step'
|
||||
// });
|
||||
|
||||
return {
|
||||
success: true
|
||||
|
||||
@@ -8,10 +8,6 @@ RUN npm -v
|
||||
RUN npm install -g bun
|
||||
RUN bunx giget --version
|
||||
|
||||
RUN ls -la
|
||||
RUN bunx giget@latest gh:appwrite/templates-for-frameworks/base-vite-template .
|
||||
RUN bun install
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
@@ -3,6 +3,6 @@ import { Daytona } from "@daytonaio/sdk";
|
||||
|
||||
export const daytona = new Daytona({
|
||||
target: "us",
|
||||
apiKey: "dtn_4ceb903baf0ef4264e457d2401d904b01c63e11a487d737be0a6113ebeb62ff0",
|
||||
apiKey: process.env.DAYTONA_API_KEY!,
|
||||
apiUrl: "https://app.daytona.io/api"
|
||||
});
|
||||
|
||||
@@ -25,10 +25,10 @@ const createSandbox = async ({ artifactId }: { artifactId: string }) => {
|
||||
let sandbox: Sandbox;
|
||||
try {
|
||||
sandbox = await daytona.create({
|
||||
snapshot: 'imgn-base-vite:v2',
|
||||
snapshot: 'imgn-base-vite:v4',
|
||||
labels: { artifactId },
|
||||
autoStopInterval: 10, // 10 minutes
|
||||
autoDeleteInterval: 60, // 20 minutes
|
||||
autoDeleteInterval: 60, // 60 minutes
|
||||
// language: 'typescript',
|
||||
public: true
|
||||
});
|
||||
@@ -109,6 +109,13 @@ export const getOrCreateArtifactSandbox = async ({
|
||||
console.log('Sandbox started');
|
||||
}
|
||||
|
||||
onStepUpdate({
|
||||
id: WorkspaceStepId.CREATE_SANDBOX,
|
||||
status: 'completed',
|
||||
text: 'Workspace set up'
|
||||
});
|
||||
|
||||
|
||||
sandbox = foundSandbox;
|
||||
} else {
|
||||
console.log('Workspace not found, creating...');
|
||||
@@ -123,6 +130,52 @@ export const getOrCreateArtifactSandbox = async ({
|
||||
artifactId
|
||||
});
|
||||
|
||||
onStepUpdate({
|
||||
id: WorkspaceStepId.CREATE_SANDBOX,
|
||||
status: 'completed',
|
||||
text: 'Workspace created'
|
||||
});
|
||||
|
||||
|
||||
onStepUpdate({
|
||||
id: WorkspaceStepId.REPOSITORY_SETUP,
|
||||
status: 'in-progress',
|
||||
text: 'Setting up repo...'
|
||||
});
|
||||
|
||||
await sandbox.process.executeCommand(
|
||||
'bunx giget@latest gh:appwrite/templates-for-frameworks/base-vite-template .',
|
||||
'/home/daytona/workspace',
|
||||
{},
|
||||
30
|
||||
);
|
||||
|
||||
onStepUpdate({
|
||||
id: WorkspaceStepId.REPOSITORY_SETUP,
|
||||
status: 'completed',
|
||||
text: 'Repository set up'
|
||||
});
|
||||
|
||||
onStepUpdate({
|
||||
id: WorkspaceStepId.INSTALL_DEPENDENCIES,
|
||||
status: 'in-progress',
|
||||
text: 'Installing dependencies...'
|
||||
});
|
||||
|
||||
await sandbox.process.executeCommand(
|
||||
'bun install',
|
||||
'/home/daytona/workspace',
|
||||
{},
|
||||
30
|
||||
);
|
||||
|
||||
onStepUpdate({
|
||||
id: WorkspaceStepId.INSTALL_DEPENDENCIES,
|
||||
status: 'completed',
|
||||
text: 'Dependencies installed'
|
||||
});
|
||||
|
||||
|
||||
// Save sandbox id to db
|
||||
await prisma.conversation.update({
|
||||
where: {
|
||||
@@ -137,12 +190,6 @@ export const getOrCreateArtifactSandbox = async ({
|
||||
console.log('Created sandbox', sandbox);
|
||||
}
|
||||
|
||||
onStepUpdate({
|
||||
id: WorkspaceStepId.CREATE_SANDBOX,
|
||||
status: 'completed',
|
||||
text: 'Workspace found'
|
||||
});
|
||||
|
||||
return { sandbox };
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ export type ListFilesInDirParams = {
|
||||
export class SynapseHTTPClient {
|
||||
private sandbox: Sandbox;
|
||||
private endpoint: string;
|
||||
private artifactBasePath: string;
|
||||
private artifactId: string;
|
||||
|
||||
constructor({
|
||||
@@ -30,7 +29,6 @@ export class SynapseHTTPClient {
|
||||
sandbox: Sandbox;
|
||||
}) {
|
||||
this.endpoint = endpoint;
|
||||
this.artifactBasePath = `/usr/local/artifact`;
|
||||
this.artifactId = artifactId;
|
||||
this.sandbox = sandbox;
|
||||
}
|
||||
@@ -48,28 +46,6 @@ export class SynapseHTTPClient {
|
||||
};
|
||||
}
|
||||
|
||||
async createFile({
|
||||
path,
|
||||
content,
|
||||
ignoreBasePath = false
|
||||
}: {
|
||||
path: string;
|
||||
content: string;
|
||||
ignoreBasePath?: boolean;
|
||||
}) {
|
||||
console.log('createFile', { path, content });
|
||||
const response = await this.request({
|
||||
type: 'fs',
|
||||
operation: 'createFile',
|
||||
params: {
|
||||
filepath: ignoreBasePath ? path : _path.resolve(this.artifactBasePath, path),
|
||||
content
|
||||
}
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async createOrUpdateFile({ filepath, content }: { filepath: string; content: string }) {
|
||||
return daytonaFs.createOrUpdateFile({
|
||||
sandbox: this.sandbox,
|
||||
|
||||
@@ -34,15 +34,13 @@
|
||||
|
||||
|
||||
const chat = new Chat<ImagineUIMessage>({
|
||||
maxSteps: 20,
|
||||
maxSteps: 50,
|
||||
id: $conversation.data.id,
|
||||
transport: new DefaultChatTransport({
|
||||
api: `${VARS.AI_SERVICE_BASE_URL}/api/chat`,
|
||||
}),
|
||||
messages: $conversation.data.messages ?? [],
|
||||
onData: (dataPart) => {
|
||||
console.log("data", dataPart);
|
||||
|
||||
if (dataPart.type === "data-workspace-state") {
|
||||
const data = dataPart.data as ImagineUIDataParts["workspace-state"];
|
||||
const { state, workspaceUrl, steps } = data;
|
||||
|
||||
Reference in New Issue
Block a user