@prostgles/prostgles 2.3.6-dev.1786565331 → 2.3.6-dev.1786615880
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/dist/common/DBGeneratedSchema.d.ts +5 -9
- package/dist/common/DBGeneratedSchema.d.ts.map +1 -1
- package/dist/common/llmUtils.d.ts.map +1 -1
- package/dist/server/package.json +3 -2
- package/dist/server/src/BackupManager/BackupManager.d.ts +0 -1
- package/dist/server/src/BackupManager/BackupManager.d.ts.map +1 -1
- package/dist/server/src/ConnectionManager/ConnectionManager.d.ts +1 -2
- package/dist/server/src/ConnectionManager/ConnectionManager.d.ts.map +1 -1
- package/dist/server/src/ConnectionManager/ConnectionManager.js +9 -5
- package/dist/server/src/ConnectionManager/ConnectionManager.js.map +1 -1
- package/dist/server/src/ConnectionManager/connectionManagerUtils.d.ts +0 -4
- package/dist/server/src/ConnectionManager/connectionManagerUtils.d.ts.map +1 -1
- package/dist/server/src/ConnectionManager/connectionManagerUtils.js +1 -8
- package/dist/server/src/ConnectionManager/connectionManagerUtils.js.map +1 -1
- package/dist/server/src/ConnectionManager/getHotReloadConfigs.d.ts.map +1 -1
- package/dist/server/src/ConnectionManager/initConnectionManager.js +1 -1
- package/dist/server/src/ConnectionManager/initConnectionManager.js.map +1 -1
- package/dist/server/src/ConnectionManager/startConnection.d.ts.map +1 -1
- package/dist/server/src/ConnectionManager/startConnection.js +1 -5
- package/dist/server/src/ConnectionManager/startConnection.js.map +1 -1
- package/dist/server/src/McpHub/DockerSandbox/getDockerRunArgs.d.ts.map +1 -1
- package/dist/server/src/McpHub/DockerSandbox/getDockerRunArgs.js +4 -2
- package/dist/server/src/McpHub/DockerSandbox/getDockerRunArgs.js.map +1 -1
- package/dist/server/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/definitionValidation/validateAgenticWorkflowDefinitions.d.ts.map +1 -1
- package/dist/server/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/proxyHandlers/createWorkflowExecutionHandlers.d.ts.map +1 -1
- package/dist/server/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/proxyHandlers/getAgentConfigWithDefaults.d.ts.map +1 -1
- package/dist/server/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/proxyHandlers/setupOrchestrationToolPermissions.d.ts.map +1 -1
- package/dist/server/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/WebDev/tools/getWebDevChatAndConnection.d.ts +0 -1
- package/dist/server/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/WebDev/tools/getWebDevChatAndConnection.d.ts.map +1 -1
- package/dist/server/src/authConfig/sessionUtils.d.ts.map +1 -1
- package/dist/server/src/authConfig/subscribeToAuthSetupChanges.d.ts.map +1 -1
- package/dist/server/src/cli/cli.js +19 -1
- package/dist/server/src/cli/cli.js.map +1 -1
- package/dist/server/src/cli/cliUtils.d.ts +1 -0
- package/dist/server/src/cli/cliUtils.d.ts.map +1 -1
- package/dist/server/src/cli/cliUtils.js +5 -0
- package/dist/server/src/cli/cliUtils.js.map +1 -1
- package/dist/server/src/connectionUtils/testDBConnection.d.ts +1 -1
- package/dist/server/src/connectionUtils/testDBConnection.d.ts.map +1 -1
- package/dist/server/src/connectionUtils/testDBConnection.js +12 -9
- package/dist/server/src/connectionUtils/testDBConnection.js.map +1 -1
- package/dist/server/src/createHttpAndIOServers/getCorsOptions.d.ts.map +1 -1
- package/dist/server/src/createHttpAndIOServers/getCorsOptions.js +4 -0
- package/dist/server/src/createHttpAndIOServers/getCorsOptions.js.map +1 -1
- package/dist/server/src/init/initUsers.d.ts.map +1 -1
- package/dist/server/src/init/saveTypescriptFilesForProduction.d.ts.map +1 -1
- package/dist/server/src/init/saveTypescriptFilesForProduction.js +3 -1
- package/dist/server/src/init/saveTypescriptFilesForProduction.js.map +1 -1
- package/dist/server/src/init/startProstgles.d.ts.map +1 -1
- package/dist/server/src/init/startProstgles.js +5 -2
- package/dist/server/src/init/startProstgles.js.map +1 -1
- package/dist/server/src/publish/getPublishLLM.d.ts.map +1 -1
- package/dist/server/src/publish/getPublishLlmChats.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getAdminServerFunctions.d.ts +0 -10
- package/dist/server/src/serverFunctions/adminServerFunctions/getAdminServerFunctions.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getAdminServerFunctions.js +0 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getAdminServerFunctions.js.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getAgenticWorkflowFunctions.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getBackupServerFunctions.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getDefineAdminFunction.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getMcpServerFunctions.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/getWebAppServerFunctions.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/webApp/getTemplatedWebAppConnection.d.ts +0 -1
- package/dist/server/src/serverFunctions/adminServerFunctions/webApp/getTemplatedWebAppConnection.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/applySampleSchema.d.ts +0 -1
- package/dist/server/src/serverFunctions/applySampleSchema.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/askLLM/askLLM.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/askLLM/getPastMessages.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/askLLM/getValidatedAskLLMChatOptions.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/askLLM/handleToolUseResultConfirmation.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/askLLM/prostglesLLMTools/getMCPServerTools.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/askLLM/prostglesLLMTools/getMcpToolsWithDynamicDescription.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/deleteConnection.d.ts +0 -1
- package/dist/server/src/serverFunctions/deleteConnection.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/getConnectionAndDatabaseConfig.d.ts +0 -1
- package/dist/server/src/serverFunctions/getConnectionAndDatabaseConfig.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/getServerFunctions.d.ts +0 -10
- package/dist/server/src/serverFunctions/getServerFunctions.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/getServerFunctionsContext.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/userServerFunctions/getLLMAccessParams.d.ts.map +1 -1
- package/dist/server/src/serverFunctions/userServerFunctions/getUserServerFunctions.d.ts.map +1 -1
- package/dist/server/src/tableConfig/tableConfigConnections.d.ts.map +1 -1
- package/dist/server/src/tableConfig/tableConfigConnections.js +0 -6
- package/dist/server/src/tableConfig/tableConfigConnections.js.map +1 -1
- package/dist/server/src/upsertConnection.d.ts +0 -1
- package/dist/server/src/upsertConnection.d.ts.map +1 -1
- package/package.json +3 -2
- package/sample_schemas/crypto/tsconfig.json +4 -0
- package/sample_schemas/food_delivery/tsconfig.json +1 -1
- package/sample_schemas/property_management/tsconfig.json +1 -1
- package/sample_schemas/weather/tsconfig.json +1 -1
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/addInstrumentationToTsLogic.ts +350 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/callWorkflowProxy.ts +99 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/defineAgenticWorkflow.spec.ts +110 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/defineAgenticWorkflow.ts +576 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/defineAgenticWorkflowHandlers.ts +127 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/defineAgenticWorkflowHandlers.types.ts +72 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/definitionHandler.ts +104 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/ensureWorkflowIsExecuted.ts +53 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/getTsLogicSummary.ts +639 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/orchestrationToolHandlers.ts +55 -0
- package/src/McpHub/ProstglesMcpHub/ProstglesMCPServers/Prostgles/agenticWorkflow/runtimeSdk/tableHandlers.ts +108 -0
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
import { TableHandler } from "prostgles-types";
|
|
2
|
+
|
|
3
|
+
type PrimitiveType = "string" | "number" | "boolean" | "unknown";
|
|
4
|
+
|
|
5
|
+
type PrimitiveTypeWithArraysAndOptional = {
|
|
6
|
+
type: PrimitiveType | `${PrimitiveType}[]`;
|
|
7
|
+
optional?: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @example
|
|
12
|
+
* {
|
|
13
|
+
* summary: { type: "string", nullable: true },
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
export type PropertyType =
|
|
17
|
+
| PrimitiveTypeWithArraysAndOptional
|
|
18
|
+
/** Object */
|
|
19
|
+
| {
|
|
20
|
+
type: Record<string, PrimitiveTypeWithArraysAndOptional>;
|
|
21
|
+
optional?: boolean;
|
|
22
|
+
nullable?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** Array of objects */
|
|
25
|
+
| {
|
|
26
|
+
arrayOfType: Record<string, PrimitiveTypeWithArraysAndOptional>;
|
|
27
|
+
optional?: boolean;
|
|
28
|
+
nullable?: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Use get_specific_tool_schemas tool to get the full definitions of mcp functions that go into McpServerToolDefinitions
|
|
33
|
+
*/
|
|
34
|
+
type McpServerToolDefinitions = Record<
|
|
35
|
+
string,
|
|
36
|
+
Record<string, (toolArguments?: unknown) => Promise<unknown>>
|
|
37
|
+
>;
|
|
38
|
+
// type McpServerToolDefinitions = {
|
|
39
|
+
// web: {
|
|
40
|
+
// search: (args: { q: string }) => Promise<{ results: string[] }>;
|
|
41
|
+
// get_snapshot: (args: { url: string }) => Promise<{ snapshot: string }>;
|
|
42
|
+
// };
|
|
43
|
+
// };
|
|
44
|
+
//EndOfReplaceMcpServerToolDefinitions;
|
|
45
|
+
|
|
46
|
+
export type DBGeneratedSchema = Record<
|
|
47
|
+
string,
|
|
48
|
+
{ columns: Record<string, any> }
|
|
49
|
+
>; //EndOfDBGeneratedSchema;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Defines which tools can be used.
|
|
53
|
+
*
|
|
54
|
+
* Here for example we allow the "status" tool from the "github" MCP server:
|
|
55
|
+
* @example
|
|
56
|
+
* {
|
|
57
|
+
* github: {
|
|
58
|
+
* status: 1
|
|
59
|
+
* }
|
|
60
|
+
* }
|
|
61
|
+
*/
|
|
62
|
+
export type McpServerToolsAllowed = {
|
|
63
|
+
[McpServerName in keyof McpServerToolDefinitions]?: {
|
|
64
|
+
[ToolName in keyof McpServerToolDefinitions[McpServerName]]?: 1;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type AgentDefinition = {
|
|
69
|
+
prompt: string;
|
|
70
|
+
modelName?: string;
|
|
71
|
+
maxCostUSD?: number;
|
|
72
|
+
maxIterations?: number;
|
|
73
|
+
tools?: McpServerToolsAllowed;
|
|
74
|
+
maxTokens?: number;
|
|
75
|
+
temperature?: number;
|
|
76
|
+
outputSchema: Record<string, PropertyType>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
type PrimitiveMap = {
|
|
80
|
+
string: string;
|
|
81
|
+
number: number;
|
|
82
|
+
boolean: boolean;
|
|
83
|
+
null: null;
|
|
84
|
+
undefined: undefined;
|
|
85
|
+
unknown: unknown;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
type ParsePrimitive<S extends string> =
|
|
89
|
+
S extends keyof PrimitiveMap ? PrimitiveMap[S] : never;
|
|
90
|
+
|
|
91
|
+
type ParseUnion<S extends string> =
|
|
92
|
+
S extends `${infer L} | ${infer R}` ? ParsePrimitive<L> | ParseUnion<R>
|
|
93
|
+
: ParsePrimitive<S>;
|
|
94
|
+
|
|
95
|
+
type ParsePropertyType<P extends PropertyType> =
|
|
96
|
+
P extends PrimitiveTypeWithArraysAndOptional ? ParsePrimitiveField<P>
|
|
97
|
+
: P extends (
|
|
98
|
+
{
|
|
99
|
+
type: infer Obj extends Record<
|
|
100
|
+
string,
|
|
101
|
+
PrimitiveTypeWithArraysAndOptional
|
|
102
|
+
>;
|
|
103
|
+
}
|
|
104
|
+
) ?
|
|
105
|
+
ParseObjectFields<Obj>
|
|
106
|
+
: P extends (
|
|
107
|
+
{
|
|
108
|
+
arrayOfType: infer Obj extends Record<
|
|
109
|
+
string,
|
|
110
|
+
PrimitiveTypeWithArraysAndOptional
|
|
111
|
+
>;
|
|
112
|
+
}
|
|
113
|
+
) ?
|
|
114
|
+
ParseObjectFields<Obj>[]
|
|
115
|
+
: never;
|
|
116
|
+
|
|
117
|
+
type ParsePrimitiveField<T extends PrimitiveTypeWithArraysAndOptional> =
|
|
118
|
+
T["type"] extends `${infer Inner}[]` ? ParseUnion<Inner & string>[]
|
|
119
|
+
: ParseUnion<T["type"] & string>;
|
|
120
|
+
|
|
121
|
+
type ParseObjectFields<
|
|
122
|
+
T extends Record<string, PrimitiveTypeWithArraysAndOptional>,
|
|
123
|
+
> = {
|
|
124
|
+
[K in keyof T]: ParsePrimitiveField<T[K]>;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
type ParseSchema<S extends Record<string, PropertyType>> = {
|
|
128
|
+
[K in keyof S]: ParsePropertyType<S[K]>;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export type DetailedTableFilter = {
|
|
132
|
+
fieldName: string;
|
|
133
|
+
/**
|
|
134
|
+
* Defaults to $eq
|
|
135
|
+
*/
|
|
136
|
+
type?:
|
|
137
|
+
| "$ilike"
|
|
138
|
+
| "$like"
|
|
139
|
+
| "$nilike"
|
|
140
|
+
| "$nlike"
|
|
141
|
+
| "$between"
|
|
142
|
+
| "$gt"
|
|
143
|
+
| "$gte"
|
|
144
|
+
| "$lt"
|
|
145
|
+
| "$lte"
|
|
146
|
+
| "$eq"
|
|
147
|
+
| "$ne"
|
|
148
|
+
| "$in"
|
|
149
|
+
| "$nin"
|
|
150
|
+
| "@@.to_tsquery"
|
|
151
|
+
| "@@.plainto_tsquery"
|
|
152
|
+
| "@@.phraseto_tsquery"
|
|
153
|
+
| "@@.websearch_to_tsquery";
|
|
154
|
+
value: unknown;
|
|
155
|
+
};
|
|
156
|
+
export type DetailedTableFilterGroup =
|
|
157
|
+
| { $and: DetailedTableFilter[] }
|
|
158
|
+
| { $or: DetailedTableFilter[] };
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Defines a list of columns with either 1 (include) or 0 (exclude).
|
|
162
|
+
*/
|
|
163
|
+
type FieldFilter = "*" | Record<string, 1> | Record<string, 0>;
|
|
164
|
+
|
|
165
|
+
export const ALLOWED_DDL_STATEMENT_TYPES = [
|
|
166
|
+
"alter table",
|
|
167
|
+
"create index",
|
|
168
|
+
"create table",
|
|
169
|
+
"create view",
|
|
170
|
+
] as const;
|
|
171
|
+
|
|
172
|
+
export type DatabaseAccessDefinition =
|
|
173
|
+
| {
|
|
174
|
+
mode: "custom";
|
|
175
|
+
/**
|
|
176
|
+
* An sql statement that creates/alters tables the agent will interact with.
|
|
177
|
+
* Permissions for these tables MUST be defined in `tablePermissions`.
|
|
178
|
+
* This is preferred over providing access to the entire database (execute_sql mode) for better security.
|
|
179
|
+
* Only ALLOWED_DDL_STATEMENT_TYPES are allowed.
|
|
180
|
+
*/
|
|
181
|
+
ddlStatements?: string;
|
|
182
|
+
/**
|
|
183
|
+
* Defines the tables, columns and rows the agent can access. Only applicable if mode is "custom".
|
|
184
|
+
* The keys of the tablePermissions object must be the table names as they appear in the database, or as they will be created from ddlStatements.
|
|
185
|
+
* For irregular table names, the keys must contain the double quotes (quote_ident(tableName) result).
|
|
186
|
+
* Use "true" to allow all fields/filters for a command, or provide a more specific definition for better security.
|
|
187
|
+
* Avoid writing more rule info than necessary. For example, to allow selectingn all fields from all data just use "select: true" instead of defining all the fields and using "select: { fields: "*" }".
|
|
188
|
+
*/
|
|
189
|
+
tablePermissions: Record<
|
|
190
|
+
/**
|
|
191
|
+
* keyof DBGeneratedSchema or new table names from ddlStatements
|
|
192
|
+
* */
|
|
193
|
+
string,
|
|
194
|
+
{
|
|
195
|
+
select?:
|
|
196
|
+
| true
|
|
197
|
+
| {
|
|
198
|
+
/**
|
|
199
|
+
* Fields that can be selected. Use "*" to allow all fields
|
|
200
|
+
*/
|
|
201
|
+
fields: FieldFilter;
|
|
202
|
+
/**
|
|
203
|
+
* Conditions that must be met for a row to be selected.
|
|
204
|
+
* This is applied in addition to any filter provided in the find/count methods, and cannot be overridden
|
|
205
|
+
*/
|
|
206
|
+
forcedFilter?: DetailedTableFilterGroup;
|
|
207
|
+
};
|
|
208
|
+
insert?:
|
|
209
|
+
| true
|
|
210
|
+
| {
|
|
211
|
+
/**
|
|
212
|
+
* Fields that can be inserted into. Use "*" to allow all fields.
|
|
213
|
+
*/
|
|
214
|
+
fields: FieldFilter;
|
|
215
|
+
};
|
|
216
|
+
update?:
|
|
217
|
+
| true
|
|
218
|
+
| {
|
|
219
|
+
/**
|
|
220
|
+
* Fields that can be updated. Use "*" to allow all fields.
|
|
221
|
+
*/
|
|
222
|
+
fields: FieldFilter;
|
|
223
|
+
forcedFilter?: DetailedTableFilterGroup;
|
|
224
|
+
};
|
|
225
|
+
delete?:
|
|
226
|
+
| true
|
|
227
|
+
| {
|
|
228
|
+
forcedFilter?: DetailedTableFilterGroup;
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
>;
|
|
232
|
+
}
|
|
233
|
+
| {
|
|
234
|
+
mode: "execute_sql" | "execute_readonly_sql";
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
type DbTableHandler = {
|
|
238
|
+
[TableName in keyof DBGeneratedSchema]: TableHandler<
|
|
239
|
+
DBGeneratedSchema[TableName]["columns"],
|
|
240
|
+
DBGeneratedSchema
|
|
241
|
+
>;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* The table handlers below are only available if databaseAccessDefinitions are defined
|
|
246
|
+
* Must provide the correct data type in filters (do not provide a boolean if the column is a string, etc.)
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* db.my_table.find({ name: "John", age: { $gt: 30 } }, { orderBy: { key: "created", asc: false, nulls: "last" }, limit: 20, select: { id: 1, name: 1 } });
|
|
250
|
+
* db.my_table.insert({ email: "john@gmail.com", name: "John", age: 35 }, { returning: "*", onConflict: "DoUpdate" }); // Will update all non conflicting fields
|
|
251
|
+
* db.my_table.insert({ email: "john@gmail.com", name: "John", age: 35 }, { returning: { email: 1 }, onConflict: "DoNothing" });
|
|
252
|
+
* db.my_table.insert({ name: "John", age: 35 }, { returning: { id: 1 } });
|
|
253
|
+
* db.my_table.update({ name: "John" }, { age: 36 }, { returning: { id: 1 } });
|
|
254
|
+
* db.my_table.delete({ age: { $lt: 20 } }, { returning: "*" });
|
|
255
|
+
*
|
|
256
|
+
* A filter is defined as a MongoDB-like query object.
|
|
257
|
+
* Supported operators:
|
|
258
|
+
* - Comparison: $eq, $ne, $gt, $gte, $lt, $lte
|
|
259
|
+
* - Logical: $and, $or
|
|
260
|
+
* - Evaluation: $like, $ilike
|
|
261
|
+
* - Array: $in, $nin
|
|
262
|
+
* - Joins: $existsJoined: { [tableName]: TableFilter }
|
|
263
|
+
* For Example:
|
|
264
|
+
* {
|
|
265
|
+
* $and: [
|
|
266
|
+
* {
|
|
267
|
+
* $or: [
|
|
268
|
+
* { topic: { $in: ["Prostgles", "Postgres"] } },
|
|
269
|
+
* { summary: { $ilike: "%postgres%" } },
|
|
270
|
+
* { id: { $gt: 5 } },
|
|
271
|
+
* ]
|
|
272
|
+
* },
|
|
273
|
+
* { summary: { $ne: null } }
|
|
274
|
+
* ]
|
|
275
|
+
* }
|
|
276
|
+
*
|
|
277
|
+
* A table select definition is either "*" to select all fields, or an object with the field names as keys and 1 as values (to select) or 0 to exclude.
|
|
278
|
+
*
|
|
279
|
+
* {
|
|
280
|
+
* field1: 1,
|
|
281
|
+
* field2: 1,
|
|
282
|
+
* referencedTable: "*", // all fields from the referenced table will be included in an array under the "referencedTable" key
|
|
283
|
+
* }
|
|
284
|
+
*
|
|
285
|
+
* */
|
|
286
|
+
type TableHandlers<
|
|
287
|
+
AccessMode extends DatabaseAccessDefinition["mode"] | undefined,
|
|
288
|
+
> =
|
|
289
|
+
AccessMode extends "custom" | "execute_sql" | "execute_readonly_sql" ?
|
|
290
|
+
DbTableHandler
|
|
291
|
+
: never;
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Runs a raw SQL query.
|
|
295
|
+
* Prefer to use the table handlers above when possible, as they are safer.
|
|
296
|
+
* Only available if databaseAccessDefinitions.mode is "execute_sql" or "execute_readonly_sql".
|
|
297
|
+
*/
|
|
298
|
+
type SqlHandler<
|
|
299
|
+
AccessMode extends DatabaseAccessDefinition["mode"] | undefined,
|
|
300
|
+
> =
|
|
301
|
+
AccessMode extends "execute_sql" | "execute_readonly_sql" ?
|
|
302
|
+
(
|
|
303
|
+
sql: string,
|
|
304
|
+
params?: Record<string, any> | any[],
|
|
305
|
+
timeout?: number,
|
|
306
|
+
) => Promise<Record<string, unknown>[]>
|
|
307
|
+
: never;
|
|
308
|
+
|
|
309
|
+
type UserInputBase<T> = T & {
|
|
310
|
+
title: string;
|
|
311
|
+
optional?: boolean;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Prefer to use this over "custom" or "enum" to restrict the input and make it easier for the user to choose the correct value.
|
|
316
|
+
* If using folder/file type inputs then only use fs to read/write the files, do not use any other mcp tools for filesystem.
|
|
317
|
+
*/
|
|
318
|
+
export type UserInputItem =
|
|
319
|
+
| UserInputBase<{
|
|
320
|
+
/**
|
|
321
|
+
* A path to a file/folder from the local system that will be mounted to the container.
|
|
322
|
+
* The agent can read and write (using fs) depending on the accessMode value.
|
|
323
|
+
*/
|
|
324
|
+
type: "folder-path" | "file-path" | "file-or-folder-path";
|
|
325
|
+
accessMode: "read" | "read-write";
|
|
326
|
+
}>
|
|
327
|
+
| UserInputBase<{
|
|
328
|
+
/**
|
|
329
|
+
* Same as above but allows multiple paths to be provided. The agent will receive an array of paths.
|
|
330
|
+
*/
|
|
331
|
+
type: "folder-paths" | "file-paths" | "file-or-folder-paths";
|
|
332
|
+
accessMode: "read" | "read-write";
|
|
333
|
+
}>
|
|
334
|
+
| UserInputBase<{
|
|
335
|
+
type: "table-column-value";
|
|
336
|
+
tableName: string;
|
|
337
|
+
columnName: string;
|
|
338
|
+
defaultValue?: any;
|
|
339
|
+
}>
|
|
340
|
+
| UserInputBase<{
|
|
341
|
+
type: "table-column-values";
|
|
342
|
+
tableName: string;
|
|
343
|
+
columnName: string;
|
|
344
|
+
defaultValue?: any[];
|
|
345
|
+
}>
|
|
346
|
+
| UserInputBase<{
|
|
347
|
+
type: "enum";
|
|
348
|
+
values: string[];
|
|
349
|
+
defaultValue?: string;
|
|
350
|
+
}>
|
|
351
|
+
| UserInputBase<{
|
|
352
|
+
type: "table-filter";
|
|
353
|
+
tableName: string;
|
|
354
|
+
defaultValue?: Record<string, any>;
|
|
355
|
+
}>
|
|
356
|
+
| UserInputBase<{
|
|
357
|
+
type: "table-column";
|
|
358
|
+
tableName: string;
|
|
359
|
+
defaultValue?: string;
|
|
360
|
+
}>
|
|
361
|
+
| UserInputBase<{
|
|
362
|
+
type: "table-name";
|
|
363
|
+
defaultValue?: string;
|
|
364
|
+
}>
|
|
365
|
+
| UserInputBase<{
|
|
366
|
+
type: "table-and-column";
|
|
367
|
+
defaultValue?: { tableName: string; columnName: string };
|
|
368
|
+
}>
|
|
369
|
+
| UserInputBase<{
|
|
370
|
+
type: "custom";
|
|
371
|
+
dataType: "string" | "number" | "boolean" | "Date";
|
|
372
|
+
defaultValue?: unknown;
|
|
373
|
+
}>;
|
|
374
|
+
|
|
375
|
+
type UserInputOutputMappingCustom = {
|
|
376
|
+
string: string;
|
|
377
|
+
number: number;
|
|
378
|
+
boolean: boolean;
|
|
379
|
+
Date: Date;
|
|
380
|
+
};
|
|
381
|
+
export type UserInputOutputMapping<Input extends UserInputItem> =
|
|
382
|
+
Input extends { type: "enum" } ? Input["values"][number]
|
|
383
|
+
: Input extends { type: "custom" } ?
|
|
384
|
+
UserInputOutputMappingCustom[Input["dataType"]]
|
|
385
|
+
: {
|
|
386
|
+
"table-filter": Record<string, any>;
|
|
387
|
+
"table-and-column": { tableName: string; columnName: string };
|
|
388
|
+
"table-column-value": unknown;
|
|
389
|
+
"table-column-values": unknown[];
|
|
390
|
+
"table-name": string;
|
|
391
|
+
"table-column": string;
|
|
392
|
+
"folder-path": string;
|
|
393
|
+
"file-or-folder-path": string;
|
|
394
|
+
"file-path": string;
|
|
395
|
+
"folder-paths": string[];
|
|
396
|
+
"file-or-folder-paths": string[];
|
|
397
|
+
"file-paths": string[];
|
|
398
|
+
enum: unknown;
|
|
399
|
+
custom: unknown;
|
|
400
|
+
}[Input["type"]];
|
|
401
|
+
|
|
402
|
+
type OptionalInputKeys<U extends Record<string, UserInputItem>> = {
|
|
403
|
+
[K in keyof U]-?: U[K] extends { optional: true } ? K : never;
|
|
404
|
+
}[keyof U];
|
|
405
|
+
|
|
406
|
+
type RequiredInputKeys<U extends Record<string, UserInputItem>> = Exclude<
|
|
407
|
+
keyof U,
|
|
408
|
+
OptionalInputKeys<U>
|
|
409
|
+
>;
|
|
410
|
+
|
|
411
|
+
export type ValueOfUserInput<U extends Record<string, UserInputItem>> = {
|
|
412
|
+
[K in RequiredInputKeys<U>]: UserInputOutputMapping<U[K]>;
|
|
413
|
+
} & {
|
|
414
|
+
[K in OptionalInputKeys<U>]?: UserInputOutputMapping<U[K]>;
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
export type DefineAgenticWorkflow = <
|
|
418
|
+
OrchestrationTools extends McpServerToolsAllowed,
|
|
419
|
+
AgentDefinitions extends Record<string, AgentDefinition>,
|
|
420
|
+
UserInput extends Record<string, UserInputItem>,
|
|
421
|
+
DatabaseAccess extends DatabaseAccessDefinition | undefined = undefined,
|
|
422
|
+
>(
|
|
423
|
+
{
|
|
424
|
+
name,
|
|
425
|
+
containerConfiguration,
|
|
426
|
+
databaseAccessDefinitions,
|
|
427
|
+
agentDefinitions,
|
|
428
|
+
userInput,
|
|
429
|
+
}: {
|
|
430
|
+
name: string;
|
|
431
|
+
containerConfiguration: {
|
|
432
|
+
/**
|
|
433
|
+
* Maximum time in seconds the container will be allowed to run in milliseconds.
|
|
434
|
+
* Defaults to 30000.
|
|
435
|
+
*/
|
|
436
|
+
timeout: number;
|
|
437
|
+
/**
|
|
438
|
+
* CPU limit (e.g., '0.5', '1'). Defaults to 1
|
|
439
|
+
*/
|
|
440
|
+
cpus?: string;
|
|
441
|
+
/**
|
|
442
|
+
* Memory limit (e.g., '512m', '1g'). Defaults to 512m
|
|
443
|
+
*/
|
|
444
|
+
memory?: string;
|
|
445
|
+
environment?: Record<string, string>;
|
|
446
|
+
/**
|
|
447
|
+
* Whether to mount the filesystem as read-only. Defaults to true
|
|
448
|
+
*/
|
|
449
|
+
readOnly?: boolean;
|
|
450
|
+
/**
|
|
451
|
+
* Whether the container should have access to the internet.
|
|
452
|
+
* Defaults to 'none'.
|
|
453
|
+
* 'bridge' provides access to the internet through NAT, which is more secure than 'host' but may not work for all use cases.
|
|
454
|
+
* Do not use 'host' unless it is strictly necessary, as it can be a security risk.
|
|
455
|
+
* Prefer to use specific tools (web/playwright mcp) that provide the required functionality instead of granting full internet access when possible.
|
|
456
|
+
*/
|
|
457
|
+
internetAccess?: "none" | "bridge" | "host";
|
|
458
|
+
};
|
|
459
|
+
userInput?: UserInput;
|
|
460
|
+
databaseAccessDefinitions?: DatabaseAccess;
|
|
461
|
+
orchestrationTools?: OrchestrationTools;
|
|
462
|
+
agentDefinitions?: AgentDefinitions;
|
|
463
|
+
},
|
|
464
|
+
workflow: (args: {
|
|
465
|
+
tableHandlers: TableHandlers<
|
|
466
|
+
DatabaseAccess extends { mode: infer M } ? M : undefined
|
|
467
|
+
>;
|
|
468
|
+
runSQL: SqlHandler<
|
|
469
|
+
DatabaseAccess extends { mode: infer M } ? M : undefined
|
|
470
|
+
>;
|
|
471
|
+
agentHandlers: AgentDefinitions extends Record<string, AgentDefinition> ?
|
|
472
|
+
{
|
|
473
|
+
[AgentName in keyof AgentDefinitions]: (
|
|
474
|
+
agentInput?: string,
|
|
475
|
+
) => Promise<ParseSchema<AgentDefinitions[AgentName]["outputSchema"]>>;
|
|
476
|
+
}
|
|
477
|
+
: undefined;
|
|
478
|
+
orchestratorToolHandlers: {
|
|
479
|
+
[ServerName in keyof OrchestrationTools]: {
|
|
480
|
+
[ToolName in keyof OrchestrationTools[ServerName]]: ServerName extends (
|
|
481
|
+
keyof McpServerToolDefinitions
|
|
482
|
+
) ?
|
|
483
|
+
ToolName extends keyof McpServerToolDefinitions[ServerName] ?
|
|
484
|
+
McpServerToolDefinitions[ServerName][ToolName]
|
|
485
|
+
: never
|
|
486
|
+
: never;
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
userInputValues: ValueOfUserInput<UserInput>;
|
|
490
|
+
setProgress: (progressPercent: number, message?: string) => Promise<void>;
|
|
491
|
+
}) => Promise<void>,
|
|
492
|
+
) => void | Promise<void>;
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Example usage:
|
|
496
|
+
*
|
|
497
|
+
import { defineAgenticWorkflow } from "./defineAgenticWorkflow";
|
|
498
|
+
void defineAgenticWorkflow(
|
|
499
|
+
{
|
|
500
|
+
name: "Test Workflow",
|
|
501
|
+
containerConfiguration: { timeout: 60_000 },
|
|
502
|
+
databaseAccessDefinitions: {
|
|
503
|
+
mode: "custom",
|
|
504
|
+
tablePermissions: {
|
|
505
|
+
'"MyUsers"': { select: true, insert: true, update: true },
|
|
506
|
+
my_research_topics: { select: true, insert: true, update: true },
|
|
507
|
+
},
|
|
508
|
+
ddlStatements: `
|
|
509
|
+
CREATE TABLE IF NOT EXISTS my_research_topics (
|
|
510
|
+
id SERIAL PRIMARY KEY,
|
|
511
|
+
topic TEXT NOT NULL,
|
|
512
|
+
summary TEXT,
|
|
513
|
+
references TEXT[]
|
|
514
|
+
);
|
|
515
|
+
`,
|
|
516
|
+
},
|
|
517
|
+
orchestrationTools: {
|
|
518
|
+
web: { search: 1, get_snapshot: 1 },
|
|
519
|
+
},
|
|
520
|
+
agentDefinitions: {
|
|
521
|
+
researcher: {
|
|
522
|
+
prompt: "You are a research assistant.",
|
|
523
|
+
tools: { web: { fetch: 1 } },
|
|
524
|
+
outputSchema: {
|
|
525
|
+
summary: { type: "string" },
|
|
526
|
+
references: { type: "string[]" },
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
userInput: {
|
|
531
|
+
documentsFolder: {
|
|
532
|
+
title: "Documents Folder",
|
|
533
|
+
type: "folder-path",
|
|
534
|
+
accessMode: "read-write",
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
async ({ agentHandlers: { researcher }, tableHandlers, orchestrationTools: { web } }) => {
|
|
539
|
+
|
|
540
|
+
const doResearch = async () => {
|
|
541
|
+
const result = await researcher(`research_topic: "Prostgles"`);
|
|
542
|
+
await tableHandlers.my_research_topics.insert({
|
|
543
|
+
topic: "Prostgles",
|
|
544
|
+
summary: result.summary,
|
|
545
|
+
references: result.references,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
await doResearch();
|
|
549
|
+
|
|
550
|
+
const finalTopics = await tableHandlers.my_research_topics.find({
|
|
551
|
+
$and: [
|
|
552
|
+
{
|
|
553
|
+
$or: [
|
|
554
|
+
{ topic: { $in: ["Prostgles", "Postgres"] } },
|
|
555
|
+
{ summary: { $ilike: "%postgres%" } },
|
|
556
|
+
{ id: { $gt: 5 } },
|
|
557
|
+
]
|
|
558
|
+
},
|
|
559
|
+
{ summary: { $ne: null } }
|
|
560
|
+
]
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
if(finalTopics.length < 10) {
|
|
564
|
+
await doResearch();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
await web.search({ q: "Prostgles" });
|
|
568
|
+
},
|
|
569
|
+
);
|
|
570
|
+
|
|
571
|
+
*/
|
|
572
|
+
|
|
573
|
+
export const END_OF_SCHEMA_PLACEHOLDER =
|
|
574
|
+
"export const END_OF_SCHEMA_PLACEHOLDER =";
|
|
575
|
+
|
|
576
|
+
export { defineAgenticWorkflow } from "./defineAgenticWorkflowHandlers";
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { callWorkflowProxy } from "./callWorkflowProxy";
|
|
2
|
+
import type { DefineAgenticWorkflow } from "./defineAgenticWorkflow";
|
|
3
|
+
import { WORKFLOW_ENV_VARS } from "./defineAgenticWorkflowHandlers.types";
|
|
4
|
+
import { definitionHandler } from "./definitionHandler";
|
|
5
|
+
import { assertWorkflowStarted } from "./ensureWorkflowIsExecuted";
|
|
6
|
+
import { getOrchestrationToolHandlers } from "./orchestrationToolHandlers";
|
|
7
|
+
import { tableHandlers } from "./tableHandlers";
|
|
8
|
+
|
|
9
|
+
const { DOCKER_MCP_ENDPOINT, MODE, USER_INPUT, EXECUTION_MODE } =
|
|
10
|
+
WORKFLOW_ENV_VARS;
|
|
11
|
+
|
|
12
|
+
const runState = { wasStarted: false };
|
|
13
|
+
assertWorkflowStarted(runState);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Execute agent invocations in series to reduce risk of avoid runaway costs and allow for human feedback between steps.
|
|
17
|
+
*/
|
|
18
|
+
export const createQueue = () => {
|
|
19
|
+
let agentExecutionChain: Promise<void> = Promise.resolve();
|
|
20
|
+
|
|
21
|
+
const enqueueAgentExecution = <T>(
|
|
22
|
+
agentExecution: () => Promise<T>,
|
|
23
|
+
): Promise<T> => {
|
|
24
|
+
const executionPromise = agentExecutionChain.then(agentExecution);
|
|
25
|
+
agentExecutionChain = executionPromise.catch(() => {}) as Promise<void>;
|
|
26
|
+
return executionPromise;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
enqueueAgentExecution,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const defineAgenticWorkflow: DefineAgenticWorkflow = async (
|
|
35
|
+
definitions,
|
|
36
|
+
handler,
|
|
37
|
+
) => {
|
|
38
|
+
runState.wasStarted = true;
|
|
39
|
+
|
|
40
|
+
if (!["series", "parallel"].includes(EXECUTION_MODE ?? "")) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Invalid EXECUTION_MODE environment variable: ${EXECUTION_MODE}. Must be either "series" or "parallel".`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!DOCKER_MCP_ENDPOINT) {
|
|
47
|
+
throw new Error("DOCKER_MCP_ENDPOINT environment variable is not set");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type ArgsObject = Parameters<typeof handler>[0];
|
|
51
|
+
if (!USER_INPUT) {
|
|
52
|
+
throw new Error("USER_INPUT environment variable is not set");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const userInputValues = JSON.parse(
|
|
56
|
+
USER_INPUT,
|
|
57
|
+
) as ArgsObject["userInputValues"];
|
|
58
|
+
|
|
59
|
+
if (MODE === "definitions-only") {
|
|
60
|
+
return definitionHandler(definitions);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { enqueueAgentExecution } = createQueue();
|
|
64
|
+
|
|
65
|
+
const agentHandlersProxy = new Proxy({} as ArgsObject["agentHandlers"], {
|
|
66
|
+
get(_target, prop: string) {
|
|
67
|
+
if (typeof prop !== "string") return undefined;
|
|
68
|
+
if (!definitions.agentDefinitions) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`No agents are defined for this workflow, but tried to access agent "${prop}"`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
if (!(prop in definitions.agentDefinitions)) {
|
|
74
|
+
throw new Error(`Agent "${prop}" is not defined in agentDefinitions`);
|
|
75
|
+
}
|
|
76
|
+
return (input: string) => {
|
|
77
|
+
if (EXECUTION_MODE === "series") {
|
|
78
|
+
/** The queue is done inside this sdk runtime to improve the activity items timings/order */
|
|
79
|
+
return enqueueAgentExecution(() => {
|
|
80
|
+
return callWorkflowProxy({ type: "agent", agentName: prop, input });
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return callWorkflowProxy({ type: "agent", agentName: prop, input });
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const accessMode = definitions.databaseAccessDefinitions?.mode;
|
|
89
|
+
|
|
90
|
+
const setProgress = (percent: number, message = "") => {
|
|
91
|
+
return callWorkflowProxy({
|
|
92
|
+
type: "progress",
|
|
93
|
+
percent,
|
|
94
|
+
message,
|
|
95
|
+
}).catch((err) => {
|
|
96
|
+
console.error("Failed to set progress:", err);
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return handler({
|
|
101
|
+
agentHandlers: agentHandlersProxy,
|
|
102
|
+
tableHandlers: tableHandlers as ArgsObject["tableHandlers"],
|
|
103
|
+
runSQL: ((sql, query_params, query_timeout) => {
|
|
104
|
+
if (
|
|
105
|
+
accessMode !== "execute_sql" &&
|
|
106
|
+
accessMode !== "execute_readonly_sql"
|
|
107
|
+
) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Database access is not enabled for this workflow, but tried to run SQL with args: ${JSON.stringify(
|
|
110
|
+
sql,
|
|
111
|
+
)}`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return callWorkflowProxy({
|
|
115
|
+
type: `db/${accessMode}` as const,
|
|
116
|
+
sql,
|
|
117
|
+
query_params,
|
|
118
|
+
query_timeout,
|
|
119
|
+
});
|
|
120
|
+
}) as ArgsObject["runSQL"],
|
|
121
|
+
orchestratorToolHandlers: getOrchestrationToolHandlers(
|
|
122
|
+
definitions,
|
|
123
|
+
) as ArgsObject["orchestratorToolHandlers"],
|
|
124
|
+
userInputValues,
|
|
125
|
+
setProgress,
|
|
126
|
+
});
|
|
127
|
+
};
|