@bendyline/docblocks 2.7.6 → 2.7.8

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.
@@ -14,7 +14,7 @@ This notice is included in the published npm tarball. Transitive packages instal
14
14
 
15
15
  | Package | Version | License | Source |
16
16
  | --- | --- | --- | --- |
17
- | @bendyline/squisq | 2.13.0 | MIT | https://github.com/bendyline/squisq |
17
+ | @bendyline/squisq | 2.13.6 | MIT | https://github.com/bendyline/squisq |
18
18
  | @bendyline/squisq-graph | 2.13.0 | MIT | https://github.com/bendyline/squisq |
19
19
  | @types/debug | 4.1.12 | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped |
20
20
  | @types/hast | 3.0.4 | MIT | https://github.com/DefinitelyTyped/DefinitelyTyped |
@@ -133,7 +133,7 @@ This notice is included in the published npm tarball. Transitive packages instal
133
133
  Package-local license, copying, and notice files are reproduced below. Where a published package omits its repository license, the reviewed aggregate or README identified in `Source files` supplies the retained material.
134
134
 
135
135
  ==============================================================================
136
- Components: @bendyline/squisq-graph@2.13.0, @bendyline/squisq@2.13.0
136
+ Components: @bendyline/squisq-graph@2.13.0, @bendyline/squisq@2.13.6
137
137
  Source files: node_modules/@bendyline/squisq-graph/LICENSE, node_modules/@bendyline/squisq/LICENSE
138
138
  ==============================================================================
139
139
  MIT License
@@ -189,7 +189,7 @@ repository license, the pinned upstream copy is vendored and identified below.
189
189
  COMPONENTS
190
190
 
191
191
  ==============================================================================
192
- Components: @bendyline/squisq@2.13.0
192
+ Components: @bendyline/squisq@2.13.6
193
193
  Source files: node_modules/@bendyline/squisq/NOTICE.md
194
194
  ==============================================================================
195
195
  # Third-Party Notices for @bendyline/squisq
@@ -220,7 +220,7 @@ third-party license texts for bundled code and data are shipped in
220
220
  THIRD_PARTY_LICENSES.txt.
221
221
 
222
222
  ==============================================================================
223
- Components: @bendyline/squisq@2.13.0
223
+ Components: @bendyline/squisq@2.13.6
224
224
  Source files: node_modules/@bendyline/squisq/THIRD_PARTY_LICENSES.txt
225
225
  ==============================================================================
226
226
  THIRD-PARTY LICENSES FOR @bendyline/squisq
@@ -1,6 +1,177 @@
1
1
  import { F as FileCommitResult, c as FileSystemEntry, b as FileMeta } from './types-DLteNrK0.js';
2
2
  import { D as DocBlocksHostFsV2API } from './filesystem-v2-CXdAPR27.js';
3
3
 
4
+ /**
5
+ * On-device image generation.
6
+ *
7
+ * Renders run on the provider's local image engine. They take seconds on a
8
+ * fast graphics card and minutes for the largest models, so a request streams
9
+ * phased progress and can be cancelled; cancelling stops the engine, and the
10
+ * next render reloads its weights. Image models are listed apart from chat
11
+ * models and never appear in a chat model picker.
12
+ */
13
+ /** Shapes a person can ask for. The provider picks pixels inside the model's range. */
14
+ declare const AI_IMAGE_ASPECTS: readonly ["1:1", "4:3", "3:4", "16:9", "9:16"];
15
+ type AiImageAspect = (typeof AI_IMAGE_ASPECTS)[number];
16
+ type AiImageUnavailableReason =
17
+ /** AI is off, or the provider is not connected. */
18
+ 'not-connected'
19
+ /** The provider has no image engine that can run on this computer. */
20
+ | 'no-engine'
21
+ /** The graphics driver lacks what the engine needs (Vulkan on Windows). */
22
+ | 'graphics-driver'
23
+ /** This build of the app cannot run image generation. */
24
+ | 'platform';
25
+ /**
26
+ * Whether image generation can be offered now.
27
+ *
28
+ * `needs-approval` means the provider serves images but this app has not been
29
+ * allowed to use them; ask with `requestAccess()` from an explicit gesture.
30
+ * While that request waits, the state is `awaiting-approval` with the code the
31
+ * person types into the provider. Chat keeps working throughout.
32
+ */
33
+ type AiImageAccess = {
34
+ readonly kind: 'ready';
35
+ } | {
36
+ readonly kind: 'needs-approval';
37
+ } | {
38
+ readonly kind: 'awaiting-approval';
39
+ readonly verificationCode: string | null;
40
+ } | {
41
+ readonly kind: 'provider-outdated';
42
+ } | {
43
+ readonly kind: 'unavailable';
44
+ readonly reason: AiImageUnavailableReason;
45
+ readonly message: string;
46
+ };
47
+ declare const AI_IMAGE_FIT_VERDICTS: readonly ["fits", "tight", "over-limit", "may-not-run", "wont-run"];
48
+ interface AiImageModelFit {
49
+ /** `wont-run` models refuse to install on this computer. */
50
+ readonly verdict: (typeof AI_IMAGE_FIT_VERDICTS)[number];
51
+ /** One sentence a person can act on; empty for a plain fit. */
52
+ readonly reason: string;
53
+ }
54
+ interface AiImageModel {
55
+ /** Opaque to the renderer. */
56
+ readonly id: string;
57
+ readonly label: string;
58
+ readonly description: string | null;
59
+ readonly state: 'installed' | 'download-required' | 'downloading';
60
+ readonly downloadBytes: number | null;
61
+ /** Installed in a store the provider reads but this app does not own; not removable here. */
62
+ readonly shared: boolean;
63
+ readonly license: string | null;
64
+ /** False when the license forbids commercial use; null when the provider does not say. */
65
+ readonly commercialUse: boolean | null;
66
+ /** Draws legible text, which design graphics depend on. */
67
+ readonly rendersText: boolean;
68
+ /** How the model reads prompts. */
69
+ readonly promptStyle: 'sentences' | 'tags' | null;
70
+ /** `workstation` marks a model for a machine with a great deal of memory. */
71
+ readonly hardwareTier: 'low' | 'mid' | 'high' | 'workstation' | null;
72
+ readonly minRamGb: number | null;
73
+ readonly fit: AiImageModelFit | null;
74
+ }
75
+ interface AiImagePreferences {
76
+ /** The model "Generate image" uses; null lets the provider choose an installed one. */
77
+ readonly model: string | null;
78
+ /** The model Illustrate's design graphics use; null offers none. */
79
+ readonly designModel: string | null;
80
+ readonly aspect: AiImageAspect;
81
+ }
82
+ type AiImagePreferencesPatch = Partial<AiImagePreferences>;
83
+ interface AiImageRequest {
84
+ readonly prompt: string;
85
+ readonly negativePrompt?: string;
86
+ /** An id from `models()`; the preferred model when absent. */
87
+ readonly model?: string;
88
+ readonly aspect?: AiImageAspect;
89
+ readonly seed?: number;
90
+ }
91
+ interface AiImageResult {
92
+ readonly mimeType: 'image/png';
93
+ readonly data: ArrayBuffer;
94
+ readonly width: number;
95
+ readonly height: number;
96
+ readonly seed: number;
97
+ readonly model: string;
98
+ readonly durationMs: number;
99
+ }
100
+ /**
101
+ * `loading-model` covers the first render after the engine starts, which
102
+ * loads the weights; `decoding` turns the result into pixels in tiles.
103
+ */
104
+ type AiImagePhase = 'queued' | 'loading-model' | 'sampling' | 'decoding';
105
+ interface AiImageProgress {
106
+ readonly phase: AiImagePhase;
107
+ /** Units done in this phase; 0 while queued or when the engine reports none. */
108
+ readonly step: number;
109
+ readonly totalSteps: number;
110
+ readonly secondsPerStep: number | null;
111
+ }
112
+ type AiImageEvent = {
113
+ readonly kind: 'progress';
114
+ readonly progress: AiImageProgress;
115
+ } | {
116
+ readonly kind: 'done';
117
+ readonly image: AiImageResult;
118
+ } | {
119
+ readonly kind: 'error';
120
+ readonly error: AiError;
121
+ };
122
+ interface AiImageHandle {
123
+ readonly done: Promise<AiResult<AiImageResult>>;
124
+ /** Stop the render. The engine stops, so the next render reloads its weights. */
125
+ cancel(): void;
126
+ }
127
+ type AiImageInstallEvent = {
128
+ readonly kind: 'progress';
129
+ readonly progress: AiProgress;
130
+ } | {
131
+ readonly kind: 'done';
132
+ readonly model: AiImageModel;
133
+ } | {
134
+ readonly kind: 'error';
135
+ readonly error: AiError;
136
+ };
137
+ interface AiImageInstallHandle {
138
+ readonly done: Promise<AiResult<AiImageModel>>;
139
+ /** Stop the download. Starting it again resumes. */
140
+ cancel(): void;
141
+ }
142
+ interface AiImagesAPI {
143
+ access(): Promise<AiImageAccess>;
144
+ onAccess(listener: (access: AiImageAccess) => void): () => void;
145
+ /** Ask the provider to allow image generation. Only from an explicit gesture. */
146
+ requestAccess(): Promise<AiResult<AiImageAccess>>;
147
+ models(): Promise<AiResult<readonly AiImageModel[]>>;
148
+ /** Start a model download from an explicit gesture. */
149
+ installModel(id: string, onProgress?: (progress: AiProgress) => void): AiImageInstallHandle;
150
+ removeModel(id: string): Promise<AiResult<null>>;
151
+ getPreferences(): Promise<AiImagePreferences>;
152
+ setPreferences(patch: AiImagePreferencesPatch): Promise<AiImagePreferences>;
153
+ generate(request: AiImageRequest, onEvent: (event: AiImageEvent) => void): AiImageHandle;
154
+ }
155
+ declare const AI_IMAGE_WIRE_LIMITS: Readonly<{
156
+ promptCharacters: 4000;
157
+ /** A PNG at the largest size a model renders. */
158
+ imageBytes: number;
159
+ models: 256;
160
+ pixels: 16384;
161
+ verificationCodeCharacters: 16;
162
+ }>;
163
+ declare function isAiImageModelId(value: unknown): value is string;
164
+ declare function isAiImageAspect(value: unknown): value is AiImageAspect;
165
+ declare function parseAiImageAccess(value: unknown): AiImageAccess | null;
166
+ declare function parseAiImageModel(value: unknown): AiImageModel | null;
167
+ declare function parseAiImageModelList(value: unknown): AiImageModel[] | null;
168
+ declare function parseAiImagePreferences(value: unknown): AiImagePreferences | null;
169
+ declare function parseAiImagePreferencesPatch(value: unknown): AiImagePreferencesPatch | null;
170
+ declare function parseAiImageRequest(value: unknown): AiImageRequest | null;
171
+ declare function parseAiImageResult(value: unknown): AiImageResult | null;
172
+ declare function parseAiImageEvent(value: unknown): AiImageEvent | null;
173
+ declare function parseAiImageInstallEvent(value: unknown): AiImageInstallEvent | null;
174
+
4
175
  /** Provider-neutral catalog management. IDs never authorize filesystem access. */
5
176
  interface AiKnowledgeCatalog {
6
177
  readonly id: string;
@@ -216,6 +387,17 @@ interface AiChatRequest {
216
387
  readonly maxTokens?: number;
217
388
  readonly purpose: AiChatPurpose;
218
389
  readonly responseFormat?: AiResponseFormat;
390
+ /**
391
+ * What to search knowledge catalogs for. Without it a provider searches with
392
+ * the last user message, which for a templated prompt is mostly document.
393
+ */
394
+ readonly knowledgeQuery?: string;
395
+ /**
396
+ * Number knowledge passages and ask the model to cite them as `[n]`. Only a
397
+ * caller that checks and renders citations should: the markers otherwise
398
+ * end up in its output.
399
+ */
400
+ readonly knowledgeCitations?: boolean;
219
401
  }
220
402
  interface AiChatCompletion {
221
403
  readonly text: string;
@@ -235,6 +417,12 @@ interface AiChatProgress {
235
417
  readonly outputTokens: number | null;
236
418
  readonly tokensPerSecond: number | null;
237
419
  }
420
+ /** One reference passage the model was given; its citation number is its position from 1. */
421
+ interface AiChatEvidence {
422
+ readonly title: string;
423
+ readonly catalogId: string;
424
+ readonly text: string;
425
+ }
238
426
  /** One knowledge catalog that contributed reference passages to a request. */
239
427
  interface AiChatKnowledgeSource {
240
428
  readonly catalogId: string;
@@ -251,8 +439,11 @@ interface AiChatKnowledgeSource {
251
439
  type AiChatKnowledge = {
252
440
  readonly outcome: 'used';
253
441
  readonly sources: readonly AiChatKnowledgeSource[];
254
- /** The passage texts the model was given, so its output can be checked against them. */
255
- readonly evidence: readonly string[];
442
+ /**
443
+ * The passages the model was given, in citation order: it was asked to
444
+ * cite `evidence[0]` as `[1]`. Its output can be checked against them.
445
+ */
446
+ readonly evidence: readonly AiChatEvidence[];
256
447
  }
257
448
  /** The catalogs were searched and nothing relevant came back. */
258
449
  | {
@@ -282,14 +473,22 @@ type AiChatEvent = {
282
473
  interface AiFactCheckRequest {
283
474
  /** The output, as Markdown. */
284
475
  readonly text: string;
285
- /** Reference passages the model was given. */
476
+ /** Reference passage texts the model was given, `[1]` first. */
286
477
  readonly evidence: readonly string[];
478
+ /**
479
+ * The model was asked to cite passages by number, and its numbers match
480
+ * `evidence`: check each sentence against what it cites. Otherwise each
481
+ * sentence is checked against all of the evidence and markers are ignored.
482
+ */
483
+ readonly citations: boolean;
287
484
  /** What the person supplied: their instructions and document. Details found here need no source. */
288
485
  readonly given: string;
289
486
  }
290
487
  interface AiFactCheckSentence {
291
- /** The sentence, possibly shortened. */
488
+ /** The sentence without citation markers, possibly shortened. */
292
489
  readonly text: string;
490
+ /** `bad-citation`: it cites a passage number the model was never given. */
491
+ readonly problem: 'unsourced' | 'bad-citation';
293
492
  /** The names, dates, numbers or quotations no source shows. */
294
493
  readonly missing: readonly string[];
295
494
  /**
@@ -350,17 +549,6 @@ interface AiSearchResult {
350
549
  readonly hits: readonly AiSearchHit[];
351
550
  readonly truncated: boolean;
352
551
  }
353
- interface AiImageRequest {
354
- readonly prompt: string;
355
- readonly width?: number;
356
- readonly height?: number;
357
- }
358
- interface AiImageResult {
359
- readonly mimeType: 'image/png';
360
- readonly data: ArrayBuffer;
361
- readonly width: number;
362
- readonly height: number;
363
- }
364
552
  interface AiTranscribeRequest {
365
553
  readonly audio: ArrayBuffer;
366
554
  readonly mimeType: string;
@@ -393,6 +581,8 @@ interface AiSpeechAudio {
393
581
  interface DocBlocksHostAiAPI {
394
582
  /** Optional catalog browsing, downloads, and retrieval model setup. */
395
583
  readonly knowledge?: AiKnowledgeAPI;
584
+ /** Optional on-device image generation and its models. */
585
+ readonly images?: AiImagesAPI;
396
586
  /** Whether the host's user-installed companion provider is present. */
397
587
  providerInstalled(): Promise<boolean>;
398
588
  status(): Promise<AiStatus>;
@@ -424,7 +614,6 @@ interface DocBlocksHostAiAPI {
424
614
  chat(request: AiChatRequest, onEvent: (event: AiChatEvent) => void): AiChatHandle;
425
615
  ensureWorkspace?(workspaceId: string, onProgress?: (progress: AiProgress) => void): AiEnsureWorkspaceHandle;
426
616
  search?(workspaceId: string, query: AiSearchQuery): Promise<AiResult<AiSearchResult>>;
427
- generateImage?(request: AiImageRequest): Promise<AiResult<AiImageResult>>;
428
617
  /** @deprecated Speech lives on `DocBlocksHostAPI.speech`; no host implements this. */
429
618
  transcribe?(request: AiTranscribeRequest): Promise<AiResult<AiTranscript>>;
430
619
  /** @deprecated Speech lives on `DocBlocksHostAPI.speech`; no host implements this. */
@@ -785,12 +974,25 @@ interface SpeechTranscribeRequest {
785
974
  */
786
975
  readonly prompt?: string;
787
976
  readonly language?: string;
977
+ /**
978
+ * Return timed `segments` with word times (Whisper's verbose output), for
979
+ * timing a narration from its audio. Dictation leaves it off.
980
+ */
981
+ readonly timestamps?: boolean;
982
+ }
983
+ /** A recognized word. Seconds from the start of the take. */
984
+ interface SpeechWord {
985
+ readonly start: number;
986
+ readonly end: number;
987
+ readonly text: string;
788
988
  }
789
989
  interface SpeechSegment {
790
990
  /** Seconds from the start of the take. */
791
991
  readonly start: number;
792
992
  readonly end: number;
793
993
  readonly text: string;
994
+ /** Present when the request asked for `timestamps`. */
995
+ readonly words?: readonly SpeechWord[];
794
996
  }
795
997
  interface SpeechTranscript {
796
998
  /** Trimmed; empty when the take held no speech. */
@@ -1123,6 +1325,14 @@ interface DocBlocksHostExternalAPI {
1123
1325
  writeBinary(resourceId: string, data: ArrayBuffer | Uint8Array): Promise<void>;
1124
1326
  commitText(resourceId: string, content: string, expectedContent: string | null): Promise<FileCommitResult>;
1125
1327
  commitBinary(resourceId: string, data: ArrayBuffer | Uint8Array, expectedVersion: string | null): Promise<ExternalBinaryCommitResult>;
1328
+ /**
1329
+ * Read, never write, a media file inside the folder of a loose markdown
1330
+ * grant, so the document's relative image paths render. `relativePath` is a
1331
+ * canonical `WorkspacePath` from that folder naming an image, audio, or video
1332
+ * file; it cannot climb out or follow a symbolic link. Resolves null when
1333
+ * the file does not exist. Bundle grants carry their media and refuse this.
1334
+ */
1335
+ readRelativeMedia?(resourceId: string, relativePath: string): Promise<ArrayBuffer | null>;
1126
1336
  /** Revoke one external resource when its transient document is closed. */
1127
1337
  revoke(resourceId: string): Promise<void>;
1128
1338
  }
@@ -1277,6 +1487,8 @@ interface HostCapabilities {
1277
1487
  readonly exportRememberedTargets: boolean;
1278
1488
  readonly openSavedExports: boolean;
1279
1489
  readonly externalResources: boolean;
1490
+ /** A loose OS-opened file's relative images can be read from beside it. */
1491
+ readonly externalRelativeMedia: boolean;
1280
1492
  readonly openRequests: boolean;
1281
1493
  readonly menuCommands: boolean;
1282
1494
  readonly pinnedDocumentMirror: boolean;
@@ -1340,4 +1552,4 @@ declare function parseHostEnvironment(value: unknown): HostEnvironment | null;
1340
1552
  */
1341
1553
  declare function deriveHostCapabilities(host: unknown): HostCapabilities;
1342
1554
 
1343
- export { type DocBlocksHostShellAPI as $, type AiChatCompletion as A, type AiPreferences as B, type AiPreferencesPatch as C, type AiProgress as D, type AiProviderInfo as E, type AiResponseFormat as F, type AiResult as G, type AiReviewMode as H, type AiSearchHit as I, type AiSearchQuery as J, type AiSearchResult as K, type AiSpeechAudio as L, type AiStatus as M, type AiSynthesizeRequest as N, type AiTranscribeRequest as O, type AiTranscript as P, type AiUnavailableReason as Q, type DocBlocksHostAPI as R, type DocBlocksHostAiAPI as S, type DocBlocksHostClipboardAPI as T, type DocBlocksHostExportAPI as U, type DocBlocksHostExternalAPI as V, type DocBlocksHostFfmpegAPI as W, type DocBlocksHostFsAPI as X, type DocBlocksHostGitAPI as Y, type DocBlocksHostLifecycleAPI as Z, type DocBlocksHostMenuAPI as _, type AiChatEvent as a, parseAiKnowledgeAction as a$, type DocBlocksHostSpeechAPI as a0, type DocBlocksHostUpdaterAPI as a1, type DocBlocksHostWorkspacesAPI as a2, type ElectronWorkspaceInfo as a3, type ExternalBinaryCommitResult as a4, type GitBranchInfo as a5, type GitCapabilities as a6, type GitCloneHandle as a7, type GitCloneProgress as a8, type GitError as a9, type SpeechCatalog as aA, type SpeechError as aB, type SpeechErrorCode as aC, type SpeechInstallEvent as aD, type SpeechInstallHandle as aE, type SpeechModelInfo as aF, type SpeechModelKind as aG, type SpeechPreferences as aH, type SpeechPreferencesPatch as aI, type SpeechProgress as aJ, type SpeechReadiness as aK, type SpeechReadinessState as aL, type SpeechResult as aM, type SpeechSegment as aN, type SpeechStatus as aO, type SpeechSynthesisHandle as aP, type SpeechSynthesisSummary as aQ, type SpeechSynthesizeEvent as aR, type SpeechSynthesizeRequest as aS, type SpeechTranscribeRequest as aT, type SpeechTranscript as aU, type SpeechVoiceInfo as aV, type SpeechWordTiming as aW, type UpdateCheckResult as aX, type UpdateInstallResult as aY, type UpdaterStatus as aZ, deriveHostCapabilities as a_, type GitErrorCode as aa, type GitFileAtRevision as ab, type GitFileChange as ac, type GitFileStatusCode as ad, type GitLogEntry as ae, type GitLogOptions as af, type GitRemoteInfo as ag, type GitRepoDetection as ah, type GitResult as ai, type GitRevision as aj, type GitStatus as ak, HOST_PLATFORMS as al, HOST_SURFACE_KINDS as am, type HostCapabilities as an, type HostCloseReason as ao, type HostEnvironment as ap, type HostExportTargetGrant as aq, type HostPinnedDocument as ar, type HostPlatform as as, type HostPrepareCloseRequest as at, type HostPrepareCloseResult as au, type HostSurfaceKind as av, type MenuCommand as aw, NO_HOST_CAPABILITIES as ax, type OpenRequest as ay, type SpeechAudioChunk as az, type AiChatHandle as b, parseAiKnowledgeState as b0, parseHostEnvironment as b1, type AiChatKnowledge as c, type AiChatKnowledgeSource as d, type AiChatMessage as e, type AiChatProgress as f, type AiChatPurpose as g, type AiChatRequest as h, type AiConnectionStep as i, type AiEnsureWorkspaceHandle as j, type AiError as k, type AiErrorCode as l, type AiFactCheck as m, type AiFactCheckRequest as n, type AiFactCheckSentence as o, type AiImageRequest as p, type AiImageResult as q, type AiKnowledgeAPI as r, type AiKnowledgeAction as s, type AiKnowledgeCatalog as t, type AiKnowledgeState as u, type AiModelDownloadInfo as v, type AiModelFit as w, type AiModelInfo as x, type AiModelInstallEvent as y, type AiModelInstallHandle as z };
1555
+ export { type AiSearchQuery as $, AI_IMAGE_ASPECTS as A, type AiImageModelFit as B, type AiImagePhase as C, type AiImagePreferences as D, type AiImagePreferencesPatch as E, type AiImageProgress as F, type AiImageRequest as G, type AiImageResult as H, type AiImageUnavailableReason as I, type AiImagesAPI as J, type AiKnowledgeAPI as K, type AiKnowledgeAction as L, type AiKnowledgeCatalog as M, type AiKnowledgeState as N, type AiModelDownloadInfo as O, type AiModelFit as P, type AiModelInfo as Q, type AiModelInstallEvent as R, type AiModelInstallHandle as S, type AiPreferences as T, type AiPreferencesPatch as U, type AiProgress as V, type AiProviderInfo as W, type AiResponseFormat as X, type AiResult as Y, type AiReviewMode as Z, type AiSearchHit as _, AI_IMAGE_FIT_VERDICTS as a, type SpeechProgress as a$, type AiSearchResult as a0, type AiSpeechAudio as a1, type AiStatus as a2, type AiSynthesizeRequest as a3, type AiTranscribeRequest as a4, type AiTranscript as a5, type AiUnavailableReason as a6, type DocBlocksHostAPI as a7, type DocBlocksHostAiAPI as a8, type DocBlocksHostClipboardAPI as a9, type GitResult as aA, type GitRevision as aB, type GitStatus as aC, HOST_PLATFORMS as aD, HOST_SURFACE_KINDS as aE, type HostCapabilities as aF, type HostCloseReason as aG, type HostEnvironment as aH, type HostExportTargetGrant as aI, type HostPinnedDocument as aJ, type HostPlatform as aK, type HostPrepareCloseRequest as aL, type HostPrepareCloseResult as aM, type HostSurfaceKind as aN, type MenuCommand as aO, NO_HOST_CAPABILITIES as aP, type OpenRequest as aQ, type SpeechAudioChunk as aR, type SpeechCatalog as aS, type SpeechError as aT, type SpeechErrorCode as aU, type SpeechInstallEvent as aV, type SpeechInstallHandle as aW, type SpeechModelInfo as aX, type SpeechModelKind as aY, type SpeechPreferences as aZ, type SpeechPreferencesPatch as a_, type DocBlocksHostExportAPI as aa, type DocBlocksHostExternalAPI as ab, type DocBlocksHostFfmpegAPI as ac, type DocBlocksHostFsAPI as ad, type DocBlocksHostGitAPI as ae, type DocBlocksHostLifecycleAPI as af, type DocBlocksHostMenuAPI as ag, type DocBlocksHostShellAPI as ah, type DocBlocksHostSpeechAPI as ai, type DocBlocksHostUpdaterAPI as aj, type DocBlocksHostWorkspacesAPI as ak, type ElectronWorkspaceInfo as al, type ExternalBinaryCommitResult as am, type GitBranchInfo as an, type GitCapabilities as ao, type GitCloneHandle as ap, type GitCloneProgress as aq, type GitError as ar, type GitErrorCode as as, type GitFileAtRevision as at, type GitFileChange as au, type GitFileStatusCode as av, type GitLogEntry as aw, type GitLogOptions as ax, type GitRemoteInfo as ay, type GitRepoDetection as az, AI_IMAGE_WIRE_LIMITS as b, type SpeechReadiness as b0, type SpeechReadinessState as b1, type SpeechResult as b2, type SpeechSegment as b3, type SpeechStatus as b4, type SpeechSynthesisHandle as b5, type SpeechSynthesisSummary as b6, type SpeechSynthesizeEvent as b7, type SpeechSynthesizeRequest as b8, type SpeechTranscribeRequest as b9, type SpeechTranscript as ba, type SpeechVoiceInfo as bb, type SpeechWord as bc, type SpeechWordTiming as bd, type UpdateCheckResult as be, type UpdateInstallResult as bf, type UpdaterStatus as bg, deriveHostCapabilities as bh, isAiImageAspect as bi, isAiImageModelId as bj, parseAiImageAccess as bk, parseAiImageEvent as bl, parseAiImageInstallEvent as bm, parseAiImageModel as bn, parseAiImageModelList as bo, parseAiImagePreferences as bp, parseAiImagePreferencesPatch as bq, parseAiImageRequest as br, parseAiImageResult as bs, parseAiKnowledgeAction as bt, parseAiKnowledgeState as bu, parseHostEnvironment as bv, type AiChatCompletion as c, type AiChatEvent as d, type AiChatEvidence as e, type AiChatHandle as f, type AiChatKnowledge as g, type AiChatKnowledgeSource as h, type AiChatMessage as i, type AiChatProgress as j, type AiChatPurpose as k, type AiChatRequest as l, type AiConnectionStep as m, type AiEnsureWorkspaceHandle as n, type AiError as o, type AiErrorCode as p, type AiFactCheck as q, type AiFactCheckRequest as r, type AiFactCheckSentence as s, type AiImageAccess as t, type AiImageAspect as u, type AiImageEvent as v, type AiImageHandle as w, type AiImageInstallEvent as x, type AiImageInstallHandle as y, type AiImageModel as z };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RawIndexedDBFileSystemStore,
3
3
  indexedDBWorkspaceDatabaseName
4
- } from "./chunk-DAPFSEKY.js";
4
+ } from "./chunk-OPLU2CYA.js";
5
5
  import {
6
6
  withFileCommitLock
7
7
  } from "./chunk-DZB666V7.js";
@@ -1616,11 +1616,23 @@ var EXTENSION_MIME_MAP = {
1616
1616
  ".svg": "image/svg+xml",
1617
1617
  ".webp": "image/webp",
1618
1618
  ".avif": "image/avif",
1619
+ // Video and audio match the extensions Squisq inserts as players, so a file
1620
+ // dropped into a document lists as the same media it was inserted as.
1619
1621
  ".mp4": "video/mp4",
1622
+ ".m4v": "video/mp4",
1623
+ ".mov": "video/quicktime",
1620
1624
  ".webm": "video/webm",
1625
+ ".ogv": "video/ogg",
1626
+ ".mkv": "video/x-matroska",
1621
1627
  ".mp3": "audio/mpeg",
1628
+ ".m4a": "audio/mp4",
1629
+ ".aac": "audio/aac",
1622
1630
  ".wav": "audio/wav",
1623
- ".ogg": "audio/ogg"
1631
+ ".ogg": "audio/ogg",
1632
+ ".oga": "audio/ogg",
1633
+ ".opus": "audio/opus",
1634
+ ".flac": "audio/flac",
1635
+ ".weba": "audio/webm"
1624
1636
  };
1625
1637
  function guessMimeType(path) {
1626
1638
  const dot = path.lastIndexOf(".");
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guessMimeType
3
- } from "./chunk-Q3OFZWJS.js";
3
+ } from "./chunk-3HUKGWDK.js";
4
4
  import {
5
5
  bytesEqual,
6
6
  compareSnapshotsByName,
@@ -17,7 +17,7 @@ import {
17
17
  createFileSystemDocumentTarget,
18
18
  describeEntryMove,
19
19
  describePartialMove
20
- } from "./chunk-FIEMYP2N.js";
20
+ } from "./chunk-D7VUEVAX.js";
21
21
  import {
22
22
  getFileSystemProviderV2
23
23
  } from "./chunk-XAMILHQP.js";
@@ -26,6 +26,7 @@ import {
26
26
  WORKSPACE_ROOT,
27
27
  fsErrorFromUnknown,
28
28
  parseWorkspacePath,
29
+ tryParseWorkspacePath,
29
30
  workspacePathBasename,
30
31
  workspacePathContains,
31
32
  workspacePathDirname,
@@ -1111,7 +1112,7 @@ var FileSystemContentContainer = class {
1111
1112
  function stripExt(name) {
1112
1113
  return name.replace(/\.[^.]+$/, "");
1113
1114
  }
1114
- function createFileMediaProvider(container, markdownBasename) {
1115
+ function createFileMediaProvider(container, markdownBasename, options = {}) {
1115
1116
  const folder = stripExt(markdownBasename) + "_files";
1116
1117
  const prefix = folder + "/";
1117
1118
  const blobUrlCache = /* @__PURE__ */ new Map();
@@ -1122,35 +1123,63 @@ function createFileMediaProvider(container, markdownBasename) {
1122
1123
  const clean = ref.replace(/^\/+/, "");
1123
1124
  return clean.startsWith(prefix) ? clean : prefix + clean;
1124
1125
  }
1126
+ function fallbackSlot(key) {
1127
+ return "\0" + key;
1128
+ }
1125
1129
  function invalidate(key) {
1126
1130
  generations.set(key, (generations.get(key) ?? 0) + 1);
1127
- pending.delete(key);
1128
- const cached = blobUrlCache.get(key);
1129
- if (cached) URL.revokeObjectURL(cached);
1130
- blobUrlCache.delete(key);
1131
+ for (const slot of [key, fallbackSlot(key)]) {
1132
+ pending.delete(slot);
1133
+ const cached = blobUrlCache.get(slot);
1134
+ if (cached) URL.revokeObjectURL(cached);
1135
+ blobUrlCache.delete(slot);
1136
+ }
1131
1137
  }
1132
1138
  function resolveUrl(ref) {
1133
1139
  if (disposed) return Promise.resolve(ref);
1134
1140
  const key = toKey(ref);
1135
- const cached = blobUrlCache.get(key);
1141
+ const readDocumentRelative = options.readDocumentRelative;
1142
+ if (!readDocumentRelative || ref.startsWith("/") || ref.startsWith(prefix)) {
1143
+ return resolveSlot(ref, key, key, () => container.readFile(key));
1144
+ }
1145
+ const found = blobUrlCache.get(key) ?? blobUrlCache.get(fallbackSlot(key));
1146
+ if (found) return Promise.resolve(found);
1147
+ const resolveFallback = () => resolveSlot(
1148
+ ref,
1149
+ key,
1150
+ fallbackSlot(key),
1151
+ () => (
1152
+ // The fallback can only add resolutions, never new failures.
1153
+ readDocumentRelative(ref).catch(() => null)
1154
+ )
1155
+ );
1156
+ if (key.split("/").some((segment) => segment === "." || segment === "..")) {
1157
+ return resolveFallback();
1158
+ }
1159
+ return resolveSlot(ref, key, key, () => container.readFile(key)).then(
1160
+ (url) => url !== ref || disposed ? url : resolveFallback()
1161
+ );
1162
+ }
1163
+ function resolveSlot(ref, key, slot, read) {
1164
+ const cached = blobUrlCache.get(slot);
1136
1165
  if (cached) return Promise.resolve(cached);
1137
- const existing = pending.get(key);
1166
+ const existing = pending.get(slot);
1138
1167
  if (existing) {
1139
1168
  return existing.promise.then((url) => url === existing.ref ? ref : url);
1140
1169
  }
1141
1170
  const generation = generations.get(key) ?? 0;
1142
1171
  const work = (async () => {
1143
- const data = await container.readFile(key);
1172
+ const data = await read();
1144
1173
  if (disposed) return ref;
1145
1174
  if ((generations.get(key) ?? 0) !== generation) return resolveUrl(ref);
1146
1175
  if (!data) return ref;
1147
1176
  const url = URL.createObjectURL(new Blob([data], { type: guessMimeType(key) }));
1148
- blobUrlCache.set(key, url);
1177
+ blobUrlCache.set(slot, url);
1149
1178
  return url;
1150
1179
  })().finally(() => {
1151
- if (pending.get(key)?.promise === work) pending.delete(key);
1180
+ if (pending.get(slot)?.promise === work) pending.delete(slot);
1152
1181
  });
1153
- pending.set(key, { ref, promise: work });
1182
+ pending.set(slot, { ref, promise: work });
1154
1183
  return work;
1155
1184
  }
1156
1185
  return {
@@ -1194,6 +1223,35 @@ function createFileMediaProvider(container, markdownBasename) {
1194
1223
  };
1195
1224
  }
1196
1225
 
1226
+ // src/filesystem/document-relative-media.ts
1227
+ function isDocumentMediaPath(path) {
1228
+ return /^(?:image|audio|video)\//.test(guessMimeType(path));
1229
+ }
1230
+ function resolveDocumentRelativeMediaPath(documentDirectory, ref) {
1231
+ const directory = tryParseWorkspacePath(documentDirectory);
1232
+ if (directory === null) return null;
1233
+ const queryAt = ref.search(/[?#]/);
1234
+ const raw = (queryAt === -1 ? ref : ref.slice(0, queryAt)).trim();
1235
+ if (!raw || /^[a-z][a-z0-9+.-]*:/i.test(raw) || /^[\\/]/.test(raw)) return null;
1236
+ let decoded = raw;
1237
+ try {
1238
+ decoded = decodeURIComponent(raw);
1239
+ } catch {
1240
+ }
1241
+ const segments = directory ? directory.split("/") : [];
1242
+ for (const segment of decoded.replace(/\\/g, "/").split("/")) {
1243
+ if (segment === "" || segment === ".") continue;
1244
+ if (segment === "..") {
1245
+ if (segments.length === 0) return null;
1246
+ segments.pop();
1247
+ continue;
1248
+ }
1249
+ segments.push(segment);
1250
+ }
1251
+ const resolved = tryParseWorkspacePath(segments.join("/"));
1252
+ return resolved && isDocumentMediaPath(resolved) ? resolved : null;
1253
+ }
1254
+
1197
1255
  export {
1198
1256
  suggestWikiArticles,
1199
1257
  resolveWikiArticlePath,
@@ -1207,5 +1265,7 @@ export {
1207
1265
  createDbkWorkspaceSnapshot,
1208
1266
  replaceMemoryWorkspaceFromDbk,
1209
1267
  FileSystemContentContainer,
1210
- createFileMediaProvider
1268
+ createFileMediaProvider,
1269
+ isDocumentMediaPath,
1270
+ resolveDocumentRelativeMediaPath
1211
1271
  };
@@ -181,13 +181,15 @@ var DocumentSession = class {
181
181
  if (content === this.content) return this.revision;
182
182
  this.content = content;
183
183
  this.revision += 1;
184
+ this.localEditedAt = Date.now();
184
185
  this.error = null;
185
186
  this.autoSaveRetryAttempt = 0;
186
187
  if (this.conflict) {
187
188
  this.conflict = {
188
189
  ...this.conflict,
189
190
  localContent: content,
190
- localRevision: this.revision
191
+ localRevision: this.revision,
192
+ localEditedAt: this.localEditedAt
191
193
  };
192
194
  }
193
195
  this.writeRecoverySnapshot();
@@ -377,6 +379,7 @@ var DocumentSession = class {
377
379
  targetKey: change.targetKey,
378
380
  localContent: this.content,
379
381
  localRevision: this.revision,
382
+ localEditedAt: this.localEditedAt,
380
383
  externalContent: change.content,
381
384
  externalVersion
382
385
  };
@@ -399,6 +402,7 @@ var DocumentSession = class {
399
402
  targetKey: change.targetKey,
400
403
  localContent: this.content,
401
404
  localRevision: this.revision,
405
+ localEditedAt: this.localEditedAt,
402
406
  externalContent: change.content,
403
407
  externalVersion: change.version ?? null
404
408
  };
@@ -411,6 +415,7 @@ var DocumentSession = class {
411
415
  this.clearAutoSaveTimer();
412
416
  this.autoSaveRetryAttempt = 0;
413
417
  this.content = content;
418
+ this.localEditedAt = void 0;
414
419
  this.revision += 1;
415
420
  this.persistedRevision = this.revision;
416
421
  this.persistedContent = content;
@@ -433,6 +438,7 @@ var DocumentSession = class {
433
438
  this.discardRecoverySnapshot();
434
439
  this.generation += 1;
435
440
  this.revision += 1;
441
+ this.localEditedAt = void 0;
436
442
  this.conflict = null;
437
443
  this.error = null;
438
444
  this.haltDrain = false;
@@ -518,6 +524,7 @@ var DocumentSession = class {
518
524
  this.externalSequence = -1;
519
525
  this.target = next.target;
520
526
  this.content = next.content;
527
+ this.localEditedAt = void 0;
521
528
  this.revision += 1;
522
529
  this.persistedRevision = this.revision;
523
530
  this.persistedContent = next.target ? next.content : null;
@@ -607,6 +614,7 @@ var DocumentSession = class {
607
614
  targetKey: target.key,
608
615
  localContent: this.content,
609
616
  localRevision: this.revision,
617
+ localEditedAt: this.localEditedAt,
610
618
  externalContent: error.externalContent,
611
619
  externalVersion: error.externalVersion
612
620
  };
@@ -715,6 +723,7 @@ var DocumentSession = class {
715
723
  this.externalSequence = -1;
716
724
  this.target = null;
717
725
  this.persistedContent = null;
726
+ this.localEditedAt = void 0;
718
727
  this.savingRevision = null;
719
728
  this.savingContent = null;
720
729
  this.error = null;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RawIndexedDBFileSystemStore
3
- } from "./chunk-DAPFSEKY.js";
3
+ } from "./chunk-OPLU2CYA.js";
4
4
  import {
5
5
  getFileSystemProviderV2
6
6
  } from "./chunk-XAMILHQP.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  HostFileSystemProviderV2
3
- } from "./chunk-45XD424D.js";
3
+ } from "./chunk-ZBRXXOW5.js";
4
4
  import {
5
5
  ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,
6
6
  maybeGetDocBlocksHost
7
- } from "./chunk-P4VIU7MB.js";
7
+ } from "./chunk-WE5W7BRL.js";
8
8
 
9
9
  // src/filesystem/electron-provider-v2.ts
10
10
  var ElectronFileSystemProviderV2 = class extends HostFileSystemProviderV2 {