@deepraxis/cli 0.1.0-dev.5e0f28e → 0.1.0-dev.6898104
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/COMMANDS.md +5 -1
- package/dist/praxis.js +442 -137
- package/package.json +1 -1
package/COMMANDS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Generated by `bun run commands`. DO NOT EDIT.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
372 HTTP operations; 374 commands including aliases.
|
|
6
6
|
|
|
7
7
|
Environment: `PRAXIS_ENV=develop|production` (dev package defaults to `develop`; stable package defaults to `production`). No `--env` option.
|
|
8
8
|
|
|
@@ -232,6 +232,10 @@ Handwritten commands: `login`, `logout`, `whoami`, `org list`, `org switch <orga
|
|
|
232
232
|
| `praxis file get <file_id>` | `file.files.retrieve` | GET `/file/v1/files/{file_id}` | |
|
|
233
233
|
| `praxis file get-content <file_id>` | `file.files.retrieveContent` | GET `/file/v1/files/{file_id}/content` | |
|
|
234
234
|
| `praxis file list` | `file.files.list` | GET `/file/v1/files` | `--purpose`, `--param-limit`, `--order`, `--after`, `--scope-id`, `--before` |
|
|
235
|
+
| `praxis file upload cancel <upload_id>` | `file.uploads.cancel` | POST `/file/v1/uploads/{upload_id}/cancel` | |
|
|
236
|
+
| `praxis file upload complete <upload_id>` | `file.uploads.complete` | POST `/file/v1/uploads/{upload_id}/complete` | `--part-ids`, `--md5` |
|
|
237
|
+
| `praxis file upload create` | `file.uploads.create` | POST `/file/v1/uploads` | `--bytes`, `--filename`, `--mime-type`, `--purpose`, `--part-size` |
|
|
238
|
+
| `praxis file upload part create` | `file.uploads.parts.create` | POST `/file/v1/uploads/{upload_id}/parts` | `--upload`, `--part-number`, `--param-data` |
|
|
235
239
|
| `praxis knowledge vector-store create` | `knowledge.vectorStores.create` | POST `/knowledge/v1/vector_stores` | `--name`, `--file-ids`, `--description` |
|
|
236
240
|
| `praxis knowledge vector-store delete <vector_store_id>` | `knowledge.vectorStores.delete` | DELETE `/knowledge/v1/vector_stores/{vector_store_id}` | |
|
|
237
241
|
| `praxis knowledge vector-store event list` | `knowledge.vectorStores.events.list` | GET `/knowledge/v1/vector_stores/{vector_store_id}/events` | `--vector-store`, `--after-seq`, `--param-limit` |
|
package/dist/praxis.js
CHANGED
|
@@ -7743,7 +7743,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
|
|
|
7743
7743
|
resource: "file.files",
|
|
7744
7744
|
method: "create",
|
|
7745
7745
|
summary: "Upload file",
|
|
7746
|
-
description: 'Upload a file to reuse in conversations or attach to a knowledge base. Unlike OpenAI Files, uploads must be nonempty and at most
|
|
7746
|
+
description: 'Upload a file to reuse in conversations or attach to a knowledge base. Unlike OpenAI Files, uploads must be nonempty and at most 100000000 bytes, and only user_data, assistants and vision purposes are accepted. Send file bytes as a multipart file part, not a filename or file ID; in the SDK use a File or Blob, for example new File(["Return within 23 days."], "policy.txt", { type: "text/plain" }). Content determines the MIME type. Supported uploads include PDF, DOCX/XLSX/PPTX, PNG/JPEG/GIF/WebP, MP3/WAV/FLAC/OGG/M4A, MP4/WebM, and UTF-8 JSON/NDJSON/CSV/Markdown/plain text; empty, unsupported, oversized files and unsupported purposes return 400. Use Uploads for larger files. The purpose vision accepts only PNG, JPEG, GIF and WebP, while conversation images require user_data. The returned ID belongs to your tenant; upload alone does not ingest the file into Knowledge. Knowledge attachment has a lower limit of 100000000 bytes. Optionally set expires_after[anchor]=created_at with expires_after[seconds] (3600–2592000), or praxis[expires_in_seconds] (3600–7776000), never both. Without expiry, the file persists until deleted.',
|
|
7747
7747
|
http: "POST",
|
|
7748
7748
|
path: "/file/v1/files",
|
|
7749
7749
|
streaming: "no",
|
|
@@ -7758,7 +7758,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
|
|
|
7758
7758
|
name: "file",
|
|
7759
7759
|
type: "string",
|
|
7760
7760
|
required: true,
|
|
7761
|
-
description: "File bytes in one multipart file part, not a filename or file ID. The file must be nonempty and at most
|
|
7761
|
+
description: "File bytes in one multipart file part, not a filename or file ID. The file must be nonempty and at most 100000000 bytes; its content determines the MIME type."
|
|
7762
7762
|
},
|
|
7763
7763
|
{
|
|
7764
7764
|
name: "purpose",
|
|
@@ -7807,7 +7807,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
|
|
|
7807
7807
|
resource: "file.files",
|
|
7808
7808
|
method: "retrieve",
|
|
7809
7809
|
summary: "Retrieve file",
|
|
7810
|
-
description: "Retrieve metadata for a live file owned by your tenant. Use its
|
|
7810
|
+
description: "Retrieve metadata for a live file owned by your tenant. Use its file- ID from upload or list. Missing, deleted, expired and other-tenant files return 404; use the content endpoint to download the bytes.",
|
|
7811
7811
|
http: "GET",
|
|
7812
7812
|
path: "/file/v1/files/{file_id}",
|
|
7813
7813
|
streaming: "no",
|
|
@@ -7824,7 +7824,7 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
|
|
|
7824
7824
|
resource: "file.files",
|
|
7825
7825
|
method: "retrieveContent",
|
|
7826
7826
|
summary: "Retrieve file content",
|
|
7827
|
-
description: "Download the original bytes of a live file owned by your tenant. Supply its
|
|
7827
|
+
description: "Download the original bytes of a live file owned by your tenant. Supply its file- ID from upload or list. A single byte Range can return a partial response; a range outside the file returns 416. Missing, deleted, expired and other-tenant files return 404.",
|
|
7828
7828
|
http: "GET",
|
|
7829
7829
|
path: "/file/v1/files/{file_id}/content",
|
|
7830
7830
|
streaming: "no",
|
|
@@ -7837,6 +7837,152 @@ The default is return=minimal: success returns HTTP 201 with an empty body. Send
|
|
|
7837
7837
|
],
|
|
7838
7838
|
query: []
|
|
7839
7839
|
},
|
|
7840
|
+
{
|
|
7841
|
+
resource: "file.uploads",
|
|
7842
|
+
method: "create",
|
|
7843
|
+
summary: "Create an upload",
|
|
7844
|
+
description: "Start a multipart upload for a file larger than the 100000000-byte direct-upload limit. Supply the exact byte length, filename, MIME type and purpose. Unlike OpenAI, only user_data, assistants and vision are accepted. The API accepts up to 8000000000 bytes; the Console and SDK uploadFile helper cap files at 2 GiB. Add parts of at most 64000000 bytes and complete within one hour. Optional part_size enables fixed-size, retryable parts. expires_after applies to the resulting file (3600–7776000 seconds on this own face); without it the file persists until deleted.",
|
|
7845
|
+
http: "POST",
|
|
7846
|
+
path: "/file/v1/uploads",
|
|
7847
|
+
streaming: "no",
|
|
7848
|
+
pagination: false,
|
|
7849
|
+
pathParams: [],
|
|
7850
|
+
query: [],
|
|
7851
|
+
body: {
|
|
7852
|
+
required: true,
|
|
7853
|
+
fields: [
|
|
7854
|
+
{
|
|
7855
|
+
name: "bytes",
|
|
7856
|
+
type: "integer",
|
|
7857
|
+
required: true,
|
|
7858
|
+
description: "Exact complete file length in bytes, from 1 through 8000000000; the sum of completed parts must match."
|
|
7859
|
+
},
|
|
7860
|
+
{
|
|
7861
|
+
name: "filename",
|
|
7862
|
+
type: "string",
|
|
7863
|
+
required: true,
|
|
7864
|
+
description: "Filename for the resulting file, at most 255 UTF-8 bytes."
|
|
7865
|
+
},
|
|
7866
|
+
{
|
|
7867
|
+
name: "mime_type",
|
|
7868
|
+
type: "string",
|
|
7869
|
+
required: true,
|
|
7870
|
+
description: "Declared MIME type; validated against the assembled content."
|
|
7871
|
+
},
|
|
7872
|
+
{
|
|
7873
|
+
name: "purpose",
|
|
7874
|
+
type: "string",
|
|
7875
|
+
enum: [
|
|
7876
|
+
"user_data",
|
|
7877
|
+
"assistants",
|
|
7878
|
+
"vision"
|
|
7879
|
+
],
|
|
7880
|
+
required: true,
|
|
7881
|
+
description: "Use user_data for conversation attachments, assistants for assistant files, or vision for PNG, JPEG, GIF and WebP images."
|
|
7882
|
+
},
|
|
7883
|
+
{
|
|
7884
|
+
name: "expires_after",
|
|
7885
|
+
type: "object",
|
|
7886
|
+
required: false,
|
|
7887
|
+
description: "Optional expiry policy for the resulting file; omission retains the file until deletion."
|
|
7888
|
+
},
|
|
7889
|
+
{
|
|
7890
|
+
name: "part_size",
|
|
7891
|
+
type: "integer",
|
|
7892
|
+
required: false,
|
|
7893
|
+
description: "Optional fixed part size in bytes, 5242880–64000000. Requires part_number on every part; retries of identical bytes at the same number return the same part. Omit to use arbitrary-sized parts."
|
|
7894
|
+
}
|
|
7895
|
+
]
|
|
7896
|
+
}
|
|
7897
|
+
},
|
|
7898
|
+
{
|
|
7899
|
+
resource: "file.uploads",
|
|
7900
|
+
method: "cancel",
|
|
7901
|
+
summary: "Cancel an upload",
|
|
7902
|
+
description: "Cancel an unfinished upload using upload_id from create and release its reserved storage. Further parts and completion are rejected. Cancelling an already cancelled upload returns the same terminal result; a completed upload cannot be cancelled. Delete its resulting file instead.",
|
|
7903
|
+
http: "POST",
|
|
7904
|
+
path: "/file/v1/uploads/{upload_id}/cancel",
|
|
7905
|
+
streaming: "no",
|
|
7906
|
+
pagination: false,
|
|
7907
|
+
pathParams: [
|
|
7908
|
+
{
|
|
7909
|
+
name: "upload_id",
|
|
7910
|
+
sdkName: "upload_id"
|
|
7911
|
+
}
|
|
7912
|
+
],
|
|
7913
|
+
query: []
|
|
7914
|
+
},
|
|
7915
|
+
{
|
|
7916
|
+
resource: "file.uploads",
|
|
7917
|
+
method: "complete",
|
|
7918
|
+
summary: "Complete an upload",
|
|
7919
|
+
description: "Assemble the uploaded parts into a file. Supply upload_id from create and part_ids from addPart in file byte order; their sizes must total the declared bytes. Optional md5 verifies the assembled content. Retrying identical part_ids and normalized md5 returns the same result; different inputs return 409. Unlike OpenAI, completed can contain a file still processing (status uploaded). Poll files.retrieve using file.id until status processed (own face state active); error, expiry or 404 means processing failed and the file cannot be used.",
|
|
7920
|
+
http: "POST",
|
|
7921
|
+
path: "/file/v1/uploads/{upload_id}/complete",
|
|
7922
|
+
streaming: "no",
|
|
7923
|
+
pagination: false,
|
|
7924
|
+
pathParams: [
|
|
7925
|
+
{
|
|
7926
|
+
name: "upload_id",
|
|
7927
|
+
sdkName: "upload_id"
|
|
7928
|
+
}
|
|
7929
|
+
],
|
|
7930
|
+
query: [],
|
|
7931
|
+
body: {
|
|
7932
|
+
required: true,
|
|
7933
|
+
fields: [
|
|
7934
|
+
{
|
|
7935
|
+
name: "part_ids",
|
|
7936
|
+
type: "array",
|
|
7937
|
+
itemType: "string",
|
|
7938
|
+
required: true,
|
|
7939
|
+
description: "All part IDs in concatenation order, without duplicates. Fixed-size uploads require increasing part_number order."
|
|
7940
|
+
},
|
|
7941
|
+
{
|
|
7942
|
+
name: "md5",
|
|
7943
|
+
type: "string",
|
|
7944
|
+
required: false,
|
|
7945
|
+
description: "Optional whole-file MD5 as 32 hexadecimal characters; verified after assembly."
|
|
7946
|
+
}
|
|
7947
|
+
]
|
|
7948
|
+
}
|
|
7949
|
+
},
|
|
7950
|
+
{
|
|
7951
|
+
resource: "file.uploads.parts",
|
|
7952
|
+
method: "create",
|
|
7953
|
+
summary: "Add an upload part",
|
|
7954
|
+
description: "Send one nonempty part as the multipart data field, at most 64000000 bytes. Parts may arrive concurrently in any order. Use upload_id from create. For a fixed-size upload, supply part_number starting at 1 and exactly part_size bytes except for the final remainder; retry the same number with identical bytes to recover its part ID. Without part_size, each request creates a new part and part_number is ignored. Save the returned part IDs for complete.",
|
|
7955
|
+
http: "POST",
|
|
7956
|
+
path: "/file/v1/uploads/{upload_id}/parts",
|
|
7957
|
+
streaming: "no",
|
|
7958
|
+
pagination: false,
|
|
7959
|
+
multipart: true,
|
|
7960
|
+
pathParams: [
|
|
7961
|
+
{
|
|
7962
|
+
name: "upload_id",
|
|
7963
|
+
sdkName: "upload_id"
|
|
7964
|
+
}
|
|
7965
|
+
],
|
|
7966
|
+
query: [
|
|
7967
|
+
{
|
|
7968
|
+
name: "part_number",
|
|
7969
|
+
type: "integer",
|
|
7970
|
+
required: false,
|
|
7971
|
+
description: "Required when create set part_size; 1 through ceil(bytes / part_size). Ignored for general uploads."
|
|
7972
|
+
}
|
|
7973
|
+
],
|
|
7974
|
+
body: {
|
|
7975
|
+
required: true,
|
|
7976
|
+
fields: [
|
|
7977
|
+
{
|
|
7978
|
+
name: "data",
|
|
7979
|
+
type: "string",
|
|
7980
|
+
required: true,
|
|
7981
|
+
description: "Raw bytes of this part, nonempty and at most 64000000 bytes."
|
|
7982
|
+
}
|
|
7983
|
+
]
|
|
7984
|
+
}
|
|
7985
|
+
},
|
|
7840
7986
|
{
|
|
7841
7987
|
resource: "knowledge.vectorStores",
|
|
7842
7988
|
method: "list",
|
|
@@ -14743,6 +14889,232 @@ for more details.`
|
|
|
14743
14889
|
}
|
|
14744
14890
|
];
|
|
14745
14891
|
|
|
14892
|
+
// ../../packages/sdk/typescript/src/core/errors.ts
|
|
14893
|
+
function problemFrom(status, headers, body, statusText) {
|
|
14894
|
+
const value = body && typeof body === "object" ? body : {};
|
|
14895
|
+
const nested = value.error && typeof value.error === "object" ? value.error : {};
|
|
14896
|
+
const string = (v) => typeof v === "string" && v.trim() ? v : undefined;
|
|
14897
|
+
const fallback = statusText || { 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 408: "Request Timeout", 409: "Conflict", 413: "Payload Too Large", 415: "Unsupported Media Type", 422: "Unprocessable Entity", 429: "Too Many Requests", 500: "Internal Server Error", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Timeout" }[status] || `HTTP ${status}`;
|
|
14898
|
+
const detail = string(value.detail) ?? string(nested.message) ?? string(value.message) ?? string(body);
|
|
14899
|
+
const title = string(value.title) ?? fallback;
|
|
14900
|
+
const param = nested.param ?? value.param;
|
|
14901
|
+
return {
|
|
14902
|
+
status,
|
|
14903
|
+
message: detail ?? title,
|
|
14904
|
+
title,
|
|
14905
|
+
detail,
|
|
14906
|
+
code: string(value.code) ?? string(nested.code) ?? string(nested.type) ?? string(value.error_code),
|
|
14907
|
+
type: string(nested.type) ?? string(value.type),
|
|
14908
|
+
param: typeof param === "string" ? param : param === null || nested.param === null ? null : undefined,
|
|
14909
|
+
errors: Array.isArray(value.errors) ? value.errors : [],
|
|
14910
|
+
requestId: headers.get("x-request-id") ?? string(value.requestId) ?? string(value.request_id),
|
|
14911
|
+
raw: body
|
|
14912
|
+
};
|
|
14913
|
+
}
|
|
14914
|
+
|
|
14915
|
+
class PraxisError extends Error {
|
|
14916
|
+
status;
|
|
14917
|
+
code;
|
|
14918
|
+
type;
|
|
14919
|
+
title;
|
|
14920
|
+
detail;
|
|
14921
|
+
errors;
|
|
14922
|
+
requestId;
|
|
14923
|
+
param;
|
|
14924
|
+
raw;
|
|
14925
|
+
constructor(problem = {}, options) {
|
|
14926
|
+
super(problem.message ?? problem.detail ?? problem.title ?? `Praxis request failed${problem.status ? ` (${problem.status})` : ""}`, options);
|
|
14927
|
+
this.name = "PraxisError";
|
|
14928
|
+
this.status = problem.status;
|
|
14929
|
+
this.code = problem.code;
|
|
14930
|
+
this.type = problem.type;
|
|
14931
|
+
this.title = problem.title;
|
|
14932
|
+
this.detail = problem.detail;
|
|
14933
|
+
this.errors = problem.errors ?? [];
|
|
14934
|
+
this.requestId = problem.requestId;
|
|
14935
|
+
this.param = problem.param;
|
|
14936
|
+
this.raw = problem.raw;
|
|
14937
|
+
}
|
|
14938
|
+
static fromResponse(response, body) {
|
|
14939
|
+
return new PraxisError(problemFrom(response.status, response.headers, body, response.statusText));
|
|
14940
|
+
}
|
|
14941
|
+
}
|
|
14942
|
+
|
|
14943
|
+
class PraxisConnectionError extends PraxisError {
|
|
14944
|
+
constructor(cause) {
|
|
14945
|
+
super({ code: "CONNECTION_ERROR", title: "Unable to connect to Praxis" }, { cause });
|
|
14946
|
+
this.name = "PraxisConnectionError";
|
|
14947
|
+
}
|
|
14948
|
+
}
|
|
14949
|
+
|
|
14950
|
+
class PraxisTimeoutError extends PraxisError {
|
|
14951
|
+
constructor(timeoutMs) {
|
|
14952
|
+
super({ code: "TIMEOUT", title: `Praxis request exceeded ${timeoutMs} ms` });
|
|
14953
|
+
this.name = "PraxisTimeoutError";
|
|
14954
|
+
}
|
|
14955
|
+
}
|
|
14956
|
+
|
|
14957
|
+
// ../../packages/sdk/typescript/src/core/retry.ts
|
|
14958
|
+
function canRetry(request) {
|
|
14959
|
+
return request.method !== "POST" || Boolean(request.headers.get("Idempotency-Key")?.trim());
|
|
14960
|
+
}
|
|
14961
|
+
function retryAfterMs(value, now = Date.now()) {
|
|
14962
|
+
if (!value)
|
|
14963
|
+
return;
|
|
14964
|
+
if (/^\d+(?:\.\d+)?$/.test(value.trim()))
|
|
14965
|
+
return Number(value) * 1000;
|
|
14966
|
+
const date = Date.parse(value);
|
|
14967
|
+
return Number.isFinite(date) ? Math.max(0, date - now) : undefined;
|
|
14968
|
+
}
|
|
14969
|
+
function retryDelay(attempt, retryAfter, random = Math.random) {
|
|
14970
|
+
return retryAfterMs(retryAfter) ?? Math.min(30000, 500 * 2 ** attempt) * (0.5 + random() * 0.5);
|
|
14971
|
+
}
|
|
14972
|
+
function abortable(promise, signal) {
|
|
14973
|
+
signal.throwIfAborted();
|
|
14974
|
+
return new Promise((resolve, reject) => {
|
|
14975
|
+
const abort = () => reject(signal.reason);
|
|
14976
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
14977
|
+
promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
14978
|
+
});
|
|
14979
|
+
}
|
|
14980
|
+
function sleep(ms, signal) {
|
|
14981
|
+
signal.throwIfAborted();
|
|
14982
|
+
return new Promise((resolve, reject) => {
|
|
14983
|
+
const abort = () => {
|
|
14984
|
+
clearTimeout(timer);
|
|
14985
|
+
reject(signal.reason);
|
|
14986
|
+
};
|
|
14987
|
+
const timer = setTimeout(() => {
|
|
14988
|
+
signal.removeEventListener("abort", abort);
|
|
14989
|
+
resolve();
|
|
14990
|
+
}, ms);
|
|
14991
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
14992
|
+
});
|
|
14993
|
+
}
|
|
14994
|
+
async function fetchWithRetry(request, fetcher, options) {
|
|
14995
|
+
const eligible = canRetry(request);
|
|
14996
|
+
const wait = options.wait ?? sleep;
|
|
14997
|
+
for (let attempt = 0;; attempt++) {
|
|
14998
|
+
options.signal.throwIfAborted();
|
|
14999
|
+
let response;
|
|
15000
|
+
try {
|
|
15001
|
+
response = await abortable(fetcher(request.clone()), options.signal);
|
|
15002
|
+
} catch (cause) {
|
|
15003
|
+
options.signal.throwIfAborted();
|
|
15004
|
+
if (!eligible || attempt >= options.maxRetries)
|
|
15005
|
+
throw new PraxisConnectionError(cause);
|
|
15006
|
+
await wait(retryDelay(attempt, null, options.random), options.signal);
|
|
15007
|
+
continue;
|
|
15008
|
+
}
|
|
15009
|
+
const retriable = response.status === 408 || response.status === 429 || response.status >= 500 && response.status <= 599;
|
|
15010
|
+
if (!eligible || !retriable || attempt >= options.maxRetries)
|
|
15011
|
+
return response;
|
|
15012
|
+
const delay = retryDelay(attempt, response.headers.get("Retry-After"), options.random);
|
|
15013
|
+
await response.body?.cancel();
|
|
15014
|
+
await wait(delay, options.signal);
|
|
15015
|
+
}
|
|
15016
|
+
}
|
|
15017
|
+
|
|
15018
|
+
// ../../packages/sdk/typescript/src/helpers/file-upload.ts
|
|
15019
|
+
var MAX_RETRIES = 5;
|
|
15020
|
+
function retryable(error) {
|
|
15021
|
+
return error instanceof PraxisConnectionError || error instanceof PraxisTimeoutError || error instanceof SyntaxError || error instanceof PraxisError && (error.status === 408 || error.status === 429 || error.status !== undefined && error.status >= 500 && error.status <= 599);
|
|
15022
|
+
}
|
|
15023
|
+
async function retry(signal, operation) {
|
|
15024
|
+
for (let used = 0;; used++) {
|
|
15025
|
+
signal.throwIfAborted();
|
|
15026
|
+
try {
|
|
15027
|
+
return await operation();
|
|
15028
|
+
} catch (error) {
|
|
15029
|
+
signal.throwIfAborted();
|
|
15030
|
+
if (used >= MAX_RETRIES || !retryable(error))
|
|
15031
|
+
throw error;
|
|
15032
|
+
await sleep(500 * 2 ** used, signal);
|
|
15033
|
+
}
|
|
15034
|
+
}
|
|
15035
|
+
}
|
|
15036
|
+
async function uploadFile(client, file, options) {
|
|
15037
|
+
options.signal?.throwIfAborted();
|
|
15038
|
+
if (file.size < 1 || file.size > 2 * 1024 ** 3)
|
|
15039
|
+
throw new RangeError("File size must be 1 byte through 2 GiB");
|
|
15040
|
+
const partSize = options.partSize ?? 50 * 1024 ** 2;
|
|
15041
|
+
const concurrency = options.concurrency ?? 3;
|
|
15042
|
+
if (!Number.isSafeInteger(partSize) || partSize < 5 * 1024 ** 2 || partSize > 64000000)
|
|
15043
|
+
throw new RangeError("partSize must be an integer from 5242880 through 64000000");
|
|
15044
|
+
if (!Number.isSafeInteger(concurrency) || concurrency < 1)
|
|
15045
|
+
throw new RangeError("concurrency must be a positive integer");
|
|
15046
|
+
const filename = options.filename ?? (typeof File !== "undefined" && file instanceof File ? file.name : "upload");
|
|
15047
|
+
const work = new AbortController;
|
|
15048
|
+
const abort = () => work.abort(options.signal?.reason);
|
|
15049
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
15050
|
+
const signal = work.signal;
|
|
15051
|
+
const request = { signal, maxRetries: 0, timeoutMs: 120000 };
|
|
15052
|
+
let uploadId;
|
|
15053
|
+
const active = async (initial) => {
|
|
15054
|
+
let result = initial;
|
|
15055
|
+
for (let polls = 0;; polls++) {
|
|
15056
|
+
signal.throwIfAborted();
|
|
15057
|
+
if (result.state === "active")
|
|
15058
|
+
return result;
|
|
15059
|
+
if (result.state !== "processing")
|
|
15060
|
+
throw new PraxisError({ code: "FILE_PROCESSING_FAILED", message: `File ${result.id} is not active (${result.state})` });
|
|
15061
|
+
await sleep(Math.min(5000, 1000 * 2 ** polls), signal);
|
|
15062
|
+
result = await retry(signal, () => client.file.files.retrieve({ path: { file_id: result.id }, ...request }));
|
|
15063
|
+
}
|
|
15064
|
+
};
|
|
15065
|
+
try {
|
|
15066
|
+
signal.throwIfAborted();
|
|
15067
|
+
options.onProgress?.(0);
|
|
15068
|
+
if (file.size <= 32 * 1024 ** 2) {
|
|
15069
|
+
const result2 = await client.file.files.create({ body: { file: new File([file], filename, { type: file.type }), purpose: options.purpose }, ...request });
|
|
15070
|
+
options.onProgress?.(1);
|
|
15071
|
+
return await active(result2);
|
|
15072
|
+
}
|
|
15073
|
+
const upload = await client.file.uploads.create({ body: { bytes: file.size, filename, mime_type: file.type || "application/octet-stream", purpose: options.purpose, part_size: partSize }, ...request });
|
|
15074
|
+
uploadId = upload.id;
|
|
15075
|
+
signal.throwIfAborted();
|
|
15076
|
+
const path = { upload_id: uploadId };
|
|
15077
|
+
const count = Math.ceil(file.size / partSize);
|
|
15078
|
+
const ids = new Array(count);
|
|
15079
|
+
let cursor = 0, confirmed = 0;
|
|
15080
|
+
const worker = async () => {
|
|
15081
|
+
while (cursor < count) {
|
|
15082
|
+
signal.throwIfAborted();
|
|
15083
|
+
const index = cursor++;
|
|
15084
|
+
const chunk = file.slice(index * partSize, Math.min(file.size, (index + 1) * partSize));
|
|
15085
|
+
const part = await retry(signal, () => client.file.uploads.parts.create({ path, query: { part_number: index + 1 }, body: { data: new File([chunk], filename) }, ...request }));
|
|
15086
|
+
ids[index] = part.id;
|
|
15087
|
+
confirmed += chunk.size;
|
|
15088
|
+
options.onProgress?.(confirmed / file.size);
|
|
15089
|
+
}
|
|
15090
|
+
};
|
|
15091
|
+
const workers = Array.from({ length: Math.min(concurrency, count) }, worker);
|
|
15092
|
+
try {
|
|
15093
|
+
await Promise.all(workers);
|
|
15094
|
+
} catch (error) {
|
|
15095
|
+
work.abort();
|
|
15096
|
+
await Promise.allSettled(workers);
|
|
15097
|
+
throw error;
|
|
15098
|
+
}
|
|
15099
|
+
const result = await retry(signal, () => client.file.uploads.complete({ path, body: { part_ids: ids }, ...request }));
|
|
15100
|
+
if (result.error)
|
|
15101
|
+
throw new PraxisError({ code: result.error.code, message: result.error.message });
|
|
15102
|
+
if (result.status !== "completed" || !result.file)
|
|
15103
|
+
throw new PraxisError({ code: "INVALID_RESPONSE", message: "Complete did not return a completed Upload with a file" });
|
|
15104
|
+
return await active(result.file);
|
|
15105
|
+
} catch (error) {
|
|
15106
|
+
work.abort();
|
|
15107
|
+
if (uploadId) {
|
|
15108
|
+
await client.file.uploads.cancel({ path: { upload_id: uploadId }, maxRetries: 0, timeoutMs: 1e4 }).catch(() => {});
|
|
15109
|
+
}
|
|
15110
|
+
if (options.signal?.aborted)
|
|
15111
|
+
throw options.signal.reason;
|
|
15112
|
+
throw error;
|
|
15113
|
+
} finally {
|
|
15114
|
+
options.signal?.removeEventListener("abort", abort);
|
|
15115
|
+
}
|
|
15116
|
+
}
|
|
15117
|
+
|
|
14746
15118
|
// ../../packages/sdk/typescript/src/core/multipart.ts
|
|
14747
15119
|
function multipartBodySerializer(body) {
|
|
14748
15120
|
const data = new FormData;
|
|
@@ -14810,9 +15182,9 @@ function createSseClient({
|
|
|
14810
15182
|
...options
|
|
14811
15183
|
}) {
|
|
14812
15184
|
let lastEventId;
|
|
14813
|
-
const
|
|
15185
|
+
const sleep2 = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
14814
15186
|
const createStream = async function* () {
|
|
14815
|
-
let
|
|
15187
|
+
let retryDelay2 = sseDefaultRetryDelay ?? 3000;
|
|
14816
15188
|
let attempt = 0;
|
|
14817
15189
|
const signal = options.signal ?? new AbortController().signal;
|
|
14818
15190
|
while (true) {
|
|
@@ -14876,7 +15248,7 @@ function createSseClient({
|
|
|
14876
15248
|
} else if (line.startsWith("retry:")) {
|
|
14877
15249
|
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
|
|
14878
15250
|
if (!Number.isNaN(parsed)) {
|
|
14879
|
-
|
|
15251
|
+
retryDelay2 = parsed;
|
|
14880
15252
|
}
|
|
14881
15253
|
}
|
|
14882
15254
|
}
|
|
@@ -14904,7 +15276,7 @@ function createSseClient({
|
|
|
14904
15276
|
data,
|
|
14905
15277
|
event: eventName,
|
|
14906
15278
|
id: lastEventId,
|
|
14907
|
-
retry:
|
|
15279
|
+
retry: retryDelay2
|
|
14908
15280
|
});
|
|
14909
15281
|
if (dataLines.length) {
|
|
14910
15282
|
yield data;
|
|
@@ -14921,8 +15293,8 @@ function createSseClient({
|
|
|
14921
15293
|
if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
|
|
14922
15294
|
break;
|
|
14923
15295
|
}
|
|
14924
|
-
const backoff = Math.min(
|
|
14925
|
-
await
|
|
15296
|
+
const backoff = Math.min(retryDelay2 * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
|
|
15297
|
+
await sleep2(backoff);
|
|
14926
15298
|
}
|
|
14927
15299
|
}
|
|
14928
15300
|
};
|
|
@@ -16346,6 +16718,55 @@ var fileRetrieveFileContent = (options) => (options.client ?? client).get({
|
|
|
16346
16718
|
url: "/file/v1/files/{file_id}/content",
|
|
16347
16719
|
...options
|
|
16348
16720
|
});
|
|
16721
|
+
var fileCreateUpload = (options) => (options.client ?? client).post({
|
|
16722
|
+
security: [{
|
|
16723
|
+
key: "BearerAuth",
|
|
16724
|
+
scheme: "bearer",
|
|
16725
|
+
type: "http"
|
|
16726
|
+
}],
|
|
16727
|
+
url: "/file/v1/uploads",
|
|
16728
|
+
...options,
|
|
16729
|
+
headers: {
|
|
16730
|
+
"Content-Type": "application/json",
|
|
16731
|
+
...options.headers
|
|
16732
|
+
}
|
|
16733
|
+
});
|
|
16734
|
+
var fileAddUploadPart = (options) => (options.client ?? client).post({
|
|
16735
|
+
...formDataBodySerializer,
|
|
16736
|
+
security: [{
|
|
16737
|
+
key: "BearerAuth",
|
|
16738
|
+
scheme: "bearer",
|
|
16739
|
+
type: "http"
|
|
16740
|
+
}],
|
|
16741
|
+
url: "/file/v1/uploads/{upload_id}/parts",
|
|
16742
|
+
...options,
|
|
16743
|
+
headers: {
|
|
16744
|
+
"Content-Type": null,
|
|
16745
|
+
...options.headers
|
|
16746
|
+
}
|
|
16747
|
+
});
|
|
16748
|
+
var fileCompleteUpload = (options) => (options.client ?? client).post({
|
|
16749
|
+
security: [{
|
|
16750
|
+
key: "BearerAuth",
|
|
16751
|
+
scheme: "bearer",
|
|
16752
|
+
type: "http"
|
|
16753
|
+
}],
|
|
16754
|
+
url: "/file/v1/uploads/{upload_id}/complete",
|
|
16755
|
+
...options,
|
|
16756
|
+
headers: {
|
|
16757
|
+
"Content-Type": "application/json",
|
|
16758
|
+
...options.headers
|
|
16759
|
+
}
|
|
16760
|
+
});
|
|
16761
|
+
var fileCancelUpload = (options) => (options.client ?? client).post({
|
|
16762
|
+
security: [{
|
|
16763
|
+
key: "BearerAuth",
|
|
16764
|
+
scheme: "bearer",
|
|
16765
|
+
type: "http"
|
|
16766
|
+
}],
|
|
16767
|
+
url: "/file/v1/uploads/{upload_id}/cancel",
|
|
16768
|
+
...options
|
|
16769
|
+
});
|
|
16349
16770
|
var healthCheck = (options) => (options?.client ?? client).get({ url: "/meta/v1/health", ...options });
|
|
16350
16771
|
var metaMethodsSearch = (options) => (options?.client ?? client).get({ url: "/meta/v1/methods", ...options });
|
|
16351
16772
|
var metaMethodsRetrieve = (options) => (options.client ?? client).get({ url: "/meta/v1/methods/{name}", ...options });
|
|
@@ -21055,6 +21476,14 @@ function createFile(transport) {
|
|
|
21055
21476
|
list: bind(transport, fileListFiles),
|
|
21056
21477
|
retrieve: bind(transport, fileRetrieveFile),
|
|
21057
21478
|
retrieveContent: bind(transport, fileRetrieveFileContent)
|
|
21479
|
+
},
|
|
21480
|
+
uploads: {
|
|
21481
|
+
cancel: bind(transport, fileCancelUpload),
|
|
21482
|
+
complete: bind(transport, fileCompleteUpload),
|
|
21483
|
+
create: bind(transport, fileCreateUpload),
|
|
21484
|
+
parts: {
|
|
21485
|
+
create: bind(transport, (options) => fileAddUploadPart({ ...options, bodySerializer: multipartBodySerializer, headers: { "Content-Type": null, ...options.headers } }))
|
|
21486
|
+
}
|
|
21058
21487
|
}
|
|
21059
21488
|
};
|
|
21060
21489
|
}
|
|
@@ -21425,132 +21854,6 @@ var resourceFactories = {
|
|
|
21425
21854
|
vault: createVault
|
|
21426
21855
|
};
|
|
21427
21856
|
|
|
21428
|
-
// ../../packages/sdk/typescript/src/core/errors.ts
|
|
21429
|
-
function problemFrom(status, headers, body, statusText) {
|
|
21430
|
-
const value = body && typeof body === "object" ? body : {};
|
|
21431
|
-
const nested = value.error && typeof value.error === "object" ? value.error : {};
|
|
21432
|
-
const string = (v) => typeof v === "string" && v.trim() ? v : undefined;
|
|
21433
|
-
const fallback = statusText || { 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 408: "Request Timeout", 409: "Conflict", 413: "Payload Too Large", 415: "Unsupported Media Type", 422: "Unprocessable Entity", 429: "Too Many Requests", 500: "Internal Server Error", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Timeout" }[status] || `HTTP ${status}`;
|
|
21434
|
-
const detail = string(value.detail) ?? string(nested.message) ?? string(value.message) ?? string(body);
|
|
21435
|
-
const title = string(value.title) ?? fallback;
|
|
21436
|
-
const param = nested.param ?? value.param;
|
|
21437
|
-
return {
|
|
21438
|
-
status,
|
|
21439
|
-
message: detail ?? title,
|
|
21440
|
-
title,
|
|
21441
|
-
detail,
|
|
21442
|
-
code: string(value.code) ?? string(nested.code) ?? string(nested.type) ?? string(value.error_code),
|
|
21443
|
-
type: string(nested.type) ?? string(value.type),
|
|
21444
|
-
param: typeof param === "string" ? param : param === null || nested.param === null ? null : undefined,
|
|
21445
|
-
errors: Array.isArray(value.errors) ? value.errors : [],
|
|
21446
|
-
requestId: headers.get("x-request-id") ?? string(value.requestId) ?? string(value.request_id),
|
|
21447
|
-
raw: body
|
|
21448
|
-
};
|
|
21449
|
-
}
|
|
21450
|
-
|
|
21451
|
-
class PraxisError extends Error {
|
|
21452
|
-
status;
|
|
21453
|
-
code;
|
|
21454
|
-
type;
|
|
21455
|
-
title;
|
|
21456
|
-
detail;
|
|
21457
|
-
errors;
|
|
21458
|
-
requestId;
|
|
21459
|
-
param;
|
|
21460
|
-
raw;
|
|
21461
|
-
constructor(problem = {}, options) {
|
|
21462
|
-
super(problem.message ?? problem.detail ?? problem.title ?? `Praxis request failed${problem.status ? ` (${problem.status})` : ""}`, options);
|
|
21463
|
-
this.name = "PraxisError";
|
|
21464
|
-
this.status = problem.status;
|
|
21465
|
-
this.code = problem.code;
|
|
21466
|
-
this.type = problem.type;
|
|
21467
|
-
this.title = problem.title;
|
|
21468
|
-
this.detail = problem.detail;
|
|
21469
|
-
this.errors = problem.errors ?? [];
|
|
21470
|
-
this.requestId = problem.requestId;
|
|
21471
|
-
this.param = problem.param;
|
|
21472
|
-
this.raw = problem.raw;
|
|
21473
|
-
}
|
|
21474
|
-
static fromResponse(response, body) {
|
|
21475
|
-
return new PraxisError(problemFrom(response.status, response.headers, body, response.statusText));
|
|
21476
|
-
}
|
|
21477
|
-
}
|
|
21478
|
-
|
|
21479
|
-
class PraxisConnectionError extends PraxisError {
|
|
21480
|
-
constructor(cause) {
|
|
21481
|
-
super({ code: "CONNECTION_ERROR", title: "Unable to connect to Praxis" }, { cause });
|
|
21482
|
-
this.name = "PraxisConnectionError";
|
|
21483
|
-
}
|
|
21484
|
-
}
|
|
21485
|
-
|
|
21486
|
-
class PraxisTimeoutError extends PraxisError {
|
|
21487
|
-
constructor(timeoutMs) {
|
|
21488
|
-
super({ code: "TIMEOUT", title: `Praxis request exceeded ${timeoutMs} ms` });
|
|
21489
|
-
this.name = "PraxisTimeoutError";
|
|
21490
|
-
}
|
|
21491
|
-
}
|
|
21492
|
-
|
|
21493
|
-
// ../../packages/sdk/typescript/src/core/retry.ts
|
|
21494
|
-
function canRetry(request) {
|
|
21495
|
-
return request.method !== "POST" || Boolean(request.headers.get("Idempotency-Key")?.trim());
|
|
21496
|
-
}
|
|
21497
|
-
function retryAfterMs(value, now = Date.now()) {
|
|
21498
|
-
if (!value)
|
|
21499
|
-
return;
|
|
21500
|
-
if (/^\d+(?:\.\d+)?$/.test(value.trim()))
|
|
21501
|
-
return Number(value) * 1000;
|
|
21502
|
-
const date = Date.parse(value);
|
|
21503
|
-
return Number.isFinite(date) ? Math.max(0, date - now) : undefined;
|
|
21504
|
-
}
|
|
21505
|
-
function retryDelay(attempt, retryAfter, random = Math.random) {
|
|
21506
|
-
return retryAfterMs(retryAfter) ?? Math.min(30000, 500 * 2 ** attempt) * (0.5 + random() * 0.5);
|
|
21507
|
-
}
|
|
21508
|
-
function abortable(promise, signal) {
|
|
21509
|
-
signal.throwIfAborted();
|
|
21510
|
-
return new Promise((resolve, reject) => {
|
|
21511
|
-
const abort = () => reject(signal.reason);
|
|
21512
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
21513
|
-
promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
21514
|
-
});
|
|
21515
|
-
}
|
|
21516
|
-
function sleep(ms, signal) {
|
|
21517
|
-
signal.throwIfAborted();
|
|
21518
|
-
return new Promise((resolve, reject) => {
|
|
21519
|
-
const abort = () => {
|
|
21520
|
-
clearTimeout(timer);
|
|
21521
|
-
reject(signal.reason);
|
|
21522
|
-
};
|
|
21523
|
-
const timer = setTimeout(() => {
|
|
21524
|
-
signal.removeEventListener("abort", abort);
|
|
21525
|
-
resolve();
|
|
21526
|
-
}, ms);
|
|
21527
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
21528
|
-
});
|
|
21529
|
-
}
|
|
21530
|
-
async function fetchWithRetry(request, fetcher, options) {
|
|
21531
|
-
const eligible = canRetry(request);
|
|
21532
|
-
const wait = options.wait ?? sleep;
|
|
21533
|
-
for (let attempt = 0;; attempt++) {
|
|
21534
|
-
options.signal.throwIfAborted();
|
|
21535
|
-
let response;
|
|
21536
|
-
try {
|
|
21537
|
-
response = await abortable(fetcher(request.clone()), options.signal);
|
|
21538
|
-
} catch (cause) {
|
|
21539
|
-
options.signal.throwIfAborted();
|
|
21540
|
-
if (!eligible || attempt >= options.maxRetries)
|
|
21541
|
-
throw new PraxisConnectionError(cause);
|
|
21542
|
-
await wait(retryDelay(attempt, null, options.random), options.signal);
|
|
21543
|
-
continue;
|
|
21544
|
-
}
|
|
21545
|
-
const retriable = response.status === 408 || response.status === 429 || response.status >= 500 && response.status <= 599;
|
|
21546
|
-
if (!eligible || !retriable || attempt >= options.maxRetries)
|
|
21547
|
-
return response;
|
|
21548
|
-
const delay = retryDelay(attempt, response.headers.get("Retry-After"), options.random);
|
|
21549
|
-
await response.body?.cancel();
|
|
21550
|
-
await wait(delay, options.signal);
|
|
21551
|
-
}
|
|
21552
|
-
}
|
|
21553
|
-
|
|
21554
21857
|
// ../../packages/sdk/typescript/src/core/sse.ts
|
|
21555
21858
|
async function* parseSSE(body, options = {}) {
|
|
21556
21859
|
const reader = body.getReader();
|
|
@@ -21992,6 +22295,8 @@ class Praxis {
|
|
|
21992
22295
|
const transport = new Transport(options);
|
|
21993
22296
|
for (const [name, create] of Object.entries(resourceFactories)) {
|
|
21994
22297
|
const resource = create(transport);
|
|
22298
|
+
if (name === "file")
|
|
22299
|
+
Object.assign(resource, { uploadFile: (file, options2) => uploadFile(this, file, options2) });
|
|
21995
22300
|
if (name === "database")
|
|
21996
22301
|
Object.assign(resource, { count: (input) => count(transport, input) });
|
|
21997
22302
|
if (name === "application")
|
|
@@ -23534,7 +23839,7 @@ function startProgress(ctx, write = (text) => writeOutput({ stderr: text })) {
|
|
|
23534
23839
|
}
|
|
23535
23840
|
|
|
23536
23841
|
// src/main.ts
|
|
23537
|
-
var version = "0.1.0-dev.
|
|
23842
|
+
var version = "0.1.0-dev.6898104";
|
|
23538
23843
|
var commands = commandTree(operations);
|
|
23539
23844
|
var manual = [["login"], ["logout"], ["whoami"], ["org", "list"], ["org", "switch"], ["api"], ["skill"]];
|
|
23540
23845
|
function route(argv) {
|