@bendyline/docblocks 2.7.6 → 2.7.7

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.3 | 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.3
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.3
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.3
224
224
  Source files: node_modules/@bendyline/squisq/THIRD_PARTY_LICENSES.txt
225
225
  ==============================================================================
226
226
  THIRD-PARTY LICENSES FOR @bendyline/squisq
@@ -216,6 +216,17 @@ interface AiChatRequest {
216
216
  readonly maxTokens?: number;
217
217
  readonly purpose: AiChatPurpose;
218
218
  readonly responseFormat?: AiResponseFormat;
219
+ /**
220
+ * What to search knowledge catalogs for. Without it a provider searches with
221
+ * the last user message, which for a templated prompt is mostly document.
222
+ */
223
+ readonly knowledgeQuery?: string;
224
+ /**
225
+ * Number knowledge passages and ask the model to cite them as `[n]`. Only a
226
+ * caller that checks and renders citations should: the markers otherwise
227
+ * end up in its output.
228
+ */
229
+ readonly knowledgeCitations?: boolean;
219
230
  }
220
231
  interface AiChatCompletion {
221
232
  readonly text: string;
@@ -235,6 +246,12 @@ interface AiChatProgress {
235
246
  readonly outputTokens: number | null;
236
247
  readonly tokensPerSecond: number | null;
237
248
  }
249
+ /** One reference passage the model was given; its citation number is its position from 1. */
250
+ interface AiChatEvidence {
251
+ readonly title: string;
252
+ readonly catalogId: string;
253
+ readonly text: string;
254
+ }
238
255
  /** One knowledge catalog that contributed reference passages to a request. */
239
256
  interface AiChatKnowledgeSource {
240
257
  readonly catalogId: string;
@@ -251,8 +268,11 @@ interface AiChatKnowledgeSource {
251
268
  type AiChatKnowledge = {
252
269
  readonly outcome: 'used';
253
270
  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[];
271
+ /**
272
+ * The passages the model was given, in citation order: it was asked to
273
+ * cite `evidence[0]` as `[1]`. Its output can be checked against them.
274
+ */
275
+ readonly evidence: readonly AiChatEvidence[];
256
276
  }
257
277
  /** The catalogs were searched and nothing relevant came back. */
258
278
  | {
@@ -282,14 +302,22 @@ type AiChatEvent = {
282
302
  interface AiFactCheckRequest {
283
303
  /** The output, as Markdown. */
284
304
  readonly text: string;
285
- /** Reference passages the model was given. */
305
+ /** Reference passage texts the model was given, `[1]` first. */
286
306
  readonly evidence: readonly string[];
307
+ /**
308
+ * The model was asked to cite passages by number, and its numbers match
309
+ * `evidence`: check each sentence against what it cites. Otherwise each
310
+ * sentence is checked against all of the evidence and markers are ignored.
311
+ */
312
+ readonly citations: boolean;
287
313
  /** What the person supplied: their instructions and document. Details found here need no source. */
288
314
  readonly given: string;
289
315
  }
290
316
  interface AiFactCheckSentence {
291
- /** The sentence, possibly shortened. */
317
+ /** The sentence without citation markers, possibly shortened. */
292
318
  readonly text: string;
319
+ /** `bad-citation`: it cites a passage number the model was never given. */
320
+ readonly problem: 'unsourced' | 'bad-citation';
293
321
  /** The names, dates, numbers or quotations no source shows. */
294
322
  readonly missing: readonly string[];
295
323
  /**
@@ -1123,6 +1151,14 @@ interface DocBlocksHostExternalAPI {
1123
1151
  writeBinary(resourceId: string, data: ArrayBuffer | Uint8Array): Promise<void>;
1124
1152
  commitText(resourceId: string, content: string, expectedContent: string | null): Promise<FileCommitResult>;
1125
1153
  commitBinary(resourceId: string, data: ArrayBuffer | Uint8Array, expectedVersion: string | null): Promise<ExternalBinaryCommitResult>;
1154
+ /**
1155
+ * Read, never write, a media file inside the folder of a loose markdown
1156
+ * grant, so the document's relative image paths render. `relativePath` is a
1157
+ * canonical `WorkspacePath` from that folder naming an image, audio, or video
1158
+ * file; it cannot climb out or follow a symbolic link. Resolves null when
1159
+ * the file does not exist. Bundle grants carry their media and refuse this.
1160
+ */
1161
+ readRelativeMedia?(resourceId: string, relativePath: string): Promise<ArrayBuffer | null>;
1126
1162
  /** Revoke one external resource when its transient document is closed. */
1127
1163
  revoke(resourceId: string): Promise<void>;
1128
1164
  }
@@ -1277,6 +1313,8 @@ interface HostCapabilities {
1277
1313
  readonly exportRememberedTargets: boolean;
1278
1314
  readonly openSavedExports: boolean;
1279
1315
  readonly externalResources: boolean;
1316
+ /** A loose OS-opened file's relative images can be read from beside it. */
1317
+ readonly externalRelativeMedia: boolean;
1280
1318
  readonly openRequests: boolean;
1281
1319
  readonly menuCommands: boolean;
1282
1320
  readonly pinnedDocumentMirror: boolean;
@@ -1340,4 +1378,4 @@ declare function parseHostEnvironment(value: unknown): HostEnvironment | null;
1340
1378
  */
1341
1379
  declare function deriveHostCapabilities(host: unknown): HostCapabilities;
1342
1380
 
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 };
1381
+ export { type DocBlocksHostMenuAPI as $, type AiChatCompletion as A, type AiModelInstallHandle as B, type AiPreferences as C, type AiPreferencesPatch as D, type AiProgress as E, type AiProviderInfo as F, type AiResponseFormat as G, type AiResult as H, type AiReviewMode as I, type AiSearchHit as J, type AiSearchQuery as K, type AiSearchResult as L, type AiSpeechAudio as M, type AiStatus as N, type AiSynthesizeRequest as O, type AiTranscribeRequest as P, type AiTranscript as Q, type AiUnavailableReason as R, type DocBlocksHostAPI as S, type DocBlocksHostAiAPI as T, type DocBlocksHostClipboardAPI as U, type DocBlocksHostExportAPI as V, type DocBlocksHostExternalAPI as W, type DocBlocksHostFfmpegAPI as X, type DocBlocksHostFsAPI as Y, type DocBlocksHostGitAPI as Z, type DocBlocksHostLifecycleAPI as _, type AiChatEvent as a, deriveHostCapabilities as a$, type DocBlocksHostShellAPI as a0, type DocBlocksHostSpeechAPI as a1, type DocBlocksHostUpdaterAPI as a2, type DocBlocksHostWorkspacesAPI as a3, type ElectronWorkspaceInfo as a4, type ExternalBinaryCommitResult as a5, type GitBranchInfo as a6, type GitCapabilities as a7, type GitCloneHandle as a8, type GitCloneProgress as a9, type SpeechAudioChunk as aA, type SpeechCatalog as aB, type SpeechError as aC, type SpeechErrorCode as aD, type SpeechInstallEvent as aE, type SpeechInstallHandle as aF, type SpeechModelInfo as aG, type SpeechModelKind as aH, type SpeechPreferences as aI, type SpeechPreferencesPatch as aJ, type SpeechProgress as aK, type SpeechReadiness as aL, type SpeechReadinessState as aM, type SpeechResult as aN, type SpeechSegment as aO, type SpeechStatus as aP, type SpeechSynthesisHandle as aQ, type SpeechSynthesisSummary as aR, type SpeechSynthesizeEvent as aS, type SpeechSynthesizeRequest as aT, type SpeechTranscribeRequest as aU, type SpeechTranscript as aV, type SpeechVoiceInfo as aW, type SpeechWordTiming as aX, type UpdateCheckResult as aY, type UpdateInstallResult as aZ, type UpdaterStatus as a_, type GitError as aa, type GitErrorCode as ab, type GitFileAtRevision as ac, type GitFileChange as ad, type GitFileStatusCode as ae, type GitLogEntry as af, type GitLogOptions as ag, type GitRemoteInfo as ah, type GitRepoDetection as ai, type GitResult as aj, type GitRevision as ak, type GitStatus as al, HOST_PLATFORMS as am, HOST_SURFACE_KINDS as an, type HostCapabilities as ao, type HostCloseReason as ap, type HostEnvironment as aq, type HostExportTargetGrant as ar, type HostPinnedDocument as as, type HostPlatform as at, type HostPrepareCloseRequest as au, type HostPrepareCloseResult as av, type HostSurfaceKind as aw, type MenuCommand as ax, NO_HOST_CAPABILITIES as ay, type OpenRequest as az, type AiChatEvidence as b, parseAiKnowledgeAction as b0, parseAiKnowledgeState as b1, parseHostEnvironment as b2, type AiChatHandle as c, type AiChatKnowledge as d, type AiChatKnowledgeSource as e, type AiChatMessage as f, type AiChatProgress as g, type AiChatPurpose as h, type AiChatRequest as i, type AiConnectionStep as j, type AiEnsureWorkspaceHandle as k, type AiError as l, type AiErrorCode as m, type AiFactCheck as n, type AiFactCheckRequest as o, type AiFactCheckSentence as p, type AiImageRequest as q, type AiImageResult as r, type AiKnowledgeAPI as s, type AiKnowledgeAction as t, type AiKnowledgeCatalog as u, type AiKnowledgeState as v, type AiModelDownloadInfo as w, type AiModelFit as x, type AiModelInfo as y, type AiModelInstallEvent 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,
@@ -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
  };
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  HostFileSystemProviderV2
3
- } from "./chunk-45XD424D.js";
3
+ } from "./chunk-NECMAJHS.js";
4
4
  import {
5
5
  ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,
6
6
  maybeGetDocBlocksHost
7
- } from "./chunk-P4VIU7MB.js";
7
+ } from "./chunk-RFEB4N5Q.js";
8
8
 
9
9
  // src/filesystem/electron-provider-v2.ts
10
10
  var ElectronFileSystemProviderV2 = class extends HostFileSystemProviderV2 {
@@ -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,7 +1,7 @@
1
1
  import {
2
2
  FILE_SYSTEM_TRANSFER_LIMITS,
3
3
  maybeGetDocBlocksHost
4
- } from "./chunk-P4VIU7MB.js";
4
+ } from "./chunk-RFEB4N5Q.js";
5
5
  import {
6
6
  parseFileSystemCapabilities
7
7
  } from "./chunk-245W57QP.js";
@@ -24,8 +24,7 @@ var RawIndexedDBFileSystemStore = class {
24
24
  this.closed = false;
25
25
  }
26
26
  async transaction(mode, operation) {
27
- const database = await this.getDatabase();
28
- const nativeTransaction = database.transaction(this.storeName, mode);
27
+ const nativeTransaction = await this.beginTransaction(mode);
29
28
  const completion = waitForTransaction(nativeTransaction);
30
29
  const transaction = new RawIndexedDBFileSystemTransaction(
31
30
  nativeTransaction.objectStore(this.storeName)
@@ -51,6 +50,30 @@ var RawIndexedDBFileSystemStore = class {
51
50
  this.database = null;
52
51
  this.opening = null;
53
52
  }
53
+ /**
54
+ * Start a native transaction, reconnecting once if the cached connection
55
+ * was closed underneath this store. Browsers close IndexedDB connections on
56
+ * their own (after the device sleeps, when site data is cleared, or when
57
+ * the storage backend restarts), and a closed connection rejects every
58
+ * later `transaction()` call with InvalidStateError ("The database
59
+ * connection is closing"). No work has run at that point, so reopening and
60
+ * starting again is safe.
61
+ */
62
+ async beginTransaction(mode) {
63
+ const database = await this.getDatabase();
64
+ try {
65
+ return database.transaction(this.storeName, mode);
66
+ } catch (error) {
67
+ if (!isClosedConnectionError(error)) throw error;
68
+ this.forgetDatabase(database);
69
+ const reopened = await this.getDatabase();
70
+ return reopened.transaction(this.storeName, mode);
71
+ }
72
+ }
73
+ forgetDatabase(database) {
74
+ if (this.database === database) this.database = null;
75
+ database.close();
76
+ }
54
77
  getDatabase() {
55
78
  if (this.closed) {
56
79
  return Promise.reject(new Error("The IndexedDB filesystem store is closed."));
@@ -67,10 +90,8 @@ var RawIndexedDBFileSystemStore = class {
67
90
  }
68
91
  this.database = database;
69
92
  this.opening = null;
70
- database.onversionchange = () => {
71
- database.close();
72
- if (this.database === database) this.database = null;
73
- };
93
+ database.onversionchange = () => this.forgetDatabase(database);
94
+ database.onclose = () => this.forgetDatabase(database);
74
95
  return database;
75
96
  }).catch((error) => {
76
97
  this.opening = null;
@@ -182,6 +203,9 @@ function openDatabase(databaseName, version, upgrade) {
182
203
  };
183
204
  });
184
205
  }
206
+ function isClosedConnectionError(error) {
207
+ return typeof error === "object" && error !== null && error.name === "InvalidStateError";
208
+ }
185
209
  function requestResult(request) {
186
210
  return new Promise((resolve, reject) => {
187
211
  request.onsuccess = () => resolve(request.result);
@@ -29,6 +29,7 @@ var NO_CAPABILITIES = Object.freeze({
29
29
  exportRememberedTargets: false,
30
30
  openSavedExports: false,
31
31
  externalResources: false,
32
+ externalRelativeMedia: false,
32
33
  openRequests: false,
33
34
  menuCommands: false,
34
35
  pinnedDocumentMirror: false,
@@ -107,6 +108,7 @@ function deriveHostCapabilities(host) {
107
108
  exportRememberedTargets: hasMethod(exports, "resolveTarget") && hasMethod(exports, "pickTarget"),
108
109
  openSavedExports: hasMethod(exports, "openSaved"),
109
110
  externalResources: hasMethod(host.external, "readText"),
111
+ externalRelativeMedia: hasMethod(host.external, "readRelativeMedia"),
110
112
  openRequests: hasMethod(host, "onOpenRequest"),
111
113
  menuCommands: hasMethod(host, "onMenuCommand"),
112
114
  pinnedDocumentMirror: hasMethod(host.menu, "setPinnedDocuments"),
@@ -153,6 +155,8 @@ var AI_WIRE_LIMITS = Object.freeze({
153
155
  knowledgeSources: 8,
154
156
  knowledgeTitles: 8,
155
157
  knowledgeTitleCharacters: 256,
158
+ /** A knowledge search; Gezel accepts up to 8,192 characters. */
159
+ knowledgeQueryCharacters: 8192,
156
160
  /** Passage texts sent with a knowledge report; Gezel caps a retrieval at 24,000 characters. */
157
161
  knowledgeEvidence: 8,
158
162
  knowledgeEvidenceCharacters: 24 * 1024,
@@ -412,7 +416,14 @@ function parseAiChatRequest(value) {
412
416
  if (!hasKeysWithin(
413
417
  value,
414
418
  ["messages", "purpose"],
415
- ["model", "temperature", "maxTokens", "responseFormat"]
419
+ [
420
+ "model",
421
+ "temperature",
422
+ "maxTokens",
423
+ "responseFormat",
424
+ "knowledgeQuery",
425
+ "knowledgeCitations"
426
+ ]
416
427
  )) {
417
428
  return null;
418
429
  }
@@ -440,13 +451,21 @@ function parseAiChatRequest(value) {
440
451
  }
441
452
  const responseFormat = value.responseFormat === void 0 ? void 0 : parseAiResponseFormat(value.responseFormat);
442
453
  if (responseFormat === null) return null;
454
+ if (value.knowledgeQuery !== void 0 && !isBoundedString(value.knowledgeQuery, AI_WIRE_LIMITS.knowledgeQueryCharacters, 1)) {
455
+ return null;
456
+ }
457
+ if (value.knowledgeCitations !== void 0 && typeof value.knowledgeCitations !== "boolean") {
458
+ return null;
459
+ }
443
460
  return {
444
461
  messages,
445
462
  purpose: value.purpose,
446
463
  ...value.model === void 0 ? {} : { model: value.model },
447
464
  ...value.temperature === void 0 ? {} : { temperature: value.temperature },
448
465
  ...value.maxTokens === void 0 ? {} : { maxTokens: value.maxTokens },
449
- ...responseFormat === void 0 ? {} : { responseFormat }
466
+ ...responseFormat === void 0 ? {} : { responseFormat },
467
+ ...value.knowledgeQuery === void 0 ? {} : { knowledgeQuery: value.knowledgeQuery },
468
+ ...value.knowledgeCitations === void 0 ? {} : { knowledgeCitations: value.knowledgeCitations }
450
469
  };
451
470
  }
452
471
  function parseAiChatProgress(value) {
@@ -489,12 +508,8 @@ function parseAiChatKnowledge(value) {
489
508
  if (value.outcome !== "used" || !hasExactKeys(value, ["outcome", "sources", "evidence"])) {
490
509
  return null;
491
510
  }
492
- const evidence = parseTextList(
493
- value.evidence,
494
- AI_WIRE_LIMITS.knowledgeEvidence,
495
- AI_WIRE_LIMITS.knowledgeEvidenceCharacters
496
- );
497
- if (!evidence || evidence.length === 0) return null;
511
+ const evidence = parseAiChatEvidence(value.evidence);
512
+ if (!evidence) return null;
498
513
  if (!Array.isArray(value.sources) || value.sources.length === 0 || value.sources.length > AI_WIRE_LIMITS.knowledgeSources) {
499
514
  return null;
500
515
  }
@@ -508,6 +523,23 @@ function parseAiChatKnowledge(value) {
508
523
  }
509
524
  return { outcome: "used", sources, evidence };
510
525
  }
526
+ function parseAiChatEvidence(value) {
527
+ if (!Array.isArray(value) || value.length === 0 || value.length > AI_WIRE_LIMITS.knowledgeEvidence) {
528
+ return null;
529
+ }
530
+ const evidence = [];
531
+ let total = 0;
532
+ for (const entry of value) {
533
+ if (!isRecord2(entry) || !hasExactKeys(entry, ["title", "catalogId", "text"])) return null;
534
+ if (!isBoundedString(entry.title, AI_WIRE_LIMITS.knowledgeTitleCharacters)) return null;
535
+ if (!isBoundedString(entry.catalogId, HOST_WIRE_LIMITS.identifierCharacters, 1)) return null;
536
+ if (!isBoundedString(entry.text, AI_WIRE_LIMITS.knowledgeEvidenceCharacters, 1)) return null;
537
+ total += entry.text.length;
538
+ if (total > AI_WIRE_LIMITS.knowledgeEvidenceCharacters) return null;
539
+ evidence.push({ title: entry.title, catalogId: entry.catalogId, text: entry.text });
540
+ }
541
+ return evidence;
542
+ }
511
543
  function parseTextList(value, entries, characters) {
512
544
  if (!Array.isArray(value) || value.length > entries) return null;
513
545
  let total = 0;
@@ -521,7 +553,10 @@ function parseTextList(value, entries, characters) {
521
553
  return texts;
522
554
  }
523
555
  function parseAiFactCheckRequest(value) {
524
- if (!isRecord2(value) || !hasExactKeys(value, ["text", "evidence", "given"])) return null;
556
+ if (!isRecord2(value) || !hasExactKeys(value, ["text", "evidence", "given", "citations"])) {
557
+ return null;
558
+ }
559
+ if (typeof value.citations !== "boolean") return null;
525
560
  if (!isBoundedString(value.text, AI_WIRE_LIMITS.factCheckTextCharacters)) return null;
526
561
  if (!isBoundedString(value.given, AI_WIRE_LIMITS.factCheckGivenCharacters)) return null;
527
562
  const evidence = parseTextList(
@@ -529,11 +564,14 @@ function parseAiFactCheckRequest(value) {
529
564
  AI_WIRE_LIMITS.factCheckEvidence,
530
565
  AI_WIRE_LIMITS.factCheckEvidenceCharacters
531
566
  );
532
- return evidence ? { text: value.text, evidence, given: value.given } : null;
567
+ return evidence ? { text: value.text, evidence, given: value.given, citations: value.citations } : null;
533
568
  }
534
569
  function parseAiFactCheckSentence(value) {
535
- if (!isRecord2(value) || !hasExactKeys(value, ["text", "missing", "strong"])) return null;
570
+ if (!isRecord2(value) || !hasExactKeys(value, ["text", "problem", "missing", "strong"])) {
571
+ return null;
572
+ }
536
573
  if (!isBoundedString(value.text, AI_WIRE_LIMITS.factCheckSentenceCharacters, 1)) return null;
574
+ if (value.problem !== "unsourced" && value.problem !== "bad-citation") return null;
537
575
  if (typeof value.strong !== "boolean") return null;
538
576
  if (!Array.isArray(value.missing) || value.missing.length > AI_WIRE_LIMITS.factCheckDetails) {
539
577
  return null;
@@ -543,7 +581,7 @@ function parseAiFactCheckSentence(value) {
543
581
  if (!isBoundedString(detail, AI_WIRE_LIMITS.knowledgeTitleCharacters, 1)) return null;
544
582
  missing.push(detail);
545
583
  }
546
- return { text: value.text, missing, strong: value.strong };
584
+ return { text: value.text, problem: value.problem, missing, strong: value.strong };
547
585
  }
548
586
  function parseAiFactCheck(value) {
549
587
  if (!isRecord2(value) || !hasExactKeys(value, ["checked", "unsourced"])) return null;
@@ -4,7 +4,7 @@ export { isElectronHost } from '../host/index.js';
4
4
  import '../v2-DwxWjFC0.js';
5
5
  import '../workspace-path-CWVrcuPL.js';
6
6
  import '../filesystem-v2-CXdAPR27.js';
7
- import '../capabilities-DJ7X9EOt.js';
7
+ import '../capabilities-D4Z1xYZV.js';
8
8
 
9
9
  /** Compatibility entry point retaining the Electron backend's exact guarantees. */
10
10
  declare class ElectronFileSystemProviderV2 extends HostFileSystemProviderV2 {
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  ElectronFileSystemProvider,
3
3
  ElectronFileSystemProviderV2
4
- } from "../chunk-56QRV45P.js";
5
- import "../chunk-45XD424D.js";
4
+ } from "../chunk-66WTIYYG.js";
5
+ import "../chunk-NECMAJHS.js";
6
6
  import {
7
7
  isElectronHost
8
- } from "../chunk-P4VIU7MB.js";
8
+ } from "../chunk-RFEB4N5Q.js";
9
9
  import "../chunk-245W57QP.js";
10
10
  import "../chunk-V5SWLUZY.js";
11
11
  import "../chunk-73OOROXH.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  HostFileSystemProviderV2
3
- } from "../chunk-45XD424D.js";
3
+ } from "../chunk-NECMAJHS.js";
4
4
  import {
5
5
  ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,
6
6
  maybeGetDocBlocksHost
7
- } from "../chunk-P4VIU7MB.js";
7
+ } from "../chunk-RFEB4N5Q.js";
8
8
  import "../chunk-245W57QP.js";
9
9
  import "../chunk-V5SWLUZY.js";
10
10
  import "../chunk-73OOROXH.js";