@cerebriline/core 4.100.240 → 4.100.242

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 (64) hide show
  1. package/assets/skills/README.md +14 -0
  2. package/assets/skills/build-project/SKILL.md +103 -0
  3. package/assets/skills/docker-compose-deploy/SKILL.md +239 -0
  4. package/assets/skills/librarian/SKILL.md +177 -0
  5. package/assets/skills/mandatory-qa-prompt-and-issue-resolution/SKILL.md +58 -0
  6. package/assets/skills/run-project/SKILL.md +103 -0
  7. package/assets/skills/sdd-discuss/SKILL.md +129 -0
  8. package/assets/skills/sdd-execute/SKILL.md +146 -0
  9. package/assets/skills/sdd-plan/SKILL.md +140 -0
  10. package/assets/skills/sdd-quick/SKILL.md +40 -0
  11. package/assets/skills/sdd-status/SKILL.md +75 -0
  12. package/assets/skills/sdd-verify/SKILL.md +122 -0
  13. package/assets/skills/sdd-wizard/SKILL.md +105 -0
  14. package/assets/skills/tdd-coverage/SKILL.md +88 -0
  15. package/assets/skills/tdd-gen/SKILL.md +82 -0
  16. package/assets/skills/tdd-test/SKILL.md +61 -0
  17. package/assets/skills/tdd-wizard/SKILL.md +162 -0
  18. package/dist/document-reader-child.js +23 -0
  19. package/dist/extensions/config/bundled-skills.d.ts +24 -0
  20. package/dist/extensions/config/index.d.ts +2 -1
  21. package/dist/extensions/config/unified-config-file-watcher.d.ts +15 -0
  22. package/dist/extensions/config/user-instruction-config-loader.d.ts +15 -0
  23. package/dist/extensions/tools/executors/document/ebook.d.ts +10 -0
  24. package/dist/extensions/tools/executors/document/formats.d.ts +25 -0
  25. package/dist/extensions/tools/executors/document/ocr.d.ts +8 -0
  26. package/dist/extensions/tools/executors/document/read-job.d.ts +68 -0
  27. package/dist/extensions/tools/executors/document/read-process.d.ts +52 -0
  28. package/dist/extensions/tools/executors/document/read-protocol.d.ts +65 -0
  29. package/dist/extensions/tools/executors/document/recognition.d.ts +14 -5
  30. package/dist/extensions/tools/executors/document-extract.d.ts +120 -1
  31. package/dist/extensions/tools/librarian-tools.d.ts +32 -0
  32. package/dist/extensions/tools/library-import-run.d.ts +79 -0
  33. package/dist/extensions/tools/library-tools.d.ts +88 -0
  34. package/dist/extensions/tools/memory-tools.d.ts +41 -0
  35. package/dist/extensions/tools/sdd-tool.d.ts +215 -0
  36. package/dist/extensions/tools/team/create-agent-tool.d.ts +5 -4
  37. package/dist/hub/daemon/entry.js +607 -603
  38. package/dist/hub/index.js +595 -591
  39. package/dist/index.d.ts +17 -1
  40. package/dist/index.js +1080 -695
  41. package/dist/services/global-settings.d.ts +9 -0
  42. package/dist/services/llms/provider-settings.d.ts +15 -15
  43. package/dist/services/retrieval/catalogue.d.ts +397 -0
  44. package/dist/services/retrieval/chunker.d.ts +44 -0
  45. package/dist/services/retrieval/embedding-client.d.ts +78 -0
  46. package/dist/services/retrieval/fingerprint.d.ts +21 -0
  47. package/dist/services/retrieval/firecrawl.d.ts +77 -0
  48. package/dist/services/retrieval/lancedb-runtime.d.ts +84 -0
  49. package/dist/services/retrieval/lancedb-runtime.manifest.d.ts +17 -0
  50. package/dist/services/retrieval/library-store.d.ts +148 -0
  51. package/dist/services/retrieval/library.d.ts +139 -0
  52. package/dist/services/retrieval/memory-recall.d.ts +97 -0
  53. package/dist/services/retrieval/memory.d.ts +184 -0
  54. package/dist/services/retrieval/retrieve.d.ts +85 -0
  55. package/dist/services/retrieval/running-heads.d.ts +38 -0
  56. package/dist/services/retrieval/tar-extract.d.ts +14 -0
  57. package/dist/services/retrieval/tar-write.d.ts +20 -0
  58. package/dist/services/retrieval/vector-index.d.ts +82 -0
  59. package/dist/services/sdd/sdd-engine.d.ts +248 -0
  60. package/dist/services/telemetry/index.js +1 -1
  61. package/dist/types/config.d.ts +7 -0
  62. package/dist/types/session.d.ts +2 -0
  63. package/package.json +4 -4
  64. package/dist/extensions/tools/code-intel.d.ts +0 -131
@@ -0,0 +1,162 @@
1
+ ---
2
+ name: tdd-wizard
3
+ description: >-
4
+ Guides the user into test-driven development from the start: learns about
5
+ the project, takes an existing specification or writes one with the user
6
+ through questions about goals and scope, then develops the test cases with
7
+ them, generates the tests, validates them and writes them to the project.
8
+ Ends by offering to carry on with the implementation, test run and coverage
9
+ phases or to leave those to the user. Use when the user wants to start a
10
+ project or a feature test-first, asks for a TDD wizard, or wants a
11
+ specification turned into tests.
12
+ disabled: true
13
+ ---
14
+
15
+ # Skill: TDD Wizard
16
+
17
+ Takes the user from an idea to a specification and a set of tests that describe it, ready for the code to be written against them. It is a guided conversation: the user decides, this skill asks, proposes, writes and checks.
18
+
19
+ Part of the TDD set: `tdd-gen` (implements from tests), `tdd-test` (runs them), `tdd-coverage` (finds what is untested). The wizard works when those are off.
20
+
21
+ ## How to conduct it
22
+
23
+ - **One stage at a time, and stop at each gate.** Every stage ends with something the user confirms before the next begins. Do not run ahead.
24
+ - **Ask one question at a time**, or a small group about one topic. Where the likely answers are few, offer them as choices, with your recommendation first. Never send a questionnaire.
25
+ - **Do not ask what the repo can answer.** Read first.
26
+ - **Propose, do not interrogate.** When the user is unsure, suggest a concrete answer for them to accept or change.
27
+ - **Write no implementation code** in this skill. Its output is the specification and the tests.
28
+ - If the user wants to skip a stage or already has its result, take what they have and move on.
29
+
30
+ Say at the start, in two or three lines, what the stages are and that they can stop after any of them.
31
+
32
+ ## Stage 1: The project
33
+
34
+ Read before asking: the README, the manifest (`package.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `*.csproj`, ...), the folder layout, the existing tests and their config.
35
+
36
+ Establish:
37
+
38
+ - **new or existing:** an empty or near-empty repo, or a feature for a project that already has code;
39
+ - **language and test framework.** Existing project: the ones it uses, and how its tests are named, placed and written. New project: ask for the language, then propose the framework that is the default for it (Vitest for TypeScript or JavaScript, pytest for Python, the built-in runner for Go and Rust, xUnit for .NET, JUnit for Java);
40
+ - **where tests go**, by the project's convention or the framework's;
41
+ - **what this session is about:** the whole project, or one feature of it.
42
+
43
+ **Gate:** state what you found in a few lines and have the user confirm or correct it.
44
+
45
+ ## Stage 2: The specification
46
+
47
+ Ask first: **is there a specification already?** A file in the repo, a document to paste, an issue or a ticket.
48
+
49
+ **There is one.** Read it. Check it against the list below and ask only about what is missing or ambiguous. Offer to save an updated copy; do not rewrite the user's document unasked.
50
+
51
+ **There is none.** Build it with the user, a topic at a time:
52
+
53
+ 1. **Goal:** what this is for, in a sentence or two. Who or what uses it.
54
+ 2. **Scope:** what it does. Get this as concrete behaviours ("a user can reset a password by email"), not qualities ("secure", "fast").
55
+ 3. **Out of scope:** what it deliberately does not do. This is as valuable as the scope; ask for it explicitly.
56
+ 4. **Interfaces:** how it is used: functions, a command line, HTTP endpoints, a screen. The inputs and outputs of each.
57
+ 5. **Rules:** validation, limits, calculations, states and what moves between them.
58
+ 6. **Errors:** what can go wrong, and what must happen when it does.
59
+ 7. **Constraints:** platform, dependencies it must or must not use, performance or data limits that are real requirements.
60
+
61
+ Do not go deeper than the user's project needs: a small utility has a short specification.
62
+
63
+ Then write the specification file. Default path `docs/SPEC.md`, or beside the feature for a single feature; ask if the repo suggests another place. Use this shape:
64
+
65
+ ```markdown
66
+ # <Project or feature>: Specification
67
+
68
+ ## Goal
69
+ ## Scope
70
+ ## Out of scope
71
+ ## Interfaces
72
+ ## Requirements
73
+ - **R1** <one behaviour, stated so that a test can prove it>
74
+ - **R2** ...
75
+ ## Errors
76
+ - **E1** <condition> → <what must happen>
77
+ ## Constraints
78
+ ## Open questions
79
+ ```
80
+
81
+ Each requirement:
82
+
83
+ - is one behaviour, not several joined by "and";
84
+ - is **testable**: it names an input or situation and an observable result. "Handles large files well" is not a requirement; "reads a 1 GB file without holding it in memory" is;
85
+ - has an id (`R1`, `E1`) that the tests will refer to.
86
+
87
+ Anything the user could not decide goes under **Open questions**, not into a requirement as a guess.
88
+
89
+ **Gate:** show the specification and have the user approve it or change it. Tests are written against the approved text.
90
+
91
+ ## Stage 3: The test cases
92
+
93
+ Derive the cases from the specification, not from imagined code. For each requirement and each error:
94
+
95
+ - the **normal case**: typical input, the expected result;
96
+ - the **boundaries**: empty, zero, one, the maximum, the first and the last, exactly at a limit and just past it;
97
+ - the **invalid input** and the **error path** the specification names;
98
+ - for anything with state: the order of operations, and doing the same thing twice.
99
+
100
+ Present them as a table before writing any test code:
101
+
102
+ | ID | Requirement | Case | Input / situation | Expected |
103
+ |---|---|---|---|---|
104
+ | T1 | R1 | valid data | name and email given | user returned with an id |
105
+ | T2 | R1 | empty name | name is `""` | rejected: "Name is required" |
106
+
107
+ Then go through it with the user: is a case missing, is one wrong, is one not worth having? Ask in particular about expected values you had to assume, such as an exact error message, a rounding rule or an ordering. A specification gap found here goes back into the specification file.
108
+
109
+ Also settle with the user:
110
+
111
+ - **the interface the tests will call:** the names and signatures of the functions, classes or endpoints. The tests fix these, so they are a design decision; propose them and let the user adjust;
112
+ - **what is faked:** the clock, the network, the database, the file system. Prefer passing dependencies in over patching them.
113
+
114
+ **Gate:** the user approves the table and the interface.
115
+
116
+ ## Stage 4: Generate the tests
117
+
118
+ Write the tests in the project's framework and in the style of its existing tests.
119
+
120
+ - One test per row of the table, named for the behaviour ("rejects an empty name"), with the requirement id in the name or in a comment so each test traces back to the specification.
121
+ - **Test behaviour through the public interface.** Assert on results and on what a caller can observe, never on private fields or on how the code is built inside.
122
+ - Arrange, act, assert; one behaviour per test. Rows that differ only in data become one table-driven or parameterised test.
123
+ - **Deterministic:** no sleeping, no real clock, no real network, no dependence on test order or on the machine.
124
+ - Import from where the implementation will live, following the project's layout. The file need not exist yet.
125
+ - Do not write the implementation, and do not write tests for behaviour the specification does not contain.
126
+
127
+ ## Stage 5: Validate, then write
128
+
129
+ Before calling the tests done, check them:
130
+
131
+ 1. **Trace:** every requirement and every error in the specification has at least one test; every test points to a requirement. List anything uncovered.
132
+ 2. **They load:** run the test command (the `tdd-test` skill if it is enabled, else the framework's run-once form). The tests must be found and counted. A syntax error, a wrong import of the test framework itself or a config error is a defect in the tests: fix it.
133
+ 3. **They fail for the right reason.** With no implementation, each test should fail because the code under test is missing or does not yet do the thing. That is the correct result here, and it is the "red" that test-driven development starts from.
134
+ 4. **None passes already.** A test that passes with nothing implemented asserts nothing, or tests the wrong thing. Fix or remove it. (In an existing project a test may pass because the behaviour is already there; say which, and keep it.)
135
+ 5. **Expected values match the specification**, row by row. Do not validate tests by adjusting them until they agree with something else.
136
+
137
+ In some languages the test file cannot even compile until the names it uses exist (Go, Rust, Java, C#, TypeScript with type-checking in the test run). Then say so, and ask before creating the minimum that lets it compile: the declarations with bodies that only raise "not implemented". That is scaffolding, not implementation.
138
+
139
+ If a framework has to be installed or configured first, say what will be added and ask before changing the project.
140
+
141
+ Write the test files, then report:
142
+
143
+ - the specification file;
144
+ - the test files, with the number of tests in each;
145
+ - the trace: requirements to tests, and anything left open;
146
+ - the result of the run: how many were found, and that they fail because the implementation is missing.
147
+
148
+ ## Stage 6: What next
149
+
150
+ Offer the choice plainly:
151
+
152
+ 1. **Continue now:** implement against these tests (`tdd-gen`), run the whole suite (`tdd-test`), then check coverage (`tdd-coverage`). Stop after each for the user to look, unless they say to go straight through.
153
+ 2. **Take it from here themselves:** give the commands for each phase, so they can run them when they choose: implement from a test file with `tdd-gen` on that file, run tests with `tdd-test`, check coverage with `tdd-coverage`.
154
+ 3. **Stop here:** the specification and the tests are the deliverable.
155
+
156
+ If the user continues and one of those skills is not enabled, do the phase directly by the same rules: write the least code that makes the tests pass **without changing the tests**, run them until green, tidy up on green, then measure coverage and propose tests for what is below 80%.
157
+
158
+ When requirements change later, the order stays the same: the specification first, then the tests, then the code.
159
+
160
+ ## Credits
161
+
162
+ Written for Cerebriline, as the front end to the workflow described in "[Test-Driven Development with Claude Code: Practical Guide](https://aiskill.market/blog/tdd-with-claude-code)" by Duke Harewood (aiskill.market, January 28, 2026), whose `/tdd`, `/test` and `/coverage` commands are the basis of `tdd-gen`, `tdd-test` and `tdd-coverage`. The test-writing guidance in Stage 4 (behaviour over implementation, table-driven cases, injected dependencies, no timing) follows that article's patterns.
@@ -0,0 +1,23 @@
1
+ import{createRequire as F$}from"node:module";var D=F$(import.meta.url);import{mkdir as wJ,writeFile as yJ}from"node:fs/promises";import{join as W$}from"node:path";import xJ from"node:fs/promises";import{existsSync as PQ,readdirSync as v$,readFileSync as AQ,statSync as S$}from"node:fs";import*as u from"node:path";import{createHash as C$}from"node:crypto";import{inflateSync as R$}from"node:zlib";var N$=new Set(["image/png","image/jpeg","image/gif","image/webp"]),L$={"image/png":"png","image/jpeg":"jpg","image/gif":"gif","image/webp":"webp","image/bmp":"bmp","image/tiff":"tif","image/svg+xml":"svg","image/emf":"emf","image/wmf":"wmf","image/x-pict":"pict"};function j$(Q){let $=(q,...Z)=>Z.every((K,H)=>Q[q+H]===K);if($(0,137,80,78,71))return"image/png";if($(0,255,216,255))return"image/jpeg";if($(0,71,73,70,56))return"image/gif";if($(0,82,73,70,70)&&$(8,87,69,66,80))return"image/webp";if($(0,66,77))return"image/bmp";if($(0,73,73,42,0)||$(0,77,77,0,42))return"image/tiff";if($(40,32,69,77,70))return"image/emf";if($(0,215,205,198,154)||$(0,1,0,9,0))return"image/wmf";if($(10,0,17,2,255))return"image/x-pict";let J=Buffer.from(Q.subarray(0,256)).toString("utf8").trimStart();if(J.startsWith("<svg")||J.startsWith("<?xml")&&J.includes("<svg"))return"image/svg+xml";return}function T$(Q){if(Q[0]!==120||![1,94,156,218].includes(Q[1]??0))return Q;try{return new Uint8Array(R$(Q))}catch{return Q}}class BQ{linkDir;byHash=new Map;names=new Set;pending=[];constructor(Q="images"){this.linkDir=Q}add(Q){if(Q.data.byteLength===0)return;let $=T$(Q.data),J=C$("sha1").update($).digest("hex"),q=this.byHash.get(J);if(q)return q;let Z=j$($)??Q.mediaType??"application/octet-stream",K=L$[Z]??"bin",H=this.uniqueName(O$(Q.stem),K),Y={file:H,link:`${this.linkDir}/${H}`,mediaType:Z,bytes:$.byteLength,...Q.width?{width:Q.width}:{},...Q.height?{height:Q.height}:{},...Q.source?{source:Q.source}:{},...Q.alt?.trim()?{alt:Q.alt.trim()}:{},...N$.has(Z)||Z==="image/svg+xml"?{}:{notViewable:!0},sha1:J};return this.byHash.set(J,Y),this.pending.push({image:Y,data:$}),Y}get images(){return this.pending.map((Q)=>Q.image)}entries(){return this.pending}uniqueName(Q,$){let J=`${Q}.${$}`;for(let q=2;this.names.has(J);q++)J=`${Q}-${q}.${$}`;return this.names.add(J),J}}function O$(Q){return Q.replace(/\.[a-z0-9]{2,4}$/i,"").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)||"image"}function x(Q){return`![${(Q.alt??"").replace(/[[\]\n]/g," ").trim()}](${Q.link})`}var P$=/\.(png|jpe?g|gif|webp|bmp|svg|tiff?)$/i;function A$(Q){if(Q.length<90)return 0;let $=new DataView(Q.buffer,Q.byteOffset,Q.byteLength),J=$.getUint32(78);if(J+14>Q.length)return 0;return $.getUint16(J+12)}function I$(Q){let $=Buffer.from(Q.buffer,Q.byteOffset,Q.byteLength);return $.includes("META-INF/rights.xml")||$.includes("META-INF/license.lcpl")}function k$(Q){let $=Buffer.from(Q.buffer,Q.byteOffset,Q.byteLength);if($.length<22||$.readUInt32LE(0)!==67324752)return"it does not start as a ZIP archive, which every EPUB is";let J=$.lastIndexOf(Buffer.from([80,75,5,6]),$.length-22);if(J<0||J<$.length-22-65535)return`it ends before its index (${$.length.toLocaleString("en-US")} bytes), so it was cut short when it was copied, downloaded or unpacked`;let q=$.readUInt32LE(J+12),Z=$.readUInt32LE(J+16);if(Z!==4294967295&&q!==4294967295&&Z+q>J)return"its index points past the end of the file, so part of it is missing";return}var IQ=120000;async function $Q(Q){let $;try{return await Promise.race([Q,new Promise((J,q)=>{$=setTimeout(()=>q(Error(`The book could not be opened: the reader gave no answer in ${IQ/1000}s, which is what it does with a damaged file. Check that the file is complete.`)),IQ)})])}finally{clearTimeout($)}}function kQ(Q,$=0,J=[]){for(let q of Q){if(J.length>=200)break;let Z=String(q.label??"").trim();if(Z)J.push(`${" ".repeat($)}${Z}`);if(Array.isArray(q.children))kQ(q.children,$+1,J)}return J}function JQ(Q){if(typeof Q==="string")return Q.trim()||void 0;if(Array.isArray(Q))for(let $ of Q){let J=JQ(typeof $==="object"&&$!==null?$.contributor??$.name:$);if(J)return J}if(typeof Q==="object"&&Q!==null){let $=Q;return JQ($.contributor??$.name??$.value)}return}async function D$(Q){let{default:$}=await import("turndown"),{gfm:J}=await import("@joplin/turndown-plugin-gfm"),q=new $({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});return q.use(J),q.remove(["script","style","head"]),q.addRule("image",{filter:"img",replacement:(Z,K)=>{let H=K,Y=H.getAttribute("src")??"";return Q(Y,H.getAttribute("alt")??"")??""}}),q.addRule("svgImage",{filter:(Z)=>Z.nodeName.toLowerCase()==="image",replacement:(Z,K)=>{let H=K,Y=H.getAttribute("xlink:href")??H.getAttribute("href")??"";return Q(Y,"")??""}}),q}async function DQ(Q,$,J,q){if((J==="mobi"||J==="azw3")&&A$($)>1)throw Error("This Kindle book is DRM-protected. It can be read only in a Kindle app; nothing here can remove the protection.");if(J==="epub"&&I$($))throw Error("This EPUB is DRM-protected (Adobe ADEPT or Readium LCP). It can be read only in a reader app licensed for it.");if(J==="epub"){let U=k$($);if(U)throw Error(`This EPUB is damaged: ${U}. Nothing can be read from it; get the file again.`)}let Z=q.scratchDir,{initEpubFile:K}=await import("@lingo-reader/epub-parser"),{initFb2File:H}=await import("@lingo-reader/fb2-parser"),{initKf8File:Y,initMobiFile:X}=await import("@lingo-reader/mobi-parser"),B,F;if(J==="epub")B=await $Q(K(Q,Z)),F="lingo-reader (EPUB)";else if(J==="fb2")B=await $Q(H(Q,Z)),F="lingo-reader (FB2)";else{let[U,V]=J==="azw3"?[Y,X]:[X,Y];try{B=await $Q(U(Q,Z)),F=`lingo-reader (${U===Y?"KF8":"MOBI"})`}catch{B=await $Q(V(Q,Z)),F=`lingo-reader (${V===Y?"KF8":"MOBI"})`}}try{let U=new Map,V=0,G=await D$((L,T)=>{if(!q.wantImages||!L||/^(data:|https?:)/i.test(L))return;let S=L;try{S=decodeURI(L.replace(/^file:\/\//,""))}catch{}if(!u.isAbsolute(S)||!PQ(S))return;if(!U.has(S))U.set(S,q.images.add({data:AQ(S),stem:u.basename(S),source:`chapter ${V}`,...T?{alt:T}:{}}));let w=U.get(S);return w?x(w):void 0}),z=B.getSpine(),C=[],I=[];for(let L=0;L<z.length;L++){let T=L+1;if(q.selects&&!q.selects(T))continue;q.signal?.throwIfAborted(),V=T,q.onProgress?.({unit:"chapter",at:T,total:z.length,pictures:U.size}),C.push(T);let w=(await B.loadChapter(z[L].id))?.html??"",i=w?G.turndown(w).trim():"";if(i)I.push(i)}if(q.wantImages&&PQ(Z))for(let L of v$(Z,{recursive:!0})){let T=u.join(Z,L);if(!P$.test(L)||U.has(T)||!S$(T).isFile())continue;U.set(T,q.images.add({data:AQ(T),stem:u.basename(L)}))}let P=B.getMetadata()??{},v=JQ(P.title),b=JQ(P.creator??P.author),d=kQ(B.getToc()??[]);return{markdown:I.join(`
2
+
3
+ `),reader:F,...v&&v!=="Unknown"?{title:v}:{},...b&&b!=="Unknown"?{author:b}:{},units:{name:"chapter",total:z.length,read:C},...d.length?{contents:d}:{}}}finally{B.destroy()}}import*as WQ from"node:path";var M$={pdf:"PDF",docx:"Word document (DOCX)",pptx:"PowerPoint presentation (PPTX)",xlsx:"Excel workbook (XLSX)",odt:"OpenDocument text (ODT)",odp:"OpenDocument presentation (ODP)",ods:"OpenDocument spreadsheet (ODS)",odg:"OpenDocument drawing (ODG)",rtf:"Rich Text (RTF)",csv:"CSV",html:"HTML",epub:"EPUB ebook",mobi:"Mobipocket / Kindle ebook (MOBI)",azw3:"Kindle KF8 ebook (AZW3)",fb2:"FictionBook (FB2)",doc:"Word 97-2003 document (DOC)",xls:"Excel 97-2003 workbook (XLS)",ppt:"PowerPoint 97-2003 presentation (PPT)"},MQ={".pdf":"pdf",".docx":"docx",".docm":"docx",".dotx":"docx",".pptx":"pptx",".pptm":"pptx",".ppsx":"pptx",".xlsx":"xlsx",".xlsm":"xlsx",".odt":"odt",".odp":"odp",".ods":"ods",".odg":"odg",".rtf":"rtf",".csv":"csv",".html":"html",".htm":"html",".xhtml":"html",".epub":"epub",".mobi":"mobi",".prc":"mobi",".azw":"mobi",".azw3":"azw3",".kf8":"azw3",".fb2":"fb2",".doc":"doc",".dot":"doc",".xls":"xls",".ppt":"ppt",".pps":"ppt"},E$={".djvu":"DjVu has no JavaScript reader.",".djv":"DjVu has no JavaScript reader.",".chm":"Compiled HTML Help (CHM) has no JavaScript reader.",".lit":"Microsoft Reader (LIT) has no JavaScript reader.",".lrf":"Sony BBeB (LRF) has no JavaScript reader.",".kfx":"KFX is Amazon's DRM-bound format and cannot be read.",".pages":"Apple Pages files have no JavaScript reader; export them as DOCX or PDF.",".key":"Apple Keynote files have no JavaScript reader; export them as PPTX or PDF.",".numbers":"Apple Numbers files have no JavaScript reader; export them as XLSX or CSV.",".xlsb":"Binary Excel workbooks (XLSB) are not read; save the workbook as XLSX.",".wps":"Microsoft Works documents are not read; save them as DOCX.",".cbz":"Comic archives are not read yet.",".cbr":"Comic archives are not read yet."},oJ=Object.keys(MQ);function EQ(Q,$){let J=WQ.extname(Q).toLowerCase(),q=E$[J];if(q)return{unsupported:q};let Z=Buffer.from($.subarray(0,512)).toString("latin1"),K=MQ[J];if(Z.startsWith("%PDF"))return{format:"pdf"};if(Z.startsWith("{\\rtf"))return{format:"rtf"};if(Z.slice(60,68)==="BOOKMOBI")return{format:K==="azw3"?"azw3":"mobi"};let H=Z.startsWith("PK\x03\x04"),Y=Z.startsWith("ÐÏ\x11ࡱ\x1Aá");if(H){if(Z.includes("mimetypeapplication/epub+zip"))return{format:"epub"};let X=/mimetypeapplication\/vnd\.oasis\.opendocument\.(text|presentation|spreadsheet|graphics)/.exec(Z);if(X)return{format:{text:"odt",presentation:"odp",spreadsheet:"ods",graphics:"odg"}[X[1]]};if(K&&["docx","pptx","xlsx","epub","odt","odp","ods","odg"].includes(K))return{format:K};if(K==="doc")return{format:"docx"};if(K==="xls")return{format:"xlsx"};if(K==="ppt")return{format:"pptx"}}if(Y){if(K==="doc"||K==="xls"||K==="ppt")return{format:K};if(K==="docx")return{format:"doc"};if(K==="xlsx")return{format:"xls"};if(K==="pptx")return{format:"ppt"};return{unsupported:"This is an OLE compound file, but its extension does not say which Office program wrote it; rename it to .doc, .xls or .ppt."}}if(K==="fb2"||/<FictionBook[\s>]/.test(Z))return{format:"fb2"};if(K==="html"||K==="csv")return{format:K};if(K)return{unsupported:`The file is named as ${M$[K]} but its contents are not; it may be damaged or a different format.`};return{unsupported:`No reader for ${J||"files without an extension"}. Readable: PDF, DOCX/DOC, PPTX/PPT, XLSX/XLS, ODT/ODP/ODS/ODG, RTF, CSV, HTML, EPUB, MOBI/AZW/AZW3, FB2.`}}import{existsSync as hQ,readFileSync as c$}from"node:fs";import{dirname as cQ,join as bQ}from"node:path";import{fileURLToPath as g$}from"node:url";class t{__destroy_into_raw(){let Q=this.__wbg_ptr;return this.__wbg_ptr=0,xQ.unregister(this),Q}free(){let Q=this.__destroy_into_raw();W.__wbg_wasmdocument_free(Q,0)}formatName(){let Q,$;try{let Z=W.__wbindgen_add_to_stack_pointer(-16);W.wasmdocument_formatName(Z,this.__wbg_ptr);var J=R().getInt32(Z+0,!0),q=R().getInt32(Z+4,!0);return Q=J,$=q,h(J,q)}finally{W.__wbindgen_add_to_stack_pointer(16),W.__wbindgen_export3(Q,$,1)}}constructor(Q,$){try{let K=W.__wbindgen_add_to_stack_pointer(-16),H=wQ(Q,W.__wbindgen_export),Y=E,X=r($,W.__wbindgen_export,W.__wbindgen_export2),B=E;W.wasmdocument_new(K,H,Y,X,B);var J=R().getInt32(K+0,!0),q=R().getInt32(K+4,!0),Z=R().getInt32(K+8,!0);if(Z)throw M(q);return this.__wbg_ptr=J,xQ.register(this,this.__wbg_ptr,this),this}finally{W.__wbindgen_add_to_stack_pointer(16)}}plainText(){let Q,$;try{let Z=W.__wbindgen_add_to_stack_pointer(-16);W.wasmdocument_plainText(Z,this.__wbg_ptr);var J=R().getInt32(Z+0,!0),q=R().getInt32(Z+4,!0);return Q=J,$=q,h(J,q)}finally{W.__wbindgen_add_to_stack_pointer(16),W.__wbindgen_export3(Q,$,1)}}toHtml(){let Q,$;try{let Z=W.__wbindgen_add_to_stack_pointer(-16);W.wasmdocument_toHtml(Z,this.__wbg_ptr);var J=R().getInt32(Z+0,!0),q=R().getInt32(Z+4,!0);return Q=J,$=q,h(J,q)}finally{W.__wbindgen_add_to_stack_pointer(16),W.__wbindgen_export3(Q,$,1)}}toIr(){try{let q=W.__wbindgen_add_to_stack_pointer(-16);W.wasmdocument_toIr(q,this.__wbg_ptr);var Q=R().getInt32(q+0,!0),$=R().getInt32(q+4,!0),J=R().getInt32(q+8,!0);if(J)throw M($);return M(Q)}finally{W.__wbindgen_add_to_stack_pointer(16)}}toMarkdownWithImages(){let Q,$;try{let Z=W.__wbindgen_add_to_stack_pointer(-16);W.wasmdocument_toMarkdownWithImages(Z,this.__wbg_ptr);var J=R().getInt32(Z+0,!0),q=R().getInt32(Z+4,!0);return Q=J,$=q,h(J,q)}finally{W.__wbindgen_add_to_stack_pointer(16),W.__wbindgen_export3(Q,$,1)}}toMarkdown(){let Q,$;try{let Z=W.__wbindgen_add_to_stack_pointer(-16);W.wasmdocument_toMarkdown(Z,this.__wbg_ptr);var J=R().getInt32(Z+0,!0),q=R().getInt32(Z+4,!0);return Q=J,$=q,h(J,q)}finally{W.__wbindgen_add_to_stack_pointer(16),W.__wbindgen_export3(Q,$,1)}}}if(Symbol.dispose)t.prototype[Symbol.dispose]=t.prototype.free;class UQ{__destroy_into_raw(){let Q=this.__wbg_ptr;return this.__wbg_ptr=0,_Q.unregister(this),Q}free(){let Q=this.__destroy_into_raw();W.__wbg_wasmeditabledocument_free(Q,0)}constructor(Q,$){try{let K=W.__wbindgen_add_to_stack_pointer(-16),H=wQ(Q,W.__wbindgen_export),Y=E,X=r($,W.__wbindgen_export,W.__wbindgen_export2),B=E;W.wasmeditabledocument_new(K,H,Y,X,B);var J=R().getInt32(K+0,!0),q=R().getInt32(K+4,!0),Z=R().getInt32(K+8,!0);if(Z)throw M(q);return this.__wbg_ptr=J,_Q.register(this,this.__wbg_ptr,this),this}finally{W.__wbindgen_add_to_stack_pointer(16)}}replaceText(Q,$){try{let K=W.__wbindgen_add_to_stack_pointer(-16),H=r(Q,W.__wbindgen_export,W.__wbindgen_export2),Y=E,X=r($,W.__wbindgen_export,W.__wbindgen_export2),B=E;W.wasmeditabledocument_replaceText(K,this.__wbg_ptr,H,Y,X,B);var J=R().getInt32(K+0,!0),q=R().getInt32(K+4,!0),Z=R().getInt32(K+8,!0);if(Z)throw M(q);return J>>>0}finally{W.__wbindgen_add_to_stack_pointer(16)}}toBytes(){try{let K=W.__wbindgen_add_to_stack_pointer(-16);W.wasmeditabledocument_toBytes(K,this.__wbg_ptr);var Q=R().getInt32(K+0,!0),$=R().getInt32(K+4,!0),J=R().getInt32(K+8,!0),q=R().getInt32(K+12,!0);if(q)throw M(J);var Z=w$(Q,$).slice();return W.__wbindgen_export3(Q,$*1,1),Z}finally{W.__wbindgen_add_to_stack_pointer(16)}}}if(Symbol.dispose)UQ.prototype[Symbol.dispose]=UQ.prototype.free;function x$(){return{__proto__:null,"./office_oxide_bg.js":{__proto__:null,__wbg_Error_67e7344beaa85059:function($,J){let q=Error(h($,J));return y(q)},__wbg_String_8564e559799eccda:function($,J){let q=String(s(J)),Z=r(q,W.__wbindgen_export,W.__wbindgen_export2),K=E;R().setInt32($+4,K,!0),R().setInt32($+0,Z,!0)},__wbg___wbindgen_throw_5d9e815e6fdf150f:function($,J){throw Error(h($,J))},__wbg_new_bebc3f4757acf305:function(){return y({})},__wbg_new_ffa92086ea89f79c:function(){return y([])},__wbg_set_13d25b81ab403f5e:function($,J,q){s($)[J>>>0]=M(q)},__wbg_set_6be42768c690e380:function($,J,q){s($)[M(J)]=M(q)},__wbindgen_generic_0000000000000001:function($){return y($)},__wbindgen_generic_0000000000000002:function($){return y($)},__wbindgen_generic_0000000000000003:function($,J){let q=h($,J);return y(q)},__wbindgen_generic_0000000000000004:function($){let J=BigInt.asUintN(64,$);return y(J)},__wbindgen_object_clone_ref:function($){let J=s($);return y(J)},__wbindgen_object_drop_ref:function($){M($)}}}}var xQ=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((Q)=>W.__wbg_wasmdocument_free(Q,1)),_Q=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((Q)=>W.__wbg_wasmeditabledocument_free(Q,1));function y(Q){if(o===_.length)_.push(_.length+1);let $=o;return o=_[$],_[$]=Q,$}function _$(Q){if(Q<1028)return;_[Q]=o,o=Q}function w$(Q,$){return Q=Q>>>0,g().subarray(Q/1,Q/1+$)}var c=null;function R(){if(c===null||c.buffer.detached===!0||c.buffer.detached===void 0&&c.buffer!==W.memory.buffer)c=new DataView(W.memory.buffer);return c}function h(Q,$){return h$(Q>>>0,$)}var n=null;function g(){if(n===null||n.byteLength===0)n=new Uint8Array(W.memory.buffer);return n}function s(Q){return _[Q]}var _=Array(1024).fill(void 0);_.push(void 0,null,!0,!1);var o=_.length;function wQ(Q,$){let J=$(Q.length*1,1)>>>0;return g().set(Q,J/1),E=Q.length,J}function r(Q,$,J){if(J===void 0){let Y=a.encode(Q),X=$(Y.length,1)>>>0;return g().subarray(X,X+Y.length).set(Y),E=Y.length,X}let q=Q.length,Z=$(q,1)>>>0,K=g(),H=0;for(;H<q;H++){let Y=Q.charCodeAt(H);if(Y>127)break;K[Z+H]=Y}if(H!==q){if(H!==0)Q=Q.slice(H);Z=J(Z,q,q=H+Q.length*3,1)>>>0;let Y=g().subarray(Z+H,Z+q),X=a.encodeInto(Q,Y);H+=X.written,Z=J(Z,q,H,1)>>>0}return E=H,Z}function M(Q){let $=s(Q);return _$(Q),$}var qQ=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});qQ.decode();var y$=2146435072,GQ=0;function h$(Q,$){if(GQ+=$,GQ>=y$)qQ=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),qQ.decode(),GQ=$;return qQ.decode(g().subarray(Q,Q+$))}var a=new TextEncoder;if(!("encodeInto"in a))a.encodeInto=function(Q,$){let J=a.encode(Q);return $.set(J),{read:Q.length,written:J.length}};var E=0,b$,f$,W;function u$(Q,$){return f$=Q,W=Q.exports,b$=$,c=null,n=null,W}function yQ(Q){if(W!==void 0)return W;if(Q!==void 0)if(Object.getPrototypeOf(Q)===Object.prototype)({module:Q}=Q);else console.warn("using deprecated parameters for `initSync()`; pass a single object instead");let $=x$();if(!(Q instanceof WebAssembly.Module))Q=new WebAssembly.Module(Q);let J=new WebAssembly.Instance(Q,$);return u$(J,Q)}var fQ="office_oxide_bg.wasm",uQ=!1;function l$(Q=m$()){let $=bQ(Q,"office-oxide",fQ);if(hQ($))return $;let J=Q;for(let q=0;q<7;q++){let Z=bQ(J,"assets","office-oxide",fQ);if(hQ(Z))return Z;let K=cQ(J);if(K===J)break;J=K}return}function m$(){try{return cQ(g$(import.meta.url))}catch{return"."}}function gQ(Q,$){if(!uQ){let J=l$();if(!J)throw Error("The reader for Word, Excel and PowerPoint 97-2003 files is missing from this installation (office_oxide_bg.wasm was not found).");yQ({module:c$(J)}),uQ=!0}return new t(Q,$)}var p$=/\[image-base64:([A-Za-z0-9+/=\s]+)\]/g;function d$(Q){return Q.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g,"")}function i$(Q,$){let J=new DataView(Q.buffer,Q.byteOffset,Q.byteLength),q=$+8;while(q+12<=Q.length){let Z=J.getUint32(q),K=String.fromCharCode(...Q.subarray(q+4,q+8));if(q+=12+Z,K==="IEND")return q-$;if(Z>Q.length)return}return}function n$(Q,$){let J=$+2;while(J+4<=Q.length){if(Q[J]!==255)return;let q=Q[J+1];if(q===217)return J+2-$;if(q===218){J+=2+(Q[J+2]<<8|Q[J+3]);while(J+1<Q.length){if(Q[J]===255){let Z=Q[J+1];if(Z===217)return J+2-$;if(Z!==0&&(Z<208||Z>215))break}J++}continue}J+=2+(Q[J+2]<<8|Q[J+3])}return}async function s$(Q){let $=await import("cfb"),J=$.default??$,q;try{q=J.read(Buffer.from(Q),{type:"buffer"})}catch{return[]}let Z=[];for(let K of q.FileIndex){let H=K.content;if(K.type!==2||!H||H.length<64)continue;let Y=H instanceof Uint8Array?H:new Uint8Array(H);for(let X=0;X+8<Y.length;X++){let B;if(Y[X]===137&&Y[X+1]===80&&Y[X+2]===78&&Y[X+3]===71)B=i$(Y,X);else if(Y[X]===255&&Y[X+1]===216&&Y[X+2]===255)B=n$(Y,X);if(B&&B>64&&X+B<=Y.length)Z.push(Y.slice(X,X+B)),X+=B-1}}return Z}async function lQ(Q,$,J){let q=gQ(Q,$),Z;try{Z=q.toMarkdownWithImages()}finally{q.free()}let K=0;Z=Z.replace(p$,(Y,X)=>{if(!J.wantImages)return"";K++;let B=J.images.add({data:Buffer.from(X.replace(/\s/g,""),"base64"),stem:`${$}-image-${K}`});return B?x(B):""}),Z=d$(Z).replace(/\n{3,}/g,`
4
+
5
+ `).trim();let H=[];if(J.wantImages&&$==="doc"){let Y=[];for(let X of await s$(Q)){let B=J.images.images.length;K++;let F=J.images.add({data:X,stem:`${$}-image-${K}`});if(F&&J.images.images.length>B)Y.push(x(F))}if(Y.length)Z+=`
6
+
7
+ ## Pictures not placed in the text
8
+
9
+ ${Y.join(`
10
+
11
+ `)}`,H.push(`${Y.length} picture(s) were found in the file but not at a place in its text; they are listed at the end.`)}return{markdown:Z,reader:"office_oxide",...H.length?{notes:H}:{}}}var o$={maxUncompressedBytes:268435456,maxZipEntries:20000},r$={pptx:{node:"slide",unit:"slide"},odp:{node:"slide",unit:"slide"},xlsx:{node:"sheet",unit:"sheet"},ods:{node:"sheet",unit:"sheet"}};async function a$(){let Q=await import("officeparser");return Q.OfficeParser??Q.default}function t$(Q,$){let J=Q?.message??"";if(!/password|encrypt/i.test(J))return;return Error($?"The document's password is not the one given in `password`.":"The document is password-protected. Ask the user for the password and call again with `password`.")}function e$(Q){return Q.replace(/^\s*---\n[\s\S]*?\n---\n/,"").trim()}async function mQ(Q,$,J){let q=await a$(),Z;try{Z=await q.parseOffice(Buffer.from(Q),{fileType:$,extractAttachments:J.wantImages,decompressionLimits:o$,...J.password?{password:J.password}:{}})}catch(V){throw t$(V,J.password)??V}let K=r$[$],H;if(K){let V=Z.content.filter((z)=>z.type===K.node),N=[],G=new Set;V.forEach((z,C)=>{if(!J.selects||J.selects(C+1))N.push(C+1),G.add(z)}),Z.content=Z.content.filter((z)=>z.type!==K.node||G.has(z)),H={name:K.unit,total:V.length,read:N}}let Y=new Map,X=(V,N)=>{if(Y.has(V))return Y.get(V);let G=Z.attachments?.find((C)=>C.name===V),z=G?J.images.add({data:Buffer.from(G.data,"base64"),stem:V,mediaType:G.mimeType,...N?{alt:N}:{}}):void 0;return Y.set(V,z),z},B=await Z.to("md",{mdConfig:{dialect:"github",fallbackToHtml:{textFormatting:!1,alignment:!1,anchors:!1,tables:!0,embeds:!1,cellLineBreaks:!0}},onNode:(V)=>{if(V.type!=="image")return;if(!J.wantImages)return!1;let N=V.metadata??{},G=N.attachmentName?X(N.attachmentName,N.altText):void 0;return G?x(G):!1}}),F=e$(String(B.value??""));if($==="rtf")F=F.replace(/^[ ]*\t[ \t]*(?![-*+] |\d+[.)] )/gm,"");if(J.wantImages){for(let V of Z.attachments??[])if(V.type==="image")X(V.name)}let U=Z.metadata??{};return{markdown:F,reader:"officeparser",...U.title?.trim()?{title:U.title.trim()}:{},...U.author?.trim()?{author:U.author.trim()}:{},...H?{units:H}:{}}}import{existsSync as VQ}from"node:fs";import{createRequire as QJ}from"node:module";import{dirname as pQ,join as l}from"node:path";import{fileURLToPath as $J}from"node:url";function FQ(){try{return pQ($J(import.meta.url))}catch{return"."}}function JJ(Q){try{let $=QJ(l(FQ(),"noop.js"));return pQ($.resolve(`${Q}/package.json`))}catch{return}}function CQ(Q,$,J,q){let Z=l(FQ(),Q);if(VQ(l(Z,q)))return Z;let K=JJ($),H=K?l(K,J):void 0;return H&&VQ(l(H,q))?H:void 0}function dQ(){return CQ("pdfjs/wasm","pdfjs-dist","wasm","jbig2.wasm")}function iQ(){return CQ("pdfjs/cmaps","pdfjs-dist","cmaps","UniJIS-UCS2-H.bcmap")}function nQ(){let Q=l(FQ(),"tesseract","worker.cjs");return VQ(Q)?Q:void 0}function sQ(){return CQ("tessdata","@tesseract.js-data/eng","4.0.0_best_int","eng.traineddata.gz")}var ZQ;function rQ(){return ZQ??=(async()=>{ZJ();let Q=globalThis;if(!Q.pdfjsWorker)Q.pdfjsWorker=await import("pdfjs-dist/legacy/build/pdf.worker.mjs");return await qJ(()=>import("pdfjs-dist/legacy/build/pdf.mjs"))})(),ZQ.catch(()=>{ZQ=void 0}),ZQ}async function qJ(Q){let $=console.warn;console.warn=(...J)=>{let q=String(J[0]??"");if(/^Warning: Cannot (load "@napi-rs\/canvas"|polyfill `(Path2D|DOMMatrix|ImageData)`)/.test(q))return;$(...J)};try{return await Q()}finally{console.warn=$}}function ZJ(){let Q=globalThis;if(Q.DOMMatrix)return;class ${a=1;b=0;c=0;d=1;e=0;f=0;constructor(J){if(J&&J.length>=6)[this.a,this.b,this.c,this.d,this.e,this.f]=Array.from(J).slice(0,6)}set(J){return[this.a,this.b,this.c,this.d,this.e,this.f]=J,this}product(J,q){return[J.a*q.a+J.c*q.b,J.b*q.a+J.d*q.b,J.a*q.c+J.c*q.d,J.b*q.c+J.d*q.d,J.a*q.e+J.c*q.f+J.e,J.b*q.e+J.d*q.f+J.f]}multiplySelf(J=new $){let q=J instanceof $?J:new $(J);return this.set(this.product(this,q))}preMultiplySelf(J=new $){let q=J instanceof $?J:new $(J);return this.set(this.product(q,this))}multiply(J){return new $(this.toArray()).multiplySelf(J)}translateSelf(J=0,q=0){return this.multiplySelf([1,0,0,1,J,q])}translate(J=0,q=0){return new $(this.toArray()).translateSelf(J,q)}scaleSelf(J=1,q=J){return this.multiplySelf([J,0,0,q,0,0])}scale(J=1,q=J){return new $(this.toArray()).scaleSelf(J,q)}invertSelf(){let J=this.a*this.d-this.b*this.c;if(!J)return this.set([Number.NaN,Number.NaN,Number.NaN,Number.NaN,Number.NaN,Number.NaN]);return this.set([this.d/J,-this.b/J,-this.c/J,this.a/J,(this.c*this.f-this.d*this.e)/J,(this.b*this.e-this.a*this.f)/J])}inverse(){return new $(this.toArray()).invertSelf()}toArray(){return[this.a,this.b,this.c,this.d,this.e,this.f]}}Q.DOMMatrix=$}function oQ(Q){return Q?`${Q.replace(/[\\/]+$/,"")}/`:void 0}function aQ(){let Q=oQ(dQ()),$=oQ(iQ());return{disableFontFace:!0,useSystemFonts:!1,isEvalSupported:!1,verbosity:0,...Q?{wasmUrl:Q}:{},...$?{cMapUrl:$,cMapPacked:!0}:{}}}var KJ=100,HJ=0.5,YJ=200,tQ=4,XJ=0.1,zJ=1,BJ=2,WJ=3;function GJ(Q,$){let[J=1,q=0,Z=0,K=1,H=0,Y=0]=$;return[Q[0]*J+Q[2]*q,Q[1]*J+Q[3]*q,Q[0]*Z+Q[2]*K,Q[1]*Z+Q[3]*K,Q[0]*H+Q[2]*Y+Q[4],Q[1]*H+Q[3]*Y+Q[5]]}async function UJ(Q,$){let[J,q,Z,K]=Q.view,H=Math.abs((Z-J)*(K-q))||1,Y=await Q.getOperatorList(),X=[1,0,0,1,0,0],B=[],F=0,U=!1,V=0,N=[];for(let G=0;G<Y.fnArray.length;G++){let z=Y.fnArray[G],C=Y.argsArray[G],I=()=>Math.abs(X[0]*X[3]-X[1]*X[2]);if(z===$.save)B.push(X);else if(z===$.restore)X=B.pop()??X;else if(z===$.transform)X=GJ(X,C);else if(z===$.setTextRenderingMode){if(C[0]===3)U=!0}else if(z===$.paintImageXObject||z===$.paintImageXObjectRepeat){if(F+=I(),typeof C[0]==="string")N.push({key:C[0],area:I()/H})}else if(z===$.paintInlineImageXObject)F+=I(),N.push({image:C[0],mask:!1,area:I()/H});else if(z===$.paintImageMaskXObject)F+=I(),N.push({image:C[0],mask:!0,area:I()/H});else if(z===$.constructPath)V++}return{coverage:Math.min(1,F/H),invisibleText:U,pathOps:V,pageArea:H,draws:N}}function eQ(Q){let $=Q.replace(/\s/g,"");if($.length<20)return!1;return($.match(/[-�\u0000-\u0008]/g)?.length??0)/$.length>0.3}var Q$=20000,$$=60000,KQ=new Set,e;function VJ(Q){if(KQ.add(Q),!e){let $=console.log;e=$,console.log=(...J)=>{let q=typeof J[0]==="string"?J[0]:"";if(q.startsWith("Warning: ")){for(let Z of KQ)Z(q.slice(9));return}$(...J)}}return()=>{if(KQ.delete(Q),KQ.size===0&&e)console.log=e,e=void 0}}function J$(Q,$,J){let q=$.startsWith("g_")?Q.commonObjs:Q.objs;return new Promise((Z)=>{let K=setTimeout(()=>Z("no answer"),J),H=(Y)=>{clearTimeout(K),Z(Y)};try{q.get($,(Y)=>H(Y??null))}catch{H(null)}})}function FJ(Q,$,J){let{width:q,height:Z,data:K}=$;if(!K||!q||!Z)return;if(J||$.kind===zJ){let X=q+7>>3;if(K.length<X*Z)return;let B=new Uint8Array(q*Z);for(let F=0;F<Z;F++){let U=F*X;for(let V=0;V<q;V++)B[F*q+V]=(K[U+(V>>3)]??0)>>7-(V&7)&1?255:0}return Q({width:q,height:Z,data:B,channels:1,depth:8})}let Y=$.kind===BJ?3:$.kind===WJ?4:K.length/(q*Z);if(Y!==1&&Y!==3&&Y!==4)return;return Q({width:q,height:Z,data:new Uint8Array(K.buffer,K.byteOffset,q*Z*Y),channels:Y,depth:8})}function CJ(Q,$){let J=Q?.name,q=Q?.message??"";if(J!=="PasswordException"&&!/password/i.test(q))return;return Error($?"The PDF's password is not the one given in `password`.":"The PDF is password-protected. Ask the user for the password and call again with `password`.")}async function q$(Q,$){let J=await rQ(),{encode:q}=await import("fast-png"),Z=new Set,K=$.onNote?VJ((X)=>{if(Z.size>=60||Z.has(X))return;Z.add(X),$.onNote?.(`pdf.js: ${X}`)}):void 0,H=J.getDocument({...aQ(),...$.onNote?{verbosity:1}:{},data:Q.slice(),...$.password?{password:$.password}:{}}),Y;try{Y=await H.promise}catch(X){throw await H.destroy().catch(()=>{}),K?.(),CJ(X,$.password)??X}try{return await RJ(Y,J.OPS,q,$)}finally{await H.destroy().catch(()=>{}),K?.()}}async function RJ(Q,$,J,q){let K=(await Q.getMetadata().catch(()=>{return}))?.info??{},H=Q.numPages,Y=[],X=[],B=[],F=[],U=[],V=[],N=0,G=(z,C)=>q.onProgress?.({unit:"page",at:z,total:H,pictures:N,...C?{activity:C}:{}});for(let z=1;z<=H;z++){if(q.selects&&!q.selects(z))continue;q.signal?.throwIfAborted(),G(z),Y.push(z),G(z,"opening the page");let C=await Q.getPage(z);G(z,"reading its text");let I=await C.getTextContent(),P="";for(let j of I.items){if(typeof j.str!=="string")continue;if(P+=j.str,j.hasEOL)P+=`
12
+ `}P=P.replace(/[ \t]+\n/g,`
13
+ `).replace(/\n{3,}/g,`
14
+
15
+ `).trim(),G(z,"reading its layout");let v=await UJ(C,$);G(z);let b=P.replace(/\s/g,"").length,d=v.coverage>=HJ,L=!1;if(d&&v.invisibleText&&b>0)F.push(z);else if(d&&(b<KJ||eQ(P)))L=!0;else if(b===0&&v.coverage===0&&v.pathOps>=YJ)U.push(z);else if(eQ(P))L=!0;if(L)X.push(z);let T=q.wantImages||L&&!!q.recognize,S=[];if(T){let j=0,O=0;for(let k of v.draws){if(O++,"key"in k)G(z,`decoding picture ${O} of ${v.draws.length}`);let A="key"in k?await J$(C,k.key,Q$):k.image;if(A==="no answer"&&"key"in k){let{key:f}=k;q.onNote?.(`page ${z}: picture ${O} of ${v.draws.length} (${f}) did not arrive in ${Q$/1000}s; asking for the page's pictures again`),G(z,`decoding picture ${O} of ${v.draws.length} again`),C.cleanup();let vQ=await Promise.race([C.getOperatorList().then(()=>!0),new Promise((zQ)=>setTimeout(()=>zQ(!1),$$))]).catch(()=>!1);if(A=vQ?await J$(C,f,$$):"no answer",A==="no answer"){let zQ=f.startsWith("g_")?C.commonObjs:C.objs,SQ="unknown";try{SQ=zQ.has(f)?"delivered late":"never delivered"}catch{}q.problems?.push(`page ${z}: picture ${O} of ${v.draws.length} (${f}) was left out, the PDF decoder gave no answer for it when asked twice (${vQ?SQ:"the page's drawing did not come back either"})`),q.onNote?.(`page ${z}: picture ${O} (${f}) left out after the second request`);continue}q.onNote?.(`page ${z}: picture ${O} (${f}) arrived on the second request`)}if(A==="no answer")continue;if(!A){q.problems?.push(`page ${z}: a picture was left out, the PDF decoder could not decode it`);continue}if(A.width<tQ||A.height<tQ)continue;let OQ=FJ(J,A,"mask"in k&&k.mask);if(!OQ){q.problems?.push(`page ${z}: a ${A.width}x${A.height} picture was left out, its pixel layout is one this cannot write`);continue}j++,N++,S.push({png:OQ,width:A.width,height:A.height,coverage:k.area,stem:`p${z}-${j}`})}}let w;if(L&&q.recognize){let j=S.filter((k)=>k.coverage>=XJ);if(j.length>0)G(z,"recognizing text");let O=j.length>0?await q.recognize(z,j):void 0;if(O?.text.trim())B.push(z),w=`[Text recognized from the page image by ${O.by}]
16
+
17
+ ${O.text.trim()}`}let i=[];if(q.wantImages)for(let j of S){let O=q.images.add({data:j.png,stem:j.stem,mediaType:"image/png",width:j.width,height:j.height,source:`page ${z}`});if(O)i.push(x(O))}G(z),V.push([`## Page ${z}`,P,w??"",...i].filter((j)=>j.length>0).join(`
18
+
19
+ `)),C.cleanup()}return{markdown:V.join(`
20
+
21
+ `),reader:"pdf.js",...typeof K.Title==="string"&&K.Title.trim()?{title:K.Title.trim()}:{},...typeof K.Author==="string"&&K.Author.trim()?{author:K.Author.trim()}:{},units:{name:"page",total:H,read:Y},...X.length?{scannedPages:X}:{},...B.length?{recognizedPages:B}:{},...F.length?{ocrLayerPages:F}:{},...U.length?{vectorPages:U}:{}}}function Z$(Q){let $=Q?.trim();if(!$)return;let J=[];for(let q of $.split(",")){let Z=q.trim();if(!Z)continue;let K=/^(\d+)\s*(?:-\s*(\d*))?$/.exec(Z);if(!K)throw Error(`range "${Q}" is not understood: use one-based numbers, spans and an open end, like "1-5,9,12-".`);let H=Number(K[1]),Y=K[2]===void 0?H:K[2]===""?Number.POSITIVE_INFINITY:Number(K[2]);if(H<1||Y<H)throw Error(`range "${Z}" is empty: numbers start at 1 and a span runs low to high.`);J.push([H,Y])}if(J.length===0)return;return{selects:(q)=>J.some(([Z,K])=>q>=Z&&q<=K),spec:$.replace(/\s+/g,"")}}function m(Q){let $=[...new Set(Q)].sort((q,Z)=>q-Z),J=[];for(let q=0;q<$.length;){let Z=q;while(Z+1<$.length&&$[Z+1]===$[Z]+1)Z++;J.push(q===Z?`${$[q]}`:`${$[q]}-${$[Z]}`),q=Z+1}return J.join(", ")}import{existsSync as K$}from"node:fs";import{copyFile as NJ,mkdir as LJ,readdir as T0,rename as O0,rm as v0,writeFile as S0}from"node:fs/promises";import{join as HQ}from"node:path";import{resolveClineDataDir as jJ}from"@cerebriline/shared/storage";var QQ="eng",RQ=".traineddata.gz";function LQ(){return HQ(jJ(),"tessdata")}function H$(Q){let J=(typeof Q==="string"?Q.split(/[+,\s]+/):Q??[]).map((q)=>q.trim().toLowerCase()).filter(Boolean);return[...new Set(J)]}async function TJ(Q,$){let J=sQ();if(J&&Q.every((K)=>K===QQ))return J;let q=Q.filter((K)=>!K$(HQ($,`${K}${RQ}`))&&!(K===QQ&&J));if(q.length>0)throw new YQ(q);let Z=HQ($,`${QQ}${RQ}`);if(J&&Q.includes(QQ)&&!K$(Z))await LJ($,{recursive:!0}),await NJ(HQ(J,`${QQ}${RQ}`),Z);return $}class YQ extends Error{languages;constructor(Q){super(`OCR language${Q.length===1?"":"s"} ${Q.join(", ")} ${Q.length===1?"is":"are"} not installed.`);this.languages=Q}}var OJ=180000,vJ=120000,SJ=1e4;function NQ(Q,$,J){let q;return Promise.race([Q,new Promise((Z,K)=>{q=setTimeout(()=>K(Error(`${J} gave no answer in ${$/1000}s`)),$)})]).finally(()=>clearTimeout(q))}class XQ{worker;languages;failure;dead;constructor(Q,$,J){this.worker=Q;this.languages=$;this.failure=J}static async open(Q,$=LQ()){let J=await TJ(Q,$),q=await import("tesseract.js"),Z=q.default??q,K=nQ(),H={},Y=await NQ(Z.createWorker(Q.join("+"),Z.OEM.LSTM_ONLY,{langPath:J,gzip:!0,cacheMethod:"none",...K?{workerPath:K}:{},errorHandler:(X)=>{let B=X instanceof Error?X:Error(`the OCR worker failed: ${String(X)}`);H.error=B,H.raise?.(B)}}),vJ,"Starting the OCR worker");return new XQ(Y,Q,H)}async recognize(Q){if(this.dead)throw this.dead;if(this.failure.error)throw this.dead=this.failure.error,this.dead;try{let{data:$}=await NQ(Promise.race([this.worker.recognize(Buffer.from(Q)),new Promise((J,q)=>{this.failure.raise=q})]),OJ,"The OCR worker");return{text:$.text??"",confidence:Math.round($.confidence??0)}}catch($){if(this.failure.error||$ instanceof Error&&/gave no answer/.test($.message))this.dead=$ instanceof Error?$:Error(String($));throw $}finally{this.failure.raise=void 0}}async close(){await NQ(this.worker.terminate(),SJ,"Stopping the OCR worker").catch(()=>{})}}var PJ=40,AJ=12,IJ=4;var kJ="This is a scanned page from a document. Transcribe all of its text exactly as written, in reading order, keeping paragraphs, headings and lists, and table rows as Markdown tables. Do not describe the page, summarize or add anything. Reply with the text only, or with nothing if the page has no text.";var Y$="The user can change this under Settings > Features > Document Reader.";function DJ(Q){let $=Q.settings.ocr??"tesseract";if(Q.request==="none")return{kind:"none",reason:'Text recognition was skipped (ocr: "none").'};if($==="off")return{kind:"none",reason:`Text recognition (OCR) is turned off. ${Y$}`};let J=!Q.request||Q.request==="auto"?$:Q.request,q=H$(Q.languages??Q.settings.ocrLanguages??["eng"]);if(J==="tesseract")return{kind:"tesseract",languages:q.length?q:["eng"]};if(Q.describeImages)return{kind:"vision"};if(Q.modelSupportsImages)return{kind:"self",why:"no vision model is configured"};return{kind:"tesseract",languages:q.length?q:["eng"],fallback:"No vision model is configured and this model does not take images, so tesseract read the pages instead."}}function X$(Q){let $=DJ(Q),J=[],q=[],Z=[],K,H=0,Y=Q.pageLimit!==void 0?Q.pageLimit:$.kind==="tesseract"?PJ:$.kind==="vision"?AJ:IJ;return{recognize:$.kind==="none"?void 0:async(B,F)=>{if(H>=Y){q.push(B);return}H++;let U=[...F].sort((z,C)=>C.coverage-z.coverage);if($.kind==="self"){let z=U[0];if(z)J.push({page:B,png:z.png});return}if($.kind==="vision")return EJ(Q.describeImages,B,U,Z);K??=XQ.open($.languages,Q.settings.ocrDataDir??LQ());let V;try{V=await K}catch(z){if(!Z.length)Z.push(MJ(z));return}let N=[],G=0;for(let z of U)try{let C=await V.recognize(z.png);if(C.text.trim())N.push(C.text.trim()),G=Math.max(G,C.confidence)}catch(C){Z.push(`page ${B}: ${C instanceof Error?C.message:String(C)}`)}if(!N.length)return;return{text:N.join(`
22
+
23
+ `),by:`tesseract (${$.languages.join("+")}, ${G}% confidence)`}},attachments:J,notes(B,F){if(!B.length)return[];let U=[],V=B.filter((G)=>!F.includes(G));if($.kind==="none")return U.push(`Scanned pages ${m(B)}: an image of text with no text layer, so their words are not in this text. ${$.reason}`),U;if(F.length){let G=$.kind==="vision"?"the vision model":`tesseract (${$.kind==="tesseract"?$.languages.join("+"):"eng"})`;U.push(`Scanned pages ${m(F)}: their text was recognized from the page image by ${G}, and may contain recognition errors.`)}if($.kind==="tesseract"&&$.fallback)U.push($.fallback);if($.kind==="self"&&J.length)U.push(`Scanned pages ${m(J.map((G)=>G.page))} are attached below as images (${$.why}): read their text from them.`);if(q.length)U.push(`Scanned pages ${m(q)} were not read: one call reads at most ${Y} scanned pages. Call again with range: "${q[0]}-" for the rest.`);let N=V.filter((G)=>!q.includes(G)&&!($.kind==="self"&&J.some((z)=>z.page===G)));if(N.length)U.push(`Scanned pages ${m(N)}: no text could be recognized${Z.length?` (${Z.slice(0,3).join("; ")})`:""}.`);return U},problems(B,F){let U=[],V=new Map;for(let G of Z){let z=/^page (\d+): ([\s\S]*)$/.exec(G);if(z)V.set(Number(z[1]),z[2]??"")}let N=Z.filter((G)=>!/^page \d+: /.test(G));for(let G of B){if(F.includes(G))continue;let z=q.includes(G)?`past the ${Y} pages recognized in one call`:V.get(G)??N[0]??($.kind==="none"?$.reason:"nothing readable was found on it");U.push(`page ${G}: a scan with no recognized text, ${z}`)}return U},async close(){if(K)await(await K.catch(()=>{return}))?.close()}}}function MJ(Q){if(Q instanceof YQ)return`${Q.message} ${Y$} In the CLI, --ocr-languages installs them`;return`tesseract did not start: ${Q instanceof Error?Q.message:String(Q)}`}async function EJ(Q,$,J,q){if(!Q)return;let Z=J[0];if(!Z)return;try{let[K]=await Q([{image:Buffer.from(Z.png).toString("base64"),mediaType:"image/png",instruction:kJ}]);return K?.trim()?{text:K.trim(),by:"the vision model"}:void 0}catch(K){q.push(`page ${$}: ${K instanceof Error?K.message:String(K)}`);return}}function _J(Q,$,J,q){switch(J){case"pdf":return q$($,q);case"doc":case"xls":case"ppt":return lQ($,J,q);case"epub":case"mobi":case"azw3":case"fb2":return DQ(Q,$,J,q);default:return mQ($,J,q)}}async function z$(Q,$={}){let J=new Uint8Array(await xJ.readFile(Q.filePath)),q=EQ(Q.namedAs??Q.filePath,J.subarray(0,512));if("unsupported"in q)throw Error(q.unsupported);let{format:Z}=q,K=Z$(Q.range),H=Z==="pdf"?X$({request:Q.recognition.request,languages:Q.recognition.languages,settings:Q.recognition.settings,describeImages:$.describeImages,modelSupportsImages:Q.recognition.modelSupportsImages,...Q.recognition.everyPage?{pageLimit:Number.POSITIVE_INFINITY}:{}}):void 0,Y=[],X=new BQ("images"),B;try{B=await _J(Q.filePath,J,Z,{images:X,wantImages:Q.wantImages,scratchDir:Q.scratchDir,problems:Y,...Q.password?{password:Q.password}:{},...K?{selects:K.selects}:{},...$.signal?{signal:$.signal}:{},...$.onProgress?{onProgress:$.onProgress}:{},...$.onNote?{onNote:$.onNote}:{},...H?.recognize?{recognize:H.recognize}:{}})}finally{await H?.close()}let F=B.scannedPages??[],U=B.recognizedPages??[];return{format:Z,result:B,images:[...X.entries()],recognitionNotes:H?.notes(F,U)??[],recognitionProblems:H?.problems(F,U)??[],attachments:H?.attachments??[],problems:Y}}var B$=".out";var G$=process;function p(Q){return new Promise(($)=>{if(!process.connected||!G$.send){$();return}G$.send(Q,()=>$())})}var jQ=new AbortController,TQ=new Map,hJ=0;function bJ(Q){let $=hJ++;return new Promise((J,q)=>{TQ.set($,{resolve:J,reject:q}),p({type:"describe",id:$,images:[...Q]})})}async function fJ(Q,$){let J=Date.now();try{let q=await z$(Q,{signal:jQ.signal,onProgress:(H)=>void p({type:"progress",progress:H}),onNote:(H)=>void p({type:"note",line:H}),...$?{describeImages:bJ}:{}}),Z=W$(Q.scratchDir,B$);await wJ(Z,{recursive:!0});let K=[];for(let[H,{image:Y,data:X}]of q.images.entries()){let B=W$(Z,String(H));await yJ(B,X),K.push({image:Y,file:B})}await p({type:"done",format:q.format,result:q.result,images:K,recognitionNotes:q.recognitionNotes,recognitionProblems:q.recognitionProblems,attachments:q.attachments,problems:q.problems,usage:{ms:Date.now()-J,peakRssMb:Math.round(process.resourceUsage().maxRSS/1024)}})}catch(q){await p({type:"failed",message:q instanceof Error?q.message:String(q),aborted:jQ.signal.aborted})}await Promise.race([cJ,new Promise((q)=>setTimeout(q,uJ).unref())]),process.exit(0)}var uJ=60000,V$=()=>{},cJ=new Promise((Q)=>{V$=Q}),U$=!1;process.on("message",(Q)=>{if(Q.type==="start"&&!U$)U$=!0,fJ(Q.job,Q.hasVision);else if(Q.type==="received")V$();else if(Q.type==="abort")jQ.abort();else if(Q.type==="described"){let $=TQ.get(Q.id);if(TQ.delete(Q.id),!$)return;if(Q.error!==void 0)$.reject(Error(Q.error));else $.resolve(Q.descriptions??[])}});process.on("disconnect",()=>process.exit(0));p({type:"ready"});
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The skills that ship with the product.
3
+ *
4
+ * They live in core's `assets/skills/`, one folder per skill, and are found
5
+ * beside the bundle first, where the extension's build copies them as
6
+ * `bundled-skills/`; then beside the executable, which is where the CLI's
7
+ * build puts them, since a compiled binary's modules have no folder on disk;
8
+ * and then in core's own `assets/`, by walking up from this module, which is
9
+ * the case for tests and for core used from `node_modules`.
10
+ *
11
+ * A bundled skill is replaced by every update, so nothing is ever written to
12
+ * its file. Whether it is on is a setting (`bundledSkills` in the global
13
+ * settings); the `disabled` field in its frontmatter is only the default.
14
+ */
15
+ /** The folder name beside a bundle. */
16
+ export declare const BUNDLED_SKILLS_DIRECTORY_NAME = "bundled-skills";
17
+ export declare function resolveBundledSkillsDirectory(besideDir?: string): string | undefined;
18
+ export declare function isBundledSkillPath(filePath: string, bundledDirectory?: string | undefined): boolean;
19
+ /**
20
+ * Whether a bundled skill is on: the user's choice if they made one, and
21
+ * otherwise what the skill's own frontmatter says.
22
+ */
23
+ export declare function isBundledSkillEnabled(name: string, enabledByDefault: boolean): boolean;
24
+ export declare function setBundledSkillEnabled(name: string, enabled: boolean): void;
@@ -1,4 +1,5 @@
1
1
  export { getBuiltinPromptTemplateSource, getBuiltinPromptTemplates, } from "./builtin-templates";
2
+ export { BUNDLED_SKILLS_DIRECTORY_NAME, isBundledSkillPath, resolveBundledSkillsDirectory, setBundledSkillEnabled, } from "./bundled-skills";
2
3
  export { auditCompactionSections, BUILTIN_COMPACTION_PROMPTS, buildCompactionTranslationRequest, type CompactionPromptSources, resolveCompactionPromptSources, stripCompactionSections, } from "./prompt-template-compaction";
3
4
  export { createPromptTemplateHooks, type PromptTemplateHooksOptions, } from "./prompt-template-hooks";
4
5
  export { loadPromptTemplates, loadPromptTemplatesFromDirectory, PROMPT_TEMPLATES_DIRECTORY_NAME, type PromptTemplateDirectory, type PromptTemplateFileWarnings, type PromptTemplateLoadError, type PromptTemplateLoadResult, resolvePromptTemplateDirectories, } from "./prompt-template-loader";
@@ -10,6 +11,6 @@ export { getShippedToolCallSignatures, HOST_TOOL_INPUT_SCHEMAS, } from "./shippe
10
11
  export type { UnifiedConfigDefinition, UnifiedConfigFileCandidate, UnifiedConfigFileContext, UnifiedConfigRecord, UnifiedConfigWatcherEvent, UnifiedConfigWatcherOptions, } from "./unified-config-file-watcher";
11
12
  export { UnifiedConfigFileWatcher } from "./unified-config-file-watcher";
12
13
  export type { CreateInstructionWatcherOptions, CreateRulesConfigDefinitionOptions, CreateSkillsConfigDefinitionOptions, CreateWorkflowsConfigDefinitionOptions, ParseMarkdownFrontmatterResult, RuleConfig, SkillConfig, UserInstructionConfig, UserInstructionConfigType, WorkflowConfig, } from "./user-instruction-config-loader";
13
- export { createRulesConfigDefinition, createSkillsConfigDefinition, createWorkflowsConfigDefinition, parseRuleConfigFromMarkdown, parseSkillConfigFromMarkdown, parseWorkflowConfigFromMarkdown, RULES_CONFIG_DIRECTORY_NAME, resolveRulesConfigSearchPaths, resolveSkillsConfigSearchPaths, resolveWorkflowsConfigSearchPaths, SKILLS_CONFIG_DIRECTORY_NAME, WORKFLOWS_CONFIG_DIRECTORY_NAME, } from "./user-instruction-config-loader";
14
+ export { createRulesConfigDefinition, createSkillsConfigDefinition, createWorkflowsConfigDefinition, parseRuleConfigFromMarkdown, parseSkillConfigFromMarkdown, parseWorkflowConfigFromMarkdown, RULES_CONFIG_DIRECTORY_NAME, resolveRulesConfigSearchPaths, resolveSkillsConfigSearchPaths, resolveWorkflowsConfigSearchPaths, SKILLS_CONFIG_DIRECTORY_NAME, setBundledSkillEnabledByPath, WORKFLOWS_CONFIG_DIRECTORY_NAME, } from "./user-instruction-config-loader";
14
15
  export type { CreateUserInstructionConfigServiceOptions, UserInstructionConfigRecord, UserInstructionConfigService, } from "./user-instruction-service";
15
16
  export { combineUserInstructionConfigServices, createUserInstructionConfigService, } from "./user-instruction-service";
@@ -13,6 +13,18 @@ export interface UnifiedConfigFileCandidate {
13
13
  export interface UnifiedConfigDefinition<TType extends string = string, TItem = unknown> {
14
14
  type: TType;
15
15
  directories: ReadonlyArray<string>;
16
+ /**
17
+ * Directories that are read and never watched, with everything under
18
+ * them: files that ship with the program and change only when it is
19
+ * replaced.
20
+ *
21
+ * A watcher is an open handle on the directory, and on Windows a folder
22
+ * with an open handle anywhere inside it cannot be renamed. The bundled
23
+ * skills live inside the VS Code extension's own folder, so watching them
24
+ * made every reinstall of the running version fail with `EPERM: rename`
25
+ * and "Please restart VS Code before reinstalling".
26
+ */
27
+ unwatchedDirectories?: ReadonlyArray<string>;
16
28
  discoverFiles?: (directoryPath: string) => Promise<ReadonlyArray<UnifiedConfigFileCandidate>>;
17
29
  includeFile?: (fileName: string, filePath: string) => boolean;
18
30
  parseFile: (context: UnifiedConfigFileContext<TType>) => TItem;
@@ -52,6 +64,8 @@ export declare class UnifiedConfigFileWatcher<TType extends string = string, TIt
52
64
  private readonly baseTypesByDirectory;
53
65
  private watchedTypesByDirectory;
54
66
  private readonly discoveredDirectoriesByType;
67
+ /** Read, never watched: see `UnifiedConfigDefinition.unwatchedDirectories`. */
68
+ private readonly unwatchedRoots;
55
69
  private readonly definitionsByType;
56
70
  private readonly pendingTypes;
57
71
  private flushTimer;
@@ -72,6 +86,7 @@ export declare class UnifiedConfigFileWatcher<TType extends string = string, TIt
72
86
  private scheduleFlush;
73
87
  private refreshTypeInternal;
74
88
  private loadDefinition;
89
+ private isUnwatched;
75
90
  private buildDesiredTypesByDirectory;
76
91
  private readDirectoryFileCandidates;
77
92
  }
@@ -14,6 +14,11 @@ export interface SkillConfig {
14
14
  disabled?: boolean;
15
15
  instructions: string;
16
16
  frontmatter: Record<string, unknown>;
17
+ /**
18
+ * Shipped with the product. Its file is never written: `disabled` here is
19
+ * the user's setting, or the frontmatter's default where they made none.
20
+ */
21
+ bundled?: boolean;
17
22
  source?: {
18
23
  type: "agent-plugin";
19
24
  pluginName: string;
@@ -45,6 +50,11 @@ export interface CreateInstructionWatcherOptions {
45
50
  }
46
51
  export interface CreateSkillsConfigDefinitionOptions {
47
52
  directories?: ReadonlyArray<string>;
53
+ /**
54
+ * Where the skills shipped with the product are. Undefined means core's
55
+ * own; `false` leaves them out. Not used when `directories` is given.
56
+ */
57
+ bundledSkillsDirectory?: string | false;
48
58
  workspacePath?: string;
49
59
  includePluginSkills?: boolean;
50
60
  pluginSkillDirectories?: ReadonlyArray<string>;
@@ -60,6 +70,11 @@ export interface CreateWorkflowsConfigDefinitionOptions {
60
70
  directories?: ReadonlyArray<string>;
61
71
  workspacePath?: string;
62
72
  }
73
+ /**
74
+ * Turn a bundled skill on or off, given its `SKILL.md`. False when the path
75
+ * is not a bundled skill's, so a caller can fall back to the frontmatter.
76
+ */
77
+ export declare function setBundledSkillEnabledByPath(filePath: string, enabled: boolean): Promise<boolean>;
63
78
  export declare function parseSkillConfigFromMarkdown(content: string, fallbackName: string): SkillConfig;
64
79
  export declare function parseRuleConfigFromMarkdown(content: string, fallbackName: string): RuleConfig;
65
80
  export declare function parseWorkflowConfigFromMarkdown(content: string, fallbackName: string): WorkflowConfig;
@@ -8,4 +8,14 @@
8
8
  * `destroy()` deletes the directory.
9
9
  */
10
10
  import type { DocumentFormat, DocumentReadResult, ReadOptions } from "./formats";
11
+ /**
12
+ * Why an EPUB cannot be opened as the ZIP it is, or nothing when it can.
13
+ *
14
+ * A ZIP's index is at its end, so a file cut short while it was copied,
15
+ * downloaded or unpacked has its first entries and no index. lingo-reader
16
+ * does not survive that: its loader drops the ZIP reader's error and the
17
+ * promise it returned never settles, so the read would wait until the tool's
18
+ * limit with nothing to say.
19
+ */
20
+ export declare function epubZipFault(data: Uint8Array): string | undefined;
11
21
  export declare function readEbook(filePath: string, data: Uint8Array, format: Extract<DocumentFormat, "epub" | "mobi" | "azw3" | "fb2">, options: ReadOptions): Promise<DocumentReadResult>;
@@ -36,6 +36,31 @@ export interface ReadOptions {
36
36
  * recognition is off; resolves undefined for a page it did not read.
37
37
  */
38
38
  recognize?: (page: number, images: readonly PageImage[]) => Promise<RecognizedText | undefined>;
39
+ /** Stops the read at the next page or chapter; the read throws. */
40
+ signal?: AbortSignal;
41
+ /** Called as the read moves: once a page or chapter, and around recognition. */
42
+ onProgress?: (progress: ReadProgress) => void;
43
+ /**
44
+ * Everything the read left out, a line each: a picture that could not be
45
+ * taken out, and why. The reader appends; nothing is left out silently.
46
+ */
47
+ problems?: string[];
48
+ /**
49
+ * Lines for the log, not for the reader of the document: what the PDF
50
+ * decoder warned about, a picture that needed asking for twice.
51
+ */
52
+ onNote?: (line: string) => void;
53
+ }
54
+ /** Where a read is. */
55
+ export interface ReadProgress {
56
+ unit: UnitName;
57
+ /** The page or chapter being read, from 1. */
58
+ at: number;
59
+ total: number;
60
+ /** Pictures taken out so far. */
61
+ pictures: number;
62
+ /** What it is doing there, when that is more than reading: "recognizing text". */
63
+ activity?: string;
39
64
  }
40
65
  /** A picture a scanned page is drawn from, as a PNG. */
41
66
  export interface PageImage {
@@ -19,6 +19,11 @@ export interface DocumentReaderSettings {
19
19
  ocrDataDir?: string;
20
20
  /** Describe extracted pictures with the vision model. @default false */
21
21
  describePictures?: boolean;
22
+ /**
23
+ * The largest file read, in MB; a larger one is refused by name.
24
+ * @default 1024
25
+ */
26
+ maxFileMb?: number;
22
27
  }
23
28
  export declare const BUNDLED_OCR_LANGUAGE = "eng";
24
29
  export declare function resolveOcrDataDir(): string;
@@ -57,6 +62,9 @@ export declare class OcrLanguageMissingError extends Error {
57
62
  export declare class TesseractReader {
58
63
  private readonly worker;
59
64
  readonly languages: readonly string[];
65
+ private readonly failure;
66
+ /** Why the worker is gone, once it is: nothing more is asked of it. */
67
+ private dead;
60
68
  private constructor();
61
69
  static open(languages: readonly string[], dataDir?: string): Promise<TesseractReader>;
62
70
  recognize(png: Uint8Array): Promise<{
@@ -0,0 +1,68 @@
1
+ /**
2
+ * One document read, as a request that can be handed to another process.
3
+ *
4
+ * Everything a read needs is in `ReadJob` as plain data, and everything it
5
+ * needs from the session while it runs (the vision model, progress, a stop)
6
+ * is in `ReadJobHooks`. `runReadJob` is the work itself: the reader process
7
+ * runs it (`read-child.ts`), and so does this process where no reader process
8
+ * can be started.
9
+ */
10
+ import { type DocumentFormat, type DocumentReadResult, type ReadProgress } from "./formats";
11
+ import { type ExtractedImage } from "./images";
12
+ import type { DocumentReaderSettings } from "./ocr";
13
+ import { type DescribeImages, type OcrRequest } from "./recognition";
14
+ export interface ReadJob {
15
+ /** The file to read. */
16
+ filePath: string;
17
+ /**
18
+ * The path whose name says what the file is, when that is not `filePath`:
19
+ * a delegated agent's overlay keeps its copy under another name.
20
+ */
21
+ namedAs?: string;
22
+ /** Whether pictures are taken out as well. */
23
+ wantImages: boolean;
24
+ password?: string;
25
+ /** Which pages, slides, sheets or chapters: `"1-5,9,12-"`. */
26
+ range?: string;
27
+ /** An existing directory the read may write in; the caller removes it. */
28
+ scratchDir: string;
29
+ /** How scanned pages are read. Only a PDF has any. */
30
+ recognition: {
31
+ request?: OcrRequest;
32
+ languages?: string;
33
+ settings: DocumentReaderSettings;
34
+ modelSupportsImages: boolean;
35
+ /** A book kept in the Library is read whole, however many scanned pages. */
36
+ everyPage?: boolean;
37
+ };
38
+ }
39
+ export interface ReadJobHooks {
40
+ /** The session's vision model, when there is one. */
41
+ describeImages?: DescribeImages;
42
+ /** Stops the read at the next page or chapter; the read throws. */
43
+ signal?: AbortSignal;
44
+ onProgress?: (progress: ReadProgress) => void;
45
+ /** Lines for the log, not for the reader of the document. */
46
+ onNote?: (line: string) => void;
47
+ }
48
+ export interface ReadJobResult {
49
+ format: DocumentFormat;
50
+ result: DocumentReadResult;
51
+ /** Every picture with its bytes, in the order they were found. */
52
+ images: {
53
+ image: ExtractedImage;
54
+ data: Uint8Array;
55
+ }[];
56
+ /** What recognition has to say, in sentences, for the result's header. */
57
+ recognitionNotes: string[];
58
+ /** Every scanned page left without text, a line each. */
59
+ recognitionProblems: string[];
60
+ /** Page images for the session's own model to read. */
61
+ attachments: {
62
+ page: number;
63
+ png: Uint8Array;
64
+ }[];
65
+ /** Everything else the read left out, a line each. */
66
+ problems: string[];
67
+ }
68
+ export declare function runReadJob(job: ReadJob, hooks?: ReadJobHooks): Promise<ReadJobResult>;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Reading a document in a process of its own.
3
+ *
4
+ * A PDF is decoded page by page into pictures, and a scanned one is then read
5
+ * by an OCR engine: hundreds of megabytes of work in whatever process does
6
+ * it. In a VS Code window that process is the extension host, which every
7
+ * extension shares and which has one fixed heap; measured on a 769-page
8
+ * scanned book, the host ran out of memory and took the session, and every
9
+ * other extension's state, with it.
10
+ *
11
+ * So each read gets a process, started for it and gone when it answers. What
12
+ * the session keeps is the result. A reader that runs out of memory or stops
13
+ * is one file that could not be read, said so with the page it stopped on.
14
+ *
15
+ * Where no reader process can be started (the file that runs in it was not
16
+ * shipped beside this bundle, or no JavaScript runtime is found) the read
17
+ * happens here, as it did before, and a note says so.
18
+ */
19
+ import type { ReadProgress } from "./formats";
20
+ import type { ExtractedImage } from "./images";
21
+ import { type ReadJob, type ReadJobHooks, type ReadJobResult } from "./read-job";
22
+ /**
23
+ * A read whose pictures are files, not bytes: a scanned book is a picture a
24
+ * page, hundreds of megabytes that the session has no reason to hold. They
25
+ * stay in the job's scratch directory until `release`, which the caller
26
+ * calls once it has done with them, on every path.
27
+ */
28
+ export interface HeldRead extends Omit<ReadJobResult, "images"> {
29
+ images: {
30
+ image: ExtractedImage;
31
+ file: string;
32
+ }[];
33
+ release(): Promise<void>;
34
+ }
35
+ /** Names the file that runs in the reader process, for a host that keeps it elsewhere. */
36
+ export declare const DOCUMENT_READER_CHILD_ENV = "CLINE_DOCUMENT_READER_CHILD";
37
+ /** `1` reads in this process, whatever is shipped. */
38
+ export declare const DOCUMENT_READER_IN_PROCESS_ENV = "CLINE_DOCUMENT_READER_IN_PROCESS";
39
+ /** How many reader processes run at once. */
40
+ export declare const DOCUMENT_READER_PROCESSES_ENV = "CLINE_DOCUMENT_READER_PROCESSES";
41
+ /** The file the reader process runs, or undefined where none was shipped. */
42
+ export declare function resolveReaderChild(env?: NodeJS.ProcessEnv): string | undefined;
43
+ /** Why a reader process ended without an answer, in a sentence. */
44
+ export declare function describeReaderExit(code: number | null, signal: NodeJS.Signals | null, stderr: string, progress: ReadProgress | undefined): string;
45
+ /** Test seam. */
46
+ export declare function resetReaderProcessState(): void;
47
+ /**
48
+ * Read one document. `job.scratchDir` is created here; it holds the
49
+ * pictures until the result's `release`, and is removed here when the read
50
+ * fails.
51
+ */
52
+ export declare function readDocumentJob(job: ReadJob, hooks?: ReadJobHooks): Promise<HeldRead>;