@toloka-platform/sdk 0.5.0 → 0.5.2

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
- 3c0d5e23bb0e2dbb4eb3ff9b8cbd12bb0131913cbc003d3ca38fd07b2817e1db toloka.js.jsc
1
+ 4144ed5bb1a0a9b6f7b983e854cc0094315f954e25f0a31097f6394bc7adc7dd toloka.js.jsc
@@ -1 +1 @@
1
- afcf63725d2847148fe664a722afd103ddd2521059bdfd79e7be0cab351b4bc4 toloka.js
1
+ babd9144be52b672bdbba134f9820f13e96c51081f7600408354e564aeb8ef13 toloka.js
package/docs/cli.md CHANGED
@@ -137,8 +137,16 @@ toloka project url
137
137
  toloka project remove <alias>
138
138
  toloka project create [alias] [--name <name>] [--team-id <id>] [--delivery-order-id <id>]
139
139
  toloka project untrack <pipeline|dataset> <name> [--confirm]
140
+ toloka project token [--preset <name>] [--permissions <list>] [--expires-in <seconds>] [--projects <list>]
141
+ toloka project tokens
142
+ toloka project revoke-token <tokenId>
143
+ toloka project revoke-tokens
140
144
  ```
141
145
 
146
+ `token` mints a project-scoped token for the selected project and prints it once; it is never stored. The token acts as you inside that project (plus any `--projects`, which must belong to the same team) with the permissions of the `--preset` (`read`, `write`, `deploy`, `labeling-read`, `labeling-write`, `labeling-deploy`; default `write`) or an explicit `--permissions` list, and expires after `--expires-in` seconds (60..21600, default six hours). Hand it to an agent as `TOLOKA_API_KEY`. One user may hold at most 1000 live tokens per project, counted against every project the token covers; beyond that, `token` fails with `429 You already hold 1000 live tokens for project <id>; revoke unused tokens first`.
147
+
148
+ `tokens` lists every live token of the selected project, newest first, with its id, user, expiry, projects, and permissions. `revoke-token <tokenId>` revokes one token and prints `Revoked <tokenId>.`; `revoke-tokens` revokes every live token of the selected project in one call and prints `Revoked <n> tokens.`. A token that covers several projects is revoked as a whole by either command. Revocation takes effect immediately.
149
+
142
150
  `add`, `switch`, `remove`, and `create` write the machine registry in the credentials file. They refuse `--api-key` / `--base-url` / `TOLOKA_*` when those would select a different key or platform than the stored file. `project list` prints project id, name, and team id. `create` uses the account's only writable team (`GET /me` lists the teams; `whoami` prints them) and asks for `--team-id` when there are several. A project owned by an internal team also needs `--delivery-order-id`; `toloka delivery-order list` shows the orders and answers with an explanation for accounts without internal teams.
143
151
 
144
152
  `project untrack` removes one pipeline or dataset binding from `toloka.json` without deleting the live resource. It previews the name and id in a terminal; outside a terminal, pass `--confirm` after reviewing the state file.
@@ -57,6 +57,7 @@ import type {
57
57
  ListProjectPipelinesParams,
58
58
  ListProjectSecrets200,
59
59
  ListProjectTokens200,
60
+ ListProjectTokensParams,
60
61
  ListProjectTrainings200,
61
62
  ListProjectTrainingsParams,
62
63
  ListProjects200,
@@ -83,6 +84,7 @@ import type {
83
84
  ProjectSecretName,
84
85
  ReplacePipelineGraphBody,
85
86
  ReplaceTrainingConfigurationBody,
87
+ RevokedScopedTokens,
86
88
  RunCost,
87
89
  RunId,
88
90
  RunItem,
@@ -1646,7 +1648,37 @@ export const createProjectToken = async (projectId: ProjectId,
1646
1648
 
1647
1649
 
1648
1650
 
1649
- export const getListProjectTokensUrl = (projectId: ProjectId,) => {
1651
+ export const getListProjectTokensUrl = (projectId: ProjectId,
1652
+ params?: ListProjectTokensParams,) => {
1653
+ const normalizedParams = new URLSearchParams();
1654
+
1655
+ Object.entries(params || {}).forEach(([key, value]) => {
1656
+
1657
+ if (value !== undefined) {
1658
+ normalizedParams.append(key, value === null ? 'null' : value.toString())
1659
+ }
1660
+ });
1661
+
1662
+ const stringifiedParams = normalizedParams.toString();
1663
+
1664
+ return stringifiedParams.length > 0 ? `/api/v2-beta/projects/${projectId}/tokens?${stringifiedParams}` : `/api/v2-beta/projects/${projectId}/tokens`
1665
+ }
1666
+
1667
+ export const listProjectTokens = async (projectId: ProjectId,
1668
+ params?: ListProjectTokensParams, options?: RequestInit): Promise<ListProjectTokens200> => {
1669
+
1670
+ return potatoFetch<ListProjectTokens200>(getListProjectTokensUrl(projectId,params),
1671
+ {
1672
+ ...options,
1673
+ method: 'GET'
1674
+
1675
+
1676
+ }
1677
+ );}
1678
+
1679
+
1680
+
1681
+ export const getRevokeProjectTokensUrl = (projectId: ProjectId,) => {
1650
1682
 
1651
1683
 
1652
1684
 
@@ -1654,12 +1686,12 @@ export const getListProjectTokensUrl = (projectId: ProjectId,) => {
1654
1686
  return `/api/v2-beta/projects/${projectId}/tokens`
1655
1687
  }
1656
1688
 
1657
- export const listProjectTokens = async (projectId: ProjectId, options?: RequestInit): Promise<ListProjectTokens200> => {
1689
+ export const revokeProjectTokens = async (projectId: ProjectId, options?: RequestInit): Promise<RevokedScopedTokens> => {
1658
1690
 
1659
- return potatoFetch<ListProjectTokens200>(getListProjectTokensUrl(projectId),
1691
+ return potatoFetch<RevokedScopedTokens>(getRevokeProjectTokensUrl(projectId),
1660
1692
  {
1661
1693
  ...options,
1662
- method: 'GET'
1694
+ method: 'DELETE'
1663
1695
 
1664
1696
 
1665
1697
  }
@@ -312,6 +312,7 @@ export * from './listProjectPipelines200';
312
312
  export * from './listProjectPipelinesParams';
313
313
  export * from './listProjectSecrets200';
314
314
  export * from './listProjectTokens200';
315
+ export * from './listProjectTokensParams';
315
316
  export * from './listProjectTrainings200';
316
317
  export * from './listProjectTrainingsParams';
317
318
  export * from './listProjects200';
@@ -784,6 +785,7 @@ export * from './quorumNodeSettingsSmartSearchAnyOfProjectDescription';
784
785
  export * from './quorumNodeSettingsUi';
785
786
  export * from './replacePipelineGraphBody';
786
787
  export * from './replaceTrainingConfigurationBody';
788
+ export * from './revokedScopedTokens';
787
789
  export * from './rootNode';
788
790
  export * from './rootNodeSettings';
789
791
  export * from './rootNodeSettingsCompletedFieldProxies';
@@ -1,5 +1,7 @@
1
1
  import type { ScopedTokenSummary } from './scopedTokenSummary';
2
+ import type { Pagination } from './pagination';
2
3
 
3
4
  export type ListProjectTokens200 = {
4
5
  tokens: ScopedTokenSummary[];
6
+ pagination: Pagination;
5
7
  };
@@ -0,0 +1,5 @@
1
+
2
+ export type ListProjectTokensParams = {
3
+ limit?: number;
4
+ offset?: number;
5
+ };
@@ -0,0 +1,4 @@
1
+
2
+ export interface RevokedScopedTokens {
3
+ revokedCount: number;
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toloka-platform/sdk",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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": "bedafbf246da90b701d9a4f34bfbbd1c1057829b"
80
+ "commit": "ae2c20f000f63863115fd153a0e15dc599dd85ed"
81
81
  }
82
82
  }
@@ -11,8 +11,8 @@
11
11
  "testing",
12
12
  "checks"
13
13
  ],
14
- "version": "0.5.0",
15
- "digest": "d10767a13e558bb74e64768dbcc5260e8f78b5541050ed5cb6d5eb9809733107",
14
+ "version": "0.5.2",
15
+ "digest": "0c36f68ae116fe72362d43c9a2b4bc74685614c41f8bccf1fb053b2d13a1ea94",
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.5.0",
32
+ "version": "0.5.2",
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.5.0",
49
+ "version": "0.5.2",
50
50
  "digest": "ccf148c682de4e452bb031db95d3933257899006b1766f0fdbc3d15265a63bb9",
51
51
  "files": [
52
52
  "SKILL.md"
@@ -63,8 +63,8 @@
63
63
  "sft",
64
64
  "models"
65
65
  ],
66
- "version": "0.5.0",
67
- "digest": "76863f7d64f0590dcb2dfa23cff6ea4e5d862a772227ab9d451155ec39004236",
66
+ "version": "0.5.2",
67
+ "digest": "f9c34569fc344f365c79c86819adffc86c78a2ce74e17ba10755ddefaf71790f",
68
68
  "files": [
69
69
  "SKILL.md"
70
70
  ]
@@ -80,8 +80,8 @@
80
80
  "prompt",
81
81
  "models"
82
82
  ],
83
- "version": "0.5.0",
84
- "digest": "bbf1a587d53afdc6a71d8302437e3148150764fed078f491babae36da2d99283",
83
+ "version": "0.5.2",
84
+ "digest": "902aee47c952e105a6340ee56bf22e79513e2d45d19a7ffbf58990f277387e34",
85
85
  "files": [
86
86
  "SKILL.md"
87
87
  ]
@@ -92,6 +92,12 @@ revoke an API key.
92
92
 
93
93
  Standalone and Bun-global `toloka` installations check the public npm registry at most once per day and install eligible releases at least 24 hours old before rerunning the command. Project-local installs, CI, and `config`, `version`, and `help` skip the check. Turn it off with `toloka config set auto-update false`. For manual standalone updates, rerun `curl -fsSL https://platform.toloka.ai/cli/install.sh | sh -s -- --native`; Bun-global updates should use `--bun` instead. Preserve the mode and put any original `TOLOKA_CLI_INSTALL_DIR`, `TOLOKA_CLI_CHANNEL`, `TOLOKA_CLI_PACKAGE`, and `TOLOKA_CLI_REGISTRY` overrides on the `sh` side of the pipe again. A package version pin does not disable automatic updates, which always use the public npm registry.
94
94
 
95
+ ## Hand out a project-scoped token
96
+
97
+ `toloka project token` mints a token that acts as the signed-in user inside the selected project only (`--projects` adds more projects of the same team), with the permissions of `--preset` (default `write`) or an explicit `--permissions` list, for at most six hours. It is printed once and never stored; pass it to another agent or script as `TOLOKA_API_KEY`. `toloka project tokens` lists the live tokens of the project; `toloka project revoke-token <tokenId>` ends one and `toloka project revoke-tokens` ends every live token of the project at once, for example when a run finished or a token leaked. One user may hold at most 1000 live tokens per project; when `token` fails with `429 … revoke unused tokens first`, run `revoke-tokens`.
98
+
99
+ A scoped token downloads project files in two steps: a request to `ProjectFile.url` with the token answers `200 {"url": "<storage URL>"}` instead of the redirect a human credential gets. Fetch that `url` as a plain request without the `X-Scoped-Token` header; HTTP clients replay custom headers across redirects, and the token must never reach the storage host.
100
+
95
101
  ## Configure the CLI
96
102
 
97
103
  Provide the API key and base URL on networked workflows through `TOLOKA_API_KEY` and
@@ -126,6 +132,10 @@ toloka project url
126
132
  toloka project remove <alias>
127
133
  toloka project create [alias] [--name <name>] [--team-id <id>] [--delivery-order-id <id>]
128
134
  toloka project untrack <pipeline|dataset> <name> [--confirm]
135
+ toloka project token [--preset <name>] [--permissions <list>] [--expires-in <seconds>] [--projects <list>]
136
+ toloka project tokens
137
+ toloka project revoke-token <tokenId>
138
+ toloka project revoke-tokens
129
139
  toloka delivery-order list
130
140
  toloka audience specialization list [--json]
131
141
  toloka init
@@ -146,6 +146,8 @@ Resume only after the user confirms a billing block is resolved. Cancel only on
146
146
 
147
147
  A run can train longer than the estimate predicted. It stays `running`, the charge stays capped at the approved `maximumCharge`, and the Model Version publishes when training finishes; treat a slow run as still running, not as failed, and do not start a duplicate run for it. A run that ends `failed` with error code `provider_failed` or `provider_timeout` is a platform-side failure: it is charged nothing and the whole hold returns to the team balance, while its reported GPU seconds stay visible; a run the user cancels during training is charged for the GPU seconds used.
148
148
 
149
+ A run can also wait for GPU capacity before training starts. In `training status --json` the run stays `running` while `progress.phase` is `queued` or `pending`; the wait can take hours when capacity is short, and the run starts training on its own. Treat it as still running.
150
+
149
151
  For a completed run, verify the observed output and download only when requested:
150
152
 
151
153
  ```sh
@@ -155,6 +155,8 @@ Resume only after the user confirms a billing block is resolved. Cancel only on
155
155
 
156
156
  A run can train longer than the estimate predicted. It stays `running`, the charge stays capped at the approved `maximumCharge`, and the Model Version publishes when training finishes; treat a slow run as still running, not as failed, and do not start a duplicate run for it. A run that ends `failed` with error code `provider_failed` or `provider_timeout` is a platform-side failure: it is charged nothing and the whole hold returns to the team balance, while its reported GPU seconds stay visible; a run the user cancels during training is charged for the GPU seconds used.
157
157
 
158
+ A run can also wait for GPU capacity before training starts. In `training status --json` the run stays `running` while `progress.phase` is `queued` or `pending`; the wait can take hours when capacity is short, and the run starts training on its own. Treat it as still running.
159
+
158
160
  For a completed run, verify the observed output and download only when requested:
159
161
 
160
162
  ```sh
@@ -14,7 +14,7 @@ import { addProject, assertProjectSelected, createProject, currentProject, listR
14
14
  import { readTolokaState } from "../../state";
15
15
  import { assertCli } from "../cli-error";
16
16
  import { formatTable } from "../table";
17
- import type { CreateScopedTokenBodyAnyOfPreset } from "../../../openapi/gen/models";
17
+ import type { CreateScopedTokenBodyAnyOfPreset, ScopedTokenSummary } from "../../../openapi/gen/models";
18
18
 
19
19
  const TOKEN_PRESETS: readonly CreateScopedTokenBodyAnyOfPreset[] = [
20
20
  "read",
@@ -183,7 +183,10 @@ export const registerProjectCommands = (program: Command, host: CommandHost): vo
183
183
  .action(async () => {
184
184
  const { client, projectId } = await resolveContext(globals(), context);
185
185
  assertProjectSelected(projectId);
186
- const { tokens } = await client.projects.listTokens({ projectId });
186
+ const tokens: ScopedTokenSummary[] = [];
187
+ for await (const token of client.projects.listAllTokens({ projectId })) {
188
+ tokens.push(token);
189
+ }
187
190
  context.io.stdout(
188
191
  tokens.length === 0
189
192
  ? "No live tokens."
@@ -209,6 +212,15 @@ export const registerProjectCommands = (program: Command, host: CommandHost): vo
209
212
  await client.projects.revokeToken({ projectId, tokenId });
210
213
  context.io.stdout(`Revoked ${tokenId}.`);
211
214
  });
215
+ project
216
+ .command("revoke-tokens")
217
+ .description("revoke every live project-scoped token of the project; they stop working immediately")
218
+ .action(async () => {
219
+ const { client, projectId } = await resolveContext(globals(), context);
220
+ assertProjectSelected(projectId);
221
+ const { revokedCount } = await client.projects.revokeAllTokens({ projectId });
222
+ context.io.stdout(`Revoked ${revokedCount} token${revokedCount === 1 ? "" : "s"}.`);
223
+ });
212
224
  const create = project
213
225
  .command("create")
214
226
  .argument("[alias]", "local name for the new project")
package/src/client.ts CHANGED
@@ -37,6 +37,7 @@ import type {
37
37
  ListAudienceSpecializationsParams,
38
38
  ListProjectModelsParams,
39
39
  ListProjectsParams,
40
+ ListProjectTokensParams,
40
41
  ListTrainingRunsParams,
41
42
  ListProjectTrainingsParams,
42
43
  Pipeline as GeneratedPipeline,
@@ -292,10 +293,17 @@ const createClientImplementation = (config: ClientConfig) => {
292
293
  }, params),
293
294
  createToken: ({ projectId, ...body }: { projectId: ProjectId } & CreateScopedTokenBody) =>
294
295
  wire.createProjectToken(projectId, body, requestOptions),
295
- listTokens: ({ projectId }: { projectId: ProjectId }) =>
296
- wire.listProjectTokens(projectId, requestOptions),
296
+ listTokens: ({ projectId, ...params }: { projectId: ProjectId } & ListProjectTokensParams) =>
297
+ wire.listProjectTokens(projectId, params, requestOptions),
298
+ listAllTokens: ({ projectId, ...params }: { projectId: ProjectId } & ListProjectTokensParams) =>
299
+ listAllPages(async (pageOptions) => {
300
+ const page = await wire.listProjectTokens(projectId, { ...params, ...pageOptions }, requestOptions);
301
+ return { items: page.tokens, pagination: page.pagination };
302
+ }, params),
297
303
  revokeToken: ({ projectId, tokenId }: { projectId: ProjectId; tokenId: string }) =>
298
304
  wire.revokeProjectToken(projectId, tokenId, requestOptions),
305
+ revokeAllTokens: ({ projectId }: { projectId: ProjectId }) =>
306
+ wire.revokeProjectTokens(projectId, requestOptions),
299
307
  revokeCurrentToken: () => wire.revokeCurrentToken(requestOptions),
300
308
  };
301
309