dsh-ab-ocr 0.1.0

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +378 -0
  3. package/cordis.patch.yml +7 -0
  4. package/lib/artifacts.d.ts +100 -0
  5. package/lib/artifacts.d.ts.map +1 -0
  6. package/lib/artifacts.js +97 -0
  7. package/lib/artifacts.js.map +1 -0
  8. package/lib/config.d.ts +77 -0
  9. package/lib/config.d.ts.map +1 -0
  10. package/lib/config.js +51 -0
  11. package/lib/config.js.map +1 -0
  12. package/lib/documents.d.ts +62 -0
  13. package/lib/documents.d.ts.map +1 -0
  14. package/lib/documents.js +173 -0
  15. package/lib/documents.js.map +1 -0
  16. package/lib/events.d.ts +161 -0
  17. package/lib/events.d.ts.map +1 -0
  18. package/lib/events.js +158 -0
  19. package/lib/events.js.map +1 -0
  20. package/lib/filename.d.ts +47 -0
  21. package/lib/filename.d.ts.map +1 -0
  22. package/lib/filename.js +77 -0
  23. package/lib/filename.js.map +1 -0
  24. package/lib/index.d.ts +85 -0
  25. package/lib/index.d.ts.map +1 -0
  26. package/lib/index.js +1761 -0
  27. package/lib/index.js.map +1 -0
  28. package/lib/levels.d.ts +24 -0
  29. package/lib/levels.d.ts.map +1 -0
  30. package/lib/levels.js +52 -0
  31. package/lib/levels.js.map +1 -0
  32. package/lib/plan.d.ts +103 -0
  33. package/lib/plan.d.ts.map +1 -0
  34. package/lib/plan.js +210 -0
  35. package/lib/plan.js.map +1 -0
  36. package/lib/recognize.d.ts +36 -0
  37. package/lib/recognize.d.ts.map +1 -0
  38. package/lib/recognize.js +390 -0
  39. package/lib/recognize.js.map +1 -0
  40. package/lib/records.d.ts +91 -0
  41. package/lib/records.d.ts.map +1 -0
  42. package/lib/records.js +130 -0
  43. package/lib/records.js.map +1 -0
  44. package/lib/render.d.ts +19 -0
  45. package/lib/render.d.ts.map +1 -0
  46. package/lib/render.js +45 -0
  47. package/lib/render.js.map +1 -0
  48. package/lib/sandbox.d.ts +54 -0
  49. package/lib/sandbox.d.ts.map +1 -0
  50. package/lib/sandbox.js +101 -0
  51. package/lib/sandbox.js.map +1 -0
  52. package/lib/types.d.ts +147 -0
  53. package/lib/types.d.ts.map +1 -0
  54. package/lib/types.js +7 -0
  55. package/lib/types.js.map +1 -0
  56. package/lib/worker.d.ts +107 -0
  57. package/lib/worker.d.ts.map +1 -0
  58. package/lib/worker.js +143 -0
  59. package/lib/worker.js.map +1 -0
  60. package/package.json +98 -0
  61. package/python/README.md +125 -0
  62. package/python/assemble.py +358 -0
  63. package/python/clean.py +197 -0
  64. package/python/layout.py +403 -0
  65. package/python/ocr_worker.py +516 -0
  66. package/python/requirements.txt +16 -0
  67. package/python/source.py +182 -0
  68. package/scripts/setup.mjs +251 -0
  69. package/tsconfig.json +30 -0
  70. package/tsdown.config.ts +18 -0
package/lib/events.js ADDED
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Interpretation of the worker's event stream, and the per-call state that
3
+ * interpretation accumulates.
4
+ *
5
+ * The worker is a separate process, so every value on this boundary is read
6
+ * defensively: a field that is absent, of the wrong type, or carries no page
7
+ * number is a protocol violation rather than a value to coerce. Everything an
8
+ * event reports about one document is kept in that document's
9
+ * {@link DocumentState} until it finishes, because the merge pass reads the
10
+ * geometry back.
11
+ * @module @deepseek-ai/dsh-ab-ocr/events
12
+ */
13
+ /**
14
+ * Read one worker event into the value the merge-shaped result is built from.
15
+ * @param event - the parsed event.
16
+ * @returns the document's counts and body, or undefined for another event.
17
+ */
18
+ export function readDoneEvent(event) {
19
+ if (event.event !== 'done')
20
+ return undefined;
21
+ return {
22
+ id: String(event.id ?? ''),
23
+ pages: Number(event.pages ?? 0),
24
+ totalPages: Number(event.totalPages ?? 0),
25
+ lines: Number(event.lines ?? 0),
26
+ headings: Number(event.headings ?? 0),
27
+ chars: Number(event.chars ?? 0),
28
+ droppedPageNumbers: Number(event.droppedPageNumbers ?? 0),
29
+ droppedRunningHeads: Number(event.droppedRunningHeads ?? 0),
30
+ joinedAcrossPages: Number(event.joinedAcrossPages ?? 0),
31
+ seconds: Number(event.seconds ?? 0),
32
+ markdown: String(event.markdown ?? ''),
33
+ };
34
+ }
35
+ /**
36
+ * Read one whole positive number off a worker event.
37
+ * @param value - the event field.
38
+ * @returns the number, or undefined when the field carries none.
39
+ */
40
+ export function wholeNumber(value) {
41
+ return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined;
42
+ }
43
+ /**
44
+ * Read the geometry one page event carries, which an assembly pass needs back.
45
+ * @param value - the event's `geometry` field.
46
+ * @returns the page's geometry, or undefined when the field does not carry it.
47
+ */
48
+ export function readGeometry(value) {
49
+ if (typeof value !== 'object' || value === null)
50
+ return undefined;
51
+ const geometry = value;
52
+ if (wholeNumber(geometry.index) === undefined)
53
+ return undefined;
54
+ if (typeof geometry.width !== 'number' || typeof geometry.height !== 'number')
55
+ return undefined;
56
+ if (!Array.isArray(geometry.lines))
57
+ return undefined;
58
+ return geometry;
59
+ }
60
+ /**
61
+ * Read the outline a finished document reported.
62
+ *
63
+ * The worker reports the level the merge inferred; the candidate carries that
64
+ * same level as its starting point until a correction replaces it.
65
+ * @param value - the event's `outline` field.
66
+ * @returns the outline entries, or an empty list when the field carries none.
67
+ */
68
+ export function readOutline(value) {
69
+ if (!Array.isArray(value))
70
+ return [];
71
+ return value.map(entry => ({ ...entry, inferred: entry.level }));
72
+ }
73
+ /**
74
+ * Read the failures a finished batch reported.
75
+ * @param value - the end event's `failures` field.
76
+ * @returns the failures, each naming a path and its reason.
77
+ */
78
+ export function readFailures(value) {
79
+ if (!Array.isArray(value))
80
+ return [];
81
+ return value.map((entry) => {
82
+ const failure = entry;
83
+ return {
84
+ id: String(failure?.id ?? ''),
85
+ input: String(failure?.input ?? ''),
86
+ error: String(failure?.error ?? ''),
87
+ };
88
+ });
89
+ }
90
+ /**
91
+ * Start the record one document reports into.
92
+ * @param job - the prepared job.
93
+ * @returns the document's empty state.
94
+ */
95
+ export function documentState(job) {
96
+ return { job, selection: [], totalPages: 0, lastPage: 0, geometry: [], carried: undefined };
97
+ }
98
+ /**
99
+ * Report why one page event breaks the order a document's files rely on.
100
+ * @param page - the page number the event carried.
101
+ * @param state - what the document has reported so far.
102
+ * @returns the problem, or undefined when the page is in order.
103
+ */
104
+ export function pageProblem(page, state) {
105
+ if (page === state.lastPage)
106
+ return 'page ' + page + ' arrived twice';
107
+ if (page < state.lastPage)
108
+ return 'page ' + page + ' arrived after page ' + state.lastPage;
109
+ if (state.totalPages > 0 && page > state.totalPages) {
110
+ return 'page ' + page + ' is past the last page of the document, ' + state.totalPages;
111
+ }
112
+ return undefined;
113
+ }
114
+ /**
115
+ * Serialize a call's artifact writes behind one chain, so two writes never race
116
+ * for one path and a failed write is recorded once.
117
+ * @param controller - the controller whose abort stops the recognition.
118
+ * @returns the queue's enqueue and settle operations.
119
+ */
120
+ export function writeQueue(controller) {
121
+ let chain = Promise.resolve();
122
+ let failed;
123
+ return {
124
+ enqueue(task) {
125
+ chain = chain.then(task).catch((error) => {
126
+ if (failed !== undefined)
127
+ return;
128
+ failed = error instanceof Error ? error : new Error(String(error));
129
+ // A denied write denies every later page the same way, so stop the
130
+ // recognition instead of finishing a document that cannot be saved.
131
+ controller.abort();
132
+ });
133
+ },
134
+ async settle() {
135
+ await chain;
136
+ return failed;
137
+ },
138
+ };
139
+ }
140
+ /**
141
+ * Report one document's failure once, whether it arrived as its own event or in
142
+ * the batch's closing list. The worker reports a failure both ways, and its two
143
+ * reports agree on the job identifier as well as on the path and the reason.
144
+ * @param call - the call collecting failures.
145
+ * @param failure - the failure the worker reported.
146
+ * @returns nothing.
147
+ */
148
+ export function reportFailure(call, failure) {
149
+ const keys = ['pair:' + failure.input + '\u0000' + failure.error];
150
+ if (failure.id !== '')
151
+ keys.push('job:' + failure.id);
152
+ if (keys.some(key => call.reported.has(key)))
153
+ return;
154
+ for (const key of keys)
155
+ call.reported.add(key);
156
+ call.failures.push({ input: failure.input, error: failure.error });
157
+ }
158
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Output naming for OCR artifacts. A source file name may carry spaces, path
3
+ * separators, characters Windows rejects, device names, and unbounded length,
4
+ * so every document passes through this module before its Markdown file is
5
+ * created.
6
+ * @module @deepseek-ai/dsh-ab-ocr/filename
7
+ */
8
+ /** Extension every recognized document is saved with. */
9
+ export declare const MARKDOWN_EXTENSION = ".md";
10
+ /** Stem used when a source name compacts to nothing. */
11
+ export declare const FALLBACK_STEM = "document";
12
+ /**
13
+ * Build the stem one source document's artifacts are named after: the source's
14
+ * own base name with its extension dropped and every space removed.
15
+ * @param sourcePath - the path the model asked to recognize.
16
+ * @returns a stem with no spaces and no characters a file system rejects.
17
+ */
18
+ export declare function markdownStem(sourcePath: string): string;
19
+ /**
20
+ * Build the Markdown file name one source document is saved under.
21
+ * @param sourcePath - the path the model asked to recognize.
22
+ * @returns the stem, with a leading underscore when the name is a reserved
23
+ * Windows device name, carrying the Markdown extension.
24
+ */
25
+ export declare function markdownFileName(sourcePath: string): string;
26
+ /**
27
+ * Build the Markdown file name one recognition's own revision is saved under,
28
+ * used when the plain name already holds a different document.
29
+ * @param sourcePath - the path the model asked to recognize.
30
+ * @param digest - the recognition's content digest.
31
+ * @returns the source's Markdown name with the digest before its extension.
32
+ */
33
+ export declare function markdownDigestFileName(sourcePath: string, digest: string): string;
34
+ /**
35
+ * Resolve where one source document's Markdown file is written.
36
+ * @param sourcePath - the absolute path the model asked to recognize.
37
+ * @param outputDir - the deployment's directory, or an empty string for the source's own.
38
+ * @returns the absolute path of the Markdown file.
39
+ */
40
+ export declare function markdownPath(sourcePath: string, outputDir: string): string;
41
+ /**
42
+ * Build the file name one page's recognized text is written under.
43
+ * @param index - the page's one-based number.
44
+ * @returns the page file's base name.
45
+ */
46
+ export declare function pageFileName(index: number): string;
47
+ //# sourceMappingURL=filename.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filename.d.ts","sourceRoot":"","sources":["../src/filename.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,QAAQ,CAAA;AAEvC,wDAAwD;AACxD,eAAO,MAAM,aAAa,aAAa,CAAA;AAcvC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CASvD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGjF;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1E;AAKD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Output naming for OCR artifacts. A source file name may carry spaces, path
3
+ * separators, characters Windows rejects, device names, and unbounded length,
4
+ * so every document passes through this module before its Markdown file is
5
+ * created.
6
+ * @module @deepseek-ai/dsh-ab-ocr/filename
7
+ */
8
+ import { basename, dirname, extname, join } from 'node:path';
9
+ /** Extension every recognized document is saved with. */
10
+ export const MARKDOWN_EXTENSION = '.md';
11
+ /** Stem used when a source name compacts to nothing. */
12
+ export const FALLBACK_STEM = 'document';
13
+ /** Characters no file name may carry: Windows' reserved set, the POSIX separator, and controls. */
14
+ const ILLEGAL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f<>:"/\\|?*]/g;
15
+ /** Device names Windows reserves in every directory, with or without an extension. */
16
+ const RESERVED_DEVICE_NAME = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;
17
+ /** Leading and trailing characters a file name may not carry on Windows. */
18
+ const EDGE_NOISE = /^[\s.\-]+|[\s.\-]+$/g;
19
+ /** Every spacing character Unicode offers, which the source name is stripped of. */
20
+ const SPACES = /[\s\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+/g;
21
+ /**
22
+ * Build the stem one source document's artifacts are named after: the source's
23
+ * own base name with its extension dropped and every space removed.
24
+ * @param sourcePath - the path the model asked to recognize.
25
+ * @returns a stem with no spaces and no characters a file system rejects.
26
+ */
27
+ export function markdownStem(sourcePath) {
28
+ const text = basename(sourcePath);
29
+ const stem = text.slice(0, text.length - extname(text).length);
30
+ const compact = stem.replace(SPACES, '').normalize('NFC');
31
+ const safe = compact
32
+ .replace(ILLEGAL_CHARACTERS, '-')
33
+ .replace(/-{2,}/g, '-')
34
+ .replace(EDGE_NOISE, '');
35
+ return safe === '' ? FALLBACK_STEM : safe;
36
+ }
37
+ /**
38
+ * Build the Markdown file name one source document is saved under.
39
+ * @param sourcePath - the path the model asked to recognize.
40
+ * @returns the stem, with a leading underscore when the name is a reserved
41
+ * Windows device name, carrying the Markdown extension.
42
+ */
43
+ export function markdownFileName(sourcePath) {
44
+ const stem = markdownStem(sourcePath);
45
+ return (RESERVED_DEVICE_NAME.test(stem) ? '_' + stem : stem) + MARKDOWN_EXTENSION;
46
+ }
47
+ /**
48
+ * Build the Markdown file name one recognition's own revision is saved under,
49
+ * used when the plain name already holds a different document.
50
+ * @param sourcePath - the path the model asked to recognize.
51
+ * @param digest - the recognition's content digest.
52
+ * @returns the source's Markdown name with the digest before its extension.
53
+ */
54
+ export function markdownDigestFileName(sourcePath, digest) {
55
+ const name = markdownFileName(sourcePath);
56
+ return name.slice(0, name.length - MARKDOWN_EXTENSION.length) + '.' + digest + MARKDOWN_EXTENSION;
57
+ }
58
+ /**
59
+ * Resolve where one source document's Markdown file is written.
60
+ * @param sourcePath - the absolute path the model asked to recognize.
61
+ * @param outputDir - the deployment's directory, or an empty string for the source's own.
62
+ * @returns the absolute path of the Markdown file.
63
+ */
64
+ export function markdownPath(sourcePath, outputDir) {
65
+ return join(outputDir === '' ? dirname(sourcePath) : outputDir, markdownFileName(sourcePath));
66
+ }
67
+ /** How many digits a per-page file index carries, which keeps a 99999-page scan in lexicographic order. */
68
+ const PAGE_INDEX_DIGITS = 5;
69
+ /**
70
+ * Build the file name one page's recognized text is written under.
71
+ * @param index - the page's one-based number.
72
+ * @returns the page file's base name.
73
+ */
74
+ export function pageFileName(index) {
75
+ return 'page-' + String(index).padStart(PAGE_INDEX_DIGITS, '0') + '.txt';
76
+ }
77
+ //# sourceMappingURL=filename.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filename.js","sourceRoot":"","sources":["../src/filename.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAE5D,yDAAyD;AACzD,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAA;AAEvC,wDAAwD;AACxD,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAA;AAEvC,mGAAmG;AACnG,MAAM,kBAAkB,GAAG,yCAAyC,CAAA;AAEpE,sFAAsF;AACtF,MAAM,oBAAoB,GAAG,0CAA0C,CAAA;AAEvE,4EAA4E;AAC5E,MAAM,UAAU,GAAG,sBAAsB,CAAA;AAEzC,oFAAoF;AACpF,MAAM,MAAM,GAAG,+DAA+D,CAAA;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACzD,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;SAChC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAC1B,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAA;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,MAAM,IAAI,GAAG,YAAY,CAAC,UAAU,CAAC,CAAA;IACrC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAA;AACnF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,MAAc;IACvE,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;IACzC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,MAAM,GAAG,kBAAkB,CAAA;AACnG,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,SAAiB;IAChE,OAAO,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAA;AAC/F,CAAC;AAED,2GAA2G;AAC3G,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAE3B;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,GAAG,MAAM,CAAA;AAC1E,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Model-facing `ocr` tool. One call recognizes a PDF or an image and saves the
3
+ * text as a Markdown file named after the source with its spaces removed.
4
+ *
5
+ * The document is processed one page at a time: the worker recognizes a page,
6
+ * reports its text and its geometry, and releases its pixels before rendering
7
+ * the next. The page's text is written to its own file as each page arrives, so
8
+ * an interrupted run keeps every page it finished. Only after the last page does
9
+ * the worker merge its records —dropping the folios and running heads,
10
+ * rebuilding the outline from the recognized glyph sizes and numbering, and
11
+ * stitching the paragraphs a page break cut in half —and reports the one
12
+ * Markdown document, which is written last, beside the record an assembly pass
13
+ * reads back. A later call carrying `levels` sends that stored geometry to the
14
+ * worker again with the caller's heading-level corrections and rewrites the
15
+ * document without recognizing it a second time.
16
+ *
17
+ * This module owns the plugin's identity, its deployment configuration, its
18
+ * routing section, and its tool registration. The work behind them lives in
19
+ * [`plan.ts`](./plan.ts) (what one call asks for), [`recognize.ts`](./recognize.ts)
20
+ * (driving the worker and writing the artifacts), [`documents.ts`](./documents.ts)
21
+ * (the artifact files of one recognition), and [`events.ts`](./events.ts) (the
22
+ * worker's event stream), with the pure leaf modules beside them.
23
+ *
24
+ * Every file is written through the filesystem capability rather than the host
25
+ * filesystem, so a deployment's file policy sees the write and its own backend
26
+ * decides how the bytes are published. That capability is read with `ctx.get`
27
+ * when a call runs — and so is the sandbox-policy service, whose resolved
28
+ * per-call policy is the only thing naming the workspace the calling session
29
+ * runs in. Both are looked up rather than declared in `inject`, for the same
30
+ * reason: a declared injection waits for the service, which would make mounting
31
+ * this row require providers of its own. The policy is resolved once per call
32
+ * and stamped onto every write, and a composition that cannot resolve one is
33
+ * refused at the call rather than writing under the deployment's fallback root.
34
+ *
35
+ * The tool reads no session state beyond the working directory it resolves
36
+ * relative paths against and returns the canonical value alone, so model-facing
37
+ * text and any replay read the same recorded call.
38
+ * @module @deepseek-ai/dsh-ab-ocr
39
+ */
40
+ import type { Context } from '@deepseek-ai/cordis';
41
+ import { type GenericCallView } from '@deepseek-ai/dsh-tools';
42
+ import type { Config } from './config.ts';
43
+ import type { OcrArgs } from './types.ts';
44
+ export type * from './types.ts';
45
+ export { Config } from './config.ts';
46
+ export { artifactPaths, digest12 } from './artifacts.ts';
47
+ export { appliedOutline, writeDocument } from './documents.ts';
48
+ export { markdownDigestFileName, markdownFileName, markdownPath, markdownStem, pageFileName } from './filename.ts';
49
+ export { parseLevels } from './levels.ts';
50
+ export { SUPPORTED_EXTENSIONS, planJobs, rejectPath, requestPaths, resolveDirectory, resolvePython, resolveWorkerScript, } from './plan.ts';
51
+ export { readDoneEvent } from './events.ts';
52
+ export { renderDocument, renderOcr } from './render.ts';
53
+ export { callFence, saveText, type CallFence } from './sandbox.ts';
54
+ export { parseEvent, splitLines } from './worker.ts';
55
+ export { recognize } from './recognize.ts';
56
+ export declare const name = "ocr";
57
+ export declare const inject: string[];
58
+ /** Wire name this plugin registers. */
59
+ export declare const TOOL_NAME = "ocr";
60
+ /**
61
+ * Name and order of the routing section this plugin contributes. Repository-owned
62
+ * tool sections allocate their order centrally; an external contribution states
63
+ * its own finite order and sits after the built-in tool band (TOOL_REPORT, 2900).
64
+ */
65
+ export declare const SECTION_NAME = "tool:ocr";
66
+ /** Order of {@link SECTION_NAME}, after the built-in tool sections. */
67
+ export declare const SECTION_ORDER = 2975;
68
+ /** Model-facing routing rule: when to make a call, which a schema cannot carry. */
69
+ export declare const SECTION_TEXT: string;
70
+ /**
71
+ * The pending-call presentation of one ocr call: a titled row carrying the
72
+ * source path. Exported so the test drives it without a registry.
73
+ * @param args - the model-supplied call arguments.
74
+ * @returns the pending generic card for this call.
75
+ */
76
+ export declare function presentCall(args: OcrArgs): GenericCallView;
77
+ /**
78
+ * Contribute the routing section and register the ocr tool. The section is
79
+ * empty wherever the tool is not visible in that scope, so a restricted
80
+ * composition is not told to call a hidden tool.
81
+ * @param ctx - registrant context carrying the tool, system-prompt, and filesystem registries.
82
+ * @param config - the deployment's worker, render, and merge values.
83
+ */
84
+ export declare function apply(ctx: Context, config: Config): void;
85
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAGzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAIzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAClH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EACL,oBAAoB,EACpB,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,mBAAmB,GACpB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,eAAO,MAAM,IAAI,QAAQ,CAAA;AACzB,eAAO,MAAM,MAAM,UAA4B,CAAA;AAE/C,uCAAuC;AACvC,eAAO,MAAM,SAAS,QAAQ,CAAA;AAE9B;;;;GAIG;AACH,eAAO,MAAM,YAAY,aAAa,CAAA;AAEtC,uEAAuE;AACvE,eAAO,MAAM,aAAa,OAAO,CAAA;AAQjC,mFAAmF;AACnF,eAAO,MAAM,YAAY,QAId,CAAA;AAEX;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,CAO1D;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAkHxD"}