mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
fixes
This commit is contained in:
@@ -7,18 +7,18 @@ import {
|
||||
createUIMessageStreamResponse,
|
||||
TextPart
|
||||
} from 'ai';
|
||||
import { createRuntimeContext, WriterType } from '@/lib/ai/mastra/utils/runtime-context';
|
||||
import { mastra } from '@/lib/ai/mastra';
|
||||
import { createRuntimeContext, WriterType } from '../../lib/ai/mastra/utils/runtime-context';
|
||||
import { mastra } from '../../lib/ai/mastra';
|
||||
import { exec as _exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
const exec = promisify(_exec);
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { createImagineClient } from '@/lib/imagine/create-artifact-client';
|
||||
import { createImagineClient } from '../../lib/imagine/create-artifact-client';
|
||||
|
||||
export const handleChatRequest = async (c: Context) => {
|
||||
const signal = c.req.raw.signal;
|
||||
|
||||
|
||||
const token = c.req.header('X-Imagine-Token');
|
||||
if (!token) {
|
||||
return c.json({ error: 'Unauthorized' }, 401);
|
||||
@@ -95,6 +95,7 @@ export const handleChatRequest = async (c: Context) => {
|
||||
isFirstMessage: isNewConversation,
|
||||
signal
|
||||
});
|
||||
c.set('runtimeContext', runtimeContext);
|
||||
const run = await mastra.getWorkflow('codeWorkflow').createRunAsync();
|
||||
|
||||
const result = run.stream({
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { anthropic, AnthropicProviderOptions } from "@ai-sdk/anthropic";
|
||||
import { anthropic } from "@ai-sdk/anthropic";
|
||||
import { Agent } from "@mastra/core";
|
||||
import { fileTools } from "../tools/file-tools";
|
||||
import { smoothStream } from "ai";
|
||||
import { RuntimeContextType } from "../utils/runtime-context";
|
||||
import { AnthropicExtendedProviderOptions } from "@/lib/types";
|
||||
import { imagineToMastraToolset } from "../tools/imagine-tool";
|
||||
|
||||
export const architectAgent = new Agent({
|
||||
name: "Software Architect Agent",
|
||||
@@ -16,10 +16,11 @@ NOTE: It is ALWAYS better to use the readMultipleFilesInParallel tool to read mu
|
||||
// model: anthropic("claude-3-7-sonnet-20250219"),
|
||||
// model: google("gemini-2.5-pro"),
|
||||
// model: openai("gpt-4.1-nano"),
|
||||
tools: {
|
||||
tools: imagineToMastraToolset({
|
||||
readFile: fileTools.readFileTool,
|
||||
readMultipleFilesInParallel: fileTools.readMultipleFilesInParallelTool,
|
||||
},
|
||||
listFilesInDirectory: fileTools.listFilesInDirectoryTool,
|
||||
}),
|
||||
defaultStreamOptions: ({ runtimeContext }: { runtimeContext: RuntimeContextType }) => {
|
||||
const abortSignal = runtimeContext.get("signal");
|
||||
return {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { fileTools } from "../tools/file-tools";
|
||||
import { smoothStream } from "ai";
|
||||
import z from "zod";
|
||||
import { RuntimeContextType } from "../utils/runtime-context";
|
||||
import { vercel } from "@ai-sdk/vercel"
|
||||
import { imagineToMastraToolset } from "../tools/imagine-tool";
|
||||
|
||||
export const developerAgent = new Agent({
|
||||
name: "Software Developer Agent",
|
||||
@@ -22,7 +22,7 @@ You must always use the reportDone tool to report to the architect that you are
|
||||
model: anthropic("claude-sonnet-4-20250514"),
|
||||
// model: anthropic("claude-3-7-sonnet-20250219"),
|
||||
// model: vercel("v0-1.5-md"),
|
||||
tools: {
|
||||
tools: imagineToMastraToolset({
|
||||
readFile: fileTools.readFileTool,
|
||||
writeFile: fileTools.writeFileTool,
|
||||
listFilesInDirectory: fileTools.listFilesInDirectoryTool,
|
||||
@@ -45,7 +45,7 @@ You must always use the reportDone tool to report to the architect that you are
|
||||
return "Thanks for your summary!";
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
defaultStreamOptions: ({ runtimeContext }: { runtimeContext: RuntimeContextType }) => {
|
||||
const abortSignal = runtimeContext.get("signal");
|
||||
return {
|
||||
|
||||
@@ -1,311 +1,319 @@
|
||||
import { createTool } from "@mastra/core";
|
||||
import { z } from "zod";
|
||||
import { createSynapseClient, SynapseHTTPClient } from "@/lib/synapse-http-client";
|
||||
import { createIdGenerator } from "ai";
|
||||
import { getWriterFromContext, RuntimeContextType } from "../utils/runtime-context";
|
||||
import { z } from 'zod';
|
||||
import { SynapseHTTPClient } from '@/lib/synapse-http-client';
|
||||
import { createIdGenerator } from 'ai';
|
||||
import { getWriterFromContext, HonoEnv } from '../utils/runtime-context';
|
||||
import { createImagineTool } from './imagine-tool';
|
||||
import { getContext } from 'hono/context-storage';
|
||||
|
||||
const readMultipleFilesInParallelTool = createTool({
|
||||
id: "readMultipleFilesInParallel",
|
||||
description: "Read multiple files from the repository. This is always encouraged over a single readFile if you know you need to read multiple files.",
|
||||
inputSchema: z.object({
|
||||
paths: z.array(z.string()).describe("The paths to the files to read"),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
files: z.array(z.object({
|
||||
path: z.string().describe("The path to the file"),
|
||||
content: z.string().describe("The content of the file"),
|
||||
})),
|
||||
}),
|
||||
execute: async (params) => {
|
||||
const { context: { paths } } = params;
|
||||
const runtimeContext = params.runtimeContext as RuntimeContextType;
|
||||
console.log(`[TOOL - readMultipleFilesInParallel]`, { paths });
|
||||
const readMultipleFilesInParallelTool = createImagineTool({
|
||||
id: 'readMultipleFilesInParallel',
|
||||
description:
|
||||
'Read multiple files from the repository. This is always encouraged over a single readFile if you know you need to read multiple files.',
|
||||
inputSchema: z.object({
|
||||
paths: z.array(z.string()).describe('The paths to the files to read')
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
files: z.array(
|
||||
z.object({
|
||||
path: z.string().describe('The path to the file'),
|
||||
content: z.string().describe('The content of the file')
|
||||
})
|
||||
)
|
||||
}),
|
||||
execute: async ({ paths }) => {
|
||||
console.log(`[TOOL - readMultipleFilesInParallel]`, { paths });
|
||||
|
||||
const files = await Promise.all(paths.map(async (path) => {
|
||||
const result = await readFileTool.execute({
|
||||
context: { path },
|
||||
runtimeContext,
|
||||
});
|
||||
return result;
|
||||
}));
|
||||
const files = await Promise.all(
|
||||
paths.map(async (path) => {
|
||||
const result = await readFileTool.execute({
|
||||
path
|
||||
});
|
||||
return result;
|
||||
})
|
||||
);
|
||||
|
||||
return { files };
|
||||
}
|
||||
})
|
||||
|
||||
const readFileTool = createTool({
|
||||
id: "readFile",
|
||||
description: "Read a file from the repository",
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe("The path to the file to read"),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
path: z.string().describe("The path to the file"),
|
||||
content: z.string().describe("The content of the file"),
|
||||
}),
|
||||
execute: async (params) => {
|
||||
const {
|
||||
context: { path },
|
||||
} = params;
|
||||
console.log("[tool - readFile] params", params.context);
|
||||
const runtimeContext = params.runtimeContext as RuntimeContextType;
|
||||
const skipWritingToolCalls = runtimeContext.get("skipWritingToolCalls");
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const toolCallId = createIdGenerator({ size: 10 })();
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: "tool-input-available",
|
||||
toolCallId,
|
||||
toolName: "readFile",
|
||||
input: {
|
||||
path,
|
||||
},
|
||||
});
|
||||
return { files };
|
||||
}
|
||||
const synapse = runtimeContext.get("synapseClient");
|
||||
const result = await synapse.readFile({ path });
|
||||
console.log(`[TOOL - readFile] Reading file at path: ${path}`);
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: "tool-output-available",
|
||||
toolCallId,
|
||||
output: {
|
||||
success: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
path: result.path,
|
||||
content: result.content,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const writeFilesTool = createTool({
|
||||
id: "writeFiles",
|
||||
description: "Write multiple files to the repository",
|
||||
inputSchema: z.object({
|
||||
files: z.array(
|
||||
z.object({
|
||||
path: z.string().describe("The path to the file to write"),
|
||||
content: z.string().describe("The content of the file to write"),
|
||||
})
|
||||
),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
successFiles: z.array(
|
||||
z.object({ path: z.string().describe("The path to the file") })
|
||||
),
|
||||
errorFiles: z.array(
|
||||
z.object({
|
||||
path: z.string().describe("The path to the file"),
|
||||
error: z.string().describe("The error message"),
|
||||
})
|
||||
),
|
||||
}),
|
||||
execute: async (params) => {
|
||||
const { context: { files } } = params;
|
||||
const runtimeContext = params.runtimeContext as RuntimeContextType;
|
||||
const synapse = runtimeContext.get("synapseClient");
|
||||
const readFileTool = createImagineTool({
|
||||
id: 'readFile',
|
||||
description: 'Read a file from the repository',
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe('The path to the file to read')
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
path: z.string().describe('The path to the file'),
|
||||
content: z.string().describe('The content of the file')
|
||||
}),
|
||||
execute: async ({ path }) => {
|
||||
const runtimeContext = getContext<HonoEnv>().var.runtimeContext;
|
||||
const skipWritingToolCalls = runtimeContext.get('skipWritingToolCalls');
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const toolCallId = createIdGenerator({ size: 10 })();
|
||||
|
||||
const { successFiles, errorFiles } = await writeFiles(files, synapse);
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: 'tool-input-available',
|
||||
toolCallId,
|
||||
toolName: 'readFile',
|
||||
input: {
|
||||
path
|
||||
}
|
||||
});
|
||||
}
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
const result = await synapse.readFile({ path });
|
||||
console.log(`[TOOL - readFile] Reading file at path: ${path}`);
|
||||
|
||||
return {
|
||||
successFiles,
|
||||
errorFiles,
|
||||
};
|
||||
},
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: 'tool-output-available',
|
||||
toolCallId,
|
||||
output: {
|
||||
success: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
path: result.path,
|
||||
content: result.content
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const writeFileTool = createTool({
|
||||
id: "writeFile",
|
||||
description:
|
||||
"Write a single file to the repository. If the file does not exist, it will be created. If the file exists, it will be overwritten. You must provide the full file contents.",
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe("The path to the file to write"),
|
||||
content: z.string().describe("The content of the file to write"),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
success: z.boolean().describe("Whether the file was written successfully"),
|
||||
error: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("The error message if the file was not written successfully"),
|
||||
}),
|
||||
execute: async (params) => {
|
||||
const {
|
||||
context: { path, content },
|
||||
} = params;
|
||||
const runtimeContext = params.runtimeContext as RuntimeContextType;
|
||||
const skipWritingToolCalls = runtimeContext.get("skipWritingToolCalls");
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const synapse = runtimeContext.get("synapseClient");
|
||||
const writeFilesTool = createImagineTool({
|
||||
id: 'writeFiles',
|
||||
description: 'Write multiple files to the repository',
|
||||
inputSchema: z.object({
|
||||
files: z.array(
|
||||
z.object({
|
||||
path: z.string().describe('The path to the file to write'),
|
||||
content: z.string().describe('The content of the file to write')
|
||||
})
|
||||
)
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
successFiles: z.array(z.object({ path: z.string().describe('The path to the file') })),
|
||||
errorFiles: z.array(
|
||||
z.object({
|
||||
path: z.string().describe('The path to the file'),
|
||||
error: z.string().describe('The error message')
|
||||
})
|
||||
)
|
||||
}),
|
||||
execute: async ({ files }) => {
|
||||
const runtimeContext = getContext<HonoEnv>().var.runtimeContext;
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
|
||||
const toolCallId = createIdGenerator({ size: 10 })();
|
||||
const { successFiles, errorFiles } = await writeFiles(files, synapse);
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: "tool-input-available",
|
||||
toolCallId,
|
||||
toolName: "writeFile",
|
||||
input: {
|
||||
path,
|
||||
content,
|
||||
},
|
||||
});
|
||||
return {
|
||||
successFiles,
|
||||
errorFiles
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const { errorFiles } = await writeFiles([{ path, content }], synapse);
|
||||
const writeFileTool = createImagineTool({
|
||||
id: 'writeFile',
|
||||
description:
|
||||
'Write a single file to the repository. If the file does not exist, it will be created. If the file exists, it will be overwritten. You must provide the full file contents.',
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe('The path to the file to write'),
|
||||
content: z.string().describe('The content of the file to write')
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
success: z.boolean().describe('Whether the file was written successfully'),
|
||||
error: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('The error message if the file was not written successfully')
|
||||
}),
|
||||
execute: async ({ path, content }) => {
|
||||
const runtimeContext = getContext<HonoEnv>().var.runtimeContext;
|
||||
const skipWritingToolCalls = runtimeContext.get('skipWritingToolCalls');
|
||||
const writer = getWriterFromContext(runtimeContext);
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
|
||||
if (errorFiles.length > 0) {
|
||||
return {
|
||||
success: false,
|
||||
error: errorFiles[0].error,
|
||||
};
|
||||
} else {
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: "tool-output-available",
|
||||
toolCallId,
|
||||
output: {
|
||||
success: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
const toolCallId = createIdGenerator({ size: 10 })();
|
||||
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: 'tool-input-available',
|
||||
toolCallId,
|
||||
toolName: 'writeFile',
|
||||
input: {
|
||||
path,
|
||||
content
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const { errorFiles } = await writeFiles([{ path, content }], synapse);
|
||||
|
||||
if (errorFiles.length > 0) {
|
||||
return {
|
||||
success: false,
|
||||
error: errorFiles[0].error
|
||||
};
|
||||
} else {
|
||||
if (!skipWritingToolCalls) {
|
||||
writer.write({
|
||||
type: 'tool-output-available',
|
||||
toolCallId,
|
||||
output: {
|
||||
success: true
|
||||
}
|
||||
});
|
||||
}
|
||||
return {
|
||||
success: true
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
async function writeFiles(files: { path: string; content: string }[], synapse: SynapseHTTPClient) {
|
||||
const successFiles: { path: string }[] = [];
|
||||
const errorFiles: { path: string; error: string }[] = [];
|
||||
const successFiles: { path: string }[] = [];
|
||||
const errorFiles: { path: string; error: string }[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
try {
|
||||
await synapse.createOrUpdateFile({
|
||||
filepath: file.path,
|
||||
content: file.content,
|
||||
});
|
||||
successFiles.push({ path: file.path });
|
||||
} catch (error) {
|
||||
errorFiles.push({
|
||||
path: file.path,
|
||||
error: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
for (const file of files) {
|
||||
try {
|
||||
await synapse.createOrUpdateFile({
|
||||
filepath: file.path,
|
||||
content: file.content
|
||||
});
|
||||
successFiles.push({ path: file.path });
|
||||
} catch (error) {
|
||||
errorFiles.push({
|
||||
path: file.path,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
successFiles,
|
||||
errorFiles,
|
||||
};
|
||||
return {
|
||||
successFiles,
|
||||
errorFiles
|
||||
};
|
||||
}
|
||||
|
||||
const listFilesInDirectoryTool = createTool({
|
||||
id: "listFilesInDirectory",
|
||||
description: "List all files in a directory",
|
||||
inputSchema: z.object({
|
||||
path: z
|
||||
.string()
|
||||
.default("/")
|
||||
.describe("The path to the directory to list files from"),
|
||||
recursive: z
|
||||
.boolean()
|
||||
.default(false)
|
||||
.describe("Whether to list files recursively (dig into subdirectories)"),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
files: z.array(
|
||||
z.object({
|
||||
path: z.string().describe("The path to the file"),
|
||||
})
|
||||
),
|
||||
}),
|
||||
execute: async (params) => {
|
||||
const { context: { path, recursive } } = params;
|
||||
const runtimeContext = params.runtimeContext as RuntimeContextType;
|
||||
const synapse = runtimeContext.get("synapseClient");
|
||||
console.log(
|
||||
`[TOOL - listFilesInDirectory] Listing files in directory at path: ${path}, recursive: ${recursive}`
|
||||
);
|
||||
const files = await synapse.listFilesInDir({
|
||||
dirPath: path || "/",
|
||||
recursive: recursive || false,
|
||||
withContent: false,
|
||||
additionalIgnorePatterns: [],
|
||||
});
|
||||
const listFilesInDirectoryTool = createImagineTool({
|
||||
id: 'listFilesInDirectory',
|
||||
description: 'List all files in a directory',
|
||||
inputSchema: z.object({
|
||||
path: z.string().default('/').describe('The path to the directory to list files from'),
|
||||
recursive: z
|
||||
.boolean()
|
||||
.default(false)
|
||||
.describe('Whether to list files recursively (dig into subdirectories)')
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
files: z.array(
|
||||
z.object({
|
||||
path: z.string().describe('The path to the file')
|
||||
})
|
||||
)
|
||||
}),
|
||||
execute: async ({ path, recursive }) => {
|
||||
const runtimeContext = getContext<HonoEnv>().var.runtimeContext;
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
console.log(
|
||||
`[TOOL - listFilesInDirectory] Listing files in directory at path: ${path}, recursive: ${recursive}`
|
||||
);
|
||||
const files = await synapse.listFilesInDir({
|
||||
dirPath: path || '/',
|
||||
recursive: recursive || false,
|
||||
withContent: false,
|
||||
additionalIgnorePatterns: []
|
||||
});
|
||||
|
||||
console.log(
|
||||
`[TOOL - listFilesInDirectory] Found ${files.length} files in directory at path: ${path}`
|
||||
);
|
||||
console.log(
|
||||
`[TOOL - listFilesInDirectory] Found ${files.length} files in directory at path: ${path}`
|
||||
);
|
||||
|
||||
return {
|
||||
files,
|
||||
};
|
||||
},
|
||||
return {
|
||||
files
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const deleteFileTool = createTool({
|
||||
id: "deleteFile",
|
||||
description: "Delete a file from the repository",
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe("The path to the file to delete"),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
success: z.boolean().describe("Whether the file was deleted successfully"),
|
||||
}),
|
||||
execute: async (params) => {
|
||||
const { context: { path } } = params;
|
||||
const runtimeContext = params.runtimeContext as RuntimeContextType;
|
||||
const synapse = runtimeContext.get("synapseClient");
|
||||
await synapse.deleteFile({ filepath: path });
|
||||
const deleteFileTool = createImagineTool({
|
||||
id: 'deleteFile',
|
||||
description: 'Delete a file from the repository',
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe('The path to the file to delete')
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
success: z.boolean().describe('Whether the file was deleted successfully')
|
||||
}),
|
||||
execute: async ({ path }) => {
|
||||
const runtimeContext = getContext<HonoEnv>().var.runtimeContext;
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
await synapse.deleteFile({ filepath: path });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
},
|
||||
return {
|
||||
success: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const moveFileTool = createTool({
|
||||
id: "moveFile",
|
||||
description:
|
||||
"Move a file from one path to another. Also useful when renaming. If the directory does not exist, it will be created.",
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe("The path to the file to move"),
|
||||
newPath: z.string().describe("The new path to the file"),
|
||||
intent: z
|
||||
.enum(["move", "rename"])
|
||||
.describe(
|
||||
"The intent of the move operation. This will help render the appropriate UI to the user."
|
||||
),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
success: z.boolean().describe("Whether the file was moved successfully"),
|
||||
}),
|
||||
execute: async (params) => {
|
||||
const { context: { path, newPath } } = params;
|
||||
const runtimeContext = params.runtimeContext as RuntimeContextType;
|
||||
const synapse = runtimeContext.get("synapseClient");
|
||||
await synapse.updateFilePath({ filepath: path, newPath });
|
||||
const moveFileTool = createImagineTool({
|
||||
id: 'moveFile',
|
||||
description:
|
||||
'Move a file from one path to another. Also useful when renaming. If the directory does not exist, it will be created.',
|
||||
inputSchema: z.object({
|
||||
path: z.string().describe('The path to the file to move'),
|
||||
newPath: z.string().describe('The new path to the file'),
|
||||
intent: z
|
||||
.enum(['move', 'rename'])
|
||||
.describe(
|
||||
'The intent of the move operation. This will help render the appropriate UI to the user.'
|
||||
)
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
success: z.boolean().describe('Whether the file was moved successfully')
|
||||
}),
|
||||
execute: async ({ path, newPath }) => {
|
||||
const runtimeContext = getContext<HonoEnv>().var.runtimeContext;
|
||||
const synapse = runtimeContext.get('synapseClient');
|
||||
await synapse.updateFilePath({ filepath: path, newPath });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
},
|
||||
return {
|
||||
success: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export const fileTools = {
|
||||
readFileTool,
|
||||
// writeFilesTool,
|
||||
writeFileTool,
|
||||
listFilesInDirectoryTool,
|
||||
deleteFileTool,
|
||||
moveFileTool,
|
||||
readMultipleFilesInParallelTool,
|
||||
readFileTool,
|
||||
writeFileTool,
|
||||
listFilesInDirectoryTool,
|
||||
deleteFileTool,
|
||||
moveFileTool,
|
||||
readMultipleFilesInParallelTool
|
||||
};
|
||||
|
||||
// function convertMastraToolToVercelTool<
|
||||
// TInputSchema extends z.ZodSchema,
|
||||
// TOutputSchema extends z.ZodSchema
|
||||
// >(mastraTool: {
|
||||
// description: string;
|
||||
// inputSchema: TInputSchema;
|
||||
// outputSchema: TOutputSchema;
|
||||
// execute: any;
|
||||
// }): VercelTool<z.infer<TInputSchema>, z.infer<TOutputSchema>> {
|
||||
// return {
|
||||
// description: mastraTool.description,
|
||||
// inputSchema: mastraTool.inputSchema,
|
||||
// outputSchema: mastraTool.outputSchema,
|
||||
// execute: mastraTool.execute,
|
||||
// } as VercelTool<z.infer<TInputSchema>, z.infer<TOutputSchema>>;
|
||||
// }
|
||||
|
||||
|
||||
// export const fileToolsVercel = {
|
||||
// readFileTool: convertMastraToolToVercelTool<typeof readFileTool.inputSchema, typeof readFileTool.outputSchema>(readFileTool)
|
||||
// };
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Tool as MastraTool, ToolExecutionContext } from '@mastra/core';
|
||||
import z from 'zod';
|
||||
|
||||
export type ImagineTool<TInput extends z.ZodSchema, TOutput extends z.ZodSchema> = {
|
||||
id: string;
|
||||
description: string;
|
||||
inputSchema: TInput;
|
||||
outputSchema: TOutput;
|
||||
execute: (input: z.infer<TInput>) => Promise<z.infer<TOutput>> | z.infer<TOutput>;
|
||||
};
|
||||
|
||||
export const createImagineTool = <TInput extends z.ZodSchema, TOutput extends z.ZodSchema>({
|
||||
id,
|
||||
description,
|
||||
inputSchema,
|
||||
outputSchema,
|
||||
execute
|
||||
}: {
|
||||
id: string;
|
||||
description: string;
|
||||
inputSchema: TInput;
|
||||
outputSchema: TOutput;
|
||||
execute: (input: z.infer<TInput>) => Promise<z.infer<TOutput>> | z.infer<TOutput>;
|
||||
}): ImagineTool<TInput, TOutput> => {
|
||||
return {
|
||||
id,
|
||||
description,
|
||||
inputSchema,
|
||||
outputSchema,
|
||||
execute
|
||||
};
|
||||
};
|
||||
|
||||
export const mastraToImagineToolCallAdapter = <
|
||||
TInput extends z.ZodSchema,
|
||||
TOutput extends z.ZodSchema
|
||||
>(
|
||||
tool: ImagineTool<TInput, TOutput>
|
||||
): MastraTool<TInput, TOutput, ToolExecutionContext<TInput>> => {
|
||||
return {
|
||||
id: tool.id,
|
||||
description: tool.description,
|
||||
inputSchema: tool.inputSchema,
|
||||
outputSchema: tool.outputSchema,
|
||||
__isMastraTool: true,
|
||||
execute: async (params: ToolExecutionContext<TInput>) => {
|
||||
return tool.execute(params.context);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const imagineToMastraToolset = <
|
||||
T extends Record<string, ImagineTool<any, any>>
|
||||
>(
|
||||
tools: T
|
||||
): {
|
||||
[K in keyof T]: T[K] extends ImagineTool<infer TInput, infer TOutput>
|
||||
? MastraTool<TInput, TOutput, ToolExecutionContext<TInput>>
|
||||
: never;
|
||||
} => {
|
||||
return Object.fromEntries(
|
||||
Object.entries(tools).map(([key, tool]) => [key, mastraToImagineToolCallAdapter(tool)])
|
||||
) as any;
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { RuntimeContext } from "@mastra/core/runtime-context";
|
||||
import { UIMessageStreamWriter } from "ai";
|
||||
import { createSynapseClient, SynapseHTTPClient } from "@/lib/synapse-http-client";
|
||||
import { ImagineUIMessage } from "@/shared-types";
|
||||
import { createSynapseClient, SynapseHTTPClient } from "../../../synapse-http-client";
|
||||
import { ImagineUIMessage } from "../../../../shared-types";
|
||||
|
||||
export type WriterType = UIMessageStreamWriter<ImagineUIMessage>;
|
||||
export type RuntimeContextPayload = {
|
||||
@@ -14,6 +14,11 @@ export type RuntimeContextPayload = {
|
||||
synapseClient: SynapseHTTPClient;
|
||||
}
|
||||
export type RuntimeContextType = RuntimeContext<RuntimeContextPayload>;
|
||||
export type HonoEnv = {
|
||||
Variables: {
|
||||
runtimeContext: RuntimeContextType,
|
||||
}
|
||||
}
|
||||
|
||||
export const cloneRuntimeContext = (runtimeContext: RuntimeContextType, overrides?: Partial<RuntimeContextPayload>): RuntimeContextType => {
|
||||
const newRuntimeContext = new RuntimeContext<RuntimeContextPayload>();
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
getPagesAndComponents,
|
||||
systemPromptPartsArrayToModelMessages,
|
||||
} from "../../system-prompt/system-prompt-utils";
|
||||
import { GitRepositoryUtils } from "@/lib/git-utils";
|
||||
import { GitRepositoryUtils } from "../../../../lib/git-utils";
|
||||
import { currentCode } from "../../system-prompt/system-prompt-parts";
|
||||
import { mastra } from "..";
|
||||
import { cacheSystemMessage } from "../utils";
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
} from "../utils/runtime-context";
|
||||
import { openai } from "@ai-sdk/openai";
|
||||
import * as systemPromptParts from "../../system-prompt/system-prompt-parts";
|
||||
import fs from "fs";
|
||||
import { anthropic } from "@ai-sdk/anthropic";
|
||||
|
||||
const planStep = createStep({
|
||||
|
||||
@@ -11,15 +11,8 @@ import { fileURLToPath } from 'url';
|
||||
import { handleChatRequest } from './handlers/chat/route';
|
||||
import { getConversation, getConversations } from './handlers/conversation';
|
||||
import { contextStorage } from "hono/context-storage";
|
||||
import { RuntimeContextType } from './lib/ai/mastra/utils/runtime-context';
|
||||
|
||||
export type HonoEnv = {
|
||||
Variables: {
|
||||
runtimeContext: RuntimeContextType,
|
||||
}
|
||||
}
|
||||
|
||||
const app = new Hono<HonoEnv>();
|
||||
const app = new Hono();
|
||||
|
||||
// Middleware
|
||||
app.use('*', cors());
|
||||
|
||||
@@ -18,4 +18,4 @@ export type ImagineUIDataParts = InferUIDataParts<{
|
||||
thinking: typeof thinkingUIDataPartSchema;
|
||||
}>;
|
||||
|
||||
export type ImagineUIMessage = UIMessage<never, ImagineUIDataParts, ImagineTools>;
|
||||
export type ImagineUIMessage = UIMessage<never, ImagineUIDataParts, ImagineTools>;
|
||||
@@ -20,5 +20,5 @@
|
||||
}
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
"exclude": ["node_modules", "dist", "tmp"]
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": false,
|
||||
"outDir": "./dist",
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"jsx": "preserve",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user