primitive-admin 1.1.0-alpha.81 → 1.1.0-alpha.83
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/assets/skill/skills/primitive-platform/SKILL.md +12 -0
- package/dist/src/commands/documents.js +455 -22
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/functions.js +889 -76
- package/dist/src/commands/functions.js.map +1 -1
- package/dist/src/commands/locks.js +15 -1
- package/dist/src/commands/locks.js.map +1 -1
- package/dist/src/commands/prompts.js +19 -2
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/sync.d.ts +50 -0
- package/dist/src/commands/sync.js +587 -316
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/workflows.d.ts +1 -29
- package/dist/src/commands/workflows.js +8 -109
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +191 -2
- package/dist/src/lib/api-client.js +283 -7
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/config-object-descriptor.js +12 -4
- package/dist/src/lib/config-object-descriptor.js.map +1 -1
- package/dist/src/lib/document-ingest-artifact.d.ts +120 -0
- package/dist/src/lib/document-ingest-artifact.js +505 -0
- package/dist/src/lib/document-ingest-artifact.js.map +1 -0
- package/dist/src/lib/document-ingest-input.d.ts +51 -0
- package/dist/src/lib/document-ingest-input.js +132 -0
- package/dist/src/lib/document-ingest-input.js.map +1 -0
- package/dist/src/lib/document-ingest.d.ts +78 -0
- package/dist/src/lib/document-ingest.js +231 -0
- package/dist/src/lib/document-ingest.js.map +1 -0
- package/dist/src/lib/env-resolver-core.d.ts +2 -2
- package/dist/src/lib/env-resolver-core.js +2 -2
- package/dist/src/lib/function-bundle.d.ts +6 -0
- package/dist/src/lib/function-bundle.js +8 -0
- package/dist/src/lib/function-bundle.js.map +1 -1
- package/dist/src/lib/function-collect.d.ts +1 -1
- package/dist/src/lib/function-collect.js +16 -0
- package/dist/src/lib/function-collect.js.map +1 -1
- package/dist/src/lib/function-db-types.d.ts +4 -0
- package/dist/src/lib/function-db-types.js +46 -2
- package/dist/src/lib/function-db-types.js.map +1 -1
- package/dist/src/lib/function-document-types.d.ts +83 -0
- package/dist/src/lib/function-document-types.js +137 -0
- package/dist/src/lib/function-document-types.js.map +1 -1
- package/dist/src/lib/function-grants-preflight.js +5 -0
- package/dist/src/lib/function-grants-preflight.js.map +1 -1
- package/dist/src/lib/function-log-lines.d.ts +76 -0
- package/dist/src/lib/function-log-lines.js +160 -0
- package/dist/src/lib/function-log-lines.js.map +1 -0
- package/dist/src/lib/function-log-row.d.ts +29 -0
- package/dist/src/lib/function-log-row.js +73 -0
- package/dist/src/lib/function-log-row.js.map +1 -0
- package/dist/src/lib/function-log-tail.d.ts +51 -2
- package/dist/src/lib/function-log-tail.js +160 -13
- package/dist/src/lib/function-log-tail.js.map +1 -1
- package/dist/src/lib/function-run.d.ts +289 -0
- package/dist/src/lib/function-run.js +389 -0
- package/dist/src/lib/function-run.js.map +1 -0
- package/dist/src/lib/function-schema-codegen.d.ts +17 -9
- package/dist/src/lib/function-schema-codegen.js +30 -29
- package/dist/src/lib/function-schema-codegen.js.map +1 -1
- package/dist/src/lib/function-sync.d.ts +226 -30
- package/dist/src/lib/function-sync.js +731 -77
- package/dist/src/lib/function-sync.js.map +1 -1
- package/dist/src/lib/function-versions.d.ts +122 -0
- package/dist/src/lib/function-versions.js +182 -0
- package/dist/src/lib/function-versions.js.map +1 -0
- package/dist/src/lib/generated-config-surfaces.d.ts +561 -91
- package/dist/src/lib/generated-config-surfaces.js +1858 -287
- package/dist/src/lib/generated-config-surfaces.js.map +1 -1
- package/dist/src/lib/generated-sdk-types.d.ts +1 -1
- package/dist/src/lib/generated-sdk-types.js +1 -1
- package/dist/src/lib/generated-sdk-types.js.map +1 -1
- package/dist/src/lib/log-inspection.d.ts +2 -0
- package/dist/src/lib/log-inspection.js +4 -0
- package/dist/src/lib/log-inspection.js.map +1 -1
- package/dist/src/lib/output.d.ts +15 -0
- package/dist/src/lib/output.js +28 -0
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/prompt-schema-codegen.d.ts +94 -0
- package/dist/src/lib/prompt-schema-codegen.js +212 -0
- package/dist/src/lib/prompt-schema-codegen.js.map +1 -0
- package/dist/src/lib/snapshot-audit-source.d.ts +45 -0
- package/dist/src/lib/snapshot-audit-source.js +58 -0
- package/dist/src/lib/snapshot-audit-source.js.map +1 -0
- package/dist/src/lib/snapshot-audit-store.d.ts +52 -0
- package/dist/src/lib/snapshot-audit-store.js +196 -0
- package/dist/src/lib/snapshot-audit-store.js.map +1 -0
- package/dist/src/lib/snapshot-audit.d.ts +207 -0
- package/dist/src/lib/snapshot-audit.js +431 -0
- package/dist/src/lib/snapshot-audit.js.map +1 -0
- package/dist/src/lib/snapshot-build-rows.d.ts +60 -0
- package/dist/src/lib/snapshot-build-rows.js +87 -0
- package/dist/src/lib/snapshot-build-rows.js.map +1 -0
- package/dist/src/lib/snapshot-manifest-layout.d.ts +61 -0
- package/dist/src/lib/snapshot-manifest-layout.js +70 -0
- package/dist/src/lib/snapshot-manifest-layout.js.map +1 -0
- package/dist/src/lib/step-run-table.d.ts +43 -0
- package/dist/src/lib/step-run-table.js +129 -0
- package/dist/src/lib/step-run-table.js.map +1 -0
- package/dist/src/lib/swift-codegen/functionGenerator.d.ts +26 -13
- package/dist/src/lib/swift-codegen/functionGenerator.js +38 -27
- package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -1
- package/dist/src/lib/sync-selectors.d.ts +45 -2
- package/dist/src/lib/sync-selectors.js +66 -5
- package/dist/src/lib/sync-selectors.js.map +1 -1
- package/dist/src/lib/workflow-toml-validator.d.ts +9 -5
- package/dist/src/lib/workflow-toml-validator.js +18 -10
- package/dist/src/lib/workflow-toml-validator.js.map +1 -1
- package/package.json +2 -2
|
@@ -753,6 +753,31 @@ export declare class ApiClient {
|
|
|
753
753
|
items: any[];
|
|
754
754
|
nextCursor?: string | null;
|
|
755
755
|
}>;
|
|
756
|
+
/**
|
|
757
|
+
* A function run's step trace — #3348.
|
|
758
|
+
*
|
|
759
|
+
* The function-scoped twin of `getWorkflowStepRuns`, and it answers with the
|
|
760
|
+
* same rows in the same shape: `workflows/:idOrKey/runs/...` resolves its
|
|
761
|
+
* first argument to a workflow DEFINITION, which a function id and a function
|
|
762
|
+
* key alike miss, so a durable run's steps needed a route that addresses the
|
|
763
|
+
* run by the function that owns it.
|
|
764
|
+
*/
|
|
765
|
+
getFunctionStepRuns(appId: string, functionId: string, runId: string): Promise<{
|
|
766
|
+
items: any[];
|
|
767
|
+
}>;
|
|
768
|
+
/**
|
|
769
|
+
* End a function run that will not settle — #3348.
|
|
770
|
+
*
|
|
771
|
+
* `terminated: false` means the run had already settled and the route
|
|
772
|
+
* reported its outcome instead of overwriting it.
|
|
773
|
+
*/
|
|
774
|
+
terminateFunctionRun(appId: string, functionId: string, runId: string): Promise<{
|
|
775
|
+
runId: string;
|
|
776
|
+
status: string;
|
|
777
|
+
terminated: boolean;
|
|
778
|
+
endedAt?: string | null;
|
|
779
|
+
instanceTerminated?: boolean;
|
|
780
|
+
}>;
|
|
756
781
|
/**
|
|
757
782
|
* A function's invocation records, newest first — #3287.
|
|
758
783
|
*
|
|
@@ -763,13 +788,102 @@ export declare class ApiClient {
|
|
|
763
788
|
listFunctionLogs(appId: string, functionId: string, params?: {
|
|
764
789
|
limit?: number;
|
|
765
790
|
cursor?: string;
|
|
791
|
+
runId?: string;
|
|
766
792
|
}): Promise<{
|
|
767
793
|
items: any[];
|
|
768
794
|
nextCursor?: string | null;
|
|
769
795
|
}>;
|
|
770
|
-
|
|
796
|
+
/**
|
|
797
|
+
* One invocation record by its id — #3448, behind `functions logs
|
|
798
|
+
* --invocation <id>`.
|
|
799
|
+
*
|
|
800
|
+
* The id the invoke envelope answered with. A record that never existed,
|
|
801
|
+
* one of ANOTHER function, and one the seven-day TTL has expired all answer
|
|
802
|
+
* the same 404, which is what the listing's own filter promises.
|
|
803
|
+
*/
|
|
804
|
+
getFunctionLog(appId: string, functionId: string, invocationId: string): Promise<any>;
|
|
805
|
+
/**
|
|
806
|
+
* One function run, RECONCILED against the engine — #3448, what
|
|
807
|
+
* `functions runs wait` polls.
|
|
808
|
+
*
|
|
809
|
+
* NOT the runs listing: that reports the STORED status, and a durable run's
|
|
810
|
+
* row stays `running` until something asks the engine, so a wait built on it
|
|
811
|
+
* would never settle.
|
|
812
|
+
*/
|
|
813
|
+
getFunctionRun(appId: string, functionId: string, runId: string): Promise<{
|
|
814
|
+
status: any;
|
|
815
|
+
run: any;
|
|
816
|
+
slice?: any;
|
|
817
|
+
}>;
|
|
818
|
+
/**
|
|
819
|
+
* The operator's own APP user — #3448 D3448-009.
|
|
820
|
+
*
|
|
821
|
+
* `getMe()` reads the ADMIN profile (`/admin/api/me`); this is the
|
|
822
|
+
* app-scoped route, which answers the app user `requireAppPermission`
|
|
823
|
+
* provisions for an admin and the `appRole` it gave them. That is the
|
|
824
|
+
* identity a `functions invoke` runs under by default, and printing it is
|
|
825
|
+
* how an operator knows their call bypassed the function's `access` gate.
|
|
826
|
+
*/
|
|
827
|
+
getAppProfile(appId: string): Promise<{
|
|
828
|
+
userId: string;
|
|
829
|
+
email: string | null;
|
|
830
|
+
name?: string | null;
|
|
831
|
+
appRole: string;
|
|
832
|
+
appId: string;
|
|
833
|
+
}>;
|
|
834
|
+
/**
|
|
835
|
+
* Invoke a function and hand back the ANSWER, whatever its HTTP status —
|
|
836
|
+
* #3448 D3448-010.
|
|
837
|
+
*
|
|
838
|
+
* `request` throws an `ApiError` on any non-2xx, which is right for every
|
|
839
|
+
* other verb and wrong for this one: a 429 carries a `Retry-After` an
|
|
840
|
+
* operator needs to see, and a 409 mode mismatch carries the version's real
|
|
841
|
+
* mode. Rendering those from an exception means re-deriving what the server
|
|
842
|
+
* already said. So this returns the envelope with its status and its retry
|
|
843
|
+
* hint, and throws only when the request did not complete at all.
|
|
844
|
+
*
|
|
845
|
+
* `bearer` is the `--user` path's minted token; absent, the CLI's own
|
|
846
|
+
* credentials. `mode` is ALWAYS sent (D3448-012): it is what makes the
|
|
847
|
+
* server, not the CLI, the authority on a wrong verb.
|
|
848
|
+
*/
|
|
849
|
+
invokeFunction(appId: string, functionKey: string, body: Record<string, unknown>, options?: {
|
|
850
|
+
bearer?: string;
|
|
851
|
+
asSystem?: boolean;
|
|
852
|
+
/**
|
|
853
|
+
* Which runtime this call means — #3482. The ROUTE is the selector:
|
|
854
|
+
* `POST functions/{key}` runs the function inside the request and
|
|
855
|
+
* `POST functions/{key}/start` runs it as a task. The admin-only system
|
|
856
|
+
* door is ONE route for both, so `--as system` keeps naming its runtime
|
|
857
|
+
* in the body (F-3482-007); phase 7's rename may fold it.
|
|
858
|
+
*/
|
|
859
|
+
runtime?: "request" | "task";
|
|
860
|
+
}): Promise<{
|
|
861
|
+
httpStatus: number;
|
|
862
|
+
retryAfterSeconds: number | null;
|
|
863
|
+
body: any;
|
|
864
|
+
}>;
|
|
865
|
+
/**
|
|
866
|
+
* A function's versions, newest first (#3462).
|
|
867
|
+
*
|
|
868
|
+
* Paging is opt-in on the server: with no `limit` and no `cursor` every
|
|
869
|
+
* version comes back, which is what this method did before paging existed and
|
|
870
|
+
* what an already-installed CLI still asks for. A caller that passes either
|
|
871
|
+
* gets the shared `{ items, hasMore, nextCursor }` page.
|
|
872
|
+
*/
|
|
873
|
+
listFunctionConfigs(appId: string, functionId: string, options?: {
|
|
874
|
+
limit?: number;
|
|
875
|
+
cursor?: string;
|
|
876
|
+
}): Promise<{
|
|
771
877
|
items: any[];
|
|
878
|
+
hasMore: boolean;
|
|
879
|
+
nextCursor?: string | null;
|
|
772
880
|
}>;
|
|
881
|
+
/**
|
|
882
|
+
* Point the function at one of its OWN existing versions (#3462). Creates no
|
|
883
|
+
* version; the activated version's capabilities, limits and triggers apply
|
|
884
|
+
* from the next call.
|
|
885
|
+
*/
|
|
886
|
+
activateFunctionConfig(appId: string, functionId: string, configId: string): Promise<any>;
|
|
773
887
|
getFunctionConfig(appId: string, functionId: string, configId: string): Promise<any>;
|
|
774
888
|
/**
|
|
775
889
|
* The stored envelope: the authored TOML bytes, every source file and the
|
|
@@ -838,7 +952,11 @@ export declare class ApiClient {
|
|
|
838
952
|
locks: any[];
|
|
839
953
|
}>;
|
|
840
954
|
getLockStatus(appId: string, key: string): Promise<any>;
|
|
841
|
-
|
|
955
|
+
/**
|
|
956
|
+
* #3562 — `owner` is sent only when one was given, so a call that names none
|
|
957
|
+
* composes byte for byte the body it always did.
|
|
958
|
+
*/
|
|
959
|
+
acquireLock(appId: string, key: string, ttlMs: number, owner?: string): Promise<any>;
|
|
842
960
|
releaseLock(appId: string, key: string, handleId: string): Promise<any>;
|
|
843
961
|
listCronTriggers(appId: string): Promise<{
|
|
844
962
|
items: any[];
|
|
@@ -1958,6 +2076,62 @@ export declare class ApiClient {
|
|
|
1958
2076
|
* record/model/blob counts, approximate size, and last-modified timestamp.
|
|
1959
2077
|
*/
|
|
1960
2078
|
getDocumentStats(appId: string, documentId: string): Promise<any>;
|
|
2079
|
+
/**
|
|
2080
|
+
* A large document's snapshot builds, newest first, one page (#3432).
|
|
2081
|
+
* `GET documents/:id/snapshots` → `{ items, hasMore, nextCursor? }`.
|
|
2082
|
+
*/
|
|
2083
|
+
listDocumentSnapshots(appId: string, documentId: string, options?: {
|
|
2084
|
+
limit?: number;
|
|
2085
|
+
cursor?: string;
|
|
2086
|
+
}): Promise<{
|
|
2087
|
+
items: any[];
|
|
2088
|
+
hasMore: boolean;
|
|
2089
|
+
nextCursor?: string;
|
|
2090
|
+
}>;
|
|
2091
|
+
/**
|
|
2092
|
+
* A large document's bulk-load sessions, newest first (#3434, criterion 9).
|
|
2093
|
+
*
|
|
2094
|
+
* Read-only, through the document read helper's app-admin arm — the same
|
|
2095
|
+
* door the snapshot readers use. The action verb `documents ingest` is
|
|
2096
|
+
* #3435's; these two are the operator's window onto what a session did.
|
|
2097
|
+
*/
|
|
2098
|
+
listDocumentIngests(appId: string, documentId: string, options?: {
|
|
2099
|
+
limit?: number;
|
|
2100
|
+
cursor?: string;
|
|
2101
|
+
}): Promise<{
|
|
2102
|
+
items: any[];
|
|
2103
|
+
hasMore: boolean;
|
|
2104
|
+
nextCursor?: string;
|
|
2105
|
+
}>;
|
|
2106
|
+
/** One bulk-load session's status (#3434). */
|
|
2107
|
+
getDocumentIngest(appId: string, documentId: string, sessionId: string): Promise<any>;
|
|
2108
|
+
/** Open a bulk-load session on a large document (#3435, criterion 9). */
|
|
2109
|
+
createDocumentIngest(appId: string, documentId: string): Promise<any>;
|
|
2110
|
+
/**
|
|
2111
|
+
* Upload one chunk of a bulk-load session's artifact (#3435).
|
|
2112
|
+
*
|
|
2113
|
+
* `multipart/form-data`: the eight descriptor fields as text parts and the
|
|
2114
|
+
* gzipped bytes as one file part named `chunk`. No `Content-Type` is set on
|
|
2115
|
+
* the request — fetch supplies the boundary, and a header written by hand
|
|
2116
|
+
* would name one the body does not use.
|
|
2117
|
+
*/
|
|
2118
|
+
uploadDocumentIngestChunk(appId: string, documentId: string, sessionId: string, chunk: {
|
|
2119
|
+
model: string;
|
|
2120
|
+
index: number;
|
|
2121
|
+
rows: number;
|
|
2122
|
+
bytes: number;
|
|
2123
|
+
rawBytes: number;
|
|
2124
|
+
sha256: string;
|
|
2125
|
+
firstId: string;
|
|
2126
|
+
lastId: string;
|
|
2127
|
+
body: Buffer;
|
|
2128
|
+
}): Promise<any>;
|
|
2129
|
+
/** Freeze a session's manifest and hand it to the pipeline (#3435). */
|
|
2130
|
+
commitDocumentIngest(appId: string, documentId: string, sessionId: string): Promise<any>;
|
|
2131
|
+
/** Give a session up; allowed until the swap (#3435). */
|
|
2132
|
+
abortDocumentIngest(appId: string, documentId: string, sessionId: string): Promise<any>;
|
|
2133
|
+
/** One snapshot build with its verification result (#3432). */
|
|
2134
|
+
getDocumentSnapshot(appId: string, documentId: string, buildId: string): Promise<any>;
|
|
1961
2135
|
/**
|
|
1962
2136
|
* Create or replace a record in a document model (issue #1964 Phase 4).
|
|
1963
2137
|
* `POST documents/:id/records/:model` with `{ id, data, options? }` —
|
|
@@ -2069,6 +2243,21 @@ export declare class ApiClient {
|
|
|
2069
2243
|
email?: string;
|
|
2070
2244
|
};
|
|
2071
2245
|
}>;
|
|
2246
|
+
/**
|
|
2247
|
+
* The admin inventory of one user's documents, followed to the end (#3399).
|
|
2248
|
+
*
|
|
2249
|
+
* The endpoint speaks the standard list contract (`{ items, hasMore,
|
|
2250
|
+
* nextCursor }`) and caps a page, so one request reads one page: reading it
|
|
2251
|
+
* would truncate a heavy user's inventory at the page size, which is the
|
|
2252
|
+
* bug this issue is about with a smaller number on it. `documents list
|
|
2253
|
+
* --user-id` and `documents export-all` both read this, and both mean "all
|
|
2254
|
+
* of them". `paginateAll` carries the repeat-cursor and max-page guards, so
|
|
2255
|
+
* a server handing out a non-advancing cursor fails loudly instead of
|
|
2256
|
+
* looping forever.
|
|
2257
|
+
*
|
|
2258
|
+
* Tolerant of a pre-contract server, which answers with a bare
|
|
2259
|
+
* `{ documents }` array and no cursor: that reads as a single page.
|
|
2260
|
+
*/
|
|
2072
2261
|
listAdminDocuments(appId: string, userId: string): Promise<any[]>;
|
|
2073
2262
|
/**
|
|
2074
2263
|
* The document `AppUser.rootDocId` points at, or null when the user has none
|
|
@@ -4,6 +4,13 @@ import { fetchWithTLS } from "./fetch.js";
|
|
|
4
4
|
import { paginateAll, normalizeCliListEnvelope } from "./paginate.js";
|
|
5
5
|
import { RefreshError, refreshAdminCredentials, } from "./refresh-admin-credentials.js";
|
|
6
6
|
import { drainAppsUntilConverged, } from "./workflow-usage.js";
|
|
7
|
+
/**
|
|
8
|
+
* Page size the admin per-user inventories are asked for (#3399).
|
|
9
|
+
*
|
|
10
|
+
* `MAX_LIST_LIMIT` on the server, so a heavy user's inventory is walked in the
|
|
11
|
+
* fewest round trips the contract allows; a larger value is clamped there.
|
|
12
|
+
*/
|
|
13
|
+
const ADMIN_INVENTORY_PAGE_SIZE = 100;
|
|
7
14
|
export class ApiError extends Error {
|
|
8
15
|
statusCode;
|
|
9
16
|
code;
|
|
@@ -780,6 +787,28 @@ export class ApiClient {
|
|
|
780
787
|
const result = await this.get(`/admin/api/apps/${appId}/functions/${functionId}/runs`, params);
|
|
781
788
|
return { items: result?.items ?? [], nextCursor: result?.nextCursor ?? null };
|
|
782
789
|
}
|
|
790
|
+
/**
|
|
791
|
+
* A function run's step trace — #3348.
|
|
792
|
+
*
|
|
793
|
+
* The function-scoped twin of `getWorkflowStepRuns`, and it answers with the
|
|
794
|
+
* same rows in the same shape: `workflows/:idOrKey/runs/...` resolves its
|
|
795
|
+
* first argument to a workflow DEFINITION, which a function id and a function
|
|
796
|
+
* key alike miss, so a durable run's steps needed a route that addresses the
|
|
797
|
+
* run by the function that owns it.
|
|
798
|
+
*/
|
|
799
|
+
async getFunctionStepRuns(appId, functionId, runId) {
|
|
800
|
+
const result = await this.get(`/admin/api/apps/${appId}/functions/${functionId}/runs/${runId}/steps`);
|
|
801
|
+
return { items: result?.items ?? [] };
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* End a function run that will not settle — #3348.
|
|
805
|
+
*
|
|
806
|
+
* `terminated: false` means the run had already settled and the route
|
|
807
|
+
* reported its outcome instead of overwriting it.
|
|
808
|
+
*/
|
|
809
|
+
async terminateFunctionRun(appId, functionId, runId) {
|
|
810
|
+
return this.post(`/admin/api/apps/${appId}/functions/${functionId}/runs/${runId}/terminate`, {});
|
|
811
|
+
}
|
|
783
812
|
/**
|
|
784
813
|
* A function's invocation records, newest first — #3287.
|
|
785
814
|
*
|
|
@@ -791,9 +820,125 @@ export class ApiClient {
|
|
|
791
820
|
const result = await this.get(`/admin/api/apps/${appId}/functions/${functionId}/logs`, params);
|
|
792
821
|
return { items: result?.items ?? [], nextCursor: result?.nextCursor ?? null };
|
|
793
822
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
823
|
+
/**
|
|
824
|
+
* One invocation record by its id — #3448, behind `functions logs
|
|
825
|
+
* --invocation <id>`.
|
|
826
|
+
*
|
|
827
|
+
* The id the invoke envelope answered with. A record that never existed,
|
|
828
|
+
* one of ANOTHER function, and one the seven-day TTL has expired all answer
|
|
829
|
+
* the same 404, which is what the listing's own filter promises.
|
|
830
|
+
*/
|
|
831
|
+
async getFunctionLog(appId, functionId, invocationId) {
|
|
832
|
+
return this.get(`/admin/api/apps/${appId}/functions/${functionId}/logs/${invocationId}`);
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* One function run, RECONCILED against the engine — #3448, what
|
|
836
|
+
* `functions runs wait` polls.
|
|
837
|
+
*
|
|
838
|
+
* NOT the runs listing: that reports the STORED status, and a durable run's
|
|
839
|
+
* row stays `running` until something asks the engine, so a wait built on it
|
|
840
|
+
* would never settle.
|
|
841
|
+
*/
|
|
842
|
+
async getFunctionRun(appId, functionId, runId) {
|
|
843
|
+
return this.get(`/admin/api/apps/${appId}/functions/${functionId}/runs/${runId}`);
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* The operator's own APP user — #3448 D3448-009.
|
|
847
|
+
*
|
|
848
|
+
* `getMe()` reads the ADMIN profile (`/admin/api/me`); this is the
|
|
849
|
+
* app-scoped route, which answers the app user `requireAppPermission`
|
|
850
|
+
* provisions for an admin and the `appRole` it gave them. That is the
|
|
851
|
+
* identity a `functions invoke` runs under by default, and printing it is
|
|
852
|
+
* how an operator knows their call bypassed the function's `access` gate.
|
|
853
|
+
*/
|
|
854
|
+
async getAppProfile(appId) {
|
|
855
|
+
return this.get(`/app/${appId}/api/me`);
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Invoke a function and hand back the ANSWER, whatever its HTTP status —
|
|
859
|
+
* #3448 D3448-010.
|
|
860
|
+
*
|
|
861
|
+
* `request` throws an `ApiError` on any non-2xx, which is right for every
|
|
862
|
+
* other verb and wrong for this one: a 429 carries a `Retry-After` an
|
|
863
|
+
* operator needs to see, and a 409 mode mismatch carries the version's real
|
|
864
|
+
* mode. Rendering those from an exception means re-deriving what the server
|
|
865
|
+
* already said. So this returns the envelope with its status and its retry
|
|
866
|
+
* hint, and throws only when the request did not complete at all.
|
|
867
|
+
*
|
|
868
|
+
* `bearer` is the `--user` path's minted token; absent, the CLI's own
|
|
869
|
+
* credentials. `mode` is ALWAYS sent (D3448-012): it is what makes the
|
|
870
|
+
* server, not the CLI, the authority on a wrong verb.
|
|
871
|
+
*/
|
|
872
|
+
async invokeFunction(appId, functionKey, body, options) {
|
|
873
|
+
const credentials = await this.ensureAuthenticated();
|
|
874
|
+
const base = `/app/${appId}/api/functions/${encodeURIComponent(functionKey)}`;
|
|
875
|
+
const path = options?.asSystem
|
|
876
|
+
? `${base}/invoke-as-system`
|
|
877
|
+
: options?.runtime === "task"
|
|
878
|
+
? `${base}/start`
|
|
879
|
+
: base;
|
|
880
|
+
const headers = {
|
|
881
|
+
Authorization: `Bearer ${options?.bearer ?? credentials.accessToken}`,
|
|
882
|
+
"Content-Type": "application/json",
|
|
883
|
+
};
|
|
884
|
+
// The CLI's own credentials reach an app-scoped route through the
|
|
885
|
+
// global-admin header; a minted user token does not need it and must not
|
|
886
|
+
// carry it.
|
|
887
|
+
if (!options?.bearer && credentials.globalAdminAppId) {
|
|
888
|
+
headers["X-Global-Admin-App-Id"] = credentials.globalAdminAppId;
|
|
889
|
+
}
|
|
890
|
+
const response = await fetchWithTLS(`${credentials.serverUrl}${path}`, {
|
|
891
|
+
method: "POST",
|
|
892
|
+
headers,
|
|
893
|
+
body: JSON.stringify(body),
|
|
894
|
+
});
|
|
895
|
+
const text = await response.text();
|
|
896
|
+
let parsed = null;
|
|
897
|
+
try {
|
|
898
|
+
parsed = text ? JSON.parse(text) : null;
|
|
899
|
+
}
|
|
900
|
+
catch {
|
|
901
|
+
// A body that is not JSON is still an answer; keep it readable.
|
|
902
|
+
parsed = { error: text };
|
|
903
|
+
}
|
|
904
|
+
const retryAfter = response.headers.get("retry-after");
|
|
905
|
+
const retryAfterSeconds = retryAfter && Number.isFinite(Number(retryAfter)) ? Number(retryAfter) : null;
|
|
906
|
+
return {
|
|
907
|
+
httpStatus: response.status,
|
|
908
|
+
retryAfterSeconds: retryAfterSeconds ??
|
|
909
|
+
(typeof parsed?.retryAfter === "number" ? parsed.retryAfter : null),
|
|
910
|
+
body: parsed,
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* A function's versions, newest first (#3462).
|
|
915
|
+
*
|
|
916
|
+
* Paging is opt-in on the server: with no `limit` and no `cursor` every
|
|
917
|
+
* version comes back, which is what this method did before paging existed and
|
|
918
|
+
* what an already-installed CLI still asks for. A caller that passes either
|
|
919
|
+
* gets the shared `{ items, hasMore, nextCursor }` page.
|
|
920
|
+
*/
|
|
921
|
+
async listFunctionConfigs(appId, functionId, options = {}) {
|
|
922
|
+
const query = new URLSearchParams();
|
|
923
|
+
if (options.limit !== undefined)
|
|
924
|
+
query.set("limit", String(options.limit));
|
|
925
|
+
if (options.cursor)
|
|
926
|
+
query.set("cursor", options.cursor);
|
|
927
|
+
const suffix = query.toString() ? `?${query.toString()}` : "";
|
|
928
|
+
const result = await this.get(`/admin/api/apps/${appId}/functions/${functionId}/configs${suffix}`);
|
|
929
|
+
return {
|
|
930
|
+
items: result?.items ?? [],
|
|
931
|
+
hasMore: result?.hasMore === true,
|
|
932
|
+
nextCursor: result?.nextCursor ?? null,
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Point the function at one of its OWN existing versions (#3462). Creates no
|
|
937
|
+
* version; the activated version's capabilities, limits and triggers apply
|
|
938
|
+
* from the next call.
|
|
939
|
+
*/
|
|
940
|
+
async activateFunctionConfig(appId, functionId, configId) {
|
|
941
|
+
return this.post(`/admin/api/apps/${appId}/functions/${functionId}/configs/${configId}/activate`, {});
|
|
797
942
|
}
|
|
798
943
|
async getFunctionConfig(appId, functionId, configId) {
|
|
799
944
|
return this.get(`/admin/api/apps/${appId}/functions/${functionId}/configs/${configId}`);
|
|
@@ -885,8 +1030,16 @@ export class ApiClient {
|
|
|
885
1030
|
async getLockStatus(appId, key) {
|
|
886
1031
|
return this.post(`/app/${appId}/api/locks/status`, { key });
|
|
887
1032
|
}
|
|
888
|
-
|
|
889
|
-
|
|
1033
|
+
/**
|
|
1034
|
+
* #3562 — `owner` is sent only when one was given, so a call that names none
|
|
1035
|
+
* composes byte for byte the body it always did.
|
|
1036
|
+
*/
|
|
1037
|
+
async acquireLock(appId, key, ttlMs, owner) {
|
|
1038
|
+
return this.post(`/app/${appId}/api/locks/acquire`, {
|
|
1039
|
+
key,
|
|
1040
|
+
ttlMs,
|
|
1041
|
+
...(owner !== undefined ? { owner } : {}),
|
|
1042
|
+
});
|
|
890
1043
|
}
|
|
891
1044
|
async releaseLock(appId, key, handleId) {
|
|
892
1045
|
return this.post(`/app/${appId}/api/locks/release`, {
|
|
@@ -2431,6 +2584,101 @@ export class ApiClient {
|
|
|
2431
2584
|
async getDocumentStats(appId, documentId) {
|
|
2432
2585
|
return this.get(`/app/${appId}/api/documents/${documentId}/stats`);
|
|
2433
2586
|
}
|
|
2587
|
+
/**
|
|
2588
|
+
* A large document's snapshot builds, newest first, one page (#3432).
|
|
2589
|
+
* `GET documents/:id/snapshots` → `{ items, hasMore, nextCursor? }`.
|
|
2590
|
+
*/
|
|
2591
|
+
async listDocumentSnapshots(appId, documentId, options = {}) {
|
|
2592
|
+
const params = new URLSearchParams();
|
|
2593
|
+
if (options.limit !== undefined)
|
|
2594
|
+
params.set("limit", String(options.limit));
|
|
2595
|
+
if (options.cursor)
|
|
2596
|
+
params.set("cursor", options.cursor);
|
|
2597
|
+
const query = params.toString();
|
|
2598
|
+
return this.get(`/app/${appId}/api/documents/${documentId}/snapshots${query ? `?${query}` : ""}`);
|
|
2599
|
+
}
|
|
2600
|
+
/**
|
|
2601
|
+
* A large document's bulk-load sessions, newest first (#3434, criterion 9).
|
|
2602
|
+
*
|
|
2603
|
+
* Read-only, through the document read helper's app-admin arm — the same
|
|
2604
|
+
* door the snapshot readers use. The action verb `documents ingest` is
|
|
2605
|
+
* #3435's; these two are the operator's window onto what a session did.
|
|
2606
|
+
*/
|
|
2607
|
+
async listDocumentIngests(appId, documentId, options = {}) {
|
|
2608
|
+
const params = new URLSearchParams();
|
|
2609
|
+
if (options.limit !== undefined)
|
|
2610
|
+
params.set("limit", String(options.limit));
|
|
2611
|
+
if (options.cursor)
|
|
2612
|
+
params.set("cursor", options.cursor);
|
|
2613
|
+
const query = params.toString();
|
|
2614
|
+
return this.get(`/app/${appId}/api/documents/${documentId}/ingest${query ? `?${query}` : ""}`);
|
|
2615
|
+
}
|
|
2616
|
+
/** One bulk-load session's status (#3434). */
|
|
2617
|
+
async getDocumentIngest(appId, documentId, sessionId) {
|
|
2618
|
+
return this.get(`/app/${appId}/api/documents/${documentId}/ingest/${encodeURIComponent(sessionId)}`);
|
|
2619
|
+
}
|
|
2620
|
+
/** Open a bulk-load session on a large document (#3435, criterion 9). */
|
|
2621
|
+
async createDocumentIngest(appId, documentId) {
|
|
2622
|
+
return this.post(`/app/${appId}/api/documents/${documentId}/ingest`, {});
|
|
2623
|
+
}
|
|
2624
|
+
/**
|
|
2625
|
+
* Upload one chunk of a bulk-load session's artifact (#3435).
|
|
2626
|
+
*
|
|
2627
|
+
* `multipart/form-data`: the eight descriptor fields as text parts and the
|
|
2628
|
+
* gzipped bytes as one file part named `chunk`. No `Content-Type` is set on
|
|
2629
|
+
* the request — fetch supplies the boundary, and a header written by hand
|
|
2630
|
+
* would name one the body does not use.
|
|
2631
|
+
*/
|
|
2632
|
+
async uploadDocumentIngestChunk(appId, documentId, sessionId, chunk) {
|
|
2633
|
+
const credentials = await this.ensureAuthenticated();
|
|
2634
|
+
const form = new FormData();
|
|
2635
|
+
form.set("model", chunk.model);
|
|
2636
|
+
form.set("index", String(chunk.index));
|
|
2637
|
+
form.set("rows", String(chunk.rows));
|
|
2638
|
+
form.set("bytes", String(chunk.bytes));
|
|
2639
|
+
form.set("rawBytes", String(chunk.rawBytes));
|
|
2640
|
+
form.set("sha256", chunk.sha256);
|
|
2641
|
+
form.set("firstId", chunk.firstId);
|
|
2642
|
+
form.set("lastId", chunk.lastId);
|
|
2643
|
+
form.set("chunk", new Blob([chunk.body]), `${chunk.index}.ndjson.gz`);
|
|
2644
|
+
const headers = {
|
|
2645
|
+
Authorization: `Bearer ${credentials.accessToken}`,
|
|
2646
|
+
};
|
|
2647
|
+
if (credentials.globalAdminAppId) {
|
|
2648
|
+
headers["X-Global-Admin-App-Id"] = credentials.globalAdminAppId;
|
|
2649
|
+
}
|
|
2650
|
+
const url = `${credentials.serverUrl}/app/${appId}/api/documents/${documentId}` +
|
|
2651
|
+
`/ingest/${encodeURIComponent(sessionId)}/chunks`;
|
|
2652
|
+
const response = await fetchWithTLS(url, {
|
|
2653
|
+
method: "POST",
|
|
2654
|
+
headers,
|
|
2655
|
+
body: form,
|
|
2656
|
+
});
|
|
2657
|
+
const text = await response.text();
|
|
2658
|
+
let result = {};
|
|
2659
|
+
try {
|
|
2660
|
+
result = text ? JSON.parse(text) : {};
|
|
2661
|
+
}
|
|
2662
|
+
catch {
|
|
2663
|
+
result = { error: text };
|
|
2664
|
+
}
|
|
2665
|
+
if (!response.ok) {
|
|
2666
|
+
throw new ApiError(result?.error || `Failed to upload chunk: ${response.statusText}`, response.status, result?.code, result?.details);
|
|
2667
|
+
}
|
|
2668
|
+
return result;
|
|
2669
|
+
}
|
|
2670
|
+
/** Freeze a session's manifest and hand it to the pipeline (#3435). */
|
|
2671
|
+
async commitDocumentIngest(appId, documentId, sessionId) {
|
|
2672
|
+
return this.post(`/app/${appId}/api/documents/${documentId}/ingest/${encodeURIComponent(sessionId)}/commit`, {});
|
|
2673
|
+
}
|
|
2674
|
+
/** Give a session up; allowed until the swap (#3435). */
|
|
2675
|
+
async abortDocumentIngest(appId, documentId, sessionId) {
|
|
2676
|
+
return this.post(`/app/${appId}/api/documents/${documentId}/ingest/${encodeURIComponent(sessionId)}/abort`, {});
|
|
2677
|
+
}
|
|
2678
|
+
/** One snapshot build with its verification result (#3432). */
|
|
2679
|
+
async getDocumentSnapshot(appId, documentId, buildId) {
|
|
2680
|
+
return this.get(`/app/${appId}/api/documents/${documentId}/snapshots/${encodeURIComponent(buildId)}`);
|
|
2681
|
+
}
|
|
2434
2682
|
/**
|
|
2435
2683
|
* Create or replace a record in a document model (issue #1964 Phase 4).
|
|
2436
2684
|
* `POST documents/:id/records/:model` with `{ id, data, options? }` —
|
|
@@ -2575,9 +2823,37 @@ export class ApiClient {
|
|
|
2575
2823
|
async lookupUserByEmail(appId, email) {
|
|
2576
2824
|
return this.get(`/app/${appId}/api/users/lookup`, { email });
|
|
2577
2825
|
}
|
|
2826
|
+
/**
|
|
2827
|
+
* The admin inventory of one user's documents, followed to the end (#3399).
|
|
2828
|
+
*
|
|
2829
|
+
* The endpoint speaks the standard list contract (`{ items, hasMore,
|
|
2830
|
+
* nextCursor }`) and caps a page, so one request reads one page: reading it
|
|
2831
|
+
* would truncate a heavy user's inventory at the page size, which is the
|
|
2832
|
+
* bug this issue is about with a smaller number on it. `documents list
|
|
2833
|
+
* --user-id` and `documents export-all` both read this, and both mean "all
|
|
2834
|
+
* of them". `paginateAll` carries the repeat-cursor and max-page guards, so
|
|
2835
|
+
* a server handing out a non-advancing cursor fails loudly instead of
|
|
2836
|
+
* looping forever.
|
|
2837
|
+
*
|
|
2838
|
+
* Tolerant of a pre-contract server, which answers with a bare
|
|
2839
|
+
* `{ documents }` array and no cursor: that reads as a single page.
|
|
2840
|
+
*/
|
|
2578
2841
|
async listAdminDocuments(appId, userId) {
|
|
2579
|
-
|
|
2580
|
-
|
|
2842
|
+
return paginateAll(async (cursor) => {
|
|
2843
|
+
const params = new URLSearchParams({
|
|
2844
|
+
userId,
|
|
2845
|
+
limit: String(ADMIN_INVENTORY_PAGE_SIZE),
|
|
2846
|
+
});
|
|
2847
|
+
if (cursor)
|
|
2848
|
+
params.set("cursor", cursor);
|
|
2849
|
+
const result = await this.get(`/admin/api/apps/${appId}/documents?${params.toString()}`);
|
|
2850
|
+
return {
|
|
2851
|
+
items: result?.items ?? result?.documents ?? [],
|
|
2852
|
+
// #1316: prefer `nextCursor`; the deprecated `cursor` alias keeps a
|
|
2853
|
+
// shipped CLI paginating against a server that still dual-emits.
|
|
2854
|
+
nextCursor: result?.nextCursor ?? result?.cursor,
|
|
2855
|
+
};
|
|
2856
|
+
});
|
|
2581
2857
|
}
|
|
2582
2858
|
/**
|
|
2583
2859
|
* The document `AppUser.rootDocId` points at, or null when the user has none
|