buildfunctions 0.0.3 → 0.0.4

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.
Files changed (70) hide show
  1. package/README.md +87 -1
  2. package/dist/client.d.ts +34 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +198 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/function/cpu-function.d.ts +19 -0
  7. package/dist/function/cpu-function.d.ts.map +1 -0
  8. package/dist/function/cpu-function.js +103 -0
  9. package/dist/function/cpu-function.js.map +1 -0
  10. package/dist/function/gpu-function.d.ts +13 -0
  11. package/dist/function/gpu-function.d.ts.map +1 -0
  12. package/dist/function/gpu-function.js +202 -0
  13. package/dist/function/gpu-function.js.map +1 -0
  14. package/dist/function/index.d.ts +8 -0
  15. package/dist/function/index.d.ts.map +1 -0
  16. package/dist/function/index.js +6 -0
  17. package/dist/function/index.js.map +1 -0
  18. package/dist/index.d.ts +45 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +55 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/sandbox/cpu-sandbox.d.ts +18 -0
  23. package/dist/sandbox/cpu-sandbox.d.ts.map +1 -0
  24. package/dist/sandbox/cpu-sandbox.js +293 -0
  25. package/dist/sandbox/cpu-sandbox.js.map +1 -0
  26. package/dist/sandbox/gpu-sandbox.d.ts +15 -0
  27. package/dist/sandbox/gpu-sandbox.d.ts.map +1 -0
  28. package/dist/sandbox/gpu-sandbox.js +359 -0
  29. package/dist/sandbox/gpu-sandbox.js.map +1 -0
  30. package/dist/sandbox/index.d.ts +6 -0
  31. package/dist/sandbox/index.d.ts.map +1 -0
  32. package/dist/sandbox/index.js +6 -0
  33. package/dist/sandbox/index.js.map +1 -0
  34. package/dist/types/index.d.ts +153 -0
  35. package/dist/types/index.d.ts.map +1 -0
  36. package/dist/types/index.js +5 -0
  37. package/dist/types/index.js.map +1 -0
  38. package/dist/utils/errors.d.ts +27 -0
  39. package/dist/utils/errors.d.ts.map +1 -0
  40. package/dist/utils/errors.js +79 -0
  41. package/dist/utils/errors.js.map +1 -0
  42. package/dist/utils/framework.d.ts +6 -0
  43. package/dist/utils/framework.d.ts.map +1 -0
  44. package/dist/utils/framework.js +17 -0
  45. package/dist/utils/framework.js.map +1 -0
  46. package/dist/utils/http.d.ts +24 -0
  47. package/dist/utils/http.d.ts.map +1 -0
  48. package/dist/utils/http.js +75 -0
  49. package/dist/utils/http.js.map +1 -0
  50. package/dist/utils/index.d.ts +8 -0
  51. package/dist/utils/index.d.ts.map +1 -0
  52. package/dist/utils/index.js +8 -0
  53. package/dist/utils/index.js.map +1 -0
  54. package/dist/utils/memory.d.ts +6 -0
  55. package/dist/utils/memory.d.ts.map +1 -0
  56. package/dist/utils/memory.js +21 -0
  57. package/dist/utils/memory.js.map +1 -0
  58. package/dist/utils/uploader.d.ts +41 -0
  59. package/dist/utils/uploader.d.ts.map +1 -0
  60. package/dist/utils/uploader.js +157 -0
  61. package/dist/utils/uploader.js.map +1 -0
  62. package/package.json +27 -17
  63. package/dist/cli.d.ts +0 -3
  64. package/dist/cli.d.ts.map +0 -1
  65. package/dist/cli.js +0 -18
  66. package/dist/cli.js.map +0 -1
  67. package/dist/test.d.ts +0 -10
  68. package/dist/test.d.ts.map +0 -1
  69. package/dist/test.js +0 -7
  70. package/dist/test.js.map +0 -1
@@ -0,0 +1,202 @@
1
+ /**
2
+ * GPU Function - Deploy GPU-accelerated serverless functions to Buildfunctions
3
+ */
4
+ import https from 'https';
5
+ import { ValidationError } from '../utils/errors.js';
6
+ import { parseMemory } from '../utils/memory.js';
7
+ import { detectFramework } from '../utils/framework.js';
8
+ const DEFAULT_GPU_BUILD_URL = 'https://prod-gpu-build.buildfunctions.link';
9
+ function getFileExtension(language) {
10
+ const extensions = {
11
+ javascript: '.js',
12
+ typescript: '.ts',
13
+ python: '.py',
14
+ go: '.go',
15
+ shell: '.sh',
16
+ };
17
+ return extensions[language] ?? '.js';
18
+ }
19
+ function getDefaultRuntime(language) {
20
+ // JavaScript requires explicit runtime (node.js or deno)
21
+ if (language === 'javascript') {
22
+ throw new ValidationError('JavaScript requires explicit runtime: "nodejs" or "deno"');
23
+ }
24
+ // All other languages have single runtime = language name
25
+ return language;
26
+ }
27
+ function validateOptions(options) {
28
+ if (!options.name || typeof options.name !== 'string') {
29
+ throw new ValidationError('Function name is required');
30
+ }
31
+ if (!/^[a-z0-9-]+$/.test(options.name.toLowerCase())) {
32
+ throw new ValidationError('Function name can only contain lowercase letters, numbers, and hyphens');
33
+ }
34
+ if (!options.code || typeof options.code !== 'string') {
35
+ throw new ValidationError('Function code is required');
36
+ }
37
+ if (!options.language) {
38
+ throw new ValidationError('Language is required');
39
+ }
40
+ // GPU Functions only support Python currently
41
+ if (options.language !== 'python') {
42
+ throw new ValidationError('GPU Functions currently only support Python. Additional languages coming soon.');
43
+ }
44
+ }
45
+ function buildRequestBody(options) {
46
+ const { name, language, code, config, envVariables, dependencies, cronSchedule, framework, } = options;
47
+ // Auto-infer runtime from language (server handles runtimeVersion)
48
+ const runtime = options.runtime ?? getDefaultRuntime(language);
49
+ // Default GPU to T4G
50
+ const gpu = options.gpu ?? 'T4G';
51
+ const fileExt = getFileExtension(language);
52
+ const functionName = name.toLowerCase();
53
+ return {
54
+ name: functionName,
55
+ language,
56
+ runtime,
57
+ sourceWith: code, // source with env vars
58
+ sourceWithout: code,
59
+ fileExt,
60
+ processorType: 'GPU',
61
+ gpu,
62
+ memoryAllocated: config?.memory ? parseMemory(config.memory) : 4096,
63
+ timeout: config?.timeout ?? 180,
64
+ cpuCores: config?.cpuCores ?? 2,
65
+ envVariables: envVariables ? JSON.stringify(Object.entries(envVariables).map(([key, value]) => ({ key, value }))) : '[]',
66
+ requirements: dependencies ?? '',
67
+ cronExpression: cronSchedule ?? '',
68
+ totalVariables: envVariables ? Object.keys(envVariables).length : 0,
69
+ selectedFramework: framework ?? detectFramework(dependencies),
70
+ // GPU Function requires these fields
71
+ useEmptyFolder: true,
72
+ selectedFunction: {
73
+ name: functionName,
74
+ sourceWith: code,
75
+ runtime,
76
+ language,
77
+ sizeInBytes: new TextEncoder().encode(code).length,
78
+ },
79
+ selectedModel: {
80
+ currentModelName: null,
81
+ isCreatingNewModel: true,
82
+ gpufProjectTitleState: 'test', // todo: need to update
83
+ useEmptyFolder: true,
84
+ },
85
+ };
86
+ }
87
+ function createGPUFunctionBuilder(options, _apiKey, gpuBuildUrl, userId, username, computeTier) {
88
+ validateOptions(options);
89
+ const resolvedGpuBuildUrl = gpuBuildUrl ?? DEFAULT_GPU_BUILD_URL;
90
+ const deploy = async () => {
91
+ // Compute runtime for use in resolved function
92
+ const resolvedRuntime = options.runtime ?? getDefaultRuntime(options.language);
93
+ const body = {
94
+ ...buildRequestBody(options),
95
+ userId,
96
+ username,
97
+ computeTier,
98
+ runCommand: null,
99
+ };
100
+ const buildUrl = `${resolvedGpuBuildUrl}/build`;
101
+ const postData = JSON.stringify(body);
102
+ const url = new URL(buildUrl);
103
+ return new Promise((resolve, reject) => {
104
+ const req = https.request({
105
+ hostname: url.hostname,
106
+ port: url.port || 443,
107
+ path: url.pathname,
108
+ method: 'POST',
109
+ headers: {
110
+ 'Content-Type': 'application/json',
111
+ 'Content-Length': Buffer.byteLength(postData),
112
+ 'Connection': 'keep-alive',
113
+ },
114
+ timeout: 30 * 60 * 1000, // 30 minutes total timeout
115
+ }, (res) => {
116
+ let responseText = '';
117
+ res.on('data', (chunk) => {
118
+ responseText += chunk.toString();
119
+ });
120
+ res.on('end', () => {
121
+ // Parse the response
122
+ let data;
123
+ try {
124
+ data = JSON.parse(responseText);
125
+ }
126
+ catch {
127
+ data = { success: res.statusCode === 201 };
128
+ }
129
+ // Storage server returns 201 on success
130
+ if (res.statusCode !== 201 && res.statusCode !== 200) {
131
+ resolve(null);
132
+ return;
133
+ }
134
+ const siteId = data.data?.siteId || data.siteId || data.id;
135
+ const funcName = options.name.toLowerCase();
136
+ const endpoint = data.endpoint || `https://${funcName}.buildfunctions.app`;
137
+ resolve({
138
+ id: siteId,
139
+ name: funcName,
140
+ subdomain: funcName,
141
+ endpoint,
142
+ lambdaUrl: data.data?.sslCertificateEndpoint || '',
143
+ language: options.language,
144
+ runtime: resolvedRuntime,
145
+ lambdaMemoryAllocated: options.config?.memory ? parseMemory(options.config.memory) : 4096,
146
+ timeoutSeconds: options.config?.timeout ?? 180,
147
+ isGPUF: true,
148
+ framework: options.framework,
149
+ createdAt: new Date().toISOString(),
150
+ updatedAt: new Date().toISOString(),
151
+ delete: async () => {
152
+ await fetch(`${resolvedGpuBuildUrl}/delete`, {
153
+ method: 'POST',
154
+ headers: { 'Content-Type': 'application/json' },
155
+ body: JSON.stringify({ siteId, userId, username }),
156
+ });
157
+ },
158
+ });
159
+ });
160
+ res.on('error', (error) => {
161
+ reject(error);
162
+ });
163
+ });
164
+ // Set socket timeout separately (for connection establishment)
165
+ req.on('socket', (socket) => {
166
+ socket.setTimeout(30 * 60 * 1000); // 30 minutes
167
+ socket.on('timeout', () => {
168
+ req.destroy(new Error('Socket timeout'));
169
+ });
170
+ });
171
+ req.on('timeout', () => {
172
+ req.destroy(new Error('Request timeout'));
173
+ });
174
+ req.on('error', (error) => {
175
+ reject(error);
176
+ });
177
+ // Send the request body
178
+ req.write(postData);
179
+ req.end();
180
+ });
181
+ };
182
+ return { deploy };
183
+ }
184
+ let globalApiKey = null;
185
+ let globalGpuBuildUrl;
186
+ let globalUserId;
187
+ let globalUsername;
188
+ let globalComputeTier;
189
+ export function setGpuApiKey(apiKey, gpuBuildUrl, userId, username, computeTier) {
190
+ globalApiKey = apiKey;
191
+ globalGpuBuildUrl = gpuBuildUrl;
192
+ globalUserId = userId;
193
+ globalUsername = username;
194
+ globalComputeTier = computeTier;
195
+ }
196
+ export function GPUFunction(options) {
197
+ if (!globalApiKey) {
198
+ throw new ValidationError('API key not set. Initialize Buildfunctions client first.');
199
+ }
200
+ return createGPUFunctionBuilder(options, globalApiKey, globalGpuBuildUrl, globalUserId, globalUsername, globalComputeTier);
201
+ }
202
+ //# sourceMappingURL=gpu-function.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu-function.js","sourceRoot":"","sources":["../../src/function/gpu-function.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Function exports
3
+ */
4
+ export { CPUFunction, setApiKey } from './cpu-function.js';
5
+ export type { CPUFunctionBuilder } from './cpu-function.js';
6
+ export { GPUFunction, setGpuApiKey } from './gpu-function.js';
7
+ export type { GPUFunctionBuilder } from './gpu-function.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/function/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Function exports
3
+ */
4
+ export { CPUFunction, setApiKey } from './cpu-function.js';
5
+ export { GPUFunction, setGpuApiKey } from './gpu-function.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/function/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Buildfunctions SDK
3
+ *
4
+ * A TypeScript SDK for Buildfunctions - the serverless platform for AI agents.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { Buildfunctions, CPUSandbox, GPUSandbox, GPUFunction } from 'buildfunctions';
9
+ *
10
+ * // Initialize the client (authenticates with the API)
11
+ * const buildfunctions = await Buildfunctions({
12
+ * apiKey: process.env.BUILDFUNCTIONS_API_KEY
13
+ * });
14
+ *
15
+ * // Access authenticated user info
16
+ * console.log(buildfunctions.user);
17
+ * console.log(buildfunctions.authenticatedAt);
18
+ *
19
+ * // Create a CPU sandbox
20
+ * const sandbox = await CPUSandbox.create({
21
+ * name: 'my-sandbox',
22
+ * language: 'python',
23
+ * memory: '512MB'
24
+ * });
25
+ *
26
+ * // Run code
27
+ * const result = await sandbox.run('print("Hello from Buildfunctions!")');
28
+ * console.log(result.stdout);
29
+ *
30
+ * // Clean up
31
+ * await sandbox.delete();
32
+ * ```
33
+ */
34
+ export { CPUFunction } from './function/cpu-function.js';
35
+ export type { CPUFunctionBuilder } from './function/cpu-function.js';
36
+ export { GPUFunction } from './function/gpu-function.js';
37
+ export type { GPUFunctionBuilder } from './function/gpu-function.js';
38
+ export { CPUSandbox } from './sandbox/cpu-sandbox.js';
39
+ export { GPUSandbox } from './sandbox/gpu-sandbox.js';
40
+ export type { BuildfunctionsConfig, AuthenticatedUser, AuthResponse, Language, Runtime, GPUType, Framework, Memory, FunctionConfig, CPUFunctionOptions, GPUFunctionOptions, CreateFunctionOptions, DeployedFunction, CPUSandboxConfig, GPUSandboxConfig, RunResult, UploadOptions, SandboxInstance, CPUSandboxInstance, GPUSandboxInstance, FindUniqueOptions, ListOptions, ErrorCode, } from './types/index.js';
41
+ export { BuildfunctionsError, AuthenticationError, NotFoundError, ValidationError, CapacityError, } from './utils/errors.js';
42
+ export { Buildfunctions, createClient } from './client.js';
43
+ export type { BuildfunctionsClient, FunctionsManager } from './client.js';
44
+ export declare function init(apiKey: string, baseUrl?: string, gpuBuildUrl?: string, userId?: string, username?: string, computeTier?: string): void;
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,OAAO,EACP,SAAS,EACT,MAAM,EACN,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,SAAS,GACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQ1E,wBAAgB,IAAI,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAKN"}
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Buildfunctions SDK
3
+ *
4
+ * A TypeScript SDK for Buildfunctions - the serverless platform for AI agents.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { Buildfunctions, CPUSandbox, GPUSandbox, GPUFunction } from 'buildfunctions';
9
+ *
10
+ * // Initialize the client (authenticates with the API)
11
+ * const buildfunctions = await Buildfunctions({
12
+ * apiKey: process.env.BUILDFUNCTIONS_API_KEY
13
+ * });
14
+ *
15
+ * // Access authenticated user info
16
+ * console.log(buildfunctions.user);
17
+ * console.log(buildfunctions.authenticatedAt);
18
+ *
19
+ * // Create a CPU sandbox
20
+ * const sandbox = await CPUSandbox.create({
21
+ * name: 'my-sandbox',
22
+ * language: 'python',
23
+ * memory: '512MB'
24
+ * });
25
+ *
26
+ * // Run code
27
+ * const result = await sandbox.run('print("Hello from Buildfunctions!")');
28
+ * console.log(result.stdout);
29
+ *
30
+ * // Clean up
31
+ * await sandbox.delete();
32
+ * ```
33
+ */
34
+ // Re-export functions
35
+ export { CPUFunction } from './function/cpu-function.js';
36
+ export { GPUFunction } from './function/gpu-function.js';
37
+ // Re-export sandboxes
38
+ export { CPUSandbox } from './sandbox/cpu-sandbox.js';
39
+ export { GPUSandbox } from './sandbox/gpu-sandbox.js';
40
+ // Re-export errors
41
+ export { BuildfunctionsError, AuthenticationError, NotFoundError, ValidationError, CapacityError, } from './utils/errors.js';
42
+ // Re-export client
43
+ export { Buildfunctions, createClient } from './client.js';
44
+ // Import internal setters for initialization
45
+ import { setApiKey } from './function/cpu-function.js';
46
+ import { setGpuApiKey } from './function/gpu-function.js';
47
+ import { setCpuSandboxApiKey } from './sandbox/cpu-sandbox.js';
48
+ import { setGpuSandboxApiKey } from './sandbox/gpu-sandbox.js';
49
+ export function init(apiKey, baseUrl, gpuBuildUrl, userId, username, computeTier) {
50
+ setApiKey(apiKey, baseUrl);
51
+ setGpuApiKey(apiKey, gpuBuildUrl, userId, username, computeTier);
52
+ setCpuSandboxApiKey(apiKey, baseUrl);
53
+ setGpuSandboxApiKey(apiKey, gpuBuildUrl, userId, username, computeTier, baseUrl);
54
+ }
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,sBAAsB;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzD,sBAAsB;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AA6BtD,mBAAmB;AACnB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,mBAAmB;AACnB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3D,6CAA6C;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,UAAU,IAAI,CAClB,MAAc,EACd,OAAgB,EAChB,WAAoB,EACpB,MAAe,EACf,QAAiB,EACjB,WAAoB;IAEpB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3B,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IACjE,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * CPU Sandbox - Hardware-isolated execution environment for untrusted AI actions
3
+ */
4
+ import type { CPUSandboxConfig, CPUSandboxInstance } from '../types/index.js';
5
+ /**
6
+ * Set the API key for sandbox operations
7
+ */
8
+ export declare function setCpuSandboxApiKey(apiKey: string, baseUrl?: string): void;
9
+ /**
10
+ * CPU Sandbox factory
11
+ */
12
+ export declare const CPUSandbox: {
13
+ /**
14
+ * Create a new CPU sandbox
15
+ */
16
+ create: (config: CPUSandboxConfig) => Promise<CPUSandboxInstance>;
17
+ };
18
+ //# sourceMappingURL=cpu-sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpu-sandbox.d.ts","sourceRoot":"","sources":["../../src/sandbox/cpu-sandbox.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAA4B,MAAM,mBAAmB,CAAC;AA0GxG;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAG1E;AAsJD;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;qBACoB,gBAAgB,KAAG,OAAO,CAAC,kBAAkB,CAAC;CAuEtE,CAAC"}
@@ -0,0 +1,293 @@
1
+ /**
2
+ * CPU Sandbox - Hardware-isolated execution environment for untrusted AI actions
3
+ */
4
+ import { ValidationError, BuildfunctionsError } from '../utils/errors.js';
5
+ import { parseMemory } from '../utils/memory.js';
6
+ import { readFile } from 'fs/promises';
7
+ import { existsSync } from 'fs';
8
+ import dns from 'dns';
9
+ import https from 'https';
10
+ const DEFAULT_BASE_URL = 'https://www.buildfunctions.com';
11
+ // AWS Route53 authoritative nameservers for buildfunctions.app
12
+ // These have the DNS records IMMEDIATELY - no propagation delay
13
+ const awsNameservers = [
14
+ '205.251.193.143', // ns-399.awsdns-49.com
15
+ '205.251.198.254', // ns-1278.awsdns-31.org
16
+ '205.251.195.249', // ns-1017.awsdns-63.net
17
+ '205.251.198.95', // ns-1631.awsdns-11.co.uk
18
+ ];
19
+ // DNS resolver using AWS Route53 authoritative nameservers
20
+ const awsResolver = new dns.Resolver();
21
+ awsResolver.setServers(awsNameservers);
22
+ /**
23
+ * Resolve hostname using AWS Route53 authoritative nameservers
24
+ */
25
+ function resolveWithAWS(hostname) {
26
+ return new Promise((resolve, reject) => {
27
+ awsResolver.resolve4(hostname, (err, addresses) => {
28
+ if (err || !addresses || addresses.length === 0) {
29
+ reject(err || new Error('No addresses'));
30
+ }
31
+ else {
32
+ resolve(addresses[0]);
33
+ }
34
+ });
35
+ });
36
+ }
37
+ /**
38
+ * HTTPS GET using resolved IP (bypasses system DNS entirely)
39
+ */
40
+ function httpsGetWithIP(ip, hostname, path) {
41
+ return new Promise((resolve, reject) => {
42
+ const req = https.request({
43
+ hostname: ip,
44
+ port: 443,
45
+ path: path,
46
+ method: 'GET',
47
+ headers: { 'Host': hostname },
48
+ servername: hostname, // SNI for TLS
49
+ timeout: 10000,
50
+ }, (res) => {
51
+ let body = '';
52
+ res.on('data', chunk => body += chunk);
53
+ res.on('end', () => resolve({ status: res.statusCode || 0, body }));
54
+ });
55
+ req.on('error', reject);
56
+ req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
57
+ req.end();
58
+ });
59
+ }
60
+ /**
61
+ * Wait for endpoint using AWS Route53 authoritative DNS
62
+ */
63
+ async function waitForEndpoint(endpoint, maxAttempts = 60, delayMs = 500) {
64
+ const url = new URL(endpoint);
65
+ const hostname = url.hostname;
66
+ const path = url.pathname + url.search || '/';
67
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
68
+ try {
69
+ // Step 1: Resolve via AWS Route53 authoritative nameservers (immediate, no propagation)
70
+ const ip = await resolveWithAWS(hostname);
71
+ // Step 2: Connect directly to IP with proper Host/SNI headers
72
+ const res = await httpsGetWithIP(ip, hostname, path);
73
+ if (res.status >= 200 && res.status < 500)
74
+ return;
75
+ }
76
+ catch (err) {
77
+ const error = err;
78
+ if (attempt === 1 || attempt % 10 === 0) {
79
+ console.log(` Waiting for endpoint... (attempt ${attempt}/${maxAttempts}) ${error.code || error.message}`);
80
+ }
81
+ }
82
+ await new Promise(r => setTimeout(r, delayMs));
83
+ }
84
+ throw new BuildfunctionsError(`Endpoint not ready after ${maxAttempts} attempts`, 'NETWORK_ERROR');
85
+ }
86
+ /**
87
+ * Fetch endpoint using AWS Route53 authoritative DNS
88
+ */
89
+ async function fetchWithAuthDNS(endpoint) {
90
+ const url = new URL(endpoint);
91
+ const hostname = url.hostname;
92
+ const path = url.pathname + url.search || '/';
93
+ const ip = await resolveWithAWS(hostname);
94
+ return httpsGetWithIP(ip, hostname, path);
95
+ }
96
+ // Global configuration
97
+ let globalApiKey = null;
98
+ let globalBaseUrl;
99
+ /**
100
+ * Set the API key for sandbox operations
101
+ */
102
+ export function setCpuSandboxApiKey(apiKey, baseUrl) {
103
+ globalApiKey = apiKey;
104
+ globalBaseUrl = baseUrl;
105
+ }
106
+ function validateConfig(config) {
107
+ if (!config.name || typeof config.name !== 'string') {
108
+ throw new ValidationError('Sandbox name is required');
109
+ }
110
+ if (!config.language || typeof config.language !== 'string') {
111
+ throw new ValidationError('Language is required');
112
+ }
113
+ // JavaScript requires explicit runtime (node or deno)
114
+ if (config.language === 'javascript' && !config.runtime) {
115
+ throw new ValidationError('JavaScript requires explicit runtime: "node" or "deno"');
116
+ }
117
+ }
118
+ /**
119
+ * Create a CPU sandbox instance
120
+ */
121
+ function createCPUSandboxInstance(id, name, runtime, endpoint, apiKey, baseUrl) {
122
+ let deleted = false;
123
+ const run = async () => {
124
+ if (deleted) {
125
+ throw new BuildfunctionsError('Sandbox has been deleted', 'INVALID_REQUEST');
126
+ }
127
+ // Wait for endpoint to be ready
128
+ await waitForEndpoint(endpoint);
129
+ // Call the sandbox endpoint using authoritative DNS
130
+ const response = await fetchWithAuthDNS(endpoint);
131
+ const responseText = response.body;
132
+ if (!responseText) {
133
+ throw new BuildfunctionsError('Empty response from sandbox', 'UNKNOWN_ERROR', response.status);
134
+ }
135
+ let data;
136
+ try {
137
+ data = JSON.parse(responseText);
138
+ }
139
+ catch {
140
+ // Response is plain text
141
+ return {
142
+ stdout: responseText,
143
+ stderr: '',
144
+ text: responseText,
145
+ results: null,
146
+ exit_code: 0,
147
+ };
148
+ }
149
+ if (response.status < 200 || response.status >= 300) {
150
+ const errorData = data;
151
+ throw new BuildfunctionsError(`Execution failed: ${errorData.error || 'Unknown error'}`, 'UNKNOWN_ERROR', response.status);
152
+ }
153
+ // Response is already the unwrapped result from the handler
154
+ return {
155
+ stdout: responseText,
156
+ stderr: '',
157
+ text: responseText,
158
+ results: data,
159
+ exit_code: 0,
160
+ };
161
+ };
162
+ const upload = async (options) => {
163
+ if (deleted) {
164
+ throw new BuildfunctionsError('Sandbox has been deleted', 'INVALID_REQUEST');
165
+ }
166
+ // Normalize options to support both snake_case and camelCase
167
+ const localPath = options.local_path ?? options.localPath;
168
+ const filePath = options.file_path ?? options.filePath;
169
+ if (!localPath || !filePath) {
170
+ throw new ValidationError('Both local_path and file_path are required');
171
+ }
172
+ // Read file content
173
+ if (!existsSync(localPath)) {
174
+ throw new ValidationError(`Local file not found: ${localPath}`);
175
+ }
176
+ const content = await readFile(localPath, 'utf-8');
177
+ const response = await fetch(`${baseUrl}/api/sdk/sandbox/upload`, {
178
+ method: 'POST',
179
+ headers: {
180
+ 'Content-Type': 'application/json',
181
+ Authorization: `Bearer ${apiKey}`,
182
+ },
183
+ body: JSON.stringify({
184
+ sandboxId: id,
185
+ filePath,
186
+ content,
187
+ type: 'cpu',
188
+ }),
189
+ });
190
+ if (!response.ok) {
191
+ throw new BuildfunctionsError('Upload failed', 'UNKNOWN_ERROR', response.status);
192
+ }
193
+ };
194
+ const deleteFn = async () => {
195
+ if (deleted) {
196
+ return;
197
+ }
198
+ const response = await fetch(`${baseUrl}/api/sdk/sandbox/delete`, {
199
+ method: 'DELETE',
200
+ headers: {
201
+ 'Content-Type': 'application/json',
202
+ Authorization: `Bearer ${apiKey}`,
203
+ },
204
+ body: JSON.stringify({
205
+ sandboxId: id,
206
+ type: 'cpu',
207
+ }),
208
+ });
209
+ if (!response.ok) {
210
+ throw new BuildfunctionsError('Delete failed', 'UNKNOWN_ERROR', response.status);
211
+ }
212
+ deleted = true;
213
+ };
214
+ return {
215
+ id,
216
+ name,
217
+ runtime,
218
+ endpoint,
219
+ type: 'cpu',
220
+ run,
221
+ upload,
222
+ delete: deleteFn,
223
+ };
224
+ }
225
+ /**
226
+ * CPU Sandbox factory
227
+ */
228
+ export const CPUSandbox = {
229
+ /**
230
+ * Create a new CPU sandbox
231
+ */
232
+ create: async (config) => {
233
+ if (!globalApiKey) {
234
+ throw new ValidationError('API key not set. Initialize Buildfunctions client first.');
235
+ }
236
+ validateConfig(config);
237
+ const baseUrl = globalBaseUrl ?? DEFAULT_BASE_URL;
238
+ // CPU sandbox endpoint
239
+ const url = `${baseUrl}/api/sdk/sandbox/create`;
240
+ // Match CPU function body exactly (from client.ts create function)
241
+ const name = config.name.toLowerCase();
242
+ const fileExt = config.language === 'python' ? '.py' : config.language === 'javascript' ? '.js' : '.py';
243
+ const requestBody = {
244
+ // Required by sandbox/create endpoint
245
+ type: 'cpu',
246
+ // Same fields as CPU function
247
+ name,
248
+ fileExt,
249
+ code: config.code ?? '',
250
+ sourceWith: config.code ?? '',
251
+ sourceWithout: config.code ?? '',
252
+ language: config.language,
253
+ runtime: config.runtime ?? config.language,
254
+ memoryAllocated: config.memory ? parseMemory(config.memory) : 128,
255
+ timeout: config.timeout ?? 10,
256
+ envVariables: JSON.stringify(config.envVariables ?? []),
257
+ requirements: config.requirements ?? '',
258
+ cronExpression: '',
259
+ subdomain: name,
260
+ totalVariables: (config.envVariables ?? []).length,
261
+ functionCount: 0,
262
+ };
263
+ const controller = new AbortController();
264
+ const timeoutId = setTimeout(() => controller.abort(), 5 * 60 * 1000); // 5 minute timeout
265
+ const response = await fetch(url, {
266
+ method: 'POST',
267
+ headers: {
268
+ 'Content-Type': 'application/json',
269
+ Authorization: `Bearer ${globalApiKey}`,
270
+ },
271
+ body: JSON.stringify(requestBody),
272
+ signal: controller.signal,
273
+ });
274
+ clearTimeout(timeoutId);
275
+ const responseText = await response.text();
276
+ if (!response.ok) {
277
+ throw new BuildfunctionsError(`Failed to create sandbox: ${responseText}`, 'UNKNOWN_ERROR', response.status);
278
+ }
279
+ let data;
280
+ try {
281
+ data = JSON.parse(responseText);
282
+ }
283
+ catch {
284
+ throw new BuildfunctionsError(`Invalid JSON response: ${responseText}`, 'UNKNOWN_ERROR', response.status);
285
+ }
286
+ // Response has siteId and endpoint
287
+ const sandboxId = data.siteId;
288
+ const sandboxEndpoint = data.endpoint || `https://${name}.buildfunctions.app`;
289
+ const sandboxRuntime = config.runtime ?? config.language;
290
+ return createCPUSandboxInstance(sandboxId, name, sandboxRuntime, sandboxEndpoint, globalApiKey, baseUrl);
291
+ },
292
+ };
293
+ //# sourceMappingURL=cpu-sandbox.js.map