orizu 0.5.40 → 0.5.42
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/dist/account-directory.d.ts.map +1 -1
- package/dist/account-directory.js +2 -10
- package/dist/app-publish-workspace.js +1 -1
- package/dist/archive-artifact-workflow.d.ts +23 -0
- package/dist/archive-artifact-workflow.d.ts.map +1 -0
- package/dist/archive-artifact-workflow.js +100 -0
- package/dist/archive-artifacts-cli.d.ts.map +1 -1
- package/dist/archive-artifacts-cli.js +7 -11
- package/dist/dataset-clone-workflow.d.ts +11 -0
- package/dist/dataset-clone-workflow.d.ts.map +1 -0
- package/dist/dataset-clone-workflow.js +100 -0
- package/dist/dataset-commands.d.ts.map +1 -1
- package/dist/dataset-commands.js +25 -58
- package/dist/dataset-split-create-workflow.d.ts +16 -0
- package/dist/dataset-split-create-workflow.d.ts.map +1 -0
- package/dist/dataset-split-create-workflow.js +115 -0
- package/dist/dataset-transfer-upload.d.ts +2 -6
- package/dist/dataset-transfer-upload.d.ts.map +1 -1
- package/dist/dataset-transfer-upload.js +9 -2
- package/dist/dataset-upload-snapshot.d.ts.map +1 -1
- package/dist/dataset-upload-snapshot.js +7 -1
- package/dist/dataset-version-workflow.d.ts +24 -0
- package/dist/dataset-version-workflow.d.ts.map +1 -0
- package/dist/dataset-version-workflow.js +99 -0
- package/dist/feedback-cli.js +3 -3
- package/dist/git-credential.js +1 -1
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +10 -2
- package/dist/hosted-boot.d.ts +7 -0
- package/dist/hosted-boot.d.ts.map +1 -1
- package/dist/hosted-boot.js +251 -58
- package/dist/hosted-harness-opencode.d.ts +1 -1
- package/dist/hosted-harness-opencode.js +7 -7
- package/dist/hosted-harness.d.ts +1 -0
- package/dist/hosted-harness.d.ts.map +1 -1
- package/dist/hosted-harness.js +2 -0
- package/dist/hosted-harvest.d.ts +2 -1
- package/dist/hosted-harvest.d.ts.map +1 -1
- package/dist/hosted-harvest.js +29 -17
- package/dist/hosted-live-channel.d.ts +25 -0
- package/dist/hosted-live-channel.d.ts.map +1 -0
- package/dist/hosted-live-channel.js +130 -0
- package/dist/hosted-loop-lifecycle.d.ts +3 -2
- package/dist/hosted-loop-lifecycle.d.ts.map +1 -1
- package/dist/hosted-loop-lifecycle.js +3 -2
- package/dist/hosted-loop.d.ts +7 -0
- package/dist/hosted-loop.d.ts.map +1 -1
- package/dist/hosted-loop.js +32 -6
- package/dist/hosted-run-event-sink.d.ts +3 -0
- package/dist/hosted-run-event-sink.d.ts.map +1 -1
- package/dist/hosted-run-event-sink.js +4 -0
- package/dist/hosted-runtime-assets.js +1 -1
- package/dist/hosted-session-cli.d.ts.map +1 -1
- package/dist/hosted-session-cli.js +4 -0
- package/dist/hosted-session-seed.d.ts +8 -6
- package/dist/hosted-session-seed.d.ts.map +1 -1
- package/dist/hosted-session-seed.js +26 -9
- package/dist/hosted-skill-staging.d.ts +36 -12
- package/dist/hosted-skill-staging.d.ts.map +1 -1
- package/dist/hosted-skill-staging.js +96 -34
- package/dist/http.d.ts +2 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +10 -6
- package/dist/index.js +2 -2
- package/dist/last-error-record.d.ts +4 -2
- package/dist/last-error-record.d.ts.map +1 -1
- package/dist/last-error-record.js +10 -68
- package/dist/last-error-workflow.d.ts +4 -0
- package/dist/last-error-workflow.d.ts.map +1 -0
- package/dist/last-error-workflow.js +78 -0
- package/dist/orizu-skill-links.d.ts +48 -0
- package/dist/orizu-skill-links.d.ts.map +1 -0
- package/dist/orizu-skill-links.js +99 -0
- package/dist/preview-runtime.d.ts +1 -0
- package/dist/preview-runtime.d.ts.map +1 -1
- package/dist/preview-runtime.js +15 -0
- package/dist/setup-and-skills-commands.d.ts.map +1 -1
- package/dist/setup-and-skills-commands.js +52 -7
- package/dist/setup-onboarding.d.ts.map +1 -1
- package/dist/setup-onboarding.js +6 -2
- package/dist/skill-installer.d.ts +16 -0
- package/dist/skill-installer.d.ts.map +1 -1
- package/dist/skill-installer.js +33 -5
- package/dist/task-commands.d.ts.map +1 -1
- package/dist/task-commands.js +9 -16
- package/dist/task-report-workflow.d.ts +47 -0
- package/dist/task-report-workflow.d.ts.map +1 -0
- package/dist/task-report-workflow.js +160 -0
- package/dist/team-create-workflow.d.ts +16 -0
- package/dist/team-create-workflow.d.ts.map +1 -0
- package/dist/team-create-workflow.js +130 -0
- package/dist/workbench-cli.d.ts.map +1 -1
- package/dist/workbench-cli.js +24 -4
- package/package.json +1 -1
- package/src/account-directory.ts +2 -10
- package/src/app-publish-workspace.ts +1 -1
- package/src/archive-artifact-workflow.ts +101 -0
- package/src/archive-artifacts-cli.ts +7 -28
- package/src/dataset-clone-workflow.ts +100 -0
- package/src/dataset-commands.ts +25 -84
- package/src/dataset-split-create-workflow.ts +128 -0
- package/src/dataset-transfer-upload.ts +12 -5
- package/src/dataset-upload-snapshot.ts +8 -1
- package/src/dataset-version-workflow.ts +105 -0
- package/src/feedback-cli.ts +4 -4
- package/src/git-credential.ts +1 -1
- package/src/help.ts +10 -2
- package/src/hosted-boot.ts +252 -57
- package/src/hosted-harness-opencode.ts +7 -7
- package/src/hosted-harness.ts +2 -0
- package/src/hosted-harvest.ts +30 -17
- package/src/hosted-live-channel.ts +136 -0
- package/src/hosted-loop-lifecycle.ts +3 -2
- package/src/hosted-loop.ts +30 -6
- package/src/hosted-run-event-sink.ts +7 -0
- package/src/hosted-runtime-assets.ts +1 -1
- package/src/hosted-session-cli.ts +4 -0
- package/src/hosted-session-seed.ts +28 -10
- package/src/hosted-skill-staging.ts +110 -36
- package/src/http.ts +12 -7
- package/src/index.ts +2 -2
- package/src/last-error-record.ts +11 -85
- package/src/last-error-workflow.ts +121 -0
- package/src/orizu-skill-links.ts +114 -0
- package/src/preview-runtime.ts +16 -0
- package/src/setup-and-skills-commands.ts +60 -6
- package/src/setup-onboarding.ts +6 -2
- package/src/skill-installer.ts +44 -5
- package/src/task-commands.ts +9 -43
- package/src/task-report-workflow.ts +179 -0
- package/src/team-create-workflow.ts +132 -0
- package/src/workbench-cli.ts +24 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-directory.d.ts","sourceRoot":"","sources":["../src/account-directory.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"account-directory.d.ts","sourceRoot":"","sources":["../src/account-directory.ts"],"names":[],"mappings":"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"}
|
|
@@ -111,16 +111,8 @@ async function fetchTeamMembers(teamSlug) {
|
|
|
111
111
|
return data.members;
|
|
112
112
|
}
|
|
113
113
|
async function createTeamOnServer(name, request = authedFetch) {
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
headers: { 'Content-Type': 'application/json' },
|
|
117
|
-
body: JSON.stringify({ name }),
|
|
118
|
-
});
|
|
119
|
-
if (!response.ok) {
|
|
120
|
-
throw new Error(`Failed to create team: ${await response.text()}`);
|
|
121
|
-
}
|
|
122
|
-
const data = await parseJsonResponse(response, 'Team create');
|
|
123
|
-
return data.team;
|
|
114
|
+
const { createTeamWithDeadline } = await import('./team-create-workflow.js');
|
|
115
|
+
return await createTeamWithDeadline(name, request);
|
|
124
116
|
}
|
|
125
117
|
async function createProjectOnServer(teamSlug, name, request = authedFetch) {
|
|
126
118
|
const response = await request('/api/cli/projects', {
|
|
@@ -75,7 +75,7 @@ function liveLayer(root, attempt) {
|
|
|
75
75
|
try: async (signal) => {
|
|
76
76
|
const response = await authedFetch(`/api/cli/workspaces/${encodeURIComponent(workspaceId)}/repo-token`, {
|
|
77
77
|
method: 'POST',
|
|
78
|
-
headers: { 'Content-Type': 'application/json' },
|
|
78
|
+
headers: { 'Content-Type': 'application/json', 'X-Orizu-Session-Seed-Protocol': '1' },
|
|
79
79
|
body: JSON.stringify({ purpose: 'team_read', sessionId: process.env.ORIZU_SESSION_ID?.trim() }),
|
|
80
80
|
signal,
|
|
81
81
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
declare const ArchiveReply: Schema.Struct<{
|
|
3
|
+
readonly artifact: Schema.Struct<{
|
|
4
|
+
readonly id: Schema.String;
|
|
5
|
+
readonly type: Schema.String;
|
|
6
|
+
readonly status: Schema.Literals<readonly ["active", "archived"]>;
|
|
7
|
+
readonly archivedAt: Schema.NullOr<Schema.String>;
|
|
8
|
+
readonly assigneeId: Schema.optionalKey<Schema.String>;
|
|
9
|
+
}>;
|
|
10
|
+
}>;
|
|
11
|
+
export type ArchiveReply = typeof ArchiveReply.Type;
|
|
12
|
+
export interface ArchiveRequest {
|
|
13
|
+
path: string;
|
|
14
|
+
body: {
|
|
15
|
+
archived: boolean;
|
|
16
|
+
assigneeId?: string;
|
|
17
|
+
};
|
|
18
|
+
label: string;
|
|
19
|
+
fetcher?: (path: string, init?: RequestInit) => Promise<Response>;
|
|
20
|
+
}
|
|
21
|
+
export declare function archiveArtifact(request: ArchiveRequest): Promise<ArchiveReply>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=archive-artifact-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-artifact-workflow.d.ts","sourceRoot":"","sources":["../src/archive-artifact-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,MAAM,EAAE,MAAM,QAAQ,CAAA;AAW5D,QAAA,MAAM,YAAY;;;;;;;;EAQhB,CAAA;AACF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAEnD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAEhD,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClE;AAoED,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAIpF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Cause, Effect, Exit, Result, Schema } from 'effect';
|
|
2
|
+
import { datasetTransferTimeoutMs } from './dataset-transfer-policy.js';
|
|
3
|
+
import { isJsonErrorResponsePayload } from './error-response.js';
|
|
4
|
+
import { authedFetch } from './http.js';
|
|
5
|
+
import { sanitizeTerminalText } from './json-response.js';
|
|
6
|
+
// Loaded only through `await import(...)` from archive-artifacts-cli.
|
|
7
|
+
const MAY_BE_SAVED = 'The change may already be saved: running the same command again is safe and shows its current state.';
|
|
8
|
+
const ArchiveReply = Schema.Struct({
|
|
9
|
+
artifact: Schema.Struct({
|
|
10
|
+
id: Schema.String,
|
|
11
|
+
type: Schema.String,
|
|
12
|
+
status: Schema.Literals(['active', 'archived']),
|
|
13
|
+
archivedAt: Schema.NullOr(Schema.String),
|
|
14
|
+
assigneeId: Schema.optionalKey(Schema.String),
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
// A refusal (4xx) means nothing changed. After any other failure once the
|
|
18
|
+
// request was sent, the change may have committed; repeating it is harmless.
|
|
19
|
+
class ArchiveFailure extends Error {
|
|
20
|
+
mayBeSaved;
|
|
21
|
+
constructor(message, mayBeSaved) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.mayBeSaved = mayBeSaved;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function reason(response) {
|
|
27
|
+
const text = await response.text();
|
|
28
|
+
let payload = null;
|
|
29
|
+
try {
|
|
30
|
+
payload = JSON.parse(text);
|
|
31
|
+
}
|
|
32
|
+
catch { /* not JSON */ }
|
|
33
|
+
if (isJsonErrorResponsePayload(response, payload) && payload.error.length > 0) {
|
|
34
|
+
return sanitizeTerminalText(payload.error).slice(0, 180);
|
|
35
|
+
}
|
|
36
|
+
// Never print a page body: a gateway's HTML says nothing useful.
|
|
37
|
+
return `the server returned a page that isn't JSON (status ${response.status})`;
|
|
38
|
+
}
|
|
39
|
+
function archiveRequest(request, timeoutMs) {
|
|
40
|
+
return Effect.suspend(() => {
|
|
41
|
+
let sent = false;
|
|
42
|
+
let timedOut = false;
|
|
43
|
+
return Effect.tryPromise({
|
|
44
|
+
try: async (signal) => {
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
const abort = () => controller.abort();
|
|
47
|
+
const timer = setTimeout(() => { timedOut = true; controller.abort(); }, timeoutMs);
|
|
48
|
+
if (signal.aborted)
|
|
49
|
+
abort();
|
|
50
|
+
else
|
|
51
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
52
|
+
try {
|
|
53
|
+
const init = {
|
|
54
|
+
method: 'PATCH',
|
|
55
|
+
headers: { 'content-type': 'application/json' },
|
|
56
|
+
body: JSON.stringify(request.body),
|
|
57
|
+
signal: controller.signal,
|
|
58
|
+
};
|
|
59
|
+
const response = request.fetcher
|
|
60
|
+
? (sent = true, await request.fetcher(request.path, init))
|
|
61
|
+
: await authedFetch(request.path, init, () => { sent = true; });
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
throw new ArchiveFailure(`Failed to ${request.label}: ${await reason(response)}`, response.status < 400 || response.status >= 500);
|
|
64
|
+
}
|
|
65
|
+
let data = null;
|
|
66
|
+
try {
|
|
67
|
+
data = JSON.parse(await response.text());
|
|
68
|
+
}
|
|
69
|
+
catch { /* decoded below */ }
|
|
70
|
+
const decoded = Schema.decodeUnknownResult(ArchiveReply)(data);
|
|
71
|
+
if (Result.isFailure(decoded)) {
|
|
72
|
+
throw new ArchiveFailure(`Failed to ${request.label}: the server's answer could not be read (status ${response.status})`, true);
|
|
73
|
+
}
|
|
74
|
+
return decoded.success;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
clearTimeout(timer);
|
|
78
|
+
signal.removeEventListener('abort', abort);
|
|
79
|
+
controller.abort();
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
catch: cause => {
|
|
83
|
+
if (timedOut)
|
|
84
|
+
return new ArchiveFailure(`Failed to ${request.label}: the request exceeded its deadline`, true);
|
|
85
|
+
if (cause instanceof ArchiveFailure)
|
|
86
|
+
return cause;
|
|
87
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
88
|
+
// Before sending (for example, not signed in) the message stands alone.
|
|
89
|
+
return new ArchiveFailure(sent ? `Failed to ${request.label}: ${message}` : message, sent);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}).pipe(Effect.mapError(failure => new Error(failure.mayBeSaved ? `${failure.message}\n${MAY_BE_SAVED}` : failure.message)));
|
|
93
|
+
}
|
|
94
|
+
// Nothing to clean up, so signals keep Node's default handling.
|
|
95
|
+
export async function archiveArtifact(request) {
|
|
96
|
+
const exit = await Effect.runPromiseExit(archiveRequest(request, datasetTransferTimeoutMs()));
|
|
97
|
+
if (Exit.isSuccess(exit))
|
|
98
|
+
return exit.value;
|
|
99
|
+
throw Cause.squash(exit.cause);
|
|
100
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-artifacts-cli.d.ts","sourceRoot":"","sources":["../src/archive-artifacts-cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAClE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClE;
|
|
1
|
+
{"version":3,"file":"archive-artifacts-cli.d.ts","sourceRoot":"","sources":["../src/archive-artifacts-cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAClE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClE;AAaD,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AA+CvC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,SAAS,QAexE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,SAAS,QAYtE;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,cAAc,EAAE,EACvB,KAAK,EAAE,SAAS,QAajB;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,EAAE,EACtB,KAAK,EAAE,SAAS,QAejB;AAyCD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,EAAE,kBAAkB,GACrB,OAAO,CAAC,IAAI,CAAC,CAiDf;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,EAAE,kBAAkB,GACrB,OAAO,CAAC,IAAI,CAAC,CAwEf"}
|
|
@@ -139,18 +139,14 @@ export async function archiveArtifactCommand(args, io) {
|
|
|
139
139
|
archived: action === 'archive',
|
|
140
140
|
...(assigneeId ? { assigneeId } : {}),
|
|
141
141
|
};
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
const { archiveArtifact } = await import('./archive-artifact-workflow.js');
|
|
143
|
+
const data = await archiveArtifact({
|
|
144
|
+
path: `/api/cli/archive-artifacts/${artifactType}/${encodeURIComponent(artifactId)}` +
|
|
145
|
+
`?${params.toString()}`,
|
|
146
|
+
body,
|
|
147
|
+
label: `${action} ${artifactType}`,
|
|
148
|
+
fetcher: io.fetcher,
|
|
148
149
|
});
|
|
149
|
-
if (!response.ok) {
|
|
150
|
-
throw new Error(`Failed to ${action} ${artifactType}: ` +
|
|
151
|
-
await extractErrorMessage(response));
|
|
152
|
-
}
|
|
153
|
-
const data = await parseJsonPayload(response, `${action === 'archive' ? 'Archive' : 'Restore'} ${artifactType}`);
|
|
154
150
|
if (io.json) {
|
|
155
151
|
io.print(JSON.stringify(data));
|
|
156
152
|
return;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
declare const ClonedDataset: Schema.Struct<{
|
|
3
|
+
readonly id: Schema.String;
|
|
4
|
+
readonly name: Schema.String;
|
|
5
|
+
readonly rowCount: Schema.Number;
|
|
6
|
+
readonly parentDatasetId: Schema.String;
|
|
7
|
+
}>;
|
|
8
|
+
export type ClonedDataset = typeof ClonedDataset.Type;
|
|
9
|
+
export declare function cloneDataset(datasetId: string, name: string | null): Promise<ClonedDataset>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=dataset-clone-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-clone-workflow.d.ts","sourceRoot":"","sources":["../src/dataset-clone-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,MAAM,EAAE,MAAM,QAAQ,CAAA;AAU5D,QAAA,MAAM,aAAa;;;;;EAKjB,CAAA;AAGF,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AA6ErD,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,CAIjG"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Cause, Effect, Exit, Result, Schema } from 'effect';
|
|
2
|
+
import { datasetTransferTimeoutMs } from './dataset-transfer-policy.js';
|
|
3
|
+
import { authedFetch } from './http.js';
|
|
4
|
+
import { parseJsonResponse } from './json-response.js';
|
|
5
|
+
// Loaded only through `await import(...)` from dataset-commands, like lock.
|
|
6
|
+
const SERVER_MAY_BE_CREATED = 'Dataset clone may already be created';
|
|
7
|
+
const ClonedDataset = Schema.Struct({
|
|
8
|
+
id: Schema.String,
|
|
9
|
+
name: Schema.String,
|
|
10
|
+
rowCount: Schema.Number,
|
|
11
|
+
parentDatasetId: Schema.String,
|
|
12
|
+
});
|
|
13
|
+
const CloneReply = Schema.Struct({ dataset: ClonedDataset });
|
|
14
|
+
const ErrorReply = Schema.Struct({ error: Schema.String });
|
|
15
|
+
// A refusal means nothing was cloned. After any other failure once the request
|
|
16
|
+
// was sent, the clone may exist. Unlike lock, cloning again is not harmless: it
|
|
17
|
+
// makes another copy, so the clone is never retried and the user is told to look.
|
|
18
|
+
class CloneFailure extends Error {
|
|
19
|
+
mayBeCreated;
|
|
20
|
+
constructor(message, mayBeCreated) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.mayBeCreated = mayBeCreated;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function mayBeCreatedGuidance(name) {
|
|
26
|
+
const target = name ? `a dataset named ${JSON.stringify(name)}` : 'a new dataset named after the source with " Copy" at the end';
|
|
27
|
+
return `The clone may already have been created. Run \`orizu datasets list\` and look for ${target} before cloning again: running clone again makes another copy.`;
|
|
28
|
+
}
|
|
29
|
+
// authedFetch raises this code only when it sent nothing, or when the server
|
|
30
|
+
// answered 401 and the changed credentials stopped a replay. Nothing was cloned.
|
|
31
|
+
function isAuthContextChange(cause) {
|
|
32
|
+
return cause instanceof Error && cause.message.startsWith('ORIZU_AUTH_CONTEXT_CHANGED:');
|
|
33
|
+
}
|
|
34
|
+
function serverError(text) {
|
|
35
|
+
try {
|
|
36
|
+
const decoded = Schema.decodeUnknownResult(ErrorReply)(JSON.parse(text));
|
|
37
|
+
return Result.isSuccess(decoded) ? decoded.success.error : null;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function cloneRequest(datasetId, name, timeoutMs) {
|
|
44
|
+
return Effect.suspend(() => {
|
|
45
|
+
let sent = false;
|
|
46
|
+
let timedOut = false;
|
|
47
|
+
return Effect.tryPromise({
|
|
48
|
+
try: async (signal) => {
|
|
49
|
+
const request = new AbortController();
|
|
50
|
+
const abort = () => request.abort();
|
|
51
|
+
const timer = setTimeout(() => { timedOut = true; request.abort(); }, timeoutMs);
|
|
52
|
+
if (signal.aborted)
|
|
53
|
+
abort();
|
|
54
|
+
else
|
|
55
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
56
|
+
try {
|
|
57
|
+
const response = await authedFetch(`/api/cli/datasets/${encodeURIComponent(datasetId)}/clone`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: { 'Content-Type': 'application/json' },
|
|
60
|
+
body: JSON.stringify(name ? { name } : {}),
|
|
61
|
+
signal: request.signal,
|
|
62
|
+
}, () => { sent = true; });
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
const text = await response.text();
|
|
65
|
+
const error = serverError(text);
|
|
66
|
+
// The app's own 5xx bodies name what happened; anything else at 5xx
|
|
67
|
+
// (a gateway page, an empty body) says nothing about the clone.
|
|
68
|
+
const mayBeCreated = response.status < 400 || error === SERVER_MAY_BE_CREATED || (response.status >= 500 && error === null);
|
|
69
|
+
throw new CloneFailure(`Clone failed: ${text}`, mayBeCreated);
|
|
70
|
+
}
|
|
71
|
+
const data = await parseJsonResponse(response, 'Dataset clone');
|
|
72
|
+
const decoded = Schema.decodeUnknownResult(CloneReply)(data);
|
|
73
|
+
if (Result.isFailure(decoded)) {
|
|
74
|
+
throw new CloneFailure(`Dataset clone returned an unexpected response (status ${response.status}).`, true);
|
|
75
|
+
}
|
|
76
|
+
return decoded.success.dataset;
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
clearTimeout(timer);
|
|
80
|
+
signal.removeEventListener('abort', abort);
|
|
81
|
+
request.abort();
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
catch: cause => {
|
|
85
|
+
if (timedOut)
|
|
86
|
+
return new CloneFailure('DATASET_TRANSFER_TIMEOUT: Dataset clone exceeded its deadline', true);
|
|
87
|
+
if (cause instanceof CloneFailure)
|
|
88
|
+
return cause;
|
|
89
|
+
return new CloneFailure(cause instanceof Error ? cause.message : String(cause), sent && !isAuthContextChange(cause));
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}).pipe(Effect.mapError(failure => new Error(failure.mayBeCreated ? `${failure.message}\n${mayBeCreatedGuidance(name)}` : failure.message)));
|
|
93
|
+
}
|
|
94
|
+
// Nothing to clean up, so signals keep Node's default handling.
|
|
95
|
+
export async function cloneDataset(datasetId, name) {
|
|
96
|
+
const exit = await Effect.runPromiseExit(cloneRequest(datasetId, name, datasetTransferTimeoutMs()));
|
|
97
|
+
if (Exit.isSuccess(exit))
|
|
98
|
+
return exit.value;
|
|
99
|
+
throw Cause.squash(exit.cause);
|
|
100
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset-commands.d.ts","sourceRoot":"","sources":["../src/dataset-commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dataset-commands.d.ts","sourceRoot":"","sources":["../src/dataset-commands.ts"],"names":[],"mappings":"AAuHA,iBAAe,oBAAoB,kBAkClC;AAED,iBAAe,oBAAoB,kBAYlC;AAED,iBAAe,mBAAmB,kBAcjC;AAED,iBAAe,qBAAqB,kBAsCnC;AAED,iBAAe,YAAY,kBAW1B;AAsBD,iBAAe,aAAa,kBAiC3B;AAED,iBAAe,WAAW,kBAwCzB;AAED,iBAAe,gBAAgB,kBA+B9B;AAgBD,iBAAe,eAAe,kBA6C7B;AAED,iBAAe,iBAAiB,kBAU/B;AAED,iBAAe,eAAe,kBA2B7B;AAED,iBAAe,iBAAiB,kBA2B/B;AA0BD,iBAAe,aAAa,kBAuB3B;AAED,iBAAe,WAAW,kBAuBzB;AAED,iBAAe,YAAY,kBAuB1B;AAED,iBAAe,mBAAmB,kBA0BjC;AAED,OAAO,EACL,aAAa,EACb,YAAY,EACZ,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,mBAAmB,GACpB,CAAA"}
|
package/dist/dataset-commands.js
CHANGED
|
@@ -5,9 +5,7 @@ import { createInterface } from 'readline/promises';
|
|
|
5
5
|
import { stdin as input, stdout as output } from 'process';
|
|
6
6
|
import { getArg, hasArg, expandHomePath, getPositionalArg, hasJsonFlag, getArchiveListStatus, cliArgs, isInteractiveTerminal, } from './command-line-arguments.js';
|
|
7
7
|
import { resolveProjectSlug, fetchDatasets, selectDatasetInteractively, selectTaskIdInteractively, } from './account-directory.js';
|
|
8
|
-
import { sanitizeTerminalText
|
|
9
|
-
import { authedFetch } from './http.js';
|
|
10
|
-
import { extractErrorMessage } from './error-response.js';
|
|
8
|
+
import { sanitizeTerminalText } from './json-response.js';
|
|
11
9
|
import { printJson, printLine } from './cli-console-output.js';
|
|
12
10
|
import { readJsonFile } from './app-commands.js';
|
|
13
11
|
import { printDatasetSummaries } from './archive-artifacts-cli.js';
|
|
@@ -51,14 +49,15 @@ function parseRatioFlag(name, fallback) {
|
|
|
51
49
|
}
|
|
52
50
|
return parsed;
|
|
53
51
|
}
|
|
54
|
-
|
|
52
|
+
// The app accepts 0 and stores seeds as 32-bit integers.
|
|
53
|
+
function parseSeedFlag(name, fallback) {
|
|
55
54
|
const value = getArg(name);
|
|
56
55
|
if (!value) {
|
|
57
56
|
return fallback;
|
|
58
57
|
}
|
|
59
58
|
const parsed = Number(value);
|
|
60
|
-
if (!Number.isInteger(parsed) || parsed
|
|
61
|
-
throw new Error(`${name} must be a
|
|
59
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 2147483647) {
|
|
60
|
+
throw new Error(`${name} must be a whole number from 0 to 2147483647`);
|
|
62
61
|
}
|
|
63
62
|
return parsed;
|
|
64
63
|
}
|
|
@@ -81,22 +80,6 @@ async function resolveDatasetIdForProject(datasetRef, projectArg) {
|
|
|
81
80
|
}
|
|
82
81
|
return matches[0].id;
|
|
83
82
|
}
|
|
84
|
-
async function requestDatasetVersionSnapshot(datasetId, options = {}) {
|
|
85
|
-
const response = await authedFetch(`/api/cli/datasets/${encodeURIComponent(datasetId)}/versions`, {
|
|
86
|
-
method: 'POST',
|
|
87
|
-
headers: { 'Content-Type': 'application/json' },
|
|
88
|
-
body: JSON.stringify({
|
|
89
|
-
...(options.versionLabel ? { versionLabel: options.versionLabel } : {}),
|
|
90
|
-
...(options.readmeMarkdown !== undefined && options.readmeMarkdown !== null
|
|
91
|
-
? { readmeMarkdown: options.readmeMarkdown }
|
|
92
|
-
: {}),
|
|
93
|
-
}),
|
|
94
|
-
});
|
|
95
|
-
if (!response.ok) {
|
|
96
|
-
throw new Error(`Failed to create dataset version: ${await extractErrorMessage(response)}`);
|
|
97
|
-
}
|
|
98
|
-
return parseJsonResponse(response, 'Dataset version create');
|
|
99
|
-
}
|
|
100
83
|
async function createDatasetVersion() {
|
|
101
84
|
const datasetId = getPositionalArg(3) || getArg('--dataset');
|
|
102
85
|
const versionLabel = getArg('--label') || getArg('--version-label') || null;
|
|
@@ -107,7 +90,8 @@ async function createDatasetVersion() {
|
|
|
107
90
|
}
|
|
108
91
|
const readmeMarkdown = readReadmeMarkdownFromArgs(usage);
|
|
109
92
|
const resolvedDatasetId = await resolveDatasetIdForProject(datasetId, project);
|
|
110
|
-
const
|
|
93
|
+
const { createDatasetVersionSnapshot } = await import('./dataset-version-workflow.js');
|
|
94
|
+
const data = await createDatasetVersionSnapshot(resolvedDatasetId, {
|
|
111
95
|
versionLabel,
|
|
112
96
|
readmeMarkdown,
|
|
113
97
|
});
|
|
@@ -166,42 +150,32 @@ async function createDatasetSplitSet() {
|
|
|
166
150
|
const splitSpec = splitFile ? readJsonFile(splitFile) : null;
|
|
167
151
|
const name = getArg('--name') || (typeof splitSpec?.name === 'string' ? splitSpec.name : 'default');
|
|
168
152
|
const strategy = getArg('--strategy') || (typeof splitSpec?.strategy === 'string' ? splitSpec.strategy : 'random');
|
|
169
|
-
|
|
153
|
+
// A file's seed goes to the app as written, so one that isn't a whole number
|
|
154
|
+
// is refused there instead of quietly replaced.
|
|
155
|
+
const seed = splitSpec && Object.prototype.hasOwnProperty.call(splitSpec, 'seed')
|
|
170
156
|
? splitSpec.seed
|
|
171
|
-
:
|
|
157
|
+
: parseSeedFlag('--seed', 1);
|
|
172
158
|
const train = parseRatioFlag('--train', 0.7);
|
|
173
159
|
const validation = parseRatioFlag('--validation', 0.2);
|
|
174
|
-
|
|
160
|
+
// Without --test, test takes whatever train and validation leave.
|
|
161
|
+
const test = getArg('--test') ? parseRatioFlag('--test', 0) : undefined;
|
|
175
162
|
if (!datasetVersionId) {
|
|
176
163
|
throw new Error('Usage: orizu datasets splits create <datasetVersionId> [--from-file <split.json>] [--name <name>] [--seed <n>] [--train <ratio>] [--validation <ratio>] [--test <ratio>] [--json]');
|
|
177
164
|
}
|
|
178
|
-
const
|
|
165
|
+
const { createSplitSet, splitRatioProblem } = await import('./dataset-split-create-workflow.js');
|
|
166
|
+
const ratioProblem = splitRatioProblem(train, validation, test);
|
|
167
|
+
if (ratioProblem)
|
|
168
|
+
throw new Error(ratioProblem);
|
|
169
|
+
const partitions = splitSpec && Object.prototype.hasOwnProperty.call(splitSpec, 'partitions') ? splitSpec.partitions : undefined;
|
|
179
170
|
const metadata = splitSpec && Object.prototype.hasOwnProperty.call(splitSpec, 'metadata')
|
|
180
171
|
? splitSpec.metadata
|
|
181
172
|
: undefined;
|
|
182
|
-
const
|
|
183
|
-
method: 'POST',
|
|
184
|
-
headers: { 'Content-Type': 'application/json' },
|
|
185
|
-
body: JSON.stringify({
|
|
186
|
-
name,
|
|
187
|
-
strategy,
|
|
188
|
-
seed,
|
|
189
|
-
train,
|
|
190
|
-
validation,
|
|
191
|
-
test,
|
|
192
|
-
partitions,
|
|
193
|
-
metadata,
|
|
194
|
-
}),
|
|
195
|
-
});
|
|
196
|
-
if (!response.ok) {
|
|
197
|
-
throw new Error(`Failed to create dataset split set: ${await response.text()}`);
|
|
198
|
-
}
|
|
199
|
-
const data = await parseJsonResponse(response, 'Dataset split set create');
|
|
173
|
+
const splitSetId = await createSplitSet({ versionId: datasetVersionId, name, strategy, seed, train, validation, test, partitions, metadata });
|
|
200
174
|
if (hasJsonFlag()) {
|
|
201
|
-
printJson({ split_set_id:
|
|
175
|
+
printJson({ split_set_id: splitSetId });
|
|
202
176
|
return;
|
|
203
177
|
}
|
|
204
|
-
printLine(`Created split set ${sanitizeTerminalText(
|
|
178
|
+
printLine(`Created split set ${sanitizeTerminalText(splitSetId)}`);
|
|
205
179
|
}
|
|
206
180
|
async function listDatasets() {
|
|
207
181
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
@@ -514,20 +488,13 @@ async function cloneDataset() {
|
|
|
514
488
|
const selected = await selectDatasetInteractively(projectArg);
|
|
515
489
|
datasetId = selected.datasetId;
|
|
516
490
|
}
|
|
517
|
-
const
|
|
518
|
-
|
|
519
|
-
headers: { 'Content-Type': 'application/json' },
|
|
520
|
-
body: JSON.stringify(name ? { name } : {}),
|
|
521
|
-
});
|
|
522
|
-
if (!response.ok) {
|
|
523
|
-
throw new Error(`Clone failed: ${await response.text()}`);
|
|
524
|
-
}
|
|
525
|
-
const data = await parseJsonResponse(response, 'Dataset clone');
|
|
491
|
+
const { cloneDataset: requestClone } = await import('./dataset-clone-workflow.js');
|
|
492
|
+
const dataset = await requestClone(datasetId, name ?? null);
|
|
526
493
|
if (hasJsonFlag()) {
|
|
527
|
-
printJson({ dataset
|
|
494
|
+
printJson({ dataset });
|
|
528
495
|
return;
|
|
529
496
|
}
|
|
530
|
-
printLine(`Cloned dataset ${sanitizeTerminalText(
|
|
497
|
+
printLine(`Cloned dataset ${sanitizeTerminalText(dataset.parentDatasetId)} -> ${sanitizeTerminalText(dataset.name)} (${sanitizeTerminalText(dataset.id)}). Row count: ${dataset.rowCount}`);
|
|
531
498
|
}
|
|
532
499
|
async function downloadAnnotations() {
|
|
533
500
|
let taskId = getArg('--task');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface SplitSetRequest {
|
|
2
|
+
versionId: string;
|
|
3
|
+
name: string;
|
|
4
|
+
strategy: string;
|
|
5
|
+
seed: unknown;
|
|
6
|
+
train: number;
|
|
7
|
+
validation: number;
|
|
8
|
+
/** Absent means "whatever train and validation leave". */
|
|
9
|
+
test: number | undefined;
|
|
10
|
+
partitions: unknown;
|
|
11
|
+
metadata: unknown;
|
|
12
|
+
}
|
|
13
|
+
/** The same rule the app enforces, checked before anything is sent. */
|
|
14
|
+
export declare function splitRatioProblem(train: number, validation: number, test: number | undefined): string | null;
|
|
15
|
+
export declare function createSplitSet(request: SplitSetRequest): Promise<string>;
|
|
16
|
+
//# sourceMappingURL=dataset-split-create-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-split-create-workflow.d.ts","sourceRoot":"","sources":["../src/dataset-split-create-workflow.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAID,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAM5G;AAsFD,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAI9E"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Cause, Effect, Exit, Result, Schema } from 'effect';
|
|
2
|
+
import { datasetTransferTimeoutMs } from './dataset-transfer-policy.js';
|
|
3
|
+
import { authedFetch } from './http.js';
|
|
4
|
+
import { parseJsonResponse } from './json-response.js';
|
|
5
|
+
// Loaded only through `await import(...)` from dataset-commands, like clone.
|
|
6
|
+
const SERVER_MAY_BE_CREATED = 'Dataset split set may already be created';
|
|
7
|
+
// Ratios like 0.7 + 0.2 + 0.1 don't add up to exactly 1 in floating point.
|
|
8
|
+
const RATIO_GAP = 1e-9;
|
|
9
|
+
const CreateReply = Schema.Struct({ splitSet: Schema.Struct({ id: Schema.String }) });
|
|
10
|
+
const ErrorReply = Schema.Struct({ error: Schema.String });
|
|
11
|
+
const shown = (value) => Math.round(value * 1e12) / 1e12;
|
|
12
|
+
/** The same rule the app enforces, checked before anything is sent. */
|
|
13
|
+
export function splitRatioProblem(train, validation, test) {
|
|
14
|
+
if (train + validation > 1 + RATIO_GAP)
|
|
15
|
+
return `--train plus --validation must not be more than 1 (they add up to ${shown(train + validation)})`;
|
|
16
|
+
if (test !== undefined && Math.abs(train + validation + test - 1) > RATIO_GAP) {
|
|
17
|
+
return `--train, --validation and --test must add up to 1 (they add up to ${shown(train + validation + test)})`;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
// A refusal means nothing was saved. After any other failure once the request
|
|
22
|
+
// was sent, the set may exist. The version allows one set per name, so running
|
|
23
|
+
// the same command again can't make a second copy; it is still never retried
|
|
24
|
+
// automatically, and the user is told how to check.
|
|
25
|
+
class SplitSetFailure extends Error {
|
|
26
|
+
mayBeCreated;
|
|
27
|
+
constructor(message, mayBeCreated) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.mayBeCreated = mayBeCreated;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function mayBeCreatedGuidance(request) {
|
|
33
|
+
return `The split set ${JSON.stringify(request.name)} may already have been created. Run \`orizu datasets splits list ${request.versionId}\` to check. Running the same command again is safe: a set with that name is refused, not duplicated.`;
|
|
34
|
+
}
|
|
35
|
+
// authedFetch raises this code only when it sent nothing, or when the server
|
|
36
|
+
// answered 401 and the changed credentials stopped a replay. Nothing was saved.
|
|
37
|
+
function isAuthContextChange(cause) {
|
|
38
|
+
return cause instanceof Error && cause.message.startsWith('ORIZU_AUTH_CONTEXT_CHANGED:');
|
|
39
|
+
}
|
|
40
|
+
function serverError(text) {
|
|
41
|
+
try {
|
|
42
|
+
const decoded = Schema.decodeUnknownResult(ErrorReply)(JSON.parse(text));
|
|
43
|
+
return Result.isSuccess(decoded) ? decoded.success.error : null;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function createRequest(request, timeoutMs) {
|
|
50
|
+
return Effect.suspend(() => {
|
|
51
|
+
let sent = false;
|
|
52
|
+
let timedOut = false;
|
|
53
|
+
return Effect.tryPromise({
|
|
54
|
+
try: async (signal) => {
|
|
55
|
+
const abortController = new AbortController();
|
|
56
|
+
const abort = () => abortController.abort();
|
|
57
|
+
const timer = setTimeout(() => { timedOut = true; abortController.abort(); }, timeoutMs);
|
|
58
|
+
if (signal.aborted)
|
|
59
|
+
abort();
|
|
60
|
+
else
|
|
61
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
62
|
+
try {
|
|
63
|
+
const response = await authedFetch(`/api/cli/dataset-versions/${encodeURIComponent(request.versionId)}/split-sets`, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: { 'Content-Type': 'application/json' },
|
|
66
|
+
body: JSON.stringify({
|
|
67
|
+
name: request.name,
|
|
68
|
+
strategy: request.strategy,
|
|
69
|
+
seed: request.seed,
|
|
70
|
+
train: request.train,
|
|
71
|
+
validation: request.validation,
|
|
72
|
+
test: request.test,
|
|
73
|
+
partitions: request.partitions,
|
|
74
|
+
metadata: request.metadata,
|
|
75
|
+
}),
|
|
76
|
+
signal: abortController.signal,
|
|
77
|
+
}, () => { sent = true; });
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const text = await response.text();
|
|
80
|
+
const error = serverError(text);
|
|
81
|
+
// The app's own 5xx bodies name what happened; anything else at 5xx
|
|
82
|
+
// (a gateway page, an empty body) says nothing about the set.
|
|
83
|
+
const mayBeCreated = response.status < 400 || error === SERVER_MAY_BE_CREATED || (response.status >= 500 && error === null);
|
|
84
|
+
throw new SplitSetFailure(`Failed to create dataset split set: ${text}`, mayBeCreated);
|
|
85
|
+
}
|
|
86
|
+
const data = await parseJsonResponse(response, 'Dataset split set create');
|
|
87
|
+
const decoded = Schema.decodeUnknownResult(CreateReply)(data);
|
|
88
|
+
if (Result.isFailure(decoded)) {
|
|
89
|
+
throw new SplitSetFailure(`Dataset split set create returned an unexpected response (status ${response.status}).`, true);
|
|
90
|
+
}
|
|
91
|
+
return decoded.success.splitSet.id;
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
signal.removeEventListener('abort', abort);
|
|
96
|
+
abortController.abort();
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
catch: cause => {
|
|
100
|
+
if (timedOut)
|
|
101
|
+
return new SplitSetFailure('DATASET_TRANSFER_TIMEOUT: Dataset split set create exceeded its deadline', sent);
|
|
102
|
+
if (cause instanceof SplitSetFailure)
|
|
103
|
+
return cause;
|
|
104
|
+
return new SplitSetFailure(cause instanceof Error ? cause.message : String(cause), sent && !isAuthContextChange(cause));
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}).pipe(Effect.mapError(failure => new Error(failure.mayBeCreated ? `${failure.message}\n${mayBeCreatedGuidance(request)}` : failure.message)));
|
|
108
|
+
}
|
|
109
|
+
// Nothing to clean up, so signals keep Node's default handling.
|
|
110
|
+
export async function createSplitSet(request) {
|
|
111
|
+
const exit = await Effect.runPromiseExit(createRequest(request, datasetTransferTimeoutMs()));
|
|
112
|
+
if (Exit.isSuccess(exit))
|
|
113
|
+
return exit.value;
|
|
114
|
+
throw Cause.squash(exit.cause);
|
|
115
|
+
}
|