@toloka-platform/sdk 0.10.1 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -1 +1 @@
1
- 859c02ad3a3eb8c625626fa848dc18f99d9a26182acf6711d7494aab99c97d58 toloka.js.jsc
1
+ 6a0f8dbdd98f49a9c663bb3051960c4f168961bc4ebd8b428ae75fd5f07ba994 toloka.js.jsc
@@ -1 +1 @@
1
- 282112f0046d172447dc497f576ae5d0a8a026e7273e66614df358793fd41245 toloka.js
1
+ 20b4b75534617c8aed19bf129f8b78fe18d43a5a91221f1aa4bf2fbc0f792175 toloka.js
@@ -13,4 +13,5 @@ export type PipelineCostEstimateNodesItemOneOfFive = {
13
13
  maxTotal: string;
14
14
  perItemExpected: PipelineCostEstimateNodesItemOneOfFivePerItemExpected;
15
15
  displayBreakdown: unknown[];
16
+ warning?: string;
16
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toloka-platform/sdk",
3
- "version": "0.10.1",
3
+ "version": "0.11.1",
4
4
  "private": false,
5
5
  "description": "Build, inspect, and operate Toloka pipeline projects as TypeScript source. The public API may change between minor versions before 1.0.",
6
6
  "license": "Apache-2.0",
@@ -77,6 +77,6 @@
77
77
  "bun": ">=1.4.0"
78
78
  },
79
79
  "tolokaBuild": {
80
- "commit": "e43b0e3d09a4dd7223638ac15b16fa7ce2f0c28d"
80
+ "commit": "62d9c4558758f7409b65de7c849c8a2e8d15ba9a"
81
81
  }
82
82
  }
@@ -11,8 +11,8 @@
11
11
  "testing",
12
12
  "checks"
13
13
  ],
14
- "version": "0.10.1",
15
- "digest": "a52f9d3be18876289f03f81aaa18c31904b3b4cb98cd0fd3b26d6177834f24c9",
14
+ "version": "0.11.1",
15
+ "digest": "79283e8ca89ddafa3d6206be108db32046f6941fb52d4b622aec72c20b791de7",
16
16
  "files": [
17
17
  "SKILL.md",
18
18
  "references/node-semantics.md",
@@ -29,7 +29,7 @@
29
29
  "bug",
30
30
  "report"
31
31
  ],
32
- "version": "0.10.1",
32
+ "version": "0.11.1",
33
33
  "digest": "70f0bd2c80b32f87896aeb27c363b8a2d37f40e22424f57fe1aad142e125ad67",
34
34
  "files": [
35
35
  "SKILL.md",
@@ -46,7 +46,7 @@
46
46
  "getting-started",
47
47
  "agent"
48
48
  ],
49
- "version": "0.10.1",
49
+ "version": "0.11.1",
50
50
  "digest": "ccf148c682de4e452bb031db95d3933257899006b1766f0fdbc3d15265a63bb9",
51
51
  "files": [
52
52
  "SKILL.md"
@@ -63,7 +63,7 @@
63
63
  "sft",
64
64
  "models"
65
65
  ],
66
- "version": "0.10.1",
66
+ "version": "0.11.1",
67
67
  "digest": "279c69977eef170dada20b664ee0c30858681e84a2cabb2fdff18b8bb1bdc055",
68
68
  "files": [
69
69
  "SKILL.md"
@@ -80,7 +80,7 @@
80
80
  "prompt",
81
81
  "models"
82
82
  ],
83
- "version": "0.10.1",
83
+ "version": "0.11.1",
84
84
  "digest": "b9f314eb6b39754bc8d2ae79aca3dc680fced5f14948c975d1e084a83c2e0a8c",
85
85
  "files": [
86
86
  "SKILL.md"
@@ -101,7 +101,9 @@ A scoped token downloads project files in two steps: a request to `ProjectFile.u
101
101
  ## Configure the CLI
102
102
 
103
103
  Provide the API key and base URL on networked workflows through `TOLOKA_API_KEY` and
104
- `TOLOKA_BASE_URL`, or with `--api-key` and `--base-url`. The registry-mutating commands
104
+ `TOLOKA_BASE_URL`, or with `--api-key` and `--base-url`. A base URL with a path (a gateway such as
105
+ `https://gateway.example/ss/pp.1`) keeps that path on every request, with or without a trailing
106
+ slash; use the given URL unchanged. The registry-mutating commands
105
107
  `toloka project add`, `toloka project switch`, `toloka project remove`, and `toloka project create`
106
108
  require `toloka login` first because they read and write the credentials file. When flags or
107
109
  `TOLOKA_*` variables are also present, they must identify the same stored key and platform. Resolve
@@ -191,7 +193,7 @@ Resolve the intended platform project before `import`, `plan`, or `apply`; use a
191
193
 
192
194
  `toloka audience specialization list` prints the global specialization catalog: `ID`, `NAME`, and `EXPERTS` columns sorted by name (`--json` for the array). Run it before setting `audience.specializations` on a node, pick entries by name, and copy `ID` into `qualificationId` and `NAME` into `value`; never invent a `qualificationId`. `EXPERTS` counts ID-verified experts currently eligible for tasks; a `0` means the id is valid but nobody currently qualifies, so prefer another specialization or widen the audience.
193
195
 
194
- `toloka pipeline cost [name] [--item-limit <n>]` forecasts what a run of a live, validated pipeline would bill. It does not start a run or change the graph. If any billed node is marked `skipped`, the displayed total is incomplete and must not be presented as the pipeline price. Compute and label a labor floor for each skipped billed node as `items × pricePerTask × annotations per item`, using `1` for generation and `overlap` for quorum. Also report `maxEntities`, quality-criteria count, and only exclusions applicable to the authored QA and workflow. Apply accepting a rate does not prove its final billed value.
196
+ `toloka pipeline cost [name] [--item-limit <n>]` forecasts what a run of a live, validated pipeline would bill. It does not start a run or change the graph. If any billed node is marked `skipped`, the displayed total is incomplete and must not be presented as the pipeline price. Compute and label a labor floor for each skipped billed node as `items × pricePerTask × annotations per item`, using `1` for generation and `overlap` for quorum. Also report `maxEntities`, quality-criteria count, and only exclusions applicable to the authored QA and workflow. Apply accepting a rate does not prove its final billed value. If the output lists warnings, include them when you present the forecast.
195
197
 
196
198
  ## Manage model checkpoints
197
199
 
package/src/cli/cost.ts CHANGED
@@ -56,9 +56,10 @@ const collectLineRows = (line: CostLine, depth: number): TableRow[] => {
56
56
 
57
57
  const collectNodeRows = (
58
58
  nodes: PipelineCostEstimate["nodes"],
59
- ): { billed: TableRow[]; unpriced: string[] } => {
59
+ ): { billed: TableRow[]; unpriced: string[]; warnings: string[] } => {
60
60
  const billed: TableRow[] = [];
61
61
  const unpriced: string[] = [];
62
+ const warnings: string[] = [];
62
63
 
63
64
  for (const node of nodes) {
64
65
  if (node.kind === "priced") {
@@ -66,6 +67,7 @@ const collectNodeRows = (
66
67
  for (const line of node.displayBreakdown) {
67
68
  if (isCostLine(line)) billed.push(...collectLineRows(line, 1));
68
69
  }
70
+ if (node.warning !== undefined) warnings.push(` ${node.nodeNameDisplay}: ${node.warning}`);
69
71
  continue;
70
72
  }
71
73
 
@@ -76,7 +78,7 @@ const collectNodeRows = (
76
78
  );
77
79
  }
78
80
 
79
- return { billed, unpriced };
81
+ return { billed, unpriced, warnings };
80
82
  };
81
83
 
82
84
  const collectTotalRows = (total: PipelineCostEstimate["total"]): TableRow[] => {
@@ -100,7 +102,7 @@ export const formatCostEstimate = (
100
102
  estimate: PipelineCostEstimate,
101
103
  pipelineName: string,
102
104
  ): string => {
103
- const { billed, unpriced } = collectNodeRows(estimate.nodes);
105
+ const { billed, unpriced, warnings } = collectNodeRows(estimate.nodes);
104
106
  const totals = collectTotalRows(estimate.total);
105
107
  const table = formatTable([["Item", "Expected", "Maximum"], ...billed, ...totals]);
106
108
  const billedRows = table.slice(0, 1 + billed.length);
@@ -122,6 +124,10 @@ export const formatCostEstimate = (
122
124
  output.push("", "Not billed", ...unpriced);
123
125
  }
124
126
 
127
+ if (warnings.length > 0) {
128
+ output.push("", "Warnings", ...warnings);
129
+ }
130
+
125
131
  if (estimate.isInternalPricing === true) {
126
132
  output.push("", "Internal-team pricing.");
127
133
  }
package/src/transport.ts CHANGED
@@ -47,6 +47,15 @@ const prepareRequestInit = (requestOptions: RequestInit, headers: Headers): Requ
47
47
  return { ...requestOptions, headers, body: "{}" };
48
48
  };
49
49
 
50
+ // The generated client passes absolute paths (`/api/v2-beta/...`), and `new URL(path, base)` resolves
51
+ // those against the base's origin, dropping its path. Join them instead, so a base URL served under a
52
+ // path prefix (a gateway in front of the platform) keeps that prefix.
53
+ const resolveRequestUrl = (url: string, baseUrl: string): URL => {
54
+ if (!url.startsWith("/") || url.startsWith("//")) return new URL(url, baseUrl);
55
+ const base = new URL(baseUrl);
56
+ return new URL(`${base.pathname.replace(/\/+$/, "")}${url}`, base.origin);
57
+ };
58
+
50
59
  export function potatoFetch<T>(url: string, options: TransportRequestInit): Promise<T>;
51
60
  export async function potatoFetch(url: string, options: TransportRequestInit): Promise<unknown> {
52
61
  const { fetch: fetchImplementation = globalThis.fetch, authorization, ...requestOptions } = options;
@@ -57,7 +66,7 @@ export async function potatoFetch(url: string, options: TransportRequestInit): P
57
66
  if (authorization !== undefined) headers.set("Authorization", await authorization());
58
67
 
59
68
  const response = await fetchImplementation(
60
- new URL(url, baseUrl),
69
+ resolveRequestUrl(url, baseUrl),
61
70
  prepareRequestInit(requestOptions, headers),
62
71
  );
63
72
  const text = await response.text();