openpond-sdk 0.12.20 → 0.12.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/OPENTELEMETRY.md +85 -0
  2. package/README.md +4 -0
  3. package/TASK_INGESTION.md +135 -0
  4. package/dist/advanced-refiner-evaluations.js +2 -2
  5. package/dist/{chunk-RN5MK7NH.js → chunk-6EZAGTZG.js} +4 -4
  6. package/dist/{chunk-3MDNVNBM.js → chunk-BNBPKCIR.js} +6 -6
  7. package/dist/chunk-NZRGRUYG.js +140 -0
  8. package/dist/chunk-NZRGRUYG.js.map +1 -0
  9. package/dist/{chunk-RT7SQHO4.js → chunk-SP7DQEQM.js} +2 -2
  10. package/dist/connected-evidence.js +3 -3
  11. package/dist/dataset-workspaces.js +125 -36
  12. package/dist/dataset-workspaces.js.map +1 -1
  13. package/dist/experiment-evaluation-schedules.js +5 -5
  14. package/dist/experiments.js +5 -5
  15. package/dist/index.js +51 -36
  16. package/dist/index.js.map +1 -1
  17. package/dist/opentelemetry.js +92 -0
  18. package/dist/opentelemetry.js.map +1 -0
  19. package/dist/taskset-drafts.js +1 -1
  20. package/dist/taskset-packages.js +13 -13
  21. package/dist/training-bundle.js +10 -10
  22. package/dist/training.js +8 -8
  23. package/dist/types/packages/sdk/src/dataset-task-ingestion.d.ts +86 -0
  24. package/dist/types/packages/sdk/src/dataset-task-ingestion.d.ts.map +1 -0
  25. package/dist/types/packages/sdk/src/dataset-workspace-client.d.ts +152 -140
  26. package/dist/types/packages/sdk/src/dataset-workspace-client.d.ts.map +1 -1
  27. package/dist/types/packages/sdk/src/dataset-workspaces.d.ts +1 -0
  28. package/dist/types/packages/sdk/src/dataset-workspaces.d.ts.map +1 -1
  29. package/dist/types/packages/sdk/src/experiment-client.d.ts +77 -77
  30. package/dist/types/packages/sdk/src/experiment-evaluation-schedules.d.ts +216 -216
  31. package/dist/types/packages/sdk/src/index.d.ts +4 -0
  32. package/dist/types/packages/sdk/src/index.d.ts.map +1 -1
  33. package/dist/types/packages/sdk/src/managed-decision-executions.d.ts +339 -339
  34. package/dist/types/packages/sdk/src/model-taskset-runs.d.ts +216 -216
  35. package/dist/types/packages/sdk/src/opentelemetry.d.ts +39 -0
  36. package/dist/types/packages/sdk/src/opentelemetry.d.ts.map +1 -0
  37. package/dist/types/packages/sdk/src/taskset-draft-client.d.ts +120 -120
  38. package/dist/types/packages/sdk/src/taskset-draft-source.d.ts +20 -20
  39. package/dist/types/packages/sdk/src/training-qualification-preparation.d.ts +25 -25
  40. package/dist/types/packages/sdk/src/training.d.ts +4465 -4465
  41. package/dist/types/packages/sdk/src/types.d.ts +2 -0
  42. package/dist/types/packages/sdk/src/types.d.ts.map +1 -1
  43. package/fixtures/python-foundation/operation-matrix.json +17 -0
  44. package/fixtures/python-foundation/schemas.json +5941 -5001
  45. package/package.json +18 -3
  46. /package/dist/{chunk-RN5MK7NH.js.map → chunk-6EZAGTZG.js.map} +0 -0
  47. /package/dist/{chunk-3MDNVNBM.js.map → chunk-BNBPKCIR.js.map} +0 -0
  48. /package/dist/{chunk-RT7SQHO4.js.map → chunk-SP7DQEQM.js.map} +0 -0
@@ -0,0 +1,85 @@
1
+ # Optional OpenTelemetry integration
2
+
3
+ `openpond-sdk/opentelemetry` implements the standard JavaScript
4
+ [`SpanExporter`](https://open-telemetry.github.io/opentelemetry-js/modules/_opentelemetry_sdk-trace.html)
5
+ interface. Install the current tracing SDK alongside OpenPond:
6
+
7
+ ```sh
8
+ npm install openpond-sdk @opentelemetry/api @opentelemetry/sdk-trace@^3.1.0
9
+ ```
10
+
11
+ This is an adapter into the structured [addTask API](./TASK_INGESTION.md), not an
12
+ OTLP receiver. Existing automatic instrumentation can produce the spans. Register
13
+ this exporter in your existing OTel configuration, alongside your observability
14
+ exporter if desired. It does not replace the global provider, install framework
15
+ instrumentation, or automatically create training tasks from every log line.
16
+
17
+ ```ts
18
+ import { OpenPondClient } from "openpond-sdk";
19
+ import { OpenPondSpanExporter } from "openpond-sdk/opentelemetry";
20
+ import { BatchSpanProcessor, TracerProvider } from "@opentelemetry/sdk-trace";
21
+
22
+ const client = new OpenPondClient({ baseUrl: apiBaseUrl, apiKey, teamId });
23
+ const exporter = new OpenPondSpanExporter({
24
+ client,
25
+ datasetId,
26
+ maxExportBatchSize: 32,
27
+ projectSpan(span) {
28
+ // These are application-owned attributes: explicitly mark selected agent runs.
29
+ if (span.attributes["app.learning_task"] !== true) return null;
30
+ const input = span.attributes["app.sanitized_task_input"];
31
+ if (typeof input !== "string" || !input.trim()) return null;
32
+ return {
33
+ name: span.name,
34
+ input: { prompt: input },
35
+ // Preserve for review; upload does not authorize training.
36
+ split: "validation",
37
+ };
38
+ },
39
+ });
40
+ const processor = new BatchSpanProcessor({
41
+ exporter,
42
+ maxExportBatchSize: 32,
43
+ maxQueueSize: 256,
44
+ exportTimeoutMillis: 30_000,
45
+ });
46
+ // If your application already has a provider, configure its processor list there.
47
+ const provider = new TracerProvider({ spanProcessors: [processor] });
48
+ const tracer = provider.getTracer("production-agent");
49
+ // Use tracer in your agent, or your existing framework instrumentation.
50
+ // At graceful application shutdown:
51
+ await provider.shutdown();
52
+ // exporter.lastExportError exposes the latest batch failure, if any.
53
+ ```
54
+
55
+ Only the returned task and trace/span source IDs are uploaded. Prompts, outputs,
56
+ attributes, exceptions and events are not copied implicitly. Redact secrets before
57
+ returning content. A selected span should contain the context needed to reproduce
58
+ a useful task; logs and exceptions can supply that context through span events in
59
+ your projection. Standalone log, metrics and OTLP ingestion are not implemented.
60
+ These examples use application attributes, not unsettled GenAI convention names.
61
+
62
+ The exporter derives a dataset-scoped idempotency key from trace ID and span ID.
63
+ Duplicate spans in a successful batch are skipped. Replaying a span after a lost
64
+ reply uses the same key. Keep projections deterministic for a span: a changed
65
+ payload with an existing key is a conflict, not a second task. Saved tasks still
66
+ require the application's separate review and training authorization.
67
+
68
+ Use `BatchSpanProcessor` for its bounded background queue; ending a span must not
69
+ wait for an HTTP write. Queues can drop spans when full. The adapter sends selected
70
+ tasks sequentially, rejects oversized/concurrent export batches, and has a 10s
71
+ per-request and 25s overall batch deadline by default. Configure small batches for
72
+ your network latency. HTTP failures, invalid projections and receipt mismatches
73
+ produce OTel export failure with bounded trace/span failure details in
74
+ `OpenPondSpanExportError.failures`. No retry worker or persistent outbox is created;
75
+ OTel's processor does not guarantee retries or durable delivery. Use direct
76
+ `addTask` with your own durable queue when loss is unacceptable.
77
+
78
+ `forceFlush()` waits for the exporter's current HTTP work; flush the **provider**
79
+ to drain its processor queue. `shutdown()` rejects new exports and waits for
80
+ accepted work. A successful flush means the queue was drained, not that every
81
+ write succeeded: inspect exporter errors/OTel diagnostics. Keep credentials on the
82
+ server and do not change providers or close dependencies while exports are active.
83
+
84
+ Python has the matching optional exporter in `ponder_sdk.opentelemetry`; see the
85
+ [Python SDK README](../../python/openpond-sdk/README.md).
package/README.md CHANGED
@@ -389,3 +389,7 @@ is immutable and owner-scoped. `comparisonBudget(id)` returns each operation's
389
389
  run ID, known settled spend, pending reservations and remaining allowance.
390
390
  Registering a comparison does not start any work. Independent experiments do
391
391
  not implicitly share a spending cap.
392
+
393
+ ## Add production tasks
394
+
395
+ Use the flat `client.addTask(datasetId, task)` operation, or bind one destination with `createTaskAdder` and call `addTask(task)`. See [task ingestion](TASK_INGESTION.md) for TypeScript/Python examples, receipt semantics and duplicate-safe retries. Task uploads do not enable training.
@@ -0,0 +1,135 @@
1
+ # Add tasks to a Dataset
2
+
3
+ Task submission uses an authenticated OpenPond API, separate from OpenTelemetry.
4
+ A successful receipt means a structured task was durably saved and is available
5
+ through the ordinary Dataset Tasks reader. It does not start training, publish
6
+ a release, create a Model or enable a collection schedule.
7
+
8
+ Create or choose an editable Dataset in Console and copy its ID. Configure the
9
+ server-side SDK with the workspace that owns it:
10
+
11
+ ```ts
12
+ import { createOpenPondClient } from "openpond-sdk";
13
+
14
+ const client = createOpenPondClient({
15
+ apiKey: process.env.OPENPOND_API_KEY!,
16
+ teamId: process.env.OPENPOND_TEAM_ID!,
17
+ });
18
+
19
+ const receipt = await client.addTask(process.env.OPENPOND_DATASET_ID!, {
20
+ name: "Handle an expired API token",
21
+ input: { request: "Fetch the report", observedError: "Token expired" },
22
+ source: { kind: "production_agent", eventId: "run-123" },
23
+ }, { idempotencyKey: "run-123" });
24
+
25
+ console.log(receipt.taskId, receipt.receivedAt);
26
+ ```
27
+
28
+ Use a configured `baseUrl` when targeting a different OpenPond API origin.
29
+ Never expose the API key in browser code or logged task content.
30
+
31
+ ## Bind the destination once
32
+
33
+ ```ts
34
+ import { createTaskAdder } from "openpond-sdk";
35
+
36
+ const addTask = createTaskAdder({
37
+ apiKey: process.env.OPENPOND_API_KEY!,
38
+ teamId: process.env.OPENPOND_TEAM_ID!,
39
+ datasetId: process.env.OPENPOND_DATASET_ID!,
40
+ baseUrl: "https://api.openpond.ai",
41
+ });
42
+
43
+ await addTask({
44
+ name: "Explain a failed agent run",
45
+ input: { request: "Summarize the report", outcome: "incomplete" },
46
+ }, { idempotencyKey: "agent-run-456" });
47
+ ```
48
+
49
+ The Dataset ID is still included in every request. The helper binds it locally;
50
+ it never uses a global account, last-selected Dataset or implicit Fix-it Model.
51
+
52
+ ## Input and receipt
53
+
54
+ Every task has a readable `name` and structured `input`. Optional fields are
55
+ `expectedOutput`, `split`, `tags` and `source` (`kind`, `eventId`, `label`,
56
+ `occurredAt`). The default split is `validation`. A `train` split alone does
57
+ not authorize training. Keep a missing correct answer absent rather than
58
+ replacing it with an error message.
59
+
60
+ The complete request is bounded to 128 KiB. The receipt includes workspace,
61
+ Dataset, task and operation identities, server `receivedAt`, saved revision,
62
+ `state: "saved"` and `trainingUseAuthorized: false`. Source occurrence time is
63
+ different from server upload time.
64
+
65
+ ## Delivery and retries
66
+
67
+ Retain an explicit stable idempotency key for each source event. Repeating the
68
+ same key and task in the same authorized destination returns the original
69
+ receipt without inserting a duplicate. Reusing a key with different content is
70
+ a conflict. Separate keys add separate tasks, including simultaneous writers.
71
+
72
+ The SDK makes one request; it does not silently replay arbitrary mutations.
73
+ When a response is lost, `DatasetTaskIngestionError.operationId` retains the
74
+ operation identity and `outcomeUnknown` indicates that persistence could not be
75
+ confirmed. Retry the original task with that same key. Do not generate a new
76
+ key merely because the response was interrupted. A supplied abort signal is
77
+ forwarded to the request; an interrupted response can still have been saved.
78
+
79
+ ```ts
80
+ import { DatasetTaskIngestionError } from "openpond-sdk";
81
+
82
+ try {
83
+ await addTask(task, { idempotencyKey: sourceEventId });
84
+ } catch (error) {
85
+ if (error instanceof DatasetTaskIngestionError && error.outcomeUnknown) {
86
+ // Retain task + error.operationId privately for a later exact retry.
87
+ }
88
+ throw error;
89
+ }
90
+ ```
91
+
92
+ The underlying route is `POST /v1/dataset-workspaces/{datasetId}/tasks`, with
93
+ `Authorization: Bearer …`, `X-OpenPond-Team-Id` and JSON:
94
+
95
+ ```json
96
+ {
97
+ "schemaVersion": "openpond.datasetTaskAppend.v1",
98
+ "operationId": "stable-source-event",
99
+ "task": {
100
+ "name": "Handle an expired API token",
101
+ "input": { "observedError": "Token expired" }
102
+ }
103
+ }
104
+ ```
105
+
106
+ The server owns authorization, atomic append and revision history. Appending
107
+ does not rewrite fixed Experiment Dataset versions or previously published
108
+ releases. Full authoring still uses the revisioned Dataset workspace API.
109
+
110
+ ## Python
111
+
112
+ The maintained `ponder-sdk` package exposes the same operation on `Client`
113
+ and `AsyncClient`:
114
+
115
+ ```python
116
+ from ponder_sdk import Client
117
+
118
+ with Client(base_url=api_origin, api_key=api_key, team_id=team_id) as client:
119
+ receipt = client.add_task(
120
+ dataset_id,
121
+ {"name": "Handle an expired API token", "input": {"error": "Token expired"}},
122
+ idempotency_key=source_event_id,
123
+ )
124
+ ```
125
+
126
+ Use `async with AsyncClient(...)` and `await client.add_task(...)` for async
127
+ applications. Both use the existing client connection pool and typed wire
128
+ validation. Retain the caller's key/task across an unknown mutation outcome.
129
+
130
+ ## OpenTelemetry
131
+
132
+ OpenTelemetry is an optional source adapter, not this HTTP request format.
133
+ Its span exporter can project explicitly selected spans into structured tasks
134
+ using the same destination and receipts. It does not make this endpoint an
135
+ OTLP receiver, automatically capture arbitrary logs, or authorize training.
@@ -12,10 +12,10 @@ import {
12
12
  sealAdvancedRefinerEvaluationPin,
13
13
  sealAdvancedRefinerReviewReceipt,
14
14
  verifyAdvancedRefinerEvaluationPin
15
- } from "./chunk-RN5MK7NH.js";
16
- import "./chunk-QNOCM5JX.js";
15
+ } from "./chunk-6EZAGTZG.js";
17
16
  import "./chunk-3B5KSH3V.js";
18
17
  import "./chunk-H3367ISL.js";
18
+ import "./chunk-QNOCM5JX.js";
19
19
  import "./chunk-626JLH4D.js";
20
20
  import "./chunk-O6FKHAWN.js";
21
21
  import "./chunk-GS5HEE4M.js";
@@ -1,12 +1,12 @@
1
- import {
2
- ExperimentImprovementOptionsSchema
3
- } from "./chunk-QNOCM5JX.js";
4
1
  import {
5
2
  EvaluationCoordinationTransport
6
3
  } from "./chunk-3B5KSH3V.js";
7
4
  import {
8
5
  ChatModelRefSchema
9
6
  } from "./chunk-H3367ISL.js";
7
+ import {
8
+ ExperimentImprovementOptionsSchema
9
+ } from "./chunk-QNOCM5JX.js";
10
10
  import {
11
11
  ImmutableReleaseRefSchema,
12
12
  contentHash
@@ -264,4 +264,4 @@ export {
264
264
  AdvancedRefinerEvaluationAccountingSchema,
265
265
  OpenPondAdvancedRefinerEvaluationClient
266
266
  };
267
- //# sourceMappingURL=chunk-RN5MK7NH.js.map
267
+ //# sourceMappingURL=chunk-6EZAGTZG.js.map
@@ -1,8 +1,3 @@
1
- import {
2
- materializePortableTasksetRelease,
3
- portableTasksetEnvironment,
4
- projectPortableTaskRecord
5
- } from "./chunk-GWXJSBWR.js";
6
1
  import {
7
2
  decodeTasksetDraftWorkspaceFile,
8
3
  isManagedTasksetDraftFilePath,
@@ -10,6 +5,11 @@ import {
10
5
  renderTasksetDraftManifests,
11
6
  validateTasksetDraftWorkspace
12
7
  } from "./chunk-Q4RGCEOI.js";
8
+ import {
9
+ materializePortableTasksetRelease,
10
+ portableTasksetEnvironment,
11
+ projectPortableTaskRecord
12
+ } from "./chunk-GWXJSBWR.js";
13
13
  import {
14
14
  TasksetSchema,
15
15
  computeTasksetHash
@@ -471,4 +471,4 @@ export {
471
471
  compileTasksetDraftWorkspace,
472
472
  compileModelTasksetDraftWorkspace
473
473
  };
474
- //# sourceMappingURL=chunk-3MDNVNBM.js.map
474
+ //# sourceMappingURL=chunk-BNBPKCIR.js.map
@@ -0,0 +1,140 @@
1
+ import {
2
+ readBoundedJsonResponse
3
+ } from "./chunk-B3ZHJ2KK.js";
4
+
5
+ // src/dataset-task-ingestion.ts
6
+ import { z } from "zod";
7
+ import { assertBoundedTaskJson } from "@openpond/evals/task-schema";
8
+ var Id = z.string().trim().min(1).max(240);
9
+ var DatasetTaskInputSchema = z.object({
10
+ name: z.string().trim().min(1).max(300),
11
+ input: z.record(z.string(), z.unknown()),
12
+ expectedOutput: z.record(z.string(), z.unknown()).nullable().default(null),
13
+ split: z.enum(["train", "validation", "frozen_eval"]).default("validation"),
14
+ source: z.object({
15
+ kind: z.string().trim().min(1).max(100),
16
+ eventId: Id.optional(),
17
+ label: z.string().trim().min(1).max(300).optional(),
18
+ occurredAt: z.iso.datetime().optional()
19
+ }).strict().optional(),
20
+ tags: z.array(Id).max(100).default([])
21
+ }).strict();
22
+ var DatasetTaskAppendRequestSchema = z.object({
23
+ schemaVersion: z.literal("openpond.datasetTaskAppend.v1"),
24
+ operationId: Id,
25
+ task: DatasetTaskInputSchema
26
+ }).strict();
27
+ var DatasetTaskAppendReceiptSchema = z.object({
28
+ schemaVersion: z.literal("openpond.datasetTaskReceipt.v1"),
29
+ teamId: Id,
30
+ datasetId: z.string().trim().min(1).max(240),
31
+ taskId: Id,
32
+ operationId: Id,
33
+ receivedAt: z.iso.datetime(),
34
+ revision: z.number().int().positive(),
35
+ state: z.literal("saved"),
36
+ trainingUseAuthorized: z.literal(false)
37
+ }).strict();
38
+ var DatasetTaskIngestionError = class extends Error {
39
+ constructor(message, status, code, operationId) {
40
+ super(message);
41
+ this.status = status;
42
+ this.code = code;
43
+ this.operationId = operationId;
44
+ this.name = "DatasetTaskIngestionError";
45
+ this.outcomeUnknown = status === 0 || status >= 500 || code === "dataset_task_receipt_invalid";
46
+ }
47
+ status;
48
+ code;
49
+ operationId;
50
+ outcomeUnknown;
51
+ };
52
+ async function addDatasetTask(config, datasetId, task, options = {}) {
53
+ const url = new URL(config.baseUrl);
54
+ if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || url.search || url.hash || url.pathname !== "/")
55
+ throw new Error("A clean API origin is required.");
56
+ const teamId = Id.parse(config.teamId);
57
+ if (!config.apiKey.trim()) throw new Error("An OpenPond API key is required.");
58
+ const id = z.string().trim().min(1).max(240).parse(datasetId);
59
+ const request = DatasetTaskAppendRequestSchema.parse({
60
+ schemaVersion: "openpond.datasetTaskAppend.v1",
61
+ operationId: options.idempotencyKey ?? crypto.randomUUID(),
62
+ task
63
+ });
64
+ assertBoundedTaskJson(request, 128 * 1024);
65
+ let response;
66
+ try {
67
+ response = await (config.fetch ?? fetch)(
68
+ `${url.origin}/v1/dataset-workspaces/${encodeURIComponent(id)}/tasks`,
69
+ {
70
+ method: "POST",
71
+ redirect: "error",
72
+ signal: options.signal,
73
+ headers: {
74
+ Authorization: `Bearer ${config.apiKey}`,
75
+ "X-OpenPond-Team-Id": teamId,
76
+ "Content-Type": "application/json"
77
+ },
78
+ body: JSON.stringify(request)
79
+ }
80
+ );
81
+ } catch {
82
+ throw new DatasetTaskIngestionError(
83
+ "Task delivery could not be confirmed. Retry with the same operation ID.",
84
+ 0,
85
+ "dataset_task_outcome_unknown",
86
+ request.operationId
87
+ );
88
+ }
89
+ let raw;
90
+ try {
91
+ raw = await readBoundedJsonResponse(response, 64 * 1024, "Dataset task receipt");
92
+ } catch {
93
+ throw new DatasetTaskIngestionError(
94
+ "Task delivery returned an invalid receipt. Retain the same operation ID before retrying.",
95
+ response.status,
96
+ "dataset_task_receipt_invalid",
97
+ request.operationId
98
+ );
99
+ }
100
+ if (!response.ok) {
101
+ const error = z.object({ message: z.string().optional(), code: z.string().optional() }).passthrough().safeParse(raw);
102
+ throw new DatasetTaskIngestionError(
103
+ error.success ? error.data.message ?? "Task submission failed." : "Task submission failed.",
104
+ response.status,
105
+ error.success ? error.data.code ?? "dataset_task_request_failed" : "dataset_task_request_failed",
106
+ request.operationId
107
+ );
108
+ }
109
+ const parsed = DatasetTaskAppendReceiptSchema.safeParse(raw);
110
+ if (!parsed.success)
111
+ throw new DatasetTaskIngestionError(
112
+ "Task delivery returned an invalid receipt.",
113
+ response.status,
114
+ "dataset_task_receipt_invalid",
115
+ request.operationId
116
+ );
117
+ const receipt = parsed.data;
118
+ if (receipt.teamId !== teamId || receipt.datasetId !== id || receipt.operationId !== request.operationId)
119
+ throw new DatasetTaskIngestionError(
120
+ "Dataset task receipt identity mismatch.",
121
+ response.status,
122
+ "dataset_task_receipt_invalid",
123
+ request.operationId
124
+ );
125
+ return receipt;
126
+ }
127
+ function createTaskAdder(config) {
128
+ const { datasetId, ...connection } = config;
129
+ return (task, options) => addDatasetTask(connection, datasetId, task, options);
130
+ }
131
+
132
+ export {
133
+ DatasetTaskInputSchema,
134
+ DatasetTaskAppendRequestSchema,
135
+ DatasetTaskAppendReceiptSchema,
136
+ DatasetTaskIngestionError,
137
+ addDatasetTask,
138
+ createTaskAdder
139
+ };
140
+ //# sourceMappingURL=chunk-NZRGRUYG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dataset-task-ingestion.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { assertBoundedTaskJson } from \"@openpond/evals/task-schema\";\nimport { readBoundedJsonResponse } from \"./protocol.js\";\n\nconst Id = z.string().trim().min(1).max(240);\nexport const DatasetTaskInputSchema = z\n .object({\n name: z.string().trim().min(1).max(300),\n input: z.record(z.string(), z.unknown()),\n expectedOutput: z.record(z.string(), z.unknown()).nullable().default(null),\n split: z.enum([\"train\", \"validation\", \"frozen_eval\"]).default(\"validation\"),\n source: z\n .object({\n kind: z.string().trim().min(1).max(100),\n eventId: Id.optional(),\n label: z.string().trim().min(1).max(300).optional(),\n occurredAt: z.iso.datetime().optional(),\n })\n .strict()\n .optional(),\n tags: z.array(Id).max(100).default([]),\n })\n .strict();\nexport const DatasetTaskAppendRequestSchema = z\n .object({\n schemaVersion: z.literal(\"openpond.datasetTaskAppend.v1\"),\n operationId: Id,\n task: DatasetTaskInputSchema,\n })\n .strict();\nexport const DatasetTaskAppendReceiptSchema = z\n .object({\n schemaVersion: z.literal(\"openpond.datasetTaskReceipt.v1\"),\n teamId: Id,\n datasetId: z.string().trim().min(1).max(240),\n taskId: Id,\n operationId: Id,\n receivedAt: z.iso.datetime(),\n revision: z.number().int().positive(),\n state: z.literal(\"saved\"),\n trainingUseAuthorized: z.literal(false),\n })\n .strict();\nexport type DatasetTaskInput = z.input<typeof DatasetTaskInputSchema>;\nexport type DatasetTaskAppendReceipt = z.infer<typeof DatasetTaskAppendReceiptSchema>;\nexport type AddTaskOptions = { idempotencyKey?: string; signal?: AbortSignal };\nexport type DatasetTaskClientOptions = {\n apiKey: string;\n baseUrl: string;\n teamId: string;\n fetch?: typeof fetch;\n};\n\nexport class DatasetTaskIngestionError extends Error {\n readonly outcomeUnknown: boolean;\n constructor(\n message: string,\n readonly status: number,\n readonly code: string,\n readonly operationId: string,\n ) {\n super(message);\n this.name = \"DatasetTaskIngestionError\";\n this.outcomeUnknown = status === 0 || status >= 500 || code === \"dataset_task_receipt_invalid\";\n }\n}\n\n/** A bounded append, independent of complete workspace downloads or replacement. */\nexport async function addDatasetTask(\n config: DatasetTaskClientOptions,\n datasetId: string,\n task: DatasetTaskInput,\n options: AddTaskOptions = {},\n): Promise<DatasetTaskAppendReceipt> {\n const url = new URL(config.baseUrl);\n if (\n ![\"http:\", \"https:\"].includes(url.protocol) ||\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n url.pathname !== \"/\"\n )\n throw new Error(\"A clean API origin is required.\");\n const teamId = Id.parse(config.teamId);\n if (!config.apiKey.trim()) throw new Error(\"An OpenPond API key is required.\");\n const id = z.string().trim().min(1).max(240).parse(datasetId);\n const request = DatasetTaskAppendRequestSchema.parse({\n schemaVersion: \"openpond.datasetTaskAppend.v1\",\n operationId: options.idempotencyKey ?? crypto.randomUUID(),\n task,\n });\n assertBoundedTaskJson(request, 128 * 1024);\n let response: Response;\n try {\n response = await (config.fetch ?? fetch)(\n `${url.origin}/v1/dataset-workspaces/${encodeURIComponent(id)}/tasks`,\n {\n method: \"POST\",\n redirect: \"error\",\n signal: options.signal,\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n \"X-OpenPond-Team-Id\": teamId,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n },\n );\n } catch {\n throw new DatasetTaskIngestionError(\n \"Task delivery could not be confirmed. Retry with the same operation ID.\",\n 0,\n \"dataset_task_outcome_unknown\",\n request.operationId,\n );\n }\n let raw: unknown;\n try {\n raw = await readBoundedJsonResponse(response, 64 * 1024, \"Dataset task receipt\");\n } catch {\n throw new DatasetTaskIngestionError(\n \"Task delivery returned an invalid receipt. Retain the same operation ID before retrying.\",\n response.status,\n \"dataset_task_receipt_invalid\",\n request.operationId,\n );\n }\n if (!response.ok) {\n const error = z\n .object({ message: z.string().optional(), code: z.string().optional() })\n .passthrough()\n .safeParse(raw);\n throw new DatasetTaskIngestionError(\n error.success ? (error.data.message ?? \"Task submission failed.\") : \"Task submission failed.\",\n response.status,\n error.success\n ? (error.data.code ?? \"dataset_task_request_failed\")\n : \"dataset_task_request_failed\",\n request.operationId,\n );\n }\n const parsed = DatasetTaskAppendReceiptSchema.safeParse(raw);\n if (!parsed.success)\n throw new DatasetTaskIngestionError(\n \"Task delivery returned an invalid receipt.\",\n response.status,\n \"dataset_task_receipt_invalid\",\n request.operationId,\n );\n const receipt = parsed.data;\n if (\n receipt.teamId !== teamId ||\n receipt.datasetId !== id ||\n receipt.operationId !== request.operationId\n )\n throw new DatasetTaskIngestionError(\n \"Dataset task receipt identity mismatch.\",\n response.status,\n \"dataset_task_receipt_invalid\",\n request.operationId,\n );\n return receipt;\n}\n\n/** Bind credentials and destination once; the returned addTask has no global state. */\nexport function createTaskAdder(config: DatasetTaskClientOptions & { datasetId: string }) {\n const { datasetId, ...connection } = config;\n return (task: DatasetTaskInput, options?: AddTaskOptions) =>\n addDatasetTask(connection, datasetId, task, options);\n}\n"],"mappings":"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","names":[]}
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-GPQLBVQC.js";
10
10
  import {
11
11
  AuthoredTasksetFileInventorySchema
12
- } from "./chunk-3MDNVNBM.js";
12
+ } from "./chunk-BNBPKCIR.js";
13
13
  import {
14
14
  configuredTasksetDraftFiles,
15
15
  createTasksetDraftWorkspace,
@@ -698,4 +698,4 @@ export {
698
698
  prepareTasksetDraftSource,
699
699
  materializeTasksetDraftWorkspace
700
700
  };
701
- //# sourceMappingURL=chunk-RT7SQHO4.js.map
701
+ //# sourceMappingURL=chunk-SP7DQEQM.js.map
@@ -49,15 +49,15 @@ import {
49
49
  ConnectedStartingAssetsRequestSchema,
50
50
  verifyConnectedStartingAssetsReceipt
51
51
  } from "./chunk-AG6UJ3DI.js";
52
- import "./chunk-3MDNVNBM.js";
53
- import "./chunk-GWXJSBWR.js";
52
+ import "./chunk-BNBPKCIR.js";
54
53
  import "./chunk-Q4RGCEOI.js";
54
+ import "./chunk-GWXJSBWR.js";
55
55
  import "./chunk-GCUWJUUM.js";
56
56
  import {
57
57
  ConnectedDatasetSourceRefSchema
58
58
  } from "./chunk-ZQ6QTYRE.js";
59
- import "./chunk-Z252BNAZ.js";
60
59
  import "./chunk-TK3DXH7A.js";
60
+ import "./chunk-Z252BNAZ.js";
61
61
  import "./chunk-H3367ISL.js";
62
62
  import "./chunk-O6FKHAWN.js";
63
63
  import "./chunk-QTNYXOJW.js";