primitive-admin 1.1.0-alpha.80 → 1.1.0-alpha.82

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.
Files changed (87) hide show
  1. package/README.md +5 -5
  2. package/assets/skill/skills/primitive-platform/SKILL.md +23 -11
  3. package/dist/bin/primitive.js +14 -15
  4. package/dist/bin/primitive.js.map +1 -1
  5. package/dist/src/commands/databases.js +3 -5
  6. package/dist/src/commands/databases.js.map +1 -1
  7. package/dist/src/commands/documents.js +163 -21
  8. package/dist/src/commands/documents.js.map +1 -1
  9. package/dist/src/commands/functions.js +736 -12
  10. package/dist/src/commands/functions.js.map +1 -1
  11. package/dist/src/commands/prompts.js +19 -2
  12. package/dist/src/commands/prompts.js.map +1 -1
  13. package/dist/src/commands/sync-app-settings.js +2 -2
  14. package/dist/src/commands/sync-app-settings.js.map +1 -1
  15. package/dist/src/commands/sync.js +29 -27
  16. package/dist/src/commands/sync.js.map +1 -1
  17. package/dist/src/commands/webhooks.d.ts +29 -0
  18. package/dist/src/commands/webhooks.js +118 -54
  19. package/dist/src/commands/webhooks.js.map +1 -1
  20. package/dist/src/commands/workflows.d.ts +1 -29
  21. package/dist/src/commands/workflows.js +8 -109
  22. package/dist/src/commands/workflows.js.map +1 -1
  23. package/dist/src/lib/api-client.d.ts +119 -3
  24. package/dist/src/lib/api-client.js +166 -5
  25. package/dist/src/lib/api-client.js.map +1 -1
  26. package/dist/src/lib/config-object-descriptor.js +12 -4
  27. package/dist/src/lib/config-object-descriptor.js.map +1 -1
  28. package/dist/src/lib/env-resolver-core.d.ts +24 -19
  29. package/dist/src/lib/env-resolver-core.js +35 -54
  30. package/dist/src/lib/env-resolver-core.js.map +1 -1
  31. package/dist/src/lib/function-db-types.js +15 -0
  32. package/dist/src/lib/function-db-types.js.map +1 -1
  33. package/dist/src/lib/function-document-types.js +4 -0
  34. package/dist/src/lib/function-document-types.js.map +1 -1
  35. package/dist/src/lib/function-log-tail.d.ts +51 -2
  36. package/dist/src/lib/function-log-tail.js +160 -13
  37. package/dist/src/lib/function-log-tail.js.map +1 -1
  38. package/dist/src/lib/function-run.d.ts +271 -0
  39. package/dist/src/lib/function-run.js +378 -0
  40. package/dist/src/lib/function-run.js.map +1 -0
  41. package/dist/src/lib/function-schema-codegen.d.ts +28 -0
  42. package/dist/src/lib/function-schema-codegen.js +41 -10
  43. package/dist/src/lib/function-schema-codegen.js.map +1 -1
  44. package/dist/src/lib/function-sync.d.ts +9 -4
  45. package/dist/src/lib/function-sync.js +29 -7
  46. package/dist/src/lib/function-sync.js.map +1 -1
  47. package/dist/src/lib/generated-config-surfaces.d.ts +555 -19
  48. package/dist/src/lib/generated-config-surfaces.js +1826 -80
  49. package/dist/src/lib/generated-config-surfaces.js.map +1 -1
  50. package/dist/src/lib/generated-sdk-types.d.ts +1 -1
  51. package/dist/src/lib/generated-sdk-types.js +1 -1
  52. package/dist/src/lib/generated-sdk-types.js.map +1 -1
  53. package/dist/src/lib/local-test-cases.js +2 -2
  54. package/dist/src/lib/local-test-cases.js.map +1 -1
  55. package/dist/src/lib/prompt-schema-codegen.d.ts +94 -0
  56. package/dist/src/lib/prompt-schema-codegen.js +212 -0
  57. package/dist/src/lib/prompt-schema-codegen.js.map +1 -0
  58. package/dist/src/lib/snapshot-manifest-layout.d.ts +61 -0
  59. package/dist/src/lib/snapshot-manifest-layout.js +70 -0
  60. package/dist/src/lib/snapshot-manifest-layout.js.map +1 -0
  61. package/dist/src/lib/step-run-table.d.ts +43 -0
  62. package/dist/src/lib/step-run-table.js +129 -0
  63. package/dist/src/lib/step-run-table.js.map +1 -0
  64. package/dist/src/lib/swift-codegen/banners.d.ts +18 -0
  65. package/dist/src/lib/swift-codegen/banners.js +19 -0
  66. package/dist/src/lib/swift-codegen/banners.js.map +1 -0
  67. package/dist/src/lib/swift-codegen/dbGenerator.js +11 -7
  68. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  69. package/dist/src/lib/swift-codegen/functionGenerator.d.ts +125 -0
  70. package/dist/src/lib/swift-codegen/functionGenerator.js +423 -0
  71. package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -0
  72. package/dist/src/lib/swift-codegen/generator.d.ts +6 -0
  73. package/dist/src/lib/swift-codegen/generator.js +21 -10
  74. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  75. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +15 -0
  76. package/dist/src/lib/swift-codegen/schemaToSwift.js +21 -4
  77. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
  78. package/dist/src/lib/sync-paths.d.ts +19 -14
  79. package/dist/src/lib/sync-paths.js +26 -24
  80. package/dist/src/lib/sync-paths.js.map +1 -1
  81. package/dist/src/lib/webhook-deliver.d.ts +209 -0
  82. package/dist/src/lib/webhook-deliver.js +519 -0
  83. package/dist/src/lib/webhook-deliver.js.map +1 -0
  84. package/dist/src/lib/workflow-toml-validator.d.ts +9 -5
  85. package/dist/src/lib/workflow-toml-validator.js +18 -10
  86. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  87. package/package.json +2 -2
@@ -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;
@@ -214,9 +221,9 @@ export class ApiClient {
214
221
  * project still holding the pre-#3153 layout that read threw the stale-layout
215
222
  * refusal out of module evaluation, where not even the `uncaughtException`
216
223
  * handler can reach it: the user got Node's raw stack trace, and `guides
217
- * get` — the command that serves the very document the refusal names — died
218
- * with it (#3273). The singleton is gone (#3154, it had no callers) and the
219
- * read stays lazy, which is what keeps that shape from coming back.
224
+ * get` — which reads nothing from the project — died with it (#3273). The
225
+ * singleton is gone (#3154, it had no callers) and the read stays lazy,
226
+ * which is what keeps that shape from coming back.
220
227
  *
221
228
  * Nothing is lost by waiting, and one thing is gained: a `login` earlier in
222
229
  * the same process is visible to a later request.
@@ -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,6 +820,93 @@ 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
  }
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 path = options?.asSystem
875
+ ? `/app/${appId}/api/functions/${encodeURIComponent(functionKey)}/invoke-as-system`
876
+ : `/app/${appId}/api/functions/${encodeURIComponent(functionKey)}`;
877
+ const headers = {
878
+ Authorization: `Bearer ${options?.bearer ?? credentials.accessToken}`,
879
+ "Content-Type": "application/json",
880
+ };
881
+ // The CLI's own credentials reach an app-scoped route through the
882
+ // global-admin header; a minted user token does not need it and must not
883
+ // carry it.
884
+ if (!options?.bearer && credentials.globalAdminAppId) {
885
+ headers["X-Global-Admin-App-Id"] = credentials.globalAdminAppId;
886
+ }
887
+ const response = await fetchWithTLS(`${credentials.serverUrl}${path}`, {
888
+ method: "POST",
889
+ headers,
890
+ body: JSON.stringify(body),
891
+ });
892
+ const text = await response.text();
893
+ let parsed = null;
894
+ try {
895
+ parsed = text ? JSON.parse(text) : null;
896
+ }
897
+ catch {
898
+ // A body that is not JSON is still an answer; keep it readable.
899
+ parsed = { error: text };
900
+ }
901
+ const retryAfter = response.headers.get("retry-after");
902
+ const retryAfterSeconds = retryAfter && Number.isFinite(Number(retryAfter)) ? Number(retryAfter) : null;
903
+ return {
904
+ httpStatus: response.status,
905
+ retryAfterSeconds: retryAfterSeconds ??
906
+ (typeof parsed?.retryAfter === "number" ? parsed.retryAfter : null),
907
+ body: parsed,
908
+ };
909
+ }
794
910
  async listFunctionConfigs(appId, functionId) {
795
911
  const result = await this.get(`/admin/api/apps/${appId}/functions/${functionId}/configs`);
796
912
  return { items: result?.items ?? [] };
@@ -2431,6 +2547,23 @@ export class ApiClient {
2431
2547
  async getDocumentStats(appId, documentId) {
2432
2548
  return this.get(`/app/${appId}/api/documents/${documentId}/stats`);
2433
2549
  }
2550
+ /**
2551
+ * A large document's snapshot builds, newest first, one page (#3432).
2552
+ * `GET documents/:id/snapshots` → `{ items, hasMore, nextCursor? }`.
2553
+ */
2554
+ async listDocumentSnapshots(appId, documentId, options = {}) {
2555
+ const params = new URLSearchParams();
2556
+ if (options.limit !== undefined)
2557
+ params.set("limit", String(options.limit));
2558
+ if (options.cursor)
2559
+ params.set("cursor", options.cursor);
2560
+ const query = params.toString();
2561
+ return this.get(`/app/${appId}/api/documents/${documentId}/snapshots${query ? `?${query}` : ""}`);
2562
+ }
2563
+ /** One snapshot build with its verification result (#3432). */
2564
+ async getDocumentSnapshot(appId, documentId, buildId) {
2565
+ return this.get(`/app/${appId}/api/documents/${documentId}/snapshots/${encodeURIComponent(buildId)}`);
2566
+ }
2434
2567
  /**
2435
2568
  * Create or replace a record in a document model (issue #1964 Phase 4).
2436
2569
  * `POST documents/:id/records/:model` with `{ id, data, options? }` —
@@ -2575,9 +2708,37 @@ export class ApiClient {
2575
2708
  async lookupUserByEmail(appId, email) {
2576
2709
  return this.get(`/app/${appId}/api/users/lookup`, { email });
2577
2710
  }
2711
+ /**
2712
+ * The admin inventory of one user's documents, followed to the end (#3399).
2713
+ *
2714
+ * The endpoint speaks the standard list contract (`{ items, hasMore,
2715
+ * nextCursor }`) and caps a page, so one request reads one page: reading it
2716
+ * would truncate a heavy user's inventory at the page size, which is the
2717
+ * bug this issue is about with a smaller number on it. `documents list
2718
+ * --user-id` and `documents export-all` both read this, and both mean "all
2719
+ * of them". `paginateAll` carries the repeat-cursor and max-page guards, so
2720
+ * a server handing out a non-advancing cursor fails loudly instead of
2721
+ * looping forever.
2722
+ *
2723
+ * Tolerant of a pre-contract server, which answers with a bare
2724
+ * `{ documents }` array and no cursor: that reads as a single page.
2725
+ */
2578
2726
  async listAdminDocuments(appId, userId) {
2579
- const result = await this.get(`/admin/api/apps/${appId}/documents`, { userId });
2580
- return result?.documents || result || [];
2727
+ return paginateAll(async (cursor) => {
2728
+ const params = new URLSearchParams({
2729
+ userId,
2730
+ limit: String(ADMIN_INVENTORY_PAGE_SIZE),
2731
+ });
2732
+ if (cursor)
2733
+ params.set("cursor", cursor);
2734
+ const result = await this.get(`/admin/api/apps/${appId}/documents?${params.toString()}`);
2735
+ return {
2736
+ items: result?.items ?? result?.documents ?? [],
2737
+ // #1316: prefer `nextCursor`; the deprecated `cursor` alias keeps a
2738
+ // shipped CLI paginating against a server that still dual-emits.
2739
+ nextCursor: result?.nextCursor ?? result?.cursor,
2740
+ };
2741
+ });
2581
2742
  }
2582
2743
  /**
2583
2744
  * The document `AppUser.rootDocId` points at, or null when the user has none