@pipelex/sdk 0.63.0 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/cli/script.d.ts +1 -1
- package/dist/client.d.ts +162 -7
- package/dist/client.js +222 -10
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js.map +1 -1
- package/dist/method-layouts.d.ts +195 -0
- package/dist/method-layouts.js +121 -0
- package/dist/method-layouts.js.map +1 -0
- package/dist/models.d.ts +27 -0
- package/dist/product-models.d.ts +12 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/architecture.md +3 -1
- package/docs/errors.md +2 -0
- package/docs/method-layouts.md +168 -0
- package/package.json +1 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A method's stored layouts: the layout a producer designed for one pipe of a published version,
|
|
3
|
+
* which the hosted platform stores beside the method (`storeMethodLayout`,
|
|
4
|
+
* `POST /v1/methods/{id}/versions/{n}/layouts`), reads back by the version
|
|
5
|
+
* (`listMethodLayouts`, `GET` of the same route) and hands back on the validate of the method by id
|
|
6
|
+
* that names `layouts` among its `views` (`PipelexValidationReport.layouts`).
|
|
7
|
+
*
|
|
8
|
+
* A layout is a data file: a tree of elements written in the vocabulary of a catalog of
|
|
9
|
+
* components, every value bound to a path in the host's form state, carrying no field
|
|
10
|
+
* descriptions and no data of its own. A host renders it over the input-form descriptor the same
|
|
11
|
+
* validate projects, and renders the plain form instead whenever it cannot. The platform stores and
|
|
12
|
+
* carries it and never judges it. The shapes are stated brand-neutrally, as the input-form
|
|
13
|
+
* descriptor they are rendered over is: snake_case members with no `pipelex_` prefix. The storage
|
|
14
|
+
* and the `layouts` token are the hosted plane's.
|
|
15
|
+
*
|
|
16
|
+
* The readers here check a layout member by member, as `readProblemItems` checks a verdict's
|
|
17
|
+
* items: neither a validate nor a read of a version's layouts loses its other layouts, nor a
|
|
18
|
+
* validate its verdict, to one layout it cannot read.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* How a stored layout was made, as its producer stated it when it wrote the layout. Every member
|
|
22
|
+
* is present on a layout the SDK hands back.
|
|
23
|
+
*/
|
|
24
|
+
export interface LayoutProvenance {
|
|
25
|
+
/** Who produced the layout, a short kebab-case slug such as `pipelex-method`. */
|
|
26
|
+
producer: string;
|
|
27
|
+
/** The id of the model the producer ran, such as `claude-4.8-opus`. */
|
|
28
|
+
model: string;
|
|
29
|
+
/** The creative seed handed to the model with the brief, verbatim; `null` when none was. */
|
|
30
|
+
seed: string | null;
|
|
31
|
+
/**
|
|
32
|
+
* The id of the app style the layout was designed under, such as `editorial`; `null` when it
|
|
33
|
+
* was designed under none. The platform holds it to the shape `^[a-z0-9-]{1,32}$` and never to
|
|
34
|
+
* a list of styles, so a host reads an id it does not know as no style.
|
|
35
|
+
*/
|
|
36
|
+
style: string | null;
|
|
37
|
+
/** How many repair rounds the producer ran before the layout validated against its catalog. */
|
|
38
|
+
repair_rounds: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One stored layout — what `storeMethodLayout` answers, an entry of `listMethodLayouts`'s `items`,
|
|
42
|
+
* and an entry of `PipelexValidationReport.layouts`.
|
|
43
|
+
*
|
|
44
|
+
* Its identity is `tree_digest`, `pipe_ref`, `catalog` and `prompt_hash` within one method: it
|
|
45
|
+
* belongs to the content it was designed for, never to a version number, so it is served for
|
|
46
|
+
* whatever selector of that method resolves the same tree, and a write of the same identity
|
|
47
|
+
* replaces it. It names no method and no version.
|
|
48
|
+
*/
|
|
49
|
+
export interface MethodLayout {
|
|
50
|
+
/**
|
|
51
|
+
* The digest of the method tree the layout was produced against, `sha256:` and 64 lowercase
|
|
52
|
+
* hexadecimal characters: the MTHDS standard's digest of the tree's listing, as a published
|
|
53
|
+
* version's `tree_digest` states it.
|
|
54
|
+
*/
|
|
55
|
+
tree_digest: string;
|
|
56
|
+
/**
|
|
57
|
+
* The namespaced pipe reference it lays out, `domain_path.pipe_code`, as the input-form
|
|
58
|
+
* descriptor keys its forms.
|
|
59
|
+
*/
|
|
60
|
+
pipe_ref: string;
|
|
61
|
+
/** The id of the catalog whose vocabulary it is written in, a slug such as `composer`. */
|
|
62
|
+
catalog: string;
|
|
63
|
+
/** The hash of the prompt the producer's model read, 12 to 64 lowercase hexadecimal digits. */
|
|
64
|
+
prompt_hash: string;
|
|
65
|
+
/**
|
|
66
|
+
* The layout itself, as the producer's model emitted it: JSON patch lines, one per line,
|
|
67
|
+
* carried as one string exactly as written. The platform never parses it.
|
|
68
|
+
*/
|
|
69
|
+
jsonl: string;
|
|
70
|
+
/** How it was made. */
|
|
71
|
+
provenance: LayoutProvenance;
|
|
72
|
+
/** The moment the write that stored it landed, ISO 8601 in UTC: the one member the platform sets. */
|
|
73
|
+
stored_at: string;
|
|
74
|
+
/**
|
|
75
|
+
* A written sample of the result the layout was designed over, as one JSON text the platform
|
|
76
|
+
* stores and never reads, so a host can draw a designed result page before anyone has run the
|
|
77
|
+
* method; `null` when none was stored, and from a platform that predates it. Parse it yourself,
|
|
78
|
+
* and treat it as untrusted: nothing but the JSON syntax was checked.
|
|
79
|
+
*/
|
|
80
|
+
sample_json: string | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The layouts stored for a published version's content — what `listMethodLayouts` answers. `items`
|
|
84
|
+
* is newest first, at most 16, and empty when none is stored.
|
|
85
|
+
*/
|
|
86
|
+
export interface MethodLayoutList {
|
|
87
|
+
items: MethodLayout[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The provenance a write states — `MethodLayoutInput.provenance`. A `null` or omitted optional
|
|
91
|
+
* member is not sent, and the platform stores its default: no seed, no style, no repair round.
|
|
92
|
+
*/
|
|
93
|
+
export interface LayoutProvenanceInput {
|
|
94
|
+
/** Who produced the layout, a slug: 1 to 64 lowercase letters, digits and hyphens, not starting with a hyphen. */
|
|
95
|
+
producer: string;
|
|
96
|
+
/** The id of the model the producer ran: 1 to 128 characters, none of them a control character. */
|
|
97
|
+
model: string;
|
|
98
|
+
/** The creative seed handed to the model with the brief, verbatim, at most 4,000 characters. */
|
|
99
|
+
seed?: string | null;
|
|
100
|
+
/** The id of the app style the layout was designed under, of the shape `^[a-z0-9-]{1,32}$`. */
|
|
101
|
+
style?: string | null;
|
|
102
|
+
/** How many repair rounds the producer ran before the layout validated, from 0 to 100. */
|
|
103
|
+
repair_rounds?: number | null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The write — `storeMethodLayout`, `POST /v1/methods/{id}/versions/{n}/layouts`: the stored layout
|
|
107
|
+
* without `stored_at`. The wire body is closed at both levels, so the client sends these members
|
|
108
|
+
* and nothing else; a `MethodLayout` read back can be passed as it is, its `stored_at` left out and
|
|
109
|
+
* its `sample_json` sent when it holds one.
|
|
110
|
+
* The bounds below are the platform's, which refuses a member breaking one with a `422`
|
|
111
|
+
* `request.invalid` naming it, `provenance.<member>` for one of the provenance's.
|
|
112
|
+
*/
|
|
113
|
+
export interface MethodLayoutInput {
|
|
114
|
+
/**
|
|
115
|
+
* The digest of the tree the layout was produced against, which must be the `tree_digest` of the
|
|
116
|
+
* version the call names (`MethodVersionSummary.tree_digest`): `sha256:` and 64 lowercase
|
|
117
|
+
* hexadecimal characters.
|
|
118
|
+
*/
|
|
119
|
+
tree_digest: string;
|
|
120
|
+
/**
|
|
121
|
+
* The pipe it lays out, `domain_path.pipe_code`: two or more dot-separated identifiers, at most
|
|
122
|
+
* 256 characters in all.
|
|
123
|
+
*/
|
|
124
|
+
pipe_ref: string;
|
|
125
|
+
/** The catalog's id, a slug of the same shape as `provenance.producer`. */
|
|
126
|
+
catalog: string;
|
|
127
|
+
/** The hash of the prompt the producer's model read, 12 to 64 lowercase hexadecimal digits. */
|
|
128
|
+
prompt_hash: string;
|
|
129
|
+
/**
|
|
130
|
+
* The layout as the producer's model emitted it, not empty, at most 128 KiB of UTF-8, holding
|
|
131
|
+
* no raw control character but the tab, the line feed and the carriage return.
|
|
132
|
+
*/
|
|
133
|
+
jsonl: string;
|
|
134
|
+
/** How it was made. */
|
|
135
|
+
provenance: LayoutProvenanceInput;
|
|
136
|
+
/**
|
|
137
|
+
* A written sample of the result the layout was designed over, one JSON text of at most 64 KiB of
|
|
138
|
+
* UTF-8, which the platform refuses if it does not parse. A `null` or omitted sample is not sent,
|
|
139
|
+
* and the write stores none, whatever the layout it replaces held.
|
|
140
|
+
*
|
|
141
|
+
* **Only a written sample belongs here, invented from the description of the result and holding
|
|
142
|
+
* no customer's data, never a run's output.** A layout's readers include the method's runners
|
|
143
|
+
* and, for a public method, other organizations, and the platform never reads the sample, so
|
|
144
|
+
* keeping that rule is the producer's.
|
|
145
|
+
*/
|
|
146
|
+
sample_json?: string | null;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The members the write takes besides `provenance`, `required` ones sent each time and `optional`
|
|
150
|
+
* ones only when given and not `null`. Checked against `MethodLayoutInput` with `satisfies`, so a
|
|
151
|
+
* member the interface gains and this list lacks fails the build rather than being dropped from
|
|
152
|
+
* the body without a word.
|
|
153
|
+
*/
|
|
154
|
+
export declare const LAYOUT_INPUT_MEMBERS: {
|
|
155
|
+
readonly tree_digest: "required";
|
|
156
|
+
readonly pipe_ref: "required";
|
|
157
|
+
readonly catalog: "required";
|
|
158
|
+
readonly prompt_hash: "required";
|
|
159
|
+
readonly jsonl: "required";
|
|
160
|
+
readonly sample_json: "optional";
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* The members of the write's provenance, `required` ones sent each time and `optional` ones only
|
|
164
|
+
* when given and not `null`, checked against `LayoutProvenanceInput` as `LAYOUT_INPUT_MEMBERS` is.
|
|
165
|
+
*/
|
|
166
|
+
export declare const PROVENANCE_INPUT_MEMBERS: {
|
|
167
|
+
readonly producer: "required";
|
|
168
|
+
readonly model: "required";
|
|
169
|
+
readonly seed: "optional";
|
|
170
|
+
readonly style: "optional";
|
|
171
|
+
readonly repair_rounds: "optional";
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* What keeps `value` from reading as a stored layout, as the end of a sentence naming it ("a
|
|
175
|
+
* layout whose `jsonl` is not a string"), or `null` when it reads as one: an object whose
|
|
176
|
+
* `tree_digest`, `pipe_ref`, `catalog`, `prompt_hash`, `jsonl` and `stored_at` are strings and
|
|
177
|
+
* whose `provenance` is an object with a string `producer` and `model`. The provenance's optional
|
|
178
|
+
* members never keep a layout from reading (`readMethodLayout`).
|
|
179
|
+
*/
|
|
180
|
+
export declare function methodLayoutFault(value: unknown): string | null;
|
|
181
|
+
/**
|
|
182
|
+
* `value` read as a stored layout, or `null` when it does not read as one (`methodLayoutFault`).
|
|
183
|
+
* The layout's `sample_json` and the provenance's `seed` and `style` are kept only when each is a
|
|
184
|
+
* string, and read as `null` otherwise, and its `repair_rounds` only when it is a non-negative
|
|
185
|
+
* integer, and read as `0` otherwise: the platform's own defaults, so each member is what
|
|
186
|
+
* `MethodLayout` and `LayoutProvenance` declare. The rest is returned as it came.
|
|
187
|
+
*/
|
|
188
|
+
export declare function readMethodLayout(value: unknown): MethodLayout | null;
|
|
189
|
+
/**
|
|
190
|
+
* A list of layouts read entry by entry, a valid report's `layouts` or `listMethodLayouts`'s
|
|
191
|
+
* `items`: each entry that reads as a layout (`readMethodLayout`), in the answer's order, newest
|
|
192
|
+
* first as the platform sends them, and anything else left out. A value that is not an array reads
|
|
193
|
+
* as no layout.
|
|
194
|
+
*/
|
|
195
|
+
export declare function readMethodLayouts(value: unknown): MethodLayout[];
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A method's stored layouts: the layout a producer designed for one pipe of a published version,
|
|
3
|
+
* which the hosted platform stores beside the method (`storeMethodLayout`,
|
|
4
|
+
* `POST /v1/methods/{id}/versions/{n}/layouts`), reads back by the version
|
|
5
|
+
* (`listMethodLayouts`, `GET` of the same route) and hands back on the validate of the method by id
|
|
6
|
+
* that names `layouts` among its `views` (`PipelexValidationReport.layouts`).
|
|
7
|
+
*
|
|
8
|
+
* A layout is a data file: a tree of elements written in the vocabulary of a catalog of
|
|
9
|
+
* components, every value bound to a path in the host's form state, carrying no field
|
|
10
|
+
* descriptions and no data of its own. A host renders it over the input-form descriptor the same
|
|
11
|
+
* validate projects, and renders the plain form instead whenever it cannot. The platform stores and
|
|
12
|
+
* carries it and never judges it. The shapes are stated brand-neutrally, as the input-form
|
|
13
|
+
* descriptor they are rendered over is: snake_case members with no `pipelex_` prefix. The storage
|
|
14
|
+
* and the `layouts` token are the hosted plane's.
|
|
15
|
+
*
|
|
16
|
+
* The readers here check a layout member by member, as `readProblemItems` checks a verdict's
|
|
17
|
+
* items: neither a validate nor a read of a version's layouts loses its other layouts, nor a
|
|
18
|
+
* validate its verdict, to one layout it cannot read.
|
|
19
|
+
*/
|
|
20
|
+
import { isPlainObject } from "./records.js";
|
|
21
|
+
/**
|
|
22
|
+
* The members the write takes besides `provenance`, `required` ones sent each time and `optional`
|
|
23
|
+
* ones only when given and not `null`. Checked against `MethodLayoutInput` with `satisfies`, so a
|
|
24
|
+
* member the interface gains and this list lacks fails the build rather than being dropped from
|
|
25
|
+
* the body without a word.
|
|
26
|
+
*/
|
|
27
|
+
export const LAYOUT_INPUT_MEMBERS = {
|
|
28
|
+
tree_digest: "required",
|
|
29
|
+
pipe_ref: "required",
|
|
30
|
+
catalog: "required",
|
|
31
|
+
prompt_hash: "required",
|
|
32
|
+
jsonl: "required",
|
|
33
|
+
sample_json: "optional",
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The members of the write's provenance, `required` ones sent each time and `optional` ones only
|
|
37
|
+
* when given and not `null`, checked against `LayoutProvenanceInput` as `LAYOUT_INPUT_MEMBERS` is.
|
|
38
|
+
*/
|
|
39
|
+
export const PROVENANCE_INPUT_MEMBERS = {
|
|
40
|
+
producer: "required",
|
|
41
|
+
model: "required",
|
|
42
|
+
seed: "optional",
|
|
43
|
+
style: "optional",
|
|
44
|
+
repair_rounds: "optional",
|
|
45
|
+
};
|
|
46
|
+
/** The members of a layout read as strings, in the order a fault names the first one missing. */
|
|
47
|
+
const LAYOUT_STRING_MEMBERS = [
|
|
48
|
+
"tree_digest",
|
|
49
|
+
"pipe_ref",
|
|
50
|
+
"catalog",
|
|
51
|
+
"prompt_hash",
|
|
52
|
+
"jsonl",
|
|
53
|
+
"stored_at",
|
|
54
|
+
];
|
|
55
|
+
/** The members of a layout's provenance read as strings. */
|
|
56
|
+
const PROVENANCE_STRING_MEMBERS = ["producer", "model"];
|
|
57
|
+
/**
|
|
58
|
+
* What keeps `value` from reading as a stored layout, as the end of a sentence naming it ("a
|
|
59
|
+
* layout whose `jsonl` is not a string"), or `null` when it reads as one: an object whose
|
|
60
|
+
* `tree_digest`, `pipe_ref`, `catalog`, `prompt_hash`, `jsonl` and `stored_at` are strings and
|
|
61
|
+
* whose `provenance` is an object with a string `producer` and `model`. The provenance's optional
|
|
62
|
+
* members never keep a layout from reading (`readMethodLayout`).
|
|
63
|
+
*/
|
|
64
|
+
export function methodLayoutFault(value) {
|
|
65
|
+
if (!isPlainObject(value))
|
|
66
|
+
return "that is not an object";
|
|
67
|
+
for (const member of LAYOUT_STRING_MEMBERS) {
|
|
68
|
+
if (typeof value[member] !== "string")
|
|
69
|
+
return `whose \`${member}\` is not a string`;
|
|
70
|
+
}
|
|
71
|
+
const provenance = value.provenance;
|
|
72
|
+
if (!isPlainObject(provenance))
|
|
73
|
+
return "whose `provenance` is not an object";
|
|
74
|
+
for (const member of PROVENANCE_STRING_MEMBERS) {
|
|
75
|
+
if (typeof provenance[member] !== "string") {
|
|
76
|
+
return `whose \`provenance.${member}\` is not a string`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* `value` read as a stored layout, or `null` when it does not read as one (`methodLayoutFault`).
|
|
83
|
+
* The layout's `sample_json` and the provenance's `seed` and `style` are kept only when each is a
|
|
84
|
+
* string, and read as `null` otherwise, and its `repair_rounds` only when it is a non-negative
|
|
85
|
+
* integer, and read as `0` otherwise: the platform's own defaults, so each member is what
|
|
86
|
+
* `MethodLayout` and `LayoutProvenance` declare. The rest is returned as it came.
|
|
87
|
+
*/
|
|
88
|
+
export function readMethodLayout(value) {
|
|
89
|
+
if (methodLayoutFault(value) !== null)
|
|
90
|
+
return null;
|
|
91
|
+
const layout = value;
|
|
92
|
+
const { seed, style, repair_rounds: rounds } = layout.provenance;
|
|
93
|
+
return {
|
|
94
|
+
...layout,
|
|
95
|
+
sample_json: typeof layout.sample_json === "string" ? layout.sample_json : null,
|
|
96
|
+
provenance: {
|
|
97
|
+
...layout.provenance,
|
|
98
|
+
seed: typeof seed === "string" ? seed : null,
|
|
99
|
+
style: typeof style === "string" ? style : null,
|
|
100
|
+
repair_rounds: Number.isSafeInteger(rounds) && rounds >= 0 ? rounds : 0,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* A list of layouts read entry by entry, a valid report's `layouts` or `listMethodLayouts`'s
|
|
106
|
+
* `items`: each entry that reads as a layout (`readMethodLayout`), in the answer's order, newest
|
|
107
|
+
* first as the platform sends them, and anything else left out. A value that is not an array reads
|
|
108
|
+
* as no layout.
|
|
109
|
+
*/
|
|
110
|
+
export function readMethodLayouts(value) {
|
|
111
|
+
if (!Array.isArray(value))
|
|
112
|
+
return [];
|
|
113
|
+
const layouts = [];
|
|
114
|
+
for (const entry of value) {
|
|
115
|
+
const layout = readMethodLayout(entry);
|
|
116
|
+
if (layout !== null)
|
|
117
|
+
layouts.push(layout);
|
|
118
|
+
}
|
|
119
|
+
return layouts;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=method-layouts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method-layouts.js","sourceRoot":"","sources":["../src/method-layouts.ts"],"names":[],"mappings":"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"}
|
package/dist/models.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* `mthds/protocol` subpath.
|
|
11
11
|
*/
|
|
12
12
|
import type { InputForm, MethodFiles, ProblemItem, MethodTreeSource, OutputForm, PipeIOContracts, RunResultExecute, RunResultStart } from "mthds/protocol";
|
|
13
|
+
import type { MethodLayout } from "./method-layouts.js";
|
|
13
14
|
import type { MethodTreeForm, NoMethodTree } from "./method-trees.js";
|
|
14
15
|
export interface DictStuff {
|
|
15
16
|
concept: string;
|
|
@@ -141,6 +142,14 @@ export type PipelexValidateSource = (MethodTreeForm & {
|
|
|
141
142
|
method_ref?: never;
|
|
142
143
|
method_id?: never;
|
|
143
144
|
}) | (ValidateMethodSelector & NoMethodTree);
|
|
145
|
+
/**
|
|
146
|
+
* The `views` tokens this SDK knows, each adding the same-named top-level member to the valid
|
|
147
|
+
* report: `input_form` and `output_form`, the runner's per-pipe form descriptors, and `layouts`, the
|
|
148
|
+
* hosted plane's stored layouts of a method validated by `method_id`. `ValidateOptions.views` reads
|
|
149
|
+
* them open: a token a later server adds is sent as its raw string, and a server ignores a token it
|
|
150
|
+
* does not know, never answering a `422` for one.
|
|
151
|
+
*/
|
|
152
|
+
export type ValidateView = "input_form" | "output_form" | "layouts";
|
|
144
153
|
/** Per-pipe dry-run verdict in `validated_pipes[]` — mirror of pipelex's `DryRunStatus`. */
|
|
145
154
|
export type DryRunStatus = "SUCCESS" | "FAILURE" | "SKIPPED";
|
|
146
155
|
/** One entry of `PipelexValidationReport.validated_pipes` — `{pipe_ref, status}`. */
|
|
@@ -262,6 +271,24 @@ export interface PipelexValidationReport {
|
|
|
262
271
|
* through `views: ["output_form"]` and absent from any verdict that did not ask.
|
|
263
272
|
*/
|
|
264
273
|
output_form?: OutputForm;
|
|
274
|
+
/**
|
|
275
|
+
* The layouts stored for the method's content, newest first by `stored_at`, at most 16: a
|
|
276
|
+
* Pipelex hosted extension, requested through `views: ["layouts"]` on a validate naming a stored
|
|
277
|
+
* method by `method_id`, and carried for every selector of that method resolving the same tree
|
|
278
|
+
* (the version it was written against, a later version holding the same tree, the draft holding
|
|
279
|
+
* it). Ask for `["input_form", "layouts"]` to receive the descriptor and the layouts over it in
|
|
280
|
+
* one answer.
|
|
281
|
+
*
|
|
282
|
+
* **Absent means none**: the member is left out when the validate names no `method_id`, when
|
|
283
|
+
* `views` does not name `layouts`, when no layout is stored for the resolved tree, and when the
|
|
284
|
+
* platform could not read them, so a host never reads an empty array and renders the plain form
|
|
285
|
+
* whenever it is absent. A platform that does not carry the view leaves it out too; its
|
|
286
|
+
* `GET /v1/version` does not list `method_layouts` among its `extensions`.
|
|
287
|
+
*
|
|
288
|
+
* Read entry by entry (`readMethodLayouts`): an entry that does not read as a layout is left
|
|
289
|
+
* out rather than failing the verdict, and a list left with none reads as absent.
|
|
290
|
+
*/
|
|
291
|
+
layouts?: MethodLayout[];
|
|
265
292
|
/** Pipes the runtime may skip when an optional slot resolves absent. */
|
|
266
293
|
liftable_pipes: LiftablePipeEntry[];
|
|
267
294
|
/**
|
package/dist/product-models.d.ts
CHANGED
|
@@ -191,6 +191,13 @@ export interface MethodData {
|
|
|
191
191
|
* arrives as its raw string. The list rows (`MethodSummary`) do not carry it.
|
|
192
192
|
*/
|
|
193
193
|
visibility?: MethodVisibility | (string & {});
|
|
194
|
+
/**
|
|
195
|
+
* The ids of the catalogs whose layouts a builder switched off, which no host draws: it draws the
|
|
196
|
+
* plain page instead, and the layouts are kept. Written whole by `setMethodLayoutsOff`, it acts at
|
|
197
|
+
* once and holds across every publish. Absent from a platform that predates it, which means none.
|
|
198
|
+
* The list rows (`MethodSummary`) do not carry it.
|
|
199
|
+
*/
|
|
200
|
+
layouts_off?: string[];
|
|
194
201
|
}
|
|
195
202
|
/** Who may see a method — `MethodData.visibility`. */
|
|
196
203
|
export type MethodVisibility = "internal" | "public";
|
|
@@ -255,6 +262,11 @@ export interface PublicMethodDetail {
|
|
|
255
262
|
latest_published: MethodVersionSummary;
|
|
256
263
|
/** `public`: another organization reads a method only while it is public. */
|
|
257
264
|
visibility: MethodVisibility | (string & {});
|
|
265
|
+
/**
|
|
266
|
+
* The ids of the catalogs whose layouts no host draws, as on `MethodData.layouts_off`: a reader
|
|
267
|
+
* of the method draws the plain page for those. Absent from a platform that predates it.
|
|
268
|
+
*/
|
|
269
|
+
layouts_off?: string[];
|
|
258
270
|
/** The latest published version's tree, one entry per file in tree path order. */
|
|
259
271
|
files: SavedMethodFile[];
|
|
260
272
|
}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/docs/architecture.md
CHANGED
|
@@ -117,6 +117,7 @@ Flat `src/` (mirrors `mthds-js`'s `runners/api` flatness — the SDK has one cli
|
|
|
117
117
|
- `client.ts` — `PipelexApiClient`: the `request()` pipeline (auth, base URL, timeouts/abort, problem-details parsing) and every route. It implements the standard's `MTHDSProtocol<DictPipeOutput>` for every route but `validate`, so the protocol-execution methods stay shaped like the standard: `validate` answers Pipelex's own verdict, `PipelexValidationResult`, because the hosted plane still sends the verdict that predates the protocol's problem items, where the standard's `ValidationResult` lists them.
|
|
118
118
|
- `models.ts` — Dict-serialized concretes (`DictStuff` / `DictWorkingMemory` / `DictPipeOutput` / `DictRunResultExecute`), the `/v1/validate` surface (`PipelexValidationResult`, whose two arms are declared whole rather than as narrowings of the standard's `ValidationResult`, listing their faults and warnings as the standard's `ProblemItem`, with its `SuggestedFix` and `FixOp`, see [errors.md](./errors.md#a-verdicts-problem-items)), the tools surface (`Diagnostic` / `LintResponse` / `FormatResponse`), and the crate-route request/response models — the shared `CrateRequestBase` / `CrateInvalidReport` vocabulary plus the `/v1/resolve`, `/v1/codegen` and `/v1/pipe-io` shapes built on it, `GeneratedArtifact` among them.
|
|
119
119
|
- `product-models.ts` — the snake_case wire shapes for the hosted-product management routes (profile, methods catalog, organizations, billing, API keys, onboarding, storage, an organization's files, runs list/detail/update). Each interface models only the fields the product actually consumes — no speculative mirrors.
|
|
120
|
+
- `method-layouts.ts` — a method's stored layouts: `MethodLayoutInput` and `LayoutProvenanceInput`, the write `storeMethodLayout` sends, `MethodLayout` and `LayoutProvenance`, what the platform stores, answers and carries on a validate's `layouts`, `MethodLayoutList`, what `listMethodLayouts` answers, and the reader they all go through, `readMethodLayout` (with `methodLayoutFault`, which names the member an unreadable layout breaks, and `readMethodLayouts`, which reads a list of layouts entry by entry). It imports the plain-object guard of `records.ts` and nothing else. The Python twin is `pipelex_sdk/method_layout_models.py`. See [method-layouts.md](./method-layouts.md).
|
|
120
121
|
- `answer-reading.ts` — `readHostedAnswer`, the reading of an answer that is not the route's result as its problem: a problem document as received, and an answer whose body is none, the hosted edge's, a gateway's or a proxy's, by its status, `client.outcome_unknown` for a start or an execute that may have created a run; and `outcomeUnknownProblem`. `ApiResponseError` reads every answer through it. The Python twin is `pipelex_sdk/answer_reading.py`. See [errors.md](./errors.md#an-answer-that-is-no-problem-document).
|
|
121
122
|
- `transport-reading.ts` — `requestMayHaveLeft`, the **pure** reading of whether a request that got no answer may have left this machine, every failure counting unless it proves nothing was sent (a failure of the connection's set-up). `ApiUnreachableError` applies it on a start or an execute, which the client marks with `mayStartRun`, to read the failure as `client.unreachable` or `client.outcome_unknown`. The Python twin is `pipelex_sdk/transport_reading.py`. See [errors.md](./errors.md#a-run-that-may-have-started--outcome_unknown).
|
|
122
123
|
- `problem-items.ts` — `readProblemItems`, the reading of a verdict's `errors` and `warnings` as the standard's problem items, member by member, so one malformed member never costs the caller its fault. The Python twin is `pipelex_sdk/problem_items.py`. See [errors.md](./errors.md#a-verdicts-problem-items).
|
|
@@ -140,7 +141,7 @@ Flat `src/` (mirrors `mthds-js`'s `runners/api` flatness — the SDK has one cli
|
|
|
140
141
|
## Client surface (current)
|
|
141
142
|
|
|
142
143
|
- **Protocol execution:** `execute` (returns a `PipelexExecuteResult` with a resolved `.main_stuff`), `start`, `validate` (returns `PipelexValidationResult`), `models`, `version`.
|
|
143
|
-
- **Two independent opt-in lists on `validate`.** `render` asks the server to render a *view format* and adds a `rendered_<format>` field; `views` asks for a *structured view* and adds a same-named top-level field — today `input_form` and `output_form`, the per-pipe form descriptors. A caller that wants the forms without the dry-run verdict reads `pipeIo` instead, which derives them with no dry run. Each resolves its own tokens against its own supported set and unknown tokens are lenient-ignored on both, never a `422`. The client always asks for `render: ["markdown"]` but sends `views` only when a caller names a token, because an opt-in view exists precisely so the default response stays byte-identical for the consumers that discard it. `pipelex-api` gates `input_form` on the token as of 0.18.0; a 0.17.0 runner resolved no token and emitted the field on every valid verdict, which is why `PipelexValidationReport.input_form` is typed optional rather than required — the one typing that reads a response from either runner correctly.
|
|
144
|
+
- **Two independent opt-in lists on `validate`.** `render` asks the server to render a *view format* and adds a `rendered_<format>` field; `views` asks for a *structured view* and adds a same-named top-level field — today `input_form` and `output_form`, the per-pipe form descriptors, and on a hosted validate by `method_id`, `layouts`, the layouts stored for the resolved tree, read entry by entry and absent when there are none ([method-layouts.md](./method-layouts.md)). `ValidateView` names the tokens this SDK knows, and `views` still takes any other as its raw string. A caller that wants the forms without the dry-run verdict reads `pipeIo` instead, which derives them with no dry run. Each resolves its own tokens against its own supported set and unknown tokens are lenient-ignored on both, never a `422`. The client always asks for `render: ["markdown"]` but sends `views` only when a caller names a token, because an opt-in view exists precisely so the default response stays byte-identical for the consumers that discard it. `pipelex-api` gates `input_form` on the token as of 0.18.0; a 0.17.0 runner resolved no token and emitted the field on every valid verdict, which is why `PipelexValidationReport.input_form` is typed optional rather than required — the one typing that reads a response from either runner correctly.
|
|
144
145
|
- **The method's tree:** `execute` / `start` / `startAndWaitForResult` (both paths) and `validate` take the whole method as its tree — every `.mthds` bundle, its `funcs/*.py`, `structures/*.py` and `requirements.txt`, and every file a step reads, such as a `PipeDocGen` step's template — in one of four forms, `directory`, `contents`, `tree` or `files`, sent inline or by hash. `startAndWaitForResult` prepares the tree once, under its `signal`, before it starts the run, so its fallback to the blocking execute sends the same files without reading or uploading them again. A tree is self-contained, so it satisfies the "something to run" precondition on its own — `pipe_code` is not required beside it. See [run-sources](#run-sources) above and [method-trees.md](./method-trees.md).
|
|
145
146
|
- **Method selectors on the run methods:** `execute` / `start` / `startAndWaitForResult` take the Pipelex API's `method_ref` (an address the runner resolves; provenance comes back typed as `method_provenance`) and the platform's `method_id` as **typed named options** (`PipelexRunOptions` / `PipelexStartOptions`), never `extra` entries. See [Pipelex API run extensions](#pipelex-api-run-extensions-method_ref) and [hosted run extensions](#hosted-run-extensions-method_id) above.
|
|
146
147
|
- **An idempotency key on a run start (hosted):** `start` and `startAndWaitForResult` take `idempotencyKey` (`PipelexStartRequestOptions`, intersected into `PipelexStartOptions`), sent as the `Idempotency-Key` header of `POST /v1/start` and never in the body; with no key there is no header. The hosted API binds the key to the run, answers a repeat of the same start with that run, and refuses the key with other options; a bare runner ignores the header. The client refuses a key that is not 1 to 255 visible ASCII characters with a `RequestArgumentError` before any request, the blocking `execute` fallback of `startAndWaitForResult` sends none, and the key leaves the error's problem as it is: a start that may have reached the server stays `client.outcome_unknown`, and the caller who sent a key recovers the run by sending the same start again under it. [errors.md](./errors.md#a-starts-idempotency-key--idempotencykey) holds the contract.
|
|
@@ -161,6 +162,7 @@ The hosted catalog/account routes the webapp drives. All ride the same `{base}/v
|
|
|
161
162
|
- **Method examples:** `createMethodExample`, `listMethodExamples`, `iterateMethodExamples`, `getMethodExample`, `updateMethodExample`, `recordMethodExampleLatestRun`, `saveAssistantMethodExample`, `deleteMethodExample`, on `/v1/methods/{id}/examples`. An example is a named set of inputs saved on a method, shared across the organization, with an `input_revision` that rises each time its inputs change and the `latest_run_id` of those inputs, which an inputs edit clears. `recordMethodExampleLatestRun` records a run against the revision whose inputs it used and answers a `MethodExampleLatestRunResult` discriminated on `outcome`, `recorded` or `stale`, each arm carrying the `example`: a run that outlasted an edit is a verdict, never thrown, and an answer off the union is one the SDK cannot read; `saveAssistantMethodExample` is the build assistant's save, which writes into the example it names only while that example is still the assistant's (`kept_by_assistant`) at the revision it read, and otherwise creates one, answering a `MethodExampleAssistantSaveResult` discriminated on `outcome`, `kept` or `created`; one helper, `readVerdict`, reads these verdicts and `publishMethod`'s, the example checked once, by the reader every example goes through. Every answer carrying an example is read with `parseExactJson` and every request body written with `stringifyExactJson`, so an integer past `Number.MAX_SAFE_INTEGER` in the inputs reads as a `bigint` and goes back digit for digit, to an edit or as a run's inputs; `3.0` still reads as `3`, and inputs holding one sent back unchanged are an edit for the platform, which compares inputs as canonical JSON. Every example the client hands back, the page rows and the verdict's `example` included, is checked by `readMethodExample` against the fields the Python SDK's model requires, with the strict types it holds them to, an example breaking one being an answer the SDK cannot read. The list is paged oldest first by an opaque cursor, and a page may be short while `nextCursor` is set; `iterateMethodExamples` follows it through the loop `iterateMethods` and `iterateRuns` share, and refuses a method id at the call rather than at the first pull. Every method takes a bare catalog id, and the client refuses an example id that is empty, `.` or `..` or holds a lone surrogate, a create without its name or inputs or whose `run_id` is given but empty, an edit naming neither `name` nor `inputs`, and a latest-run write without a run id or a positive integer revision before sending. See [method-examples.md](./method-examples.md).
|
|
162
163
|
- **Template catalog:** `listMethodTemplates`, `iterateMethodTemplates`, on `GET /v1/method-templates`, and `listMethodCategories`, on `GET /v1/method-categories`. The public methods of the deployment's templates organization, in the order the platform serves for the `ordering` asked for, filtered by `category`, with the page's `categories` and each card's thumbnails behind short-lived links. `listMethodTemplates` reads the page with its own reader rather than `requestPage`, since its `ordering` and `categories` sit beside `items` and `nextCursor`, and redacts the links of an answer it cannot read; `iterateMethodTemplates` follows the cursor with the same ordering and category. `listMethodCategories` reads the catalog's whole list of categories, which an admin of the platform keeps, in its order. Both check each category with one reader, `methodCategoriesFault`: a string `slug` and `label`, and `labels`, an object of strings by language tag ([public-methods.md](./public-methods.md)).
|
|
163
164
|
- **Method copies:** `copyMethod`, on `/v1/methods/{id}/copy`. `copyMethod` makes a new, unpublished method in an organization the caller may change methods in, the method's own for a duplicate, holding the original's draft tree, its form inputs and its examples, the stored files they name copied into the destination, and answers a `MethodCopyResult` discriminated on `outcome`: `copied` with the copy as `method` and what was copied, or `refused` with the `references` of a bundle naming storage the destination cannot read or, in a duplicate, a file under the original's run files, which erasing the original would remove. The two arms carry different members, so the verdict is read by the copy itself rather than by `readVerdict`, which reads verdicts whose arms share one: an `outcome` off the union, a `copied` answer whose `method` is not an object and a `refused` one whose `references` is not an array are each an answer the SDK cannot read. Its body is closed, `destination_org_id` with `name` and `expected_draft_updated_at` when given, and its last argument takes an `idempotencyKey`, sent as the `Idempotency-Key` header through the same `requestRaw` option and the same `idempotencyKeyOf` check a start uses. Every method read carries `copied_from`, the original a copy names, `null` on a method created afresh. `MethodErrorCode` names the copy's own codes, `pipelex.org.not_found` and `pipelex.catalog.copy_too_large`, whose `limit` member is typed `MethodCopyLimit`. It takes a bare catalog id. See [method-copy.md](./method-copy.md).
|
|
165
|
+
- **Method layouts:** `storeMethodLayout` and `listMethodLayouts`, on `/v1/methods/{id}/versions/{n}/layouts`, `setMethodLayoutsOff`, on `/v1/methods/{id}/layouts-off`, and the `layouts` view of `validate`. A layout is a data file a producer designed for one pipe of a published version, which the platform stores keyed by the content it was designed for, `tree_digest`, `pipe_ref`, `catalog` and `prompt_hash`, a write of the same identity replacing it, and carries on every validate by `method_id` that names `layouts` and resolves the same tree. The write takes a bare catalog id and a positive integer version, refuses a layout or a provenance that is not an object before sending, and sends the closed body alone, its members listed once in `method-layouts.ts` (`LAYOUT_INPUT_MEMBERS`, `PROVENANCE_INPUT_MEMBERS`) and held to the input interfaces by `satisfies`, `sample_json` and each optional provenance member that is `null` or omitted left out; its last argument takes an `idempotencyKey` (`MethodLayoutWriteOptions`), sent as the `Idempotency-Key` header through the same `idempotencyKeyOf` check a start and a copy use, since a write sent again without one runs again, restamping the layout and applying the bound again; the platform's refusals (`422` `request.invalid` naming the member, `tree_digest` among them for a tree that is not the version's, `403` `auth.forbidden` for a runner, `404` `pipelex.catalog.not_found` naming the method or the version, `409` `pipelex.catalog.being_deleted`) are `ApiResponseError`s. One reader in `method-layouts.ts`, `readMethodLayout`, holds the write's answer and each entry of a report's `layouts` to the same rule, the six identity and payload members strings and the provenance an object with a string `producer` and `model`, its `seed` and `style` read as `null` and its `repair_rounds` as `0` when they do not fit; an answer breaking it is one the SDK cannot read, and an entry breaking it is left out of the report, a list left with none removed, so `layouts` is absent or holds at least one layout. `listMethodLayouts` reads the same list with no dry run, its `items` read entry by entry by that rule, and `setMethodLayoutsOff` writes the whole list of switched-off catalogs, an array or a `RequestArgumentError` before sending, its idempotency key sent as the write's is. See [method-layouts.md](./method-layouts.md).
|
|
164
166
|
- **Organizations:** `listMemberships`, `createOrganization`, `renameOrganization` (`PATCH`). Each membership carries the caller's `role_in_org`, an `OrgRole` (`admin`, `member` or `runner`) read open: a role a later platform adds arrives as its raw string, so a `switch` over it says what an unknown role does. The role is for display; what it may do is the platform's to decide, and a call refused to the caller's role is an `ApiResponseError`. The org "switch" is a WorkOS-session op (`/api/active-org`), not a `/v1` route — out of SDK scope.
|
|
165
167
|
- **Organization branding:** `getBranding` (`GET /v1/branding`, any role, web session or API key) and `updateOrganizationBranding` (`PATCH /v1/organizations/{org_id}/branding`, a write by the `admin` or the `member` role, never a `runner`) answer the same `OrganizationBranding`: the organization's name, its light and dark colour sets (`BrandingColors`), its square and wide logos (`LogoDescriptor`), its app `style` and `typeface`, and its read-only `white_label` entitlement, the last three read as `null`, `null` and `false` from a platform that predates them. The write's `OrganizationBrandingUpdate` sets a key given a value, clears a key given `null` and keeps a key left out; a refused field is named by its `location.field`, a colour by its dotted key, a logo by its slot in `ApiResponseError.errors` with a `LogoRefusalCode` when the platform measured it. See [organization-branding.md](./organization-branding.md).
|
|
166
168
|
- **Caller webhooks:** `listRunWebhookDeliveries`, `getRunWebhookDelivery` and `replayRunWebhookDelivery`, on `/v1/runs/{id}/webhook-deliveries`, `/v1/runs/{id}/webhook-deliveries/{delivery_id}` and its `/replay`, read a run's delivery log and send a settled delivery again, any member by web session or API key, the replay taking an `idempotencyKey` under which the platform stores its answer; `getWebhookSecret`, on `GET /v1/organizations/{org_id}/webhook-secret`, and `rotateWebhookSecret`, on `POST /v1/organizations/{org_id}/webhook-secret/rotate`, read and rotate the organization's signing secret, an admin's routes from a web session only, the rotation taking an `idempotencyKey` the platform never replays. See [webhooks.md](./webhooks.md).
|
package/docs/errors.md
CHANGED
|
@@ -96,6 +96,8 @@ What the hosted API answers a start sent under a key:
|
|
|
96
96
|
|
|
97
97
|
**A copy takes a key too.** `copyMethod` sends an `idempotencyKey` the same way, held to the same rule, and the hosted API keeps it for the same 24 hours, scoped to the caller and the method's organization. A copy binds no run, so its answers under a key differ from a start's: [method-copy.md](./method-copy.md#retrying-a-copy--idempotencykey) gives them.
|
|
98
98
|
|
|
99
|
+
**And a layout write.** `storeMethodLayout` sends an `idempotencyKey` the same way, held to the same rule. A write sent again without one runs again, restamping the layout and applying the bound of layouts a content keeps again, so a write whose answer was lost is sent again under the key it was first sent with, which answers it as the first write was answered: [method-layouts.md](./method-layouts.md#storing-a-layout) gives the answers. `setMethodLayoutsOff` takes a key by the same rule, since a write of the whole list sent again undoes a switch that landed in between.
|
|
100
|
+
|
|
99
101
|
**So do a secret rotation and a delivery replay.** `rotateWebhookSecret` and `replayRunWebhookDelivery` send an `idempotencyKey` the same way, held to the same rule. A rotation's answer carries a secret, so the platform never replays it, while a replay's stored answer is given again: [webhooks.md](./webhooks.md) gives both.
|
|
100
102
|
|
|
101
103
|
## Each class's problem
|