@pipelex/sdk 0.51.0 → 0.53.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 +20 -19
- package/dist/answer-reading.d.ts +70 -0
- package/dist/answer-reading.js +106 -0
- package/dist/answer-reading.js.map +1 -0
- package/dist/artifacts.js +45 -32
- package/dist/artifacts.js.map +1 -1
- package/dist/cli/present.d.ts +11 -14
- package/dist/cli/present.js +41 -37
- package/dist/cli/present.js.map +1 -1
- package/dist/cli/run.js +8 -7
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/script.d.ts +1 -1
- package/dist/cli/source.js +2 -2
- package/dist/cli/source.js.map +1 -1
- package/dist/client.d.ts +254 -213
- package/dist/client.js +542 -472
- package/dist/client.js.map +1 -1
- package/dist/codegen-check.d.ts +21 -15
- package/dist/codegen-check.js +54 -27
- package/dist/codegen-check.js.map +1 -1
- package/dist/errors.d.ts +298 -455
- package/dist/errors.js +426 -534
- package/dist/errors.js.map +1 -1
- package/dist/exact-json.d.ts +8 -12
- package/dist/exact-json.js +19 -12
- package/dist/exact-json.js.map +1 -1
- package/dist/hooks/check-core.d.ts +12 -7
- package/dist/hooks/check-core.js +20 -14
- package/dist/hooks/check-core.js.map +1 -1
- package/dist/hooks/validate-stage.js +12 -3
- package/dist/hooks/validate-stage.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/method-selector.js +7 -5
- package/dist/method-selector.js.map +1 -1
- package/dist/method-trees.d.ts +6 -7
- package/dist/method-trees.js +31 -37
- package/dist/method-trees.js.map +1 -1
- package/dist/models.d.ts +33 -210
- package/dist/models.js +2 -1
- package/dist/models.js.map +1 -1
- package/dist/prepare-inputs.d.ts +2 -2
- package/dist/prepare-inputs.js +51 -54
- package/dist/prepare-inputs.js.map +1 -1
- package/dist/problem-items.d.ts +19 -0
- package/dist/problem-items.js +52 -0
- package/dist/problem-items.js.map +1 -0
- package/dist/product-models.d.ts +43 -29
- package/dist/records.d.ts +12 -0
- package/dist/records.js +23 -0
- package/dist/records.js.map +1 -0
- package/dist/runs.d.ts +49 -38
- package/dist/runs.js +45 -19
- package/dist/runs.js.map +1 -1
- package/dist/transport-reading.d.ts +18 -0
- package/dist/{run-may-have-started.js → transport-reading.js} +15 -44
- package/dist/transport-reading.js.map +1 -0
- package/dist/upload-grant.d.ts +9 -6
- package/dist/upload-grant.js +42 -29
- package/dist/upload-grant.js.map +1 -1
- package/dist/upload.js +53 -33
- package/dist/upload.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/architecture.md +19 -19
- package/docs/artifact-download.md +6 -6
- package/docs/cli.md +1 -1
- package/docs/crate-routes.md +13 -14
- package/docs/errors.md +154 -267
- package/docs/exact-integers.md +1 -1
- package/docs/files.md +13 -13
- package/docs/hook-bundle.md +15 -1
- package/docs/input-preparation.md +14 -14
- package/docs/method-copy.md +35 -33
- package/docs/method-examples.md +13 -14
- package/docs/method-trees.md +27 -28
- package/docs/organization-branding.md +14 -16
- package/docs/run-results.md +8 -8
- package/package.json +1 -1
- package/dist/error-models.d.ts +0 -302
- package/dist/error-models.js +0 -203
- package/dist/error-models.js.map +0 -1
- package/dist/error-verdicts.d.ts +0 -46
- package/dist/error-verdicts.js +0 -120
- package/dist/error-verdicts.js.map +0 -1
- package/dist/run-may-have-started.d.ts +0 -31
- package/dist/run-may-have-started.js.map +0 -1
package/dist/models.d.ts
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Holds the Dict-serialized protocol concretes (`DictStuff` / `DictWorkingMemory`
|
|
5
5
|
* / `DictPipeOutput` and the default `RunResultExecute` binding), the Pipelex
|
|
6
|
-
* `/v1/validate` surface (`PipelexValidationResult
|
|
6
|
+
* `/v1/validate` surface (`PipelexValidationResult`, whose faults are the standard's
|
|
7
|
+
* `ProblemItem`s), the
|
|
7
8
|
* request/response models of the tools routes and the crate routes, and the verdict of
|
|
8
9
|
* the model reference check. Built on the protocol wire types imported from the
|
|
9
10
|
* `mthds/protocol` subpath.
|
|
10
11
|
*/
|
|
11
|
-
import type { InputForm, MethodFiles, MethodTreeSource, OutputForm, PipeIOContracts, RunResultExecute, RunResultStart } from "mthds/protocol";
|
|
12
|
+
import type { InputForm, MethodFiles, ProblemItem, MethodTreeSource, OutputForm, PipeIOContracts, RunResultExecute, RunResultStart } from "mthds/protocol";
|
|
12
13
|
import type { MethodTreeForm, NoMethodTree } from "./method-trees.js";
|
|
13
14
|
export interface DictStuff {
|
|
14
15
|
concept: string;
|
|
@@ -85,8 +86,8 @@ export interface PipelexRunResultStart extends RunResultStart {
|
|
|
85
86
|
* one of inline source / `method_ref` / `method_id` per request — any second
|
|
86
87
|
* selector is a request-shape `422`. An unknown or foreign-org id is a `404`
|
|
87
88
|
* (indistinguishable by design); a bare id of a method never published is a `409`
|
|
88
|
-
* `
|
|
89
|
-
* `
|
|
89
|
+
* `pipelex.catalog.not_published`; a version never published is a `404`
|
|
90
|
+
* `pipelex.catalog.not_found`; a malformed suffix, or a stored method with no MTHDS
|
|
90
91
|
* source, is a `422`.
|
|
91
92
|
*/
|
|
92
93
|
export interface PipelexHostedToolingExtensions {
|
|
@@ -301,17 +302,12 @@ export interface PipelexValidationReport {
|
|
|
301
302
|
/** Per-pipe dry-run sweep outcomes. */
|
|
302
303
|
validated_pipes: ValidatedPipeEntry[];
|
|
303
304
|
/**
|
|
304
|
-
* Advisory findings on a VALID bundle
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
* (`input_presence_vacuous`), the intent-hint lints (`hint_unknown_key`,
|
|
309
|
-
* `hint_unknown_intent`, `hint_inapplicable_intent`, which ride here exclusively), then the
|
|
310
|
-
* findings a `PipeDocGen` step's template check made in its office template file during
|
|
311
|
-
* the dry run (`template_check_warning`, a `dry_run` item carrying `pipe_code`,
|
|
312
|
-
* `domain_code`, `template_file` and `template_location`).
|
|
305
|
+
* Advisory findings on a VALID bundle, one problem item each with the code its finding's
|
|
306
|
+
* type names: the same item shape as the invalid arm's `errors[]`, so one reader serves
|
|
307
|
+
* both, but these never flip `is_valid`. Empty when there is nothing to report. The client
|
|
308
|
+
* reads them member by member (`readProblemItems`).
|
|
313
309
|
*/
|
|
314
|
-
warnings:
|
|
310
|
+
warnings: ProblemItem[];
|
|
315
311
|
/** Qualified refs of pipes still declared as `PipeSignature`. */
|
|
316
312
|
pending_signatures: string[];
|
|
317
313
|
/** `not pending_signatures` — whether the validated library is complete enough to run. */
|
|
@@ -332,17 +328,20 @@ export interface PipelexValidationReport {
|
|
|
332
328
|
}
|
|
333
329
|
/**
|
|
334
330
|
* Pipelex's `POST /v1/validate` 200 body for an INVALID bundle — the `is_valid: false`
|
|
335
|
-
* arm of the response union,
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
331
|
+
* arm of the response union, listing its faults as problem items. The structural
|
|
332
|
+
* artifacts of the valid arm are absent (they don't exist when load/parse/wiring failed);
|
|
333
|
+
* `errors[]` is non-empty on every invalid verdict the server sends, and the client reads
|
|
334
|
+
* it member by member (`readProblemItems`), so an item whose `code` or `detail` is not a
|
|
335
|
+
* string is skipped and a malformed member is left out of its item.
|
|
340
336
|
*/
|
|
341
337
|
export interface PipelexInvalidReport {
|
|
342
338
|
/** Discriminant of the invalid arm. */
|
|
343
339
|
is_valid: false;
|
|
344
|
-
/**
|
|
345
|
-
|
|
340
|
+
/**
|
|
341
|
+
* One problem item per fault, each with its own `code`, `detail`, `params`, `location`
|
|
342
|
+
* and, when the server has one, its `suggested_fix`.
|
|
343
|
+
*/
|
|
344
|
+
errors: ProblemItem[];
|
|
346
345
|
/** Outstanding signatures (best-effort; empty when no library could be assembled). */
|
|
347
346
|
pending_signatures: string[];
|
|
348
347
|
/** An invalid bundle is never runnable. */
|
|
@@ -351,8 +350,8 @@ export interface PipelexInvalidReport {
|
|
|
351
350
|
message: string;
|
|
352
351
|
/**
|
|
353
352
|
* Opt-in Pipelex-API presentation extra: the server-rendered Markdown view of the
|
|
354
|
-
* invalid verdict
|
|
355
|
-
*
|
|
353
|
+
* invalid verdict's errors, present only when the request asked for it
|
|
354
|
+
* (`render: ["markdown"]`). Absent by default.
|
|
356
355
|
*/
|
|
357
356
|
rendered_markdown?: string;
|
|
358
357
|
}
|
|
@@ -363,185 +362,6 @@ export interface PipelexInvalidReport {
|
|
|
363
362
|
* answers, not narrowings of the protocol's (see the section's heading above).
|
|
364
363
|
*/
|
|
365
364
|
export type PipelexValidationResult = PipelexValidationReport | PipelexInvalidReport;
|
|
366
|
-
/**
|
|
367
|
-
* Which validation stage produced a `ValidationErrorItem` — mirror of pipelex's
|
|
368
|
-
* closed `ValidationErrorCategory` set. `pipe_factory` and graph-level `dry_run`
|
|
369
|
-
* items carry no `source`; map those by `domain_code` / `pipe_code`. The other
|
|
370
|
-
* categories carry `source` when the runtime can attribute one.
|
|
371
|
-
*/
|
|
372
|
-
export type ValidationErrorCategory = "blueprint_validation" | "pipe_factory" | "pipe_validation" | "dry_run";
|
|
373
|
-
/**
|
|
374
|
-
* One structured bundle-validation error — mirror of pipelex's `ValidationErrorItem`.
|
|
375
|
-
* Carried by `PipelexInvalidReport.validation_errors[]` on the **200** invalid arm of
|
|
376
|
-
* `POST /v1/validate` (NOT a 422 — an invalid bundle is a produced verdict), by the
|
|
377
|
-
* VALID arm's advisory `warnings[]`, by the crate routes' **200** invalid arm
|
|
378
|
-
* (`CrateInvalidReport.validation_errors[]`), by the 422 problem body a run route answers
|
|
379
|
-
* when the runner refuses the method for its validation errors
|
|
380
|
-
* (`ApiResponseError.validationErrors`), and by a failed run's stored report.
|
|
381
|
-
*
|
|
382
|
-
* **The shape is the hosted plane's.** It is the item the runner sends today, which
|
|
383
|
-
* predates the standard's problem items: from protocol 2.0.0 a verdict lists its faults
|
|
384
|
-
* as `ProblemItem`s under a registry `code`, which the hosted plane does not send yet, so
|
|
385
|
-
* this declaration is not the standard's and is not pinned to it. Its fix shares the
|
|
386
|
-
* standard's operation and safety vocabularies, which `tests/validation-items.test.ts`
|
|
387
|
-
* pins.
|
|
388
|
-
*
|
|
389
|
-
* Only `category` and `message` are always present; the rest are populated per
|
|
390
|
-
* `category`. Every other member is `?: T | null` because the two channels serialize an
|
|
391
|
-
* unset locator differently: the invalid arm and the crate routes drop the key
|
|
392
|
-
* (`exclude_none` server-side) while the valid arm — which carries `warnings[]` — does
|
|
393
|
-
* not, so the same item arrives with explicit `null`s there. A truthiness check reads
|
|
394
|
-
* both; an `=== undefined` check would be wrong on one of them.
|
|
395
|
-
*
|
|
396
|
-
* `source` is the declaring file: its path (CLI), or its tree path in the tree the
|
|
397
|
-
* request sent — the owning file for cross-file diagnostics.
|
|
398
|
-
*
|
|
399
|
-
* An `unknown_model` item (a model reference the runner's model deck does not know)
|
|
400
|
-
* carries the reference as written, the kind of model the field takes and the close
|
|
401
|
-
* matches, and, when there is exactly one close match, a `suggested_fix` that remaps
|
|
402
|
-
* the reference to it.
|
|
403
|
-
*
|
|
404
|
-
* A `template_check_warning` item, on the valid arm's `warnings[]` only, is a finding of a
|
|
405
|
-
* `PipeDocGen` step's template check in its office template file during the dry run, such
|
|
406
|
-
* as a field of the template that matches no input: a `dry_run` item carrying the step's
|
|
407
|
-
* `pipe_code` and `domain_code`, the template file as the step names it and the place in
|
|
408
|
-
* it the engine's finding names.
|
|
409
|
-
*/
|
|
410
|
-
export interface ValidationErrorItem {
|
|
411
|
-
category: ValidationErrorCategory;
|
|
412
|
-
message: string;
|
|
413
|
-
error_type?: string | null;
|
|
414
|
-
pipe_code?: string | null;
|
|
415
|
-
concept_code?: string | null;
|
|
416
|
-
domain_code?: string | null;
|
|
417
|
-
source?: string | null;
|
|
418
|
-
field_path?: string | null;
|
|
419
|
-
field_name?: string | null;
|
|
420
|
-
variable_names?: string[] | null;
|
|
421
|
-
missing_concept_code?: string | null;
|
|
422
|
-
/** The pipe a reference names that the bundle does not declare. */
|
|
423
|
-
missing_pipe_code?: string | null;
|
|
424
|
-
declared_concepts?: string[] | null;
|
|
425
|
-
/**
|
|
426
|
-
* On an `unknown_model` item: the model reference exactly as the author wrote it
|
|
427
|
-
* (`gpt-5.1`, `@best-sonet`, `$writting-factual`).
|
|
428
|
-
*/
|
|
429
|
-
model_reference?: string | null;
|
|
430
|
-
/** On an `unknown_model` item: the kind of model the field takes (`llm`, `img_gen`, …). */
|
|
431
|
-
model_type?: string | null;
|
|
432
|
-
/**
|
|
433
|
-
* On an `unknown_model` item: the close matches of the same kind, each spelled as a
|
|
434
|
-
* reference the field accepts.
|
|
435
|
-
*/
|
|
436
|
-
suggestions?: string[] | null;
|
|
437
|
-
/**
|
|
438
|
-
* On a `template_check_warning` item: the template file as the `PipeDocGen` step names it
|
|
439
|
-
* (`templates/invoice.xlsx`); `null` for a step of the server's own library, whose path is
|
|
440
|
-
* the server's and is never shown.
|
|
441
|
-
*/
|
|
442
|
-
template_file?: string | null;
|
|
443
|
-
/**
|
|
444
|
-
* On a `template_check_warning` item: the place in the template file the finding names, in
|
|
445
|
-
* the engine's own words (a defined name, a table, a cell, a shape, a tag); `null` when the
|
|
446
|
-
* finding names none.
|
|
447
|
-
*/
|
|
448
|
-
template_location?: string | null;
|
|
449
|
-
/** The server's deterministic repair proposal for this error, when it has one. */
|
|
450
|
-
suggested_fix?: SuggestedFix | null;
|
|
451
|
-
}
|
|
452
|
-
/** Whether a `SuggestedFix` is safe to auto-apply, or needs explicit opt-in. */
|
|
453
|
-
export type FixSafety = "safe" | "unsafe";
|
|
454
|
-
/** The semantic patch operations a `SuggestedFix` is composed of. */
|
|
455
|
-
export type FixOpKind = "set_key" | "ensure_table" | "delete_key" | "delete_table" | "rename_table_key" | "move_key" | "remap_value";
|
|
456
|
-
/** A TOML-representable scalar a `set_key` op can write. */
|
|
457
|
-
export type TomlScalar = string | number | boolean;
|
|
458
|
-
/**
|
|
459
|
-
* What a `set_key` op writes: a scalar, or a flat scalar mapping for fixes that create
|
|
460
|
-
* a whole table at once (written as an inline table). Deeper nesting is not modelled —
|
|
461
|
-
* the server does not emit it.
|
|
462
|
-
*/
|
|
463
|
-
export type TomlValue = TomlScalar | Record<string, TomlScalar>;
|
|
464
|
-
/** `TomlValue` under the name `mthds` gives it, so either client's vocabulary reads here. */
|
|
465
|
-
export type FixValue = TomlValue;
|
|
466
|
-
/**
|
|
467
|
-
* What every fix op carries: the table it acts in. `table_path` addresses the containing
|
|
468
|
-
* table (e.g. `["pipe", "my_seq"]`), aligned with the `field_path` conventions of
|
|
469
|
-
* `ValidationErrorItem`, and is empty for the document root.
|
|
470
|
-
*
|
|
471
|
-
* The segment `"*"` is the wildcard — "every entry of the open mapping at this node".
|
|
472
|
-
* The server refuses it as a `key` on every kind but `remap_value`, the only one with a
|
|
473
|
-
* per-key meaning for it.
|
|
474
|
-
*/
|
|
475
|
-
interface FixOpBase {
|
|
476
|
-
table_path: string[];
|
|
477
|
-
}
|
|
478
|
-
/** Write `key = value` in the addressed table, whatever it currently holds. */
|
|
479
|
-
export interface SetKeyOp extends FixOpBase {
|
|
480
|
-
kind: "set_key";
|
|
481
|
-
key: string;
|
|
482
|
-
value: TomlValue;
|
|
483
|
-
}
|
|
484
|
-
/** Create the addressed table when it is missing. `table_path` is never empty. */
|
|
485
|
-
export interface EnsureTableOp extends FixOpBase {
|
|
486
|
-
kind: "ensure_table";
|
|
487
|
-
}
|
|
488
|
-
/** Remove `key` from the addressed table. */
|
|
489
|
-
export interface DeleteKeyOp extends FixOpBase {
|
|
490
|
-
kind: "delete_key";
|
|
491
|
-
key: string;
|
|
492
|
-
}
|
|
493
|
-
/** Remove the addressed table entirely. `table_path` is never empty. */
|
|
494
|
-
export interface DeleteTableOp extends FixOpBase {
|
|
495
|
-
kind: "delete_table";
|
|
496
|
-
}
|
|
497
|
-
/** Rename `key` to `new_key` within the addressed table. */
|
|
498
|
-
export interface RenameTableKeyOp extends FixOpBase {
|
|
499
|
-
kind: "rename_table_key";
|
|
500
|
-
key: string;
|
|
501
|
-
new_key: string;
|
|
502
|
-
}
|
|
503
|
-
/** Move `key` out of the addressed table into `new_table_path`, under `new_key`. */
|
|
504
|
-
export interface MoveKeyOp extends FixOpBase {
|
|
505
|
-
kind: "move_key";
|
|
506
|
-
key: string;
|
|
507
|
-
new_table_path: string[];
|
|
508
|
-
new_key: string;
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Rewrite `key`'s value through `mapping`, leaving an unmapped value untouched. The
|
|
512
|
-
* unknown-model fix is one: it maps the reference as written to its one close match, so
|
|
513
|
-
* it changes nothing once the author has edited the field.
|
|
514
|
-
*/
|
|
515
|
-
export interface RemapValueOp extends FixOpBase {
|
|
516
|
-
kind: "remap_value";
|
|
517
|
-
key: string;
|
|
518
|
-
mapping: Record<string, string>;
|
|
519
|
-
}
|
|
520
|
-
/** One patch operation of a `SuggestedFix` — discriminated on `kind`. */
|
|
521
|
-
export type FixOp = SetKeyOp | EnsureTableOp | DeleteKeyOp | DeleteTableOp | RenameTableKeyOp | MoveKeyOp | RemapValueOp;
|
|
522
|
-
/**
|
|
523
|
-
* A deterministic fix for one validation error, ready for a style-preserving applier —
|
|
524
|
-
* mirror of pipelex's `SuggestedFix`. The ops are semantic patches over the `.mthds`
|
|
525
|
-
* document, not a text diff, so an applier keeps the author's formatting.
|
|
526
|
-
*
|
|
527
|
-
* The shape is the hosted plane's, as `ValidationErrorItem`'s is: the standard's
|
|
528
|
-
* `SuggestedFix` names the file `file` rather than `source` and is open to members it does
|
|
529
|
-
* not declare. Its operation kinds, its safeties and the values a `set_key` writes are the
|
|
530
|
-
* standard's (this SDK's `TomlValue` is the standard's `FixValue`), and a type-level test
|
|
531
|
-
* pins them.
|
|
532
|
-
*/
|
|
533
|
-
export interface SuggestedFix {
|
|
534
|
-
/** The kebab-case rule id, e.g. `"match-sequence-output"`. */
|
|
535
|
-
fix_code: string;
|
|
536
|
-
description: string;
|
|
537
|
-
safety: FixSafety;
|
|
538
|
-
/**
|
|
539
|
-
* The file the ops target, when known (multi-file libraries). An applier must only
|
|
540
|
-
* apply these ops to that file.
|
|
541
|
-
*/
|
|
542
|
-
source?: string | null;
|
|
543
|
-
ops: FixOp[];
|
|
544
|
-
}
|
|
545
365
|
/** Which analysis produced a `Diagnostic` — mirror of `pipelex-tools`' closed kind set. */
|
|
546
366
|
export type DiagnosticKind = "syntax" | "semantic" | "schema";
|
|
547
367
|
/** Source span of a `Diagnostic` — byte offsets plus 1-based line/column coordinates. */
|
|
@@ -673,7 +493,11 @@ export interface CrateRouteOptions {
|
|
|
673
493
|
*/
|
|
674
494
|
export interface CrateInvalidReport {
|
|
675
495
|
is_valid: false;
|
|
676
|
-
|
|
496
|
+
/**
|
|
497
|
+
* One problem item per fault, the same items `/v1/validate` lists for the identical
|
|
498
|
+
* failure, read member by member (`readProblemItems`).
|
|
499
|
+
*/
|
|
500
|
+
errors: ProblemItem[];
|
|
677
501
|
message: string;
|
|
678
502
|
}
|
|
679
503
|
/**
|
|
@@ -787,12 +611,12 @@ export interface PipeIORequest extends CrateRequestBase, PipelexHostedToolingExt
|
|
|
787
611
|
* The pipe to describe, as a QUALIFIED `domain.pipe_code` ref. Omit it and the
|
|
788
612
|
* server's selection chain decides: the `main_pipe` of the `METHODS.toml` at the tree's
|
|
789
613
|
* root, whether the tree was sent or fetched, else the closure's single `main_pipe`
|
|
790
|
-
* declaration. A selection the server refuses is a
|
|
791
|
-
*
|
|
792
|
-
*
|
|
793
|
-
*
|
|
794
|
-
*
|
|
795
|
-
*
|
|
614
|
+
* declaration. A selection the server refuses is a problem coded by what went wrong, of
|
|
615
|
+
* the domain `input`, the candidates in its parameters where there are some:
|
|
616
|
+
* `request.pipe_not_found` for a ref that names no pipe, `request.pipe_unspecified` for
|
|
617
|
+
* (without `all_pipes`) a method with no entry pipe, `request.pipe_ambiguous` for a code that
|
|
618
|
+
* matches pipes in several domains or (without `all_pipes`) several `main_pipe` declarations.
|
|
619
|
+
* A malformed request is `request.malformed`.
|
|
796
620
|
*
|
|
797
621
|
* The server does not refuse a bare code yet: a bare ref that matches one pipe is
|
|
798
622
|
* resolved across domains, and the valid arm reports the qualified ref.
|
|
@@ -978,4 +802,3 @@ export interface HandleReferenceVerdict extends ModelReferenceVerdictBase {
|
|
|
978
802
|
* matches of one verdict share its kind; no field is added to the wire to make it so.
|
|
979
803
|
*/
|
|
980
804
|
export type ModelReferenceVerdict = PresetReferenceVerdict | AliasReferenceVerdict | WaterfallReferenceVerdict | HandleReferenceVerdict;
|
|
981
|
-
export {};
|
package/dist/models.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Holds the Dict-serialized protocol concretes (`DictStuff` / `DictWorkingMemory`
|
|
5
5
|
* / `DictPipeOutput` and the default `RunResultExecute` binding), the Pipelex
|
|
6
|
-
* `/v1/validate` surface (`PipelexValidationResult
|
|
6
|
+
* `/v1/validate` surface (`PipelexValidationResult`, whose faults are the standard's
|
|
7
|
+
* `ProblemItem`s), the
|
|
7
8
|
* request/response models of the tools routes and the crate routes, and the verdict of
|
|
8
9
|
* the model reference check. Built on the protocol wire types imported from the
|
|
9
10
|
* `mthds/protocol` subpath.
|
package/dist/models.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
package/dist/prepare-inputs.d.ts
CHANGED
|
@@ -180,8 +180,8 @@ export declare function inputFormFault(entry: unknown): InputFormFault | undefin
|
|
|
180
180
|
* `MethodFileTransferError` before the route is asked. A bare or alias-qualified `pipe_ref`, a
|
|
181
181
|
* closure that does not load, and a selection the route refuses (an unknown
|
|
182
182
|
* `pipe_ref`, no entry pipe, several) throw {@link InputPreparationError}. So
|
|
183
|
-
* does an answer that breaks the route's contract, with
|
|
184
|
-
*
|
|
183
|
+
* does an answer that breaks the route's contract, with the problem
|
|
184
|
+
* `client.response_unreadable`: no boolean `is_valid`, an `input_form` that does not describe
|
|
185
185
|
* the selected pipe, or a descriptor that is malformed or names a kind this SDK
|
|
186
186
|
* does not know, which is checked whole before anything is uploaded. Any other
|
|
187
187
|
* failure from the route (a malformed selector, an unknown or foreign-org id, no
|
package/dist/prepare-inputs.js
CHANGED
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
* dict. See `docs/input-preparation.md`, which `pipelex-sdk-python` mirrors case
|
|
31
31
|
* for case.
|
|
32
32
|
*/
|
|
33
|
-
import {
|
|
33
|
+
import { readProblemItems } from "./problem-items.js";
|
|
34
34
|
import { throwIfAborted } from "./runs.js";
|
|
35
|
-
import { ApiResponseError, InputPreparationError, InvalidInputValueError, MethodLoadError, UploadNotAllowedError, } from "./errors.js";
|
|
35
|
+
import { ApiResponseError, InputPreparationError, InvalidInputValueError, MethodLoadError, UploadNotAllowedError, argumentInvalidProblem, responseUnreadableProblem, } from "./errors.js";
|
|
36
36
|
import { treeShapeFault } from "./method-trees.js";
|
|
37
37
|
import { uploadFile, uploadKindFields } from "./upload.js";
|
|
38
38
|
const PIPELEX_STORAGE_SCHEME = "pipelex-storage://";
|
|
@@ -59,18 +59,17 @@ const WALKED_KINDS = {
|
|
|
59
59
|
};
|
|
60
60
|
const KNOWN_KINDS = new Set(Object.keys(WALKED_KINDS));
|
|
61
61
|
/**
|
|
62
|
-
* The
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* no pipe
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* file, a fetched package with no `.mthds` file, a stored method with no source)
|
|
69
|
-
* shares the generic `ValidationError` type and stays an `ApiResponseError`.
|
|
62
|
+
* The problem codes of the route's pipe-selection refusals, the only refusals `prepareInputs`
|
|
63
|
+
* turns into an `InputPreparationError`: a ref that names no pipe (`request.pipe_not_found`),
|
|
64
|
+
* several pipes it could mean (`request.pipe_ambiguous`), and no pipe named where the method has
|
|
65
|
+
* no entry pipe (`request.pipe_unspecified`). They are the run routes' vocabulary too. Every other
|
|
66
|
+
* refusal (a malformed body, an over-limit file, a fetched package with no `.mthds` file, a stored
|
|
67
|
+
* method with no source) stays an `ApiResponseError`.
|
|
70
68
|
*/
|
|
71
|
-
const
|
|
72
|
-
"
|
|
73
|
-
"
|
|
69
|
+
const PIPE_SELECTION_CODES = new Set([
|
|
70
|
+
"request.pipe_not_found",
|
|
71
|
+
"request.pipe_ambiguous",
|
|
72
|
+
"request.pipe_unspecified",
|
|
74
73
|
]);
|
|
75
74
|
/** Strict plain-object test — excludes arrays, `Uint8Array`, `Blob`, and other exotics. */
|
|
76
75
|
function isPlainObject(value) {
|
|
@@ -316,7 +315,7 @@ async function resolveNode(ctx, node, callerValue, at) {
|
|
|
316
315
|
default: {
|
|
317
316
|
// Unreachable: the descriptor was checked against WALKED_KINDS before the walk began.
|
|
318
317
|
const unwalked = node;
|
|
319
|
-
throw new InputPreparationError(`Cannot prepare inputs: the walk has no arm for the kind ${described(unwalked.kind)}.`, {
|
|
318
|
+
throw new InputPreparationError(`Cannot prepare inputs: the walk has no arm for the kind ${described(unwalked.kind)}.`, { problem: responseUnreadableProblem(200) });
|
|
320
319
|
}
|
|
321
320
|
}
|
|
322
321
|
}
|
|
@@ -343,12 +342,12 @@ function refuseNonMap(name, value, holds, isValue) {
|
|
|
343
342
|
if (value === undefined || value === null)
|
|
344
343
|
return;
|
|
345
344
|
if (!isPlainObject(value)) {
|
|
346
|
-
throw new InputPreparationError(`Cannot prepare inputs: \`${name}\` must be ${holds}, got ${describeNonMap(value)}
|
|
345
|
+
throw new InputPreparationError(`Cannot prepare inputs: \`${name}\` must be ${holds}, got ${describeNonMap(value)}.`, { problem: argumentInvalidProblem(name, "not_a_map") });
|
|
347
346
|
}
|
|
348
347
|
for (const [key, entry] of Object.entries(value)) {
|
|
349
348
|
if (!isValue(entry)) {
|
|
350
349
|
throw new InputPreparationError(`Cannot prepare inputs: \`${name}\` must be ${holds}, and "${key}" holds ` +
|
|
351
|
-
`${entry === null ? "null" : describeNonMap(entry)}
|
|
350
|
+
`${entry === null ? "null" : describeNonMap(entry)}.`, { problem: argumentInvalidProblem(name, "entry_mistyped") });
|
|
352
351
|
}
|
|
353
352
|
}
|
|
354
353
|
}
|
|
@@ -365,11 +364,11 @@ function checkedTree(value) {
|
|
|
365
364
|
if (fault !== undefined) {
|
|
366
365
|
throw new InputPreparationError("Cannot prepare inputs: `tree` must be a listed method tree — its `files`, its `digest` and " +
|
|
367
366
|
"a `readFile` — such as the `MethodTree` the client's `listMethodTree` returns, got " +
|
|
368
|
-
`${fault}
|
|
367
|
+
`${fault}.`, { problem: argumentInvalidProblem("tree", "not_a_tree") });
|
|
369
368
|
}
|
|
370
369
|
const tree = value;
|
|
371
370
|
if (tree.files.length === 0) {
|
|
372
|
-
throw new InputPreparationError("Cannot prepare inputs: `tree` holds no file, and a method tree holds at least one.");
|
|
371
|
+
throw new InputPreparationError("Cannot prepare inputs: `tree` holds no file, and a method tree holds at least one.", { problem: argumentInvalidProblem("tree", "empty") });
|
|
373
372
|
}
|
|
374
373
|
return tree;
|
|
375
374
|
}
|
|
@@ -390,14 +389,14 @@ function resolveSelector(request) {
|
|
|
390
389
|
const rawFiles = raw["files"];
|
|
391
390
|
if (rawFiles !== undefined && rawFiles !== null && !isPlainObject(rawFiles)) {
|
|
392
391
|
throw new InputPreparationError("Cannot prepare inputs: `files` must be the method's tree as a map from tree path to file " +
|
|
393
|
-
`entry, got ${Array.isArray(rawFiles) ? "a list" : typeof rawFiles}
|
|
392
|
+
`entry, got ${Array.isArray(rawFiles) ? "a list" : typeof rawFiles}.`, { problem: argumentInvalidProblem("files", "not_a_map") });
|
|
394
393
|
}
|
|
395
394
|
refuseNonMap("contents", raw["contents"], "the method's files as a map from tree path to bytes or text", (entry) => typeof entry === "string" || entry instanceof Uint8Array);
|
|
396
395
|
refuseNonMap("dependencies", raw["dependencies"], "the method packages as a map from package address to its map of file entries", isPlainObject);
|
|
397
396
|
const rawDirectory = raw["directory"];
|
|
398
397
|
if (rawDirectory !== undefined && rawDirectory !== null && typeof rawDirectory !== "string") {
|
|
399
398
|
throw new InputPreparationError("Cannot prepare inputs: `directory` must be the method's directory as a path, got " +
|
|
400
|
-
`${describeNonMap(rawDirectory)}
|
|
399
|
+
`${describeNonMap(rawDirectory)}.`, { problem: argumentInvalidProblem("directory", "not_a_string") });
|
|
401
400
|
}
|
|
402
401
|
const directory = typeof rawDirectory === "string" && rawDirectory !== "" ? rawDirectory : undefined;
|
|
403
402
|
const files = nonEmptyMap(rawFiles);
|
|
@@ -417,7 +416,7 @@ function resolveSelector(request) {
|
|
|
417
416
|
treeForms.push("`files`");
|
|
418
417
|
if (treeForms.length > 1) {
|
|
419
418
|
throw new InputPreparationError(`Cannot prepare inputs: the method's tree was given as ${treeForms.join(" and ")}. Give it ` +
|
|
420
|
-
"in one form — `directory`, `contents`, `tree` or `files`.");
|
|
419
|
+
"in one form — `directory`, `contents`, `tree` or `files`.", { problem: argumentInvalidProblem("files", "mutually_exclusive") });
|
|
421
420
|
}
|
|
422
421
|
const given = [...treeForms];
|
|
423
422
|
if (methodRef !== undefined)
|
|
@@ -427,12 +426,12 @@ function resolveSelector(request) {
|
|
|
427
426
|
if (given.length === 0) {
|
|
428
427
|
throw new InputPreparationError("Cannot prepare inputs: no method selector. Supply exactly one of the method's tree " +
|
|
429
428
|
"(`directory`, `contents`, `tree` or `files`), `method_ref` (a published method's address) or " +
|
|
430
|
-
"`method_id` (a stored method's catalog id).");
|
|
429
|
+
"`method_id` (a stored method's catalog id).", { problem: argumentInvalidProblem("files", "nothing_to_prepare") });
|
|
431
430
|
}
|
|
432
431
|
if (given.length > 1) {
|
|
433
432
|
throw new InputPreparationError(`Cannot prepare inputs: ${given.join(" and ")} were ${given.length === 2 ? "both" : "all"} ` +
|
|
434
433
|
"given. Supply exactly one method " +
|
|
435
|
-
"selector — the method's tree, `method_ref` or `method_id`.");
|
|
434
|
+
"selector — the method's tree, `method_ref` or `method_id`.", { problem: argumentInvalidProblem("files", "mutually_exclusive") });
|
|
436
435
|
}
|
|
437
436
|
if (treeForms.length === 1) {
|
|
438
437
|
return {
|
|
@@ -447,7 +446,7 @@ function resolveSelector(request) {
|
|
|
447
446
|
const owner = methodRef !== undefined ? "published" : "stored";
|
|
448
447
|
if (dependencies !== undefined) {
|
|
449
448
|
throw new InputPreparationError(`Cannot prepare inputs: \`dependencies\` accompany the method's own tree; a ${owner} ` +
|
|
450
|
-
"method's packages are its own.");
|
|
449
|
+
"method's packages are its own.", { problem: argumentInvalidProblem("dependencies", "without_a_tree") });
|
|
451
450
|
}
|
|
452
451
|
if (methodRef !== undefined)
|
|
453
452
|
return { method_ref: methodRef };
|
|
@@ -472,11 +471,11 @@ function normalizePipeRef(raw) {
|
|
|
472
471
|
return undefined;
|
|
473
472
|
if (pipeRef.includes("->")) {
|
|
474
473
|
throw new InputPreparationError(`Cannot prepare inputs: \`pipe_ref\` "${pipeRef}" names a dependency package's pipe. ` +
|
|
475
|
-
"Preparation covers the method's own pipes: name one as `domain.pipe_code`.");
|
|
474
|
+
"Preparation covers the method's own pipes: name one as `domain.pipe_code`.", { problem: argumentInvalidProblem("pipe_ref", "dependency_pipe") });
|
|
476
475
|
}
|
|
477
476
|
if (!pipeRef.includes(".")) {
|
|
478
477
|
throw new InputPreparationError(`Cannot prepare inputs: \`pipe_ref\` must be qualified (\`domain.pipe_code\`), got the bare ` +
|
|
479
|
-
`"${pipeRef}"
|
|
478
|
+
`"${pipeRef}".`, { problem: argumentInvalidProblem("pipe_ref", "not_qualified") });
|
|
480
479
|
}
|
|
481
480
|
return pipeRef;
|
|
482
481
|
}
|
|
@@ -490,7 +489,7 @@ function resolveAllowUploads(raw) {
|
|
|
490
489
|
return true;
|
|
491
490
|
if (typeof raw === "boolean")
|
|
492
491
|
return raw;
|
|
493
|
-
throw new InputPreparationError(`Cannot prepare inputs: \`allowUploads\` must be a boolean, got ${raw === null ? "null" : typeof raw}
|
|
492
|
+
throw new InputPreparationError(`Cannot prepare inputs: \`allowUploads\` must be a boolean, got ${raw === null ? "null" : typeof raw}.`, { problem: argumentInvalidProblem("allowUploads", "not_a_bool") });
|
|
494
493
|
}
|
|
495
494
|
/**
|
|
496
495
|
* The request's `upload`, checked once before any request as `uploadFile` checks its own: absent
|
|
@@ -502,7 +501,7 @@ function resolveUploadAs(raw) {
|
|
|
502
501
|
return {};
|
|
503
502
|
if (!isPlainObject(raw)) {
|
|
504
503
|
throw new InputPreparationError("Cannot prepare inputs: `upload` must be an object of `kind` and `method_id`, got " +
|
|
505
|
-
`${describeNonMap(raw)}
|
|
504
|
+
`${describeNonMap(raw)}.`, { problem: argumentInvalidProblem("upload", "not_upload_kind_options") });
|
|
506
505
|
}
|
|
507
506
|
return uploadKindFields(raw, "Cannot prepare inputs", "upload.");
|
|
508
507
|
}
|
|
@@ -515,9 +514,9 @@ function resolveUploadAs(raw) {
|
|
|
515
514
|
* the method runs is the run's verdict, not preparation's. The `is_valid: false`
|
|
516
515
|
* arm means the closure does not load, which is a preparation failure. So is a
|
|
517
516
|
* selection the route refuses — an unknown `pipe_ref`, no entry pipe, several —
|
|
518
|
-
* which it answers with a
|
|
519
|
-
*
|
|
520
|
-
*
|
|
517
|
+
* which it answers with a problem of one of {@link PIPE_SELECTION_CODES}; every
|
|
518
|
+
* other failure is re-thrown unchanged. An answer with no boolean `is_valid` is
|
|
519
|
+
* neither arm, so it fails the preparation with `client.response_unreadable`, as an
|
|
521
520
|
* `input_form` that does not describe the selected pipe does, and one whose
|
|
522
521
|
* descriptor is malformed where the walk reads it.
|
|
523
522
|
*/
|
|
@@ -528,12 +527,11 @@ async function fetchSignature(client, selector, pipeRef, signal) {
|
|
|
528
527
|
result = await client.pipeIo(request, signal === undefined ? {} : { signal });
|
|
529
528
|
}
|
|
530
529
|
catch (error) {
|
|
531
|
-
if (error instanceof ApiResponseError &&
|
|
532
|
-
error.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
throw new InputPreparationError(`Cannot prepare inputs: ${detail}`, { cause: error });
|
|
530
|
+
if (error instanceof ApiResponseError && PIPE_SELECTION_CODES.has(error.code)) {
|
|
531
|
+
throw new InputPreparationError(`Cannot prepare inputs: ${error.problem.detail}`, {
|
|
532
|
+
cause: error,
|
|
533
|
+
problem: error.problem,
|
|
534
|
+
});
|
|
537
535
|
}
|
|
538
536
|
throw error;
|
|
539
537
|
}
|
|
@@ -542,27 +540,26 @@ async function fetchSignature(client, selector, pipeRef, signal) {
|
|
|
542
540
|
// An answer with no boolean discriminant is neither arm: the route broke its own contract,
|
|
543
541
|
// which no change to the request fixes.
|
|
544
542
|
throw new InputPreparationError("Cannot prepare inputs: the pipe I/O answer carries no boolean `is_valid`, so it says " +
|
|
545
|
-
"neither that the method loaded nor why it did not.", {
|
|
543
|
+
"neither that the method loaded nor why it did not.", { problem: responseUnreadableProblem(200) });
|
|
546
544
|
}
|
|
547
545
|
if (!answer.is_valid) {
|
|
548
|
-
const
|
|
549
|
-
throw new MethodLoadError(`Cannot prepare inputs: the method signature did not resolve — ${invalidReason(answer)}`, {
|
|
550
|
-
|
|
546
|
+
const errors = readProblemItems(answer.errors);
|
|
547
|
+
throw new MethodLoadError(`Cannot prepare inputs: the method signature did not resolve — ${invalidReason(answer, errors)}`, {
|
|
548
|
+
errors,
|
|
551
549
|
serverMessage: typeof answer.message === "string" ? answer.message : undefined,
|
|
552
550
|
});
|
|
553
551
|
}
|
|
554
552
|
return result;
|
|
555
553
|
}
|
|
556
554
|
/**
|
|
557
|
-
* Why an invalid pipe I/O answer says the closure did not load: its first
|
|
558
|
-
*
|
|
559
|
-
*
|
|
555
|
+
* Why an invalid pipe I/O answer says the closure did not load: its first problem item's `detail`,
|
|
556
|
+
* else its own `message`. Each is read only when it has its declared type, since the answer is the
|
|
557
|
+
* server's, and an answer carrying neither still fails the preparation.
|
|
560
558
|
*/
|
|
561
|
-
function invalidReason(answer) {
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
return first.message;
|
|
559
|
+
function invalidReason(answer, errors) {
|
|
560
|
+
const first = errors[0];
|
|
561
|
+
if (first !== undefined)
|
|
562
|
+
return first.detail;
|
|
566
563
|
return typeof answer.message === "string" ? answer.message : "the answer gives no reason";
|
|
567
564
|
}
|
|
568
565
|
/**
|
|
@@ -581,7 +578,7 @@ function selectedDescriptor(report) {
|
|
|
581
578
|
: "none";
|
|
582
579
|
// The route broke its own contract, which no change to the request fixes.
|
|
583
580
|
throw new InputPreparationError(`Cannot prepare inputs: the pipe I/O answer selected ${pipeRef === undefined ? "no pipe" : `"${pipeRef}"`}, ` +
|
|
584
|
-
`but its \`input_form\` does not describe it (it describes: ${describedPipes}).`, {
|
|
581
|
+
`but its \`input_form\` does not describe it (it describes: ${describedPipes}).`, { problem: responseUnreadableProblem(200) });
|
|
585
582
|
}
|
|
586
583
|
return checkedDescriptor(pipeRef, inputForm[pipeRef]);
|
|
587
584
|
}
|
|
@@ -591,7 +588,7 @@ function selectedDescriptor(report) {
|
|
|
591
588
|
* its first fault.
|
|
592
589
|
*
|
|
593
590
|
* A malformation is the route breaking its contract, at whatever depth and under
|
|
594
|
-
* whichever input, so it is refused with
|
|
591
|
+
* whichever input, so it is refused with `client.response_unreadable`. It is
|
|
595
592
|
* never passed through: a node the SDK cannot read may be a file position, and
|
|
596
593
|
* under the default mode passing it through would send the caller's local path to
|
|
597
594
|
* the runner verbatim. A `kind` outside {@link WALKED_KINDS} is refused for the
|
|
@@ -601,7 +598,7 @@ function checkedDescriptor(pipeRef, entry) {
|
|
|
601
598
|
const found = inputFormFault(entry);
|
|
602
599
|
if (found !== undefined) {
|
|
603
600
|
throw new InputPreparationError(`Cannot prepare inputs: the pipe I/O answer's \`input_form\` for "${pipeRef}" ` +
|
|
604
|
-
`is ${found.message}.`, {
|
|
601
|
+
`is ${found.message}.`, { problem: responseUnreadableProblem(200) });
|
|
605
602
|
}
|
|
606
603
|
return entry;
|
|
607
604
|
}
|
|
@@ -706,8 +703,8 @@ function described(value) {
|
|
|
706
703
|
* `MethodFileTransferError` before the route is asked. A bare or alias-qualified `pipe_ref`, a
|
|
707
704
|
* closure that does not load, and a selection the route refuses (an unknown
|
|
708
705
|
* `pipe_ref`, no entry pipe, several) throw {@link InputPreparationError}. So
|
|
709
|
-
* does an answer that breaks the route's contract, with
|
|
710
|
-
*
|
|
706
|
+
* does an answer that breaks the route's contract, with the problem
|
|
707
|
+
* `client.response_unreadable`: no boolean `is_valid`, an `input_form` that does not describe
|
|
711
708
|
* the selected pipe, or a descriptor that is malformed or names a kind this SDK
|
|
712
709
|
* does not know, which is checked whole before anything is uploaded. Any other
|
|
713
710
|
* failure from the route (a malformed selector, an unknown or foreign-org id, no
|