@hraness/wordcell 0.21.3 → 0.22.1

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 (93) hide show
  1. package/README.md +170 -64
  2. package/dist/authoring.js +5 -3
  3. package/dist/{authority-4sp9d552.js → authority-06eqhqam.js} +57 -12
  4. package/dist/benchmark.js +4 -4
  5. package/dist/capture.js +6 -5
  6. package/dist/cli.js +39 -33
  7. package/dist/clip/acquire.js +3 -2
  8. package/dist/clip/cli.js +6 -5
  9. package/dist/clip/doctor.js +4 -3
  10. package/dist/clip/jobs.js +3 -3
  11. package/dist/clip/refresh.js +1 -1
  12. package/dist/evaluation-builder.js +20 -19
  13. package/dist/evaluation-kb.js +16 -15
  14. package/dist/graph-authority.js +5 -5
  15. package/dist/graph-percolation.js +7 -7
  16. package/dist/graph.js +1 -1
  17. package/dist/{index-pbr6rv47.js → index-1k595z6v.js} +6 -6
  18. package/dist/{index-0k2x4nn9.js → index-233z9wmn.js} +17 -5
  19. package/dist/index-3agn8scn.js +306 -0
  20. package/dist/index-4knsp9qj.js +34 -0
  21. package/dist/index-66pshdtx.js +341 -0
  22. package/dist/{index-59ssmqqm.js → index-76dbn6pe.js} +1 -1
  23. package/dist/{index-0rfcqab6.js → index-810nfzdj.js} +617 -66
  24. package/dist/index-9rf81m0p.js +368 -0
  25. package/dist/{index-51bap0mq.js → index-bqtqeak3.js} +10 -10
  26. package/dist/{index-9zcpdbjg.js → index-de2w8crk.js} +13 -13
  27. package/dist/{index-bgfzwt4h.js → index-djrcc1yf.js} +6 -6
  28. package/dist/{index-6sw24nvv.js → index-ecqpgr5y.js} +53 -2
  29. package/dist/{index-van48n3g.js → index-fc4dr114.js} +4 -2
  30. package/dist/{index-jzcws0zn.js → index-g5vsqmdy.js} +27 -57
  31. package/dist/index-hmw17zaa.js +1985 -0
  32. package/dist/index-j70m75wd.js +217 -0
  33. package/dist/{index-nd6nynv2.js → index-jk1sgx36.js} +1 -1
  34. package/dist/{index-3ehtt59c.js → index-n386evxj.js} +1 -1
  35. package/dist/{index-vdw5yjfa.js → index-q7tbg07z.js} +110 -20
  36. package/dist/{index-ekpwvbra.js → index-qbssx940.js} +1 -2
  37. package/dist/{index-115b07ap.js → index-rr9kzq4n.js} +5 -5
  38. package/dist/{index-11621h23.js → index-tf4wzjew.js} +1 -1
  39. package/dist/{index-why54q5p.js → index-vnybgywh.js} +4 -4
  40. package/dist/{index-bcfn9xah.js → index-xv80vzfp.js} +7 -7
  41. package/dist/index.js +289 -95
  42. package/dist/percolate.js +2 -2
  43. package/dist/portfolio.js +16 -15
  44. package/dist/publish-model.js +36 -0
  45. package/dist/publish-reader/reader.css +1042 -0
  46. package/dist/publish-reader/reader.js +1534 -0
  47. package/dist/publish-reader/theme.js +92 -0
  48. package/dist/publish-search.js +52 -0
  49. package/dist/publish.js +36 -0
  50. package/dist/rerank-typesafe.js +13 -0
  51. package/dist/rerank.js +14 -0
  52. package/dist/sdk.js +16 -13
  53. package/dist/search.js +3 -3
  54. package/dist/semantic.js +5 -5
  55. package/dist/{support-vm4mkw0k.js → support-1rh2d7mt.js} +38 -32
  56. package/dist/workflows/decision-context.js +15 -14
  57. package/dist/workflows/index.js +15 -14
  58. package/package.json +65 -6
  59. package/skills/wordcell/AGENTS.md +1 -0
  60. package/skills/wordcell/SKILL.md +2 -1
  61. package/skills/wordcell/agents/openai.yaml +1 -1
  62. package/skills/wordcell/references/publish.md +127 -0
  63. package/skills/wordcell/references/query.md +22 -0
  64. package/skills/wordcell/references/refresh.md +14 -0
  65. package/src/authoring-model.ts +29 -0
  66. package/src/authoring-program.ts +38 -3
  67. package/src/authoring.ts +17 -3
  68. package/src/cli-program.ts +441 -12
  69. package/src/graph.ts +1 -1
  70. package/src/index.ts +4 -0
  71. package/src/oh/authority.ts +14 -5
  72. package/src/oh/canonical-rust.ts +127 -0
  73. package/src/oh/projection-rust.ts +63 -0
  74. package/src/oh-adoption.ts +7 -1
  75. package/src/publish-graph.ts +0 -0
  76. package/src/publish-index.ts +195 -0
  77. package/src/publish-markdown.ts +617 -0
  78. package/src/publish-model.ts +599 -0
  79. package/src/publish-nav.ts +204 -0
  80. package/src/publish-pages.ts +382 -0
  81. package/src/publish-reader/reader.css +1042 -0
  82. package/src/publish-reader/reader.ts +1017 -0
  83. package/src/publish-reader/theme.ts +97 -0
  84. package/src/publish-search.ts +418 -0
  85. package/src/publish-select.ts +419 -0
  86. package/src/publish-theme.ts +106 -0
  87. package/src/publish.ts +904 -0
  88. package/src/rerank-credentials.ts +56 -0
  89. package/src/rerank-typesafe.ts +472 -0
  90. package/src/rerank.ts +389 -0
  91. package/src/sdk.ts +157 -6
  92. package/src/serve.ts +180 -0
  93. package/src/vault.ts +23 -9
@@ -0,0 +1,368 @@
1
+ // @bun
2
+ import {
3
+ MAX_RERANK_CANDIDATES,
4
+ MAX_RERANK_SNIPPET_BYTES,
5
+ MAX_RERANK_STATE_BYTES
6
+ } from "./index-j70m75wd.js";
7
+
8
+ // src/rerank-typesafe.ts
9
+ var DEFAULT_SYSTEMONE_ENDPOINT = "https://api.typesafe.ai/v1/systemone";
10
+ var DEFAULT_SYSTEMONE_MODEL = "jev-1.13.0";
11
+ var DEFAULT_RERANK_TIMEOUT_MS = 8000;
12
+ var DEFAULT_RERANK_MAX_RESPONSE_BYTES = 64 * 1024;
13
+ var DEFAULT_RERANK_CONCURRENCY = 4;
14
+ var MAX_RERANK_TIMEOUT_MS = DEFAULT_RERANK_TIMEOUT_MS;
15
+ var MAX_RERANK_RESPONSE_BYTES = DEFAULT_RERANK_MAX_RESPONSE_BYTES;
16
+ var MAX_RERANK_CONCURRENCY = 8;
17
+ var RELEVANCE_QUESTION = "relevant";
18
+ var RELEVANCE_INSTRUCTIONS = "Could this note help answer the search query in a personal Markdown knowledge " + "vault of notes, plans, concepts, and captured sources?";
19
+ var RELEVANCE_CRITERIA = {
20
+ true: "The note's title, path, or snippet directly addresses the query's subject or task.",
21
+ false: "The note is unrelated to the query or only touches a neighboring topic."
22
+ };
23
+ async function readBoundedResponse(response, maxBytes, signal) {
24
+ const body = response.body;
25
+ if (body === null)
26
+ return new Uint8Array;
27
+ const reader = body.getReader();
28
+ const abort = () => {
29
+ reader.cancel().catch(() => {
30
+ return;
31
+ });
32
+ };
33
+ signal.addEventListener("abort", abort, { once: true });
34
+ const chunks = [];
35
+ let total = 0;
36
+ try {
37
+ for (;; ) {
38
+ if (signal.aborted)
39
+ throw new Error("request aborted");
40
+ const { done, value } = await reader.read();
41
+ if (signal.aborted)
42
+ throw new Error("request aborted");
43
+ if (done)
44
+ break;
45
+ if (value === undefined || value.byteLength === 0)
46
+ continue;
47
+ total += value.byteLength;
48
+ if (total > maxBytes) {
49
+ reader.cancel().catch(() => {
50
+ return;
51
+ });
52
+ throw new Error(`response exceeds the ${maxBytes}-byte limit`);
53
+ }
54
+ chunks.push(value);
55
+ }
56
+ } finally {
57
+ signal.removeEventListener("abort", abort);
58
+ if (signal.aborted)
59
+ abort();
60
+ reader.releaseLock();
61
+ }
62
+ const bytes = new Uint8Array(total);
63
+ let offset = 0;
64
+ for (const chunk of chunks) {
65
+ bytes.set(chunk, offset);
66
+ offset += chunk.byteLength;
67
+ }
68
+ return bytes;
69
+ }
70
+ async function fetchSystemOneTransport(request) {
71
+ const signals = [AbortSignal.timeout(request.timeoutMs)];
72
+ if (request.signal !== undefined)
73
+ signals.push(request.signal);
74
+ const signal = AbortSignal.any(signals);
75
+ const body = new Uint8Array(request.body.byteLength);
76
+ body.set(request.body);
77
+ const response = await fetch(request.url, {
78
+ method: "POST",
79
+ headers: request.headers,
80
+ body: body.buffer,
81
+ redirect: "error",
82
+ signal
83
+ });
84
+ if (signal.aborted) {
85
+ response.body?.cancel().catch(() => {
86
+ return;
87
+ });
88
+ throw new Error("request aborted");
89
+ }
90
+ return {
91
+ status: response.status,
92
+ body: await readBoundedResponse(response, request.maxResponseBytes, signal)
93
+ };
94
+ }
95
+ function finiteNumber(value) {
96
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
97
+ }
98
+ function recordValue(value) {
99
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
100
+ }
101
+ function hasExactKeys(value, expected) {
102
+ const actual = Object.keys(value);
103
+ return actual.length === expected.length && expected.every((key) => Object.hasOwn(value, key));
104
+ }
105
+ function tokenCount(value) {
106
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= 1e9 ? value : null;
107
+ }
108
+ function acceptedResponseModel(value) {
109
+ return value === DEFAULT_SYSTEMONE_MODEL;
110
+ }
111
+ function parseSystemOneResponse(value) {
112
+ const root = recordValue(value);
113
+ if (root === null || !hasExactKeys(root, ["model", "answers", "usage"]))
114
+ return null;
115
+ const answers = recordValue(root["answers"]);
116
+ if (answers === null || !hasExactKeys(answers, [RELEVANCE_QUESTION]))
117
+ return null;
118
+ const answer = recordValue(answers[RELEVANCE_QUESTION]);
119
+ if (answer === null || !hasExactKeys(answer, ["type", "noul"]) || answer["type"] !== "noul")
120
+ return null;
121
+ const noul = finiteNumber(answer["noul"]);
122
+ if (noul === null || noul < 0 || noul > 1)
123
+ return null;
124
+ const usage = recordValue(root["usage"]);
125
+ if (usage === null || !hasExactKeys(usage, ["input_tokens", "output_tokens"]))
126
+ return null;
127
+ const inputTokens = tokenCount(usage["input_tokens"]);
128
+ const outputTokens = tokenCount(usage["output_tokens"]);
129
+ if (!acceptedResponseModel(root["model"]) || inputTokens === null || outputTokens === null)
130
+ return null;
131
+ return { noul, model: root["model"], inputTokens, outputTokens };
132
+ }
133
+ async function mapWithConcurrency(items, concurrency, operation) {
134
+ const results = new Array(items.length);
135
+ let cursor = 0;
136
+ const workers = Array.from({ length: Math.max(1, Math.min(concurrency, items.length)) }, async () => {
137
+ while (cursor < items.length) {
138
+ const index = cursor;
139
+ cursor += 1;
140
+ results[index] = await operation(items[index], index);
141
+ }
142
+ });
143
+ await Promise.all(workers);
144
+ return results;
145
+ }
146
+ function validApiKey(value) {
147
+ return value !== undefined && /^[\x21-\x7e]{1,512}$/u.test(value);
148
+ }
149
+ function boundedPositiveInteger(value, fallback, maximum) {
150
+ const resolved = value ?? fallback;
151
+ return Number.isSafeInteger(resolved) && resolved >= 1 && resolved <= maximum ? resolved : null;
152
+ }
153
+ function validRerankRequest(value) {
154
+ const request = recordValue(value);
155
+ if (request === null || typeof request["query"] !== "string" || request["query"].trim() === "" || Buffer.byteLength(request["query"], "utf8") > MAX_RERANK_STATE_BYTES || request["signal"] !== undefined && !(request["signal"] instanceof AbortSignal) || !Array.isArray(request["candidates"]) || request["candidates"].length > MAX_RERANK_CANDIDATES)
156
+ return false;
157
+ const ids = new Set;
158
+ for (const [index, value2] of request["candidates"].entries()) {
159
+ const candidate = recordValue(value2);
160
+ if (candidate === null || typeof candidate["id"] !== "string" || candidate["id"] === "" || ids.has(candidate["id"]) || candidate["baselineRank"] !== index + 1 || typeof candidate["score"] !== "number" || !Number.isFinite(candidate["score"]) || typeof candidate["title"] !== "string" || typeof candidate["path"] !== "string" || typeof candidate["snippet"] !== "string" || Buffer.byteLength(candidate["id"], "utf8") > MAX_RERANK_STATE_BYTES || Buffer.byteLength(candidate["title"], "utf8") > MAX_RERANK_STATE_BYTES || Buffer.byteLength(candidate["path"], "utf8") > MAX_RERANK_STATE_BYTES || Buffer.byteLength(candidate["snippet"], "utf8") > MAX_RERANK_SNIPPET_BYTES)
161
+ return false;
162
+ ids.add(candidate["id"]);
163
+ }
164
+ return true;
165
+ }
166
+ function createTypeSafeReranker(options = {}) {
167
+ const transport = options.transport ?? fetchSystemOneTransport;
168
+ const timeoutMs = boundedPositiveInteger(options.timeoutMs, DEFAULT_RERANK_TIMEOUT_MS, MAX_RERANK_TIMEOUT_MS);
169
+ const maxResponseBytes = boundedPositiveInteger(options.maxResponseBytes, DEFAULT_RERANK_MAX_RESPONSE_BYTES, MAX_RERANK_RESPONSE_BYTES);
170
+ const concurrency = boundedPositiveInteger(options.concurrency, DEFAULT_RERANK_CONCURRENCY, MAX_RERANK_CONCURRENCY);
171
+ const environment = options.environment ?? process.env;
172
+ const apiKey = Object.hasOwn(environment, "TYPESAFE_API_KEY") ? environment["TYPESAFE_API_KEY"] : undefined;
173
+ return {
174
+ id: "typesafe",
175
+ rerank: async (request) => {
176
+ const started = performance.now();
177
+ const controller = new AbortController;
178
+ let attempted = 0;
179
+ let completed = 0;
180
+ let usageReceipts = 0;
181
+ let inputTokens = 0;
182
+ let outputTokens = 0;
183
+ let candidateCount = 0;
184
+ let observedModel;
185
+ let closed = false;
186
+ let firstFailure;
187
+ let timer;
188
+ let callerAbort;
189
+ let callerSignal;
190
+ let resolveStopped;
191
+ const stopped = new Promise((resolve) => {
192
+ resolveStopped = resolve;
193
+ });
194
+ const stop = (message) => {
195
+ firstFailure ??= message;
196
+ controller.abort();
197
+ resolveStopped?.();
198
+ };
199
+ const details = () => attempted === 0 ? {} : {
200
+ ...observedModel === undefined ? {} : { model: observedModel },
201
+ usage: Object.freeze({ inputTokens, outputTokens }),
202
+ accounting: Object.freeze({
203
+ candidates: candidateCount,
204
+ attempted,
205
+ completed,
206
+ elapsedMs: performance.now() - started,
207
+ usageComplete: usageReceipts === attempted && completed === attempted
208
+ })
209
+ };
210
+ const failed = (message) => ({
211
+ status: "failed",
212
+ message,
213
+ ...details()
214
+ });
215
+ try {
216
+ if (timeoutMs === null || maxResponseBytes === null || concurrency === null) {
217
+ return failed("TypeSafe rerank configuration was invalid.");
218
+ }
219
+ if (!validRerankRequest(request)) {
220
+ return failed("TypeSafe rerank request was malformed or exceeded its limits.");
221
+ }
222
+ candidateCount = request.candidates.length;
223
+ callerSignal = request.signal;
224
+ if (callerSignal?.aborted === true) {
225
+ return failed("TypeSafe rerank request was aborted.");
226
+ }
227
+ if (!validApiKey(apiKey)) {
228
+ return { status: "unavailable", message: "TYPESAFE_API_KEY is missing or invalid; the TypeSafe rerank lane is unavailable." };
229
+ }
230
+ if (candidateCount === 0)
231
+ return { status: "ready", ordering: [], probabilities: {} };
232
+ const encoder = new TextEncoder;
233
+ const decoder = new TextDecoder("utf-8", { fatal: true });
234
+ const bodies = [];
235
+ for (const candidate of request.candidates) {
236
+ const state = { query: request.query, candidate: {
237
+ key: candidate.id,
238
+ title: candidate.title,
239
+ path: candidate.path,
240
+ snippet: candidate.snippet
241
+ } };
242
+ if (encoder.encode(JSON.stringify(state)).byteLength > MAX_RERANK_STATE_BYTES) {
243
+ return failed(`TypeSafe rerank state exceeds the ${MAX_RERANK_STATE_BYTES}-byte limit.`);
244
+ }
245
+ bodies.push(encoder.encode(JSON.stringify({
246
+ model: DEFAULT_SYSTEMONE_MODEL,
247
+ state,
248
+ questions: { [RELEVANCE_QUESTION]: {
249
+ type: "noul",
250
+ instructions: RELEVANCE_INSTRUCTIONS,
251
+ criteria: RELEVANCE_CRITERIA
252
+ } }
253
+ })));
254
+ }
255
+ const deadline = started + timeoutMs;
256
+ const timeoutMessage = "TypeSafe rerank window exceeded its deadline.";
257
+ callerAbort = () => stop("TypeSafe rerank request was aborted.");
258
+ callerSignal?.addEventListener("abort", callerAbort, { once: true });
259
+ if (callerSignal?.aborted)
260
+ callerAbort();
261
+ timer = setTimeout(() => stop(timeoutMessage), Math.max(0, deadline - performance.now()));
262
+ const scored = await Promise.race([
263
+ mapWithConcurrency(bodies, concurrency, async (body) => {
264
+ if (closed || firstFailure !== undefined)
265
+ return { ok: false, message: firstFailure ?? timeoutMessage };
266
+ if (performance.now() >= deadline) {
267
+ stop(timeoutMessage);
268
+ return { ok: false, message: timeoutMessage };
269
+ }
270
+ attempted += 1;
271
+ let response;
272
+ try {
273
+ response = await transport({
274
+ url: DEFAULT_SYSTEMONE_ENDPOINT,
275
+ body,
276
+ headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json" },
277
+ timeoutMs: Math.max(1, Math.ceil(deadline - performance.now())),
278
+ maxResponseBytes,
279
+ signal: controller.signal
280
+ });
281
+ } catch {
282
+ if (!closed) {
283
+ completed += 1;
284
+ stop("TypeSafe rerank request failed.");
285
+ }
286
+ return { ok: false, message: firstFailure ?? "TypeSafe rerank request failed." };
287
+ }
288
+ if (closed)
289
+ return { ok: false, message: firstFailure ?? timeoutMessage };
290
+ completed += 1;
291
+ if (performance.now() >= deadline)
292
+ stop(timeoutMessage);
293
+ try {
294
+ if (!Number.isSafeInteger(response.status) || !(response.body instanceof Uint8Array) || response.body.byteLength > maxResponseBytes) {
295
+ stop("TypeSafe rerank transport returned a malformed or oversized response.");
296
+ return { ok: false, message: firstFailure };
297
+ }
298
+ let parsed;
299
+ try {
300
+ parsed = JSON.parse(decoder.decode(response.body));
301
+ } catch {
302
+ stop(response.status === 200 ? "TypeSafe rerank response was not valid UTF-8 JSON." : `TypeSafe rerank request returned HTTP ${response.status}.`);
303
+ return { ok: false, message: firstFailure };
304
+ }
305
+ const root = recordValue(parsed);
306
+ const usage = recordValue(root?.["usage"]);
307
+ const input = tokenCount(usage?.["input_tokens"]);
308
+ const output = tokenCount(usage?.["output_tokens"]);
309
+ if (usage !== null && hasExactKeys(usage, ["input_tokens", "output_tokens"]) && input !== null && output !== null) {
310
+ if (inputTokens + input > 1e9 || outputTokens + output > 1e9) {
311
+ stop("TypeSafe rerank aggregate usage exceeded its limits.");
312
+ return { ok: false, message: firstFailure };
313
+ }
314
+ inputTokens += input;
315
+ outputTokens += output;
316
+ usageReceipts += 1;
317
+ }
318
+ if (acceptedResponseModel(root?.["model"]))
319
+ observedModel = DEFAULT_SYSTEMONE_MODEL;
320
+ if (response.status !== 200) {
321
+ stop(`TypeSafe rerank request returned HTTP ${response.status}.`);
322
+ return { ok: false, message: firstFailure };
323
+ }
324
+ const answer = parseSystemOneResponse(parsed);
325
+ if (answer === null) {
326
+ stop("TypeSafe rerank response was malformed.");
327
+ return { ok: false, message: firstFailure };
328
+ }
329
+ return { ok: true, ...answer };
330
+ } catch {
331
+ stop("TypeSafe rerank transport returned a malformed response.");
332
+ return { ok: false, message: firstFailure };
333
+ }
334
+ }),
335
+ stopped.then(() => {
336
+ return;
337
+ })
338
+ ]);
339
+ closed = true;
340
+ if (firstFailure !== undefined)
341
+ return failed(firstFailure);
342
+ if (scored === undefined || scored.some((entry) => !entry.ok)) {
343
+ return failed("TypeSafe rerank result was incomplete.");
344
+ }
345
+ const probabilities = Object.create(null);
346
+ for (const [index, entry] of scored.entries()) {
347
+ const candidate = request.candidates[index];
348
+ if (candidate === undefined || !entry.ok)
349
+ return failed("TypeSafe rerank result was incomplete.");
350
+ probabilities[candidate.id] = entry.noul;
351
+ }
352
+ const ordering = request.candidates.toSorted((left, right) => (probabilities[right.id] ?? -1) - (probabilities[left.id] ?? -1) || left.baselineRank - right.baselineRank || left.id.localeCompare(right.id)).map(({ id }) => id);
353
+ return { status: "ready", ordering: Object.freeze(ordering), probabilities, ...details() };
354
+ } catch {
355
+ return failed("TypeSafe rerank request was malformed or failed.");
356
+ } finally {
357
+ closed = true;
358
+ if (timer !== undefined)
359
+ clearTimeout(timer);
360
+ if (callerAbort !== undefined)
361
+ callerSignal?.removeEventListener("abort", callerAbort);
362
+ controller.abort();
363
+ }
364
+ }
365
+ };
366
+ }
367
+
368
+ export { DEFAULT_SYSTEMONE_ENDPOINT, DEFAULT_SYSTEMONE_MODEL, createTypeSafeReranker };
@@ -5,34 +5,34 @@ import {
5
5
  MAX_SEARCH_RESULTS,
6
6
  openKnowledgeBase,
7
7
  validateKnowledgeBaseSearchHistory
8
- } from "./index-vdw5yjfa.js";
8
+ } from "./index-q7tbg07z.js";
9
9
  import {
10
10
  expandSearchRequest,
11
11
  parseSearchRules
12
12
  } from "./index-adx6khj5.js";
13
- import {
14
- scanVault
15
- } from "./index-0k2x4nn9.js";
16
13
  import {
17
14
  indexGitHistory
18
15
  } from "./index-1gwbassd.js";
19
- import {
20
- MAX_ATTACHMENT_REFERENCES,
21
- validateMarkdownAttachments
22
- } from "./index-x3fthpsc.js";
23
16
  import {
24
17
  validateSearchQuery
25
- } from "./index-why54q5p.js";
18
+ } from "./index-vnybgywh.js";
19
+ import {
20
+ scanVault
21
+ } from "./index-233z9wmn.js";
26
22
  import {
27
23
  validateQueryOptions
28
24
  } from "./index-48pz4jpc.js";
25
+ import {
26
+ MAX_ATTACHMENT_REFERENCES,
27
+ validateMarkdownAttachments
28
+ } from "./index-x3fthpsc.js";
29
29
  import {
30
30
  documentIdState,
31
31
  parseQualifiedDocumentUri,
32
32
  parseVaultKey,
33
33
  portfolioDocumentIdentity,
34
34
  portfolioVaultIdentity
35
- } from "./index-ekpwvbra.js";
35
+ } from "./index-qbssx940.js";
36
36
 
37
37
  // src/portfolio.ts
38
38
  import { createHash as createHash2 } from "crypto";
@@ -18,7 +18,10 @@ import {
18
18
  inspectClipEnvironment,
19
19
  renderAdapterCapabilities,
20
20
  renderDoctorReport
21
- } from "./index-van48n3g.js";
21
+ } from "./index-fc4dr114.js";
22
+ import {
23
+ cloneBrowserProfile
24
+ } from "./index-5n05se68.js";
22
25
  import {
23
26
  acquireBrowser,
24
27
  acquireCookieHttp,
@@ -26,7 +29,7 @@ import {
26
29
  acquireFile,
27
30
  acquireHttp,
28
31
  assertSafePersistentProfile
29
- } from "./index-jzcws0zn.js";
32
+ } from "./index-g5vsqmdy.js";
30
33
  import {
31
34
  CONTENT_REWRITE_TRUNCATION_WARNING,
32
35
  buildClipMarkdown,
@@ -38,6 +41,14 @@ import {
38
41
  rewriteContentWithStatus,
39
42
  slugify
40
43
  } from "./index-hgve9rh2.js";
44
+ import {
45
+ MAX_COOKIE_BYTES,
46
+ filterCookieProviderResult,
47
+ filterCookies,
48
+ readCookieFile,
49
+ renderCookieHeader,
50
+ renderNetscapeCookieJar
51
+ } from "./index-2gv8y733.js";
41
52
  import {
42
53
  startNetworkProxy
43
54
  } from "./index-w2zc0vwa.js";
@@ -63,21 +74,10 @@ import {
63
74
  sanitizeArtifactUrl,
64
75
  writeCaptureBundle
65
76
  } from "./index-mxxxytys.js";
66
- import {
67
- MAX_COOKIE_BYTES,
68
- filterCookieProviderResult,
69
- filterCookies,
70
- readCookieFile,
71
- renderCookieHeader,
72
- renderNetscapeCookieJar
73
- } from "./index-2gv8y733.js";
74
77
  import {
75
78
  sanitizeTerminalLine,
76
79
  sanitizeTerminalText
77
80
  } from "./index-1xxnjn0d.js";
78
- import {
79
- cloneBrowserProfile
80
- } from "./index-5n05se68.js";
81
81
 
82
82
  // src/clip/capture.ts
83
83
  import {
@@ -1,20 +1,20 @@
1
1
  // @bun
2
+ import {
3
+ percolateVault
4
+ } from "./index-jk1sgx36.js";
2
5
  import {
3
6
  createGraphSnapshot,
4
7
  openGraphAuthority
5
- } from "./index-bcfn9xah.js";
8
+ } from "./index-xv80vzfp.js";
6
9
  import {
7
10
  GraphAuthorityError,
8
11
  validateGraphPercolationOptions
9
- } from "./index-11621h23.js";
10
- import {
11
- percolateVault
12
- } from "./index-nd6nynv2.js";
12
+ } from "./index-tf4wzjew.js";
13
13
  import {
14
14
  analyzeVault,
15
15
  lookupNote,
16
16
  parseNote
17
- } from "./index-ekpwvbra.js";
17
+ } from "./index-qbssx940.js";
18
18
 
19
19
  // src/graph-percolation.ts
20
20
  async function percolateWithGraph(snapshot, options) {
@@ -7,7 +7,7 @@ import {
7
7
  isCanonicalRelationPredicate,
8
8
  parseDocumentId,
9
9
  parseQualifiedDocumentUri
10
- } from "./index-ekpwvbra.js";
10
+ } from "./index-qbssx940.js";
11
11
 
12
12
  // src/authoring-model.ts
13
13
  import { createHash } from "crypto";
@@ -443,6 +443,25 @@ function normalizedRequestedBody(body) {
443
443
  `) ? body : `${body}
444
444
  `;
445
445
  }
446
+ function renderUpdatedNoteBody(snapshot, parts, body) {
447
+ if (typeof body !== "string")
448
+ throw new TypeError("a note body must be a string");
449
+ if (Buffer.byteLength(body, "utf8") > MAX_NOTE_BYTES) {
450
+ throw new RangeError("the note body is too large for bounded authoring");
451
+ }
452
+ if (Buffer.from(body, "utf8").toString("utf8") !== body) {
453
+ throw new TypeError("a note body must contain well-formed Unicode");
454
+ }
455
+ const normalized = normalizedRequestedBody(body);
456
+ if (!parts.hadFrontmatter) {
457
+ if (frontmatter(normalized, snapshot.relativePath).hadFrontmatter) {
458
+ throw new TypeError("a body update cannot introduce frontmatter into a note");
459
+ }
460
+ return normalized;
461
+ }
462
+ const header = snapshot.content.slice(0, snapshot.content.length - parts.bodySuffix.length);
463
+ return `${header}${parts.newline}${parts.newline}${normalized}`;
464
+ }
446
465
  function renderCreatedNote(input, documentId) {
447
466
  const title = validateTitle(input.title);
448
467
  const type = validateType(input.type);
@@ -1158,6 +1177,35 @@ function editNoteRelationProgram(platform, operation, root, sourceIdInput, predi
1158
1177
  }), (lock) => authoringNative(() => lock.release()));
1159
1178
  });
1160
1179
  }
1180
+ function updateNoteBodyProgram(platform, root, idInput, body, options) {
1181
+ return Effect2.gen(function* () {
1182
+ const id = yield* authoringSync(() => canonicalNoteId(idInput));
1183
+ const expected = yield* authoringSync(() => {
1184
+ if (typeof options?.expectedRevision !== "string") {
1185
+ throw new TypeError("expectedRevision is required for a note body update");
1186
+ }
1187
+ return requireRevision(options.expectedRevision);
1188
+ });
1189
+ const vault = yield* authoringNative(() => platform.resolveVault(root));
1190
+ const dependencies = yield* authoringSync(() => platform.dependenciesFor(options.dependencies));
1191
+ return yield* authoringResource(authoringNative(() => platform.acquireNoteLock(vault.root, id, options.lock)), (lock) => Effect2.gen(function* () {
1192
+ yield* authoringNative(() => platform.recoverInterruptedAuthoring(vault, id, lock));
1193
+ const source = yield* authoringNative(() => platform.readSnapshot(vault, id));
1194
+ yield* authoringSync(() => assertExpected(source, expected));
1195
+ const parts = yield* authoringSync(() => frontmatter(source.content, source.relativePath));
1196
+ const identity = yield* authoringSync(() => existingDocumentId(parts));
1197
+ if (identity.kind === "invalid")
1198
+ return yield* fail(new TypeError("the note has an invalid document_id"));
1199
+ const documentId = identity.kind === "valid" ? identity.documentId : undefined;
1200
+ const relations = yield* authoringSync(() => relationsFromParts(parts, source.relativePath));
1201
+ const content = yield* authoringSync(() => renderUpdatedNoteBody(source, parts, body));
1202
+ if (content === source.content)
1203
+ return yield* authoringSync(() => noteResult(source, relations, false, documentId));
1204
+ const revision = yield* installNote(platform, vault, id, content, source, lock, dependencies);
1205
+ return yield* authoringSync(() => noteResult({ relativePath: source.relativePath, revision }, relations, true, documentId));
1206
+ }), (lock) => authoringNative(() => lock.release()));
1207
+ });
1208
+ }
1161
1209
 
1162
1210
  // src/authoring.ts
1163
1211
  async function noteRevision(root, id) {
@@ -1179,6 +1227,9 @@ async function createNote(root, input, options = {}) {
1179
1227
  async function createConceptNote(root, input, options = {}) {
1180
1228
  return createNote(root, { ...input, type: "concept" }, options);
1181
1229
  }
1230
+ async function updateNoteBody(root, id, body, options) {
1231
+ return runAuthoring(updateNoteBodyProgram(nativeAuthoringPlatform, root, id, body, options));
1232
+ }
1182
1233
  async function addNoteRelation(root, sourceId, predicate, targetId, options = {}) {
1183
1234
  return runAuthoring(editNoteRelationProgram(nativeAuthoringPlatform, "add", root, sourceId, predicate, targetId, options));
1184
1235
  }
@@ -1186,4 +1237,4 @@ async function removeNoteRelation(root, sourceId, predicate, targetId, options =
1186
1237
  return runAuthoring(editNoteRelationProgram(nativeAuthoringPlatform, "remove", root, sourceId, predicate, targetId, options));
1187
1238
  }
1188
1239
 
1189
- export { InvalidCanonicalNoteIdError, NoteRevisionConflictError, NoteAlreadyExistsError, NoteRecoveryRequiredError, canonicalNoteId, canonicalRelationTarget, normalizeRelationPredicate, noteRevision, listNoteRelations, createNote, createConceptNote, addNoteRelation, removeNoteRelation };
1240
+ export { InvalidCanonicalNoteIdError, NoteRevisionConflictError, NoteAlreadyExistsError, NoteRecoveryRequiredError, canonicalNoteId, canonicalRelationTarget, normalizeRelationPredicate, noteRevision, listNoteRelations, createNote, createConceptNote, updateNoteBody, addNoteRelation, removeNoteRelation };
@@ -1,11 +1,13 @@
1
1
  // @bun
2
2
  import {
3
- findKbPackageRoot,
4
3
  isolatedAgentBrowserEnvironment
5
- } from "./index-jzcws0zn.js";
4
+ } from "./index-g5vsqmdy.js";
6
5
  import {
7
6
  BoundedByteBuffer
8
7
  } from "./index-gh719d91.js";
8
+ import {
9
+ findKbPackageRoot
10
+ } from "./index-4knsp9qj.js";
9
11
 
10
12
  // src/clip/doctor.ts
11
13
  import { chmodSync, existsSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "fs";