@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.
- package/README.md +1 -1
- package/dist/cli/toloka.js +119 -114
- package/dist/cli/toloka.js.jsc +0 -0
- package/dist/cli/toloka.js.jsc.sha256 +1 -1
- package/dist/cli/toloka.js.sha256 +1 -1
- package/docs/cli-v2.md +4 -0
- package/docs/cli.md +56 -5
- package/docs/getting-started.md +2 -2
- package/docs/limitations.md +1 -1
- package/openapi/gen/api.ts +22 -0
- package/openapi/gen/models/createDatasetBody.ts +2 -0
- package/openapi/gen/models/createDatasetBodyProfile.ts +2 -0
- package/openapi/gen/models/createDatasetUploadBodyFormat.ts +1 -1
- package/openapi/gen/models/dataset.ts +2 -0
- package/openapi/gen/models/datasetProfile.ts +3 -0
- package/openapi/gen/models/datasetProfileStamp.ts +6 -0
- package/openapi/gen/models/datasetProfileStampName.ts +2 -0
- package/openapi/gen/models/index.ts +5 -0
- package/openapi/gen/models/runCost.ts +7 -0
- package/package.json +2 -1
- package/skills/catalog.json +22 -0
- package/skills/{SKILL.md → toloka-build/SKILL.md} +1 -1
- package/skills/{references → toloka-build/references}/workflow-and-cli.md +14 -4
- package/skills/toloka-report-issue/SKILL.md +25 -0
- package/skills/toloka-report-issue/references/report-template.md +34 -0
- package/src/cli/analytics.ts +53 -1
- package/src/cli/file-system.ts +34 -0
- package/src/cli/format-error.ts +19 -0
- package/src/cli/init.ts +149 -194
- package/src/cli/program.ts +103 -21
- package/src/cli/report.ts +144 -0
- package/src/cli/skill.ts +363 -0
- package/src/pipeline-graph-v1.contract.json +5 -1
- /package/skills/{references → toloka-build/references}/node-semantics.md +0 -0
package/dist/cli/toloka.js.jsc
CHANGED
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
bbe06fffb8a659ebc2903d962ff2b4a225fe3abc691e607a01258350163c36c7 toloka.js.jsc
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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`
|
|
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
|
|
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-
|
|
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
|
|
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.
|
package/docs/getting-started.md
CHANGED
|
@@ -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
|
|
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
|
|
package/docs/limitations.md
CHANGED
|
@@ -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.
|
|
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
|
|
package/openapi/gen/api.ts
CHANGED
|
@@ -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,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
|
}
|
|
@@ -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';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toloka-platform/sdk",
|
|
3
|
-
"version": "0.1.0-preview.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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]`.
|
package/src/cli/analytics.ts
CHANGED
|
@@ -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;
|