openpond-sdk 0.6.1 → 0.6.3
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/README.md +15 -0
- package/dist/{chunk-QLEJOCQX.js → chunk-2DMYAJLS.js} +2 -2
- package/dist/{chunk-APHPXQEA.js → chunk-CEZEVILU.js} +4 -4
- package/dist/chunk-CEZEVILU.js.map +7 -0
- package/dist/{chunk-27ETSPHQ.js → chunk-IWT6JUZD.js} +2 -2
- package/dist/{chunk-7O5X7DBU.js → chunk-MEKWESBF.js} +2 -2
- package/dist/index.js +135 -41
- package/dist/index.js.map +3 -3
- package/dist/profile-actions.js +2 -2
- package/dist/project-actions.js +2 -2
- package/dist/types/packages/cloud/src/api/core.d.ts +2 -0
- package/dist/types/packages/cloud/src/api/core.d.ts.map +1 -1
- package/dist/types/packages/cloud/src/sandbox/sandbox-instance-client.d.ts +2 -1
- package/dist/types/packages/cloud/src/sandbox/sandbox-instance-client.d.ts.map +1 -1
- package/dist/types/packages/cloud/src/sandbox/types/client.d.ts +2 -0
- package/dist/types/packages/cloud/src/sandbox/types/client.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/index.d.ts +6 -6
- package/dist/types/packages/sdk/src/index.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/model-batch-review-preparation.d.ts +1 -1
- package/dist/types/packages/sdk/src/model-starter-catalog.d.ts +10 -10
- package/dist/types/packages/sdk/src/model-starters.d.ts +8 -8
- package/dist/types/packages/sdk/src/taskset-authored-contracts.d.ts +2 -2
- package/dist/types/packages/sdk/src/taskset-authored-files.d.ts +2 -2
- package/dist/types/packages/sdk/src/taskset-draft-api-contracts.d.ts +4 -4
- package/dist/types/packages/sdk/src/taskset-draft-client.d.ts +12 -12
- package/dist/types/packages/sdk/src/taskset-draft-core.d.ts +3 -3
- package/dist/types/packages/sdk/src/taskset-draft-document.d.ts +2 -2
- package/dist/types/packages/sdk/src/taskset-draft-package-compiler.d.ts +8 -8
- package/dist/types/packages/sdk/src/taskset-draft-source.d.ts +4 -4
- package/dist/types/packages/sdk/src/taskset-draft-workspace.d.ts +4 -4
- package/dist/types/packages/sdk/src/taskset-package-grader-projection.d.ts +1 -1
- package/dist/types/packages/sdk/src/taskset-package-projection.d.ts +10 -10
- package/dist/types/packages/sdk/src/training-learning-batch.d.ts +6 -6
- package/dist/types/packages/sdk/src/types.d.ts +17 -1
- package/dist/types/packages/sdk/src/types.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/work-model.d.ts +17 -0
- package/dist/types/packages/sdk/src/work-model.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/work-sandbox.d.ts +17 -0
- package/dist/types/packages/sdk/src/work-sandbox.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/work.d.ts +8 -2
- package/dist/types/packages/sdk/src/work.d.ts.map +1 -1
- package/dist/workflows.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-APHPXQEA.js.map +0 -7
- /package/dist/{chunk-QLEJOCQX.js.map → chunk-2DMYAJLS.js.map} +0 -0
- /package/dist/{chunk-27ETSPHQ.js.map → chunk-IWT6JUZD.js.map} +0 -0
- /package/dist/{chunk-7O5X7DBU.js.map → chunk-MEKWESBF.js.map} +0 -0
package/README.md
CHANGED
|
@@ -16,6 +16,21 @@ Node.js 22.14 or newer is required. This package is server-only: never expose an
|
|
|
16
16
|
|
|
17
17
|
## Next.js route handler
|
|
18
18
|
|
|
19
|
+
Sandbox and model configuration are independently optional. With only `apiKey`,
|
|
20
|
+
Work uses OpenPond's hosted defaults. To run tools in your installed runtime while
|
|
21
|
+
keeping the hosted model, add `sandbox: { endpoint, apiKey }`. To choose a model,
|
|
22
|
+
add `model: { endpoint, apiKey, model }`, where `endpoint` is an OpenAI-compatible
|
|
23
|
+
Chat Completions base URL. Each override requires its own credential; credentials
|
|
24
|
+
are never borrowed from another service. Both overrides together allow omitting
|
|
25
|
+
the hosted `apiKey` for Work.
|
|
26
|
+
|
|
27
|
+
The customer runtime uses fresh guests for subsequent turns. Persist history and
|
|
28
|
+
outputs in your application, then pass them into the next run. A failed output
|
|
29
|
+
save retains the guest for recovery; retry persistence before deleting it. Hosted
|
|
30
|
+
repository provisioning and spending budgets do not apply to a custom runtime.
|
|
31
|
+
An optional UUID `requestId` lets an application reconcile interrupted allocations
|
|
32
|
+
through sandbox metadata; it does not replay model or tool operations.
|
|
33
|
+
|
|
19
34
|
```ts
|
|
20
35
|
// app/api/work/route.ts
|
|
21
36
|
import { createOpenPondClient } from "openpond-sdk";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
apiFetch,
|
|
3
3
|
readApiJson
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CEZEVILU.js";
|
|
5
5
|
|
|
6
6
|
// src/profile-actions.ts
|
|
7
7
|
var OpenPondProfileActionsClient = class {
|
|
@@ -69,4 +69,4 @@ function requiredValue(value, name) {
|
|
|
69
69
|
export {
|
|
70
70
|
OpenPondProfileActionsClient
|
|
71
71
|
};
|
|
72
|
-
//# sourceMappingURL=chunk-
|
|
72
|
+
//# sourceMappingURL=chunk-2DMYAJLS.js.map
|
|
@@ -38,13 +38,13 @@ var OpenPondApiError = class extends Error {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
async function apiFetch(baseUrl, token, requestPath, options = {}) {
|
|
41
|
-
const { timeoutMs = DEFAULT_API_TIMEOUT_MS, maxResponseBytes = DEFAULT_API_RESPONSE_BYTES, ...init } = options;
|
|
41
|
+
const { timeoutMs = DEFAULT_API_TIMEOUT_MS, maxResponseBytes = DEFAULT_API_RESPONSE_BYTES, explicitBearerAuth = false, ...init } = options;
|
|
42
42
|
const requestUrl = `${baseUrl}${requestPath}`;
|
|
43
43
|
const headers = new Headers(init.headers);
|
|
44
44
|
headers.set("Content-Type", "application/json");
|
|
45
|
-
const apiKey = process.env.OPENPOND_API_KEY;
|
|
45
|
+
const apiKey = !explicitBearerAuth ? process.env.OPENPOND_API_KEY : void 0;
|
|
46
46
|
const trimmedToken = token?.trim() || "";
|
|
47
|
-
const tokenIsApiKey = trimmedToken.startsWith("opk_");
|
|
47
|
+
const tokenIsApiKey = !explicitBearerAuth && trimmedToken.startsWith("opk_");
|
|
48
48
|
const effectiveApiKey = apiKey || (tokenIsApiKey ? trimmedToken : null);
|
|
49
49
|
if (effectiveApiKey && !headers.has("openpond-api-key"))
|
|
50
50
|
headers.set("openpond-api-key", effectiveApiKey);
|
|
@@ -152,4 +152,4 @@ export {
|
|
|
152
152
|
apiFetch,
|
|
153
153
|
readApiJson
|
|
154
154
|
};
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-CEZEVILU.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../cloud/src/api/core.ts"],
|
|
4
|
+
"sourcesContent": ["const DEFAULT_API_TIMEOUT_MS = 30_000;\nconst DEFAULT_API_RESPONSE_BYTES = 8 * 1024 * 1024;\nexport const LONG_STREAM_API_OPTIONS = { timeoutMs: 15 * 60 * 1000, maxResponseBytes: 64 * 1024 * 1024 } as const;\n\nexport type ApiFetchOptions = RequestInit & {\n /** Generic services always use their explicit bearer token, regardless of prefix. */\n explicitBearerAuth?: boolean;\n timeoutMs?: number;\n maxResponseBytes?: number;\n};\n\nexport class ApiTimeoutError extends Error {\n readonly code = \"OPENPOND_API_TIMEOUT\";\n\n constructor(readonly timeoutMs: number, readonly requestUrl: string) {\n super(`API request timed out after ${timeoutMs}ms: ${requestUrl}`);\n this.name = \"ApiTimeoutError\";\n }\n}\n\nexport class ApiResponseTooLargeError extends Error {\n readonly code = \"OPENPOND_API_RESPONSE_TOO_LARGE\";\n\n constructor(readonly maximumBytes: number, readonly requestUrl: string) {\n super(`API response exceeded ${maximumBytes} bytes: ${requestUrl}`);\n this.name = \"ApiResponseTooLargeError\";\n }\n}\n\nexport class OpenPondApiError extends Error {\n readonly code: string;\n\n constructor(\n readonly status: number,\n errorCode: string | null,\n label: string,\n readonly apiMessage: string | null = null,\n ) {\n const detail = apiMessage || errorCode;\n super(`${label} failed: ${status}${detail ? ` ${detail}` : \"\"}`);\n this.name = \"OpenPondApiError\";\n this.code = errorCode || \"OPENPOND_API_ERROR\";\n }\n}\n\nexport async function apiFetch(\n baseUrl: string,\n token: string | null,\n requestPath: string,\n options: ApiFetchOptions = {},\n): Promise<Response> {\n const { timeoutMs = DEFAULT_API_TIMEOUT_MS, maxResponseBytes = DEFAULT_API_RESPONSE_BYTES, explicitBearerAuth = false, ...init } = options;\n const requestUrl = `${baseUrl}${requestPath}`;\n const headers = new Headers(init.headers);\n headers.set(\"Content-Type\", \"application/json\");\n const apiKey = !explicitBearerAuth ? process.env.OPENPOND_API_KEY : undefined;\n const trimmedToken = token?.trim() || \"\";\n const tokenIsApiKey = !explicitBearerAuth && trimmedToken.startsWith(\"opk_\");\n const effectiveApiKey = apiKey || (tokenIsApiKey ? trimmedToken : null);\n if (effectiveApiKey && !headers.has(\"openpond-api-key\")) headers.set(\"openpond-api-key\", effectiveApiKey);\n if (token) {\n headers.set(\"Authorization\", tokenIsApiKey ? `ApiKey ${trimmedToken}` : `Bearer ${token}`);\n } else if (apiKey && !headers.has(\"Authorization\")) {\n headers.set(\"Authorization\", `ApiKey ${apiKey}`);\n }\n\n const timeoutController = new AbortController();\n const timeoutError = new ApiTimeoutError(timeoutMs, requestUrl);\n const timer = timeoutMs > 0\n ? setTimeout(() => timeoutController.abort(timeoutError), timeoutMs)\n : null;\n timer?.unref?.();\n const signal = composedSignal(init.signal, timeoutController.signal, timeoutMs);\n const cleanup = () => {\n if (timer) clearTimeout(timer);\n };\n\n try {\n const response = await fetch(requestUrl, { ...init, headers, signal });\n return boundedResponse(response, {\n cleanup,\n maximumBytes: maxResponseBytes,\n requestUrl,\n timeoutController,\n timeoutError,\n });\n } catch (error) {\n cleanup();\n if (timeoutController.signal.aborted) throw timeoutError;\n throw error;\n }\n}\n\nexport async function readApiJson<T>(response: Response, label: string): Promise<T> {\n let payload: T & { error?: unknown; message?: unknown };\n try {\n const text = await response.text();\n payload = (text ? JSON.parse(text) : {}) as T & { error?: unknown; message?: unknown };\n } catch (error) {\n if (error instanceof ApiTimeoutError || error instanceof ApiResponseTooLargeError) throw error;\n payload = {} as T & { error?: unknown; message?: unknown };\n }\n if (!response.ok) {\n const errorCode = typeof payload.error === \"string\" ? payload.error : null;\n const apiMessage =\n typeof payload.message === \"string\" ? payload.message : null;\n throw new OpenPondApiError(response.status, errorCode, label, apiMessage);\n }\n return payload as T;\n}\n\nfunction boundedResponse(\n response: Response,\n input: {\n cleanup: () => void;\n maximumBytes: number;\n requestUrl: string;\n timeoutController: AbortController;\n timeoutError: ApiTimeoutError;\n },\n): Response {\n if (!response.body) {\n input.cleanup();\n return response;\n }\n const contentLength = Number(response.headers.get(\"content-length\"));\n if (input.maximumBytes > 0 && Number.isFinite(contentLength) && contentLength > input.maximumBytes) {\n input.cleanup();\n void response.body.cancel();\n throw new ApiResponseTooLargeError(input.maximumBytes, input.requestUrl);\n }\n\n const reader = response.body.getReader();\n let receivedBytes = 0;\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const result = await reader.read();\n if (result.done) {\n input.cleanup();\n controller.close();\n return;\n }\n receivedBytes += result.value.byteLength;\n if (input.maximumBytes > 0 && receivedBytes > input.maximumBytes) {\n input.cleanup();\n await reader.cancel();\n controller.error(new ApiResponseTooLargeError(input.maximumBytes, input.requestUrl));\n return;\n }\n controller.enqueue(result.value);\n } catch (error) {\n input.cleanup();\n controller.error(input.timeoutController.signal.aborted ? input.timeoutError : error);\n }\n },\n async cancel(reason) {\n input.cleanup();\n await reader.cancel(reason);\n },\n });\n return new Response(body, {\n headers: response.headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\nfunction composedSignal(\n callerSignal: AbortSignal | null | undefined,\n timeoutSignal: AbortSignal,\n timeoutMs: number,\n): AbortSignal | undefined {\n if (timeoutMs <= 0) return callerSignal ?? undefined;\n return callerSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : timeoutSignal;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
apiFetch,
|
|
3
3
|
readApiJson
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CEZEVILU.js";
|
|
5
5
|
|
|
6
6
|
// src/project-actions.ts
|
|
7
7
|
import { promises as fs } from "node:fs";
|
|
@@ -80,4 +80,4 @@ function projectActionPath(projectId, suffix, teamId) {
|
|
|
80
80
|
export {
|
|
81
81
|
OpenPondProjectActionsClient
|
|
82
82
|
};
|
|
83
|
-
//# sourceMappingURL=chunk-
|
|
83
|
+
//# sourceMappingURL=chunk-IWT6JUZD.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
apiFetch,
|
|
3
3
|
readApiJson
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CEZEVILU.js";
|
|
5
5
|
|
|
6
6
|
// src/workflows.ts
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
@@ -77,4 +77,4 @@ function requiredId(value, label) {
|
|
|
77
77
|
export {
|
|
78
78
|
OpenPondWorkflowsClient
|
|
79
79
|
};
|
|
80
|
-
//# sourceMappingURL=chunk-
|
|
80
|
+
//# sourceMappingURL=chunk-MEKWESBF.js.map
|
package/dist/index.js
CHANGED
|
@@ -5,18 +5,18 @@ import {
|
|
|
5
5
|
import "./chunk-5FBPNWT4.js";
|
|
6
6
|
import {
|
|
7
7
|
OpenPondProjectActionsClient
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IWT6JUZD.js";
|
|
9
9
|
import {
|
|
10
10
|
OpenPondProfileActionsClient
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-2DMYAJLS.js";
|
|
12
12
|
import {
|
|
13
13
|
OpenPondWorkflowsClient
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-MEKWESBF.js";
|
|
15
15
|
import {
|
|
16
16
|
OpenPondApiError,
|
|
17
17
|
apiFetch,
|
|
18
18
|
readApiJson
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-CEZEVILU.js";
|
|
20
20
|
import "./chunk-LXXQVGQY.js";
|
|
21
21
|
import {
|
|
22
22
|
DEFAULT_REFINER_REVIEW_PROFILE,
|
|
@@ -630,14 +630,17 @@ var OpenPondSandboxInstanceClient = class {
|
|
|
630
630
|
apiKey;
|
|
631
631
|
apiRootUrl;
|
|
632
632
|
sandboxApiUrl;
|
|
633
|
+
customEndpoint;
|
|
633
634
|
constructor(options) {
|
|
634
635
|
this.apiKey = options.apiKey;
|
|
636
|
+
this.customEndpoint = options.customEndpoint ?? false;
|
|
635
637
|
this.sandboxApiUrl = normalizeSandboxApiUrl(options.sandboxApiUrl ?? options.baseUrl ?? DEFAULT_OPENPOND_API_BASE_URL);
|
|
636
638
|
this.apiRootUrl = apiRootUrlFromSandboxApiUrl(this.sandboxApiUrl);
|
|
637
639
|
}
|
|
638
640
|
create(input, options = {}) {
|
|
639
641
|
return this.request("", {
|
|
640
642
|
method: "POST",
|
|
643
|
+
...this.customEndpoint ? { timeoutMs: 18e4 } : {},
|
|
641
644
|
headers: asyncRequestHeaders(options),
|
|
642
645
|
body: JSON.stringify(input)
|
|
643
646
|
}).then((payload) => payload.sandbox);
|
|
@@ -940,11 +943,11 @@ var OpenPondSandboxInstanceClient = class {
|
|
|
940
943
|
});
|
|
941
944
|
}
|
|
942
945
|
async request(path, init = {}) {
|
|
943
|
-
const response = await apiFetch(this.sandboxApiUrl, this.apiKey, path, init);
|
|
946
|
+
const response = await apiFetch(this.sandboxApiUrl, this.apiKey, path, this.customEndpoint ? { ...init, explicitBearerAuth: true, redirect: "error" } : init);
|
|
944
947
|
return readApiJson(response, "Sandbox request");
|
|
945
948
|
}
|
|
946
949
|
async requestApiRoot(path, init = {}) {
|
|
947
|
-
const response = await apiFetch(this.apiRootUrl, this.apiKey, path, init);
|
|
950
|
+
const response = await apiFetch(this.apiRootUrl, this.apiKey, path, this.customEndpoint ? { ...init, explicitBearerAuth: true, redirect: "error" } : init);
|
|
948
951
|
return readApiJson(response, "OpenPond API request");
|
|
949
952
|
}
|
|
950
953
|
};
|
|
@@ -1834,6 +1837,77 @@ async function* streamHostedChatTurn(options) {
|
|
|
1834
1837
|
}
|
|
1835
1838
|
}
|
|
1836
1839
|
|
|
1840
|
+
// src/work-sandbox.ts
|
|
1841
|
+
function workSandbox(client, custom) {
|
|
1842
|
+
return {
|
|
1843
|
+
supportsResume: !custom,
|
|
1844
|
+
get: (...args) => client.get(...args),
|
|
1845
|
+
start: custom ? async () => {
|
|
1846
|
+
throw new Error("This runtime does not support resuming a stopped guest; start fresh Work with saved outputs");
|
|
1847
|
+
} : (...args) => client.start(...args),
|
|
1848
|
+
exec: (id, input) => client.exec(id, custom ? { ...input, timeoutSeconds: Math.min(input.timeoutSeconds ?? 30, 60) } : input),
|
|
1849
|
+
mkdir: (...args) => client.mkdir(...args),
|
|
1850
|
+
uploadFile: (...args) => client.uploadFile(...args),
|
|
1851
|
+
uploadFileBase64: (...args) => client.uploadFileBase64(...args),
|
|
1852
|
+
listFiles: (...args) => client.listFiles(...args),
|
|
1853
|
+
downloadFileResponse: (...args) => client.downloadFileResponse(...args),
|
|
1854
|
+
stop: (...args) => client.stop(...args),
|
|
1855
|
+
delete: (...args) => client.delete(...args),
|
|
1856
|
+
createWork: ({ requestId, repo, budgetUsd, metadata }) => {
|
|
1857
|
+
if (custom) {
|
|
1858
|
+
if (repo?.trim()) throw new Error("This runtime does not support repository provisioning; provide Work inputs instead");
|
|
1859
|
+
if (budgetUsd !== void 0) throw new Error("Hosted spending budgets are not supported by this runtime");
|
|
1860
|
+
const request = { resources: custom.resources ?? { cpu: 1, memoryGb: 2, diskGb: 10 }, ...requestId ? { requestId } : {} };
|
|
1861
|
+
return client.create(request);
|
|
1862
|
+
}
|
|
1863
|
+
const budget = budgetUsd?.trim() || "1.00";
|
|
1864
|
+
return client.create({
|
|
1865
|
+
...repo?.trim() ? { repo: repo.trim() } : {},
|
|
1866
|
+
runtimeProfileId: "openpond-work-v1",
|
|
1867
|
+
resources: { cpu: 2, memoryGb: 4, diskGb: 16 },
|
|
1868
|
+
budget: { maxUsd: budget },
|
|
1869
|
+
quotas: { maxSpendUsd: budget, maxDurationSeconds: 3600, idleTimeoutSeconds: 900, maxCommands: 200, maxOpenPorts: 4 },
|
|
1870
|
+
metadata: { source: "openpond-sdk-work", ...metadata, ...requestId ? { workRequestId: requestId } : {} }
|
|
1871
|
+
}, { async: true });
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
function configuredEndpoint(value, name) {
|
|
1876
|
+
const endpoint = new URL(value);
|
|
1877
|
+
if (!["http:", "https:"].includes(endpoint.protocol) || endpoint.username || endpoint.password || endpoint.search || endpoint.hash)
|
|
1878
|
+
throw new Error(`${name} must be an HTTP(S) endpoint without embedded credentials, query or fragment`);
|
|
1879
|
+
return endpoint.toString().replace(/\/$/, "");
|
|
1880
|
+
}
|
|
1881
|
+
function configuredKey(value, name) {
|
|
1882
|
+
if (!value?.trim()) throw new Error(`${name} is required`);
|
|
1883
|
+
return value.trim();
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
// src/work-model.ts
|
|
1887
|
+
import { z } from "zod";
|
|
1888
|
+
var completionSchema = z.object({
|
|
1889
|
+
choices: z.array(z.object({ message: z.object({
|
|
1890
|
+
content: z.string().nullable().optional(),
|
|
1891
|
+
tool_calls: z.array(z.object({
|
|
1892
|
+
id: z.string().min(1),
|
|
1893
|
+
type: z.literal("function"),
|
|
1894
|
+
function: z.object({ name: z.string().min(1), arguments: z.string() })
|
|
1895
|
+
})).optional()
|
|
1896
|
+
}) })).min(1)
|
|
1897
|
+
});
|
|
1898
|
+
async function workModelTurn(options, custom) {
|
|
1899
|
+
if (!custom) return sendHostedChatTurn(options);
|
|
1900
|
+
const response = await fetch(`${options.apiBaseUrl}/chat/completions`, {
|
|
1901
|
+
method: "POST",
|
|
1902
|
+
headers: { authorization: `Bearer ${options.token}`, "content-type": "application/json" },
|
|
1903
|
+
body: JSON.stringify({ model: options.model, messages: options.messages, tools: options.tools, tool_choice: "auto", stream: false }),
|
|
1904
|
+
signal: options.signal,
|
|
1905
|
+
redirect: "error"
|
|
1906
|
+
});
|
|
1907
|
+
if (!response.ok) throw new Error(`Configured model request failed (${response.status})`);
|
|
1908
|
+
return completionSchema.parse(await response.json());
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1837
1911
|
// src/work.ts
|
|
1838
1912
|
var DEFAULT_MODEL = "openpond-chat";
|
|
1839
1913
|
var DEFAULT_MAX_STEPS = 24;
|
|
@@ -1850,11 +1924,15 @@ var OpenPondWorkClient = class {
|
|
|
1850
1924
|
#apiBaseUrl;
|
|
1851
1925
|
#chatApiBaseUrl;
|
|
1852
1926
|
#sandboxes;
|
|
1927
|
+
#defaultModel;
|
|
1928
|
+
#customModel;
|
|
1853
1929
|
constructor(input) {
|
|
1854
1930
|
this.#apiKey = input.apiKey;
|
|
1855
1931
|
this.#apiBaseUrl = input.apiBaseUrl;
|
|
1856
1932
|
this.#chatApiBaseUrl = input.chatApiBaseUrl;
|
|
1857
|
-
this.#sandboxes = input.sandboxes;
|
|
1933
|
+
this.#sandboxes = workSandbox(input.sandboxes, input.sandboxConfig);
|
|
1934
|
+
this.#defaultModel = input.defaultModel ?? DEFAULT_MODEL;
|
|
1935
|
+
this.#customModel = input.customModel ?? false;
|
|
1858
1936
|
}
|
|
1859
1937
|
async run(input) {
|
|
1860
1938
|
const prompt = input.prompt.trim();
|
|
@@ -1889,10 +1967,10 @@ var OpenPondWorkClient = class {
|
|
|
1889
1967
|
for (let step = 1; step <= maxSteps; step += 1) {
|
|
1890
1968
|
input.signal?.throwIfAborted();
|
|
1891
1969
|
await emit({ type: "status", message: `Thinking \xB7 step ${step}` });
|
|
1892
|
-
const completion = await
|
|
1970
|
+
const completion = await workModelTurn({
|
|
1893
1971
|
apiBaseUrl: this.#chatApiBaseUrl,
|
|
1894
1972
|
token: this.#apiKey,
|
|
1895
|
-
model: input.model?.trim() ||
|
|
1973
|
+
model: input.model?.trim() || this.#defaultModel,
|
|
1896
1974
|
messages,
|
|
1897
1975
|
tools: WORK_TOOLS,
|
|
1898
1976
|
toolChoice: "auto",
|
|
@@ -1903,7 +1981,7 @@ var OpenPondWorkClient = class {
|
|
|
1903
1981
|
apiBaseUrl: this.#apiBaseUrl,
|
|
1904
1982
|
...input.metadata
|
|
1905
1983
|
}
|
|
1906
|
-
});
|
|
1984
|
+
}, this.#customModel);
|
|
1907
1985
|
const choice = completion.choices?.[0];
|
|
1908
1986
|
const assistantText = choice?.message?.content?.trim() ?? "";
|
|
1909
1987
|
const toolCalls = choice?.message?.tool_calls ?? [];
|
|
@@ -1932,6 +2010,7 @@ var OpenPondWorkClient = class {
|
|
|
1932
2010
|
return result;
|
|
1933
2011
|
}
|
|
1934
2012
|
for (const [index, toolCall] of toolCalls.entries()) {
|
|
2013
|
+
input.signal?.throwIfAborted();
|
|
1935
2014
|
const result = await this.#executeTool(
|
|
1936
2015
|
sandbox.id,
|
|
1937
2016
|
toolCall,
|
|
@@ -1958,9 +2037,14 @@ var OpenPondWorkClient = class {
|
|
|
1958
2037
|
}
|
|
1959
2038
|
}
|
|
1960
2039
|
async deleteSandbox(sandboxId) {
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2040
|
+
try {
|
|
2041
|
+
const sandbox = await this.#sandboxes.get(sandboxId);
|
|
2042
|
+
if (sandbox.state === "deleted") return;
|
|
2043
|
+
await this.#sandboxes.delete(sandboxId);
|
|
2044
|
+
} catch (error) {
|
|
2045
|
+
if (error instanceof OpenPondApiError && error.status === 404) return;
|
|
2046
|
+
throw error;
|
|
2047
|
+
}
|
|
1964
2048
|
}
|
|
1965
2049
|
async #stageInputs(sandboxId, inputs) {
|
|
1966
2050
|
if (inputs.length === 0) return;
|
|
@@ -2028,7 +2112,7 @@ var OpenPondWorkClient = class {
|
|
|
2028
2112
|
error: message
|
|
2029
2113
|
});
|
|
2030
2114
|
if ((input.cleanup ?? "keep") !== "keep") {
|
|
2031
|
-
await this.#
|
|
2115
|
+
await this.#preserveFailedOutputs(sandboxId, lifecycle, emit);
|
|
2032
2116
|
}
|
|
2033
2117
|
throw error;
|
|
2034
2118
|
}
|
|
@@ -2037,7 +2121,7 @@ var OpenPondWorkClient = class {
|
|
|
2037
2121
|
} else if ((input.cleanup ?? "keep") === "delete" && !input.discardOutputs) {
|
|
2038
2122
|
lifecycle.persistence.status = "failed";
|
|
2039
2123
|
lifecycle.persistence.error = "Deleting a Work sandbox with outputs requires persistOutput or discardOutputs: true";
|
|
2040
|
-
await this.#
|
|
2124
|
+
await this.#preserveFailedOutputs(sandboxId, lifecycle, emit);
|
|
2041
2125
|
throw new Error(lifecycle.persistence.error);
|
|
2042
2126
|
} else {
|
|
2043
2127
|
lifecycle.persistence.status = "not_requested";
|
|
@@ -2049,6 +2133,16 @@ var OpenPondWorkClient = class {
|
|
|
2049
2133
|
emit
|
|
2050
2134
|
);
|
|
2051
2135
|
}
|
|
2136
|
+
async #preserveFailedOutputs(sandboxId, lifecycle, emit) {
|
|
2137
|
+
if (this.#sandboxes.supportsResume) {
|
|
2138
|
+
await this.#cleanupSandbox(sandboxId, "stop", lifecycle, emit);
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
lifecycle.cleanup.status = "pending";
|
|
2142
|
+
lifecycle.cleanup.finalSandboxState = "running";
|
|
2143
|
+
lifecycle.cleanup.error = "Output persistence must be retried before guest deletion";
|
|
2144
|
+
await emit({ type: "cleanup", policy: lifecycle.cleanupPolicy, status: "pending", sandboxState: "running", error: lifecycle.cleanup.error });
|
|
2145
|
+
}
|
|
2052
2146
|
async #cleanupSandbox(sandboxId, policy, lifecycle, emit) {
|
|
2053
2147
|
if (policy === "keep") return;
|
|
2054
2148
|
lifecycle.cleanup.status = "running";
|
|
@@ -2109,24 +2203,7 @@ var OpenPondWorkClient = class {
|
|
|
2109
2203
|
const ready = await this.#waitUntilRunning(existing.id, input.signal);
|
|
2110
2204
|
return ready;
|
|
2111
2205
|
}
|
|
2112
|
-
const
|
|
2113
|
-
const created = await this.#sandboxes.create(
|
|
2114
|
-
{
|
|
2115
|
-
...input.repo?.trim() ? { repo: input.repo.trim() } : {},
|
|
2116
|
-
runtimeProfileId: "openpond-work-v1",
|
|
2117
|
-
resources: { cpu: 2, memoryGb: 4, diskGb: 16 },
|
|
2118
|
-
budget: { maxUsd: budgetUsd },
|
|
2119
|
-
quotas: {
|
|
2120
|
-
maxSpendUsd: budgetUsd,
|
|
2121
|
-
maxDurationSeconds: 3600,
|
|
2122
|
-
idleTimeoutSeconds: 900,
|
|
2123
|
-
maxCommands: 200,
|
|
2124
|
-
maxOpenPorts: 4
|
|
2125
|
-
},
|
|
2126
|
-
metadata: { source: "openpond-sdk-work", ...input.metadata }
|
|
2127
|
-
},
|
|
2128
|
-
{ async: true }
|
|
2129
|
-
);
|
|
2206
|
+
const created = await this.#sandboxes.createWork(input);
|
|
2130
2207
|
return this.#waitUntilRunning(created.id, input.signal);
|
|
2131
2208
|
}
|
|
2132
2209
|
async #waitUntilRunning(sandboxId, signal) {
|
|
@@ -2220,7 +2297,9 @@ function systemPrompt(sandboxId, hasInputs) {
|
|
|
2220
2297
|
"You are OpenPond Work, a careful coding agent operating in an isolated Linux sandbox.",
|
|
2221
2298
|
`The active sandbox is ${sandboxId}.`,
|
|
2222
2299
|
...hasInputs ? [
|
|
2223
|
-
`
|
|
2300
|
+
`The authoritative saved files for this turn are staged under /workspace/${WORK_INPUT_DIRECTORY}; their manifest is /workspace/${WORK_INPUT_MANIFEST}.`,
|
|
2301
|
+
"Before revising a previous output, read its staged file and manifest. Copy the staged input into the output directory before editing it; previous output paths may not exist in this sandbox.",
|
|
2302
|
+
"Preserve the actual file bytes. Never reconstruct a saved file from the conversation or claim to have preserved it without reading the staged input."
|
|
2224
2303
|
] : [],
|
|
2225
2304
|
"Use run_command to inspect the workspace, edit files, and validate your work.",
|
|
2226
2305
|
`Place completed user-facing files in ${WORK_OUTPUT_DIRECTORY}. The runtime collects new and revised files there automatically when the turn completes.`,
|
|
@@ -2381,20 +2460,35 @@ var OpenPondClient = class {
|
|
|
2381
2460
|
profileActions;
|
|
2382
2461
|
learning;
|
|
2383
2462
|
constructor(options) {
|
|
2384
|
-
const apiKey = options.apiKey
|
|
2385
|
-
if (!apiKey
|
|
2463
|
+
const apiKey = options.apiKey?.trim() ?? "";
|
|
2464
|
+
if (!apiKey && (!options.sandbox || !options.model))
|
|
2465
|
+
throw new Error("OpenPond API key is required when using a default sandbox or model");
|
|
2466
|
+
const sandbox = options.sandbox ? {
|
|
2467
|
+
...options.sandbox,
|
|
2468
|
+
endpoint: configuredEndpoint(options.sandbox.endpoint, "Sandbox endpoint"),
|
|
2469
|
+
apiKey: configuredKey(options.sandbox.apiKey, "Sandbox API key")
|
|
2470
|
+
} : void 0;
|
|
2471
|
+
const model = options.model ? {
|
|
2472
|
+
endpoint: configuredEndpoint(options.model.endpoint, "Model endpoint"),
|
|
2473
|
+
apiKey: configuredKey(options.model.apiKey, "Model API key"),
|
|
2474
|
+
model: configuredKey(options.model.model, "Model ID")
|
|
2475
|
+
} : void 0;
|
|
2386
2476
|
const apiBaseUrl = options.baseUrl?.trim() || "https://api.openpond.ai";
|
|
2387
2477
|
this.learning = (scope) => new OpenPondLearningClient({ apiKey, baseUrl: apiBaseUrl, scope });
|
|
2388
2478
|
this.sandboxes = createOpenPondSandboxClient({
|
|
2389
|
-
apiKey,
|
|
2479
|
+
apiKey: sandbox?.apiKey ?? apiKey,
|
|
2390
2480
|
baseUrl: apiBaseUrl,
|
|
2391
|
-
sandboxApiUrl: options.sandboxApiUrl
|
|
2481
|
+
sandboxApiUrl: sandbox?.endpoint ?? options.sandboxApiUrl,
|
|
2482
|
+
customEndpoint: Boolean(sandbox)
|
|
2392
2483
|
});
|
|
2393
2484
|
this.work = new OpenPondWorkClient({
|
|
2394
|
-
apiKey,
|
|
2485
|
+
apiKey: model?.apiKey ?? apiKey,
|
|
2395
2486
|
apiBaseUrl,
|
|
2396
|
-
chatApiBaseUrl: options.chatApiUrl?.trim() || resolveOpChatApiBaseUrl({ apiBaseUrl, env: {} }),
|
|
2397
|
-
sandboxes: this.sandboxes
|
|
2487
|
+
chatApiBaseUrl: model?.endpoint || options.chatApiUrl?.trim() || resolveOpChatApiBaseUrl({ apiBaseUrl, env: {} }),
|
|
2488
|
+
sandboxes: this.sandboxes,
|
|
2489
|
+
sandboxConfig: sandbox,
|
|
2490
|
+
defaultModel: model?.model,
|
|
2491
|
+
customModel: Boolean(model)
|
|
2398
2492
|
});
|
|
2399
2493
|
this.workflows = new OpenPondWorkflowsClient({ apiKey, apiBaseUrl });
|
|
2400
2494
|
this.actions = new OpenPondProjectActionsClient({ apiKey, apiBaseUrl });
|