@pipelex/sdk 0.49.0 → 0.51.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.
@@ -132,6 +132,26 @@ export interface MethodData {
132
132
  * same field on the list, where a method mid-erasure stays listed.
133
133
  */
134
134
  deletion_state?: MethodDeletionState | null;
135
+ /**
136
+ * The method this one was copied from, on a method `copyMethod` made; `null` on a method
137
+ * created afresh, and absent from a platform that predates copies. Written once, when the copy
138
+ * is made, and never rewritten. The list rows (`MethodSummary`) do not carry it.
139
+ */
140
+ copied_from?: MethodCopiedFrom | null;
141
+ }
142
+ /**
143
+ * The method a copy was made from, as it stood at the copy — `MethodData.copied_from`. Opaque ids
144
+ * only, never a name: the original may have changed or been erased since, and its organization
145
+ * may be one the reader does not belong to, so nothing here is a link the reader can follow
146
+ * unless they belong to that organization.
147
+ */
148
+ export interface MethodCopiedFrom {
149
+ /** The canonical id of the organization that holds the original. */
150
+ org_id: string;
151
+ /** The original's method id. */
152
+ method_id: string;
153
+ /** The digest of the original's draft the copy took; `null` for an empty draft. */
154
+ draft_digest: string | null;
135
155
  }
136
156
  /**
137
157
  * A saved method with its draft's files — what `getMethod` answers. `files` lists the draft's
@@ -357,10 +377,122 @@ export interface MethodVersionPage {
357
377
  items: MethodVersionSummary[];
358
378
  nextCursor: string | null;
359
379
  }
380
+ /**
381
+ * The copy — `copyMethod`, `POST /v1/methods/{id}/copy`. Its wire body is closed: the client
382
+ * sends these members and nothing else, a `null` reading as not given.
383
+ */
384
+ export interface MethodCopyInput {
385
+ /**
386
+ * The canonical id of the organization the copy is made in, where the caller is an admin or a
387
+ * member: the method's own organization for a duplicate, another team, or the caller's
388
+ * personal workspace.
389
+ */
390
+ destination_org_id: string;
391
+ /** The copy's name, under the creation's rules; the original's when omitted or `null`. */
392
+ name?: string | null;
393
+ /**
394
+ * The original's draft token (`MethodData.updated_at`) the caller last saw, echoed verbatim:
395
+ * a draft that moved since is refused with a `409` `method_update_conflict`, and nothing is
396
+ * copied. Omitted or `null`, the copy takes the draft as it stands when the request is served.
397
+ */
398
+ expected_draft_updated_at?: string | null;
399
+ }
400
+ /** What a copy did — the discriminant of `MethodCopyResult`. */
401
+ export type MethodCopyOutcome = "copied" | "refused";
402
+ /**
403
+ * Why a copy was refused: `bundle_names_other_storage`, a `.mthds` file of the draft holds a
404
+ * `pipelex-storage://` reference the destination cannot read, which every run there would refuse.
405
+ */
406
+ export type MethodCopyRefusalReason = "bundle_names_other_storage";
407
+ /** One stored file a bundle of the draft names that the destination cannot read. */
408
+ export interface BundleStorageReference {
409
+ /** The tree path of the `.mthds` file that holds the reference. */
410
+ path: string;
411
+ /** The `pipelex-storage://` reference as the file writes it, a malformed one included. */
412
+ uri: string;
413
+ }
414
+ /** A copy that was made: `method` is the copy, in the destination, `copied_from` included. */
415
+ export interface MethodCopied {
416
+ outcome: "copied";
417
+ method: MethodData;
418
+ /** How many saved examples the copy holds, each a new example at `input_revision` 1. */
419
+ examples_copied: number;
420
+ /** How many distinct stored files were copied into the destination for the copy's inputs. */
421
+ stored_files_copied: number;
422
+ }
423
+ /**
424
+ * A copy refused before anything was written: a bundle of the draft names stored files the
425
+ * destination cannot read. The person removes or replaces each reference in the original and
426
+ * copies again, since rewriting the bundle would change the author's code without asking them.
427
+ */
428
+ export interface MethodCopyRefused {
429
+ outcome: "refused";
430
+ reason: MethodCopyRefusalReason;
431
+ /** What was refused and what to do, for a person. */
432
+ message: string;
433
+ /** Every reference the destination cannot read, ordered by bundle path, then by reference. */
434
+ references: BundleStorageReference[];
435
+ }
436
+ /**
437
+ * The answer of `copyMethod`, a `200` discriminated on `outcome`, because a bundle the destination
438
+ * cannot run is a verdict about the method, not a failure of the request. Branch on `outcome`,
439
+ * never on the status: a destination the caller may not write to, a stale token, a method being
440
+ * deleted or a copy past its bounds are thrown as `ApiResponseError` instead, since they produce
441
+ * no verdict.
442
+ */
443
+ export type MethodCopyResult = MethodCopied | MethodCopyRefused;
444
+ /**
445
+ * The bound a `422` `method_copy_too_large` names, read from the refusal's
446
+ * `ApiResponseError.problemDocument.limit`: `max_stored_files`, the most distinct stored files one
447
+ * copy copies, or `max_stored_bytes`, the most bytes they add up to, each set per deployment; its
448
+ * `value`, and what the copy `reached`. Removing examples, or the files they hold, brings the copy
449
+ * under it.
450
+ */
451
+ export interface MethodCopyLimit {
452
+ name: "max_stored_files" | "max_stored_bytes";
453
+ value: number;
454
+ reached: number;
455
+ }
456
+ /** Query for one page of a method's copies. */
457
+ export interface ListMethodCopiesQuery {
458
+ /**
459
+ * Page size, from 1 to 100; the API defaults to 50 and refuses a `limit` outside that range
460
+ * with a `422`.
461
+ */
462
+ limit?: number;
463
+ /** Opaque `nextCursor` from the previous page. */
464
+ cursor?: string;
465
+ }
466
+ /**
467
+ * The original's record of one copy made of it — a row of `listMethodCopies`. It names the
468
+ * destination by its id alone, never its name, so the listing tells no reader the name of an
469
+ * organization they do not belong to: show a destination's name only from the reader's own
470
+ * memberships. The marker stays when its copy is erased, and the copy then reads as not found.
471
+ */
472
+ export interface MethodCopyMarker {
473
+ /** The copy's method id, in the destination organization. */
474
+ copy_method_id: string;
475
+ /** The canonical id of the organization the copy was made in. */
476
+ destination_org_id: string;
477
+ /** The canonical id of the member who made the copy. */
478
+ copied_by_user_id: string;
479
+ /** ISO 8601 UTC instant the copy's row was written. */
480
+ copied_at: string;
481
+ }
482
+ /**
483
+ * One page of a method's copies, in the order of the copies' ids, which says nothing of when each
484
+ * was made. `nextCursor` is opaque — pass it straight back to `listMethodCopies` to continue;
485
+ * `null` means this was the last page. A method never copied, and a copy, which names its
486
+ * original through `copied_from` and has no copies of its own, answer an empty page.
487
+ */
488
+ export interface MethodCopyPage {
489
+ items: MethodCopyMarker[];
490
+ nextCursor: string | null;
491
+ }
360
492
  /**
361
493
  * One saved example of a method — what `createMethodExample`, `getMethodExample`,
362
- * `updateMethodExample` and both arms of `recordMethodExampleLatestRun` answer, and a row of
363
- * `listMethodExamples`.
494
+ * `updateMethodExample` and both arms of `recordMethodExampleLatestRun` and
495
+ * `saveAssistantMethodExample` answer, and a row of `listMethodExamples`.
364
496
  */
365
497
  export interface MethodExample {
366
498
  /** The example's id, `ex_…`, minted by the platform. */
@@ -399,6 +531,13 @@ export interface MethodExample {
399
531
  created_at: string;
400
532
  /** ISO-8601 UTC instant of its last change: its name, its inputs or its latest run. */
401
533
  updated_at: string;
534
+ /**
535
+ * Whether the build assistant keeps this example's inputs current with its test inputs: `true`
536
+ * on an example the assistant's save created (`saveAssistantMethodExample`), `false` on every
537
+ * other, and `false` from the first inputs change that is not the assistant's own. A rename
538
+ * leaves it as it is.
539
+ */
540
+ kept_by_assistant: boolean;
402
541
  }
403
542
  /** The create — `createMethodExample`, `POST /v1/methods/{id}/examples`. */
404
543
  export interface MethodExampleCreateInput {
@@ -465,6 +604,49 @@ export interface MethodExampleLatestRunStale {
465
604
  * method being deleted are thrown as `ApiResponseError` instead.
466
605
  */
467
606
  export type MethodExampleLatestRunResult = MethodExampleLatestRunRecorded | MethodExampleLatestRunStale;
607
+ /**
608
+ * The build assistant's save — `saveAssistantMethodExample`,
609
+ * `POST /v1/methods/{id}/examples/assistant-save`: its new test inputs, and the example it read as
610
+ * its own with the revision it read it at, both or neither.
611
+ */
612
+ export interface MethodExampleAssistantSaveInput {
613
+ /** The name a new example takes, 1 to 200 characters and not blank; an example kept current keeps its own. */
614
+ name: string;
615
+ /** The assistant's test inputs, a JSON object; a `bigint` in them is sent as its exact digits. */
616
+ inputs: Record<string, unknown>;
617
+ /**
618
+ * The assistant's example the caller read, the method's newest with `kept_by_assistant` true,
619
+ * to keep current. Omitted, or `null`, the save creates a new example.
620
+ */
621
+ example_id?: string | null;
622
+ /** The `input_revision` the caller read that example at; given with `example_id` and only with it. */
623
+ input_revision?: number | null;
624
+ }
625
+ /** What an assistant save did — the discriminant of `MethodExampleAssistantSaveResult`. */
626
+ export type MethodExampleAssistantSaveOutcome = "kept" | "created";
627
+ /**
628
+ * The named example was still the assistant's at the revision read, and now holds the inputs;
629
+ * `example` is it as it now stands, its name untouched.
630
+ */
631
+ export interface MethodExampleAssistantKept {
632
+ outcome: "kept";
633
+ example: MethodExample;
634
+ }
635
+ /**
636
+ * A new example, flagged as the assistant's, holds the inputs under the save's `name`: none was
637
+ * named, or a person's edit, another save or a deletion took the named one first.
638
+ */
639
+ export interface MethodExampleAssistantCreated {
640
+ outcome: "created";
641
+ example: MethodExample;
642
+ }
643
+ /**
644
+ * The answer of `saveAssistantMethodExample`, a `200` discriminated on `outcome`. Finding that a
645
+ * person has taken the example is the expected course of events whenever a person edits the
646
+ * assistant's inputs while it works, so it is answered rather than thrown: remember the answer's
647
+ * `example` as the assistant's from then on.
648
+ */
649
+ export type MethodExampleAssistantSaveResult = MethodExampleAssistantKept | MethodExampleAssistantCreated;
468
650
  /** Query for one page of a method's examples. */
469
651
  export interface ListMethodExamplesQuery {
470
652
  /**
@@ -692,9 +874,17 @@ export interface UploadInput {
692
874
  */
693
875
  method_id?: string;
694
876
  }
877
+ /** The answer to `POST /v1/upload`: the stored file's reference, its name and its record. */
695
878
  export interface UploadedFile {
879
+ /** The file's `pipelex-storage://` reference. */
696
880
  uri: string;
881
+ /** The name as sent. */
697
882
  filename: string;
883
+ /**
884
+ * The file's record, `fl_<uuid7>`, written `stored`, as an upload grant's `file_id` is.
885
+ * Absent from a deployment that predates file records, which answers none.
886
+ */
887
+ file_id?: string;
698
888
  }
699
889
  /**
700
890
  * What an upload is recorded as: `uploaded`, a person's file, or `test`, a test input
@@ -704,41 +894,77 @@ export type UploadKind = "uploaded" | "test";
704
894
  /**
705
895
  * What an upload grant is requested for — `POST /v1/upload/grant`. The file is
706
896
  * described, never sent: its bytes go to storage with the grant, from wherever
707
- * they are held.
897
+ * they are held. `describeUpload` reads this description off a `File` or a `Blob`,
898
+ * its SHA-256 included.
708
899
  */
709
900
  export interface UploadGrantInput {
710
901
  /** The original filename with its extension; the stored object keeps the extension. */
711
902
  filename: string;
712
903
  /**
713
- * MIME type, signed into the grant so the upload must carry it. Omitted, `null`
714
- * or empty, none is signed — a browser's `File.type` is empty for a type it
715
- * does not know, and means the same.
904
+ * The MIME type the file is declared as. The platform types the stored object by
905
+ * the name's extension and never stores this one, which serves only a name with no
906
+ * extension. Omitted, `null` or empty, none is declared — a browser's `File.type` is
907
+ * empty for a type it does not know, and means the same.
716
908
  */
717
909
  content_type?: string | null;
718
910
  /** The file's exact size in bytes. The grant accepts a body of this size and no other. */
719
911
  size: number;
912
+ /**
913
+ * The SHA-256 of the file's bytes, as 64 lowercase hexadecimal digits. With it, the
914
+ * object is named after its bytes, so a file the organization already holds is not
915
+ * sent again: the grant answers `stored: true`. Without it, the grant always names a
916
+ * new object and asks for the bytes. Any other string is a `422`, and so is a `size`
917
+ * other than the one the organization holds those bytes at (`blob_mismatch`).
918
+ */
919
+ sha256?: string;
920
+ /** What the upload is recorded as; `uploaded` when omitted. */
921
+ kind?: UploadKind;
922
+ /**
923
+ * The bare catalog id of the method a `test` file is for, required with `kind: "test"`
924
+ * and refused without it.
925
+ */
926
+ method_id?: string;
720
927
  }
721
928
  /**
722
- * A presigned, create-only `PUT` for one new object in the caller's organization,
723
- * and the `pipelex-storage://` URI that object will carry. A bearer capability
724
- * until `expires_at`: whoever holds it can write that one object, once, so it is
929
+ * The answer to an upload grant request: the file's record and `pipelex-storage://`
930
+ * URI, and either the news that the organization already holds the bytes
931
+ * (`stored: true`) or a presigned, create-only `PUT` to send them with. **Branch on
932
+ * `stored`, never on whether `url` is present.** A grant with a target is a bearer
933
+ * capability until `expires_at`: whoever holds it can write that one object, so it is
725
934
  * never logged. `uploadWithGrant` (also on the browser-safe `@pipelex/sdk/upload`
726
- * entry) is the sender.
935
+ * entry) is the sender, and sends nothing for a stored grant.
727
936
  */
728
937
  export interface UploadGrant {
729
- /** The reference the object carries — it names nothing until the `PUT` has succeeded. */
938
+ /**
939
+ * The file's record, `fl_<uuid7>`, `stored` once the bytes are and `pending` before.
940
+ * Absent from a deployment that predates file records, which answers none.
941
+ */
942
+ file_id?: string;
943
+ /**
944
+ * The reference the file carries. With `stored: false`, it names nothing until the
945
+ * `PUT` has succeeded.
946
+ */
730
947
  uri: string;
731
- /** Where to `PUT` the file, as the raw request body. */
732
- url: string;
733
948
  /**
734
- * The signed headers to send unchanged: `If-None-Match: *`, the `Content-Type`
735
- * when one was declared, and the provenance `x-amz-meta-*` values. `Content-Length`
736
- * is signed too but is not listed — the body sets it, so the body must be
737
- * exactly the declared size.
949
+ * `true` when the organization already holds these bytes: nothing is to be sent, and
950
+ * `uri` and `file_id` name the file now. `false` when the bytes go to `url`. Absent from
951
+ * a deployment that predates hashed uploads, whose grant is always a target, so an
952
+ * absent `stored` reads as `false`, as `uploadWithGrant` reads it.
738
953
  */
739
- headers: Record<string, string>;
740
- /** ISO-8601 UTC instant after which storage refuses the `PUT`. */
741
- expires_at: string;
954
+ stored?: boolean;
955
+ /** Where to `PUT` the file, as the raw request body; `null` when `stored`. */
956
+ url: string | null;
957
+ /**
958
+ * The signed headers to send unchanged, `null` when `stored`: `If-None-Match: *`,
959
+ * the `Content-Type` the name's extension implies, the provenance `x-amz-meta-*`
960
+ * values and, when the grant was asked for with a `sha256`, the checksum
961
+ * `x-amz-checksum-sha256`, which storage holds the body to. `Content-Length` is
962
+ * signed too but is not listed — the body sets it, so the body must be exactly the
963
+ * declared size.
964
+ */
965
+ headers: Record<string, string> | null;
966
+ /** ISO-8601 UTC instant after which storage refuses the `PUT`; `null` when `stored`. */
967
+ expires_at: string | null;
742
968
  /** The largest file any grant allows, in bytes (the service's upload cap). */
743
969
  max_bytes: number;
744
970
  }
@@ -860,6 +1086,350 @@ export interface FilePage {
860
1086
  items: FileSummary[];
861
1087
  nextCursor: string | null;
862
1088
  }
1089
+ /**
1090
+ * For a file a run made, whether the run's result reaches it: `final`, an output of the run, or
1091
+ * `intermediate`, a file made along the way, which no list holds.
1092
+ */
1093
+ export type FileRole = "final" | "intermediate";
1094
+ /** Whether a file's bytes are stored: `stored`, or `pending` while an upload's bytes have not been seen. */
1095
+ export type FileState = "stored" | "pending";
1096
+ /**
1097
+ * One file's whole record — what `renameFile` answers, each record `getFilesByUri` lists, and the
1098
+ * `file` of a run's file entry; `getFile` answers it with its methods and uses (`FileDetail`). It
1099
+ * is a `FileSummary` with the members a list leaves out.
1100
+ */
1101
+ export interface FileRecord extends FileSummary {
1102
+ /**
1103
+ * The address the record was written under, once another run or an example took the file and
1104
+ * the platform copied it into the organization's `assets/`; `uri` is then the copy's. `null`
1105
+ * until then.
1106
+ */
1107
+ source_uri: string | null;
1108
+ /** The name the file arrived with, never changed: a rename changes `name` alone. */
1109
+ original_name: string;
1110
+ /**
1111
+ * The SHA-256 of the bytes in lowercase hexadecimal, or `null` for a file stored before every
1112
+ * writer sent one.
1113
+ */
1114
+ sha256: string | null;
1115
+ /** For a file a run made, `final` or `intermediate`; `null` for the other kinds. */
1116
+ role: FileRole | null;
1117
+ /** `stored`, or `pending` while an upload's bytes have not been seen. */
1118
+ state: FileState;
1119
+ }
1120
+ /** What holds an address a use links: a run that took it as an input, or an example that holds it. */
1121
+ export type FileUseHolderType = "run" | "example";
1122
+ /**
1123
+ * An address taken as an input by a run, or held by an example. A use names an address, not a
1124
+ * record, so every record holding the address shows the same uses; a file a run made names that
1125
+ * run in its `origin`, never as a use.
1126
+ */
1127
+ export interface FileUse {
1128
+ /** The `pipelex-storage://` address used. */
1129
+ uri: string;
1130
+ holder_type: FileUseHolderType;
1131
+ /** The run's id or the example's id. */
1132
+ holder_id: string;
1133
+ /** The method of the run or of the example; `null` for a run of no saved method. */
1134
+ method_id: string | null;
1135
+ /** ISO-8601 instant the use was recorded. */
1136
+ created_at: string;
1137
+ }
1138
+ /**
1139
+ * One page of a file's uses, the examples that hold its address first, then the runs that took
1140
+ * it. It is a member of `FileDetail`, as the platform serializes it: pass `next_cursor` back to
1141
+ * `getFile` as `usesCursor` for the next page; `null` means there is none.
1142
+ */
1143
+ export interface FileUsePage {
1144
+ items: FileUse[];
1145
+ next_cursor: string | null;
1146
+ }
1147
+ /** One file with what links it to the organization's methods, runs and examples — `getFile`. */
1148
+ export interface FileDetail extends FileRecord {
1149
+ /** The methods whose list of files holds this one, because one of their runs or examples took or made it. */
1150
+ method_ids: string[];
1151
+ /** One page of the file's uses. */
1152
+ uses: FileUsePage;
1153
+ }
1154
+ /** Query of `getFile`, for the page of the file's uses it answers. */
1155
+ export interface GetFileQuery {
1156
+ /** How many uses the page holds, from 1 to 200; the API defaults to 50. Sent as `uses_limit`. */
1157
+ usesLimit?: number;
1158
+ /** The previous answer's `uses.next_cursor`. Sent as `uses_cursor`. */
1159
+ usesCursor?: string;
1160
+ }
1161
+ /** Options of `getFilesByUri`. */
1162
+ export interface GetFilesByUriOptions {
1163
+ /**
1164
+ * The run whose input the address is: the records of the member who started it come first, so
1165
+ * a run's inputs show the name its starter gave the file. Sent as `run_id`.
1166
+ */
1167
+ runId?: string;
1168
+ }
1169
+ /**
1170
+ * The records holding one address — `getFilesByUri` — in the order a surface picks the one to
1171
+ * show, the first being it. Empty for an address no record holds, such as a file stored before
1172
+ * the platform kept records.
1173
+ */
1174
+ export interface FileRecordList {
1175
+ items: FileRecord[];
1176
+ }
1177
+ /** The rename — `renameFile`, `PATCH /v1/files/{file_id}`. */
1178
+ export interface FileRenameInput {
1179
+ /**
1180
+ * The new name, at most 512 characters. The platform removes the characters no list or header
1181
+ * can show, trims the ends, refuses a name with nothing left, and adds the file's own extension,
1182
+ * the one its `original_name` ends with, when the name does not end with it, case aside.
1183
+ */
1184
+ name: string;
1185
+ }
1186
+ /** One file to link — `linkFiles` — named by exactly one of its record's id and its address. */
1187
+ export type FileLinkTarget = {
1188
+ file_id: string;
1189
+ uri?: never;
1190
+ } | {
1191
+ uri: string;
1192
+ file_id?: never;
1193
+ };
1194
+ /**
1195
+ * Why one file got no link — a value, never a thrown error. `code` is `not_found` (an unknown file,
1196
+ * or one deleted meanwhile), `conflict` (a file whose upload has not finished), `invalid_storage_uri`
1197
+ * (a malformed address) or `forbidden` (another organization's address); `detail` is the sentence
1198
+ * a person reads.
1199
+ */
1200
+ export interface FileLinkError {
1201
+ code: string;
1202
+ detail: string;
1203
+ }
1204
+ /**
1205
+ * One requested file's link, or why it has none. Either the link members are set and `error` is
1206
+ * `null`, or `error` is set and they are `null`. Branch on `error`, never on the HTTP status: the
1207
+ * request is a `200` whenever every file got a verdict.
1208
+ */
1209
+ export type FileLink = {
1210
+ /**
1211
+ * The record linked: the one asked for, or for an address, the record whose name the link
1212
+ * carries; `null` for an address no record holds, a file stored before records existed.
1213
+ */
1214
+ file_id: string | null;
1215
+ /** The address the link reads. */
1216
+ uri: string;
1217
+ /** The name the download saves under, which the link's `Content-Disposition` carries. */
1218
+ name: string;
1219
+ /** The file's type, which decides whether a browser shows it in place or downloads it. */
1220
+ media_type: string;
1221
+ /** A presigned `GET` of the file, valid for fifteen minutes; a bearer capability, so keep it out of logs. */
1222
+ url: string;
1223
+ /** ISO-8601 UTC instant the link stops working. */
1224
+ expires_at: string;
1225
+ error: null;
1226
+ } | {
1227
+ /** The file id as requested, or `null` when the file was named by its address. */
1228
+ file_id: string | null;
1229
+ /** The address as requested, or `null` when the file was named by its id. */
1230
+ uri: string | null;
1231
+ name: null;
1232
+ media_type: null;
1233
+ url: null;
1234
+ expires_at: null;
1235
+ error: FileLinkError;
1236
+ };
1237
+ /** The answer of `linkFiles`: exactly one `FileLink` per requested file, in the request's order. */
1238
+ export interface FileLinksResult {
1239
+ items: FileLink[];
1240
+ }
1241
+ /**
1242
+ * Where an archive stands: `queued` and `building`, read it again shortly; `ready`, its `url`
1243
+ * downloads the zip; `failed`, its `failure` says why, and a new request is the remedy.
1244
+ */
1245
+ export type FileArchiveState = "queued" | "building" | "ready" | "failed";
1246
+ /** How an archive's files were chosen: `files`, by their ids, or `run`, as one run's files. */
1247
+ export type FileArchiveSource = "files" | "run";
1248
+ /**
1249
+ * Why an archive failed: `file_gone`, a selected file was deleted before the zip was ready;
1250
+ * `build_failed`, the build failed or did not finish within the hour. Asking again is the remedy
1251
+ * for both.
1252
+ */
1253
+ export type FileArchiveFailureCode = "file_gone" | "build_failed";
1254
+ /** What a failed archive says about its failure. */
1255
+ export interface FileArchiveFailure {
1256
+ code: FileArchiveFailureCode;
1257
+ /** A sentence for a person, naming the file when one was gone. */
1258
+ detail: string;
1259
+ }
1260
+ /**
1261
+ * One zip of an organization's files — what `requestFileArchive` (`queued`) and `getFileArchive`
1262
+ * answer. An archive is never a file: no list shows it, and it is gone a day after it was asked
1263
+ * for, past `expires_at`, when reading it answers `404`.
1264
+ */
1265
+ export interface FileArchive {
1266
+ /** The archive's id, `arc_…`. */
1267
+ archive_id: string;
1268
+ /** The name the zip downloads under, ending in `.zip`. */
1269
+ name: string;
1270
+ state: FileArchiveState;
1271
+ source: FileArchiveSource;
1272
+ /** The run whose files the archive holds, for a `run` archive; `null` otherwise. */
1273
+ run_id: string | null;
1274
+ /** How many files the zip holds. */
1275
+ file_count: number;
1276
+ /** The files' total size in bytes, before compression. */
1277
+ total_bytes: number;
1278
+ /** ISO-8601 instant the archive was asked for. */
1279
+ created_at: string;
1280
+ /** ISO-8601 instant after which the archive is gone and reads as unknown, a day after `created_at`. */
1281
+ expires_at: string;
1282
+ /** The zip's own size in bytes, once it is ready; `null` until then. */
1283
+ archive_bytes: number | null;
1284
+ /** ISO-8601 instant the zip was complete; `null` until then. */
1285
+ ready_at: string | null;
1286
+ /** Why the archive failed; `null` unless `state` is `failed`. */
1287
+ failure: FileArchiveFailure | null;
1288
+ /**
1289
+ * A presigned `GET` of the zip, valid for fifteen minutes and signed with a `Content-Disposition`
1290
+ * naming `name`, set only on a read of a `ready` archive; each read signs a fresh one. A bearer
1291
+ * capability, so keep it out of logs.
1292
+ */
1293
+ url: string | null;
1294
+ /** ISO-8601 instant `url` stops working; `null` without a link. */
1295
+ url_expires_at: string | null;
1296
+ }
1297
+ /**
1298
+ * The request — `requestFileArchive`, `POST /v1/files/archives` — naming the files by exactly one
1299
+ * of `file_ids` and `run_id`.
1300
+ *
1301
+ * - `file_ids`: any of the organization's files, in the order the zip holds them, at least one; an
1302
+ * id given twice is zipped once. At most 500 files once duplicates are removed and 1,000 ids
1303
+ * listed.
1304
+ * - `run_id`: a run of the organization, whose zip holds what went in and what came out, never a
1305
+ * file it made along the way nor an input given as a web link.
1306
+ *
1307
+ * `name` is the name the zip downloads under, `.zip` added when it does not end with it; omitted,
1308
+ * or with nothing usable left once the platform cleans it, the platform names it
1309
+ * `files-<run_id>.zip` or `files-<YYYYMMDD-HHMMSS>.zip`.
1310
+ */
1311
+ export type FileArchiveRequest = {
1312
+ file_ids: readonly string[];
1313
+ run_id?: never;
1314
+ name?: string;
1315
+ } | {
1316
+ run_id: string;
1317
+ file_ids?: never;
1318
+ name?: string;
1319
+ };
1320
+ /**
1321
+ * The cap a `422` `file_archive_too_large` names, read from the refusal's
1322
+ * `ApiResponseError.problemDocument.limit`: `max_files` (500) or `max_total_bytes`
1323
+ * (2,000,000,000), its `value`, and what the selection `reached`. For a run, the count stops as
1324
+ * soon as it passes the cap, so `reached` is one more than `max_files` and means "at least".
1325
+ */
1326
+ export interface FileArchiveLimit {
1327
+ name: "max_files" | "max_total_bytes";
1328
+ value: number;
1329
+ reached: number;
1330
+ }
1331
+ /**
1332
+ * The copy of a file into a method's draft — `copyFileIntoDraft`,
1333
+ * `POST /v1/methods/{id}/draft/files/from-file`, "Add to method files".
1334
+ */
1335
+ export interface DraftFileFromFileInput {
1336
+ /** The file to copy, one of the organization's, `fl_…`. */
1337
+ file_id: string;
1338
+ /** The tree path the file takes in the draft, such as `assets/logo.png`; a file already there is replaced. */
1339
+ path: string;
1340
+ /**
1341
+ * The draft token (`MethodData.updated_at`) the caller last read, echoed verbatim: a draft that
1342
+ * moved since is refused with a `409` `method_update_conflict`. Omitted, the file is added to the
1343
+ * draft as it stands when the request is served, never erasing another save.
1344
+ */
1345
+ expected_updated_at?: string;
1346
+ }
1347
+ /**
1348
+ * What the copy did in the organization's blob store, the field the answer is discriminated on:
1349
+ * `copied`, the bytes were copied under their SHA-256, or `already_held`, the store held them and
1350
+ * nothing was copied.
1351
+ */
1352
+ export type DraftFileBlob = "copied" | "already_held";
1353
+ /** The copied file as the draft's tree now names it. */
1354
+ export interface DraftFileAdded {
1355
+ /** Its tree path. */
1356
+ path: string;
1357
+ /** The SHA-256 of its bytes, in lowercase hexadecimal. */
1358
+ sha256: string;
1359
+ /** Its size in bytes. */
1360
+ size: number;
1361
+ }
1362
+ /**
1363
+ * The answer of `copyFileIntoDraft`, a `200` discriminated on `blob`; both arms carry the file as
1364
+ * the draft names it and the method as the draft write stored it, with its new draft token.
1365
+ */
1366
+ export interface DraftFileFromFileResult {
1367
+ blob: DraftFileBlob;
1368
+ file: DraftFileAdded;
1369
+ method: MethodData;
1370
+ }
1371
+ /** Whether a run's records are all written: `listed`, or `listing` while the platform is still recording them. */
1372
+ export type RunFilesState = "listing" | "listed";
1373
+ /** Where a file sits in its run: what went in, what came out, or what was made along the way. */
1374
+ export type RunFileMark = "input" | "final" | "intermediate";
1375
+ /** One file of a run, with its mark and the record a surface shows for it. */
1376
+ export interface RunFileEntry {
1377
+ mark: RunFileMark;
1378
+ /**
1379
+ * For an input given by its address, the run's input that held it; `null` for an inline input
1380
+ * and for the files the run made.
1381
+ */
1382
+ input_name: string | null;
1383
+ /**
1384
+ * The address the run took or wrote; a record a take moved to a copy says where it lives now in
1385
+ * its own `uri`.
1386
+ */
1387
+ uri: string;
1388
+ /**
1389
+ * The record a surface shows for the file: for an input, the one of the member who started the
1390
+ * run first, then the caller's, then the oldest. `null` for an input address no record holds,
1391
+ * such as a file stored before records existed.
1392
+ */
1393
+ file: FileRecord | null;
1394
+ }
1395
+ /** A web link the run's inputs held, which gets no record: the platform neither fetched nor kept what it served. */
1396
+ export interface RunInputLink {
1397
+ /** The run's input that held the link. */
1398
+ input_name: string;
1399
+ /** The link, as the run was given it. */
1400
+ url: string;
1401
+ /** Why the link matters to a replay of the run: it must still serve the same file. */
1402
+ warning: string;
1403
+ }
1404
+ /** Query of `listRunFiles`, paging the run's own records. */
1405
+ export interface ListRunFilesQuery {
1406
+ /** How many of the run's own records the page holds at most, from 1 to 200; the API defaults to 50. */
1407
+ limit?: number;
1408
+ /** Opaque `nextCursor` from the previous page. */
1409
+ cursor?: string;
1410
+ }
1411
+ /**
1412
+ * One page of a run's files, sorted by where they sit in the run — `listRunFiles`.
1413
+ *
1414
+ * The inputs given by their address and the web links come on the first page only; the run's own
1415
+ * records, its inline inputs, its final outputs and the files it made along the way, are paged by
1416
+ * address. `nextCursor` is opaque — pass it straight back to `listRunFiles`; `null` is the last
1417
+ * page. `state` is `listing` until the platform has recorded every file of the run, a few seconds
1418
+ * after it ends, so a client showing a run that just ended reads it again until it is `listed`.
1419
+ */
1420
+ export interface RunFilesPage {
1421
+ pipeline_run_id: string;
1422
+ state: RunFilesState;
1423
+ /** What went in: the inputs by address (first page only), then the inline inputs. */
1424
+ inputs: RunFileEntry[];
1425
+ /** What came out: the run's final outputs. */
1426
+ outputs: RunFileEntry[];
1427
+ /** What was made along the way. */
1428
+ intermediates: RunFileEntry[];
1429
+ /** The web links the inputs held (first page only). */
1430
+ links: RunInputLink[];
1431
+ nextCursor: string | null;
1432
+ }
863
1433
  /**
864
1434
  * A run's record — the base of `RunDetail`, which `getRunDetail` returns. The run-history list
865
1435
  * does not return it: its rows are the slimmer `RunHistoryItem`.