@markii/host 0.17.0-next.5 → 0.17.0-next.6

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 (39) hide show
  1. package/dist/browser-worker.classic.js +43 -43
  2. package/dist/browser-worker.js +43 -43
  3. package/dist/conformance/host/18-last-run-and-grants/expected.json +42 -0
  4. package/dist/conformance/host/18-last-run-and-grants/note.mk.md +5 -0
  5. package/dist/conformance/host/18-last-run-and-grants/scenario.json +27 -0
  6. package/dist/conformance/host/README.md +11 -4
  7. package/dist/conformance.d.ts +1 -1
  8. package/dist/conformance.js +1 -1
  9. package/dist/host/adapter.d.ts +21 -7
  10. package/dist/host/cascade-export-behavior.d.ts +3 -1
  11. package/dist/host/cascade-export-behavior.js +7 -4
  12. package/dist/host/conformance-runner.d.ts +8 -0
  13. package/dist/host/conformance-runner.js +40 -2
  14. package/dist/host/create-host.d.ts +231 -62
  15. package/dist/host/create-host.js +204 -98
  16. package/dist/host/export-behavior.d.ts +2 -0
  17. package/dist/host/export-behavior.js +10 -4
  18. package/dist/host/pack-archive.d.ts +7 -6
  19. package/dist/host/pack-archive.js +11 -7
  20. package/dist/host/pack-install.js +9 -7
  21. package/dist/host/pack-remove.d.ts +7 -18
  22. package/dist/host/pack-remove.js +2 -0
  23. package/dist/host/pack-trust-behavior.d.ts +13 -36
  24. package/dist/host/pack-trust-behavior.js +22 -1
  25. package/dist/host/run-behavior.d.ts +21 -34
  26. package/dist/host/run-behavior.js +23 -5
  27. package/dist/index.d.ts +5 -10
  28. package/dist/index.js +0 -1
  29. package/dist/internal.d.ts +9 -2
  30. package/dist/internal.js +3 -2
  31. package/dist/node-worker.js +3 -1
  32. package/dist/node.d.ts +1 -2
  33. package/dist/node.js +1 -1
  34. package/dist/run/node-isolate.d.ts +6 -2
  35. package/dist/run/node-isolate.js +2 -0
  36. package/dist/run/run-host.d.ts +2 -2
  37. package/dist/run/worker-entry-browser.d.ts +6 -1
  38. package/dist/run/worker-entry-browser.js +62 -5
  39. package/package.json +11 -11
@@ -5,28 +5,38 @@
5
5
  * environment-neutral. VS Code's webview imports only the pure pieces and
6
6
  * never calls this function.
7
7
  *
8
- * It provides `run`, `diagnostics`, `open`, `exportNote`, `installPack`, `loadPacks`, `completeAt`,
9
- * `hoverAt`, and `insertComponent`, over the behavior modules (`./export-behavior.js`, `./pack-install.js`,
10
- * `./pack-load.js`, `./editor-behavior.js`). Every one of them
11
- * returns the shared `Unsupported` outcome, with one diagnostics line,
12
- * when the adapter lacks the capability it needs — AGENTS.md's "clean is
13
- * not silent": a decline is never a silent no-op.
8
+ * It provides `run`, `lastRun`, `forgetGrants`, `diagnostics`, `open`,
9
+ * `exportNote`, `exportLinkedSet`, `installPack`, `loadPacks`, `completeAt`,
10
+ * `hoverAt`, and `insertComponent`, over the behavior modules
11
+ * (`./export-behavior.js`, `./pack-install.js`, `./pack-load.js`,
12
+ * `./editor-behavior.js`). A behavior that needs a capability the adapter
13
+ * lacks returns the shared `Unsupported` outcome with one diagnostics line,
14
+ * so a decline is never a silent no-op ("clean is not silent").
15
+ *
16
+ * Outcome vocabulary, the same in every behavior:
17
+ * `declined` is a user's "no" to a prompt or a cancelled picker; `failed`
18
+ * is an I/O or runtime failure and carries a `reason`; `invalid` is input
19
+ * that was read and judged bad and carries a `reason`; `unsupported` is a
20
+ * host that lacks the capability. No behavior rejects.
14
21
  */
15
22
  import type { HostAdapter, HostExportFormat, HostTextEdit } from './adapter.js';
16
23
  import type { RunResult, SpawnRunRequest } from '../run/run-host.js';
17
- import type { StoredValue } from '@markii/runtime';
24
+ import type { RunTrigger, StoredValue } from '@markii/runtime';
25
+ import type { BundleManifest } from '@markii/bundle';
26
+ import type { PinPolicy } from '../run/net-pinning.js';
27
+ import type { PackModulesMap } from '../run/lua-resolver.js';
28
+ import type { ValuesFailure } from '../values-failure.js';
29
+ import { type RunTrace } from '../run/run-trace.js';
18
30
  import type { OnDiagnostic, UnavailableComponent } from '@markii/stdlib';
19
31
  import type { CompletionItem, ComponentDocumentation, LineColumn } from '@markii/stdlib/editor';
20
- import { type RunViaAdapterRequest, type RunViaAdapterResult } from './run-behavior.js';
21
32
  import { type PackDiscoveryIo } from './pack-load.js';
22
33
  import type { ExportBodyRenderer, ExportPackStylesheet, ExportRenderInfo, HtmlExportEngine, StaticExportReason } from '../export/note-export.js';
23
34
  import type { EmbeddedImageReport, ExportImageReader } from '../export/image-embed.js';
24
- import type { CascadeLinkResolver } from '../export/cascade.js';
25
- import { type CascadeExportOutcome } from './cascade-export-behavior.js';
35
+ import type { CascadeLinkResolver, CascadeTruncation } from '../export/cascade.js';
36
+ import { type CascadeExportedNote, type UnreadableCascadeNote } from './cascade-export-behavior.js';
26
37
  import type { DiscoveredPack, SkippedPackFolder } from '../packs/discover.js';
27
38
  import { type TerminalPackScript } from './terminal-packs.js';
28
- import { type RemovePackOutcome } from './pack-remove.js';
29
- import type { DisablePackOutcome, EnablePackOutcome, InstalledPacksListing } from './pack-trust-behavior.js';
39
+ import type { InstalledPacksListing } from './pack-trust-behavior.js';
30
40
  /** The shared decline shape every behavior returns when the adapter lacks the capability it needs. */
31
41
  export interface Unsupported {
32
42
  readonly kind: 'unsupported';
@@ -43,17 +53,63 @@ export type OpenOutcome = {
43
53
  readonly kind: 'failed';
44
54
  readonly reason: string;
45
55
  };
46
- export type RunRequest = RunViaAdapterRequest;
47
- export type RunOutcome = ({
48
- readonly kind: 'ran';
49
- } & RunViaAdapterResult) | Unsupported;
50
- export interface ExportRequest {
51
- readonly format: HostExportFormat;
52
- /** The note's own path, used to name the exported file. */
53
- readonly notePath: string;
56
+ export interface RunRequest {
57
+ /** Stable identity for the note this run belongs to. The same key reads the run back through `lastRun` and clears its grants through `forgetGrants`. */
58
+ readonly documentKey: string;
54
59
  readonly text: string;
55
- /** The note's last-run values, baked into an html/pdf export. Omitted or empty exports the note's standard empty states. */
56
- readonly values?: Record<string, StoredValue>;
60
+ readonly trigger: RunTrigger;
61
+ /** The address policy for the run's network access. Omitted keeps the fail-closed default, which refuses private and loopback addresses. */
62
+ readonly netPolicy?: PinPolicy;
63
+ /** Present only for a bundle-backed note. */
64
+ readonly bundle?: {
65
+ readonly manifest: BundleManifest;
66
+ /** Called once per run, before the grant flow, to read the bundle's files. */
67
+ readonly buildSnapshot: () => Promise<Record<string, Uint8Array>>;
68
+ /** Receives the bundle's `.cache/` subtree after a run that produced one. */
69
+ readonly persistCacheOut: (cacheOut: Record<string, Uint8Array>) => Promise<void>;
70
+ };
71
+ /** Pre-read pack Lua modules, so a script's `require` of a pack module resolves. Omit it when no packs are loaded. */
72
+ readonly packModules?: PackModulesMap;
73
+ /** Called once per script as its value arrives, already scrubbed for the wire. */
74
+ readonly onValue?: (name: string, value: StoredValue) => void;
75
+ /** The wall-clock budget for the run. Defaults to 15 seconds. */
76
+ readonly timeoutMs?: number;
77
+ }
78
+ export type RunOutcome = {
79
+ readonly kind: 'ran';
80
+ readonly values: Record<string, StoredValue>;
81
+ readonly failures: ValuesFailure[];
82
+ /** The same failures with their messages, for the diagnostics surface only. */
83
+ readonly failureDetails: {
84
+ name: string;
85
+ kind: ValuesFailure['kind'];
86
+ message: string;
87
+ }[];
88
+ /** Lines describing a mismatch between declared and reached hosts, for the diagnostics surface only. */
89
+ readonly netDeclarationDiagnostics: string[];
90
+ /** The outcome this run recorded, for the in-note marker. */
91
+ readonly trace: RunTrace;
92
+ /** How many of this run's values came back `fresh`. */
93
+ readonly freshCount: number;
94
+ /** How many of this run's values came back `error`. */
95
+ readonly errorCount: number;
96
+ }
97
+ /** The run threw. The diagnostics line and a failed trace are already written. */
98
+ | {
99
+ readonly kind: 'failed';
100
+ readonly reason: string;
101
+ } | Unsupported;
102
+ /** What a note's last run left in the adapter's memento. */
103
+ export interface LastRunOutcome {
104
+ /** The stored values marked for showing on open: a `fresh` value reads `stale` until a new run lands. Empty when nothing is stored. */
105
+ readonly values: Record<string, StoredValue>;
106
+ /** The stored values exactly as persisted, for an export that bakes a snapshot in. Empty when nothing is stored. */
107
+ readonly persistedValues: Record<string, StoredValue>;
108
+ /** The last run's recorded outcome, absent when nothing is stored. */
109
+ readonly trace?: RunTrace;
110
+ }
111
+ /** The render options a single-note export and a linked-set export share. */
112
+ export interface ExportRenderOptions {
57
113
  /**
58
114
  * Installed pack components the static HTML engine cannot draw. A
59
115
  * directive naming one is labeled "no HTML view" instead of "unknown
@@ -63,7 +119,7 @@ export interface ExportRequest {
63
119
  readonly unavailableComponents?: readonly UnavailableComponent[];
64
120
  /** Receives the static engine's render diagnostics, such as the `no-engine-view` event. */
65
121
  readonly onDiagnostic?: OnDiagnostic;
66
- /** The host's own render of the body (a React pass bound to its loaded packs). Omitted means the static engine renders, and `staticReason` says why. Used by the `html` and `pdf` formats. */
122
+ /** The host's own render of the body (a React pass bound to its loaded packs). Omitted means the static engine renders, and `staticReason` says why. */
67
123
  readonly renderBody?: ExportBodyRenderer;
68
124
  /** Why the static engine renders when `renderBody` is omitted. Defaults to `no-packs`. */
69
125
  readonly staticReason?: StaticExportReason;
@@ -71,11 +127,21 @@ export interface ExportRequest {
71
127
  readonly packStylesheets?: readonly ExportPackStylesheet[];
72
128
  /** How many loaded packs contributed to the render. Diagnostics only. */
73
129
  readonly packCount?: number;
74
- /** Reads one of the note's local images so the export embeds it as a `data:` URI. Omitted leaves every image source as written. */
75
- readonly embedImages?: ExportImageReader;
76
130
  /** Hides the collapsed script marker in the exported file. Defaults to `false`. */
77
131
  readonly hideScriptBlocks?: boolean;
78
132
  }
133
+ export interface ExportRequest extends ExportRenderOptions {
134
+ readonly format: HostExportFormat;
135
+ /** The note's own path, used to name the exported file. */
136
+ readonly notePath: string;
137
+ readonly text: string;
138
+ /** The note's last-run values, baked into an html/pdf export. Omitted or empty exports the note's standard empty states. */
139
+ readonly values?: Record<string, StoredValue>;
140
+ /** Reads one of the note's local images so the export embeds it as a `data:` URI. Omitted leaves every image source as written. */
141
+ readonly embedImages?: ExportImageReader;
142
+ /** Where to write the file. When present the adapter's `resolveTarget` is not asked. */
143
+ readonly targetPath?: string;
144
+ }
79
145
  export type ExportOutcome = {
80
146
  readonly kind: 'exported';
81
147
  readonly path: string;
@@ -92,44 +158,41 @@ export type ExportOutcome = {
92
158
  readonly kind: 'failed';
93
159
  readonly reason: string;
94
160
  }
95
- /** `adapter.exports.resolveTarget`/`htmlToPdf`/an injected `renderAnsi` was unavailable at the moment of export — a picker cancel, or a seam this host declared but did not wire up. */
161
+ /** The picker was cancelled, or a seam this host declared (`htmlToPdf`, an injected `renderAnsi`) was not wired up at the moment of export. Nothing was written. */
96
162
  | {
97
- readonly kind: 'cancelled';
163
+ readonly kind: 'declined';
98
164
  } | Unsupported;
99
- export interface ExportLinkedSetRequest {
165
+ export interface ExportLinkedSetRequest extends ExportRenderOptions {
100
166
  /** The root note's path, in whatever form `adapter.readFile` and `resolveLink` understand. */
101
167
  readonly rootPath: string;
102
168
  /** Resolves one link in a note to the path of a note this host can export, or `undefined` to leave the link as written. */
103
169
  readonly resolveLink: CascadeLinkResolver;
104
170
  /** Reads one note's persisted last-run values, keyed by that note's own path. An empty object exports that note's standard empty states. */
105
171
  readonly readValues: (notePath: string) => Record<string, StoredValue>;
106
- /** The host's own render of each note's body. Omitted renders every note with the static engine, and `staticReason` says why. */
107
- readonly renderBody?: ExportBodyRenderer;
108
- /** Why the static engine renders when `renderBody` is omitted. Defaults to `no-packs`. */
109
- readonly staticReason?: StaticExportReason;
110
- /** The loaded packs' stylesheets, embedded only when `renderBody` ran. */
111
- readonly packStylesheets?: readonly ExportPackStylesheet[];
112
- /** How many loaded packs contributed to the render. Diagnostics only. */
113
- readonly packCount?: number;
114
- /** Installed pack components the static engine cannot draw. */
115
- readonly unavailableComponents?: readonly UnavailableComponent[];
116
- /** Receives the static engine's render diagnostics for every note. */
117
- readonly onDiagnostic?: OnDiagnostic;
118
172
  /** Builds the image reader for one note, bound to that note's own folder. Omitted embeds no images. */
119
173
  readonly embedImagesFor?: (notePath: string) => ExportImageReader;
120
- /** Hides the collapsed script marker in every exported note. Defaults to `false`. */
121
- readonly hideScriptBlocks?: boolean;
174
+ /** Where to write the archive. When present the adapter's `resolveLinkedSetTarget` is not asked. */
175
+ readonly targetPath?: string;
122
176
  }
123
- export type ExportLinkedSetOutcome = Extract<CascadeExportOutcome, {
124
- kind: 'exported';
125
- }> | {
177
+ export type ExportLinkedSetOutcome = {
178
+ readonly kind: 'exported';
179
+ /** The written archive's display path. */
180
+ readonly path: string;
181
+ readonly bytes: number;
182
+ /** Every note the archive contains, breadth first, the root note first. */
183
+ readonly notes: readonly CascadeExportedNote[];
184
+ /** Notes a link pointed at that could not be read. */
185
+ readonly unreadable: readonly UnreadableCascadeNote[];
186
+ /** Set when a bound stopped the walk before it ran out of links to follow. */
187
+ readonly truncated?: CascadeTruncation;
188
+ } | {
126
189
  readonly kind: 'failed';
127
190
  readonly path?: string;
128
191
  readonly reason: string;
129
192
  }
130
193
  /** The host's picker was cancelled, so nothing was written. */
131
194
  | {
132
- readonly kind: 'cancelled';
195
+ readonly kind: 'declined';
133
196
  } | Unsupported;
134
197
  export interface InstallPackRequest {
135
198
  readonly archiveBytes: Uint8Array;
@@ -149,8 +212,15 @@ export type InstallPackOutcome = {
149
212
  } | {
150
213
  readonly kind: 'reserved';
151
214
  readonly namespace: string;
152
- } | {
153
- readonly kind: 'rejected';
215
+ }
216
+ /** The archive was read and judged bad: it is not a valid pack archive. Nothing was written. */
217
+ | {
218
+ readonly kind: 'invalid';
219
+ readonly reason: string;
220
+ }
221
+ /** A prompt, a check or a write failed. */
222
+ | {
223
+ readonly kind: 'failed';
154
224
  readonly reason: string;
155
225
  } | Unsupported;
156
226
  export type LoadPacksOutcome = {
@@ -164,6 +234,11 @@ export type LoadPacksOutcome = {
164
234
  readonly components: readonly UnavailableComponent[];
165
235
  /** The installed components with no view for this host's engine, for a renderer's `unavailableComponents` option. */
166
236
  readonly unavailable: readonly UnavailableComponent[];
237
+ }
238
+ /** An adapter primitive rejected while the packs were read. The diagnostics line is already written. */
239
+ | {
240
+ readonly kind: 'failed';
241
+ readonly reason: string;
167
242
  } | Unsupported;
168
243
  export type LoadTerminalPacksOutcome = {
169
244
  readonly kind: 'loaded';
@@ -184,13 +259,76 @@ export type LoadTerminalPacksOutcome = {
184
259
  * shows these.
185
260
  */
186
261
  readonly failureLines: readonly string[];
262
+ }
263
+ /** An adapter primitive rejected while the packs were read. The diagnostics line is already written. */
264
+ | {
265
+ readonly kind: 'failed';
266
+ readonly reason: string;
267
+ } | Unsupported;
268
+ export type RemovePackOutcome = {
269
+ readonly kind: 'removed';
270
+ readonly namespace: string;
271
+ } | {
272
+ readonly kind: 'not-installed';
273
+ readonly namespace: string;
274
+ } | {
275
+ readonly kind: 'reserved';
276
+ readonly namespace: string;
277
+ }
278
+ /** The namespace is not a valid pack name. */
279
+ | {
280
+ readonly kind: 'invalid';
281
+ readonly reason: string;
282
+ } | {
283
+ readonly kind: 'failed';
284
+ readonly reason: string;
187
285
  } | Unsupported;
188
- export type RemovePackResult = RemovePackOutcome | Unsupported;
189
286
  export type InstalledPacksOutcome = ({
190
287
  readonly kind: 'listed';
191
- } & InstalledPacksListing) | Unsupported;
192
- export type EnablePackResult = EnablePackOutcome | Unsupported;
193
- export type DisablePackResult = DisablePackOutcome | Unsupported;
288
+ } & InstalledPacksListing)
289
+ /** An adapter primitive rejected while the install root was read. The diagnostics line is already written. */
290
+ | {
291
+ readonly kind: 'failed';
292
+ readonly reason: string;
293
+ } | Unsupported;
294
+ export type EnablePackOutcome = {
295
+ readonly kind: 'enabled';
296
+ readonly namespace: string;
297
+ }
298
+ /** The user refused the consent prompt. */
299
+ | {
300
+ readonly kind: 'declined';
301
+ readonly namespace: string;
302
+ } | {
303
+ readonly kind: 'not-installed';
304
+ readonly namespace: string;
305
+ } | {
306
+ readonly kind: 'reserved';
307
+ readonly namespace: string;
308
+ }
309
+ /** The namespace is not a valid pack name. */
310
+ | {
311
+ readonly kind: 'invalid';
312
+ readonly reason: string;
313
+ } | {
314
+ readonly kind: 'failed';
315
+ readonly reason: string;
316
+ } | Unsupported;
317
+ export type DisablePackOutcome = {
318
+ readonly kind: 'disabled';
319
+ readonly namespace: string;
320
+ } | {
321
+ readonly kind: 'not-enabled';
322
+ readonly namespace: string;
323
+ }
324
+ /** The namespace is not a valid pack name. */
325
+ | {
326
+ readonly kind: 'invalid';
327
+ readonly reason: string;
328
+ } | {
329
+ readonly kind: 'failed';
330
+ readonly reason: string;
331
+ } | Unsupported;
194
332
  export interface EditorPositionRequest {
195
333
  readonly line: number;
196
334
  readonly column: number;
@@ -218,6 +356,11 @@ export type CompleteOutcome = {
218
356
  /** Nothing to offer here: no directive context, or a bare colon run closing an open container. Not a failure. */
219
357
  | {
220
358
  readonly kind: 'none';
359
+ }
360
+ /** The editor or the catalog threw. The diagnostics line is already written. */
361
+ | {
362
+ readonly kind: 'failed';
363
+ readonly reason: string;
221
364
  } | Unsupported;
222
365
  export type HoverOutcome = {
223
366
  readonly kind: 'hover';
@@ -229,6 +372,11 @@ export type HoverOutcome = {
229
372
  readonly end: number;
230
373
  } | {
231
374
  readonly kind: 'none';
375
+ }
376
+ /** The editor or the catalog threw. The diagnostics line is already written. */
377
+ | {
378
+ readonly kind: 'failed';
379
+ readonly reason: string;
232
380
  } | Unsupported;
233
381
  export interface InsertComponentRequest {
234
382
  readonly name: string;
@@ -248,12 +396,24 @@ export type InsertOutcome = {
248
396
  } | {
249
397
  readonly kind: 'not-found';
250
398
  readonly name: string;
251
- } | {
399
+ }
400
+ /** The edit was not applied, or the editor or the catalog threw. The diagnostics line is already written. */
401
+ | {
252
402
  readonly kind: 'failed';
403
+ readonly reason: string;
253
404
  } | Unsupported;
254
405
  export interface MarkiiHost {
255
406
  open(request: OpenRequest): Promise<OpenOutcome>;
256
407
  run(request: RunRequest): Promise<RunOutcome>;
408
+ /**
409
+ * What the last run of `documentKey` left in the adapter's memento: the
410
+ * values as they should be shown on open, the values as stored, and the
411
+ * recorded trace. Empty when nothing is stored. Synchronous, because the
412
+ * memento read is.
413
+ */
414
+ lastRun(documentKey: string): LastRunOutcome;
415
+ /** Clears the stored script grants of `documentKey`, so its next manual run prompts again for every host. Nothing stored is not an error. */
416
+ forgetGrants(documentKey: string): Promise<void>;
257
417
  exportNote(request: ExportRequest): Promise<ExportOutcome>;
258
418
  /** Exports a note and the notes it links to as one zip archive of HTML files. */
259
419
  exportLinkedSet(request: ExportLinkedSetRequest): Promise<ExportLinkedSetOutcome>;
@@ -266,7 +426,7 @@ export interface MarkiiHost {
266
426
  */
267
427
  loadTerminalPacks(): Promise<LoadTerminalPacksOutcome>;
268
428
  /** Removes one installed pack by namespace, through the install root. Writes its outcome to the diagnostics surface. Under `trust: 'device-list'` it also withdraws the namespace's trust entry. */
269
- removePack(namespace: string): Promise<RemovePackResult>;
429
+ removePack(namespace: string): Promise<RemovePackOutcome>;
270
430
  /**
271
431
  * Under `trust: 'device-list'`: the install root's folders split into the
272
432
  * ones this device has enabled and the ones merely present. Unsupported
@@ -274,9 +434,9 @@ export interface MarkiiHost {
274
434
  */
275
435
  installedPacks(): Promise<InstalledPacksOutcome>;
276
436
  /** Asks the install consent prompt, then trusts an installed folder on this device. Unsupported without the trust list. */
277
- enablePack(namespace: string): Promise<EnablePackResult>;
437
+ enablePack(namespace: string): Promise<EnablePackOutcome>;
278
438
  /** Withdraws a namespace's trust entry and leaves its folder in place. Unsupported without the trust list. */
279
- disablePack(namespace: string): Promise<DisablePackResult>;
439
+ disablePack(namespace: string): Promise<DisablePackOutcome>;
280
440
  completeAt(request: EditorPositionRequest): Promise<CompleteOutcome>;
281
441
  /**
282
442
  * `completeAt` for a caller that must answer synchronously (Obsidian's
@@ -292,17 +452,26 @@ export interface MarkiiHost {
292
452
  diagnostics(line: string): void;
293
453
  }
294
454
  /**
295
- * Injectables a test needs to make a run/export deterministic. Defaults
296
- * are the real implementations; no option changes behavior for a real
297
- * host.
455
+ * What an outside host may pass to `createMarkiiHost`. Neither field
456
+ * changes what a behavior decides; each supplies an engine this package
457
+ * never imports itself.
298
458
  */
299
459
  export interface MarkiiHostOptions {
300
- readonly spawnRun?: (options: SpawnRunRequest) => Promise<RunResult>;
301
460
  /** The static HTML engine behind the `html` and `pdf` exports (`createHtmlExportEngine()` from `@markii/host/html-engine`). Without it those formats decline, like `renderAnsi` for `ansi`. */
302
461
  readonly htmlEngine?: HtmlExportEngine;
303
- /** Pack discovery's file reads. Defaults to reads through the adapter's own `readFile` and `listFolder`. */
304
- readonly packDiscoveryIo?: PackDiscoveryIo;
305
462
  /** `@markii/ansi`'s renderer, injected because this package never depends on `@markii/ansi` (a platform renderer, never a `@markii/host` dependency). A host declaring `'ansi'` in `adapter.exports.formats` without supplying this gets `Unsupported` at export time. */
306
463
  readonly renderAnsi?: (text: string) => Promise<string>;
307
464
  }
465
+ /**
466
+ * The test seams of `createMarkiiHostWithSeams`, which `@markii/host/internal`
467
+ * exports. They make a run or a pack discovery deterministic. Defaults are
468
+ * the real implementations.
469
+ */
470
+ export interface MarkiiHostSeams extends MarkiiHostOptions {
471
+ readonly spawnRun?: (options: SpawnRunRequest) => Promise<RunResult>;
472
+ /** Pack discovery's file reads. Defaults to reads through the adapter's own `readFile` and `listFolder`. */
473
+ readonly packDiscoveryIo?: PackDiscoveryIo;
474
+ }
308
475
  export declare function createMarkiiHost(adapter: HostAdapter, options?: MarkiiHostOptions): MarkiiHost;
476
+ /** `createMarkiiHost` with the test seams. Exported from `@markii/host/internal` only. */
477
+ export declare function createMarkiiHostWithSeams(adapter: HostAdapter, options?: MarkiiHostSeams): MarkiiHost;