@sylphx/sdk 0.2.0 → 0.2.1
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/index.js +168 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +167 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2852,6 +2852,172 @@ async function captureMessage(config, message, options = {}) {
|
|
|
2852
2852
|
body: request
|
|
2853
2853
|
});
|
|
2854
2854
|
}
|
|
2855
|
+
|
|
2856
|
+
// src/sandbox.ts
|
|
2857
|
+
var DEFAULT_IMAGE = "registry.sylphx.com/library/exec-server:latest";
|
|
2858
|
+
var SandboxClient = class _SandboxClient {
|
|
2859
|
+
id;
|
|
2860
|
+
config;
|
|
2861
|
+
constructor(id, config) {
|
|
2862
|
+
this.id = id;
|
|
2863
|
+
this.config = config;
|
|
2864
|
+
}
|
|
2865
|
+
// ---------------------------------------------------------------------------
|
|
2866
|
+
// Factory
|
|
2867
|
+
// ---------------------------------------------------------------------------
|
|
2868
|
+
/**
|
|
2869
|
+
* Create a new sandbox.
|
|
2870
|
+
*
|
|
2871
|
+
* The sandbox pod starts asynchronously — it will be in `starting` status
|
|
2872
|
+
* after creation. File/run operations will block until the pod is ready.
|
|
2873
|
+
*
|
|
2874
|
+
* @param config - Sylphx config with a secret key (sk_*) and project ref
|
|
2875
|
+
* @param options - Sandbox creation options
|
|
2876
|
+
*/
|
|
2877
|
+
static async create(config, options) {
|
|
2878
|
+
const record = await callApi(config, `/sandboxes`, {
|
|
2879
|
+
method: "POST",
|
|
2880
|
+
body: {
|
|
2881
|
+
image: options?.image ?? DEFAULT_IMAGE,
|
|
2882
|
+
idleTimeoutMs: options?.idleTimeoutMs ?? 3e5,
|
|
2883
|
+
resources: options?.resources,
|
|
2884
|
+
env: options?.env,
|
|
2885
|
+
storage: options?.storageGi !== void 0 ? { enabled: true, sizeGi: options.storageGi } : void 0
|
|
2886
|
+
}
|
|
2887
|
+
});
|
|
2888
|
+
return new _SandboxClient(record.id, config);
|
|
2889
|
+
}
|
|
2890
|
+
/**
|
|
2891
|
+
* Reconnect to an existing sandbox by ID.
|
|
2892
|
+
*
|
|
2893
|
+
* Use this to resume operations on a sandbox created in a previous request.
|
|
2894
|
+
*/
|
|
2895
|
+
static fromId(config, sandboxId) {
|
|
2896
|
+
return new _SandboxClient(sandboxId, config);
|
|
2897
|
+
}
|
|
2898
|
+
// ---------------------------------------------------------------------------
|
|
2899
|
+
// Lifecycle
|
|
2900
|
+
// ---------------------------------------------------------------------------
|
|
2901
|
+
/**
|
|
2902
|
+
* Get the current status of this sandbox.
|
|
2903
|
+
*/
|
|
2904
|
+
async getStatus() {
|
|
2905
|
+
return callApi(
|
|
2906
|
+
this.config,
|
|
2907
|
+
`/sandboxes/${this.id}`,
|
|
2908
|
+
{ method: "GET" }
|
|
2909
|
+
);
|
|
2910
|
+
}
|
|
2911
|
+
/**
|
|
2912
|
+
* Terminate the sandbox immediately.
|
|
2913
|
+
*
|
|
2914
|
+
* Deletes the K8s Pod and Service. PVC (storage) is preserved for reuse.
|
|
2915
|
+
* This operation is idempotent — safe to call multiple times.
|
|
2916
|
+
*/
|
|
2917
|
+
async terminate() {
|
|
2918
|
+
await callApi(
|
|
2919
|
+
this.config,
|
|
2920
|
+
`/sandboxes/${this.id}`,
|
|
2921
|
+
{ method: "DELETE" }
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
// ---------------------------------------------------------------------------
|
|
2925
|
+
// File Operations
|
|
2926
|
+
// ---------------------------------------------------------------------------
|
|
2927
|
+
/**
|
|
2928
|
+
* Write a file to the sandbox filesystem.
|
|
2929
|
+
*
|
|
2930
|
+
* @param path - Absolute path inside the sandbox (e.g. '/workspace/file.py')
|
|
2931
|
+
* @param content - File content as string or Buffer
|
|
2932
|
+
* @param encoding - 'utf8' (default) or 'base64' for binary files
|
|
2933
|
+
*/
|
|
2934
|
+
async writeFile(path, content, encoding = "utf8") {
|
|
2935
|
+
const contentStr = Buffer.isBuffer(content) ? content.toString("base64") : content;
|
|
2936
|
+
const effectiveEncoding = Buffer.isBuffer(content) ? "base64" : encoding;
|
|
2937
|
+
await callApi(
|
|
2938
|
+
this.config,
|
|
2939
|
+
`/sandboxes/${this.id}/files`,
|
|
2940
|
+
{
|
|
2941
|
+
method: "POST",
|
|
2942
|
+
body: { path, content: contentStr, encoding: effectiveEncoding }
|
|
2943
|
+
}
|
|
2944
|
+
);
|
|
2945
|
+
}
|
|
2946
|
+
/**
|
|
2947
|
+
* Read a file from the sandbox filesystem.
|
|
2948
|
+
*
|
|
2949
|
+
* @param path - Absolute path inside the sandbox
|
|
2950
|
+
* @returns File content as a string
|
|
2951
|
+
*/
|
|
2952
|
+
async readFile(path) {
|
|
2953
|
+
const result = await callApi(
|
|
2954
|
+
this.config,
|
|
2955
|
+
`/sandboxes/${this.id}/files`,
|
|
2956
|
+
{
|
|
2957
|
+
method: "GET",
|
|
2958
|
+
query: { path }
|
|
2959
|
+
}
|
|
2960
|
+
);
|
|
2961
|
+
return result.content;
|
|
2962
|
+
}
|
|
2963
|
+
/**
|
|
2964
|
+
* Delete a file from the sandbox filesystem.
|
|
2965
|
+
*
|
|
2966
|
+
* @param path - Absolute path inside the sandbox
|
|
2967
|
+
*/
|
|
2968
|
+
async deleteFile(path) {
|
|
2969
|
+
await callApi(
|
|
2970
|
+
this.config,
|
|
2971
|
+
`/sandboxes/${this.id}/files`,
|
|
2972
|
+
{
|
|
2973
|
+
method: "DELETE",
|
|
2974
|
+
query: { path }
|
|
2975
|
+
}
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2978
|
+
/**
|
|
2979
|
+
* List files in a directory.
|
|
2980
|
+
*
|
|
2981
|
+
* @param path - Directory path inside the sandbox (default: '/')
|
|
2982
|
+
* @returns Array of file/directory paths
|
|
2983
|
+
*/
|
|
2984
|
+
async listFiles(path = "/") {
|
|
2985
|
+
const result = await callApi(
|
|
2986
|
+
this.config,
|
|
2987
|
+
`/sandboxes/${this.id}/list`,
|
|
2988
|
+
{
|
|
2989
|
+
method: "GET",
|
|
2990
|
+
query: { path }
|
|
2991
|
+
}
|
|
2992
|
+
);
|
|
2993
|
+
return result.files;
|
|
2994
|
+
}
|
|
2995
|
+
// ---------------------------------------------------------------------------
|
|
2996
|
+
// Command Execution
|
|
2997
|
+
// ---------------------------------------------------------------------------
|
|
2998
|
+
/**
|
|
2999
|
+
* Run a command inside the sandbox.
|
|
3000
|
+
*
|
|
3001
|
+
* The command runs synchronously inside the exec pod and returns when complete.
|
|
3002
|
+
*
|
|
3003
|
+
* @param command - Full command + args as array (e.g. ['python3', 'script.py'])
|
|
3004
|
+
* @param options - Optional cwd, env, timeout, stdin
|
|
3005
|
+
* @returns { stdout, stderr, exitCode, durationMs }
|
|
3006
|
+
*
|
|
3007
|
+
* @example
|
|
3008
|
+
* ```typescript
|
|
3009
|
+
* const { stdout, exitCode } = await sandbox.run(['python3', '-c', 'print(1+1)'])
|
|
3010
|
+
* console.log(stdout) // "2\n"
|
|
3011
|
+
* console.log(exitCode) // 0
|
|
3012
|
+
* ```
|
|
3013
|
+
*/
|
|
3014
|
+
async run(command, options) {
|
|
3015
|
+
return callApi(this.config, `/sandboxes/${this.id}/run`, {
|
|
3016
|
+
method: "POST",
|
|
3017
|
+
body: { command, ...options }
|
|
3018
|
+
});
|
|
3019
|
+
}
|
|
3020
|
+
};
|
|
2855
3021
|
export {
|
|
2856
3022
|
ACHIEVEMENT_TIER_CONFIG,
|
|
2857
3023
|
AuthenticationError,
|
|
@@ -2862,6 +3028,7 @@ export {
|
|
|
2862
3028
|
NotFoundError,
|
|
2863
3029
|
RETRYABLE_CODES,
|
|
2864
3030
|
RateLimitError,
|
|
3031
|
+
SandboxClient,
|
|
2865
3032
|
SylphxError,
|
|
2866
3033
|
TimeoutError,
|
|
2867
3034
|
ValidationError,
|