@toloka-platform/sdk 0.2.0-preview.3 → 0.2.0
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 +5 -6
- package/dist/cli/toloka.js +136 -136
- 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 +3 -2
- package/docs/cli.md +35 -7
- package/docs/getting-started.md +4 -2
- package/docs/limitations.md +2 -2
- package/openapi/gen/models/baseModel.ts +1 -0
- package/openapi/gen/models/currentUser.ts +2 -0
- package/openapi/gen/models/currentUserTeamsItem.ts +6 -0
- package/openapi/gen/models/gistingTrainingConfiguration.ts +6 -2
- package/openapi/gen/models/gistingTrainingConfigurationBatchSize.ts +2 -0
- package/openapi/gen/models/gistingTrainingConfigurationGistTokens.ts +2 -0
- package/openapi/gen/models/gistingTrainingConfigurationInput.ts +6 -2
- package/openapi/gen/models/gistingTrainingConfigurationInputBatchSize.ts +2 -0
- package/openapi/gen/models/gistingTrainingConfigurationInputGistTokens.ts +2 -0
- package/openapi/gen/models/index.ts +9 -4
- package/openapi/gen/models/sftTrainingConfiguration.ts +6 -3
- package/openapi/gen/models/sftTrainingConfigurationBatchSize.ts +2 -0
- package/openapi/gen/models/sftTrainingConfigurationInput.ts +6 -3
- package/openapi/gen/models/sftTrainingConfigurationInputBatchSize.ts +2 -0
- package/openapi/gen/models/sftTrainingConfigurationInputLoraRank.ts +2 -0
- package/openapi/gen/models/sftTrainingConfigurationLoraRank.ts +2 -0
- package/package.json +2 -2
- package/skills/catalog.json +11 -11
- package/skills/toloka-build/SKILL.md +29 -18
- package/skills/toloka-build/references/node-semantics.md +7 -7
- package/skills/toloka-build/references/workflow-and-cli.md +15 -12
- package/skills/toloka-fine-tuning/SKILL.md +145 -62
- package/skills/toloka-get-started/SKILL.md +37 -21
- package/skills/toloka-gisting/SKILL.md +156 -66
- package/skills/toloka-report-issue/references/report-template.md +1 -1
- package/src/cli/analytics.ts +50 -23
- package/src/cli/auth.ts +31 -12
- package/src/cli/auto-update.ts +12 -6
- package/src/cli/check.ts +76 -29
- package/src/cli/cli-entry.ts +3 -2
- package/src/cli/cli-error.ts +43 -0
- package/src/cli/commands/dataset.ts +13 -3
- package/src/cli/commands/models.ts +6 -7
- package/src/cli/commands/pipeline.ts +6 -7
- package/src/cli/commands/project.ts +9 -16
- package/src/cli/commands/report.ts +6 -2
- package/src/cli/commands/secret.ts +5 -4
- package/src/cli/commands/source.ts +4 -4
- package/src/cli/commands/status.ts +2 -3
- package/src/cli/commands/training.ts +50 -17
- package/src/cli/config.ts +2 -2
- package/src/cli/context.ts +55 -17
- package/src/cli/credentials.ts +12 -4
- package/src/cli/data.ts +96 -34
- package/src/cli/delivery-orders.ts +18 -1
- package/src/cli/file-system.ts +6 -2
- package/src/cli/format-error.ts +45 -2
- package/src/cli/init.ts +13 -7
- package/src/cli/models.ts +43 -12
- package/src/cli/program.ts +5 -56
- package/src/cli/project-context.ts +117 -32
- package/src/cli/project.ts +80 -28
- package/src/cli/report.ts +24 -9
- package/src/cli/runs.ts +33 -8
- package/src/cli/settings.ts +13 -5
- package/src/cli/skill.ts +61 -22
- package/src/cli/source.ts +3 -2
- package/src/cli/terminal-io.ts +13 -6
- package/src/cli/trainings.ts +129 -35
- package/src/cli/version.ts +2 -2
- package/src/client.ts +3 -9
- package/src/transport.ts +13 -1
- package/openapi/gen/models/gistingTrainingConfigurationInputRegime.ts +0 -2
- package/openapi/gen/models/gistingTrainingConfigurationRegime.ts +0 -2
- package/openapi/gen/models/sftTrainingConfigurationInputRegime.ts +0 -2
- package/openapi/gen/models/sftTrainingConfigurationRegime.ts +0 -2
package/src/cli/check.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { dirname, join } from "node:path";
|
|
8
8
|
|
|
9
|
-
import { assert } from "es-toolkit";
|
|
10
9
|
import {
|
|
11
10
|
createBundledTaskUiTypechecker,
|
|
12
11
|
findPostprocessKeyCollisions,
|
|
@@ -27,6 +26,8 @@ import {
|
|
|
27
26
|
import { resolveCliEntry } from "./cli-entry";
|
|
28
27
|
import { API_KEY_ENVIRONMENT_NAMES } from "./environment";
|
|
29
28
|
import { loadProjectSource, type ProjectSource } from "./source";
|
|
29
|
+
import { assertCli, REPORT_HINT, TolokaCliError } from "./cli-error";
|
|
30
|
+
import type { TolokaCliErrorOptions } from "./cli-error";
|
|
30
31
|
|
|
31
32
|
export type CheckStatus = "passed" | "failed" | "missing" | "partial" | "infrastructure_error";
|
|
32
33
|
export type CheckKind =
|
|
@@ -118,10 +119,10 @@ export type CheckProjectResult = {
|
|
|
118
119
|
|
|
119
120
|
export type FreshCheckFailurePhase = "spawn" | "execute" | "read_result" | "parse_result";
|
|
120
121
|
|
|
121
|
-
export class FreshCheckProcessError extends
|
|
122
|
+
export class FreshCheckProcessError extends TolokaCliError {
|
|
122
123
|
readonly phase: FreshCheckFailurePhase;
|
|
123
124
|
|
|
124
|
-
constructor(phase: FreshCheckFailurePhase, message: string, options
|
|
125
|
+
constructor(phase: FreshCheckFailurePhase, message: string, options: TolokaCliErrorOptions) {
|
|
125
126
|
super(message, options);
|
|
126
127
|
this.name = "FreshCheckProcessError";
|
|
127
128
|
this.phase = phase;
|
|
@@ -358,13 +359,15 @@ const filterInventory = (
|
|
|
358
359
|
pipeline.sourceDirectory.split("/").at(-1) === pipelineSelector,
|
|
359
360
|
);
|
|
360
361
|
if (pipelineSelector !== undefined) {
|
|
361
|
-
|
|
362
|
+
assertCli(
|
|
362
363
|
pipelines.length > 0,
|
|
363
364
|
`Unknown pipeline ${JSON.stringify(pipelineSelector)}. Available: ${inventory.map((item) => item.sourceDirectory).join(", ")}`,
|
|
365
|
+
{ hint: { description: "Pass one of the listed source directories." } },
|
|
364
366
|
);
|
|
365
|
-
|
|
367
|
+
assertCli(
|
|
366
368
|
pipelines.length === 1,
|
|
367
369
|
`Pipeline selector ${JSON.stringify(pipelineSelector)} is ambiguous: ${pipelines.map((item) => item.sourceDirectory).join(", ")}`,
|
|
370
|
+
{ hint: { description: "Pass the full source directory of the pipeline you mean." } },
|
|
368
371
|
);
|
|
369
372
|
}
|
|
370
373
|
if (nodeSelector === undefined) return { pipelines };
|
|
@@ -373,11 +376,12 @@ const filterInventory = (
|
|
|
373
376
|
.filter((node) => node.id === nodeSelector || node.name === nodeSelector)
|
|
374
377
|
.map((node) => ({ pipeline, node })),
|
|
375
378
|
);
|
|
376
|
-
|
|
379
|
+
assertCli(
|
|
377
380
|
matches.length === 1,
|
|
378
381
|
matches.length === 0
|
|
379
382
|
? `Unknown checkable node ${JSON.stringify(nodeSelector)}.`
|
|
380
383
|
: `Node selector ${JSON.stringify(nodeSelector)} is ambiguous across pipelines.`,
|
|
384
|
+
{ hint: { description: "Pass the pipeline selector together with the node id." } },
|
|
381
385
|
);
|
|
382
386
|
return { pipelines: [matches[0]!.pipeline], nodeId: matches[0]!.node.id };
|
|
383
387
|
};
|
|
@@ -789,28 +793,47 @@ const isCheckStatus = (value: unknown): value is CheckStatus =>
|
|
|
789
793
|
value === "infrastructure_error";
|
|
790
794
|
|
|
791
795
|
const parseFreshCheckDiagnostic = (value: unknown): CheckDiagnostic => {
|
|
792
|
-
|
|
796
|
+
assertCli(
|
|
797
|
+
typeof value === "object" && value !== null,
|
|
798
|
+
"Fresh check returned invalid diagnostics",
|
|
799
|
+
{ hint: REPORT_HINT },
|
|
800
|
+
);
|
|
793
801
|
const message = Reflect.get(value, "message");
|
|
794
802
|
const severity = Reflect.get(value, "severity");
|
|
795
803
|
const setting = Reflect.get(value, "setting");
|
|
796
804
|
const line = Reflect.get(value, "line");
|
|
797
805
|
const column = Reflect.get(value, "column");
|
|
798
806
|
const code = Reflect.get(value, "code");
|
|
799
|
-
|
|
800
|
-
|
|
807
|
+
assertCli(
|
|
808
|
+
typeof message === "string",
|
|
809
|
+
"Fresh check diagnostic has no message",
|
|
810
|
+
{ hint: REPORT_HINT },
|
|
811
|
+
);
|
|
812
|
+
assertCli(
|
|
801
813
|
severity === undefined || severity === "error" || severity === "warning",
|
|
802
814
|
"Fresh check diagnostic has invalid severity",
|
|
815
|
+
{ hint: REPORT_HINT },
|
|
803
816
|
);
|
|
804
|
-
|
|
817
|
+
assertCli(
|
|
805
818
|
setting === undefined || typeof setting === "string",
|
|
806
819
|
"Fresh check diagnostic has invalid setting",
|
|
820
|
+
{ hint: REPORT_HINT },
|
|
821
|
+
);
|
|
822
|
+
assertCli(
|
|
823
|
+
line === undefined || Number.isInteger(line),
|
|
824
|
+
"Fresh check diagnostic has invalid line",
|
|
825
|
+
{ hint: REPORT_HINT },
|
|
807
826
|
);
|
|
808
|
-
|
|
809
|
-
assert(
|
|
827
|
+
assertCli(
|
|
810
828
|
column === undefined || Number.isInteger(column),
|
|
811
829
|
"Fresh check diagnostic has invalid column",
|
|
830
|
+
{ hint: REPORT_HINT },
|
|
831
|
+
);
|
|
832
|
+
assertCli(
|
|
833
|
+
code === undefined || typeof code === "string",
|
|
834
|
+
"Fresh check diagnostic has invalid code",
|
|
835
|
+
{ hint: REPORT_HINT },
|
|
812
836
|
);
|
|
813
|
-
assert(code === undefined || typeof code === "string", "Fresh check diagnostic has invalid code");
|
|
814
837
|
return {
|
|
815
838
|
message,
|
|
816
839
|
...(severity === undefined ? {} : { severity }),
|
|
@@ -822,7 +845,11 @@ const parseFreshCheckDiagnostic = (value: unknown): CheckDiagnostic => {
|
|
|
822
845
|
};
|
|
823
846
|
|
|
824
847
|
const parseFreshCheckResultItem = (value: unknown): CheckResult => {
|
|
825
|
-
|
|
848
|
+
assertCli(
|
|
849
|
+
typeof value === "object" && value !== null,
|
|
850
|
+
"Fresh check returned an invalid result",
|
|
851
|
+
{ hint: REPORT_HINT },
|
|
852
|
+
);
|
|
826
853
|
const scope = Reflect.get(value, "scope");
|
|
827
854
|
const kind = Reflect.get(value, "kind");
|
|
828
855
|
const status = Reflect.get(value, "status");
|
|
@@ -831,25 +858,33 @@ const parseFreshCheckResultItem = (value: unknown): CheckResult => {
|
|
|
831
858
|
const pipeline = Reflect.get(value, "pipelineFingerprint");
|
|
832
859
|
const nodeId = Reflect.get(value, "nodeId");
|
|
833
860
|
const truncated = Reflect.get(value, "truncatedDiagnosticCount");
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
861
|
+
assertCli(isCheckScope(scope), "Fresh check returned an invalid scope", { hint: REPORT_HINT });
|
|
862
|
+
assertCli(isCheckKind(kind), "Fresh check returned an invalid kind", { hint: REPORT_HINT });
|
|
863
|
+
assertCli(isCheckStatus(status), "Fresh check returned an invalid status", { hint: REPORT_HINT });
|
|
864
|
+
assertCli(
|
|
865
|
+
Array.isArray(diagnostics),
|
|
866
|
+
"Fresh check returned invalid diagnostics",
|
|
867
|
+
{ hint: REPORT_HINT },
|
|
868
|
+
);
|
|
869
|
+
assertCli(
|
|
839
870
|
sourceDirectory === undefined || typeof sourceDirectory === "string",
|
|
840
871
|
"Fresh check returned an invalid source directory",
|
|
872
|
+
{ hint: REPORT_HINT },
|
|
841
873
|
);
|
|
842
|
-
|
|
874
|
+
assertCli(
|
|
843
875
|
pipeline === undefined || typeof pipeline === "string",
|
|
844
876
|
"Fresh check returned an invalid pipeline fingerprint",
|
|
877
|
+
{ hint: REPORT_HINT },
|
|
845
878
|
);
|
|
846
|
-
|
|
879
|
+
assertCli(
|
|
847
880
|
nodeId === undefined || typeof nodeId === "string",
|
|
848
881
|
"Fresh check returned an invalid node id",
|
|
882
|
+
{ hint: REPORT_HINT },
|
|
849
883
|
);
|
|
850
|
-
|
|
884
|
+
assertCli(
|
|
851
885
|
truncated === undefined || (Number.isInteger(truncated) && Number(truncated) >= 0),
|
|
852
886
|
"Fresh check returned an invalid truncated count",
|
|
887
|
+
{ hint: REPORT_HINT },
|
|
853
888
|
);
|
|
854
889
|
return {
|
|
855
890
|
scope,
|
|
@@ -864,14 +899,19 @@ const parseFreshCheckResultItem = (value: unknown): CheckResult => {
|
|
|
864
899
|
};
|
|
865
900
|
|
|
866
901
|
const parseFreshCheckResult = (value: unknown, json: boolean): CheckProjectResult => {
|
|
867
|
-
|
|
902
|
+
assertCli(
|
|
903
|
+
typeof value === "object" && value !== null,
|
|
904
|
+
"Fresh check returned invalid JSON",
|
|
905
|
+
{ hint: REPORT_HINT },
|
|
906
|
+
);
|
|
868
907
|
const exitCode = Reflect.get(value, "exitCode");
|
|
869
908
|
const rawResults = Reflect.get(value, "results");
|
|
870
|
-
|
|
909
|
+
assertCli(
|
|
871
910
|
exitCode === 0 || exitCode === 1 || exitCode === 2,
|
|
872
911
|
"Fresh check returned an invalid exit code",
|
|
912
|
+
{ hint: REPORT_HINT },
|
|
873
913
|
);
|
|
874
|
-
|
|
914
|
+
assertCli(Array.isArray(rawResults), "Fresh check returned no results", { hint: REPORT_HINT });
|
|
875
915
|
const results = rawResults.map(parseFreshCheckResultItem);
|
|
876
916
|
return {
|
|
877
917
|
exitCode,
|
|
@@ -899,13 +939,16 @@ export const readFreshCheckResult = async (
|
|
|
899
939
|
output.length === 0
|
|
900
940
|
? `Local check process exited ${run.exitCode} before producing results`
|
|
901
941
|
: `Local check process failed before producing results:\n${output}`,
|
|
902
|
-
{
|
|
942
|
+
{
|
|
943
|
+
cause: error,
|
|
944
|
+
hint: { description: "Fix the errors printed above, then re-run toloka check." },
|
|
945
|
+
},
|
|
903
946
|
);
|
|
904
947
|
}
|
|
905
948
|
throw new FreshCheckProcessError(
|
|
906
949
|
"read_result",
|
|
907
950
|
"Local check process completed without producing a result file",
|
|
908
|
-
{ cause: error },
|
|
951
|
+
{ cause: error, hint: REPORT_HINT },
|
|
909
952
|
);
|
|
910
953
|
}
|
|
911
954
|
|
|
@@ -915,6 +958,7 @@ export const readFreshCheckResult = async (
|
|
|
915
958
|
} catch (error) {
|
|
916
959
|
throw new FreshCheckProcessError("parse_result", "Local check process returned invalid JSON", {
|
|
917
960
|
cause: error,
|
|
961
|
+
hint: REPORT_HINT,
|
|
918
962
|
});
|
|
919
963
|
}
|
|
920
964
|
|
|
@@ -924,7 +968,7 @@ export const readFreshCheckResult = async (
|
|
|
924
968
|
throw new FreshCheckProcessError(
|
|
925
969
|
"parse_result",
|
|
926
970
|
`Local check process returned an invalid result: ${error instanceof Error ? error.message : String(error)}`,
|
|
927
|
-
{ cause: error },
|
|
971
|
+
{ cause: error, hint: REPORT_HINT },
|
|
928
972
|
);
|
|
929
973
|
}
|
|
930
974
|
};
|
|
@@ -958,7 +1002,10 @@ export const runFreshCheck = async (options: CheckProjectOptions): Promise<Check
|
|
|
958
1002
|
throw new FreshCheckProcessError(
|
|
959
1003
|
"spawn",
|
|
960
1004
|
`Unable to start the local check process: ${error instanceof Error ? error.message : String(error)}`,
|
|
961
|
-
{
|
|
1005
|
+
{
|
|
1006
|
+
cause: error,
|
|
1007
|
+
hint: { description: "Check that bun is installed and on PATH, then re-run toloka check." },
|
|
1008
|
+
},
|
|
962
1009
|
);
|
|
963
1010
|
}
|
|
964
1011
|
return await readFreshCheckResult(
|
package/src/cli/cli-entry.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import { existsSync, realpathSync } from "node:fs";
|
|
3
2
|
import { dirname, join } from "node:path";
|
|
3
|
+
import { assertCli } from "./cli-error";
|
|
4
4
|
|
|
5
5
|
const CLI_ENTRY = join("bin", "toloka.js");
|
|
6
6
|
|
|
@@ -33,9 +33,10 @@ export const resolveCliEntry = (runtimeEntry: string | undefined = process.argv[
|
|
|
33
33
|
return entry;
|
|
34
34
|
}
|
|
35
35
|
const workingDirectoryEntry = findCliEntryAbove(process.cwd());
|
|
36
|
-
|
|
36
|
+
assertCli(
|
|
37
37
|
workingDirectoryEntry !== undefined,
|
|
38
38
|
`Cannot locate the toloka CLI entry point. An installed @toloka-platform/sdk ships ${CLI_ENTRY} in a directory above its runtime entry, but none exists above ${runtimeEntry ?? "the unset process.argv[1]"} or above ${process.cwd()}. Reinstall @toloka-platform/sdk.`,
|
|
39
|
+
{ hint: { disabled: true } },
|
|
39
40
|
);
|
|
40
41
|
return workingDirectoryEntry;
|
|
41
42
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type CliErrorHint =
|
|
2
|
+
| { readonly description: string; readonly disabled?: never }
|
|
3
|
+
| { readonly disabled: true; readonly description?: never };
|
|
4
|
+
|
|
5
|
+
export type TolokaCliErrorOptions = {
|
|
6
|
+
readonly hint: CliErrorHint;
|
|
7
|
+
readonly cause?: unknown;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class TolokaCliError extends Error {
|
|
11
|
+
readonly hint: CliErrorHint;
|
|
12
|
+
|
|
13
|
+
constructor(message: string, options: TolokaCliErrorOptions) {
|
|
14
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
15
|
+
this.name = "TolokaCliError";
|
|
16
|
+
this.hint = options.hint;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function assertCli(
|
|
21
|
+
condition: unknown,
|
|
22
|
+
message: string,
|
|
23
|
+
options: TolokaCliErrorOptions,
|
|
24
|
+
): asserts condition {
|
|
25
|
+
if (!condition) throw new TolokaCliError(message, options);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const formatHint = (hint: CliErrorHint): string | undefined =>
|
|
29
|
+
"disabled" in hint ? undefined : `Hint: ${hint.description}`;
|
|
30
|
+
|
|
31
|
+
export const REPORT_HINT: CliErrorHint = {
|
|
32
|
+
description:
|
|
33
|
+
"This looks like a defect in the CLI or the platform. Write a report as the toloka-report-issue skill describes, then send it with toloka report <report.md>.",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const RETRY_OR_REPORT_HINT: CliErrorHint = {
|
|
37
|
+
description:
|
|
38
|
+
"Retry the command; if it keeps failing, write a report as the toloka-report-issue skill describes and send it with toloka report <report.md>.",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const REINSTALL_HINT: CliErrorHint = {
|
|
42
|
+
description: "Reinstall @toloka-platform/sdk to restore the bundled files.",
|
|
43
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import { resolve } from "node:path";
|
|
3
2
|
import type { Command } from "commander";
|
|
4
3
|
import { positiveInteger, resolveContext, type CommandHost } from "../context";
|
|
5
4
|
import {
|
|
5
|
+
createDataset,
|
|
6
6
|
generateDatasetFieldDeclarations,
|
|
7
7
|
listProjectDatasets,
|
|
8
8
|
loadDataset,
|
|
9
9
|
uploadDataset,
|
|
10
10
|
} from "../data";
|
|
11
|
-
import {
|
|
11
|
+
import { assertProjectSelected } from "../project-context";
|
|
12
12
|
|
|
13
13
|
export const registerDatasetCommands = (program: Command, host: CommandHost): void => {
|
|
14
14
|
const { context, globals } = host;
|
|
@@ -20,10 +20,20 @@ export const registerDatasetCommands = (program: Command, host: CommandHost): vo
|
|
|
20
20
|
.description("list live datasets in the selected project")
|
|
21
21
|
.action(async () => {
|
|
22
22
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
23
|
-
|
|
23
|
+
assertProjectSelected(projectId);
|
|
24
24
|
const result = await listProjectDatasets(client, { projectId });
|
|
25
25
|
context.io.stdout(result.output);
|
|
26
26
|
});
|
|
27
|
+
dataset
|
|
28
|
+
.command("create")
|
|
29
|
+
.argument("<name>", "dataset name")
|
|
30
|
+
.description("create an empty dataset in the selected project")
|
|
31
|
+
.action(async (name: string) => {
|
|
32
|
+
const { client, projectId } = await resolveContext(globals(), context);
|
|
33
|
+
assertProjectSelected(projectId);
|
|
34
|
+
const result = await createDataset(client, { projectId, name });
|
|
35
|
+
context.io.stdout(result.output);
|
|
36
|
+
});
|
|
27
37
|
dataset
|
|
28
38
|
.command("fields")
|
|
29
39
|
.argument("<name>", "dataset name or id")
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import type { Command } from "commander";
|
|
3
2
|
import { resolveContext, type CommandHost } from "../context";
|
|
4
3
|
import {
|
|
@@ -12,7 +11,7 @@ import {
|
|
|
12
11
|
listModelVersions,
|
|
13
12
|
parseBaseModelId,
|
|
14
13
|
} from "../models";
|
|
15
|
-
import {
|
|
14
|
+
import { assertProjectSelected } from "../project-context";
|
|
16
15
|
|
|
17
16
|
export const registerModelCommands = (program: Command, host: CommandHost): void => {
|
|
18
17
|
const { context, globals } = host;
|
|
@@ -47,7 +46,7 @@ export const registerModelCommands = (program: Command, host: CommandHost): void
|
|
|
47
46
|
.description("list Models owned by the selected project")
|
|
48
47
|
.action(async (options: { json: boolean }) => {
|
|
49
48
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
50
|
-
|
|
49
|
+
assertProjectSelected(projectId);
|
|
51
50
|
await listModels(client, { projectId, json: options.json }, context.io);
|
|
52
51
|
});
|
|
53
52
|
model
|
|
@@ -57,7 +56,7 @@ export const registerModelCommands = (program: Command, host: CommandHost): void
|
|
|
57
56
|
.description("show one project Model")
|
|
58
57
|
.action(async (nameOrId: string, options: { json: boolean }) => {
|
|
59
58
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
60
|
-
|
|
59
|
+
assertProjectSelected(projectId);
|
|
61
60
|
await getModel(client, { projectId, nameOrId, json: options.json }, context.io);
|
|
62
61
|
});
|
|
63
62
|
model
|
|
@@ -67,7 +66,7 @@ export const registerModelCommands = (program: Command, host: CommandHost): void
|
|
|
67
66
|
.description("list immutable versions of a model")
|
|
68
67
|
.action(async (nameOrId: string, options: { json: boolean }) => {
|
|
69
68
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
70
|
-
|
|
69
|
+
assertProjectSelected(projectId);
|
|
71
70
|
await listModelVersions(client, { projectId, nameOrId, json: options.json }, context.io);
|
|
72
71
|
});
|
|
73
72
|
model
|
|
@@ -80,7 +79,7 @@ export const registerModelCommands = (program: Command, host: CommandHost): void
|
|
|
80
79
|
.action(
|
|
81
80
|
async (name: string, options: { base: string; description?: string; json: boolean }) => {
|
|
82
81
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
83
|
-
|
|
82
|
+
assertProjectSelected(projectId);
|
|
84
83
|
await createModel(
|
|
85
84
|
client,
|
|
86
85
|
{
|
|
@@ -101,7 +100,7 @@ export const registerModelCommands = (program: Command, host: CommandHost): void
|
|
|
101
100
|
.description("archive a project Model")
|
|
102
101
|
.action(async (nameOrId: string, options: { json: boolean }) => {
|
|
103
102
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
104
|
-
|
|
103
|
+
assertProjectSelected(projectId);
|
|
105
104
|
await archiveModel(client, { projectId, nameOrId, json: options.json }, context.io);
|
|
106
105
|
});
|
|
107
106
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import type { Command } from "commander";
|
|
3
2
|
import { estimatePipelineCost } from "../cost";
|
|
4
3
|
import { exitCodeForOutcome, positiveInteger, resolveContext, type CommandHost } from "../context";
|
|
5
|
-
import {
|
|
4
|
+
import { assertProjectSelected } from "../project-context";
|
|
6
5
|
import {
|
|
7
6
|
cancelPipelineRun,
|
|
8
7
|
listLivePipelines,
|
|
@@ -25,7 +24,7 @@ export const registerPipelineCommands = (program: Command, host: CommandHost): v
|
|
|
25
24
|
.description("list live pipelines in the selected project")
|
|
26
25
|
.action(async (options: { limit?: number }) => {
|
|
27
26
|
const { client, projectId, state } = await resolveContext(globals(), context);
|
|
28
|
-
|
|
27
|
+
assertProjectSelected(projectId);
|
|
29
28
|
const result = await listLivePipelines({
|
|
30
29
|
client,
|
|
31
30
|
projectId,
|
|
@@ -42,7 +41,7 @@ export const registerPipelineCommands = (program: Command, host: CommandHost): v
|
|
|
42
41
|
.description("start a run on a deployed pipeline")
|
|
43
42
|
.action(async (name: string | undefined, options: { wait: boolean; timeout?: number }) => {
|
|
44
43
|
const { client, state, projectId } = await resolveContext(globals(), context);
|
|
45
|
-
|
|
44
|
+
assertProjectSelected(projectId);
|
|
46
45
|
const result = await startPipelineRun(client, {
|
|
47
46
|
projectId,
|
|
48
47
|
state,
|
|
@@ -60,7 +59,7 @@ export const registerPipelineCommands = (program: Command, host: CommandHost): v
|
|
|
60
59
|
.description("report the latest run's state and item counts")
|
|
61
60
|
.action(async (name: string | undefined) => {
|
|
62
61
|
const { client, state, projectId } = await resolveContext(globals(), context);
|
|
63
|
-
|
|
62
|
+
assertProjectSelected(projectId);
|
|
64
63
|
const result = await pipelineRunStatus(client, {
|
|
65
64
|
projectId,
|
|
66
65
|
state,
|
|
@@ -77,7 +76,7 @@ export const registerPipelineCommands = (program: Command, host: CommandHost): v
|
|
|
77
76
|
.description("list recent runs")
|
|
78
77
|
.action(async (name: string | undefined, options: { limit?: number }) => {
|
|
79
78
|
const { client, state, projectId } = await resolveContext(globals(), context);
|
|
80
|
-
|
|
79
|
+
assertProjectSelected(projectId);
|
|
81
80
|
const result = await listPipelineRuns(client, {
|
|
82
81
|
projectId,
|
|
83
82
|
state,
|
|
@@ -94,7 +93,7 @@ export const registerPipelineCommands = (program: Command, host: CommandHost): v
|
|
|
94
93
|
.description("forecast what a run of this pipeline would bill")
|
|
95
94
|
.action(async (name: string | undefined, options: { itemLimit?: number }) => {
|
|
96
95
|
const { client, state, projectId } = await resolveContext(globals(), context);
|
|
97
|
-
|
|
96
|
+
assertProjectSelected(projectId);
|
|
98
97
|
const result = await estimatePipelineCost(client, {
|
|
99
98
|
projectId,
|
|
100
99
|
state,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import type { Command } from "commander";
|
|
3
2
|
import { createClient } from "../../client";
|
|
4
3
|
import {
|
|
@@ -11,17 +10,9 @@ import {
|
|
|
11
10
|
type CommandHost,
|
|
12
11
|
} from "../context";
|
|
13
12
|
import { requireStoredCredentials } from "../credentials";
|
|
14
|
-
import {
|
|
15
|
-
MISSING_PROJECT_ID_MESSAGE,
|
|
16
|
-
addProject,
|
|
17
|
-
createProject,
|
|
18
|
-
currentProject,
|
|
19
|
-
listRemoteProjects,
|
|
20
|
-
removeProject,
|
|
21
|
-
switchProject,
|
|
22
|
-
untrackProjectResource,
|
|
23
|
-
} from "../project-context";
|
|
13
|
+
import { addProject, assertProjectSelected, createProject, currentProject, listRemoteProjects, removeProject, switchProject, untrackProjectResource } from "../project-context";
|
|
24
14
|
import { readTolokaState } from "../../state";
|
|
15
|
+
import { assertCli } from "../cli-error";
|
|
25
16
|
|
|
26
17
|
export const registerProjectCommands = (program: Command, host: CommandHost): void => {
|
|
27
18
|
const { context, exitCode, globals } = host;
|
|
@@ -97,7 +88,7 @@ export const registerProjectCommands = (program: Command, host: CommandHost): vo
|
|
|
97
88
|
.description("print the current project URL")
|
|
98
89
|
.action(async () => {
|
|
99
90
|
const { baseUrl, client, projectId } = await resolveContext(globals(), context);
|
|
100
|
-
|
|
91
|
+
assertProjectSelected(projectId);
|
|
101
92
|
const live = await client.projects.get({ projectId });
|
|
102
93
|
const url = new URL(
|
|
103
94
|
`/teams/${encodeURIComponent(live.teamId)}/projects/${encodeURIComponent(live.id)}`,
|
|
@@ -125,9 +116,10 @@ export const registerProjectCommands = (program: Command, host: CommandHost): vo
|
|
|
125
116
|
.option("--confirm", "confirm untracking in a non-interactive environment", false)
|
|
126
117
|
.description("remove a pipeline or dataset from local tracking without deleting it")
|
|
127
118
|
.action(async (type: string, name: string, options: { confirm: boolean }) => {
|
|
128
|
-
|
|
119
|
+
assertCli(
|
|
129
120
|
type === "pipeline" || type === "dataset",
|
|
130
121
|
"Resource type must be pipeline or dataset.",
|
|
122
|
+
{ hint: { description: "Run toloka project untrack pipeline <name> or toloka project untrack dataset <name>." } },
|
|
131
123
|
);
|
|
132
124
|
const sourceRoot = await resolveSourceRoot(globals(), context.io);
|
|
133
125
|
await untrackProjectResource({
|
|
@@ -144,9 +136,10 @@ export const registerProjectCommands = (program: Command, host: CommandHost): vo
|
|
|
144
136
|
.option("--name <name>", "platform project name")
|
|
145
137
|
.option("--team-id <id>", "team that owns the project")
|
|
146
138
|
.description("create a live project and select it");
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
139
|
+
create.option(
|
|
140
|
+
"--delivery-order-id <id>",
|
|
141
|
+
"Sunday delivery order id (required when the owning team is internal)",
|
|
142
|
+
);
|
|
150
143
|
create.action(
|
|
151
144
|
async (
|
|
152
145
|
alias: string | undefined,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import type { Command } from "commander";
|
|
3
2
|
import { authoredByOption, resolveInitRoot, type CommandHost } from "../context";
|
|
4
3
|
import { PRODUCTION_BASE_URL, resolveInternalBaseUrl } from "../config";
|
|
5
4
|
import { submitIssueReport, type IssueReportAuthor } from "../report";
|
|
5
|
+
import { assertCli } from "../cli-error";
|
|
6
6
|
|
|
7
7
|
export const registerReportCommand = (program: Command, host: CommandHost): void => {
|
|
8
8
|
const { context, exitCode, globals } = host;
|
|
@@ -17,7 +17,11 @@ export const registerReportCommand = (program: Command, host: CommandHost): void
|
|
|
17
17
|
markdownPath: string,
|
|
18
18
|
options: { authoredBy: IssueReportAuthor; confirm: boolean },
|
|
19
19
|
) => {
|
|
20
|
-
|
|
20
|
+
assertCli(
|
|
21
|
+
context.analytics,
|
|
22
|
+
"Issue reporting requires CLI analytics.",
|
|
23
|
+
{ hint: { description: "Set TOLOKA_TELEMETRY=1 to enable analytics, then re-run toloka report." } },
|
|
24
|
+
);
|
|
21
25
|
const sourceRoot = resolveInitRoot(globals());
|
|
22
26
|
const baseUrl =
|
|
23
27
|
globals().baseUrl ??
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import type { Command } from "commander";
|
|
3
2
|
import { resolveContext, type CommandHost } from "../context";
|
|
4
3
|
import { setProjectSecret } from "../data";
|
|
5
|
-
import {
|
|
4
|
+
import { assertProjectSelected } from "../project-context";
|
|
5
|
+
import { assertCli } from "../cli-error";
|
|
6
6
|
|
|
7
7
|
export const registerSecretCommands = (program: Command, host: CommandHost): void => {
|
|
8
8
|
const { context, exitCode, globals } = host;
|
|
@@ -17,15 +17,16 @@ export const registerSecretCommands = (program: Command, host: CommandHost): voi
|
|
|
17
17
|
.description("set a secret value without writing it to disk")
|
|
18
18
|
.action(async (name: string, options: { fromEnv?: string }) => {
|
|
19
19
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
20
|
-
|
|
20
|
+
assertProjectSelected(projectId);
|
|
21
21
|
|
|
22
22
|
const value =
|
|
23
23
|
options.fromEnv === undefined
|
|
24
24
|
? (await context.io.readStdin()).replace(/\r?\n$/u, "")
|
|
25
25
|
: context.environment[options.fromEnv];
|
|
26
|
-
|
|
26
|
+
assertCli(
|
|
27
27
|
value !== undefined,
|
|
28
28
|
`Missing secret value. Set ${options.fromEnv ?? "the named environment variable"} or pipe it to stdin.`,
|
|
29
|
+
{ hint: { disabled: true } },
|
|
29
30
|
);
|
|
30
31
|
|
|
31
32
|
try {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import { writeFile } from "node:fs/promises";
|
|
3
2
|
import type { Command } from "commander";
|
|
4
3
|
import {
|
|
@@ -12,8 +11,9 @@ import {
|
|
|
12
11
|
import { resolveContext, resolveInitRoot, resolveSourceRoot, type CommandHost } from "../context";
|
|
13
12
|
import { initProject } from "../init";
|
|
14
13
|
import { applyProject, importProject, planProject, validateProject } from "../project";
|
|
15
|
-
import {
|
|
14
|
+
import { assertProjectSelected, resolveProjectContext } from "../project-context";
|
|
16
15
|
import { readTolokaState } from "../../state";
|
|
16
|
+
import { assertCli, REPORT_HINT } from "../cli-error";
|
|
17
17
|
|
|
18
18
|
const runChecksInterruptibly = async (
|
|
19
19
|
options: CheckProjectOptions,
|
|
@@ -77,7 +77,7 @@ export const registerSourceCommands = (program: Command, host: CommandHost): voi
|
|
|
77
77
|
projectId: selectedProjectId,
|
|
78
78
|
} = await resolveContext(globals(), context);
|
|
79
79
|
const id = projectId ?? selectedProjectId;
|
|
80
|
-
|
|
80
|
+
assertProjectSelected(id);
|
|
81
81
|
const result = await importProject(client, {
|
|
82
82
|
sourceRoot,
|
|
83
83
|
projectId: id,
|
|
@@ -192,7 +192,7 @@ export const registerSourceCommands = (program: Command, host: CommandHost): voi
|
|
|
192
192
|
exitCode.value = checked.exitCode;
|
|
193
193
|
return;
|
|
194
194
|
}
|
|
195
|
-
|
|
195
|
+
assertCli(checked.source, "Passing checks must return project source", { hint: REPORT_HINT });
|
|
196
196
|
const { client, projectId } = await resolveContext(globals(), context);
|
|
197
197
|
const result = await applyProject(client, {
|
|
198
198
|
sourceRoot,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { assert } from "es-toolkit";
|
|
2
1
|
import type { Command } from "commander";
|
|
3
2
|
import { resolveContext, type CommandHost } from "../context";
|
|
4
3
|
import { projectStatus } from "../project";
|
|
5
|
-
import {
|
|
4
|
+
import { assertProjectSelected } from "../project-context";
|
|
6
5
|
|
|
7
6
|
export const registerStatusCommand = (program: Command, host: CommandHost): void => {
|
|
8
7
|
const { context, globals } = host;
|
|
@@ -11,7 +10,7 @@ export const registerStatusCommand = (program: Command, host: CommandHost): void
|
|
|
11
10
|
.description("report project health: live counts and pending source changes")
|
|
12
11
|
.action(async () => {
|
|
13
12
|
const { sourceRoot, client, projectId } = await resolveContext(globals(), context);
|
|
14
|
-
|
|
13
|
+
assertProjectSelected(projectId);
|
|
15
14
|
const result = await projectStatus(client, { sourceRoot, projectId });
|
|
16
15
|
context.io.stdout(result.output);
|
|
17
16
|
});
|