@mastra/deployer 0.0.0-commonjs-20250227130920
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +41 -0
- package/CHANGELOG.md +897 -0
- package/LICENSE +44 -0
- package/README.md +159 -0
- package/dist/_tsup-dts-rollup.d.cts +360 -0
- package/dist/_tsup-dts-rollup.d.ts +360 -0
- package/dist/build/analyze.cjs +367 -0
- package/dist/build/analyze.d.cts +1 -0
- package/dist/build/analyze.d.ts +1 -0
- package/dist/build/analyze.js +2 -0
- package/dist/build/bundler.cjs +353 -0
- package/dist/build/bundler.d.cts +2 -0
- package/dist/build/bundler.d.ts +2 -0
- package/dist/build/bundler.js +2 -0
- package/dist/build/index.cjs +1146 -0
- package/dist/build/index.d.cts +10 -0
- package/dist/build/index.d.ts +10 -0
- package/dist/build/index.js +5 -0
- package/dist/bundler/index.cjs +999 -0
- package/dist/bundler/index.d.cts +1 -0
- package/dist/bundler/index.d.ts +1 -0
- package/dist/bundler/index.js +5 -0
- package/dist/chunk-3ONBKVC4.js +113 -0
- package/dist/chunk-AXS5WSIK.js +290 -0
- package/dist/chunk-DTSFVNIF.js +260 -0
- package/dist/chunk-JMH7HCD6.js +274 -0
- package/dist/chunk-SGK37ZWD.js +254 -0
- package/dist/chunk-YNXJO2XU.js +69 -0
- package/dist/index.cjs +1229 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +131 -0
- package/dist/server/index.cjs +4930 -0
- package/dist/server/index.d.cts +2 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +4923 -0
- package/dist/templates/instrumentation-template.js +86 -0
- package/eslint.config.js +6 -0
- package/global.d.ts +0 -0
- package/package.json +112 -0
- package/public/templates/instrumentation-template.js +86 -0
- package/src/build/analyze.ts +279 -0
- package/src/build/babel/fix-libsql.ts +41 -0
- package/src/build/babel/get-deployer.ts +54 -0
- package/src/build/babel/get-telemetry-config.ts +62 -0
- package/src/build/babel/remove-deployer.ts +43 -0
- package/src/build/bundle.ts +139 -0
- package/src/build/bundler.ts +135 -0
- package/src/build/deployer.ts +67 -0
- package/src/build/deps.ts +149 -0
- package/src/build/env.ts +76 -0
- package/src/build/fs.ts +66 -0
- package/src/build/index.ts +7 -0
- package/src/build/isNodeBuiltin.ts +7 -0
- package/src/build/plugins/fix-libsql.ts +69 -0
- package/src/build/plugins/hono-alias.ts +17 -0
- package/src/build/plugins/pino.ts +93 -0
- package/src/build/plugins/remove-deployer.ts +37 -0
- package/src/build/plugins/telemetry-fix.ts +54 -0
- package/src/build/telemetry.ts +76 -0
- package/src/build/utils.ts +12 -0
- package/src/build/watcher.ts +43 -0
- package/src/bundler/index.ts +144 -0
- package/src/deploy/base.ts +30 -0
- package/src/deploy/index.ts +2 -0
- package/src/deploy/log.ts +61 -0
- package/src/index.ts +3 -0
- package/src/server/handlers/agents.ts +209 -0
- package/src/server/handlers/client.ts +36 -0
- package/src/server/handlers/error.ts +29 -0
- package/src/server/handlers/logs.ts +53 -0
- package/src/server/handlers/memory.ts +196 -0
- package/src/server/handlers/prompt.ts +128 -0
- package/src/server/handlers/root.ts +6 -0
- package/src/server/handlers/telemetry.ts +48 -0
- package/src/server/handlers/tools.ts +114 -0
- package/src/server/handlers/utils.ts +15 -0
- package/src/server/handlers/vector.ts +149 -0
- package/src/server/handlers/workflows.ts +119 -0
- package/src/server/index.ts +1355 -0
- package/src/server/openapi.json +434 -0
- package/src/server/openapi.script.js +22 -0
- package/src/server/types.ts +4 -0
- package/src/server/welcome.ts +105 -0
- package/tsconfig.json +5 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Mastra } from '@mastra/core';
|
|
2
|
+
import { Agent } from '@mastra/core/agent';
|
|
3
|
+
import type { Context } from 'hono';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
import { handleError } from './error';
|
|
7
|
+
|
|
8
|
+
export async function generateSystemPromptHandler(c: Context) {
|
|
9
|
+
try {
|
|
10
|
+
// Check if this is a playground request
|
|
11
|
+
const agentId = c.req.param('agentId');
|
|
12
|
+
const isPlayground = c.get('playground') === true;
|
|
13
|
+
if (!isPlayground) {
|
|
14
|
+
return c.json({ error: 'This API is only available in the playground environment' }, 403);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { instructions, comment } = await c.req.json();
|
|
18
|
+
|
|
19
|
+
if (!instructions) {
|
|
20
|
+
return c.json({ error: 'Missing instructions in request body' }, 400);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const mastra: Mastra<any> = c.get('mastra');
|
|
24
|
+
const agent = mastra.getAgent(agentId);
|
|
25
|
+
|
|
26
|
+
if (!agent) {
|
|
27
|
+
return c.json({ error: 'Agent not found' }, 404);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let evalSummary = '';
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
// Get both test and live evals
|
|
34
|
+
const testEvals = (await mastra.storage?.getEvalsByAgentName?.(agent.name, 'test')) || [];
|
|
35
|
+
const liveEvals = (await mastra.storage?.getEvalsByAgentName?.(agent.name, 'live')) || [];
|
|
36
|
+
// Format eval results for the prompt
|
|
37
|
+
const evalsMapped = [...testEvals, ...liveEvals].filter(
|
|
38
|
+
({ instructions: evalInstructions }) => evalInstructions === instructions,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
evalSummary = evalsMapped
|
|
42
|
+
.map(
|
|
43
|
+
({ input, output, result }) => `
|
|
44
|
+
Input: ${input}\n
|
|
45
|
+
Output: ${output}\n
|
|
46
|
+
Result: ${JSON.stringify(result)}
|
|
47
|
+
|
|
48
|
+
`,
|
|
49
|
+
)
|
|
50
|
+
.join('');
|
|
51
|
+
} catch (error) {
|
|
52
|
+
mastra.getLogger().error(`Error fetching evals`, { error });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const ENHANCE_SYSTEM_PROMPT_INSTRUCTIONS = `
|
|
56
|
+
You are an expert system prompt engineer, specialized in analyzing and enhancing instructions to create clear, effective, and comprehensive system prompts. Your goal is to help users transform their basic instructions into well-structured system prompts that will guide AI behavior effectively.
|
|
57
|
+
Follow these steps to analyze and enhance the instructions:
|
|
58
|
+
1. ANALYSIS PHASE
|
|
59
|
+
- Identify the core purpose and goals
|
|
60
|
+
- Extract key constraints and requirements
|
|
61
|
+
- Recognize domain-specific terminology and concepts
|
|
62
|
+
- Note any implicit assumptions that should be made explicit
|
|
63
|
+
2. PROMPT STRUCTURE
|
|
64
|
+
Create a system prompt with these components:
|
|
65
|
+
a) ROLE DEFINITION
|
|
66
|
+
- Clear statement of the AI's role and purpose
|
|
67
|
+
- Key responsibilities and scope
|
|
68
|
+
- Primary stakeholders and users
|
|
69
|
+
b) CORE CAPABILITIES
|
|
70
|
+
- Main functions and abilities
|
|
71
|
+
- Specific domain knowledge required
|
|
72
|
+
- Tools and resources available
|
|
73
|
+
c) BEHAVIORAL GUIDELINES
|
|
74
|
+
- Communication style and tone
|
|
75
|
+
- Decision-making framework
|
|
76
|
+
- Error handling approach
|
|
77
|
+
- Ethical considerations
|
|
78
|
+
d) CONSTRAINTS & BOUNDARIES
|
|
79
|
+
- Explicit limitations
|
|
80
|
+
- Out-of-scope activities
|
|
81
|
+
- Security and privacy considerations
|
|
82
|
+
e) SUCCESS CRITERIA
|
|
83
|
+
- Quality standards
|
|
84
|
+
- Expected outcomes
|
|
85
|
+
- Performance metrics
|
|
86
|
+
3. QUALITY CHECKS
|
|
87
|
+
Ensure the prompt is:
|
|
88
|
+
- Clear and unambiguous
|
|
89
|
+
- Comprehensive yet concise
|
|
90
|
+
- Properly scoped
|
|
91
|
+
- Technically accurate
|
|
92
|
+
- Ethically sound
|
|
93
|
+
4. OUTPUT FORMAT
|
|
94
|
+
Return a structured response with:
|
|
95
|
+
- Enhanced system prompt
|
|
96
|
+
- Analysis of key components
|
|
97
|
+
- Identified goals and constraints
|
|
98
|
+
- Core domain concepts
|
|
99
|
+
Remember: A good system prompt should be specific enough to guide behavior but flexible enough to handle edge cases.
|
|
100
|
+
Focus on creating prompts that are clear, actionable, and aligned with the intended use case.
|
|
101
|
+
`;
|
|
102
|
+
|
|
103
|
+
const systemPromptAgent = new Agent({
|
|
104
|
+
name: 'system-prompt-enhancer',
|
|
105
|
+
instructions: ENHANCE_SYSTEM_PROMPT_INSTRUCTIONS,
|
|
106
|
+
model: agent.llm?.getModel(),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const result = await systemPromptAgent.generate(
|
|
110
|
+
`
|
|
111
|
+
We need to improve the system prompt.
|
|
112
|
+
Current: ${instructions}
|
|
113
|
+
${comment ? `User feedback: ${comment}` : ''}
|
|
114
|
+
${evalSummary ? `\nEvaluation Results:\n${evalSummary}` : ''}
|
|
115
|
+
`,
|
|
116
|
+
{
|
|
117
|
+
output: z.object({
|
|
118
|
+
new_prompt: z.string(),
|
|
119
|
+
explanation: z.string(),
|
|
120
|
+
}),
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
return c.json(result?.object || {});
|
|
125
|
+
} catch (error) {
|
|
126
|
+
return handleError(error, 'Error generating system prompt');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { MastraStorage } from '@mastra/core/storage';
|
|
2
|
+
import type { Telemetry } from '@mastra/core/telemetry';
|
|
3
|
+
import type { Context } from 'hono';
|
|
4
|
+
|
|
5
|
+
import { HTTPException } from 'hono/http-exception';
|
|
6
|
+
|
|
7
|
+
import { handleError } from './error';
|
|
8
|
+
|
|
9
|
+
export async function getTelemetryHandler(c: Context) {
|
|
10
|
+
try {
|
|
11
|
+
const mastra = c.get('mastra');
|
|
12
|
+
const telemetry: Telemetry = mastra.telemetry;
|
|
13
|
+
const storage: MastraStorage = mastra.storage;
|
|
14
|
+
|
|
15
|
+
const { name, scope, page, perPage } = c.req.query();
|
|
16
|
+
const attribute = c.req.queries('attribute');
|
|
17
|
+
|
|
18
|
+
if (!telemetry) {
|
|
19
|
+
throw new HTTPException(400, { message: 'Telemetry is not initialized' });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!storage) {
|
|
23
|
+
throw new HTTPException(400, { message: 'Storage is not initialized' });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Parse attribute query parameter if present
|
|
27
|
+
const attributes = attribute
|
|
28
|
+
? Object.fromEntries(
|
|
29
|
+
(Array.isArray(attribute) ? attribute : [attribute]).map(attr => {
|
|
30
|
+
const [key, value] = attr.split(':');
|
|
31
|
+
return [key, value];
|
|
32
|
+
}),
|
|
33
|
+
)
|
|
34
|
+
: undefined;
|
|
35
|
+
|
|
36
|
+
const traces = await storage.getTraces({
|
|
37
|
+
name,
|
|
38
|
+
scope,
|
|
39
|
+
page: Number(page ?? 0),
|
|
40
|
+
perPage: Number(perPage ?? 100),
|
|
41
|
+
attributes,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return c.json({ traces });
|
|
45
|
+
} catch (error) {
|
|
46
|
+
return handleError(error, 'Error saving messages');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import { HTTPException } from 'hono/http-exception';
|
|
3
|
+
import { stringify } from 'superjson';
|
|
4
|
+
import zodToJsonSchema from 'zod-to-json-schema';
|
|
5
|
+
|
|
6
|
+
import { handleError } from './error';
|
|
7
|
+
|
|
8
|
+
// Tool handlers
|
|
9
|
+
export async function getToolsHandler(c: Context) {
|
|
10
|
+
try {
|
|
11
|
+
const tools = c.get('tools');
|
|
12
|
+
|
|
13
|
+
if (!tools) {
|
|
14
|
+
return c.json({});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const serializedTools = Object.entries(tools).reduce(
|
|
18
|
+
(acc, [id, _tool]) => {
|
|
19
|
+
const tool = _tool as any;
|
|
20
|
+
acc[id] = {
|
|
21
|
+
...tool,
|
|
22
|
+
inputSchema: tool.inputSchema ? stringify(zodToJsonSchema(tool.inputSchema)) : undefined,
|
|
23
|
+
outputSchema: tool.outputSchema ? stringify(zodToJsonSchema(tool.outputSchema)) : undefined,
|
|
24
|
+
};
|
|
25
|
+
return acc;
|
|
26
|
+
},
|
|
27
|
+
{} as Record<string, any>,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return c.json(serializedTools);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return handleError(error, 'Error getting tools');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function getToolByIdHandler(c: Context) {
|
|
37
|
+
try {
|
|
38
|
+
const tools = c.get('tools');
|
|
39
|
+
const toolId = c.req.param('toolId');
|
|
40
|
+
const tool = Object.values(tools || {}).find((tool: any) => tool.id === toolId) as any;
|
|
41
|
+
|
|
42
|
+
if (!tool) {
|
|
43
|
+
throw new HTTPException(404, { message: 'Tool not found' });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const serializedTool = {
|
|
47
|
+
...tool,
|
|
48
|
+
inputSchema: tool.inputSchema ? stringify(zodToJsonSchema(tool.inputSchema)) : undefined,
|
|
49
|
+
outputSchema: tool.outputSchema ? stringify(zodToJsonSchema(tool.outputSchema)) : undefined,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return c.json(serializedTool);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return handleError(error, 'Error getting tool');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function executeToolHandler(tools: Record<string, any>) {
|
|
59
|
+
return async (c: Context) => {
|
|
60
|
+
try {
|
|
61
|
+
const toolId = decodeURIComponent(c.req.param('toolId'));
|
|
62
|
+
const tool = Object.values(tools || {}).find((tool: any) => tool.id === toolId) as any;
|
|
63
|
+
|
|
64
|
+
if (!tool) {
|
|
65
|
+
return c.json({ error: 'Tool not found' }, 404);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!tool?.execute) {
|
|
69
|
+
return c.json({ error: 'Tool is not executable' }, 400);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { data } = await c.req.json();
|
|
73
|
+
const mastra = c.get('mastra');
|
|
74
|
+
const result = await tool.execute({
|
|
75
|
+
context: data,
|
|
76
|
+
mastra,
|
|
77
|
+
runId: mastra.runId,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return c.json(result);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
return handleError(error, 'Error executing tool');
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function executeAgentToolHandler(c: Context) {
|
|
88
|
+
try {
|
|
89
|
+
const mastra = c.get('mastra');
|
|
90
|
+
const agentId = c.req.param('agentId');
|
|
91
|
+
const toolId = c.req.param('toolId');
|
|
92
|
+
const agent = mastra.getAgent(agentId);
|
|
93
|
+
const tool = Object.values(agent?.tools || {}).find((tool: any) => tool.id === toolId) as any;
|
|
94
|
+
|
|
95
|
+
if (!tool) {
|
|
96
|
+
throw new HTTPException(404, { message: 'Tool not found' });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!tool?.execute) {
|
|
100
|
+
return c.json({ error: 'Tool is not executable' }, 400);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const { data } = await c.req.json();
|
|
104
|
+
const result = await tool.execute({
|
|
105
|
+
context: data,
|
|
106
|
+
mastra,
|
|
107
|
+
runId: agentId,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return c.json(result);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
return handleError(error, 'Error executing tool');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HTTPException } from 'hono/http-exception';
|
|
2
|
+
|
|
3
|
+
// Validation helper
|
|
4
|
+
export function validateBody(body: Record<string, unknown>) {
|
|
5
|
+
const errorResponse = Object.entries(body).reduce<Record<string, string>>((acc, [key, value]) => {
|
|
6
|
+
if (!value) {
|
|
7
|
+
acc[key] = `${key} is required`;
|
|
8
|
+
}
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
|
|
12
|
+
if (Object.keys(errorResponse).length > 0) {
|
|
13
|
+
throw new HTTPException(400, { message: JSON.stringify(errorResponse) });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { MastraVector, QueryResult, IndexStats } from '@mastra/core/vector';
|
|
2
|
+
import type { Context } from 'hono';
|
|
3
|
+
|
|
4
|
+
import { HTTPException } from 'hono/http-exception';
|
|
5
|
+
|
|
6
|
+
import { handleError } from './error';
|
|
7
|
+
|
|
8
|
+
interface UpsertRequest {
|
|
9
|
+
indexName: string;
|
|
10
|
+
vectors: number[][];
|
|
11
|
+
metadata?: Record<string, any>[];
|
|
12
|
+
ids?: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface CreateIndexRequest {
|
|
16
|
+
indexName: string;
|
|
17
|
+
dimension: number;
|
|
18
|
+
metric?: 'cosine' | 'euclidean' | 'dotproduct';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface QueryRequest {
|
|
22
|
+
indexName: string;
|
|
23
|
+
queryVector: number[];
|
|
24
|
+
topK?: number;
|
|
25
|
+
filter?: Record<string, any>;
|
|
26
|
+
includeVector?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const getVector = (c: Context, vectorName: string): MastraVector => {
|
|
30
|
+
const vector = c.get('mastra').getVector(vectorName);
|
|
31
|
+
if (!vector) {
|
|
32
|
+
throw new HTTPException(404, { message: `Vector store ${vectorName} not found` });
|
|
33
|
+
}
|
|
34
|
+
return vector;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Upsert vectors
|
|
38
|
+
export async function upsertVectors(c: Context) {
|
|
39
|
+
try {
|
|
40
|
+
const vectorName = c.req.param('vectorName');
|
|
41
|
+
const { indexName, vectors, metadata, ids } = await c.req.json<UpsertRequest>();
|
|
42
|
+
|
|
43
|
+
if (!indexName || !vectors || !Array.isArray(vectors)) {
|
|
44
|
+
throw new HTTPException(400, { message: 'Invalid request body. indexName and vectors array are required.' });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const vector = getVector(c, vectorName);
|
|
48
|
+
const result = await vector.upsert(indexName, vectors, metadata, ids);
|
|
49
|
+
return c.json({ ids: result });
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return handleError(error, 'Error upserting vectors');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Create index
|
|
56
|
+
export async function createIndex(c: Context) {
|
|
57
|
+
try {
|
|
58
|
+
const vectorName = c.req.param('vectorName');
|
|
59
|
+
const { indexName, dimension, metric } = await c.req.json<CreateIndexRequest>();
|
|
60
|
+
|
|
61
|
+
if (!indexName || typeof dimension !== 'number' || dimension <= 0) {
|
|
62
|
+
throw new HTTPException(400, {
|
|
63
|
+
message: 'Invalid request body. indexName and positive dimension number are required.',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (metric && !['cosine', 'euclidean', 'dotproduct'].includes(metric)) {
|
|
68
|
+
throw new HTTPException(400, { message: 'Invalid metric. Must be one of: cosine, euclidean, dotproduct' });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const vector = getVector(c, vectorName);
|
|
72
|
+
await vector.createIndex(indexName, dimension, metric);
|
|
73
|
+
return c.json({ success: true });
|
|
74
|
+
} catch (error) {
|
|
75
|
+
return handleError(error, 'Error creating index');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Query vectors
|
|
80
|
+
export async function queryVectors(c: Context) {
|
|
81
|
+
try {
|
|
82
|
+
const vectorName = c.req.param('vectorName');
|
|
83
|
+
const { indexName, queryVector, topK = 10, filter, includeVector = false } = await c.req.json<QueryRequest>();
|
|
84
|
+
|
|
85
|
+
if (!indexName || !queryVector || !Array.isArray(queryVector)) {
|
|
86
|
+
throw new HTTPException(400, { message: 'Invalid request body. indexName and queryVector array are required.' });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const vector = getVector(c, vectorName);
|
|
90
|
+
const results: QueryResult[] = await vector.query(indexName, queryVector, topK, filter, includeVector);
|
|
91
|
+
return c.json({ results });
|
|
92
|
+
} catch (error) {
|
|
93
|
+
return handleError(error, 'Error querying vectors');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// List indexes
|
|
98
|
+
export async function listIndexes(c: Context) {
|
|
99
|
+
try {
|
|
100
|
+
const vectorName = c.req.param('vectorName');
|
|
101
|
+
const vector = getVector(c, vectorName);
|
|
102
|
+
|
|
103
|
+
const indexes = await vector.listIndexes();
|
|
104
|
+
return c.json({ indexes: indexes.filter(Boolean) });
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return handleError(error, 'Error listing indexes');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Describe index
|
|
111
|
+
export async function describeIndex(c: Context) {
|
|
112
|
+
try {
|
|
113
|
+
const vectorName = c.req.param('vectorName');
|
|
114
|
+
const indexName = c.req.param('indexName');
|
|
115
|
+
|
|
116
|
+
if (!indexName) {
|
|
117
|
+
throw new HTTPException(400, { message: 'Index name is required' });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const vector = getVector(c, vectorName);
|
|
121
|
+
const stats: IndexStats = await vector.describeIndex(indexName);
|
|
122
|
+
|
|
123
|
+
return c.json({
|
|
124
|
+
dimension: stats.dimension,
|
|
125
|
+
count: stats.count,
|
|
126
|
+
metric: stats.metric?.toLowerCase(),
|
|
127
|
+
});
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return handleError(error, 'Error describing index');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Delete index
|
|
134
|
+
export async function deleteIndex(c: Context) {
|
|
135
|
+
try {
|
|
136
|
+
const vectorName = c.req.param('vectorName');
|
|
137
|
+
const indexName = c.req.param('indexName');
|
|
138
|
+
|
|
139
|
+
if (!indexName) {
|
|
140
|
+
throw new HTTPException(400, { message: 'Index name is required' });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const vector = getVector(c, vectorName);
|
|
144
|
+
await vector.deleteIndex(indexName);
|
|
145
|
+
return c.json({ success: true });
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return handleError(error, 'Error deleting index');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { Mastra } from '@mastra/core';
|
|
2
|
+
import type { Context } from 'hono';
|
|
3
|
+
import { streamText } from 'hono/streaming';
|
|
4
|
+
import { stringify } from 'superjson';
|
|
5
|
+
import zodToJsonSchema from 'zod-to-json-schema';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import { handleError } from './error';
|
|
9
|
+
|
|
10
|
+
export async function getWorkflowsHandler(c: Context) {
|
|
11
|
+
try {
|
|
12
|
+
const mastra: Mastra = c.get('mastra');
|
|
13
|
+
const workflows = mastra.getWorkflows({ serialized: true });
|
|
14
|
+
return c.json(workflows);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
return handleError(error, 'Error getting workflows');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function getWorkflowByIdHandler(c: Context) {
|
|
21
|
+
try {
|
|
22
|
+
const mastra: Mastra = c.get('mastra');
|
|
23
|
+
const workflowId = c.req.param('workflowId');
|
|
24
|
+
const workflow = mastra.getWorkflow(workflowId);
|
|
25
|
+
|
|
26
|
+
const triggerSchema = workflow?.triggerSchema;
|
|
27
|
+
const stepGraph = workflow.stepGraph;
|
|
28
|
+
const stepSubscriberGraph = workflow.stepSubscriberGraph;
|
|
29
|
+
const serializedSteps = Object.entries(workflow.steps).reduce<any>((acc, [key, step]) => {
|
|
30
|
+
const _step = step as any;
|
|
31
|
+
acc[key] = {
|
|
32
|
+
..._step,
|
|
33
|
+
inputSchema: _step.inputSchema ? stringify(zodToJsonSchema(_step.inputSchema)) : undefined,
|
|
34
|
+
outputSchema: _step.outputSchema ? stringify(zodToJsonSchema(_step.outputSchema)) : undefined,
|
|
35
|
+
};
|
|
36
|
+
return acc;
|
|
37
|
+
}, {});
|
|
38
|
+
|
|
39
|
+
return c.json({
|
|
40
|
+
name: workflow.name,
|
|
41
|
+
triggerSchema: triggerSchema ? stringify(zodToJsonSchema(triggerSchema)) : undefined,
|
|
42
|
+
steps: serializedSteps,
|
|
43
|
+
stepGraph,
|
|
44
|
+
stepSubscriberGraph,
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return handleError(error, 'Error getting workflow');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function executeWorkflowHandler(c: Context) {
|
|
52
|
+
try {
|
|
53
|
+
const mastra: Mastra = c.get('mastra');
|
|
54
|
+
const workflowId = c.req.param('workflowId');
|
|
55
|
+
const workflow = mastra.getWorkflow(workflowId);
|
|
56
|
+
const body = await c.req.json();
|
|
57
|
+
|
|
58
|
+
const { start } = workflow.createRun();
|
|
59
|
+
|
|
60
|
+
const result = await start({
|
|
61
|
+
triggerData: body,
|
|
62
|
+
});
|
|
63
|
+
return c.json(result);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
return handleError(error, 'Error executing workflow');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function watchWorkflowHandler(c: Context) {
|
|
70
|
+
try {
|
|
71
|
+
const mastra: Mastra = c.get('mastra');
|
|
72
|
+
const logger = mastra.getLogger();
|
|
73
|
+
const workflowId = c.req.param('workflowId');
|
|
74
|
+
const workflow = mastra.getWorkflow(workflowId);
|
|
75
|
+
|
|
76
|
+
return streamText(
|
|
77
|
+
c,
|
|
78
|
+
async stream => {
|
|
79
|
+
// NOTE: looks like the UI is closing the watch request, so as long as that is the case
|
|
80
|
+
// this promise doesn't need to be resolved or rejected
|
|
81
|
+
return new Promise((_resolve, _reject) => {
|
|
82
|
+
let unwatch: () => void = workflow.watch(({ activePaths, context }) => {
|
|
83
|
+
void stream.write(JSON.stringify({ activePaths, context }) + '\x1E');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
stream.onAbort(() => {
|
|
87
|
+
unwatch?.();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
async (err, stream) => {
|
|
92
|
+
logger.error('Error in watch stream: ' + err?.message);
|
|
93
|
+
stream.abort();
|
|
94
|
+
await stream.close();
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return handleError(error, 'Error watching workflow');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function resumeWorkflowHandler(c: Context) {
|
|
103
|
+
try {
|
|
104
|
+
const mastra: Mastra = c.get('mastra');
|
|
105
|
+
const workflowId = c.req.param('workflowId');
|
|
106
|
+
const workflow = mastra.getWorkflow(workflowId);
|
|
107
|
+
const { stepId, runId, context } = await c.req.json();
|
|
108
|
+
|
|
109
|
+
const result = await workflow.resume({
|
|
110
|
+
stepId,
|
|
111
|
+
runId,
|
|
112
|
+
context,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return c.json(result);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
return handleError(error, 'Error resuming workflow step');
|
|
118
|
+
}
|
|
119
|
+
}
|