primitive-admin 1.1.0-alpha.83 → 1.1.0-alpha.84

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 (38) hide show
  1. package/assets/skill/skills/primitive-platform/SKILL.md +105 -675
  2. package/dist/src/commands/collections.js +61 -0
  3. package/dist/src/commands/collections.js.map +1 -1
  4. package/dist/src/commands/databases.js +10 -2
  5. package/dist/src/commands/databases.js.map +1 -1
  6. package/dist/src/commands/documents.d.ts +38 -0
  7. package/dist/src/commands/documents.js +235 -53
  8. package/dist/src/commands/documents.js.map +1 -1
  9. package/dist/src/commands/functions.js +1 -1
  10. package/dist/src/commands/functions.js.map +1 -1
  11. package/dist/src/lib/api-client.d.ts +28 -0
  12. package/dist/src/lib/api-client.js +40 -11
  13. package/dist/src/lib/api-client.js.map +1 -1
  14. package/dist/src/lib/db-codegen/dbTypeIR.js +8 -0
  15. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
  16. package/dist/src/lib/document-ingest-rows.d.ts +137 -0
  17. package/dist/src/lib/document-ingest-rows.js +181 -0
  18. package/dist/src/lib/document-ingest-rows.js.map +1 -0
  19. package/dist/src/lib/document-ingest.d.ts +25 -2
  20. package/dist/src/lib/document-ingest.js +184 -31
  21. package/dist/src/lib/document-ingest.js.map +1 -1
  22. package/dist/src/lib/function-db-types.d.ts +1 -1
  23. package/dist/src/lib/function-db-types.js +1 -1
  24. package/dist/src/lib/function-document-types.js +23 -2
  25. package/dist/src/lib/function-document-types.js.map +1 -1
  26. package/dist/src/lib/generated-sdk-types.d.ts +1 -1
  27. package/dist/src/lib/generated-sdk-types.js +1 -1
  28. package/dist/src/lib/generated-sdk-types.js.map +1 -1
  29. package/dist/src/lib/resolve-owner.d.ts +19 -0
  30. package/dist/src/lib/resolve-owner.js +20 -0
  31. package/dist/src/lib/resolve-owner.js.map +1 -0
  32. package/dist/src/lib/skill-installer.d.ts +49 -3
  33. package/dist/src/lib/skill-installer.js +275 -100
  34. package/dist/src/lib/skill-installer.js.map +1 -1
  35. package/dist/src/lib/snapshot-build.d.ts +50 -0
  36. package/dist/src/lib/snapshot-build.js +111 -0
  37. package/dist/src/lib/snapshot-build.js.map +1 -0
  38. package/package.json +2 -2
@@ -0,0 +1,137 @@
1
+ /**
2
+ * What `documents ingests get` shows an operator, as data (#3598).
3
+ *
4
+ * The rows were composed inline in the command's action, which made the only
5
+ * way to check one a spawned CLI against a live server with a session in
6
+ * exactly the right state — and #3598 adds a block of rows nobody could check
7
+ * that way without a slow load to look at. They are a pure function of the
8
+ * payload now, as `snapshot-build-rows` is; the command still owns the
9
+ * printing, and the live suite still owns "a real terminal really shows this".
10
+ *
11
+ * Label and value, in the order they print. Everything past the first block is
12
+ * optional here, because a session written before its field existed carries
13
+ * none of it and an operator inspecting an old session should see the session
14
+ * rather than a crash.
15
+ */
16
+ /** One printed row: its label and the value beside it. */
17
+ export type IngestSessionRow = [string, unknown];
18
+ /** Where one tick's time went, as the server publishes it. */
19
+ export interface IngestTickTotals {
20
+ manifestMs?: number;
21
+ readMs?: number;
22
+ decodeMs?: number;
23
+ copyMs?: number;
24
+ applyMs?: number;
25
+ reconcileMs?: number;
26
+ swapMs?: number;
27
+ sealMs?: number;
28
+ registerMs?: number;
29
+ totalMs?: number;
30
+ /**
31
+ * Ticks whose stage timers were bracketed by a clock settle (#3638).
32
+ *
33
+ * Equal to `ticks` when every tick managed it. Less means the stage
34
+ * milliseconds above are, for those ticks, the old un-bracketed figures: 0
35
+ * for every synchronous stage.
36
+ */
37
+ bracketedTicks?: number;
38
+ /** What each stage's SQL did, without asking a clock (#3638). */
39
+ counters?: Record<string, IngestStageCounters>;
40
+ }
41
+ /** One stage's clock-free counters, as the server publishes them (#3638). */
42
+ export interface IngestStageCounters {
43
+ statements?: number;
44
+ /** From the SQL cursor's own counter; `null` where the host has none. */
45
+ rowsRead?: number | null;
46
+ /** From the SQL cursor's own counter; `null` where the host has none. */
47
+ rowsWritten?: number | null;
48
+ rowsReturned?: number;
49
+ byTarget?: Record<string, IngestStageCounters>;
50
+ }
51
+ /** The payload `GET .../ingest/{sessionId}` answers with. */
52
+ export interface IngestSessionPayload {
53
+ sessionId: string;
54
+ documentId: string;
55
+ state: string;
56
+ createdBy?: string;
57
+ createdAt?: string | null;
58
+ updatedAt?: string | null;
59
+ completedAt?: string | null;
60
+ expiresAt?: string | null;
61
+ chunks: number;
62
+ rows: number;
63
+ bytes: number;
64
+ /** #3598 — decompressed bytes; null when a swept session cannot say. */
65
+ rawBytes?: number | null;
66
+ stateEnteredAt?: string | null;
67
+ progress?: {
68
+ rowsCopied?: number;
69
+ chunksApplied?: number;
70
+ rowsApplied?: number;
71
+ recordsReconciled?: number;
72
+ /** #3618 — moved-aside rows removed; the counter that moves in `registering`. */
73
+ oldRowsRemoved?: number;
74
+ };
75
+ copyStartedAt?: string | null;
76
+ discontinuityEpoch?: number | null;
77
+ buildId?: string | null;
78
+ failure?: {
79
+ code: string;
80
+ reason: string;
81
+ rows?: Array<{
82
+ model: string;
83
+ id: string;
84
+ } | string>;
85
+ } | null;
86
+ timings?: {
87
+ since?: string | null;
88
+ ticks?: number;
89
+ totals?: IngestTickTotals;
90
+ states?: Record<string, {
91
+ ms?: number;
92
+ ticks?: number;
93
+ intervalMs?: number;
94
+ }>;
95
+ longestInterval?: {
96
+ intervalMs: number;
97
+ state: string;
98
+ } | null;
99
+ } | null;
100
+ throughput?: {
101
+ pipelineMs: number;
102
+ rowsPerSecond: number;
103
+ storedBytesPerSecond: number;
104
+ rawBytesPerSecond: number | null;
105
+ } | null;
106
+ }
107
+ export declare function ingestSessionRows(session: IngestSessionPayload): IngestSessionRow[];
108
+ /**
109
+ * What the client itself spent, beside what the server did (#3598).
110
+ *
111
+ * Every phase past the build is OPTIONAL, and absent means the run never
112
+ * finished it — an upload that failed halfway, a commit that was never
113
+ * reached. A 0 there would read as a measurement of no time at all, which is
114
+ * the same mistake `rawBytes` and `throughput` refuse to make on the server
115
+ * side (finding 3598-FROZEN-02).
116
+ */
117
+ export interface IngestClientTimings {
118
+ /** Reading, checking, sorting, cutting and gzipping the artifact. */
119
+ buildMs: number;
120
+ createMs?: number;
121
+ uploadMs?: number;
122
+ /** Stored bytes put, from the plan's own chunk sizes. */
123
+ uploadedBytes?: number;
124
+ commitMs?: number;
125
+ /** Time spent polling after the commit; 0 under `--no-wait`. */
126
+ waitMs?: number;
127
+ }
128
+ /**
129
+ * The client's phases as rows, so the two sides read side by side.
130
+ *
131
+ * The wall-clock number `documents ingest` used to print covered the artifact
132
+ * build, the upload AND everything the platform then did, and could be blamed
133
+ * on either. These say which. A phase the run never finished prints `—`,
134
+ * which here means what it means everywhere else in this file: not a
135
+ * measurement.
136
+ */
137
+ export declare function ingestClientRows(timings: IngestClientTimings): IngestSessionRow[];
@@ -0,0 +1,181 @@
1
+ /**
2
+ * What `documents ingests get` shows an operator, as data (#3598).
3
+ *
4
+ * The rows were composed inline in the command's action, which made the only
5
+ * way to check one a spawned CLI against a live server with a session in
6
+ * exactly the right state — and #3598 adds a block of rows nobody could check
7
+ * that way without a slow load to look at. They are a pure function of the
8
+ * payload now, as `snapshot-build-rows` is; the command still owns the
9
+ * printing, and the live suite still owns "a real terminal really shows this".
10
+ *
11
+ * Label and value, in the order they print. Everything past the first block is
12
+ * optional here, because a session written before its field existed carries
13
+ * none of it and an operator inspecting an old session should see the session
14
+ * rather than a crash.
15
+ */
16
+ import { formatDate } from "./output.js";
17
+ /** The states a session passes through, in the order it passes through them. */
18
+ const STATES = [
19
+ "uploading",
20
+ "committed",
21
+ "validating",
22
+ "staging",
23
+ "applying",
24
+ "finalizing",
25
+ "registering",
26
+ ];
27
+ /** The per-stage rows, in the order a tick spends them. */
28
+ const STAGES = [
29
+ ["Manifest (ms)", "manifestMs"],
30
+ ["Read (ms)", "readMs"],
31
+ ["Decode (ms)", "decodeMs"],
32
+ ["Copy (ms)", "copyMs"],
33
+ ["Apply (ms)", "applyMs"],
34
+ ["Reconcile (ms)", "reconcileMs"],
35
+ ["Swap (ms)", "swapMs"],
36
+ ["Seal (ms)", "sealMs"],
37
+ ["Register (ms)", "registerMs"],
38
+ ];
39
+ const DASH = "—";
40
+ const title = (state) => state.charAt(0).toUpperCase() + state.slice(1);
41
+ /** Megabytes per second, at one decimal — the unit a load is discussed in. */
42
+ const mbPerSecond = (bytesPerSecond) => `${(bytesPerSecond / 1_000_000).toFixed(2)} MB/s`;
43
+ export function ingestSessionRows(session) {
44
+ const progress = session.progress ?? {};
45
+ const rows = [
46
+ ["Session", session.sessionId],
47
+ ["Document", session.documentId],
48
+ ["State", session.state],
49
+ ["Created by", session.createdBy],
50
+ ["Created", formatDate(session.createdAt)],
51
+ ["Updated", formatDate(session.updatedAt)],
52
+ [
53
+ "Completed",
54
+ session.completedAt
55
+ ? formatDate(session.completedAt)
56
+ : DASH,
57
+ ],
58
+ ["Chunks", session.chunks],
59
+ ["Rows", session.rows],
60
+ ["Bytes", session.bytes],
61
+ // #3598 — what the pipeline actually parsed, which is the numerator of
62
+ // any megabytes-per-second figure. `—` rather than 0 when a completed
63
+ // session's chunk descriptors were swept before timings existed.
64
+ ["Raw bytes", session.rawBytes ?? DASH],
65
+ [
66
+ "Progress",
67
+ `copied ${progress.rowsCopied ?? 0} rows, applied ` +
68
+ `${progress.chunksApplied ?? 0} chunks / ${progress.rowsApplied ?? 0} rows, ` +
69
+ `reconciled ${progress.recordsReconciled ?? 0} records, ` +
70
+ `removed ${progress.oldRowsRemoved ?? 0} moved-aside rows`,
71
+ ],
72
+ [
73
+ "Copy point",
74
+ session.copyStartedAt
75
+ ? formatDate(session.copyStartedAt)
76
+ : DASH,
77
+ ],
78
+ ["Discontinuity epoch", session.discontinuityEpoch ?? DASH],
79
+ ["Build", session.buildId ?? DASH],
80
+ ["Expires", formatDate(session.expiresAt)],
81
+ ];
82
+ // Why it stopped is the reason an operator opened this at all, so it comes
83
+ // before the profile rather than after it.
84
+ if (session.failure) {
85
+ rows.push(["Failure", session.failure.code]);
86
+ rows.push(["Reason", session.failure.reason]);
87
+ for (const row of session.failure.rows ?? []) {
88
+ rows.push([
89
+ " Row",
90
+ typeof row === "string" ? row : `${row.model} ${row.id}`,
91
+ ]);
92
+ }
93
+ }
94
+ const timings = session.timings;
95
+ rows.push(["Ticks", timings?.ticks ?? DASH]);
96
+ // One row per state the session actually recorded. A state it never entered
97
+ // gets none: a block an operator learns is usually blank is a block they
98
+ // stop reading.
99
+ for (const state of STATES) {
100
+ const window = timings?.states?.[state];
101
+ if (!window)
102
+ continue;
103
+ rows.push([
104
+ title(state),
105
+ `${window.ms ?? 0} ms / ${window.ticks ?? 0} ticks / ` +
106
+ `${window.intervalMs ?? 0} ms between ticks`,
107
+ ]);
108
+ }
109
+ for (const [label, key] of STAGES) {
110
+ rows.push([label, timings?.totals?.[key] ?? DASH]);
111
+ }
112
+ // #3638 — the clock-free half, and the flag that says whether the
113
+ // milliseconds above measure anything. A stage row reads
114
+ // `statements / rows read / rows written`, with `—` where the host had no
115
+ // cursor counter to read: an unknown, never a measured zero.
116
+ const counters = timings?.totals?.counters;
117
+ rows.push([
118
+ "Bracketed ticks",
119
+ timings?.totals?.bracketedTicks ?? DASH,
120
+ ]);
121
+ for (const [label, key] of STAGES) {
122
+ const bucket = counters?.[key.replace(/Ms$/, "")];
123
+ if (!bucket)
124
+ continue;
125
+ rows.push([
126
+ `${label.replace(" (ms)", "")} SQL`,
127
+ `${bucket.statements ?? 0} statements / ` +
128
+ `${bucket.rowsRead ?? DASH} rows read / ` +
129
+ `${bucket.rowsWritten ?? DASH} rows written`,
130
+ ]);
131
+ }
132
+ const longest = timings?.longestInterval;
133
+ rows.push([
134
+ "Longest interval",
135
+ longest ? `${longest.intervalMs} ms in ${longest.state}` : DASH,
136
+ ]);
137
+ // Stated only when the server stated it — which it does only when the
138
+ // window was measured from `uploading`. `—` here means "not a measurement",
139
+ // and that is the honest thing for it to mean.
140
+ const throughput = session.throughput;
141
+ rows.push([
142
+ "Throughput",
143
+ throughput
144
+ ? `${throughput.rowsPerSecond.toFixed(1)} rows/s, ` +
145
+ `${mbPerSecond(throughput.storedBytesPerSecond)} stored` +
146
+ (throughput.rawBytesPerSecond === null
147
+ ? ""
148
+ : `, ${mbPerSecond(throughput.rawBytesPerSecond)} raw`) +
149
+ ` over ${(throughput.pipelineMs / 1000).toFixed(1)}s`
150
+ : DASH,
151
+ ]);
152
+ return rows;
153
+ }
154
+ /**
155
+ * The client's phases as rows, so the two sides read side by side.
156
+ *
157
+ * The wall-clock number `documents ingest` used to print covered the artifact
158
+ * build, the upload AND everything the platform then did, and could be blamed
159
+ * on either. These say which. A phase the run never finished prints `—`,
160
+ * which here means what it means everywhere else in this file: not a
161
+ * measurement.
162
+ */
163
+ export function ingestClientRows(timings) {
164
+ const rows = [
165
+ ["Client build (ms)", timings.buildMs],
166
+ ["Client create (ms)", timings.createMs ?? DASH],
167
+ ["Client upload (ms)", timings.uploadMs ?? DASH],
168
+ ["Client uploaded bytes", timings.uploadedBytes ?? DASH],
169
+ ["Client commit (ms)", timings.commitMs ?? DASH],
170
+ ["Client wait (ms)", timings.waitMs ?? DASH],
171
+ ];
172
+ const { uploadMs, uploadedBytes } = timings;
173
+ if (uploadMs !== undefined && uploadMs > 0 && (uploadedBytes ?? 0) > 0) {
174
+ rows.push([
175
+ "Client upload rate",
176
+ mbPerSecond((uploadedBytes / uploadMs) * 1000),
177
+ ]);
178
+ }
179
+ return rows;
180
+ }
181
+ //# sourceMappingURL=document-ingest-rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-ingest-rows.js","sourceRoot":"","sources":["../../../src/lib/document-ingest-rows.ts"],"names":[],"mappings":"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"}
@@ -12,13 +12,20 @@
12
12
  * - Ctrl-C during the uploads aborts too, because the session it was filling
13
13
  * is not going to be committed; Ctrl-C while POLLING leaves the session
14
14
  * alone, because by then the document is already being changed and giving up
15
- * on watching is not giving up on the load.
15
+ * on watching is not giving up on the load;
16
+ * - a session READ that fails while polling is retried on a bounded schedule
17
+ * (#3597), for the same reason: the read failing says nothing about the load,
18
+ * and a multi-hour load will meet transient reads. When the bound is spent
19
+ * the wait stops and says the session is still running — it never reports it
20
+ * as cancelled or failed.
16
21
  *
17
22
  * Exit codes follow `functions runs wait`/`invoke`, as `docs/cli-design.md`
18
23
  * records them: 0 completed, 1 failed or refused, 124 a wait that gave up,
19
- * 130 Ctrl-C.
24
+ * 130 Ctrl-C. Both ways of giving up on the WATCHING are 124 and both say the
25
+ * session keeps running; only the load itself failing is 1.
20
26
  */
21
27
  import type { IngestArtifactPlan, IngestChunkDescriptor } from "./document-ingest-artifact.js";
28
+ import type { IngestClientTimings } from "./document-ingest-rows.js";
22
29
  /** A plan the operator did not confirm, or cannot be asked about. */
23
30
  export declare class IngestRefusedError extends Error {
24
31
  constructor(message: string);
@@ -61,6 +68,22 @@ export interface IngestOutcome {
61
68
  session: any | null;
62
69
  /** The reason, for stderr. */
63
70
  message?: string;
71
+ /**
72
+ * What THIS side spent, phase by phase (#3598).
73
+ *
74
+ * A bulk load's wall-clock time used to be one number covering the artifact
75
+ * build, the upload and everything the platform then did, which meant it
76
+ * could be blamed on either side. A phase the run never finished is
77
+ * ABSENT rather than 0 (finding 3598-FROZEN-02): an upload that died
78
+ * halfway has no rate, and a commit that was never reached did not take no
79
+ * time. The one exception is the wait, which is real elapsed time whether
80
+ * or not the session settled, so a poll that fails after minutes reports
81
+ * those minutes (finding 3598-FROZEN-01).
82
+ *
83
+ * `buildMs` is the verb's, not the driver's — the artifact is already built
84
+ * by the time anything here runs — and is filled in by the caller.
85
+ */
86
+ timings: Omit<IngestClientTimings, "buildMs">;
64
87
  }
65
88
  /** The plan summary an operator confirms, one line per row. */
66
89
  export declare function summariseIngestPlan(plan: IngestArtifactPlan): string[];