openpond-sdk 0.2.2 → 0.2.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.
@@ -1,5 +1,5 @@
1
1
  // src/taskset-package-contracts.ts
2
- import { z as z15 } from "zod";
2
+ import { z as z17 } from "zod";
3
3
 
4
4
  // ../harness/dist/common.js
5
5
  import { z } from "zod";
@@ -1859,6 +1859,63 @@ import { validateTaskValue } from "@openpond/evals/task-schema";
1859
1859
  // src/model-projects.ts
1860
1860
  import { z as z11 } from "zod";
1861
1861
  import { assertBoundedTaskJson } from "@openpond/evals/task-schema";
1862
+
1863
+ // src/protocol.ts
1864
+ var OpenPondProtocolError = class extends Error {
1865
+ code;
1866
+ constructor(code, message) {
1867
+ super(message);
1868
+ this.name = "OpenPondProtocolError";
1869
+ this.code = code;
1870
+ }
1871
+ };
1872
+ function canonicalJson2(value) {
1873
+ return JSON.stringify(normalizeCanonicalJson(value));
1874
+ }
1875
+ function normalizeCanonicalJson(value) {
1876
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
1877
+ return value;
1878
+ }
1879
+ if (typeof value === "number") {
1880
+ if (!Number.isFinite(value)) {
1881
+ throw new OpenPondProtocolError(
1882
+ "non_json_value",
1883
+ "Canonical JSON cannot contain a non-finite number."
1884
+ );
1885
+ }
1886
+ return Object.is(value, -0) ? 0 : value;
1887
+ }
1888
+ if (Array.isArray(value)) {
1889
+ return value.map((entry) => normalizeCanonicalJson(entry));
1890
+ }
1891
+ if (typeof value === "object") {
1892
+ const prototype = Object.getPrototypeOf(value);
1893
+ if (prototype !== Object.prototype && prototype !== null) {
1894
+ throw new OpenPondProtocolError(
1895
+ "non_json_value",
1896
+ "Canonical JSON accepts only plain objects."
1897
+ );
1898
+ }
1899
+ const result = {};
1900
+ for (const key of Object.keys(value).sort()) {
1901
+ const entry = value[key];
1902
+ if (entry === void 0 || typeof entry === "function" || typeof entry === "symbol") {
1903
+ throw new OpenPondProtocolError(
1904
+ "non_json_value",
1905
+ `Canonical JSON cannot contain ${typeof entry} at ${key}.`
1906
+ );
1907
+ }
1908
+ result[key] = normalizeCanonicalJson(entry);
1909
+ }
1910
+ return result;
1911
+ }
1912
+ throw new OpenPondProtocolError(
1913
+ "non_json_value",
1914
+ `Canonical JSON cannot contain ${typeof value}.`
1915
+ );
1916
+ }
1917
+
1918
+ // src/model-projects.ts
1862
1919
  var IdSchema = z11.string().trim().min(1).max(500);
1863
1920
  var HashSchema = z11.string().regex(/^[a-f0-9]{64}$/);
1864
1921
  var TimestampSchema = z11.string().datetime({ offset: true });
@@ -1912,6 +1969,7 @@ var ModelProjectTrainingSetupSchema = z11.object({
1912
1969
  var HostedModelProjectTrainingSetupSchema = ModelProjectTrainingSetupSchema.omit({ managedGpuRequirement: true });
1913
1970
  var HostedModelProjectLinkSchema = z11.object({
1914
1971
  schemaVersion: z11.literal("openpond.hostedModelProjectLink.v1"),
1972
+ apiOrigin: z11.string().url().refine((value) => new URL(value).origin === value, "Use a canonical API origin.").nullable().default(null),
1915
1973
  teamId: IdSchema,
1916
1974
  projectId: IdSchema,
1917
1975
  portableProjectId: IdSchema,
@@ -1922,9 +1980,11 @@ var HostedModelProjectLinkSchema = z11.object({
1922
1980
  tasksets: z11.array(
1923
1981
  z11.object({
1924
1982
  localTasksetId: IdSchema,
1983
+ localTasksetHash: HashSchema.nullable().default(null),
1925
1984
  releaseId: IdSchema,
1926
1985
  releaseRevision: z11.number().int().positive(),
1927
1986
  releaseHash: HashSchema,
1987
+ packageHash: HashSchema.nullable().default(null),
1928
1988
  hostedTasksetId: IdSchema,
1929
1989
  syncedAt: TimestampSchema
1930
1990
  }).strict()
@@ -2186,22 +2246,381 @@ function validateModelTasksetPackage(value) {
2186
2246
  return result;
2187
2247
  }
2188
2248
 
2249
+ // src/taskset-package-contracts.ts
2250
+ import { taskBatchPackageMetadata as taskBatchPackageMetadata2 } from "@openpond/evals/learning";
2251
+
2252
+ // src/taskset-package-learning.ts
2253
+ import { z as z16 } from "zod";
2254
+ import {
2255
+ TaskBatchSchema,
2256
+ TaskEvidenceSchema,
2257
+ TaskAdmissionDecisionSchema,
2258
+ LearningSourceSchema,
2259
+ LearningTextAssetSchema as LearningTextAssetSchema2,
2260
+ assertLearningContentHash as assertLearningContentHash2,
2261
+ compileTaskBatch,
2262
+ learningRef as learningRef3,
2263
+ sameLearningRef as sameLearningRef2,
2264
+ taskBatchPackageMetadata,
2265
+ verifyLearningTextAsset as verifyLearningTextAsset4
2266
+ } from "@openpond/evals/learning";
2267
+
2268
+ // src/training.ts
2269
+ import { z as z15 } from "zod";
2270
+ var IdSchema2 = z15.string().trim().min(1).max(500);
2271
+ var HashSchema3 = z15.string().regex(/^[a-f0-9]{64}$/);
2272
+ var TimestampSchema2 = z15.string().datetime({ offset: true });
2273
+ var TrainingInputArtifactUploadSchema = z15.object({
2274
+ schemaVersion: z15.literal("openpond.trainingInputArtifactUpload.v2"),
2275
+ kind: z15.enum(["portable_training_bundle", "reward_model_dataset"]),
2276
+ idempotencyKey: z15.string().trim().min(1).max(500),
2277
+ sourceManifest: ModelProjectImmutableRefSchema,
2278
+ payload: z15.unknown(),
2279
+ contentHash: HashSchema3
2280
+ }).strict();
2281
+ var TrainingInputArtifactSchema = z15.object({
2282
+ schemaVersion: z15.literal("openpond.trainingInputArtifact.v2"),
2283
+ kind: z15.enum(["portable_training_bundle", "reward_model_dataset"]),
2284
+ sourceManifest: ModelProjectImmutableRefSchema,
2285
+ artifactRef: z15.string().trim().min(1).max(2e3),
2286
+ contentHash: HashSchema3,
2287
+ sizeBytes: z15.number().int().positive(),
2288
+ createdAt: TimestampSchema2
2289
+ }).strict();
2290
+ var TrainingJobKindSchema = z15.enum([
2291
+ "reward_model_train",
2292
+ "policy_optimize"
2293
+ ]);
2294
+ var TrainingJobStateSchema = z15.enum([
2295
+ "queued",
2296
+ "admitting",
2297
+ "provisioning",
2298
+ "running",
2299
+ "stopping",
2300
+ "cancelling",
2301
+ "succeeded",
2302
+ "failed",
2303
+ "cancelled"
2304
+ ]);
2305
+ var TrainingCapabilityRequirementSchema = z15.object({
2306
+ id: IdSchema2,
2307
+ version: z15.string().trim().min(1).max(200).nullable().default(null),
2308
+ required: z15.boolean().default(true)
2309
+ }).strict();
2310
+ var TrainingJobSourceSchema = z15.object({
2311
+ modelProject: z15.object({
2312
+ id: IdSchema2,
2313
+ portableProjectId: IdSchema2,
2314
+ revision: z15.number().int().positive(),
2315
+ contentHash: HashSchema3
2316
+ }).strict(),
2317
+ harnessRunManifest: ModelProjectImmutableRefSchema,
2318
+ harnessRelease: ModelProjectImmutableRefSchema,
2319
+ taskset: ModelProjectVersionedRefSchema,
2320
+ tasksetRelease: ModelProjectImmutableRefSchema,
2321
+ dataset: ModelProjectImmutableRefSchema,
2322
+ evidenceSets: z15.array(ModelProjectImmutableRefSchema).max(1e4)
2323
+ }).strict();
2324
+ var RewardModelTrainingRequestSchema = z15.object({
2325
+ kind: z15.literal("reward_model_train"),
2326
+ baseModel: ModelProjectBaseModelSchema,
2327
+ preferenceDatasetRelease: ModelProjectImmutableRefSchema,
2328
+ processorRelease: ModelProjectImmutableRefSchema,
2329
+ recipe: z15.object({
2330
+ schemaVersion: z15.literal("openpond.rewardModelRecipe.v1"),
2331
+ method: z15.literal("reward_model"),
2332
+ parameterization: z15.literal("lora_with_scalar_head")
2333
+ }).catchall(z15.unknown())
2334
+ }).strict();
2335
+ var DeterministicRewardSourceSchema = z15.object({
2336
+ kind: z15.literal("deterministic"),
2337
+ grader: ModelProjectImmutableRefSchema,
2338
+ composer: ModelProjectImmutableRefSchema.nullable().default(null)
2339
+ }).strict();
2340
+ var LearnedRewardSourceSchema = z15.object({
2341
+ kind: z15.literal("learned_reward"),
2342
+ rewardModelVersion: ModelProjectImmutableRefSchema,
2343
+ qualificationReport: ModelProjectImmutableRefSchema.nullable().default(null),
2344
+ evaluationReferences: z15.array(ModelProjectImmutableRefSchema).max(1e3).default([]),
2345
+ scorerArtifact: z15.object({
2346
+ artifactRef: z15.string().trim().min(1).max(2e3),
2347
+ contentHash: HashSchema3,
2348
+ executionReceipt: ModelProjectImmutableRefSchema
2349
+ }).strict(),
2350
+ processorRelease: ModelProjectImmutableRefSchema,
2351
+ rewardComposerRelease: ModelProjectImmutableRefSchema
2352
+ }).strict();
2353
+ var PolicyOptimizationRequestSchema = z15.object({
2354
+ kind: z15.literal("policy_optimize"),
2355
+ baseModel: ModelProjectBaseModelSchema,
2356
+ recipe: ModelProjectRecipeDocumentSchema,
2357
+ rewardSource: z15.discriminatedUnion("kind", [
2358
+ DeterministicRewardSourceSchema,
2359
+ LearnedRewardSourceSchema
2360
+ ]),
2361
+ resumeFrom: ModelProjectImmutableRefSchema.nullable().default(null)
2362
+ }).strict();
2363
+ var TrainingJobRequestSchema = z15.discriminatedUnion("kind", [
2364
+ RewardModelTrainingRequestSchema,
2365
+ PolicyOptimizationRequestSchema
2366
+ ]);
2367
+ var TrainingJobApprovalSchema = z15.object({
2368
+ approvalHash: HashSchema3,
2369
+ approvedAt: TimestampSchema2,
2370
+ exportApproved: z15.boolean(),
2371
+ maximumSpendUsd: z15.number().nonnegative(),
2372
+ retentionDays: z15.number().int().nonnegative().nullable(),
2373
+ region: z15.string().trim().min(1).max(200).nullable().default(null)
2374
+ }).strict();
2375
+ var TrainingJobSubmissionSchema = z15.object({
2376
+ schemaVersion: z15.literal("openpond.trainingJobSubmission.v2"),
2377
+ idempotencyKey: z15.string().trim().min(1).max(500),
2378
+ name: z15.string().trim().min(1).max(200),
2379
+ source: TrainingJobSourceSchema,
2380
+ job: TrainingJobRequestSchema,
2381
+ requestedCapabilities: z15.array(TrainingCapabilityRequirementSchema).max(1e3),
2382
+ placementObjective: z15.enum(["fast", "balanced", "economical"]),
2383
+ budget: z15.object({
2384
+ maximumSpendUsd: z15.number().nonnegative(),
2385
+ maximumWallSeconds: z15.number().int().positive()
2386
+ }).strict(),
2387
+ approval: TrainingJobApprovalSchema,
2388
+ contentHash: HashSchema3
2389
+ }).strict().superRefine((submission, context) => {
2390
+ if (submission.approval.maximumSpendUsd !== submission.budget.maximumSpendUsd) {
2391
+ context.addIssue({
2392
+ code: "custom",
2393
+ path: ["approval", "maximumSpendUsd"],
2394
+ message: "Approved spend must equal the immutable Job budget."
2395
+ });
2396
+ }
2397
+ });
2398
+ var TrainingJobSchema = z15.object({
2399
+ schemaVersion: z15.literal("openpond.trainingJob.v2"),
2400
+ id: IdSchema2,
2401
+ teamId: IdSchema2,
2402
+ kind: TrainingJobKindSchema,
2403
+ modelProjectId: IdSchema2,
2404
+ portableProjectId: IdSchema2,
2405
+ sourceProjectRevision: z15.number().int().positive(),
2406
+ submissionHash: HashSchema3,
2407
+ state: TrainingJobStateSchema,
2408
+ phase: z15.string().trim().min(1).max(200),
2409
+ version: z15.number().int().nonnegative(),
2410
+ progress: z15.number().min(0).max(1),
2411
+ rolloutProgress: z15.object({
2412
+ groupsCompleted: z15.number().int().nonnegative(),
2413
+ groupsTarget: z15.number().int().nonnegative(),
2414
+ optimizerUpdatesApplied: z15.number().int().nonnegative(),
2415
+ optimizerUpdatesSkipped: z15.number().int().nonnegative()
2416
+ }).strict(),
2417
+ accruedSpendUsd: z15.number().nonnegative(),
2418
+ terminalReason: z15.string().trim().min(1).max(5e3).nullable(),
2419
+ createdAt: TimestampSchema2,
2420
+ updatedAt: TimestampSchema2,
2421
+ completedAt: TimestampSchema2.nullable()
2422
+ }).strict();
2423
+ var TrainingJobPageSchema = z15.object({
2424
+ schemaVersion: z15.literal("openpond.trainingJobPage.v2"),
2425
+ jobs: z15.array(TrainingJobSchema).max(1e3),
2426
+ nextCursor: z15.string().trim().min(1).max(2e3).nullable()
2427
+ }).strict();
2428
+ var TrainingJobEventSchema = z15.object({
2429
+ schemaVersion: z15.literal("openpond.trainingJobEvent.v2"),
2430
+ id: IdSchema2,
2431
+ jobId: IdSchema2,
2432
+ sequence: z15.number().int().nonnegative(),
2433
+ type: IdSchema2,
2434
+ phase: z15.string().trim().min(1).max(200),
2435
+ message: z15.string().trim().min(1).max(5e3).nullable(),
2436
+ data: z15.record(z15.string(), z15.unknown()).default({}),
2437
+ createdAt: TimestampSchema2
2438
+ }).strict();
2439
+ var TrainingJobLogSchema = z15.object({
2440
+ schemaVersion: z15.literal("openpond.trainingJobLog.v2"),
2441
+ jobId: IdSchema2,
2442
+ sequence: z15.number().int().nonnegative(),
2443
+ level: z15.enum(["debug", "info", "warning", "error"]),
2444
+ message: z15.string().max(2e4),
2445
+ createdAt: TimestampSchema2
2446
+ }).strict();
2447
+ var TrainingJobControlRequestSchema = z15.object({ expectedVersion: z15.number().int().nonnegative() }).strict();
2448
+ var TrainingJobOutputSchema = z15.object({
2449
+ schemaVersion: z15.literal("openpond.trainingJobOutput.v2"),
2450
+ id: IdSchema2,
2451
+ jobId: IdSchema2,
2452
+ kind: z15.enum([
2453
+ "checkpoint",
2454
+ "adapter",
2455
+ "scorer",
2456
+ "metrics",
2457
+ "evaluation",
2458
+ "trace",
2459
+ "receipt"
2460
+ ]),
2461
+ artifactRef: z15.string().trim().min(1).max(2e3),
2462
+ contentHash: HashSchema3,
2463
+ sizeBytes: z15.number().int().nonnegative(),
2464
+ metadata: z15.record(z15.string(), z15.unknown()).default({}),
2465
+ createdAt: TimestampSchema2
2466
+ }).strict();
2467
+ var TrainingExecutionReceiptSchema = z15.object({
2468
+ schemaVersion: z15.literal("openpond.trainingExecutionReceipt.v2"),
2469
+ id: IdSchema2,
2470
+ teamId: IdSchema2,
2471
+ jobId: IdSchema2,
2472
+ submissionHash: HashSchema3,
2473
+ manifestHash: HashSchema3,
2474
+ recipeHash: HashSchema3,
2475
+ capabilityHash: HashSchema3,
2476
+ runtimeRelease: ModelProjectImmutableRefSchema,
2477
+ inputs: z15.array(ModelProjectImmutableRefSchema).max(1e4),
2478
+ outputs: z15.array(ModelProjectImmutableRefSchema).max(1e4),
2479
+ spendUsd: z15.number().nonnegative(),
2480
+ durationSeconds: z15.number().nonnegative(),
2481
+ cleanupComplete: z15.boolean(),
2482
+ issuer: IdSchema2,
2483
+ issuedAt: TimestampSchema2,
2484
+ signature: z15.string().trim().min(1).max(1e4).nullable()
2485
+ }).strict();
2486
+ var TrainingJobOutputsSchema = z15.object({
2487
+ schemaVersion: z15.literal("openpond.trainingJobOutputs.v2"),
2488
+ outputs: z15.array(TrainingJobOutputSchema).max(1e4),
2489
+ receipt: TrainingExecutionReceiptSchema.nullable()
2490
+ }).strict();
2491
+ var TrainingApiErrorSchema = z15.object({
2492
+ schemaVersion: z15.literal("openpond.trainingApiError.v2"),
2493
+ code: z15.string().trim().min(1).max(200),
2494
+ message: z15.string().trim().min(1).max(5e3),
2495
+ retryable: z15.boolean().default(false),
2496
+ requestId: z15.string().trim().min(1).max(500).nullable().default(null),
2497
+ details: z15.record(z15.string(), z15.unknown()).default({})
2498
+ }).strict();
2499
+ var TrainingCapabilitiesSchema = z15.object({
2500
+ schemaVersion: z15.literal("openpond.trainingCapabilities.v2"),
2501
+ capabilityHash: HashSchema3,
2502
+ jobKinds: z15.array(TrainingJobKindSchema),
2503
+ methods: z15.array(z15.string().trim().min(1).max(200)),
2504
+ placements: z15.array(
2505
+ z15.enum(["local", "remote", "colocated", "provider_native"])
2506
+ ),
2507
+ controls: z15.object({
2508
+ cancel: z15.boolean(),
2509
+ stopAfterGroup: z15.boolean(),
2510
+ resumeFromCheckpoint: z15.boolean()
2511
+ }).strict(),
2512
+ limits: z15.object({
2513
+ maximumSpendUsd: z15.number().nonnegative(),
2514
+ maximumWallSeconds: z15.number().int().positive(),
2515
+ maximumArtifactBytes: z15.number().int().positive()
2516
+ }).strict(),
2517
+ checkedAt: TimestampSchema2,
2518
+ expiresAt: TimestampSchema2
2519
+ }).strict();
2520
+
2521
+ // src/taskset-package-learning.ts
2522
+ var TasksetPackageLearningResourcesSchema = z16.object({
2523
+ batch: TaskBatchSchema,
2524
+ evidence: z16.array(TaskEvidenceSchema).min(1).max(1e4),
2525
+ decisions: z16.array(TaskAdmissionDecisionSchema).min(1).max(1e4),
2526
+ sources: z16.array(LearningSourceSchema).min(1).max(1e4),
2527
+ assets: z16.array(LearningTextAssetSchema2).max(1e3)
2528
+ }).strict();
2529
+ function learningPackageContextFiles(resources) {
2530
+ return resources.evidence.filter((evidence) => evidence.submission.evaluatorContext !== null).map((evidence) => {
2531
+ const text = canonicalJson2(evidence.submission.evaluatorContext);
2532
+ const bytes = new TextEncoder().encode(text);
2533
+ return {
2534
+ asset: {
2535
+ id: `task-evidence:${evidence.contentHash}`,
2536
+ path: `learning/context/${evidence.contentHash}.json`,
2537
+ contentHash: sha256(bytes),
2538
+ sizeBytes: bytes.byteLength,
2539
+ mediaType: "application/json",
2540
+ visibility: "host_private"
2541
+ },
2542
+ base64: btoa(Array.from(bytes, (byte) => String.fromCharCode(byte)).join(""))
2543
+ };
2544
+ });
2545
+ }
2546
+ function validateTasksetLearningResources(taskset, input) {
2547
+ const resources = TasksetPackageLearningResourcesSchema.parse(input);
2548
+ const metadata = taskBatchPackageMetadata(taskset);
2549
+ if (!sameLearningRef2(learningRef3(resources.batch), metadata.batch)) throw new Error("Taskset learning batch differs from its admission metadata.");
2550
+ for (const collection of [resources.evidence, resources.decisions, resources.sources, resources.assets]) {
2551
+ const identities = /* @__PURE__ */ new Set();
2552
+ for (const resource of collection) {
2553
+ assertLearningContentHash2(resource);
2554
+ const key = `${resource.id}:${resource.revision}`;
2555
+ if (identities.has(key)) throw new Error("Taskset learning resource identities must be unique.");
2556
+ identities.add(key);
2557
+ }
2558
+ }
2559
+ if (resources.evidence.length !== resources.batch.examples.length || resources.decisions.length !== resources.batch.examples.length) throw new Error("Taskset learning snapshots must match the admitted batch inventory.");
2560
+ for (const evidence of resources.evidence) {
2561
+ const source = resources.sources.find((source2) => sameLearningRef2(learningRef3(source2), evidence.source));
2562
+ if (!source || !sameLearningRef2(source.taskDefinition, learningRef3(metadata.definition))) throw new Error("Taskset evidence source differs from its task definition.");
2563
+ }
2564
+ if (resources.sources.some((source) => !resources.evidence.some((evidence) => sameLearningRef2(evidence.source, learningRef3(source))))) throw new Error("Taskset package includes an unrelated learning source.");
2565
+ const rewardAssets = metadata.rewards.flatMap((reward) => [
2566
+ ...reward.assets,
2567
+ ...reward.implementation.kind === "custom_verifier" ? [reward.implementation.verifierRef] : reward.implementation.kind === "model_judge" || reward.implementation.kind === "human" ? [reward.implementation.rubricRef] : [],
2568
+ ..."inputContract" in reward.implementation ? [reward.implementation.inputContract] : []
2569
+ ]);
2570
+ for (const ref of rewardAssets) {
2571
+ const asset = resources.assets.find((asset2) => asset2.id === ref.id);
2572
+ if (!asset) throw new Error("Taskset learning Reward asset is missing.");
2573
+ verifyLearningTextAsset4(asset, ref);
2574
+ }
2575
+ if (resources.assets.some((asset) => !rewardAssets.some((ref) => ref.id === asset.id))) throw new Error("Taskset package includes an unrelated learning asset.");
2576
+ const compiled = compileTaskBatch({
2577
+ batch: resources.batch,
2578
+ definition: metadata.definition,
2579
+ binding: metadata.binding,
2580
+ rewards: metadata.rewards,
2581
+ evidence: resources.evidence,
2582
+ decisions: resources.decisions
2583
+ });
2584
+ const compiledMetadata = taskBatchPackageMetadata(compiled);
2585
+ if (contentHash(compiledMetadata) !== contentHash(metadata)) throw new Error("Taskset admission metadata differs from its reviewed snapshots.");
2586
+ const execution = (release) => ({ policy: release.policy, environment: release.environment, tools: release.tools });
2587
+ if (contentHash(execution(compiled)) !== contentHash(execution(taskset))) throw new Error("Taskset execution differs from its reviewed task definition.");
2588
+ const taskContent = (task) => ({
2589
+ id: task.id,
2590
+ clusterKey: task.clusterKey,
2591
+ split: task.split,
2592
+ input: task.input,
2593
+ expectedOutput: task.expectedOutput,
2594
+ policyVisibleContext: task.policyVisibleContext,
2595
+ privilegedContextRef: task.privilegedContextRef,
2596
+ artifactRefs: task.artifactRefs,
2597
+ requiredOutputs: task.requiredOutputs ?? [],
2598
+ tags: task.tags
2599
+ });
2600
+ if (contentHash(compiled.tasks.map(taskContent)) !== contentHash(taskset.tasks.map(taskContent))) throw new Error("Taskset rows differ from their reviewed evidence.");
2601
+ return resources;
2602
+ }
2603
+
2189
2604
  // src/taskset-package-contracts.ts
2190
2605
  var MAX_TASKSET_PACKAGE_BYTES = 64 * 1024 * 1024;
2191
- var TasksetPackageFileSchema = z15.object({
2606
+ var TasksetPackageFileSchema = z17.object({
2192
2607
  asset: ImmutableAssetRefSchema,
2193
- base64: z15.string().max(Math.ceil(MAX_TASKSET_PACKAGE_BYTES / 3) * 4)
2608
+ base64: z17.string().max(Math.ceil(MAX_TASKSET_PACKAGE_BYTES / 3) * 4)
2194
2609
  }).strict();
2195
2610
  var BoundModelResourcesSchema = ModelTasksetPackageSchema.omit({ taskset: true, executionResources: true });
2196
- var TasksetPackageContentSchema = z15.object({
2197
- schemaVersion: z15.literal("openpond.tasksetPackage.v1"),
2611
+ var TasksetPackageContentSchema = z17.object({
2612
+ schemaVersion: z17.literal("openpond.tasksetPackage.v1"),
2198
2613
  taskset: TasksetReleaseSchema2,
2199
2614
  environment: EnvironmentReleaseSchema3,
2200
2615
  verifierSet: VerifierSetReleaseSchema3,
2201
- files: z15.array(TasksetPackageFileSchema).max(1e4),
2202
- modelResources: BoundModelResourcesSchema.optional()
2616
+ files: z17.array(TasksetPackageFileSchema).max(1e4),
2617
+ modelResources: BoundModelResourcesSchema.optional(),
2618
+ learningResources: TasksetPackageLearningResourcesSchema.optional()
2203
2619
  }).strict();
2204
- var TasksetPackageSchema = TasksetPackageContentSchema.extend({ contentHash: z15.string().regex(/^[a-f0-9]{64}$/) }).strict();
2620
+ var TasksetPackageSchema = TasksetPackageContentSchema.extend({ contentHash: z17.string().regex(/^[a-f0-9]{64}$/) }).strict();
2621
+ function tasksetPackageRewardBinding(value) {
2622
+ return value.learningResources ? taskBatchPackageMetadata2(value.taskset).binding : value.modelResources?.rewardBinding ?? null;
2623
+ }
2205
2624
  function decodeTasksetPackageFile(value) {
2206
2625
  const file = TasksetPackageFileSchema.parse(value);
2207
2626
  const raw = atob(file.base64);
@@ -2247,11 +2666,18 @@ function validateTasksetPackage(value) {
2247
2666
  }
2248
2667
  for (const declarations of [taskset.metadata.environmentResources, environment.metadata.resources]) {
2249
2668
  if (declarations === void 0) continue;
2250
- for (const resource of z15.array(z15.object({ path: z15.string().min(1) }).passthrough()).parse(declarations)) {
2669
+ for (const resource of z17.array(z17.object({ path: z17.string().min(1) }).passthrough()).parse(declarations)) {
2251
2670
  if (!result.files.some((file) => file.asset.path === resource.path)) throw new Error(`Taskset environment resource is missing: ${resource.path}.`);
2252
2671
  }
2253
2672
  }
2254
- if (result.modelResources) {
2673
+ if (result.learningResources) {
2674
+ if (result.modelResources) throw new Error("Taskset package cannot declare competing authoring graphs.");
2675
+ const learning = validateTasksetLearningResources(taskset, result.learningResources);
2676
+ for (const expected of learningPackageContextFiles(learning)) {
2677
+ if (!same2(files.get(expected.asset.id), expected)) throw new Error("Taskset private context differs from its reviewed evidence.");
2678
+ }
2679
+ for (const asset of learning.assets) requireAsset(asset.asset);
2680
+ } else if (result.modelResources) {
2255
2681
  const model = validateModelTasksetPackage({ ...result.modelResources, taskset, executionResources: { environment, verifierSet } });
2256
2682
  for (const asset of model.assets) requireAsset(asset.asset);
2257
2683
  } else if (["starter", "rewardBinding", "rewardExecution", "modelTasksetDerivation", "learning"].some((key) => taskset.metadata[key] !== void 0)) {
@@ -2269,69 +2695,83 @@ function same2(left, right) {
2269
2695
  }
2270
2696
 
2271
2697
  // src/taskset-package-client.ts
2272
- import { z as z17 } from "zod";
2698
+ import { z as z19 } from "zod";
2273
2699
 
2274
2700
  // src/taskset-catalog.ts
2275
- import { z as z16 } from "zod";
2276
- var IdSchema2 = z16.string().trim().min(1).max(500);
2277
- var HashSchema3 = z16.string().regex(/^[a-f0-9]{64}$/);
2278
- var TasksetCatalogReleaseRefSchema = z16.object({ id: IdSchema2, revision: z16.number().int().positive(), contentHash: HashSchema3 }).strict();
2279
- var HostedTasksetSummarySchema = z16.object({
2280
- schemaVersion: z16.literal("openpond.hostedTasksetSummary.v1"),
2281
- id: IdSchema2,
2282
- teamId: IdSchema2,
2701
+ import { z as z18 } from "zod";
2702
+ var IdSchema3 = z18.string().trim().min(1).max(500);
2703
+ var HashSchema4 = z18.string().regex(/^[a-f0-9]{64}$/);
2704
+ var TasksetCatalogReleaseRefSchema = z18.object({ id: IdSchema3, revision: z18.number().int().positive(), contentHash: HashSchema4 }).strict();
2705
+ var HostedTasksetSummarySchema = z18.object({
2706
+ schemaVersion: z18.literal("openpond.hostedTasksetSummary.v1"),
2707
+ id: IdSchema3,
2708
+ teamId: IdSchema3,
2283
2709
  release: TasksetCatalogReleaseRefSchema,
2284
- name: z16.string().min(1).max(500),
2285
- description: z16.string().max(2e4),
2286
- taskCount: z16.number().int().nonnegative(),
2287
- buildIntent: z16.string().min(1).max(100),
2288
- methodHint: z16.string().min(1).max(100).nullable(),
2289
- packageBytes: z16.number().int().nonnegative().nullable(),
2290
- storedBytes: z16.number().int().nonnegative().nullable(),
2291
- createdAt: z16.string().datetime({ offset: true })
2292
- }).strict();
2293
- var TasksetCatalogQuerySchema = z16.object({
2294
- afterId: IdSchema2.optional(),
2295
- limit: z16.number().int().min(1).max(100).default(30),
2296
- modelProjectId: IdSchema2.optional()
2297
- }).strict();
2298
- var TasksetCatalogPageSchema = z16.object({
2299
- items: z16.array(HostedTasksetSummarySchema).max(100),
2300
- nextCursor: IdSchema2.nullable()
2301
- }).strict();
2302
- var TasksetCatalogErrorSchema = z16.object({
2303
- code: z16.string().min(1),
2304
- message: z16.string().min(1)
2710
+ name: z18.string().min(1).max(500),
2711
+ description: z18.string().max(2e4),
2712
+ taskCount: z18.number().int().nonnegative(),
2713
+ buildIntent: z18.string().min(1).max(100),
2714
+ methodHint: z18.string().min(1).max(100).nullable(),
2715
+ packageBytes: z18.number().int().nonnegative().nullable(),
2716
+ storedBytes: z18.number().int().nonnegative().nullable(),
2717
+ createdAt: z18.string().datetime({ offset: true })
2718
+ }).strict();
2719
+ var TasksetCatalogQuerySchema = z18.object({
2720
+ afterId: IdSchema3.optional(),
2721
+ limit: z18.number().int().min(1).max(100).default(30),
2722
+ modelProjectId: IdSchema3.optional()
2723
+ }).strict();
2724
+ var TasksetCatalogPageSchema = z18.object({
2725
+ items: z18.array(HostedTasksetSummarySchema).max(100),
2726
+ nextCursor: IdSchema3.nullable()
2727
+ }).strict();
2728
+ var TasksetCatalogErrorSchema = z18.object({
2729
+ code: z18.string().min(1),
2730
+ message: z18.string().min(1)
2305
2731
  }).strict();
2306
2732
 
2307
2733
  // src/taskset-package-client.ts
2308
- var IdSchema3 = z17.string().trim().min(1).max(500);
2309
- var HashSchema4 = z17.string().regex(/^[a-f0-9]{64}$/);
2310
- var TasksetPackagePublicationSchema = z17.object({
2311
- schemaVersion: z17.literal("openpond.tasksetPackagePublication.v1"),
2312
- operationId: IdSchema3,
2313
- modelProjectId: IdSchema3,
2314
- expectedProjectEtag: HashSchema4.nullable(),
2315
- name: z17.string().trim().min(1).max(200),
2316
- description: z17.string().max(5e3),
2317
- buildIntent: z17.enum(["demonstrations", "preferences", "verifiable_reward", "rubric", "discovery"]),
2318
- methodHint: z17.enum(["sft", "dpo", "grpo", "ppo"]).nullable(),
2319
- package: TasksetPackageSchema
2320
- }).strict();
2321
- var TasksetPackageReceiptSchema = z17.object({
2322
- schemaVersion: z17.literal("openpond.tasksetPackageReceipt.v1"),
2323
- teamId: IdSchema3,
2324
- modelProjectId: IdSchema3,
2325
- operationId: IdSchema3,
2734
+ import { learningRef as learningRef4 } from "@openpond/evals/learning";
2735
+ var IdSchema4 = z19.string().trim().min(1).max(500);
2736
+ var HashSchema5 = z19.string().regex(/^[a-f0-9]{64}$/);
2737
+ var TasksetPackageModelConfigurationSchema = HostedModelProjectSyncSchema.pick({
2738
+ portableProjectId: true,
2739
+ name: true,
2740
+ objective: true,
2741
+ defaultBaseModel: true,
2742
+ defaultDestinationId: true,
2743
+ sourceRevision: true,
2744
+ sourceUpdatedAt: true
2745
+ }).extend({ trainingSetup: HostedModelProjectTrainingSetupSchema.omit({ tasksetRef: true, rewardBindingRef: true, tasksetRelease: true, recipe: true }) }).strict();
2746
+ var TasksetPackagePublicationSchema = z19.object({
2747
+ schemaVersion: z19.literal("openpond.tasksetPackagePublication.v1"),
2748
+ operationId: IdSchema4,
2749
+ modelProjectId: IdSchema4,
2750
+ expectedProjectEtag: HashSchema5.nullable(),
2751
+ name: z19.string().trim().min(1).max(200),
2752
+ description: z19.string().max(5e3),
2753
+ buildIntent: z19.enum(["demonstrations", "preferences", "verifiable_reward", "rubric", "discovery"]),
2754
+ methodHint: z19.enum(["sft", "dpo", "grpo", "ppo"]).nullable(),
2755
+ package: TasksetPackageSchema,
2756
+ modelConfiguration: TasksetPackageModelConfigurationSchema.optional(),
2757
+ selection: z19.enum(["select", "attach"]).optional()
2758
+ }).strict().refine((value) => value.selection !== "attach" || value.modelConfiguration === void 0, "Attachment-only publication cannot replace Model configuration.");
2759
+ var TasksetPackageReceiptSchema = z19.object({
2760
+ schemaVersion: z19.literal("openpond.tasksetPackageReceipt.v1"),
2761
+ teamId: IdSchema4,
2762
+ modelProjectId: IdSchema4,
2763
+ operationId: IdSchema4,
2326
2764
  taskset: TasksetCatalogReleaseRefSchema,
2327
- packageHash: HashSchema4,
2328
- hostedTasksetId: IdSchema3,
2329
- projectEtag: HashSchema4
2330
- }).strict();
2331
- var TasksetPackageReadbackSchema = z17.object({
2332
- schemaVersion: z17.literal("openpond.tasksetPackageReadback.v1"),
2333
- teamId: IdSchema3,
2334
- modelProjectId: IdSchema3,
2765
+ packageHash: HashSchema5,
2766
+ hostedTasksetId: IdSchema4,
2767
+ projectEtag: HashSchema5,
2768
+ project: HostedModelProjectSummarySchema.optional(),
2769
+ selection: z19.enum(["select", "attach"]).optional()
2770
+ }).strict();
2771
+ var TasksetPackageReadbackSchema = z19.object({
2772
+ schemaVersion: z19.literal("openpond.tasksetPackageReadback.v1"),
2773
+ teamId: IdSchema4,
2774
+ modelProjectId: IdSchema4,
2335
2775
  package: TasksetPackageSchema
2336
2776
  }).strict();
2337
2777
  var OpenPondTasksetPackageError = class extends Error {
@@ -2359,12 +2799,29 @@ var OpenPondTasksetPackageClient = class {
2359
2799
  if (receipt.teamId !== this.#options.teamId || receipt.modelProjectId !== request.modelProjectId || receipt.operationId !== request.operationId || receipt.packageHash !== request.package.contentHash || receipt.taskset.id !== release.id || receipt.taskset.revision !== release.revision || receipt.taskset.contentHash !== release.contentHash) {
2360
2800
  throw new OpenPondTasksetPackageError(502, "package_receipt_mismatch", "Taskset publication receipt did not match the requested package and owner.");
2361
2801
  }
2802
+ if (request.selection !== void 0 && receipt.selection !== request.selection) throw new OpenPondTasksetPackageError(502, "package_receipt_mismatch", "Taskset publication did not retain its selection mode.");
2803
+ if (request.selection === "attach" && receipt.projectEtag !== request.expectedProjectEtag) throw new OpenPondTasksetPackageError(502, "package_receipt_mismatch", "Attaching a historical Taskset changed the Model configuration.");
2804
+ if (request.modelConfiguration) {
2805
+ const expected = request.modelConfiguration;
2806
+ const project = receipt.project;
2807
+ const binding = tasksetPackageRewardBinding(request.package);
2808
+ const setup = HostedModelProjectTrainingSetupSchema.parse({
2809
+ ...expected.trainingSetup,
2810
+ tasksetRef: learningRef4(release),
2811
+ rewardBindingRef: binding ? learningRef4(binding) : null,
2812
+ tasksetRelease: null,
2813
+ recipe: null
2814
+ });
2815
+ if (!project || project.teamId !== this.#options.teamId || project.etag !== receipt.projectEtag || ![project.id, project.portableProjectId].includes(request.modelProjectId) || project.portableProjectId !== expected.portableProjectId || project.name !== expected.name || project.objective !== expected.objective || project.sourceRevision !== expected.sourceRevision || Date.parse(project.sourceUpdatedAt) !== Date.parse(expected.sourceUpdatedAt) || contentHash(project.defaultBaseModel) !== contentHash(expected.defaultBaseModel) || project.defaultDestinationId !== expected.defaultDestinationId || contentHash(project.trainingSetup) !== contentHash(setup)) {
2816
+ throw new OpenPondTasksetPackageError(502, "package_receipt_mismatch", "Taskset publication did not retain the requested Model configuration.");
2817
+ }
2818
+ }
2362
2819
  return receipt;
2363
2820
  }
2364
2821
  async get(modelProjectId, reference, options = {}) {
2365
- const project = IdSchema3.parse(modelProjectId);
2822
+ const project = IdSchema4.parse(modelProjectId);
2366
2823
  const ref = TasksetCatalogReleaseRefSchema.parse(reference);
2367
- const expectedPackageHash = options.expectedPackageHash === void 0 ? void 0 : HashSchema4.parse(options.expectedPackageHash);
2824
+ const expectedPackageHash = options.expectedPackageHash === void 0 ? void 0 : HashSchema5.parse(options.expectedPackageHash);
2368
2825
  const response = TasksetPackageReadbackSchema.parse(await this.#request(`/${encodeURIComponent(project)}/${encodeURIComponent(ref.id)}/${ref.revision}/${ref.contentHash}`, "GET", void 0, options.signal));
2369
2826
  const taskset = response.package.taskset;
2370
2827
  if (response.teamId !== this.#options.teamId || response.modelProjectId !== project || taskset.id !== ref.id || taskset.revision !== ref.revision || taskset.contentHash !== ref.contentHash) throw new OpenPondTasksetPackageError(502, "package_readback_mismatch", "Taskset package did not match the requested release and owner.");
@@ -2401,7 +2858,7 @@ var OpenPondTasksetPackageClient = class {
2401
2858
  }
2402
2859
  const payload = JSON.parse(text);
2403
2860
  if (!response.ok) {
2404
- const error = z17.object({ code: z17.string(), message: z17.string() }).safeParse(payload);
2861
+ const error = z19.object({ code: z19.string(), message: z19.string() }).safeParse(payload);
2405
2862
  throw new OpenPondTasksetPackageError(response.status, error.success ? error.data.code : "package_request_failed", error.success ? error.data.message : `Taskset package request failed (${response.status}).`);
2406
2863
  }
2407
2864
  return payload;
@@ -2413,12 +2870,17 @@ export {
2413
2870
  OpenPondTasksetPackageError,
2414
2871
  TasksetPackageContentSchema,
2415
2872
  TasksetPackageFileSchema,
2873
+ TasksetPackageLearningResourcesSchema,
2874
+ TasksetPackageModelConfigurationSchema,
2416
2875
  TasksetPackagePublicationSchema,
2417
2876
  TasksetPackageReadbackSchema,
2418
2877
  TasksetPackageReceiptSchema,
2419
2878
  TasksetPackageSchema,
2420
2879
  createTasksetPackage,
2421
2880
  decodeTasksetPackageFile,
2881
+ learningPackageContextFiles,
2882
+ tasksetPackageRewardBinding,
2883
+ validateTasksetLearningResources,
2422
2884
  validateTasksetPackage
2423
2885
  };
2424
2886
  //# sourceMappingURL=taskset-packages.js.map