openpond-sdk 0.3.3 → 0.5.0
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/MODEL_STARTERS.md +26 -0
- package/TASKSETS.md +55 -0
- package/dist/actions-local.js +67 -118
- package/dist/actions-local.js.map +4 -4
- package/dist/actions.js +4 -92
- package/dist/actions.js.map +4 -4
- package/dist/chunk-25TBEGXB.js +220 -0
- package/dist/chunk-25TBEGXB.js.map +7 -0
- package/dist/chunk-27ETSPHQ.js +83 -0
- package/dist/chunk-27ETSPHQ.js.map +7 -0
- package/dist/chunk-5PRP457R.js +477 -0
- package/dist/chunk-5PRP457R.js.map +7 -0
- package/dist/chunk-65D4C7HP.js +273 -0
- package/dist/chunk-65D4C7HP.js.map +7 -0
- package/dist/chunk-6LGGLXAM.js +2395 -0
- package/dist/chunk-6LGGLXAM.js.map +7 -0
- package/dist/chunk-747CMU2Y.js +222 -0
- package/dist/chunk-747CMU2Y.js.map +7 -0
- package/dist/chunk-7O5X7DBU.js +80 -0
- package/dist/chunk-7O5X7DBU.js.map +7 -0
- package/dist/chunk-A4ZDOZKP.js +115 -0
- package/dist/chunk-A4ZDOZKP.js.map +7 -0
- package/dist/chunk-APHPXQEA.js +155 -0
- package/dist/chunk-APHPXQEA.js.map +7 -0
- package/dist/chunk-AVW35YOH.js +574 -0
- package/dist/chunk-AVW35YOH.js.map +7 -0
- package/dist/chunk-EPJM7VEV.js +177 -0
- package/dist/chunk-EPJM7VEV.js.map +7 -0
- package/dist/chunk-EV4PKJWN.js +1373 -0
- package/dist/chunk-EV4PKJWN.js.map +7 -0
- package/dist/chunk-K5ZCYOZO.js +49 -0
- package/dist/chunk-K5ZCYOZO.js.map +7 -0
- package/dist/chunk-LXXQVGQY.js +1 -0
- package/dist/chunk-LXXQVGQY.js.map +7 -0
- package/dist/chunk-NF63YMOL.js +593 -0
- package/dist/chunk-NF63YMOL.js.map +7 -0
- package/dist/chunk-P27DQ65Z.js +138 -0
- package/dist/chunk-P27DQ65Z.js.map +7 -0
- package/dist/chunk-QLEJOCQX.js +72 -0
- package/dist/chunk-QLEJOCQX.js.map +7 -0
- package/dist/chunk-S7I45WJQ.js +57 -0
- package/dist/chunk-S7I45WJQ.js.map +7 -0
- package/dist/index.js +33 -2488
- package/dist/index.js.map +4 -4
- package/dist/learning.js +16 -2042
- package/dist/learning.js.map +4 -4
- package/dist/model-batch-review.js +5 -42
- package/dist/model-batch-review.js.map +3 -3
- package/dist/model-projects.js +29 -430
- package/dist/model-projects.js.map +3 -3
- package/dist/model-starter-attempts.js +13 -420
- package/dist/model-starter-attempts.js.map +4 -4
- package/dist/model-starter-catalog.js +17 -460
- package/dist/model-starter-catalog.js.map +4 -4
- package/dist/model-starters.js +32 -709
- package/dist/model-starters.js.map +4 -4
- package/dist/model-taskset-authoring.js +11 -44
- package/dist/model-taskset-authoring.js.map +3 -3
- package/dist/model-taskset-runs.js +196 -0
- package/dist/model-taskset-runs.js.map +7 -0
- package/dist/profile-actions.js +4 -211
- package/dist/profile-actions.js.map +3 -3
- package/dist/project-actions.js +4 -224
- package/dist/project-actions.js.map +3 -3
- package/dist/refiner.js +14 -554
- package/dist/refiner.js.map +4 -4
- package/dist/taskset-catalog.js +9 -104
- package/dist/taskset-catalog.js.map +3 -3
- package/dist/taskset-drafts.js +465 -0
- package/dist/taskset-drafts.js.map +7 -0
- package/dist/taskset-packages.js +946 -3089
- package/dist/taskset-packages.js.map +4 -4
- package/dist/training.js +43 -822
- package/dist/training.js.map +4 -4
- package/dist/types/packages/sdk/src/index.d.ts +3 -3
- package/dist/types/packages/sdk/src/index.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/learning-client.d.ts +130 -0
- package/dist/types/packages/sdk/src/learning-client.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/learning.d.ts +1 -129
- package/dist/types/packages/sdk/src/learning.d.ts.map +1 -1
- package/dist/types/packages/sdk/src/model-taskset-runs-contracts.d.ts +568 -0
- package/dist/types/packages/sdk/src/model-taskset-runs-contracts.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/model-taskset-runs.d.ts +722 -0
- package/dist/types/packages/sdk/src/model-taskset-runs.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-authored-contracts.d.ts +1170 -0
- package/dist/types/packages/sdk/src/taskset-authored-contracts.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-authored-files.d.ts +560 -0
- package/dist/types/packages/sdk/src/taskset-authored-files.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-authored-portable-release.d.ts +92 -0
- package/dist/types/packages/sdk/src/taskset-authored-portable-release.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-authored-tool-environment.d.ts +15 -0
- package/dist/types/packages/sdk/src/taskset-authored-tool-environment.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-authored-validation.d.ts +18 -0
- package/dist/types/packages/sdk/src/taskset-authored-validation.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-api-contracts.d.ts +1681 -0
- package/dist/types/packages/sdk/src/taskset-draft-api-contracts.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-authoring.d.ts +19 -0
- package/dist/types/packages/sdk/src/taskset-draft-authoring.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-client.d.ts +2713 -0
- package/dist/types/packages/sdk/src/taskset-draft-client.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-core.d.ts +1000 -0
- package/dist/types/packages/sdk/src/taskset-draft-core.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-dataset-artifacts.d.ts +429 -0
- package/dist/types/packages/sdk/src/taskset-draft-dataset-artifacts.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-dataset-sources.d.ts +284 -0
- package/dist/types/packages/sdk/src/taskset-draft-dataset-sources.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-document.d.ts +846 -0
- package/dist/types/packages/sdk/src/taskset-draft-document.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-files.d.ts +8 -0
- package/dist/types/packages/sdk/src/taskset-draft-files.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-harness-actions.d.ts +28 -0
- package/dist/types/packages/sdk/src/taskset-draft-harness-actions.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-manifests.d.ts +8 -0
- package/dist/types/packages/sdk/src/taskset-draft-manifests.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-package-compiler.d.ts +967 -0
- package/dist/types/packages/sdk/src/taskset-draft-package-compiler.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-publication.d.ts +10 -0
- package/dist/types/packages/sdk/src/taskset-draft-publication.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-source.d.ts +1297 -0
- package/dist/types/packages/sdk/src/taskset-draft-source.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-draft-workspace.d.ts +1597 -0
- package/dist/types/packages/sdk/src/taskset-draft-workspace.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-drafts.d.ts +16 -0
- package/dist/types/packages/sdk/src/taskset-drafts.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-package-grader-projection.d.ts +64 -0
- package/dist/types/packages/sdk/src/taskset-package-grader-projection.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-package-projection.d.ts +1514 -0
- package/dist/types/packages/sdk/src/taskset-package-projection.d.ts.map +1 -0
- package/dist/types/packages/sdk/src/taskset-packages.d.ts +6 -0
- package/dist/types/packages/sdk/src/taskset-packages.d.ts.map +1 -1
- package/dist/workflows.js +4 -221
- package/dist/workflows.js.map +3 -3
- package/package.json +11 -3
package/MODEL_STARTERS.md
CHANGED
|
@@ -119,3 +119,29 @@ Keep hidden case inputs and expected results in the private initial-state asset.
|
|
|
119
119
|
Ordinary task input is policy-visible. The service passes only each hidden case's
|
|
120
120
|
explicit `input` to candidate code; expected results stay with the authored grader.
|
|
121
121
|
See the Evals JavaScript environment contract for service fields and Node execution.
|
|
122
|
+
|
|
123
|
+
### Complete Taskset evaluation runs
|
|
124
|
+
|
|
125
|
+
`OpenPondModelTasksetRunsClient` from `openpond-sdk/model-taskset-runs` exposes
|
|
126
|
+
`create`, `get`, `list`, `cancel` and `result` through
|
|
127
|
+
`/v1/model-taskset-runs`. A request pins a Model attachment and an ordered
|
|
128
|
+
population of `{ receiptId, taskId, seed, fixtureId }` members. Receipt IDs are
|
|
129
|
+
unique within the run; hosted seeds are canonical integer strings between
|
|
130
|
+
`0` and `2147483647`. Requests support up to 10,000 members and never accept
|
|
131
|
+
replacement world state, verifier bytes or caller-generated scores.
|
|
132
|
+
|
|
133
|
+
Use `{ kind: "fixture" }` with each member's authored fixture ID to check a
|
|
134
|
+
package without claiming model execution. Use a `hosted_chat` policy with a
|
|
135
|
+
model ID and sampling/output limits for a model evaluation; those members
|
|
136
|
+
have `fixtureId: null`. A model evaluation pins both the provider snapshot and
|
|
137
|
+
the requested sampling configuration. Reusing an operation ID must return the
|
|
138
|
+
same admitted request or report a conflict.
|
|
139
|
+
|
|
140
|
+
Details retain the request, immutable public run manifest, policy snapshot and
|
|
141
|
+
current summary. Terminal results retain canonical receipts in admitted order
|
|
142
|
+
and the authored metric only for completed evaluations. Failed and cancelled
|
|
143
|
+
runs cannot publish a metric value; completed but entirely unscorable runs
|
|
144
|
+
retain a null metric value. The client verifies workspace, manifest,
|
|
145
|
+
population, grading role, metric references and result hashes on readback.
|
|
146
|
+
Hosts remain responsible for owner-authenticated evidence and durable
|
|
147
|
+
dispatch/cancellation; a content hash is not producer authentication.
|
package/TASKSETS.md
CHANGED
|
@@ -190,3 +190,58 @@ Model selection and retry receipts atomically. Bound Reward packages and reviewe
|
|
|
190
190
|
batches use their respective authoring graphs and are rejected by this ordinary
|
|
191
191
|
package compiler. Draft persistence, HTTP operations and editor controls are host
|
|
192
192
|
integration work.
|
|
193
|
+
|
|
194
|
+
## Shared draft documents and compilation
|
|
195
|
+
|
|
196
|
+
`openpond-sdk/taskset-drafts` exports the complete `TasksetDraftSchema`, the
|
|
197
|
+
authoring validator and the immutable `TasksetDraftWorkspaceSchema`. Desktop
|
|
198
|
+
imports these same contracts and authoring functions. A workspace contains one
|
|
199
|
+
draft document and hashed source files; managed form manifests are synthesized
|
|
200
|
+
from the document instead of stored as a second editable copy.
|
|
201
|
+
|
|
202
|
+
Use `saveTasksetDraftWorkspaceDocument` for form edits and
|
|
203
|
+
`saveTasksetDraftWorkspaceFile` for file edits. Both require the expected draft
|
|
204
|
+
revision and return a new workspace. File edits also compare the previous file
|
|
205
|
+
hash, preserve exact UTF-8/base64 bytes and reject managed manifests or retained
|
|
206
|
+
source archives. Published workspaces cannot be edited. The JSON workspace is
|
|
207
|
+
limited to 64 MiB; editable file content is limited to 6 MB.
|
|
208
|
+
|
|
209
|
+
Server-side package helpers are exported from `openpond-sdk/taskset-packages`:
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
const projected = prepareImportedTasksetPackage({
|
|
213
|
+
package: source, profileId: owner.scopeId, name, createdAt: now,
|
|
214
|
+
});
|
|
215
|
+
const initialized = prepareTasksetDraftSource({
|
|
216
|
+
source, preparation, expectedModelRevision,
|
|
217
|
+
sourceDraft: tasksetDraftFromTaskset(projected.taskset, now),
|
|
218
|
+
});
|
|
219
|
+
const workspace = materializeTasksetDraftWorkspace({ initialized, source });
|
|
220
|
+
const publishedPackage = compileModelTasksetDraftWorkspace({
|
|
221
|
+
workspace, preparation, adapterId: "my-authoring-host", now,
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`tasksetDraftFromTaskset` is exported from `openpond-sdk/taskset-drafts`.
|
|
226
|
+
Retain the original `preparation` and source package before initialization.
|
|
227
|
+
Compilation verifies that preparation, applies the same publication validation
|
|
228
|
+
as Desktop, pins changed code and private assets, and seals an owned package.
|
|
229
|
+
It does not execute a model, run graders, select a Taskset or commit host state.
|
|
230
|
+
Imported source still requires explicit source review before publication.
|
|
231
|
+
|
|
232
|
+
## Hosted draft client contract
|
|
233
|
+
|
|
234
|
+
`OpenPondTasksetDraftClient` from `openpond-sdk/taskset-drafts` defines the
|
|
235
|
+
scoped `/v1/models/:modelId/taskset-drafts` protocol. Construct it in server code
|
|
236
|
+
with `baseUrl`, `apiKey` and `teamId`. It supports source inspection,
|
|
237
|
+
initialization, listing, document/file reads and edits, explicit Model refresh,
|
|
238
|
+
validation, publication and deletion. Hosting these endpoints requires a server
|
|
239
|
+
implementation; exporting this client alone does not make them available.
|
|
240
|
+
|
|
241
|
+
Validation pins the exact draft revision and workspace hash and returns the
|
|
242
|
+
compiled package hash and Taskset reference. Publication requires those same
|
|
243
|
+
values plus an operation ID. The host must atomically compare the draft and
|
|
244
|
+
Model revisions, publish/select the package, finalize the draft and retain the
|
|
245
|
+
retry receipt. The client verifies response scope, revisions and file hashes;
|
|
246
|
+
it never retries writes automatically. Hosts own authorization, durable storage,
|
|
247
|
+
pagination, transaction isolation and idempotent recovery.
|
package/dist/actions-local.js
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PROJECT_ACTION_CONFIG_PATH,
|
|
3
|
+
isProjectActionDefinition,
|
|
4
|
+
loadProjectActionConfiguration,
|
|
5
|
+
resolveProjectActionRuntime
|
|
6
|
+
} from "./chunk-P27DQ65Z.js";
|
|
7
|
+
|
|
1
8
|
// ../actions/src/local.ts
|
|
2
9
|
import { randomUUID } from "node:crypto";
|
|
3
10
|
import { spawn } from "node:child_process";
|
|
4
|
-
import { promises as fs5 } from "node:fs";
|
|
5
|
-
import path5 from "node:path";
|
|
6
|
-
|
|
7
|
-
// ../actions/src/build.ts
|
|
8
11
|
import { promises as fs4 } from "node:fs";
|
|
9
12
|
import path4 from "node:path";
|
|
13
|
+
|
|
14
|
+
// ../actions/src/build.ts
|
|
15
|
+
import { promises as fs3 } from "node:fs";
|
|
16
|
+
import path3 from "node:path";
|
|
10
17
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
18
|
import { build } from "esbuild";
|
|
12
19
|
|
|
13
|
-
// ../actions/src/define-action.ts
|
|
14
|
-
import { z } from "zod";
|
|
15
|
-
function isProjectActionDefinition(value) {
|
|
16
|
-
return Boolean(
|
|
17
|
-
value && typeof value === "object" && value.kind === "openpond-project-action" && typeof value.id === "string" && typeof value.run === "function"
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
20
|
// ../actions/src/schema.ts
|
|
22
|
-
import { z
|
|
21
|
+
import { z } from "zod";
|
|
23
22
|
function projectActionJsonSchema(schema) {
|
|
24
|
-
return
|
|
23
|
+
return z.toJSONSchema(schema, { unrepresentable: "any" });
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
// ../actions/src/catalog.ts
|
|
@@ -90,92 +89,42 @@ function toCatalogEntry(action) {
|
|
|
90
89
|
};
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
// ../actions/src/
|
|
92
|
+
// ../actions/src/discovery.ts
|
|
94
93
|
import { promises as fs } from "node:fs";
|
|
95
94
|
import path from "node:path";
|
|
96
|
-
import { z as z3 } from "zod";
|
|
97
|
-
var PROJECT_ACTION_CONFIG_PATH = "openpond/project-actions.json";
|
|
98
|
-
var connectionSchema = z3.object({
|
|
99
|
-
values: z3.record(z3.string(), z3.unknown()).optional().default({}),
|
|
100
|
-
environment: z3.record(z3.string(), z3.string().trim().min(1)).optional().default({})
|
|
101
|
-
}).strict();
|
|
102
|
-
var configSchema = z3.object({
|
|
103
|
-
sourceDirectory: z3.string().trim().min(1).optional(),
|
|
104
|
-
outputDirectory: z3.string().trim().min(1).optional(),
|
|
105
|
-
environment: z3.record(z3.string(), z3.string().trim().min(1)).optional().default({}),
|
|
106
|
-
connections: z3.record(z3.string(), connectionSchema).optional().default({})
|
|
107
|
-
}).strict();
|
|
108
|
-
async function loadProjectActionConfiguration(projectRoot) {
|
|
109
|
-
const resolvedRoot = path.resolve(projectRoot);
|
|
110
|
-
const configPath = path.join(resolvedRoot, PROJECT_ACTION_CONFIG_PATH);
|
|
111
|
-
const raw = await fs.readFile(configPath, "utf8").catch((error) => {
|
|
112
|
-
if (error.code === "ENOENT") return null;
|
|
113
|
-
throw error;
|
|
114
|
-
});
|
|
115
|
-
if (raw === null) return configSchema.parse({});
|
|
116
|
-
let value;
|
|
117
|
-
try {
|
|
118
|
-
value = JSON.parse(raw);
|
|
119
|
-
} catch (error) {
|
|
120
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
121
|
-
throw new Error(`${PROJECT_ACTION_CONFIG_PATH} is not valid JSON: ${message}`);
|
|
122
|
-
}
|
|
123
|
-
return configSchema.parse(value);
|
|
124
|
-
}
|
|
125
|
-
function resolveProjectActionRuntime(config, hostEnvironment = process.env) {
|
|
126
|
-
const environment = {};
|
|
127
|
-
for (const [runtimeName, hostName] of Object.entries(config.environment)) {
|
|
128
|
-
const value = hostEnvironment[hostName];
|
|
129
|
-
if (value !== void 0) environment[runtimeName] = value;
|
|
130
|
-
}
|
|
131
|
-
const connections = {};
|
|
132
|
-
for (const [name, descriptor] of Object.entries(config.connections)) {
|
|
133
|
-
const value = { ...descriptor.values };
|
|
134
|
-
for (const [property, hostName] of Object.entries(descriptor.environment)) {
|
|
135
|
-
const environmentValue = hostEnvironment[hostName];
|
|
136
|
-
if (environmentValue !== void 0) value[property] = environmentValue;
|
|
137
|
-
}
|
|
138
|
-
connections[name] = value;
|
|
139
|
-
}
|
|
140
|
-
return { environment, connections };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// ../actions/src/discovery.ts
|
|
144
|
-
import { promises as fs2 } from "node:fs";
|
|
145
|
-
import path2 from "node:path";
|
|
146
95
|
var ACTION_FILE = /\.(?:[cm]?[jt]s)$/i;
|
|
147
96
|
var IGNORED_FILE = /(?:\.d\.ts|\.test\.[cm]?[jt]s|\.spec\.[cm]?[jt]s)$/i;
|
|
148
97
|
async function discoverProjectActionFiles(input) {
|
|
149
|
-
const projectRoot =
|
|
150
|
-
const sourceRoot =
|
|
98
|
+
const projectRoot = path.resolve(input.projectRoot);
|
|
99
|
+
const sourceRoot = path.resolve(projectRoot, input.sourceDirectory ?? "openpond/actions");
|
|
151
100
|
if (!isWithin(projectRoot, sourceRoot)) {
|
|
152
101
|
throw new Error("Project Action source directory must stay inside the Project root.");
|
|
153
102
|
}
|
|
154
|
-
const stats = await
|
|
103
|
+
const stats = await fs.stat(sourceRoot).catch(() => null);
|
|
155
104
|
if (!stats?.isDirectory()) {
|
|
156
105
|
throw new Error(`Project Action source directory does not exist: ${sourceRoot}`);
|
|
157
106
|
}
|
|
158
107
|
const files = await walk(sourceRoot);
|
|
159
|
-
const actions = files.filter((file) => ACTION_FILE.test(file) && !IGNORED_FILE.test(file)).map((file) =>
|
|
108
|
+
const actions = files.filter((file) => ACTION_FILE.test(file) && !IGNORED_FILE.test(file)).map((file) => path.relative(projectRoot, file).split(path.sep).join("/")).sort();
|
|
160
109
|
if (actions.length === 0) {
|
|
161
110
|
throw new Error(`No Project Action files were found under ${sourceRoot}.`);
|
|
162
111
|
}
|
|
163
112
|
return { projectRoot, sourceRoot, files: actions };
|
|
164
113
|
}
|
|
165
114
|
async function walk(directory) {
|
|
166
|
-
const entries = await
|
|
115
|
+
const entries = await fs.readdir(directory, { withFileTypes: true });
|
|
167
116
|
const files = [];
|
|
168
117
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
169
118
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
170
|
-
const target =
|
|
119
|
+
const target = path.join(directory, entry.name);
|
|
171
120
|
if (entry.isDirectory()) files.push(...await walk(target));
|
|
172
121
|
else if (entry.isFile()) files.push(target);
|
|
173
122
|
}
|
|
174
123
|
return files;
|
|
175
124
|
}
|
|
176
125
|
function isWithin(root, target) {
|
|
177
|
-
const relative =
|
|
178
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
126
|
+
const relative = path.relative(root, target);
|
|
127
|
+
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
179
128
|
}
|
|
180
129
|
|
|
181
130
|
// ../actions/src/hash.ts
|
|
@@ -196,15 +145,15 @@ function sortValue(value) {
|
|
|
196
145
|
}
|
|
197
146
|
|
|
198
147
|
// ../actions/src/setup.ts
|
|
199
|
-
import { promises as
|
|
148
|
+
import { promises as fs2 } from "node:fs";
|
|
200
149
|
import { createRequire } from "node:module";
|
|
201
|
-
import
|
|
150
|
+
import path2 from "node:path";
|
|
202
151
|
async function validateProjectActionStaticSetup(projectRoot, requirements) {
|
|
203
152
|
for (const requirement of requirements) {
|
|
204
153
|
if (requirement.required === false) continue;
|
|
205
154
|
if (requirement.kind === "package") {
|
|
206
155
|
try {
|
|
207
|
-
createRequire(
|
|
156
|
+
createRequire(path2.join(projectRoot, "package.json")).resolve(requirement.name);
|
|
208
157
|
} catch {
|
|
209
158
|
throw new Error(`Project Action package is not installed: ${requirement.name}`);
|
|
210
159
|
}
|
|
@@ -228,10 +177,10 @@ async function validateProjectActionRunSetup(projectRoot, requirements, request)
|
|
|
228
177
|
}
|
|
229
178
|
async function executableExists(name) {
|
|
230
179
|
if (!name.trim() || name.includes("/") || name.includes("\\")) return false;
|
|
231
|
-
for (const directory of (process.env.PATH ?? "").split(
|
|
232
|
-
const candidates = process.platform === "win32" ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").map((extension) =>
|
|
180
|
+
for (const directory of (process.env.PATH ?? "").split(path2.delimiter).filter(Boolean)) {
|
|
181
|
+
const candidates = process.platform === "win32" ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").map((extension) => path2.join(directory, `${name}${extension}`)) : [path2.join(directory, name)];
|
|
233
182
|
for (const candidate of candidates) {
|
|
234
|
-
if (await
|
|
183
|
+
if (await fs2.access(candidate).then(() => true).catch(() => false)) return true;
|
|
235
184
|
}
|
|
236
185
|
}
|
|
237
186
|
return false;
|
|
@@ -245,24 +194,24 @@ async function buildProjectActions(input) {
|
|
|
245
194
|
projectRoot: input.projectRoot,
|
|
246
195
|
sourceDirectory: input.sourceDirectory ?? configuration.sourceDirectory
|
|
247
196
|
});
|
|
248
|
-
const outputDirectory =
|
|
197
|
+
const outputDirectory = path3.resolve(
|
|
249
198
|
discovered.projectRoot,
|
|
250
199
|
input.outputDirectory ?? configuration.outputDirectory ?? DEFAULT_PROJECT_ACTION_OUTPUT_DIRECTORY
|
|
251
200
|
);
|
|
252
201
|
assertWithinProject(discovered.projectRoot, outputDirectory);
|
|
253
|
-
await
|
|
254
|
-
const entryPath =
|
|
255
|
-
const bundlePath =
|
|
256
|
-
const runnerPath =
|
|
257
|
-
const registryPath =
|
|
258
|
-
const manifestPath =
|
|
202
|
+
await fs3.mkdir(outputDirectory, { recursive: true });
|
|
203
|
+
const entryPath = path3.join(outputDirectory, "entry.mjs");
|
|
204
|
+
const bundlePath = path3.join(outputDirectory, "bundle.mjs");
|
|
205
|
+
const runnerPath = path3.join(outputDirectory, "runner.mjs");
|
|
206
|
+
const registryPath = path3.join(outputDirectory, "action-registry.json");
|
|
207
|
+
const manifestPath = path3.join(outputDirectory, "build-manifest.json");
|
|
259
208
|
const imports = discovered.files.map((file, index) => {
|
|
260
|
-
const relative =
|
|
209
|
+
const relative = path3.relative(outputDirectory, path3.join(discovered.projectRoot, file)).split(path3.sep).join("/");
|
|
261
210
|
const specifier = relative.startsWith(".") ? relative : `./${relative}`;
|
|
262
211
|
return `import * as actionModule${index} from ${JSON.stringify(specifier)};`;
|
|
263
212
|
});
|
|
264
213
|
const modules = discovered.files.map((_file, index) => `actionModule${index}`).join(", ");
|
|
265
|
-
await
|
|
214
|
+
await fs3.writeFile(
|
|
266
215
|
entryPath,
|
|
267
216
|
[
|
|
268
217
|
...imports,
|
|
@@ -291,22 +240,22 @@ async function buildProjectActions(input) {
|
|
|
291
240
|
await validateProjectActionStaticSetup(discovered.projectRoot, action.setup);
|
|
292
241
|
}
|
|
293
242
|
const registry = createProjectActionRegistry(actions);
|
|
294
|
-
await
|
|
295
|
-
await
|
|
296
|
-
const bundleHash = sha256(await
|
|
243
|
+
await fs3.writeFile(registryPath, canonicalJson(registry), "utf8");
|
|
244
|
+
await fs3.writeFile(runnerPath, runtimeSource(), { encoding: "utf8", mode: 493 });
|
|
245
|
+
const bundleHash = sha256(await fs3.readFile(bundlePath));
|
|
297
246
|
const registryHash = sha256(canonicalJson(registry));
|
|
298
247
|
const manifest = {
|
|
299
248
|
schemaVersion: "openpond.projectActionBuild.v1",
|
|
300
|
-
sourceDirectory:
|
|
249
|
+
sourceDirectory: path3.relative(discovered.projectRoot, discovered.sourceRoot).split(path3.sep).join("/"),
|
|
301
250
|
sourceFiles: discovered.files,
|
|
302
|
-
bundleFile:
|
|
303
|
-
runnerFile:
|
|
304
|
-
registryFile:
|
|
251
|
+
bundleFile: path3.basename(bundlePath),
|
|
252
|
+
runnerFile: path3.basename(runnerPath),
|
|
253
|
+
registryFile: path3.basename(registryPath),
|
|
305
254
|
bundleHash,
|
|
306
255
|
registryHash
|
|
307
256
|
};
|
|
308
|
-
await
|
|
309
|
-
await
|
|
257
|
+
await fs3.writeFile(manifestPath, canonicalJson(manifest), "utf8");
|
|
258
|
+
await fs3.rm(entryPath, { force: true });
|
|
310
259
|
return {
|
|
311
260
|
projectRoot: discovered.projectRoot,
|
|
312
261
|
outputDirectory,
|
|
@@ -322,17 +271,17 @@ function dependencySearchPaths(projectRoot) {
|
|
|
322
271
|
const candidates = [];
|
|
323
272
|
let current = projectRoot;
|
|
324
273
|
while (true) {
|
|
325
|
-
candidates.push(
|
|
326
|
-
const parent =
|
|
274
|
+
candidates.push(path3.join(current, "node_modules"));
|
|
275
|
+
const parent = path3.dirname(current);
|
|
327
276
|
if (parent === current) break;
|
|
328
277
|
current = parent;
|
|
329
278
|
}
|
|
330
|
-
candidates.push(
|
|
279
|
+
candidates.push(path3.resolve(path3.dirname(fileURLToPath(import.meta.url)), "../../../node_modules"));
|
|
331
280
|
return [...new Set(candidates)];
|
|
332
281
|
}
|
|
333
282
|
function assertWithinProject(projectRoot, target) {
|
|
334
|
-
const relative =
|
|
335
|
-
if (relative.startsWith("..") ||
|
|
283
|
+
const relative = path3.relative(projectRoot, target);
|
|
284
|
+
if (relative.startsWith("..") || path3.isAbsolute(relative)) {
|
|
336
285
|
throw new Error("Project Action output directory must stay inside the Project root.");
|
|
337
286
|
}
|
|
338
287
|
}
|
|
@@ -410,7 +359,7 @@ try {
|
|
|
410
359
|
// ../actions/src/local.ts
|
|
411
360
|
var localConcurrency = /* @__PURE__ */ new Map();
|
|
412
361
|
function createLocalActionRunner(options) {
|
|
413
|
-
const projectRoot =
|
|
362
|
+
const projectRoot = path4.resolve(options.projectRoot);
|
|
414
363
|
const buildPolicy = options.build ?? "if-missing";
|
|
415
364
|
let currentBuild = null;
|
|
416
365
|
const ensureBuild = async () => {
|
|
@@ -418,7 +367,7 @@ function createLocalActionRunner(options) {
|
|
|
418
367
|
if (currentBuild) return currentBuild;
|
|
419
368
|
if (buildPolicy === "never" || buildPolicy === "if-missing") {
|
|
420
369
|
const configuration = await loadProjectActionConfiguration(projectRoot);
|
|
421
|
-
const outputDirectory =
|
|
370
|
+
const outputDirectory = path4.resolve(
|
|
422
371
|
projectRoot,
|
|
423
372
|
options.outputDirectory ?? configuration.outputDirectory ?? DEFAULT_PROJECT_ACTION_OUTPUT_DIRECTORY
|
|
424
373
|
);
|
|
@@ -463,17 +412,17 @@ function createLocalActionRunner(options) {
|
|
|
463
412
|
};
|
|
464
413
|
await validateProjectActionRunSetup(projectRoot, catalogAction.setupRequirements, resolvedRequest);
|
|
465
414
|
const runId = request.runId?.trim() || randomUUID();
|
|
466
|
-
const actionOutputDirectory =
|
|
467
|
-
request.outputDirectory ??
|
|
415
|
+
const actionOutputDirectory = path4.resolve(
|
|
416
|
+
request.outputDirectory ?? path4.join(projectRoot, ".openpond", "outputs", runId)
|
|
468
417
|
);
|
|
469
418
|
assertWithinProject2(projectRoot, actionOutputDirectory, "Project Action output directory");
|
|
470
|
-
await
|
|
419
|
+
await fs4.mkdir(actionOutputDirectory, { recursive: true });
|
|
471
420
|
const release = await acquireLocalActionSlot(
|
|
472
421
|
`${projectRoot}\0${request.actionId}`,
|
|
473
422
|
catalogAction.implementation.concurrency,
|
|
474
423
|
resolvedRequest.signal
|
|
475
424
|
);
|
|
476
|
-
const responseFile =
|
|
425
|
+
const responseFile = path4.join(built.outputDirectory, `.run-${randomUUID()}.json`);
|
|
477
426
|
const startedAt = Date.now();
|
|
478
427
|
let childResult;
|
|
479
428
|
let payload;
|
|
@@ -495,12 +444,12 @@ function createLocalActionRunner(options) {
|
|
|
495
444
|
connections: resolvedRequest.connections ?? {}
|
|
496
445
|
}
|
|
497
446
|
});
|
|
498
|
-
payload = JSON.parse(await
|
|
447
|
+
payload = JSON.parse(await fs4.readFile(responseFile, "utf8"));
|
|
499
448
|
} catch (error) {
|
|
500
449
|
const message = error instanceof Error ? error.message : String(error);
|
|
501
450
|
throw new Error(redactRuntimeValues(message, resolvedRequest));
|
|
502
451
|
} finally {
|
|
503
|
-
await
|
|
452
|
+
await fs4.rm(responseFile, { force: true }).catch(() => void 0);
|
|
504
453
|
release();
|
|
505
454
|
}
|
|
506
455
|
return {
|
|
@@ -557,11 +506,11 @@ async function acquireLocalActionSlot(key, limit, signal) {
|
|
|
557
506
|
};
|
|
558
507
|
}
|
|
559
508
|
async function loadBuild(projectRoot, outputDirectory) {
|
|
560
|
-
const manifestPath =
|
|
561
|
-
const registryPath =
|
|
509
|
+
const manifestPath = path4.join(outputDirectory, "build-manifest.json");
|
|
510
|
+
const registryPath = path4.join(outputDirectory, "action-registry.json");
|
|
562
511
|
const [manifestText, registryText] = await Promise.all([
|
|
563
|
-
|
|
564
|
-
|
|
512
|
+
fs4.readFile(manifestPath, "utf8").catch(() => null),
|
|
513
|
+
fs4.readFile(registryPath, "utf8").catch(() => null)
|
|
565
514
|
]);
|
|
566
515
|
if (!manifestText || !registryText) return null;
|
|
567
516
|
const manifest = JSON.parse(manifestText);
|
|
@@ -569,8 +518,8 @@ async function loadBuild(projectRoot, outputDirectory) {
|
|
|
569
518
|
return {
|
|
570
519
|
projectRoot,
|
|
571
520
|
outputDirectory,
|
|
572
|
-
bundlePath:
|
|
573
|
-
runnerPath:
|
|
521
|
+
bundlePath: path4.join(outputDirectory, manifest.bundleFile),
|
|
522
|
+
runnerPath: path4.join(outputDirectory, manifest.runnerFile),
|
|
574
523
|
registryPath,
|
|
575
524
|
manifestPath,
|
|
576
525
|
registry,
|
|
@@ -645,8 +594,8 @@ function executeChild(input) {
|
|
|
645
594
|
});
|
|
646
595
|
}
|
|
647
596
|
function assertWithinProject2(projectRoot, target, label) {
|
|
648
|
-
const relative =
|
|
649
|
-
if (relative.startsWith("..") ||
|
|
597
|
+
const relative = path4.relative(projectRoot, target);
|
|
598
|
+
if (relative.startsWith("..") || path4.isAbsolute(relative)) {
|
|
650
599
|
throw new Error(`${label} must stay inside the Project root.`);
|
|
651
600
|
}
|
|
652
601
|
}
|