@auxx/sdk 0.0.12 → 0.0.13
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/lib/api/api.js +2 -1
- package/lib/api/schemas.js +1 -0
- package/lib/build/server/find-tool-server-modules.js +279 -0
- package/lib/build/server/find-workflow-block-server-modules.js +10 -2
- package/lib/build/server/generate-server-entry.js +46 -1
- package/lib/build/server/zod-to-provider-tool-schema.js +42 -0
- package/lib/client/workflow/index.d.ts +1 -1
- package/lib/client/workflow/index.d.ts.map +1 -1
- package/lib/commands/dev/bundle-javascript.js +17 -1
- package/lib/commands/dev/prepare-build-context.js +11 -2
- package/lib/commands/dev/server-builder.js +2 -1
- package/lib/commands/dev/upload.js +5 -1
- package/lib/commands/dev.js +2 -1
- package/lib/commands/version/create/bundle-javascript.js +4 -0
- package/lib/commands/version/create.js +5 -1
- package/lib/env-loader.js +17 -1
- package/lib/root/app.d.ts +5 -2
- package/lib/root/app.d.ts.map +1 -1
- package/lib/root/index.d.ts +4 -2
- package/lib/root/index.d.ts.map +1 -1
- package/lib/root/index.js +2 -1
- package/lib/root/tools/define-tool.d.ts +4 -0
- package/lib/root/tools/define-tool.d.ts.map +1 -0
- package/lib/root/tools/define-tool.js +7 -0
- package/lib/root/tools/index.d.ts +5 -0
- package/lib/root/tools/index.d.ts.map +1 -0
- package/lib/root/tools/index.js +3 -0
- package/lib/root/tools/refs.d.ts +9 -0
- package/lib/root/tools/refs.d.ts.map +1 -0
- package/lib/root/tools/refs.js +4 -0
- package/lib/root/tools/types.d.ts +97 -0
- package/lib/root/tools/types.d.ts.map +1 -0
- package/lib/root/tools/types.js +1 -0
- package/lib/root/workflow/types.d.ts +27 -14
- package/lib/root/workflow/types.d.ts.map +1 -1
- package/lib/root/workflow/types.js +3 -0
- package/lib/root/workflow/utils.d.ts +4 -4
- package/lib/root/workflow/utils.d.ts.map +1 -1
- package/lib/runtime/workflow.js +17 -0
- package/lib/server/connections.d.ts +1 -0
- package/lib/server/connections.d.ts.map +1 -1
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.d.ts.map +1 -1
- package/lib/shared/errors.d.ts +4 -0
- package/lib/shared/errors.d.ts.map +1 -1
- package/lib/shared/errors.js +8 -0
- package/lib/shared/index.d.ts +1 -1
- package/lib/shared/index.d.ts.map +1 -1
- package/lib/shared/index.js +1 -1
- package/lib/util/compile-and-extract-catalog.js +279 -0
- package/package.json +5 -1
package/lib/api/api.js
CHANGED
|
@@ -123,7 +123,7 @@ class ApiImpl {
|
|
|
123
123
|
}
|
|
124
124
|
return complete(result.value);
|
|
125
125
|
}
|
|
126
|
-
async createDeployment({ appId, clientBundleSha, serverBundleSha, deploymentType, settingsSchema, targetOrganizationId, environmentVariables, version, metadata, }) {
|
|
126
|
+
async createDeployment({ appId, clientBundleSha, serverBundleSha, deploymentType, settingsSchema, catalog, targetOrganizationId, environmentVariables, version, metadata, }) {
|
|
127
127
|
const result = await this.fetcher.post({
|
|
128
128
|
path: `/api/v1/apps/${appId}/deployments`,
|
|
129
129
|
body: {
|
|
@@ -131,6 +131,7 @@ class ApiImpl {
|
|
|
131
131
|
serverBundleSha,
|
|
132
132
|
deploymentType,
|
|
133
133
|
settingsSchema,
|
|
134
|
+
catalog,
|
|
134
135
|
targetOrganizationId,
|
|
135
136
|
environmentVariables,
|
|
136
137
|
version,
|
package/lib/api/schemas.js
CHANGED
|
@@ -38,6 +38,7 @@ const appDataSchema = z.object({
|
|
|
38
38
|
avatarId: z.string().nullable().optional(),
|
|
39
39
|
avatarUrl: z.string().nullable().optional(),
|
|
40
40
|
category: z.string().nullable().optional(),
|
|
41
|
+
verified: z.boolean().optional(),
|
|
41
42
|
createdAt: z.string().or(z.date()),
|
|
42
43
|
updatedAt: z.string().or(z.date()),
|
|
43
44
|
});
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { parse } from '@typescript-eslint/parser';
|
|
3
|
+
import { analyze } from '@typescript-eslint/scope-manager';
|
|
4
|
+
import { walk } from 'zimmerframe';
|
|
5
|
+
import { complete, errored } from '../../errors.js';
|
|
6
|
+
import { getAppEntryPoint } from '../../util/get-app-entry-point.js';
|
|
7
|
+
function checkPath(path, doesModuleExist) {
|
|
8
|
+
return doesModuleExist(path) ? path : null;
|
|
9
|
+
}
|
|
10
|
+
function resolvePathWithExtension(path, doesModuleExist) {
|
|
11
|
+
return (checkPath(path + '.ts', doesModuleExist) ||
|
|
12
|
+
checkPath(path + '.tsx', doesModuleExist) ||
|
|
13
|
+
checkPath(path + '.js', doesModuleExist));
|
|
14
|
+
}
|
|
15
|
+
function resolveAbsolutePath(sourcePath, currPath) {
|
|
16
|
+
if (sourcePath.startsWith('.')) {
|
|
17
|
+
const currDir = currPath.split('/').slice(0, -1).join('/');
|
|
18
|
+
const combinedPath = currDir + '/' + sourcePath;
|
|
19
|
+
const parts = combinedPath.split('/');
|
|
20
|
+
const resolvedParts = [];
|
|
21
|
+
for (const part of parts) {
|
|
22
|
+
if (part === '..') {
|
|
23
|
+
resolvedParts.pop();
|
|
24
|
+
}
|
|
25
|
+
else if (part !== '.') {
|
|
26
|
+
resolvedParts.push(part);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return resolvedParts.join('/');
|
|
30
|
+
}
|
|
31
|
+
return sourcePath;
|
|
32
|
+
}
|
|
33
|
+
function unwrapTypeAnnotations(node) {
|
|
34
|
+
while (node) {
|
|
35
|
+
if (node.type === 'TSSatisfiesExpression' || node.type === 'TSAsExpression') {
|
|
36
|
+
node = node.expression;
|
|
37
|
+
}
|
|
38
|
+
else if (node.type === 'TSTypeAssertion') {
|
|
39
|
+
node = node.expression;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return node;
|
|
46
|
+
}
|
|
47
|
+
function resolveIdentifierToValue(node, scope) {
|
|
48
|
+
const variable = scope.set.get(node.name);
|
|
49
|
+
if (!variable) {
|
|
50
|
+
throw new Error(`Unable to find variable ${node.name} in scope`);
|
|
51
|
+
}
|
|
52
|
+
if (variable.defs.length !== 1) {
|
|
53
|
+
throw new Error(`Expected exactly one definition for variable ${node.name}, found ${variable.defs.length}`);
|
|
54
|
+
}
|
|
55
|
+
const def = variable.defs[0];
|
|
56
|
+
if (!def)
|
|
57
|
+
return null;
|
|
58
|
+
if (def.node.type === 'VariableDeclarator')
|
|
59
|
+
return def.node.init;
|
|
60
|
+
if (def.type === 'ImportBinding')
|
|
61
|
+
return def;
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function loadModule(sourcePath, currPath, helpers) {
|
|
65
|
+
const absolutePath = resolveAbsolutePath(sourcePath, currPath);
|
|
66
|
+
const fullPath = resolvePathWithExtension(absolutePath, helpers.doesModuleExist);
|
|
67
|
+
if (!fullPath) {
|
|
68
|
+
throw new Error(`Unable to resolve path for module ${sourcePath} from ${currPath}`);
|
|
69
|
+
}
|
|
70
|
+
if (helpers.modules.has(fullPath)) {
|
|
71
|
+
return helpers.modules.get(fullPath);
|
|
72
|
+
}
|
|
73
|
+
const content = helpers.getModuleSource(fullPath);
|
|
74
|
+
const ast = parse(content, { range: true, jsx: true });
|
|
75
|
+
const scopeManager = analyze(ast, { sourceType: 'module' });
|
|
76
|
+
const moduleScope = scopeManager.acquire(ast, true);
|
|
77
|
+
const namedExports = new Map();
|
|
78
|
+
const module = { content, ast, scope: moduleScope, namedExports, path: fullPath };
|
|
79
|
+
helpers.modules.set(fullPath, module);
|
|
80
|
+
walk(ast, null, {
|
|
81
|
+
ExportNamedDeclaration(node) {
|
|
82
|
+
if (node.declaration?.type === 'VariableDeclaration' &&
|
|
83
|
+
node.declaration.declarations.length === 1 &&
|
|
84
|
+
node.declaration.declarations[0].type === 'VariableDeclarator' &&
|
|
85
|
+
node.declaration.declarations[0].id.type === 'Identifier') {
|
|
86
|
+
const declaration = node.declaration.declarations[0];
|
|
87
|
+
namedExports.set(declaration.id.name, declaration.init);
|
|
88
|
+
}
|
|
89
|
+
if (node?.specifiers && moduleScope) {
|
|
90
|
+
for (const specifier of node.specifiers) {
|
|
91
|
+
if (specifier.type === 'ExportSpecifier' &&
|
|
92
|
+
specifier.exported.type === 'Identifier' &&
|
|
93
|
+
specifier.local.type === 'Identifier') {
|
|
94
|
+
if (node.source !== null) {
|
|
95
|
+
namedExports.set(specifier.exported.name, node);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const resolved = resolveIdentifierToValue(specifier.local, moduleScope);
|
|
99
|
+
if (resolved)
|
|
100
|
+
namedExports.set(specifier.exported.name, resolved);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
ExportDefaultDeclaration(node) {
|
|
107
|
+
if (node.declaration) {
|
|
108
|
+
if (node.declaration.type === 'FunctionDeclaration' ||
|
|
109
|
+
node.declaration.type === 'ArrowFunctionExpression' ||
|
|
110
|
+
node.declaration.type === 'FunctionExpression') {
|
|
111
|
+
namedExports.set('default', node.declaration);
|
|
112
|
+
}
|
|
113
|
+
else if (node.declaration.type === 'Identifier' && moduleScope) {
|
|
114
|
+
const resolved = resolveIdentifierToValue(node.declaration, moduleScope);
|
|
115
|
+
if (resolved)
|
|
116
|
+
namedExports.set('default', resolved);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
return module;
|
|
122
|
+
}
|
|
123
|
+
function captureExecuteRef(toolId, node, scope, currPath, helpers) {
|
|
124
|
+
let importValue = node.type === 'Identifier' ? resolveIdentifierToValue(node, scope) : node;
|
|
125
|
+
if (!importValue) {
|
|
126
|
+
throw new Error(`Tool '${toolId}': unable to resolve 'execute'`);
|
|
127
|
+
}
|
|
128
|
+
importValue = unwrapTypeAnnotations(importValue);
|
|
129
|
+
const isInlineFunction = importValue.type === 'ArrowFunctionExpression' ||
|
|
130
|
+
importValue.type === 'FunctionExpression' ||
|
|
131
|
+
importValue.type === 'FunctionDeclaration';
|
|
132
|
+
if (isInlineFunction) {
|
|
133
|
+
throw new Error(`Tool '${toolId}': 'execute' must be imported from a separate .server.ts file. ` +
|
|
134
|
+
`Inline server functions are not allowed.`);
|
|
135
|
+
}
|
|
136
|
+
if (importValue.type !== 'ImportBinding' && importValue.type !== 'ExportNamedDeclaration') {
|
|
137
|
+
throw new Error(`Tool '${toolId}': 'execute' must be imported from another file. Found ${importValue.type}.`);
|
|
138
|
+
}
|
|
139
|
+
const importDeclaration = importValue.type === 'ExportNamedDeclaration' ? importValue : importValue.parent;
|
|
140
|
+
const sourcePath = importDeclaration.source.value;
|
|
141
|
+
const isServerFile = sourcePath.endsWith('.server') ||
|
|
142
|
+
sourcePath.endsWith('.server.ts') ||
|
|
143
|
+
sourcePath.endsWith('.server.tsx') ||
|
|
144
|
+
sourcePath.endsWith('.server.js');
|
|
145
|
+
if (!isServerFile) {
|
|
146
|
+
throw new Error(`Tool '${toolId}': 'execute' must be imported from a .server.ts file (got '${sourcePath}').`);
|
|
147
|
+
}
|
|
148
|
+
if (importValue.type === 'ImportBinding') {
|
|
149
|
+
const specifier = importDeclaration.specifiers.find((s) => s.local && s.local.name === importValue.name.name);
|
|
150
|
+
if (specifier && specifier.type !== 'ImportDefaultSpecifier') {
|
|
151
|
+
throw new Error(`Tool '${toolId}': 'execute' must be imported as a default export from '${sourcePath}'.`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
let absolutePath = resolveAbsolutePath(sourcePath, currPath);
|
|
155
|
+
absolutePath = resolvePathWithExtension(absolutePath, helpers.doesModuleExist) || absolutePath;
|
|
156
|
+
return { path: absolutePath, export: 'default' };
|
|
157
|
+
}
|
|
158
|
+
function visitTool(node, scope, result, currPath, helpers) {
|
|
159
|
+
if (node.type === 'Identifier') {
|
|
160
|
+
let targetScope = scope;
|
|
161
|
+
let value = resolveIdentifierToValue(node, scope);
|
|
162
|
+
let targetPath = currPath;
|
|
163
|
+
if (value?.type === 'ImportBinding') {
|
|
164
|
+
const importDeclaration = value.parent;
|
|
165
|
+
const module = loadModule(importDeclaration.source.value, currPath, helpers);
|
|
166
|
+
const local = value.name.name;
|
|
167
|
+
const specifier = importDeclaration.specifiers.find((s) => s.local && s.local.name === local);
|
|
168
|
+
const name = specifier?.imported?.name ?? 'default';
|
|
169
|
+
if (!module.namedExports.has(name)) {
|
|
170
|
+
throw new Error(`Unable to find named export ${name} in module ${importDeclaration.source.value}`);
|
|
171
|
+
}
|
|
172
|
+
value = module.namedExports.get(name) ?? null;
|
|
173
|
+
if (module.scope)
|
|
174
|
+
targetScope = module.scope;
|
|
175
|
+
targetPath = module.path;
|
|
176
|
+
}
|
|
177
|
+
value = value ? unwrapTypeAnnotations(value) : null;
|
|
178
|
+
if (!value) {
|
|
179
|
+
throw new Error(`Tool ${node.name}: expected initializer`);
|
|
180
|
+
}
|
|
181
|
+
if (value.type === 'CallExpression') {
|
|
182
|
+
visitTool(value.arguments[0], targetScope, result, targetPath, helpers);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (value.type !== 'ObjectExpression') {
|
|
186
|
+
throw new Error(`Tool ${node.name}: expected ObjectExpression, got ${value.type}`);
|
|
187
|
+
}
|
|
188
|
+
visitTool(value, targetScope, result, targetPath, helpers);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (node.type === 'CallExpression') {
|
|
192
|
+
visitTool(node.arguments[0], scope, result, currPath, helpers);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (node.type === 'ObjectExpression') {
|
|
196
|
+
let id;
|
|
197
|
+
let execute = null;
|
|
198
|
+
for (const property of node.properties) {
|
|
199
|
+
if (property.type !== 'Property' || property.key.type !== 'Identifier')
|
|
200
|
+
continue;
|
|
201
|
+
const name = property.key.name;
|
|
202
|
+
if (name === 'id') {
|
|
203
|
+
if (property.value.type !== 'Literal' || typeof property.value.value !== 'string') {
|
|
204
|
+
throw new Error(`Tool: 'id' must be a string literal`);
|
|
205
|
+
}
|
|
206
|
+
id = property.value.value;
|
|
207
|
+
}
|
|
208
|
+
else if (name === 'execute') {
|
|
209
|
+
execute = captureExecuteRef(id ?? '<unknown>', property.value, scope, currPath, helpers);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (!id)
|
|
213
|
+
throw new Error(`Tool: missing 'id'`);
|
|
214
|
+
if (!execute)
|
|
215
|
+
throw new Error(`Tool '${id}': missing 'execute'`);
|
|
216
|
+
result.set(id, { execute });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function findProperty(obj, name, scope) {
|
|
220
|
+
const property = obj.properties.find((p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === name);
|
|
221
|
+
if (!property)
|
|
222
|
+
return null;
|
|
223
|
+
let value = property.value;
|
|
224
|
+
if (value.type === 'Identifier') {
|
|
225
|
+
const resolvedValue = resolveIdentifierToValue(value, scope);
|
|
226
|
+
if (resolvedValue && resolvedValue.type !== 'ImportBinding')
|
|
227
|
+
value = resolvedValue;
|
|
228
|
+
}
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
231
|
+
export function findToolModulesFromSource(source, currPath, helpers) {
|
|
232
|
+
const result = new Map();
|
|
233
|
+
try {
|
|
234
|
+
const ast = parse(source, { range: true, jsx: true });
|
|
235
|
+
const scopeManager = analyze(ast, { sourceType: 'module' });
|
|
236
|
+
const moduleScope = scopeManager.acquire(ast, true);
|
|
237
|
+
if (moduleScope === null) {
|
|
238
|
+
throw new Error('Expected to be able to acquire module scope');
|
|
239
|
+
}
|
|
240
|
+
;
|
|
241
|
+
walk(ast, null, {
|
|
242
|
+
ExportNamedDeclaration(node) {
|
|
243
|
+
if (!node.declaration || node.declaration.type !== 'VariableDeclaration')
|
|
244
|
+
return;
|
|
245
|
+
if (node.declaration.declarations.length !== 1)
|
|
246
|
+
return;
|
|
247
|
+
const declaration = node.declaration.declarations[0];
|
|
248
|
+
if (declaration.id.type !== 'Identifier' || declaration.id.name !== 'app')
|
|
249
|
+
return;
|
|
250
|
+
const appValue = declaration.init;
|
|
251
|
+
if (!appValue || appValue.type !== 'ObjectExpression')
|
|
252
|
+
return;
|
|
253
|
+
const tools = findProperty(appValue, 'tools', moduleScope);
|
|
254
|
+
if (tools?.type !== 'ArrayExpression')
|
|
255
|
+
return;
|
|
256
|
+
for (const element of tools.elements) {
|
|
257
|
+
if (element)
|
|
258
|
+
visitTool(element, moduleScope, result, currPath, helpers);
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
265
|
+
return errored({ code: 'TOOL_RESOLUTION_FAILED', message });
|
|
266
|
+
}
|
|
267
|
+
return complete(result);
|
|
268
|
+
}
|
|
269
|
+
export async function findToolModules(srcDirAbsolute) {
|
|
270
|
+
const appEntryPoint = await getAppEntryPoint(srcDirAbsolute);
|
|
271
|
+
if (!appEntryPoint) {
|
|
272
|
+
return complete(new Map());
|
|
273
|
+
}
|
|
274
|
+
return findToolModulesFromSource(appEntryPoint.content, appEntryPoint.path, {
|
|
275
|
+
getModuleSource: (p) => fs.readFileSync(p, 'utf-8'),
|
|
276
|
+
doesModuleExist: (p) => fs.existsSync(p),
|
|
277
|
+
modules: new Map(),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
@@ -240,12 +240,20 @@ function visitBlock(node, scope, result, currPath, helpers) {
|
|
|
240
240
|
targetPath = module.path;
|
|
241
241
|
}
|
|
242
242
|
value = unwrapTypeAnnotations(value);
|
|
243
|
+
if (value?.type === 'CallExpression') {
|
|
244
|
+
visitBlock(value.arguments[0], targetScope, result, targetPath, helpers);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
243
247
|
if (!value || value.type !== 'ObjectExpression') {
|
|
244
248
|
throw new Error(`Expected variable ${node.name} to have an initializer`);
|
|
245
249
|
}
|
|
246
250
|
visitBlock(value, targetScope, result, targetPath, helpers);
|
|
247
251
|
return;
|
|
248
252
|
}
|
|
253
|
+
if (node.type === 'CallExpression') {
|
|
254
|
+
visitBlock(node.arguments[0], scope, result, currPath, helpers);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
249
257
|
if (node.type === 'ObjectExpression') {
|
|
250
258
|
let id;
|
|
251
259
|
let execute;
|
|
@@ -381,12 +389,12 @@ export function findWorkflowBlockModulesFromSource(source, currPath, helpers) {
|
|
|
381
389
|
const message = error instanceof Error ? error.message : String(error);
|
|
382
390
|
return errored({ code: 'WORKFLOW_BLOCK_RESOLUTION_FAILED', message });
|
|
383
391
|
}
|
|
384
|
-
return complete(result);
|
|
392
|
+
return complete({ blocks: result });
|
|
385
393
|
}
|
|
386
394
|
export async function findWorkflowBlockModules(srcDirAbsolute) {
|
|
387
395
|
const appEntryPoint = await getAppEntryPoint(srcDirAbsolute);
|
|
388
396
|
if (!appEntryPoint) {
|
|
389
|
-
return complete(new Map());
|
|
397
|
+
return complete({ blocks: new Map() });
|
|
390
398
|
}
|
|
391
399
|
const getModuleSource = (path) => {
|
|
392
400
|
return fs.readFileSync(path, 'utf-8');
|
|
@@ -16,7 +16,7 @@ async function findServerFunctionModules(cwd, pattern) {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
export async function generateServerEntry({ appDirAbsolute, srcDirAbsolute, webhooksDirAbsolute, eventDirAbsolute, workflowBlockModules, log, }) {
|
|
19
|
+
export async function generateServerEntry({ appDirAbsolute, srcDirAbsolute, webhooksDirAbsolute, eventDirAbsolute, workflowBlockModules, toolModules = new Map(), log, }) {
|
|
20
20
|
const pathsResult = await combineAsync({
|
|
21
21
|
serverFunctionConcretePaths: findServerFunctionModules(srcDirAbsolute, 'server'),
|
|
22
22
|
webhookConcretePaths: findServerFunctionModules(webhooksDirAbsolute, 'webhook'),
|
|
@@ -105,6 +105,51 @@ export async function generateServerEntry({ appDirAbsolute, srcDirAbsolute, webh
|
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
// Tool module registry
|
|
109
|
+
const toolModulesMap = new Map()
|
|
110
|
+
|
|
111
|
+
${[...toolModules.entries()]
|
|
112
|
+
.map(([toolId, handlers]) => `toolModulesMap.set(
|
|
113
|
+
${JSON.stringify(toolId)},
|
|
114
|
+
{
|
|
115
|
+
${[...Object.entries(handlers)]
|
|
116
|
+
.map(([handler, data]) => data
|
|
117
|
+
? `${JSON.stringify(handler)}: {
|
|
118
|
+
module: () => import(${JSON.stringify(path.join(appDirAbsolute, data.path))}),
|
|
119
|
+
export: ${JSON.stringify(data.export)}
|
|
120
|
+
},`
|
|
121
|
+
: '')
|
|
122
|
+
.join('\n')}
|
|
123
|
+
}
|
|
124
|
+
)`)
|
|
125
|
+
.join('\n')}
|
|
126
|
+
|
|
127
|
+
// Build __AUXX_TOOLS__ — the single tool registry read by the unified
|
|
128
|
+
// lambda tool-executor for both agent-surfaced and action-surfaced
|
|
129
|
+
// invocations. Mirrors __AUXX_WORKFLOW_BLOCKS__: the executor reads
|
|
130
|
+
// execute(input, ctx) off this global. See plans/kopilot/agents/triggers/app-surface-implementation-plan.md §5.2.
|
|
131
|
+
const __AUXX_TOOLS__ = {};
|
|
132
|
+
|
|
133
|
+
for (const [toolId, handlers] of toolModulesMap.entries()) {
|
|
134
|
+
__AUXX_TOOLS__[toolId] = {
|
|
135
|
+
execute: async (...args) => {
|
|
136
|
+
const executeHandler = handlers.execute;
|
|
137
|
+
if (!executeHandler) {
|
|
138
|
+
throw new Error(\`No execute handler for tool \${toolId}\`);
|
|
139
|
+
}
|
|
140
|
+
const module = await executeHandler.module();
|
|
141
|
+
const func = module[executeHandler.export];
|
|
142
|
+
if (!func) {
|
|
143
|
+
throw new Error(\`Execute export not found in tool \${toolId}\`);
|
|
144
|
+
}
|
|
145
|
+
if (typeof func !== "function") {
|
|
146
|
+
throw new Error(\`Execute export in tool \${toolId} is not a function\`);
|
|
147
|
+
}
|
|
148
|
+
return await func(...args);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
108
153
|
var stdin_default;
|
|
109
154
|
var stdin_webhooks_default;
|
|
110
155
|
var stdin_events_default;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
export function zodToProviderToolSchema(schema, _provider = 'anthropic') {
|
|
3
|
+
const raw = z.toJSONSchema(schema, { unrepresentable: 'any' });
|
|
4
|
+
delete raw.$schema;
|
|
5
|
+
delete raw.id;
|
|
6
|
+
const refs = [];
|
|
7
|
+
const cleaned = stripAuxxRefAndMineRefs(raw, [], refs);
|
|
8
|
+
return { jsonSchema: cleaned, refs };
|
|
9
|
+
}
|
|
10
|
+
function stripAuxxRefAndMineRefs(node, path, out) {
|
|
11
|
+
if (!node || typeof node !== 'object')
|
|
12
|
+
return node;
|
|
13
|
+
if (Array.isArray(node)) {
|
|
14
|
+
return node.map((entry, i) => stripAuxxRefAndMineRefs(entry, [...path, String(i)], out));
|
|
15
|
+
}
|
|
16
|
+
const obj = { ...node };
|
|
17
|
+
if (obj.auxxRef && typeof obj.auxxRef === 'object') {
|
|
18
|
+
const kind = obj.auxxRef.kind;
|
|
19
|
+
if (typeof kind === 'string') {
|
|
20
|
+
out.push({ path: [...path], kind });
|
|
21
|
+
}
|
|
22
|
+
delete obj.auxxRef;
|
|
23
|
+
}
|
|
24
|
+
if (obj.properties && typeof obj.properties === 'object') {
|
|
25
|
+
const props = obj.properties;
|
|
26
|
+
const cleanedProps = {};
|
|
27
|
+
for (const key of Object.keys(props)) {
|
|
28
|
+
cleanedProps[key] = stripAuxxRefAndMineRefs(props[key], [...path, key], out);
|
|
29
|
+
}
|
|
30
|
+
obj.properties = cleanedProps;
|
|
31
|
+
}
|
|
32
|
+
if (obj.items) {
|
|
33
|
+
obj.items = stripAuxxRefAndMineRefs(obj.items, [...path, '[]'], out);
|
|
34
|
+
}
|
|
35
|
+
if (obj.anyOf) {
|
|
36
|
+
obj.anyOf = obj.anyOf.map((entry) => stripAuxxRefAndMineRefs(entry, path, out));
|
|
37
|
+
}
|
|
38
|
+
if (obj.oneOf) {
|
|
39
|
+
obj.oneOf = obj.oneOf.map((entry) => stripAuxxRefAndMineRefs(entry, path, out));
|
|
40
|
+
}
|
|
41
|
+
return obj;
|
|
42
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { BaseType, Connection, InferWorkflowInput, InferWorkflowOutput, WorkflowBlock, WorkflowCategory, WorkflowExecutionContext, WorkflowOrganization, WorkflowSchema, WorkflowSDK,
|
|
1
|
+
export type { BaseType, Connection, InferWorkflowInput, InferWorkflowOutput, Trigger, WorkflowBlock, WorkflowCategory, WorkflowExecutionContext, WorkflowOrganization, WorkflowSchema, WorkflowSDK, WorkflowUser, } from '../../root/workflow/types.js';
|
|
2
2
|
export * from './components/index.js';
|
|
3
3
|
export * from './hooks/index.js';
|
|
4
4
|
export type { PathTo, PathToField, ValueAtPath } from './types/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/index.ts"],"names":[],"mappings":"AASA,YAAY,EACV,QAAQ,EACR,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/index.ts"],"names":[],"mappings":"AASA,YAAY,EACV,QAAQ,EACR,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,8BAA8B,CAAA;AAGrC,cAAc,uBAAuB,CAAA;AAErC,cAAc,kBAAkB,CAAA;AAEhC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import chokidar from 'chokidar';
|
|
2
3
|
import { complete, isComplete, isErrored } from '../../errors.js';
|
|
4
|
+
import { compileAndExtractCatalog, } from '../../util/compile-and-extract-catalog.js';
|
|
3
5
|
import { compileAndExtractSettingsSchema } from '../../util/compile-and-extract-settings.js';
|
|
4
6
|
import { prepareBuildContext } from './prepare-build-context.js';
|
|
5
7
|
export function bundleJavaScript(onSuccess, onError) {
|
|
@@ -39,7 +41,21 @@ export function bundleJavaScript(onSuccess, onError) {
|
|
|
39
41
|
}
|
|
40
42
|
const results = bundleResults.value;
|
|
41
43
|
const settingsSchema = await compileAndExtractSettingsSchema();
|
|
42
|
-
await
|
|
44
|
+
const catalogResult = await compileAndExtractCatalog();
|
|
45
|
+
let catalog;
|
|
46
|
+
if (isErrored(catalogResult)) {
|
|
47
|
+
const err = catalogResult.error;
|
|
48
|
+
const detail = 'error' in err && err.error instanceof Error
|
|
49
|
+
? `\n ${err.error.message}`
|
|
50
|
+
: 'message' in err
|
|
51
|
+
? `\n ${err.message}`
|
|
52
|
+
: '';
|
|
53
|
+
process.stderr.write(chalk.yellow(`⚠ Catalog extraction failed (${err.code}) — deployment will ship with no catalog${detail}\n`));
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
catalog = catalogResult.value;
|
|
57
|
+
}
|
|
58
|
+
await onSuccess?.([results.client.outputFiles[0].text, results.server.outputFiles[0].text], settingsSchema, catalog);
|
|
43
59
|
isBuilding = false;
|
|
44
60
|
if (buildQueued && !isDisposing) {
|
|
45
61
|
buildQueued = false;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { findToolModules } from '../../build/server/find-tool-server-modules.js';
|
|
3
4
|
import { findWorkflowBlockModules } from '../../build/server/find-workflow-block-server-modules.js';
|
|
4
5
|
import { combine, combineAsync, complete, isComplete, isErrored, map, } from '../../errors.js';
|
|
5
6
|
import { ClientBuilder } from './client-builder.js';
|
|
@@ -41,10 +42,15 @@ export async function prepareBuildContext(mode) {
|
|
|
41
42
|
if (isErrored(workflowBlockModulesResult)) {
|
|
42
43
|
return workflowBlockModulesResult;
|
|
43
44
|
}
|
|
44
|
-
const
|
|
45
|
+
const toolModulesResult = await findToolModules(srcDir);
|
|
46
|
+
if (isErrored(toolModulesResult)) {
|
|
47
|
+
return toolModulesResult;
|
|
48
|
+
}
|
|
49
|
+
const { blocks: workflowBlockModules } = workflowBlockModulesResult.value;
|
|
50
|
+
const toolModules = toolModulesResult.value;
|
|
45
51
|
return combineAsync({
|
|
46
52
|
client: client.rebuild({ workflowBlockModules }),
|
|
47
|
-
server: server.rebuild({ workflowBlockModules }),
|
|
53
|
+
server: server.rebuild({ workflowBlockModules, toolModules }),
|
|
48
54
|
});
|
|
49
55
|
},
|
|
50
56
|
dispose: async (timeoutMs) => {
|
|
@@ -86,5 +92,8 @@ export function printBuildContextError(error) {
|
|
|
86
92
|
case 'WORKFLOW_BLOCK_RESOLUTION_FAILED':
|
|
87
93
|
process.stderr.write(`${chalk.red('✖ ')}Failed to build workflow block(s): ${error.message}\n`);
|
|
88
94
|
break;
|
|
95
|
+
case 'TOOL_RESOLUTION_FAILED':
|
|
96
|
+
process.stderr.write(`${chalk.red('✖ ')}Failed to resolve tool(s): ${error.message}\n`);
|
|
97
|
+
break;
|
|
89
98
|
}
|
|
90
99
|
}
|
|
@@ -42,13 +42,14 @@ export class ServerBuilder {
|
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
async rebuild({ workflowBlockModules, }) {
|
|
45
|
+
async rebuild({ workflowBlockModules, toolModules, }) {
|
|
46
46
|
const jsResult = await generateServerEntry({
|
|
47
47
|
appDirAbsolute: path.resolve(this._directories.app),
|
|
48
48
|
srcDirAbsolute: path.resolve(this._directories.src),
|
|
49
49
|
webhooksDirAbsolute: path.resolve(this._directories.webhooks),
|
|
50
50
|
eventDirAbsolute: path.resolve(this._directories.events),
|
|
51
51
|
workflowBlockModules,
|
|
52
|
+
toolModules: toolModules ?? new Map(),
|
|
52
53
|
log: console.log,
|
|
53
54
|
});
|
|
54
55
|
if (isErrored(jsResult)) {
|
|
@@ -5,7 +5,7 @@ import { combineAsync, complete, isErrored } from '../../errors.js';
|
|
|
5
5
|
import { calculateBundleSha } from '../../util/calculate-bundle-sha.js';
|
|
6
6
|
import { spinnerify } from '../../util/spinner.js';
|
|
7
7
|
import { uploadBundle } from '../../util/upload-bundle.js';
|
|
8
|
-
export async function upload({ contents, appId, targetOrganizationId, environmentVariables, cliVersion, settingsSchema, }) {
|
|
8
|
+
export async function upload({ contents, appId, targetOrganizationId, environmentVariables, cliVersion, settingsSchema, catalog, }) {
|
|
9
9
|
return await spinnerify('Uploading...', () => `Upload complete at ${new Date().toLocaleTimeString()}`, async () => {
|
|
10
10
|
const [clientBundle, serverBundle] = contents;
|
|
11
11
|
const clientSha = calculateBundleSha(clientBundle);
|
|
@@ -34,6 +34,9 @@ export async function upload({ contents, appId, targetOrganizationId, environmen
|
|
|
34
34
|
if (settingsSchema) {
|
|
35
35
|
process.stdout.write(`${chalk.green('✓ ')}Settings schema included\n`);
|
|
36
36
|
}
|
|
37
|
+
if (catalog && (catalog.tools.length || catalog.toolsets.length)) {
|
|
38
|
+
process.stdout.write(`${chalk.green('✓ ')}Catalog extracted (${catalog.tools.length} tools, ${catalog.toolsets.length} toolsets, ${catalog.workflow.blocks.length} blocks, ${catalog.triggers.length} triggers, ${catalog.actions.length} actions)\n`);
|
|
39
|
+
}
|
|
37
40
|
const deployResult = await api.createDeployment({
|
|
38
41
|
appId,
|
|
39
42
|
clientBundleSha: clientSha,
|
|
@@ -42,6 +45,7 @@ export async function upload({ contents, appId, targetOrganizationId, environmen
|
|
|
42
45
|
targetOrganizationId,
|
|
43
46
|
environmentVariables,
|
|
44
47
|
settingsSchema,
|
|
48
|
+
catalog,
|
|
45
49
|
metadata: { cliVersion },
|
|
46
50
|
});
|
|
47
51
|
if (isErrored(deployResult)) {
|
package/lib/commands/dev.js
CHANGED
|
@@ -129,7 +129,7 @@ export const dev = new Command('dev')
|
|
|
129
129
|
});
|
|
130
130
|
cleanupFunctions.push(cleanupTs);
|
|
131
131
|
let haveBundlingErrors = false;
|
|
132
|
-
const cleanupJs = bundleJavaScript(async (contents, settingsSchema) => {
|
|
132
|
+
const cleanupJs = bundleJavaScript(async (contents, settingsSchema, catalog) => {
|
|
133
133
|
if (haveBundlingErrors) {
|
|
134
134
|
process.stdout.write(`${chalk.green('✓')} Bundling errors fixed\n`);
|
|
135
135
|
haveBundlingErrors = false;
|
|
@@ -141,6 +141,7 @@ export const dev = new Command('dev')
|
|
|
141
141
|
environmentVariables,
|
|
142
142
|
cliVersion,
|
|
143
143
|
settingsSchema,
|
|
144
|
+
catalog,
|
|
144
145
|
});
|
|
145
146
|
if (isErrored(uploadResult)) {
|
|
146
147
|
printUploadError(uploadResult);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { complete, errored, isErrored } from '../../../errors.js';
|
|
2
|
+
import { compileAndExtractCatalog, } from '../../../util/compile-and-extract-catalog.js';
|
|
2
3
|
import { compileAndExtractSettingsSchema } from '../../../util/compile-and-extract-settings.js';
|
|
3
4
|
import { prepareBuildContext } from '../../dev/prepare-build-context.js';
|
|
4
5
|
export async function bundleJavaScript() {
|
|
@@ -26,8 +27,11 @@ export async function bundleJavaScript() {
|
|
|
26
27
|
});
|
|
27
28
|
}
|
|
28
29
|
const settingsSchema = await compileAndExtractSettingsSchema();
|
|
30
|
+
const catalogResult = await compileAndExtractCatalog();
|
|
31
|
+
const catalog = isErrored(catalogResult) ? undefined : catalogResult.value;
|
|
29
32
|
return complete({
|
|
30
33
|
bundles: [builds.client.outputFiles[0].text, builds.server.outputFiles[0].text],
|
|
31
34
|
settingsSchema,
|
|
35
|
+
catalog,
|
|
32
36
|
});
|
|
33
37
|
}
|
|
@@ -64,11 +64,14 @@ export const versionCreate = new Command('create')
|
|
|
64
64
|
}
|
|
65
65
|
process.exit(1);
|
|
66
66
|
}
|
|
67
|
-
const { bundles, settingsSchema } = bundleResult.value;
|
|
67
|
+
const { bundles, settingsSchema, catalog } = bundleResult.value;
|
|
68
68
|
const [clientBundle, serverBundle] = bundles;
|
|
69
69
|
if (settingsSchema) {
|
|
70
70
|
process.stdout.write(`${chalk.green('✓ ')}Settings schema extracted\n`);
|
|
71
71
|
}
|
|
72
|
+
if (catalog && (catalog.tools.length || catalog.toolsets.length)) {
|
|
73
|
+
process.stdout.write(`${chalk.green('✓ ')}Catalog extracted (${catalog.tools.length} tools, ${catalog.toolsets.length} toolsets, ${catalog.workflow.blocks.length} blocks, ${catalog.triggers.length} triggers, ${catalog.actions.length} actions)\n`);
|
|
74
|
+
}
|
|
72
75
|
const deployResult = await spinnerify('Uploading...', 'Upload complete', async () => {
|
|
73
76
|
const cliVersionResult = loadAuxxCliVersion();
|
|
74
77
|
if (isErrored(cliVersionResult)) {
|
|
@@ -112,6 +115,7 @@ export const versionCreate = new Command('create')
|
|
|
112
115
|
serverBundleSha: serverSha,
|
|
113
116
|
deploymentType: 'production',
|
|
114
117
|
settingsSchema,
|
|
118
|
+
catalog,
|
|
115
119
|
metadata: { cliVersion },
|
|
116
120
|
});
|
|
117
121
|
if (isErrored(result)) {
|
package/lib/env-loader.js
CHANGED
|
@@ -1,2 +1,18 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
1
3
|
import dotenv from 'dotenv';
|
|
2
|
-
|
|
4
|
+
function findEnvFile() {
|
|
5
|
+
let dir = resolve(process.cwd());
|
|
6
|
+
const root = dirname(dir) === dir ? dir : '/';
|
|
7
|
+
while (true) {
|
|
8
|
+
const candidate = join(dir, '.env');
|
|
9
|
+
if (existsSync(candidate))
|
|
10
|
+
return candidate;
|
|
11
|
+
const parent = dirname(dir);
|
|
12
|
+
if (parent === dir || dir === root)
|
|
13
|
+
break;
|
|
14
|
+
dir = parent;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
dotenv.config({ path: findEnvFile() });
|