@paged-media/plugin-sdk 0.2.43-canary.0 → 0.2.46-canary.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +545 -6
  2. package/dist/index.js +10855 -60
  3. package/package.json +4 -3
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PagedBundle, BindingProvider, Disposable, ActiveBindingProvider, BindingPropertyRequest, BindingReadResult, BindingPropertyWrite, BindingWriteResult, BindingCollectionRequest, BindingCollectionResult, MutationInput, FontFaceAsset, BundleHost, ClipboardPayload, ConsentResult, DataProviderRegistration, DataProviderHandle, DataProviderInfo, DataProviderSnapshot, JournalRecord, ShellSurface, WidgetSurface, WillSaveEvent, ToolSettingValue, SchemaPanelRenderer, SchemaPanelContribution, EditContextContribution, ObjectTypeContribution, Diagnostic, TextCaret, OpenDocumentResult, PagedEditor, PluginManifest, ToolContribution, PanelContribution, CommandContribution, KeybindingContribution, OverlayContribution, ImporterContribution, ExporterContribution, ToolPreviewShape, EnteredEditContext, BindingsSurface, PanelProps, SchemaGate, WasmArtifact, CanvasPointerEvent, Mutation, MutationOutcome, BindingProviderHandle } from '@paged-media/plugin-api';
1
+ import { PagedBundle, ParsedAddress, ElementId, MutationInput, MutationOutcome, ObjectErrorCode, ObjectKindInfo, PropertySchema, ObjectValue, ObjectOp, PagedEditor, ObjectsSurface, ObjectModelContribution, PartsSurface, PluginLogger, ObjectModelHandle, BindingProvider, Disposable, ActiveBindingProvider, BindingPropertyRequest, BindingReadResult, BindingPropertyWrite, BindingWriteResult, BindingCollectionRequest, BindingCollectionResult, FontFaceAsset, BundleHost, ClipboardPayload, ConsentResult, DataProviderRegistration, DataProviderHandle, DataProviderInfo, DataProviderSnapshot, JournalRecord, ShellSurface, WidgetSurface, WillSaveEvent, ToolSettingValue, SchemaPanelRenderer, SchemaPanelContribution, EditContextContribution, ObjectTypeContribution, Diagnostic, TextCaret, OpenDocumentResult, PluginManifest, ToolContribution, PanelContribution, CommandContribution, KeybindingContribution, OverlayContribution, ImporterContribution, ExporterContribution, ToolPreviewShape, EnteredEditContext, ValueType, ObjectCommandInfo, PropertyPath, BindingsSurface, PanelProps, SchemaGate, WasmArtifact, CanvasPointerEvent, Mutation, PanelSchemaPropertyRow, PanelSchemaRow, PropertyFieldAddress, PanelSchema, ValueEdit, Address, ListEdit, StructEdit, ObjectWriteResult, BindingProviderHandle } from '@paged-media/plugin-api';
2
2
  import { ComponentType } from 'react';
3
3
 
4
4
  /**
@@ -9,6 +9,167 @@ import { ComponentType } from 'react';
9
9
  */
10
10
  declare function defineBundle(bundle: PagedBundle): PagedBundle;
11
11
 
12
+ /** Parse an address (ADR 131); `null` when it is not one. Never throws. */
13
+ declare function parseAddress(text: string): ParsedAddress | null;
14
+ /** Format a parsed address in its CANONICAL form (aliases never emitted). */
15
+ declare function formatAddress(a: ParsedAddress): string;
16
+ /** Canonicalise an address string; `null` when it does not parse. */
17
+ declare function normalizeAddress(text: string): string | null;
18
+ /** The QUALIFIED kind an address belongs to for schema/routing purposes:
19
+ * `frame` for every page item, `story` for ranges, `page` for `page:#n`,
20
+ * `plugin:<id>/<kind>` for plugin objects. */
21
+ declare function addressKindOf(a: ParsedAddress): string;
22
+ /** The `ElementId` today's wire carries for an address, or `null` when the
23
+ * wire has no form for it (layers, swatches, pages, the document… — the
24
+ * forms core's `Set` will carry as strings). Tables and cells need their
25
+ * owning story, which only a resolver knows: see core-objects.ts. */
26
+ declare function toElementId(a: ParsedAddress): ElementId | null;
27
+ /** The canonical address of a wire `ElementId` (total, ADR 131). */
28
+ declare function fromElementId(id: ElementId): string;
29
+ type SelectorHead = {
30
+ type: "address";
31
+ address: ParsedAddress;
32
+ } | {
33
+ type: "kind";
34
+ kind: string;
35
+ } | {
36
+ type: "any";
37
+ };
38
+ interface SelectorPredicate {
39
+ key: string;
40
+ op: "=" | "!=" | "^=" | "*=";
41
+ value: string;
42
+ }
43
+ interface SelectorStep {
44
+ /** How this step relates to the previous one (absent on the first). */
45
+ combinator?: "child" | "descendant";
46
+ head: SelectorHead;
47
+ predicates: SelectorPredicate[];
48
+ /** `:nth(n)`, 1-based. */
49
+ nth?: number;
50
+ }
51
+ interface ParsedSelector {
52
+ steps: SelectorStep[];
53
+ }
54
+ /** Parse a selector (ADR 131); `null` when it is not one. Never throws. */
55
+ declare function parseSelector(text: string): ParsedSelector | null;
56
+
57
+ /** A core write plan: the ops, or a typed refusal. */
58
+ type CorePlan = {
59
+ ok: true;
60
+ mutations: MutationInput[];
61
+ } | {
62
+ ok: false;
63
+ code: ObjectErrorCode;
64
+ reason: string;
65
+ };
66
+ /** A core `create` plan (protocol 71). `address` is the new object's
67
+ * address when its id is known up front (a swatch, a style, a text
68
+ * variable), else `$h:<handle>`; `resolve` names the object after the
69
+ * commit (a minted page item, page or layer). `kind` is the SDK kind the
70
+ * rows of later ops on `$h:<handle>` come from. */
71
+ type CoreCreatePlan = {
72
+ ok: true;
73
+ mutations: MutationInput[];
74
+ kind: string;
75
+ address: string;
76
+ /** Props the create op does not carry: set on the new object. */
77
+ props?: Record<string, unknown>;
78
+ resolve?: (outcome: MutationOutcome) => Promise<string | null>;
79
+ } | {
80
+ ok: false;
81
+ code: ObjectErrorCode;
82
+ reason: string;
83
+ };
84
+ /** The core backend the registry routes to. */
85
+ interface CoreObjects {
86
+ /** The engine protocol this seam speaks, once known (feature-detected
87
+ * on first use; the registry awaits it before reading rows). */
88
+ ready?(): Promise<number>;
89
+ kinds(): ObjectKindInfo[];
90
+ schema(kind: string): PropertySchema[];
91
+ get(a: ParsedAddress, path: string): Promise<ObjectValue>;
92
+ /** Plan a write (value already schema-validated). `kind` names the SDK
93
+ * kind of a `$h:` handle address made earlier in the same batch. */
94
+ planSet(a: ParsedAddress, path: string, value: unknown, kind?: string): Promise<CorePlan>;
95
+ /** Plan a `create` of a core object (protocol 71). `handle` binds the
96
+ * new object for later ops of the same batch. */
97
+ planCreate?(op: Extract<ObjectOp, {
98
+ op: "create";
99
+ }>, handle: string): Promise<CoreCreatePlan>;
100
+ /** Plan a `delete` of a core object. */
101
+ planDelete?(a: ParsedAddress): Promise<CorePlan>;
102
+ /** The wire `ElementId` of an address (labels go here). */
103
+ elementIdOf(a: ParsedAddress): Promise<ElementId | null>;
104
+ /** The `x-paged:` labels on a label HOST — a page item, a story (range),
105
+ * a page or the document — as key → raw value; null when the address
106
+ * is not a label host or does not exist. */
107
+ labelsOf(a: ParsedAddress): Promise<Record<string, string> | null>;
108
+ /** The mutation that sets (`value`) or clears (`null`) one plugin label
109
+ * on a label host: `setPluginMetadata` (item / story), `setPageMetadata`
110
+ * (page, protocol 70) or `setDocumentMetadata` (doc); null when the
111
+ * address is not a label host. */
112
+ planLabel(a: ParsedAddress, key: string, value: string | null, caller: string): Promise<MutationInput | null>;
113
+ /** Evaluate core selector steps (no plugin steps). */
114
+ query(steps: readonly SelectorStep[]): Promise<string[]>;
115
+ /** Commit mutations as ONE engine mutation (a `batch` when > 1). */
116
+ commit(mutations: readonly MutationInput[]): Promise<MutationOutcome>;
117
+ /** Pre-71 only: remember a table's story (a `cell:` address carries
118
+ * none; the old wire's `TableCell` id needs it). A no-op at 71. */
119
+ noteTableStory?(tableId: string, storyId: string): void;
120
+ /** Engine changes (mutation / undo / redo / load). */
121
+ onDidChange(listener: () => void): () => void;
122
+ /** Drop derived caches (a host that loads without a broadcast). */
123
+ invalidate(): void;
124
+ /** Release the engine subscription (a private, per-host backend). */
125
+ dispose(): void;
126
+ }
127
+ interface CreateCoreObjectsOptions {
128
+ /** The engine's protocol, when the caller knows it (skips the probe). */
129
+ protocol?: number | (() => number | undefined);
130
+ }
131
+ /** The first protocol with `Set` / `RequestGet` / `RequestQuery`. */
132
+ declare const OBJECT_MODEL_PROTOCOL = 71;
133
+ /**
134
+ * The core seam over a live engine. Feature-detects the engine protocol
135
+ * and delegates to the protocol-71 seam or the pre-71 table.
136
+ */
137
+ declare function createCoreObjects(getEditor: () => PagedEditor, options?: CreateCoreObjectsOptions): CoreObjects;
138
+ /** Every item kind word a selector may use for core frames. */
139
+ declare const FRAME_KIND_WORDS: readonly string[];
140
+
141
+ /** What a plugin host hands the registry at registration. */
142
+ interface ObjectModelRegistration {
143
+ plugin: string;
144
+ model: ObjectModelContribution;
145
+ /** The plugin's OWN parts door — `state` writes land in its namespace. */
146
+ parts?: PartsSurface;
147
+ log?: PluginLogger;
148
+ }
149
+ /** The shared registry: the ungated `ObjectsSurface` (what the host app,
150
+ * the harness and the CLI call) plus the adapter-side `register`. */
151
+ interface ObjectRegistry extends ObjectsSurface {
152
+ register(registration: ObjectModelRegistration): ObjectModelHandle;
153
+ /** The core backend, when one is wired (null = plugin objects only). */
154
+ readonly core: CoreObjects | null;
155
+ /** A view of this registry whose writes report each engine commit they
156
+ * make (its `appliedSeq`) to `note` — including the writes a plugin
157
+ * command's handler makes, since an `invoke` through the view hands the
158
+ * handler the same view. Writes through any other surface (a panel, a
159
+ * UI edit made meanwhile) are never reported. The script bridge answers
160
+ * a round through one, so the host can send exactly the script's own
161
+ * writes as `HostObjectsResult.committed` (protocol 71). */
162
+ tracked(note: (appliedSeq: number) => void): ObjectsSurface;
163
+ }
164
+ interface CreateObjectRegistryOptions {
165
+ core?: CoreObjects | null;
166
+ log?: Pick<PluginLogger, "warn">;
167
+ }
168
+ /** Non-ASCII → `\uXXXX`, as InDesign keeps label values (survey,
169
+ * 2026-10-06); still valid JSON. */
170
+ declare function escapeLabelValue(text: string): string;
171
+ declare function createObjectRegistry(options?: CreateObjectRegistryOptions): ObjectRegistry;
172
+
12
173
  /** The implemented feature set — `host.supports()` answers from this,
13
174
  * so docs/tests can't drift from code. Form: `"area.member@major"`. */
14
175
  declare const HOST_FEATURES: readonly string[];
@@ -420,6 +581,13 @@ interface CreateBundleHostOptions {
420
581
  * (nothing would ever consult the provider) and
421
582
  * `supports("bindings.provider@1")` is false. */
422
583
  bindingProviders?: BindingProviderBackend;
584
+ /** Host-provided SHARED OBJECT REGISTRY (ADR 323): the editor / headless
585
+ * host / Node CLI creates ONE (`createObjectRegistry({ core:
586
+ * createCoreObjects(getEditor) })`) and injects the SAME instance into
587
+ * every plugin host, so `host.objects` routes across bundles. When
588
+ * absent, the host builds a PRIVATE registry (core + this bundle's own
589
+ * kinds) and `supports("objects.shared@1")` is false. */
590
+ objects?: ObjectRegistry;
423
591
  /** Console sink override.
424
592
  *
425
593
  * Originally a test hook, and now ALSO the production capture point: the
@@ -443,6 +611,11 @@ interface CreateBundleHostOptions {
443
611
  * `host.widgets` is the plain-textarea fallback and
444
612
  * `supports("widgets.codeEditor@1")` answers false. */
445
613
  widgets?: Partial<WidgetSurface>;
614
+ /** §12.8 — the host's `PropertyField` (and its schema-panel property
615
+ * rows) render LIST and STRUCT values with `items` / `fields`, editing
616
+ * through `editValue`. Makes `supports("widgets.propertyField.values@1")`
617
+ * true (only together with `widgets.PropertyField`). */
618
+ propertyFieldValues?: boolean;
446
619
  /** The host's will-save registry. When absent, `document.onWillSave`
447
620
  * holds listeners that never run and `supports("document.onWillSave@1")`
448
621
  * is false. */
@@ -568,6 +741,75 @@ interface BundleHostHandle {
568
741
  }
569
742
  declare function createBundleHost(getEditor: () => PagedEditor, manifest: PluginManifest, options?: CreateBundleHostOptions): BundleHostHandle;
570
743
 
744
+ /** One call a suspended script makes (core `HostObjectCall`). */
745
+ type HostObjectCall = {
746
+ op: "get";
747
+ address: string;
748
+ path: string;
749
+ } | {
750
+ op: "batch";
751
+ ops: unknown[];
752
+ } | {
753
+ op: "query";
754
+ selector: string;
755
+ } | {
756
+ op: "schema";
757
+ target: string;
758
+ }
759
+ /** A typed command (`paged.invoke`): `core.<op>` or a plugin's. */
760
+ | {
761
+ op: "invoke";
762
+ id: string;
763
+ args?: unknown;
764
+ }
765
+ /** The typed commands on offer (`paged.commands`), optionally one owner's. */
766
+ | {
767
+ op: "commands";
768
+ owner?: string;
769
+ };
770
+ /** The answer to one call (core `HostObjectAnswer`). */
771
+ interface HostObjectAnswer {
772
+ value?: unknown;
773
+ error?: {
774
+ code: string;
775
+ reason: string;
776
+ index?: number;
777
+ } | null;
778
+ }
779
+ interface ScriptRunResult {
780
+ output: string[];
781
+ error: string | null;
782
+ budgetKind?: string | null;
783
+ /** Host round trips the script took (0 = it never touched a plugin). */
784
+ hostRounds: number;
785
+ }
786
+ /** A request/reply door onto the engine (`client.send`). */
787
+ type ScriptSend = (message: {
788
+ kind: string;
789
+ payload: unknown;
790
+ }) => Promise<{
791
+ kind: string;
792
+ payload?: any;
793
+ }>;
794
+ /** Answer a suspended script's calls through the object registry, one
795
+ * answer per call, in order. Never throws: a failure is the answer's
796
+ * `error` (the script sees an exception carrying its `code`). */
797
+ declare function answerHostObjects(objects: ObjectsSurface, calls: readonly HostObjectCall[]): Promise<HostObjectAnswer[]>;
798
+ /** {@link answerHostObjects}, plus `committed`: the engine `appliedSeq` of
799
+ * every write made ANSWERING these calls (a batch that committed). The
800
+ * host sends it as `HostObjectsResult.committed` — protocol 71 folds only
801
+ * a script session's own undo records, so without it a script's plugin
802
+ * write would be a separate undo step; a write made by anyone else
803
+ * while the script waits is never listed and stays its own step. */
804
+ declare function answerHostObjectsRound(objects: ObjectsSurface, calls: readonly HostObjectCall[]): Promise<{
805
+ answers: HostObjectAnswer[];
806
+ committed: number[];
807
+ }>;
808
+ /** Run a script whose `plugin:` calls are answered by `objects`. */
809
+ declare function runScriptWithObjects(send: ScriptSend, objects: ObjectsSurface | null, source: string, options?: {
810
+ budget?: unknown;
811
+ }): Promise<ScriptRunResult>;
812
+
571
813
  /** The published package the headless harness boots. */
572
814
  declare const CANVAS_WASM_PKG = "@paged-media/canvas-wasm";
573
815
  /**
@@ -649,7 +891,7 @@ interface RecordedContribution {
649
891
  id: string;
650
892
  value: ToolContribution | PanelContribution | SchemaPanelContribution | CommandContribution | KeybindingContribution | OverlayContribution | EditContextContribution | ObjectTypeContribution | ImporterContribution | ExporterContribution;
651
893
  }
652
- interface HarnessOptions extends LoadHeadlessEngineOptions, Pick<CreateBundleHostOptions, "console" | "storage" | "capabilityMode" | "assetSource" | "blobStore" | "clipboard" | "secrets" | "bindingProviders" | "willSave" | "toolSettings"> {
894
+ interface HarnessOptions extends LoadHeadlessEngineOptions, Pick<CreateBundleHostOptions, "console" | "storage" | "capabilityMode" | "assetSource" | "blobStore" | "clipboard" | "secrets" | "bindingProviders" | "dataProviders" | "objects" | "willSave" | "toolSettings"> {
653
895
  /** D-27 — back `host.text` with the ENGINE's shaper
654
896
  * (`CanvasWorker.measureText`, the one the editor's worker calls)
655
897
  * instead of the estimate, so `measureString` / `measureStrings`
@@ -755,6 +997,22 @@ interface HeadlessHost {
755
997
  * that a path it does not declare comes back as a typed refusal to
756
998
  * fall through to core). */
757
999
  readonly bindingProviders: BindingProviderBackend;
1000
+ /** ADR 323 — the SHARED object registry every bundle host here routes
1001
+ * through (core addresses over this engine + every loaded bundle's
1002
+ * kinds). The ungated host side: what the Node CLI, a Boa bridge or a
1003
+ * conformance test calls. */
1004
+ readonly objects: ObjectRegistry;
1005
+ /** Run a `paged.*` Boa script against the loaded document with the
1006
+ * async host bridge armed (ADR 323, engine protocol 71): its `plugin:`
1007
+ * addresses are answered by `objects`, so core and plugin writes of one
1008
+ * script land as ONE undo step. */
1009
+ runScript(source: string, options?: {
1010
+ budget?: unknown;
1011
+ }): Promise<ScriptRunResult>;
1012
+ /** The SHARED data-provider registry (D-09) injected into every bundle
1013
+ * host here, so a provider bundle and a consumer bundle rendezvous
1014
+ * headlessly and `supports("dataProviders@1")` is true. */
1015
+ readonly dataProviders: DataProviderBackend;
758
1016
  /** The will-save registry this host injected: `fire()` runs every
759
1017
  * bundle's `document.onWillSave` listener and awaits them, as a save
760
1018
  * would. */
@@ -765,6 +1023,21 @@ interface HeadlessHost {
765
1023
  /** Load an IDML package into the headless document. Resolves to the
766
1024
  * loaded page ids (or throws on a parse failure). */
767
1025
  load(idml: Uint8Array): Promise<string[]>;
1026
+ /** ADR 324 — the core EXPORT door the Node CLI (and a conformance test)
1027
+ * calls: the active document as `.paged` (`exportPaged`), `.idml`
1028
+ * (`exportIdml`, `linkBase` for relative links) or PDF (the
1029
+ * `exportPdfBegin` → one `exportPdfPage` per page → `exportPdfFinish`
1030
+ * loop the editor's client drives; `pdf` is the wire's
1031
+ * `ExportPdfWireOptions`). Rejects with the engine's error. Plugin
1032
+ * formats go through `exportersContributed()`. */
1033
+ exportDocument(format: "paged" | "idml" | "pdf", options?: {
1034
+ pdf?: Record<string, unknown>;
1035
+ linkBase?: string | null;
1036
+ }): Promise<{
1037
+ bytes: Uint8Array;
1038
+ diagnostics: string[];
1039
+ lost?: string[];
1040
+ }>;
768
1041
  /** D-26 — every document a bundle opened through `host.documents.open`,
769
1042
  * in order (declined opens are not listed). */
770
1043
  openedDocuments(): ReadonlyArray<{
@@ -772,9 +1045,11 @@ interface HeadlessHost {
772
1045
  requester: string;
773
1046
  pageIds: string[];
774
1047
  }>;
775
- /** Activate a bundle against this host (apiVersion-negotiated). The
776
- * returned disposer runs the bundle's teardown; the host's own
777
- * facade teardown runs on `dispose()`. */
1048
+ /** Activate a bundle against this host (apiVersion-negotiated). Several
1049
+ * bundles may be loaded at once (each gets its own host bound to its
1050
+ * manifest; they meet through the shared registries — objects, data
1051
+ * providers, binding providers). `host` is the LAST loaded bundle's.
1052
+ * The returned disposer runs that bundle's teardown. */
778
1053
  loadBundle(bundle: PagedBundle): Disposable;
779
1054
  /** Tear down: bundle teardown + facade teardown + free the wasm. The
780
1055
  * honesty contract — after dispose the contribution log is empty and
@@ -818,6 +1093,168 @@ declare const API_VERSION = "0.2.0";
818
1093
  */
819
1094
  declare function satisfiesApiVersion(range: string, version?: string): boolean;
820
1095
 
1096
+ declare const VALUE_TYPE_KINDS: readonly ["bool", "number", "length", "color", "enum", "text", "ref", "bounds", "transform", "point", "bytes", "asset", "list", "map", "struct"];
1097
+ /** Why `t` is not a well-formed `ValueType`, or null. */
1098
+ declare function checkValueType(t: unknown, at?: string): string | null;
1099
+ /**
1100
+ * Path grammar of a schema ROW: dotted identifiers, each optionally
1101
+ * followed by bracket segments. `[]` makes an INDEXED row (`points[]`,
1102
+ * `points[].anchor`, `ranges[][]`) that stands for every `points[3]` /
1103
+ * `cells[B4]` a caller names; its type is the type of ONE item at that
1104
+ * index. A concrete index (`colorize[0]`) is an ordinary row and wins
1105
+ * over the indexed one.
1106
+ */
1107
+ declare const ROW_PATH: RegExp;
1108
+ /** The row path a concrete path resolves to: every `[<index>]` becomes
1109
+ * `[]` (`points[3].anchor` → `points[].anchor`). Bracket contents may be
1110
+ * any text without `]` (a list index, a map key such as `x-paged:oid`). */
1111
+ declare function rowPathOf(path: string): string;
1112
+ /** Find the row for a concrete path: exact first, then its indexed form. */
1113
+ declare function findRow<R extends {
1114
+ path: string;
1115
+ }>(rows: ReadonlyMap<string, R>, path: string): R | null;
1116
+ /** Why a schema row list is unusable (empty, malformed, duplicate path). */
1117
+ declare function checkSchemaRows(rows: unknown): string | null;
1118
+ /** Why `value` does not satisfy `type` (and the row's range / nullable), or
1119
+ * null when it does. */
1120
+ declare function validateValue(type: ValueType, value: unknown, row?: Pick<PropertySchema, "nullable" | "range">, at?: string): string | null;
1121
+ /** Bytes → the `data:` URI core reads an asset back as (the MIME typed by
1122
+ * the bytes' magic, the same table core uses; otherwise
1123
+ * `application/octet-stream`). */
1124
+ declare function assetFromBytes(bytes: Uint8Array | ArrayBuffer): string;
1125
+ /**
1126
+ * Fill struct DEFAULTS into a value that already validated: a missing
1127
+ * field with a `default` gets it (recursively, also inside lists and
1128
+ * maps); optional fields stay absent. An `asset` given as bytes is
1129
+ * encoded to its `data:` URI. Returns a new value; the input is
1130
+ * not mutated.
1131
+ */
1132
+ declare function applyDefaults(type: ValueType, value: unknown): unknown;
1133
+ /** Parse a length with an optional unit (`"3mm"`, `"12"`, `"0.5in"`) into
1134
+ * points; null when it is not one. */
1135
+ declare function parseLength(text: string): number | null;
1136
+ /**
1137
+ * EXPLICIT coercion of a loosely typed input (a CLI argument, a CSV cell)
1138
+ * to `type`. Returns `{ ok: true, value }` or `{ ok: false, reason }`; the
1139
+ * coerced value is then checked with `validateValue` as usual. Values that
1140
+ * already have the right shape pass through unchanged.
1141
+ */
1142
+ declare function coerceValue(type: ValueType, input: unknown): {
1143
+ ok: true;
1144
+ value: unknown;
1145
+ } | {
1146
+ ok: false;
1147
+ reason: string;
1148
+ };
1149
+
1150
+ /** An engine error text → the refusal code it means. */
1151
+ declare function codeOfEngineError(text: string): ObjectErrorCode;
1152
+
1153
+ /** The command id prefix: `core.insertTable`. */
1154
+ declare const CORE_COMMAND_PREFIX = "core.";
1155
+ /** Wire ops that are NOT typed commands, each with the reason. */
1156
+ declare const CORE_COMMAND_EXCLUSIONS: Readonly<Record<string, string>>;
1157
+ /** What a creating command makes. `element`: the engine mints it (reported
1158
+ * in `minted`, bindable by handle) — `multi` mints one per `elementIds`
1159
+ * entry; `page` / `layer`: found by diffing the page / layer list;
1160
+ * `named`: the address follows from the args. The Rust side of this table
1161
+ * is paged-canvas `created_element_id` (and `duplicate_roots`). */
1162
+ type Creates = {
1163
+ by: "element";
1164
+ kind: "frame" | "table";
1165
+ multi?: true;
1166
+ } | {
1167
+ by: "page";
1168
+ } | {
1169
+ by: "layer";
1170
+ } | {
1171
+ by: "named";
1172
+ address: (args: Record<string, unknown>) => string | null;
1173
+ };
1174
+ declare const CORE_COMMAND_CREATES: Readonly<Record<string, Creates>>;
1175
+ /** The ops that are typed commands, in wire order. */
1176
+ declare const CORE_COMMAND_OPS: readonly string[];
1177
+ /** The typed command list (static: it is the vendored wire's). */
1178
+ declare function coreCommandInfos(): ObjectCommandInfo[];
1179
+ declare const isCoreCommand: (id: string) => boolean;
1180
+
1181
+ interface CoreWireOpRow {
1182
+ args: Extract<ValueType, {
1183
+ kind: "struct";
1184
+ }>;
1185
+ nullFill: readonly string[];
1186
+ }
1187
+ declare const CORE_WIRE_OPS: Readonly<Record<string, CoreWireOpRow>>;
1188
+
1189
+ type CorePathScope = "frame" | "story" | "cell" | "table" | "layer" | "page";
1190
+ interface CorePathRow {
1191
+ scope: CorePathScope;
1192
+ /** The wire `Value` variant a write carries. */
1193
+ wire: string;
1194
+ type?: ValueType;
1195
+ inferred?: true;
1196
+ readOnly?: true;
1197
+ }
1198
+ declare const OP: {
1199
+ readonly op: true;
1200
+ };
1201
+ /** A path the pre-71 wire does not carry: only the protocol-71 seam reaches it. */
1202
+ declare const V71: {
1203
+ readonly since: 71;
1204
+ };
1205
+ declare const CORE_PATHS: Record<PropertyPath, CorePathRow | typeof OP | typeof V71>;
1206
+ /** The catalog's advertised ALIASES (Boa names) → the wire path, mirrored
1207
+ * from `catalog.json` `pathAliases`. Accepted on input, never listed. */
1208
+ declare const CORE_PATH_ALIASES: Readonly<Record<string, PropertyPath>>;
1209
+ /** One `propertySchemas` row as core's catalog publishes it (protocol 71). */
1210
+ interface CoreCatalogRow {
1211
+ addressKind: string;
1212
+ appliesTo?: readonly string[];
1213
+ path: string;
1214
+ type: {
1215
+ kind: string;
1216
+ unit?: string;
1217
+ members?: readonly string[];
1218
+ to?: string;
1219
+ of?: string;
1220
+ shape?: string;
1221
+ };
1222
+ wire: string;
1223
+ nullable?: boolean;
1224
+ range?: {
1225
+ min?: number;
1226
+ max?: number;
1227
+ step?: number;
1228
+ };
1229
+ default?: unknown;
1230
+ access?: "readWrite" | "readOnly" | "derived";
1231
+ virtual?: {
1232
+ op: string;
1233
+ field?: string;
1234
+ clearOp?: string;
1235
+ } | null;
1236
+ bindable?: boolean;
1237
+ }
1238
+ /** A normalised core row: the SDK schema row, the wire `Value` variant a
1239
+ * write carries, and the CORE address kind the row belongs to (the SDK
1240
+ * folds `storyRange` into `story` and `group` into `frame`). */
1241
+ interface CoreRow71 {
1242
+ schema: PropertySchema;
1243
+ wire: string;
1244
+ coreKind: string;
1245
+ /** Not in core's catalog: typed from the interim table (CORE_ROWLESS_PATHS). */
1246
+ inferred?: true;
1247
+ }
1248
+ /** Core's catalog type → the SDK's `ValueType`; null for an OPERATION row
1249
+ * (path-point edits, outline / offset / simplify): those are geometry
1250
+ * ops, not values, and stay reachable as a raw wire `{ type, value }`. */
1251
+ declare function normalizeCoreType(t: CoreCatalogRow["type"]): ValueType | null;
1252
+ /** The raw rows of the vendored catalog (empty before protocol 71). */
1253
+ declare const CORE_CATALOG_ROWS: readonly CoreCatalogRow[];
1254
+ /** SDK kind → path → normalised row, from the vendored catalog. Indexed
1255
+ * core paths (`labels[key]`, `rows[i].height`) become `[]` rows. */
1256
+ declare function coreSchema71(): ReadonlyMap<string, ReadonlyMap<string, CoreRow71>>;
1257
+
821
1258
  /** The default widget catalog: a textarea CodeEditor and a native colour
822
1259
  * input. Each member is replaced by the one the host app injects through
823
1260
  * `createBundleHost({ widgets })`; members it omits keep the fallback. */
@@ -1010,6 +1447,108 @@ declare function contributePanel(host: BundleHost, panel: PanelContribution): Di
1010
1447
  * list the id). */
1011
1448
  declare function contributeSchemaPanel(host: BundleHost, panel: SchemaPanelContribution): Disposable;
1012
1449
 
1450
+ /** Is this row an object-model property row (the property row)? */
1451
+ declare function isPropertyRow(row: PanelSchemaRow): row is PanelSchemaPropertyRow;
1452
+ /** Options shared by the row builders (everything but `field`/`path`/`address`). */
1453
+ type PropertyRowOptions = Omit<PanelSchemaPropertyRow, "field" | "path" | "address">;
1454
+ /** One property row. */
1455
+ declare function propertyRow(path: string, address: PropertyFieldAddress, opts?: PropertyRowOptions): PanelSchemaPropertyRow;
1456
+ /** Rows for several paths of one kind, in order. `labels` maps a path to
1457
+ * its row label (absent = the schema row's title). */
1458
+ declare function propertyRows(kind: string, paths: readonly string[], address: PropertyFieldAddress, opts?: {
1459
+ labels?: Readonly<Record<string, string>>;
1460
+ row?: (path: string) => PropertyRowOptions;
1461
+ }): PanelSchemaPropertyRow[];
1462
+ /** Every property row of a schema, with where it sits. */
1463
+ declare function propertyRowsOf(schema: PanelSchema): Array<{
1464
+ section: number;
1465
+ row: number;
1466
+ field: PanelSchemaPropertyRow;
1467
+ }>;
1468
+ interface PanelSchemaIssue {
1469
+ /** `sections[1].rows[3]` — where the problem is. */
1470
+ at: string;
1471
+ message: string;
1472
+ }
1473
+ interface ValidatePanelSchemaOptions {
1474
+ /** The schema rows of a qualified kind (`plugin:<id>/<kind>`), or
1475
+ * `undefined` when unknown. With it, every property row's path is
1476
+ * checked against its kind's schema. */
1477
+ schemaOf?: (kind: string) => readonly PropertySchema[] | undefined;
1478
+ /** The bundle's plugin id: a `plugin:` kind or address of ANOTHER plugin
1479
+ * is then reported (a panel edits its own objects or core's). */
1480
+ pluginId?: string;
1481
+ }
1482
+ /** The qualified kind a selector selects (its last step's head), if any. */
1483
+ declare function selectorKind(selector: string): string | null;
1484
+ /**
1485
+ * Every problem in a panel schema, as data. An empty list = it renders as
1486
+ * declared. Checks the property rows in full (address form, kind,
1487
+ * path against `schemaOf`) and the v1 rows' one structural rule (a
1488
+ * non-empty widget id).
1489
+ */
1490
+ declare function validatePanelSchema(schema: PanelSchema, opts?: ValidatePanelSchemaOptions): PanelSchemaIssue[];
1491
+
1492
+ type Ok<T> = {
1493
+ ok: true;
1494
+ } & T;
1495
+ type No = {
1496
+ ok: false;
1497
+ code: ObjectErrorCode;
1498
+ reason: string;
1499
+ };
1500
+ /** The value a new item / an unset field starts from: a struct's field
1501
+ * defaults (required fields without one get their type's default,
1502
+ * optional ones stay absent), an enum's first member, 0, "", false, [],
1503
+ * `Color/Black` for a colour, the zero point / identity transform. */
1504
+ declare function defaultValueOf(type: ValueType, row?: Pick<PropertySchema, "default" | "range">): unknown;
1505
+ /**
1506
+ * Apply one edit to a value of `type` (a list, or a struct for
1507
+ * `fieldSet`). Pure; the result is validated against `type`.
1508
+ */
1509
+ declare function applyValueEdit(current: unknown, edit: ValueEdit, type: ValueType): Ok<{
1510
+ value: unknown;
1511
+ }> | No;
1512
+ type Reader = Pick<ObjectsSurface, "get" | "schema">;
1513
+ /**
1514
+ * Lower one edit of `path` on every target to `set` ops (read, apply,
1515
+ * set). Each target is edited from its OWN current value, so a multi-
1516
+ * selection stays per-object. Refusals are typed; no op is produced
1517
+ * unless every target accepts the edit.
1518
+ */
1519
+ declare function planValueEdit(objects: Reader, addresses: readonly Address[], path: string, edit: ValueEdit): Promise<Ok<{
1520
+ ops: ObjectOp[];
1521
+ }> | No>;
1522
+ /** {@link planValueEdit}, then ONE `batch` (one undo step). */
1523
+ declare function editValue(objects: Reader & Pick<ObjectsSurface, "batch">, addresses: readonly Address[], path: string, edit: ListEdit | StructEdit, opts?: {
1524
+ label?: string;
1525
+ }): Promise<ObjectWriteResult>;
1526
+
1527
+ interface ObjectListRow {
1528
+ selfId: Address;
1529
+ name: string;
1530
+ secondary?: string;
1531
+ }
1532
+ interface PublishObjectListOptions {
1533
+ /** Binding the rows are published under (the list row's `items.bind`). */
1534
+ rows: string;
1535
+ /** Binding holding the chosen address (the list row's
1536
+ * `selectionBinding`, the property rows' `{ bind }`). */
1537
+ select: string;
1538
+ /** The selector to list, from the selection's addresses; `null` = no
1539
+ * list (empty rows). E.g. `(sel) => sel.length === 1 ? `${sel[0]} > plugin:x/layer` : null`. */
1540
+ selector(selection: readonly Address[]): string | null;
1541
+ /** Path read for the row label (default `name`; the address id else). */
1542
+ labelPath?: string;
1543
+ /** Path read for the secondary line. */
1544
+ secondaryPath?: string;
1545
+ }
1546
+ /** Publish the list and keep it live. Dispose to stop. */
1547
+ declare function publishObjectList(host: BundleHost, opts: PublishObjectListOptions): Disposable & {
1548
+ /** Re-read now (resolves when published). */
1549
+ refresh(): Promise<void>;
1550
+ };
1551
+
1013
1552
  /** Register an EDIT CONTEXT (B-02): a content type that, on
1014
1553
  * double-click (or programmatically), pushes a scoped context —
1015
1554
  * restricted tools, emphasized panels, breadcrumb, narrowed
@@ -1037,4 +1576,4 @@ declare function contributeObjectType(host: BundleHost, contribution: ObjectType
1037
1576
  */
1038
1577
  declare function contributeBindingProvider(host: BundleHost, contextType: string, provider: BindingProvider): BindingProviderHandle;
1039
1578
 
1040
- export { API_VERSION, ASSET_BUDGETS, BLOB_BUDGETS, type BindingProviderBackend, type BlobStore, type BundleAssetProvider, type BundleAssetSource, type BundleHostHandle, type BundleTrust, CANVAS_WASM_PKG, CLICK_DRAG_THRESHOLD_PX, type ClipboardBackend, type ConsentBackend, type CreateBundleHostOptions, type DataProviderBackend, type DiagnosticsSink, DisposableStore, type DocumentsBackend, FALLBACK_WIDGETS, HOST_FEATURES, type HarnessOptions, type HeadlessCanvasWorker, type HeadlessHost, type HeadlessHostHandle, type JournalSink, type LoadBundleWasmOptions, type LoadHeadlessEngineOptions, type LoadedBundle, type LoadedBundleWasm, type LoadedEngine, type NativeDocumentBackend, type PageDrag, type PagesBackend, PluginApiNotImplemented, PluginCapabilityError, type RecordableAssetSource, type RecordedContribution, type RecordedFontFaceRequest, type RegisteredBindingProvider, type SecretStoreBackend, type SeededFace, type ShellBackend, type SpawnedWorker, type StorageBacking, type TextCaretBackend, type ToolSettingsBackend, WASM_BUDGETS, WORKER_BUDGETS, type WillSaveBackend, type WorkerBackend, beginPageDrag, commitAndSelect, contributeBindingProvider, contributeEditContext, contributeObjectType, contributePanel, contributeSchemaPanel, contributeTool, createBindingProviderRegistry, createBundleHost, createDataProviderRegistry, createHeadlessHost, createRecordableAssetSource, defineBundle, endLocalFor, inMemoryToolSettings, inMemoryWillSave, loadBundle, loadBundleWasm, loadHeadlessEngine, makeSchemaPanelComponent, protocolFromVersion, pxToPt, readVendoredWireVersion, resolveCanvasWasm, resolveGate, satisfiesApiVersion, toDisposable };
1579
+ export { API_VERSION, ASSET_BUDGETS, BLOB_BUDGETS, type BindingProviderBackend, type BlobStore, type BundleAssetProvider, type BundleAssetSource, type BundleHostHandle, type BundleTrust, CANVAS_WASM_PKG, CLICK_DRAG_THRESHOLD_PX, CORE_CATALOG_ROWS, CORE_COMMAND_CREATES, CORE_COMMAND_EXCLUSIONS, CORE_COMMAND_OPS, CORE_COMMAND_PREFIX, CORE_PATHS, CORE_PATH_ALIASES, CORE_WIRE_OPS, type ClipboardBackend, type ConsentBackend, type CoreCatalogRow, type CoreCreatePlan, type CoreObjects, type CorePathRow, type CorePathScope, type CorePlan, type CoreRow71, type CoreWireOpRow, type CreateBundleHostOptions, type CreateCoreObjectsOptions, type CreateObjectRegistryOptions, type DataProviderBackend, type DiagnosticsSink, DisposableStore, type DocumentsBackend, FALLBACK_WIDGETS, FRAME_KIND_WORDS, HOST_FEATURES, type HarnessOptions, type HeadlessCanvasWorker, type HeadlessHost, type HeadlessHostHandle, type HostObjectAnswer, type HostObjectCall, type JournalSink, type LoadBundleWasmOptions, type LoadHeadlessEngineOptions, type LoadedBundle, type LoadedBundleWasm, type LoadedEngine, type NativeDocumentBackend, OBJECT_MODEL_PROTOCOL, type ObjectListRow, type ObjectModelRegistration, type ObjectRegistry, type PageDrag, type PagesBackend, type PanelSchemaIssue, type ParsedSelector, PluginApiNotImplemented, PluginCapabilityError, type PropertyRowOptions, type PublishObjectListOptions, ROW_PATH, type RecordableAssetSource, type RecordedContribution, type RecordedFontFaceRequest, type RegisteredBindingProvider, type ScriptRunResult, type ScriptSend, type SecretStoreBackend, type SeededFace, type SelectorHead, type SelectorPredicate, type SelectorStep, type ShellBackend, type SpawnedWorker, type StorageBacking, type TextCaretBackend, type ToolSettingsBackend, VALUE_TYPE_KINDS, type ValidatePanelSchemaOptions, WASM_BUDGETS, WORKER_BUDGETS, type WillSaveBackend, type WorkerBackend, addressKindOf, answerHostObjects, answerHostObjectsRound, applyDefaults, applyValueEdit, assetFromBytes, beginPageDrag, checkSchemaRows, checkValueType, codeOfEngineError, coerceValue, commitAndSelect, contributeBindingProvider, contributeEditContext, contributeObjectType, contributePanel, contributeSchemaPanel, contributeTool, coreCommandInfos, coreSchema71, createBindingProviderRegistry, createBundleHost, createCoreObjects, createDataProviderRegistry, createHeadlessHost, createObjectRegistry, createRecordableAssetSource, defaultValueOf, defineBundle, editValue, endLocalFor, escapeLabelValue, findRow, formatAddress, fromElementId, inMemoryToolSettings, inMemoryWillSave, isCoreCommand, isPropertyRow, loadBundle, loadBundleWasm, loadHeadlessEngine, makeSchemaPanelComponent, normalizeAddress, normalizeCoreType, parseAddress, parseLength, parseSelector, planValueEdit, propertyRow, propertyRows, propertyRowsOf, protocolFromVersion, publishObjectList, pxToPt, readVendoredWireVersion, resolveCanvasWasm, resolveGate, rowPathOf, runScriptWithObjects, satisfiesApiVersion, selectorKind, toDisposable, toElementId, validatePanelSchema, validateValue };