@toloka-platform/sdk 0.1.0-preview.4 → 0.1.0-preview.5

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 (34) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/toloka.js +119 -114
  3. package/dist/cli/toloka.js.jsc +0 -0
  4. package/dist/cli/toloka.js.jsc.sha256 +1 -1
  5. package/dist/cli/toloka.js.sha256 +1 -1
  6. package/docs/cli-v2.md +4 -0
  7. package/docs/cli.md +56 -5
  8. package/docs/getting-started.md +2 -2
  9. package/docs/limitations.md +1 -1
  10. package/openapi/gen/api.ts +22 -0
  11. package/openapi/gen/models/createDatasetBody.ts +2 -0
  12. package/openapi/gen/models/createDatasetBodyProfile.ts +2 -0
  13. package/openapi/gen/models/createDatasetUploadBodyFormat.ts +1 -1
  14. package/openapi/gen/models/dataset.ts +2 -0
  15. package/openapi/gen/models/datasetProfile.ts +3 -0
  16. package/openapi/gen/models/datasetProfileStamp.ts +6 -0
  17. package/openapi/gen/models/datasetProfileStampName.ts +2 -0
  18. package/openapi/gen/models/index.ts +5 -0
  19. package/openapi/gen/models/runCost.ts +7 -0
  20. package/package.json +2 -1
  21. package/skills/catalog.json +22 -0
  22. package/skills/{SKILL.md → toloka-build/SKILL.md} +1 -1
  23. package/skills/{references → toloka-build/references}/workflow-and-cli.md +14 -4
  24. package/skills/toloka-report-issue/SKILL.md +25 -0
  25. package/skills/toloka-report-issue/references/report-template.md +34 -0
  26. package/src/cli/analytics.ts +53 -1
  27. package/src/cli/file-system.ts +34 -0
  28. package/src/cli/format-error.ts +19 -0
  29. package/src/cli/init.ts +149 -194
  30. package/src/cli/program.ts +103 -21
  31. package/src/cli/report.ts +144 -0
  32. package/src/cli/skill.ts +363 -0
  33. package/src/pipeline-graph-v1.contract.json +5 -1
  34. /package/skills/{references → toloka-build/references}/node-semantics.md +0 -0
Binary file
@@ -1 +1 @@
1
- dfdcb0c64d04df834c08b292facaf8edb31aba8a00876f29d6240cd08c9bf378 toloka.js.jsc
1
+ bbe06fffb8a659ebc2903d962ff2b4a225fe3abc691e607a01258350163c36c7 toloka.js.jsc
@@ -1 +1 @@
1
- 0e0efdf2d8a9bfacfacd3801a8cd89ceaa80534f262dbf4c9617fc7c22ef822c toloka.js
1
+ 43e152b2ae5342013785dd1c89843bead8b68039ea6576ae5a8bea5944263127 toloka.js
package/docs/cli-v2.md CHANGED
@@ -80,6 +80,7 @@ toloka project list # remote projects this key can see
80
80
  toloka project add cat-labeling pp.019f… # register + select
81
81
  toloka project switch cat-labeling
82
82
  toloka project current # alias of the project line in whoami
83
+ toloka project url # print the selected project's UI URL
83
84
  toloka project remove cat-labeling # local unbind only
84
85
  ```
85
86
 
@@ -95,6 +96,8 @@ toloka project create cat-labeling --team-id <teamId>
95
96
 
96
97
  `project create` writes the machine alias, sets `current`, and if cwd has no `toloka.json`, writes one.
97
98
 
99
+ UI links follow the resource-first shape `toloka <resource> url`. `project url` is available now; future pipeline, dataset, and other entity links belong under their existing resource groups. Every `url` command prints exactly one URL with no label to stdout. Opening a browser, if added, must be an explicit `--web` option rather than the default.
100
+
98
101
  ### init
99
102
 
100
103
  `init` sets up **this directory** for an agent. A selected platform project is optional.
@@ -118,6 +121,7 @@ Resource commands never search the disk for a pipeline first. They load the proj
118
121
 
119
122
  | Command | Scope | Pipeline required? |
120
123
  | ----------------------------- | ----------------------------- | ------------------ |
124
+ | `project url` | project UI URL | no |
121
125
  | `plan` / `apply` / `validate` | whole project | no |
122
126
  | `secret set` | project | no |
123
127
  | `dataset list` | project | no |
package/docs/cli.md CHANGED
@@ -33,7 +33,7 @@ Credentials and the platform base URL resolve from the same precedence order, hi
33
33
 
34
34
  `toloka login` verifies the key against the platform before saving anything. It writes `$XDG_CONFIG_HOME/toloka/credentials.json`, which defaults to `~/.config/toloka/credentials.json`, with file mode `0600` and a parent directory with mode `0700`. The file may also store local project aliases. The legacy `~/.toloka/credentials.json` is still read when the new path has no file. `toloka logout` deletes the stored file but does not revoke the key.
35
35
 
36
- Anonymous usage events (`sdk_cli_command_completed` / `sdk_cli_command_failed`) go to Toloka's PostHog project so we can see which commands run and which error classes they hit. Event payloads contain only an allowlisted command classifier, duration, exit code, outcome or error code, SDK and Bun versions, actor, and channel. Raw arguments, flag values, environment variables, API keys, secret names, base URLs and hosts, local paths, project ids, error messages, stack traces, and source context are not sent. GeoIP enrichment is disabled. Distinct id starts as a random UUID stored next to the credentials file. After a successful authenticated command, the CLI calls `GET /me` and aliases that UUID onto the platform user id without setting person properties. Set `TOLOKA_TELEMETRY=0` or `DO_NOT_TRACK=1` to turn this off. CI is off unless you set `TOLOKA_TELEMETRY=1`.
36
+ Ordinary usage events (`sdk_cli_command_completed` / `sdk_cli_command_failed`) go to Toloka's PostHog project so we can see which commands run and which error classes they hit. Their payloads contain only an allowlisted command classifier, duration, exit code, outcome or error code, SDK and Bun versions, actor, and channel. Raw arguments, flag values, environment variables, API keys, secret names, base URLs and hosts, local paths, project ids, error messages, stack traces, and source context are not sent. GeoIP enrichment is disabled. Distinct id starts as a random UUID stored next to the credentials file. After a successful authenticated command, the CLI calls `GET /me` and aliases that UUID onto the platform user id without setting person properties. Set `TOLOKA_TELEMETRY=0` or `DO_NOT_TRACK=1` to disable capture. CI environments are disabled unless `TOLOKA_TELEMETRY=1`. The explicitly approved full-text `report` event is documented in [report](#report).
37
37
 
38
38
  The root program accepts these flags before any command:
39
39
 
@@ -44,7 +44,21 @@ The root program accepts these flags before any command:
44
44
  | `--base-url <url>` | Platform base URL for this command only |
45
45
  | `--project-id <id>` | Target project; overrides env, checkout, and the registry |
46
46
 
47
- Commands resolve the project root by walking up from the working directory until they find a `toloka.json` file. The CLI reports that directory on stderr when it differs from the working directory. Passing `--source-root` disables discovery. With no marker found, the working directory is used. `init` does not walk up: it binds the working directory or `--source-root` only. The authentication commands `login`, `logout`, and `auth-status` do not need a project root.
47
+ Commands resolve the project root by walking up from the working directory until they find a `toloka.json` file. The CLI reports that directory on stderr when it differs from the working directory. Passing `--source-root` disables discovery. With no marker found, the working directory is used. `init` and `report` do not walk up: they use the working directory or `--source-root` only. The authentication commands `login`, `logout`, and `auth-status` do not need a project root.
48
+
49
+ ## Resources and Base Actions
50
+
51
+ The CLI is resource-first: `toloka <resource> <action>`. A Base Action has one meaning wherever a resource implements it. A resource exposes only the Base Actions that have real behavior; there are no placeholder actions.
52
+
53
+ | Base Action | Meaning |
54
+ | ----------- | ----------------------------------------------------------------------------------------- |
55
+ | `list` | Read a bounded, paginated collection of one Resource type. |
56
+ | `get` | Read exactly one Resource selected by a stable identifier. |
57
+ | `create` | Create exactly one Resource and return its stable identifier and representation. |
58
+ | `delete` | Remove exactly one Resource selected by a stable identifier and return no representation. |
59
+ | `url` | Read exactly one browser-ready URL with no surrounding prose. |
60
+
61
+ Resources may also expose specialized actions beyond the Base Actions, such as `pipeline cost`, `skill search`, and `skill install`.
48
62
 
49
63
  ## project
50
64
 
@@ -55,12 +69,15 @@ toloka project list
55
69
  toloka project add [alias] [projectId]
56
70
  toloka project switch <alias>
57
71
  toloka project current
72
+ toloka project url
58
73
  toloka project remove <alias>
59
74
  toloka project create [alias] [--name <name>] [--team-id <id>]
60
75
  ```
61
76
 
62
77
  `add`, `switch`, `remove`, and `create` write the machine registry in the credentials file. They refuse `--api-key` / `--base-url` / `POTATO_*` when those would select a different key or platform than the stored file. `create` reuses the only visible team when every listed project shares one; otherwise pass `--team-id`.
63
78
 
79
+ `url` fetches the selected project to resolve its team and prints only its platform UI URL to stdout, making the output safe to capture in scripts and agent workflows.
80
+
64
81
  ## login
65
82
 
66
83
  Stores an API key for this machine after verifying it.
@@ -93,15 +110,17 @@ On success it prints the platform URL with its source, the API key masked unless
93
110
 
94
111
  ## init
95
112
 
96
- Initializes the current project directory and installs agent entry points.
113
+ Initializes the current project directory and installs the Agent Bootstrap entry points.
97
114
 
98
115
  ```sh
99
116
  toloka init
100
117
  ```
101
118
 
102
- `init` does not require a selected platform project. It always writes `.claude/skills/toloka-build/SKILL.md`, `.cursor/rules/toloka-build.mdc` when Cursor configuration exists, and an SDK-owned block in `AGENTS.md`. When a project is already selected through `--project-id`, `TOLOKA_PROJECT_ID` / `POTATO_PROJECT_ID`, `toloka.json`, or the machine registry, it also writes `toloka.json` when missing. It does not walk up to a parent checkout.
119
+ `init` does not require a selected platform project. It always maintains one `<toloka>` … `</toloka>` Agent Bootstrap block in `AGENTS.md` and writes minimal pointers to it: `.claude/skills/toloka-bootstrap/SKILL.md` when `.claude/` exists (or when no agent configuration exists at all) and `.cursor/rules/toloka-bootstrap.mdc` with `alwaysApply: true` when `.cursor/rules/` exists. The bootstrap tells an agent to run `toloka --help`, search the bundled Skill Catalog with `toloka skill search`, install a matching skill with `toloka skill install`, and read `.agents/skills/<skill-id>/SKILL.md`; it does not embed the build workflow. Bytes outside the block are preserved, and re-running `init` refreshes the block and both pointers in place without adding duplicates. When a project is already selected through `--project-id`, `TOLOKA_PROJECT_ID` / `POTATO_PROJECT_ID`, `toloka.json`, or the machine registry, it also writes `toloka.json` when missing. It does not walk up to a parent checkout.
120
+
121
+ `init` removes only Toloka-generated legacy entry points that still carry the `<!-- toloka:sdk-version … -->` marker: the full `toloka-build` and `toloka-pipeline-as-code` Claude skills and Cursor rules, plus the `<!-- toloka:begin -->` … `<!-- toloka:end -->` block in `AGENTS.md`, which is replaced by the `<toloka>` block in place. Files without that marker, other skills and rules, and installed skills under `.agents/skills/` are left untouched. An `AGENTS.md` whose current or legacy block is unterminated, reversed, or duplicated is refused with the file's full path before anything, including `toloka.json`, is written.
103
122
 
104
- On success it prints `Initialized agent entry points for @toloka-platform/sdk <version> in <root>:` followed by the file list, or `Agent entry points are up to date` when nothing changed. It warns on stderr when the SDK is not listed in the project dependencies. Every other `toloka` command compares the recorded skill digest with the installed SDK and warns on stderr when the generated files are stale; that warning never blocks the command.
123
+ On success it prints `Initialized agent entry points for @toloka-platform/sdk <version> in <root>:` followed by the file list and one `removed <path>` line per legacy entry point, or `Agent entry points are up to date` when nothing changed. It warns on stderr when the SDK is not listed in the project dependencies. Every other project command warns on stderr when a generated legacy entry point is still present or the recorded bootstrap version differs from the installed SDK; that warning never blocks the command. `support` commands skip the check because they never read the checkout.
105
124
 
106
125
  ## import
107
126
 
@@ -202,6 +221,38 @@ toloka dataset upload <name> <file>
202
221
 
203
222
  `dataset upload` appends JSONL rows. Field schemas are immutable after the first upload: you can add columns, never alter or remove one. See [datasets](./datasets.md).
204
223
 
224
+ ## report
225
+
226
+ Preview and submit one Markdown issue report through the CLI's existing PostHog telemetry client. The command is project-independent: it does not read `toloka.json`, walk up to find a project root, require credentials, or call the Toloka API.
227
+
228
+ ```sh
229
+ toloka report <markdownPath> [--authored-by human|agent] [--confirm]
230
+ ```
231
+
232
+ The report path must name a non-empty regular UTF-8 file no larger than 256 KiB. The CLI refuses symbolic-link files and paths that traverse a symbolic-link directory under the selected source root. It prints the complete report, declared authorship, and platform origin before submission. Control and bidirectional formatting characters are escaped in the preview but preserved in the submitted report text.
233
+
234
+ In a terminal the command asks `Send this report to Toloka? [y/N]`; outside a terminal it refuses unless `--confirm` is passed. `--authored-by` defaults to `human`. Add `--confirm` only after reviewing the exact preview.
235
+
236
+ One `sdk_cli_issue_report_submitted` event carries `report_id`, the complete `report_text`, its UTF-8 `report_length_bytes`, `authored_by`, and `platform`, plus the standard pseudonymous CLI telemetry context. The command never reads or sends an API key. It flushes PostHog before printing `Submitted issue report: <id>`; a delivery failure exits non-zero and prints no success ID. When CLI telemetry is disabled, issue reporting is unavailable rather than bypassing that preference.
237
+
238
+ ## skill
239
+
240
+ Discover bundled agent skills and install them into the project. The Skill Catalog ships inside the SDK package, so these actions are local and deterministic: they need no credentials, make no network requests, and change with the package version only.
241
+
242
+ ```sh
243
+ toloka skill list [--json]
244
+ toloka skill search <query> [--json]
245
+ toloka skill install <skillId> [--force]
246
+ ```
247
+
248
+ `list` prints every skill in the catalog with its installation status: `not-installed` when `.agents/skills/<skillId>` is absent, `current` when the installed files match the catalog digest, and `stale` when they differ. Each skill line (`id`, status, name) is followed by one indented description line. `--json` prints the Skill Descriptors (`id`, `name`, `description`, `tags`, `version`, `digest`, `files`) plus `status` and never includes file contents.
249
+
250
+ `search` matches `<query>` case-insensitively against each skill's id, name, description, and tags and prints the matches in the same format. When nothing matches it says so (or prints `[]` with `--json`), exits 0, and installs nothing.
251
+
252
+ `install` copies the complete skill — its `SKILL.md` entry point and every reference — from the package into `.agents/skills/<skillId>/` under the project root and prints the destination. Every path is confined to that directory and the command refuses to write through symbolic links. An existing `.agents/skills/<skillId>` is refused unless `--force` is passed. With `--force` the new copy is written to a temporary sibling directory and verified against the catalog digest, the existing directory is renamed to a backup, the verified copy is moved into place, and the backup is removed; a failed swap restores the backup, so the directory never holds a mixed version. A malformed catalog, an unsafe path, or a digest mismatch fails before any existing file changes.
253
+
254
+ After an SDK upgrade `list` reports installed skills whose catalog digest changed as `stale` until they are refreshed with `install --force`. Local edits to an installed skill also make it `stale`; `list` and `search` never modify local files.
255
+
205
256
  ## Exit codes
206
257
 
207
258
  `toloka pipeline run --wait` maps the run outcome to the process exit code.
@@ -44,7 +44,7 @@ CI does not need `login`. Set `POTATO_API_KEY` and the stored file is ignored. S
44
44
 
45
45
  ## Start with an agent
46
46
 
47
- Initialize the current directory and install the bundled agent skills. No platform project needs to be selected yet.
47
+ Initialize the current directory and install the Agent Bootstrap. No platform project needs to be selected yet.
48
48
 
49
49
  ```sh
50
50
  toloka init
@@ -54,7 +54,7 @@ Open your coding agent in this directory and describe the project you want, for
54
54
 
55
55
  > Create a Toloka project that collects captions for images. Show me the plan before applying it.
56
56
 
57
- The skill guides the agent through creating and selecting the platform project, authoring the TypeScript source, validating it, showing the plan, and applying the approved changes. `toloka.json` is created when the project is selected.
57
+ The bootstrap directs the agent to `toloka --help` and to search and install the matching bundled skill; the `toloka-build` skill then guides the agent through creating and selecting the platform project, authoring the TypeScript source, validating it, showing the plan, and applying the approved changes. `toloka.json` is created when the project is selected.
58
58
 
59
59
  ## Manual project setup
60
60
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  What this Preview SDK does not do yet, stated plainly so you can decide what to depend on.
4
4
 
5
- `@toloka-platform/sdk` is `0.1.0-preview.4`. This is a Preview: the authoring API, the CLI surface, and the generated source layout can change without a major version bump. Pin an exact version. Do not depend on this in production yet.
5
+ `@toloka-platform/sdk` is `0.1.0-preview.5`. This is a Preview: the authoring API, the CLI surface, and the generated source layout can change without a major version bump. Pin an exact version. Do not depend on this in production yet.
6
6
 
7
7
  ## The SDK does not certify deployability
8
8
 
@@ -54,6 +54,7 @@ import type {
54
54
  ProjectSecret,
55
55
  ProjectSecretName,
56
56
  ReplacePipelineGraphBody,
57
+ RunCost,
57
58
  RunId,
58
59
  RunItem,
59
60
  RunItemId,
@@ -707,6 +708,27 @@ export const getPipelineRun = async (runId: RunId, options?: RequestInit): Promi
707
708
 
708
709
 
709
710
 
711
+ export const getGetPipelineRunCostUrl = (runId: RunId,) => {
712
+
713
+
714
+
715
+
716
+ return `/api/v2-beta/runs/${runId}/cost`
717
+ }
718
+
719
+ export const getPipelineRunCost = async (runId: RunId, options?: RequestInit): Promise<RunCost> => {
720
+
721
+ return potatoFetch<RunCost>(getGetPipelineRunCostUrl(runId),
722
+ {
723
+ ...options,
724
+ method: 'GET'
725
+
726
+
727
+ }
728
+ );}
729
+
730
+
731
+
710
732
  export const getCancelPipelineRunUrl = (runId: RunId,) => {
711
733
 
712
734
 
@@ -1,4 +1,6 @@
1
+ import type { CreateDatasetBodyProfile } from './createDatasetBodyProfile';
1
2
 
2
3
  export type CreateDatasetBody = {
3
4
  name?: string;
5
+ profile?: CreateDatasetBodyProfile;
4
6
  };
@@ -0,0 +1,2 @@
1
+
2
+ export type CreateDatasetBodyProfile = 'chat-sft' | 'instruction';
@@ -1,2 +1,2 @@
1
1
 
2
- export type CreateDatasetUploadBodyFormat = 'json' | 'csv';
2
+ export type CreateDatasetUploadBodyFormat = 'json' | 'csv' | 'jsonl';
@@ -1,10 +1,12 @@
1
1
  import type { DatasetId } from './datasetId';
2
2
  import type { ProjectId } from './projectId';
3
+ import type { DatasetProfile } from './datasetProfile';
3
4
 
4
5
  export interface Dataset {
5
6
  id: DatasetId;
6
7
  projectId: ProjectId;
7
8
  name: string;
8
9
  hidden: boolean;
10
+ profile: DatasetProfile;
9
11
  createdAt: string;
10
12
  }
@@ -0,0 +1,3 @@
1
+ import type { DatasetProfileStamp } from './datasetProfileStamp';
2
+
3
+ export type DatasetProfile = DatasetProfileStamp | null;
@@ -0,0 +1,6 @@
1
+ import type { DatasetProfileStampName } from './datasetProfileStampName';
2
+
3
+ export interface DatasetProfileStamp {
4
+ name: DatasetProfileStampName;
5
+ version: number;
6
+ }
@@ -0,0 +1,2 @@
1
+
2
+ export type DatasetProfileStampName = 'chat-sft' | 'instruction';
@@ -68,6 +68,7 @@ export * from './codeNodeSettingsFieldProxiesInputItem';
68
68
  export * from './codeNodeSettingsFieldProxiesOutputItem';
69
69
  export * from './copyPipelineBody';
70
70
  export * from './createDatasetBody';
71
+ export * from './createDatasetBodyProfile';
71
72
  export * from './createDatasetExportBody';
72
73
  export * from './createDatasetField200';
73
74
  export * from './createDatasetFieldBody';
@@ -111,6 +112,9 @@ export * from './datasetItem';
111
112
  export * from './datasetItemCurrentSubmissionId';
112
113
  export * from './datasetItemDuplicateOfSubmissionId';
113
114
  export * from './datasetItemId';
115
+ export * from './datasetProfile';
116
+ export * from './datasetProfileStamp';
117
+ export * from './datasetProfileStampName';
114
118
  export * from './estimatePipelineCostBody';
115
119
  export * from './estimatePipelineCostBodyItemFilter';
116
120
  export * from './estimatePipelineCostBodyItemFilterFieldSourcesItem';
@@ -691,6 +695,7 @@ export * from './rootNodeSettingsItemFilterFieldValuesItemSourcesItemOneOfTwo';
691
695
  export * from './rootNodeSettingsItemFilterFieldValuesItemValue';
692
696
  export * from './rootNodeSettingsStartedFieldProxies';
693
697
  export * from './rootNodeSettingsStartedFieldProxiesOutputItem';
698
+ export * from './runCost';
694
699
  export * from './runId';
695
700
  export * from './runItem';
696
701
  export * from './runItemId';
@@ -0,0 +1,7 @@
1
+ import type { RunId } from './runId';
2
+
3
+ export interface RunCost {
4
+ runId: RunId;
5
+ computedAt: string;
6
+ total: string;
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toloka-platform/sdk",
3
- "version": "0.1.0-preview.4",
3
+ "version": "0.1.0-preview.5",
4
4
  "private": false,
5
5
  "description": "Preview. Build, inspect, and operate Toloka pipeline projects as TypeScript source. The public API may change.",
6
6
  "license": "Apache-2.0",
@@ -32,6 +32,7 @@
32
32
  "build": "bun ./scripts/build-cli.ts ./dist/cli",
33
33
  "generate": "orval --config ./openapi/orval.config.js",
34
34
  "prepack": "bun run build",
35
+ "sync-skill-catalog": "bun ./scripts/sync-skill-catalog.ts",
35
36
  "test": "vitest run",
36
37
  "typecheck": "tsc --noEmit"
37
38
  },
@@ -0,0 +1,22 @@
1
+ {
2
+ "skills": [
3
+ {
4
+ "id": "toloka-build",
5
+ "name": "Build Toloka pipelines as code",
6
+ "description": "Build, inspect, and change Toloka platform pipeline projects as TypeScript source with @toloka-platform/sdk and toloka. Use when the user wants to create, adopt, inspect, plan, or apply a pipeline project as code.",
7
+ "tags": ["pipelines", "authoring", "sdk"],
8
+ "version": "0.1.0-preview.5",
9
+ "digest": "135d0b6ff6aa7bf26782bc26e6adbe7ee70c9db1565722ee356618211543d0bc",
10
+ "files": ["SKILL.md", "references/node-semantics.md", "references/workflow-and-cli.md"]
11
+ },
12
+ {
13
+ "id": "toloka-report-issue",
14
+ "name": "Report a Toloka problem",
15
+ "description": "Report a problem with the Toloka platform, CLI, or SDK as a redacted Markdown issue report sent through the toloka CLI only after explicit approval. Use when the user hits unexpected behavior, an error, or a bug and wants Toloka engineers to investigate.",
16
+ "tags": ["support", "issue", "bug", "report"],
17
+ "version": "0.1.0-preview.5",
18
+ "digest": "9a673337ad1cbbcec7c2fadb2d49d38e923c797d049818fdaa15ff30ffd153f3",
19
+ "files": ["SKILL.md", "references/report-template.md"]
20
+ }
21
+ ]
22
+ }
@@ -46,7 +46,7 @@ Import authoring helpers from `@toloka-platform/sdk`.
46
46
 
47
47
  Let constructors mint IDs for new declarations. Preserve `id` options generated by `toloka import`, but never invent or hand-edit raw `fp_…`, `ds.…`, `pl.…`, or `pp.…` values in authored settings. Never add a `layout` block: layout is not authored, existing layout is preserved, and the server supplies defaults.
48
48
 
49
- Read [node semantics](references/node-semantics.md) before selecting or configuring a node. Use the published [face image collection example](../examples/face-image-collection/) as a concrete authoring pattern.
49
+ Read [node semantics](references/node-semantics.md) before selecting or configuring a node. Use `node_modules/@toloka-platform/sdk/examples/face-image-collection/` as a concrete authoring pattern.
50
50
 
51
51
  ## Get human-work settings right the first time
52
52
 
@@ -33,9 +33,9 @@ bun add --dev @toloka-platform/sdk
33
33
  toloka init
34
34
  ```
35
35
 
36
- `init` does not require a selected project. It checks that `@toloka-platform/sdk` is declared in `dependencies` or `devDependencies`, then writes a Claude skill for `.claude/`, a Cursor rule when `.cursor/rules/` exists, and a marked block in an existing `AGENTS.md`; with no agent configuration, it creates the Claude skill and `AGENTS.md`. If a project is already selected through `--project-id`, `TOLOKA_PROJECT_ID` / `POTATO_PROJECT_ID`, `toloka.json`, or the machine registry, it also writes `toloka.json` when missing.
36
+ `init` does not require a selected project. It checks that `@toloka-platform/sdk` is declared in `dependencies` or `devDependencies`, then maintains one `<toloka>` Agent Bootstrap block in `AGENTS.md` and writes minimal pointers to it: a Claude skill at `.claude/skills/toloka-bootstrap/SKILL.md` when `.claude/` exists (or when no agent configuration exists at all) and an always-applied Cursor rule at `.cursor/rules/toloka-bootstrap.mdc` when `.cursor/rules/` exists. If a project is already selected through `--project-id`, `TOLOKA_PROJECT_ID` / `POTATO_PROJECT_ID`, `toloka.json`, or the machine registry, it also writes `toloka.json` when missing.
37
37
 
38
- The generated entry points contain the core read, edit, validate, plan, and apply loop and point back to the fuller references in this package. Every `toloka` command except `init` compares the recorded skill-content digest with the installed SDK and warns on stderr when they differ. The warning never blocks the command; re-run `toloka init` to refresh the pointers.
38
+ The bootstrap is small: it tells an agent to run `toloka --help`, search the bundled Skill Catalog with `toloka skill search <query>`, install the match with `toloka skill install <skill-id>`, and read `.agents/skills/<skill-id>/SKILL.md`. This skill is that installed copy. Commands warn on stderr when a generated legacy entry point is still present or the recorded bootstrap version differs from the installed SDK. Help, `init`, `report`, `project url`, and version invocations skip this checkout-dependent warning. The warning never blocks a command; re-run `toloka init` to refresh the bootstrap and its pointers.
39
39
 
40
40
  ## Store credentials once
41
41
 
@@ -71,13 +71,16 @@ require `toloka login` first because they read and write the credentials file. W
71
71
  project ID in this order: `--project-id`, `TOLOKA_PROJECT_ID`, `POTATO_PROJECT_ID`, `toloka.json`,
72
72
  then the machine registry `current`.
73
73
 
74
- Anonymous command telemetry is on by default (`sdk_cli_command_completed` / `sdk_cli_command_failed`). Set `TOLOKA_TELEMETRY=0` or `DO_NOT_TRACK=1` to disable it. CI is off unless `TOLOKA_TELEMETRY=1`.
74
+ Anonymous command telemetry is on by default (`sdk_cli_command_completed` / `sdk_cli_command_failed`). `toloka report` uses the same PostHog client to send explicitly approved Markdown in `sdk_cli_issue_report_submitted`. Set `TOLOKA_TELEMETRY=0` or `DO_NOT_TRACK=1` to disable both; CI is off unless `TOLOKA_TELEMETRY=1`.
75
75
 
76
76
  All commands accept `--source-root <directory>`. Prefer running from the source root so paths and diffs stay obvious. `init` does not walk up: it binds the working directory or `--source-root` only.
77
77
 
78
78
  The real command surface is:
79
79
 
80
80
  ```text
81
+ toloka version
82
+ toloka -v
83
+ toloka --version
81
84
  toloka login
82
85
  toloka logout
83
86
  toloka auth-status
@@ -85,6 +88,7 @@ toloka project list
85
88
  toloka project add [alias] [projectId]
86
89
  toloka project switch <alias>
87
90
  toloka project current
91
+ toloka project url
88
92
  toloka project remove <alias>
89
93
  toloka project create [alias] [--name <name>] [--team-id <id>]
90
94
  toloka init
@@ -105,10 +109,16 @@ toloka pipeline runs [name] [--limit <n>]
105
109
  toloka pipeline cost [name] [--item-limit <n>]
106
110
  toloka pipeline results <runId> [--limit <n>] [--failed]
107
111
  toloka pipeline cancel <runId>
112
+ toloka skill list [--json]
113
+ toloka skill search <query> [--json]
114
+ toloka skill install <skill-id> [--force]
115
+ toloka report <markdown> [--authored-by human|agent] [--confirm]
108
116
  ```
109
117
 
110
118
  Select the platform project with `toloka project add` or `toloka project create` before `import`, `plan`, or `apply`. `init` may run first, and `import` uses the selected project when the id is omitted.
111
119
 
120
+ `toloka project url` prints only the selected project's platform UI URL. Use it when the user needs a working link to inspect the live project.
121
+
112
122
  `toloka pipeline cost [name] [--item-limit <n>]` forecasts what a run of a live pipeline would bill. It does not start a run and does not change the graph. Name the live pipeline or id; a TTY may pick among several. The typed client equivalent is `client.pipelines.estimateCost({ pipelineId, itemLimit? })`.
113
123
 
114
124
  ## Adopt an existing live project
@@ -254,4 +264,4 @@ Read the returned path and reason. Check connection endpoints, duplicate or unkn
254
264
 
255
265
  ## Use the shipped example
256
266
 
257
- Read [the face image collection pipeline](../../examples/face-image-collection/pipeline.ts), its `fields.ts`, and its `nodes/` modules for a real composition of `field`, `root`, `generation`, `code`, `connect`, and `definePipeline`. Copy its source organization, not its task-specific settings.
267
+ Read `node_modules/@toloka-platform/sdk/examples/face-image-collection/pipeline.ts`, its `fields.ts`, and its `nodes/` modules for a real composition of `field`, `root`, `generation`, `code`, `connect`, and `definePipeline`. Copy its source organization, not its task-specific settings.
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: toloka-report-issue
3
+ description: Report a problem with the Toloka platform, CLI, or SDK as a redacted Markdown issue report sent through the toloka CLI only after explicit approval. Use when the user hits unexpected behavior, an error, or a bug and wants Toloka engineers to investigate.
4
+ ---
5
+
6
+ # Report a Toloka problem
7
+
8
+ Use this skill when Toloka platform, CLI, or SDK behavior blocks the user's work and they want Toloka engineers to investigate. The result is one Markdown issue report sent through the `toloka` CLI. Nothing leaves the machine until the user has reviewed the complete report and approved it.
9
+
10
+ ## Workflow
11
+
12
+ 1. Collect verified facts: what the user ran, what they expected, what happened, and any relevant project, pipeline, dataset, run, thread, or request IDs. Ask for missing reproduction steps or reproduce the failure with real commands. Never invent a timeline, command output, or identifier.
13
+ 2. Copy [the template](references/report-template.md), preserve its section order, and replace the example with the user's evidence. Write `None` for sections that do not apply. The final UTF-8 Markdown file must not exceed 256 KiB.
14
+ 3. Redact before previewing. Include only evidence the user selected. Replace every API key, token, password, cookie, connection string, or personal value with a marker such as `[REDACTED:api-key]`, and list each replacement under Redactions without the original value. Never read environment variables, credential files, shell history, or logs the user did not name.
15
+ 4. Show the user the exact complete Markdown file and ask whether to send it. If they decline or request changes, do not submit; revise the file and ask again.
16
+ 5. Only after approval, run `toloka report <report.md> --authored-by agent --confirm`. The command previews the same Markdown, submits it as one PostHog event, flushes delivery, and prints `Submitted issue report: <id>` only after PostHog accepts the flush.
17
+ 6. Return the printed report ID to the user. If submission fails, keep the Markdown file, report the exact error, and do not claim success or retry without approval.
18
+
19
+ ## Boundaries
20
+
21
+ - Submit only the Markdown file. The command has no attachment or structured-reference flags; put relevant IDs and text evidence in the report itself.
22
+ - The event contains the complete Markdown, report ID, UTF-8 byte length, declared authorship, platform origin, and the standard pseudonymous CLI telemetry context. It never reads or sends the API key.
23
+ - `--authored-by agent` records who prepared the report. It does not authenticate or grant access.
24
+ - Issue reporting is unavailable when CLI telemetry is disabled. Do not bypass that setting.
25
+ - Use the CLI, not the SDK or raw PostHog API. The user-visible preview and explicit approval are the consent boundary.
@@ -0,0 +1,34 @@
1
+ # Issue Report: `toloka apply` returns HTTP 500 for the cat labeling project
2
+
3
+ ## Summary
4
+
5
+ `toloka apply` fails with HTTP 500 after `toloka validate` passed, so the edited pipeline never reaches the platform.
6
+
7
+ ## Steps to reproduce
8
+
9
+ 1. Change the labeler instruction in `pipelines/cat-labeling/nodes/annotate-cats/node.ts`.
10
+ 2. Run `toloka validate`; it reports no issues.
11
+ 3. Run `toloka apply`.
12
+
13
+ ## Expected behavior
14
+
15
+ `toloka apply` writes the new graph version and prints the changed node.
16
+
17
+ ## Actual behavior
18
+
19
+ The CLI exits 1 with `Potato API request failed with status 500`. The same command failed three times between 09:12 and 09:20 UTC; `toloka plan` still shows the pending change.
20
+
21
+ ## Relevant IDs
22
+
23
+ - Project: pp.0192f3a4-5b6c-7d8e-9f01-23456789abcd
24
+ - Pipeline: pl.0192f3a4-5b6c-7d8e-9f01-23456789abce
25
+ - Request: None supplied
26
+
27
+ ## Environment
28
+
29
+ - toloka CLI 0.1.0-preview.5 (`toloka --version`), Bun 1.4.0, macOS 15
30
+ - Platform: https://platform.toloka.ai
31
+
32
+ ## Redactions
33
+
34
+ - The API key in the user-selected command output was replaced with `[REDACTED:api-key]`.
@@ -1,3 +1,4 @@
1
+ import { assert } from "es-toolkit";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import { chmod, readFile, writeFile } from "node:fs/promises";
3
4
  import { dirname, join } from "node:path";
@@ -28,13 +29,22 @@ export type CliAnalyticsCapture = {
28
29
  readonly error?: unknown;
29
30
  };
30
31
 
32
+ export type IssueReportSubmission = {
33
+ readonly reportId: string;
34
+ readonly reportText: string;
35
+ readonly authoredBy: "human" | "agent";
36
+ readonly platform: string;
37
+ };
38
+
31
39
  export type CliAnalytics = {
32
40
  readonly shouldIdentify: boolean;
41
+ readonly issueReportingEnabled: boolean;
33
42
  readonly identifyCurrentUser: (user: {
34
43
  readonly id: string;
35
44
  readonly email: string | null;
36
45
  }) => void;
37
46
  readonly captureCommand: (event: CliAnalyticsCapture) => void;
47
+ readonly submitIssueReport: (report: IssueReportSubmission) => Promise<void>;
38
48
  readonly shutdown: () => Promise<void>;
39
49
  };
40
50
 
@@ -46,6 +56,8 @@ export type PosthogLike = {
46
56
  disableGeoip: boolean;
47
57
  }) => void;
48
58
  alias: (event: { distinctId: string; alias: string }) => void;
59
+ flush: () => Promise<void>;
60
+ on?: (event: "error", listener: (error: Error) => void) => void;
49
61
  shutdown: (shutdownTimeoutMs?: number) => Promise<void>;
50
62
  };
51
63
 
@@ -86,6 +98,7 @@ const COMMAND_GROUPS: Readonly<Record<string, Readonly<Record<string, true>>>> =
86
98
  },
87
99
  dataset: { list: true, fields: true, load: true, upload: true },
88
100
  secret: { set: true },
101
+ skill: { list: true, search: true, install: true },
89
102
  };
90
103
 
91
104
  const ROOT_COMMANDS: Readonly<Record<string, true>> = {
@@ -99,6 +112,8 @@ const ROOT_COMMANDS: Readonly<Record<string, true>> = {
99
112
  plan: true,
100
113
  status: true,
101
114
  validate: true,
115
+ report: true,
116
+ version: true,
102
117
  whoami: true,
103
118
  };
104
119
 
@@ -116,6 +131,7 @@ const nameFromTokens = (tokens: readonly string[]): string => {
116
131
  };
117
132
 
118
133
  export function commandNameFromArgv(argv: readonly string[]): string {
134
+ if (argv.includes("-v") || argv.includes("--version")) return "version";
119
135
  const tokens: string[] = [];
120
136
  for (let index = 0; index < argv.length; index += 1) {
121
137
  const token = argv[index];
@@ -161,8 +177,12 @@ const readAnonymousId = async (environment: CliEnvironment): Promise<string> =>
161
177
 
162
178
  const noopAnalytics = (): CliAnalytics => ({
163
179
  shouldIdentify: false,
180
+ issueReportingEnabled: false,
164
181
  identifyCurrentUser() {},
165
182
  captureCommand() {},
183
+ async submitIssueReport() {
184
+ assert(false, "Issue reporting is disabled. Re-run with TOLOKA_TELEMETRY=1.");
185
+ },
166
186
  async shutdown() {},
167
187
  });
168
188
 
@@ -177,6 +197,11 @@ export function createCliAnalytics(options: {
177
197
  let client = options.client;
178
198
  let distinctId = options.distinctId;
179
199
  let identifiedUserId: string | undefined;
200
+ const deliveryErrors: Error[] = [];
201
+ const captureDeliveryError = (error: Error) => {
202
+ deliveryErrors.push(error);
203
+ };
204
+ client?.on?.("error", captureDeliveryError);
180
205
 
181
206
  const ensure = async () => {
182
207
  if (client !== undefined && distinctId !== undefined) return;
@@ -186,7 +211,7 @@ export function createCliAnalytics(options: {
186
211
  flushAt: 1,
187
212
  flushInterval: 0,
188
213
  });
189
- created.on("error", () => {});
214
+ created.on("error", captureDeliveryError);
190
215
  client = created;
191
216
  }
192
217
  distinctId ??= await readAnonymousId(environment);
@@ -202,6 +227,7 @@ export function createCliAnalytics(options: {
202
227
  let queue: Promise<void> = ensure().catch(() => {});
203
228
 
204
229
  return {
230
+ issueReportingEnabled: true,
205
231
  shouldIdentify: true,
206
232
  identifyCurrentUser(user) {
207
233
  queue = queue
@@ -252,6 +278,32 @@ export function createCliAnalytics(options: {
252
278
  })
253
279
  .catch(() => {});
254
280
  },
281
+ submitIssueReport(report) {
282
+ const submission = queue.then(async () => {
283
+ assert(client && distinctId, "PostHog issue reporting could not be initialized.");
284
+ deliveryErrors.length = 0;
285
+ client.capture({
286
+ distinctId,
287
+ event: "sdk_cli_issue_report_submitted",
288
+ disableGeoip: true,
289
+ properties: {
290
+ ...sharedProperties(),
291
+ report_id: report.reportId,
292
+ report_text: report.reportText,
293
+ report_length_bytes: new TextEncoder().encode(report.reportText).length,
294
+ authored_by: report.authoredBy,
295
+ platform: report.platform,
296
+ $process_person_profile: false,
297
+ },
298
+ });
299
+ await client.flush();
300
+ const reportError = deliveryErrors[0];
301
+ deliveryErrors.length = 0;
302
+ if (reportError !== undefined) throw reportError;
303
+ });
304
+ queue = submission.catch(() => {});
305
+ return submission;
306
+ },
255
307
  async shutdown() {
256
308
  try {
257
309
  await queue;