@modelprofile.com/flexharness 6.0.0 → 7.0.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 (169) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts_chat/classes.chatsession.d.ts +37 -0
  3. package/dist_ts_chat/classes.chatsession.js +102 -0
  4. package/dist_ts_chat/index.d.ts +2 -0
  5. package/dist_ts_chat/index.js +2 -0
  6. package/dist_ts_chat/interfaces.d.ts +72 -0
  7. package/dist_ts_chat/interfaces.js +2 -0
  8. package/dist_ts_chat/plugins.d.ts +4 -0
  9. package/dist_ts_chat/plugins.js +4 -0
  10. package/dist_ts_chat_cli/components.chatapp.d.ts +10 -0
  11. package/dist_ts_chat_cli/components.chatapp.js +75 -0
  12. package/dist_ts_chat_cli/components.inputarea.d.ts +7 -0
  13. package/dist_ts_chat_cli/components.inputarea.js +18 -0
  14. package/dist_ts_chat_cli/components.message.d.ts +12 -0
  15. package/dist_ts_chat_cli/components.message.js +21 -0
  16. package/dist_ts_chat_cli/components.messagelist.d.ts +9 -0
  17. package/dist_ts_chat_cli/components.messagelist.js +19 -0
  18. package/dist_ts_chat_cli/components.statusbar.d.ts +9 -0
  19. package/dist_ts_chat_cli/components.statusbar.js +15 -0
  20. package/dist_ts_chat_cli/index.d.ts +2 -0
  21. package/dist_ts_chat_cli/index.js +2 -0
  22. package/dist_ts_chat_cli/plugins.d.ts +12 -0
  23. package/dist_ts_chat_cli/plugins.js +14 -0
  24. package/dist_ts_chat_cli/startchat.d.ts +18 -0
  25. package/dist_ts_chat_cli/startchat.js +17 -0
  26. package/dist_ts_chat_web/flexchat-input.d.ts +21 -0
  27. package/dist_ts_chat_web/flexchat-input.js +172 -0
  28. package/dist_ts_chat_web/flexchat-message.d.ts +26 -0
  29. package/dist_ts_chat_web/flexchat-message.js +174 -0
  30. package/dist_ts_chat_web/flexchat-window.d.ts +34 -0
  31. package/dist_ts_chat_web/flexchat-window.js +394 -0
  32. package/dist_ts_chat_web/index.d.ts +3 -0
  33. package/dist_ts_chat_web/index.js +4 -0
  34. package/dist_ts_chat_web/plugins.d.ts +6 -0
  35. package/dist_ts_chat_web/plugins.js +4 -0
  36. package/dist_ts_compaction/index.d.ts +2 -0
  37. package/dist_ts_compaction/index.js +2 -0
  38. package/dist_ts_compaction/plugins.d.ts +4 -0
  39. package/dist_ts_compaction/plugins.js +3 -0
  40. package/dist_ts_compaction/smartagent.compaction.d.ts +14 -0
  41. package/dist_ts_compaction/smartagent.compaction.js +49 -0
  42. package/dist_ts_document/index.d.ts +19 -0
  43. package/dist_ts_document/index.js +55 -0
  44. package/dist_ts_document/plugins.d.ts +3 -0
  45. package/dist_ts_document/plugins.js +4 -0
  46. package/dist_ts_kvm/classes.browserkvm.d.ts +22 -0
  47. package/dist_ts_kvm/classes.browserkvm.js +271 -0
  48. package/dist_ts_kvm/classes.kvmterminal.d.ts +8 -0
  49. package/dist_ts_kvm/classes.kvmterminal.js +88 -0
  50. package/dist_ts_kvm/commandwrappers.d.ts +14 -0
  51. package/dist_ts_kvm/commandwrappers.js +58 -0
  52. package/dist_ts_kvm/index.d.ts +6 -0
  53. package/dist_ts_kvm/index.js +7 -0
  54. package/dist_ts_kvm/interfaces.d.ts +106 -0
  55. package/dist_ts_kvm/interfaces.js +2 -0
  56. package/dist_ts_kvm/ocr.d.ts +14 -0
  57. package/dist_ts_kvm/ocr.js +23 -0
  58. package/dist_ts_kvm/plugins.d.ts +6 -0
  59. package/dist_ts_kvm/plugins.js +10 -0
  60. package/dist_ts_kvm/tools.d.ts +15 -0
  61. package/dist_ts_kvm/tools.js +40 -0
  62. package/dist_ts_mcp/index.d.ts +86 -0
  63. package/dist_ts_mcp/index.js +284 -0
  64. package/dist_ts_mcp/requestcontext.d.ts +11 -0
  65. package/dist_ts_mcp/requestcontext.js +42 -0
  66. package/dist_ts_media/index.d.ts +8 -0
  67. package/dist_ts_media/index.js +21 -0
  68. package/dist_ts_media/plugins.d.ts +2 -0
  69. package/dist_ts_media/plugins.js +3 -0
  70. package/dist_ts_ocr/classes.imageocr.d.ts +19 -0
  71. package/dist_ts_ocr/classes.imageocr.js +27 -0
  72. package/dist_ts_ocr/index.d.ts +2 -0
  73. package/dist_ts_ocr/index.js +3 -0
  74. package/dist_ts_ocr/ocr.mistral.d.ts +75 -0
  75. package/dist_ts_ocr/ocr.mistral.js +77 -0
  76. package/dist_ts_tools/index.d.ts +17 -0
  77. package/dist_ts_tools/index.js +10 -0
  78. package/dist_ts_tools/plugins.d.ts +7 -0
  79. package/dist_ts_tools/plugins.js +6 -0
  80. package/dist_ts_tools/tool.browser.d.ts +11 -0
  81. package/dist_ts_tools/tool.browser.js +128 -0
  82. package/dist_ts_tools/tool.context.d.ts +4 -0
  83. package/dist_ts_tools/tool.context.js +23 -0
  84. package/dist_ts_tools/tool.filesystem.d.ts +11 -0
  85. package/dist_ts_tools/tool.filesystem.js +106 -0
  86. package/dist_ts_tools/tool.http.d.ts +2 -0
  87. package/dist_ts_tools/tool.http.js +65 -0
  88. package/dist_ts_tools/tool.json.d.ts +2 -0
  89. package/dist_ts_tools/tool.json.js +47 -0
  90. package/dist_ts_tools/tool.shell.d.ts +15 -0
  91. package/dist_ts_tools/tool.shell.js +329 -0
  92. package/dist_ts_tools/utils.truncation.d.ts +10 -0
  93. package/dist_ts_tools/utils.truncation.js +26 -0
  94. package/dist_ts_tools_node/index.d.ts +5 -0
  95. package/dist_ts_tools_node/index.js +4 -0
  96. package/dist_ts_tools_node/plugins.d.ts +13 -0
  97. package/dist_ts_tools_node/plugins.js +13 -0
  98. package/dist_ts_tools_node/tool.context.d.ts +31 -0
  99. package/dist_ts_tools_node/tool.context.js +837 -0
  100. package/dist_ts_tools_node/tool.persistence.d.ts +15 -0
  101. package/dist_ts_tools_node/tool.persistence.js +129 -0
  102. package/dist_ts_tools_node/tools.local.d.ts +11 -0
  103. package/dist_ts_tools_node/tools.local.js +15 -0
  104. package/package.json +112 -4
  105. package/readme.md +122 -66
  106. package/ts/00_commitinfo_data.ts +1 -1
  107. package/ts/readme.md +122 -66
  108. package/ts_chat/classes.chatsession.ts +116 -0
  109. package/ts_chat/index.ts +8 -0
  110. package/ts_chat/interfaces.ts +64 -0
  111. package/ts_chat/plugins.ts +7 -0
  112. package/ts_chat/readme.md +49 -0
  113. package/ts_chat_cli/components.chatapp.ts +103 -0
  114. package/ts_chat_cli/components.inputarea.ts +29 -0
  115. package/ts_chat_cli/components.message.ts +48 -0
  116. package/ts_chat_cli/components.messagelist.ts +45 -0
  117. package/ts_chat_cli/components.statusbar.ts +31 -0
  118. package/ts_chat_cli/index.ts +2 -0
  119. package/ts_chat_cli/plugins.ts +21 -0
  120. package/ts_chat_cli/readme.md +40 -0
  121. package/ts_chat_cli/startchat.ts +34 -0
  122. package/ts_chat_web/flexchat-input.ts +184 -0
  123. package/ts_chat_web/flexchat-message.ts +185 -0
  124. package/ts_chat_web/flexchat-window.ts +416 -0
  125. package/ts_chat_web/index.ts +3 -0
  126. package/ts_chat_web/plugins.ts +9 -0
  127. package/ts_chat_web/readme.md +46 -0
  128. package/ts_compaction/index.ts +2 -0
  129. package/ts_compaction/plugins.ts +6 -0
  130. package/ts_compaction/readme.md +37 -0
  131. package/ts_compaction/smartagent.compaction.ts +59 -0
  132. package/ts_document/index.ts +82 -0
  133. package/ts_document/plugins.ts +3 -0
  134. package/ts_document/readme.md +49 -0
  135. package/ts_kvm/classes.browserkvm.ts +335 -0
  136. package/ts_kvm/classes.kvmterminal.ts +103 -0
  137. package/ts_kvm/commandwrappers.ts +83 -0
  138. package/ts_kvm/index.ts +6 -0
  139. package/ts_kvm/interfaces.ts +152 -0
  140. package/ts_kvm/ocr.ts +41 -0
  141. package/ts_kvm/plugins.ts +13 -0
  142. package/ts_kvm/readme.md +482 -0
  143. package/ts_kvm/tools.ts +58 -0
  144. package/ts_mcp/index.ts +470 -0
  145. package/ts_mcp/readme.md +37 -0
  146. package/ts_mcp/requestcontext.ts +66 -0
  147. package/ts_media/index.ts +29 -0
  148. package/ts_media/plugins.ts +2 -0
  149. package/ts_media/readme.md +37 -0
  150. package/ts_ocr/classes.imageocr.ts +53 -0
  151. package/ts_ocr/index.ts +2 -0
  152. package/ts_ocr/ocr.mistral.ts +192 -0
  153. package/ts_ocr/readme.md +48 -0
  154. package/ts_tools/index.ts +49 -0
  155. package/ts_tools/plugins.ts +7 -0
  156. package/ts_tools/readme.md +37 -0
  157. package/ts_tools/tool.browser.ts +159 -0
  158. package/ts_tools/tool.context.ts +23 -0
  159. package/ts_tools/tool.filesystem.ts +144 -0
  160. package/ts_tools/tool.http.ts +78 -0
  161. package/ts_tools/tool.json.ts +53 -0
  162. package/ts_tools/tool.shell.ts +418 -0
  163. package/ts_tools/utils.truncation.ts +39 -0
  164. package/ts_tools_node/index.ts +5 -0
  165. package/ts_tools_node/plugins.ts +16 -0
  166. package/ts_tools_node/readme.md +37 -0
  167. package/ts_tools_node/tool.context.ts +991 -0
  168. package/ts_tools_node/tool.persistence.ts +146 -0
  169. package/ts_tools_node/tools.local.ts +26 -0
@@ -0,0 +1,37 @@
1
+ Vision recipes for a caller-supplied language model.
2
+
3
+ Part of the [FlexHarness toolbox](https://code.foss.global/modelprofile.com/flexharness).
4
+ Install the components your project uses. Provider adapters are registered explicitly;
5
+ the agent and harness do not install or register vendor SDKs.
6
+
7
+ ```sh
8
+ pnpm add @modelprofile.com/flexharness
9
+ ```
10
+
11
+ See the [toolbox usage and migration guide](https://code.foss.global/modelprofile.com/flexharness#readme)
12
+ for composition examples and the SmartAI/SmartAgent migration map.
13
+
14
+ ## Issue Reporting and Security
15
+
16
+ Report issues and security concerns through [community.foss.global](https://community.foss.global).
17
+
18
+ ## License and Legal Information
19
+
20
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.
21
+
22
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
23
+
24
+ ### Trademarks
25
+
26
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
27
+
28
+ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
29
+
30
+ ### Company Information
31
+
32
+ Task Venture Capital GmbH<br>
33
+ Registered at District Court Bremen HRB 35230 HB, Germany
34
+
35
+ For any legal inquiries or further information, please contact us via email at hello@task.vc.
36
+
37
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
@@ -0,0 +1,53 @@
1
+ import {
2
+ createMistralOcrEngine,
3
+ type ISmartAiMistralOcrOptions,
4
+ type ISmartAiMistralOcrRecognizeOptions,
5
+ type ISmartAiOcrEngine,
6
+ type ISmartAiOcrImageInput,
7
+ type ISmartAiOcrResult,
8
+ type TSmartAiOcrImageMimeType,
9
+ } from './ocr.mistral.js';
10
+
11
+ export interface IImageOcrOptions {
12
+ engine?: ISmartAiOcrEngine;
13
+ mistralOptions?: ISmartAiMistralOcrOptions;
14
+ }
15
+
16
+ export interface IImageOcrRecognitionOptions extends IImageOcrOptions {
17
+ recognizeOptions?: ISmartAiMistralOcrRecognizeOptions;
18
+ }
19
+
20
+ export interface IImageOcrBytesOptions extends IImageOcrRecognitionOptions {
21
+ mimeType: TSmartAiOcrImageMimeType;
22
+ }
23
+
24
+ /** Image recognition without a local OCR executable or PDF dependency. */
25
+ export class ImageOcr {
26
+ constructor(private readonly options: IImageOcrOptions = {}) {}
27
+
28
+ public async recognizeImage(
29
+ input: ISmartAiOcrImageInput,
30
+ options: IImageOcrRecognitionOptions = {},
31
+ ): Promise<ISmartAiOcrResult> {
32
+ const engine = options.engine ?? this.options.engine ?? createMistralOcrEngine({
33
+ ...this.options.mistralOptions,
34
+ ...options.mistralOptions,
35
+ });
36
+ return engine.recognizeImage(input, options.recognizeOptions);
37
+ }
38
+
39
+ /** Accepts Uint8Array, including Node Buffer, without importing Node builtins. */
40
+ public async recognizeImageBytes(
41
+ bytes: Uint8Array,
42
+ options: IImageOcrBytesOptions,
43
+ ): Promise<ISmartAiOcrResult> {
44
+ const chunks: string[] = [];
45
+ for (let offset = 0; offset < bytes.length; offset += 8192) {
46
+ chunks.push(String.fromCharCode(...bytes.subarray(offset, offset + 8192)));
47
+ }
48
+ return this.recognizeImage({
49
+ dataBase64: btoa(chunks.join('')),
50
+ mimeType: options.mimeType,
51
+ }, options);
52
+ }
53
+ }
@@ -0,0 +1,2 @@
1
+ export * from './ocr.mistral.js';
2
+ export * from './classes.imageocr.js';
@@ -0,0 +1,192 @@
1
+ export type TSmartAiOcrImageMimeType =
2
+ | 'image/png'
3
+ | 'image/jpeg'
4
+ | 'image/webp'
5
+ | 'image/gif'
6
+ | string;
7
+
8
+ export type TSmartAiMistralOcrTableFormat = 'markdown' | 'html';
9
+
10
+ export type TSmartAiMistralOcrConfidenceScoresGranularity = 'page' | 'word';
11
+
12
+ export interface ISmartAiOcrImageInput {
13
+ dataBase64: string;
14
+ mimeType: TSmartAiOcrImageMimeType;
15
+ }
16
+
17
+ export interface ISmartAiOcrPageResult {
18
+ index: number;
19
+ text: string;
20
+ confidence?: number;
21
+ }
22
+
23
+ export interface ISmartAiOcrResult<TRaw = unknown> {
24
+ text: string;
25
+ confidence?: number;
26
+ pages: ISmartAiOcrPageResult[];
27
+ raw: TRaw;
28
+ }
29
+
30
+ export interface ISmartAiOcrEngine {
31
+ recognizeImage: (
32
+ input: ISmartAiOcrImageInput,
33
+ options?: ISmartAiMistralOcrRecognizeOptions
34
+ ) => Promise<ISmartAiOcrResult<IMistralOcrResponse>>;
35
+ }
36
+
37
+ export interface IMistralOcrPageConfidenceScores {
38
+ average_page_confidence_score?: number;
39
+ averagePageConfidenceScore?: number;
40
+ minimum_page_confidence_score?: number;
41
+ minimumPageConfidenceScore?: number;
42
+ }
43
+
44
+ export interface IMistralOcrPageResponse {
45
+ index: number;
46
+ markdown: string;
47
+ confidence_scores?: IMistralOcrPageConfidenceScores | null;
48
+ confidenceScores?: IMistralOcrPageConfidenceScores | null;
49
+ }
50
+
51
+ export interface IMistralOcrResponse {
52
+ pages: IMistralOcrPageResponse[];
53
+ model: string;
54
+ document_annotation?: unknown;
55
+ documentAnnotation?: unknown;
56
+ usage_info?: unknown;
57
+ usageInfo?: unknown;
58
+ }
59
+
60
+ export interface IMistralOcrRequest {
61
+ model: string;
62
+ document: {
63
+ type: 'image_url';
64
+ image_url: string;
65
+ };
66
+ include_image_base64?: boolean;
67
+ table_format?: TSmartAiMistralOcrTableFormat;
68
+ extract_header?: boolean;
69
+ extract_footer?: boolean;
70
+ confidence_scores_granularity?: TSmartAiMistralOcrConfidenceScoresGranularity;
71
+ }
72
+
73
+ export interface ISmartAiMistralOcrTransport {
74
+ process: (request: IMistralOcrRequest) => Promise<IMistralOcrResponse>;
75
+ }
76
+
77
+ export interface ISmartAiMistralOcrOptions {
78
+ apiKey?: string;
79
+ model?: string;
80
+ endpointUrl?: string;
81
+ transport?: ISmartAiMistralOcrTransport;
82
+ includeImageBase64?: boolean;
83
+ tableFormat?: TSmartAiMistralOcrTableFormat;
84
+ extractHeader?: boolean;
85
+ extractFooter?: boolean;
86
+ confidenceScoresGranularity?: TSmartAiMistralOcrConfidenceScoresGranularity;
87
+ }
88
+
89
+ export interface ISmartAiMistralOcrRecognizeOptions {
90
+ includeImageBase64?: boolean;
91
+ tableFormat?: TSmartAiMistralOcrTableFormat;
92
+ extractHeader?: boolean;
93
+ extractFooter?: boolean;
94
+ confidenceScoresGranularity?: TSmartAiMistralOcrConfidenceScoresGranularity;
95
+ }
96
+
97
+ const defaultMistralOcrModel = 'mistral-ocr-latest';
98
+ const defaultMistralOcrEndpointUrl = 'https://api.mistral.ai/v1/ocr';
99
+
100
+ const createMistralOcrHttpTransport = (options: {
101
+ apiKey?: string;
102
+ endpointUrl?: string;
103
+ }): ISmartAiMistralOcrTransport => {
104
+ return {
105
+ process: async (request) => {
106
+ if (!options.apiKey) {
107
+ throw new Error('Mistral OCR requires an apiKey when no custom transport is provided.');
108
+ }
109
+
110
+ const response = await fetch(options.endpointUrl ?? defaultMistralOcrEndpointUrl, {
111
+ method: 'POST',
112
+ headers: {
113
+ Authorization: `Bearer ${options.apiKey}`,
114
+ 'Content-Type': 'application/json',
115
+ },
116
+ body: JSON.stringify(request),
117
+ });
118
+
119
+ if (!response.ok) {
120
+ const errorBody = await response.text();
121
+ throw new Error(`Mistral OCR request failed with status ${response.status}: ${errorBody}`);
122
+ }
123
+
124
+ return (await response.json()) as IMistralOcrResponse;
125
+ },
126
+ };
127
+ };
128
+
129
+ const getPageConfidence = (page: IMistralOcrPageResponse): number | undefined => {
130
+ const confidenceScores = page.confidence_scores ?? page.confidenceScores;
131
+ return (
132
+ confidenceScores?.average_page_confidence_score ??
133
+ confidenceScores?.averagePageConfidenceScore
134
+ );
135
+ };
136
+
137
+ export const createMistralOcrEngine = (
138
+ options: ISmartAiMistralOcrOptions = {}
139
+ ): ISmartAiOcrEngine => {
140
+ const transport =
141
+ options.transport ??
142
+ createMistralOcrHttpTransport({
143
+ apiKey: options.apiKey,
144
+ endpointUrl: options.endpointUrl,
145
+ });
146
+ const model = options.model ?? defaultMistralOcrModel;
147
+
148
+ return {
149
+ recognizeImage: async (input, recognizeOptions = {}) => {
150
+ if (!input.dataBase64) {
151
+ throw new Error('Mistral OCR image input requires dataBase64.');
152
+ }
153
+ if (!input.mimeType) {
154
+ throw new Error('Mistral OCR image input requires mimeType.');
155
+ }
156
+
157
+ const response = await transport.process({
158
+ model,
159
+ document: {
160
+ type: 'image_url',
161
+ image_url: `data:${input.mimeType};base64,${input.dataBase64}`,
162
+ },
163
+ include_image_base64:
164
+ recognizeOptions.includeImageBase64 ?? options.includeImageBase64 ?? false,
165
+ table_format: recognizeOptions.tableFormat ?? options.tableFormat,
166
+ extract_header: recognizeOptions.extractHeader ?? options.extractHeader,
167
+ extract_footer: recognizeOptions.extractFooter ?? options.extractFooter,
168
+ confidence_scores_granularity:
169
+ recognizeOptions.confidenceScoresGranularity ?? options.confidenceScoresGranularity,
170
+ });
171
+
172
+ const pages = response.pages.map((page) => ({
173
+ index: page.index,
174
+ text: page.markdown,
175
+ confidence: getPageConfidence(page),
176
+ }));
177
+ const pageConfidences = pages
178
+ .map((page) => page.confidence)
179
+ .filter((confidence): confidence is number => typeof confidence === 'number');
180
+ const confidence = pageConfidences.length
181
+ ? pageConfidences.reduce((sum, value) => sum + value, 0) / pageConfidences.length
182
+ : undefined;
183
+
184
+ return {
185
+ text: pages.map((page) => page.text).join('\n\n').trim(),
186
+ confidence,
187
+ pages,
188
+ raw: response,
189
+ };
190
+ },
191
+ };
192
+ };
@@ -0,0 +1,48 @@
1
+ Image OCR with Mistral or an injected recognition engine. This subpath imports no runtime dependencies and works with Node buffers and browser byte arrays.
2
+
3
+ Part of the [FlexHarness toolbox](https://code.foss.global/modelprofile.com/flexharness).
4
+ Install the components your project uses. Provider adapters are registered explicitly;
5
+ the agent and harness do not install or register vendor SDKs.
6
+
7
+ ```sh
8
+ pnpm add @modelprofile.com/flexharness
9
+ ```
10
+
11
+ ```typescript
12
+ import { ImageOcr } from '@modelprofile.com/flexharness/ocr';
13
+
14
+ const ocr = new ImageOcr({ mistralOptions: { apiKey: process.env.MISTRAL_API_KEY } });
15
+ const result = await ocr.recognizeImageBytes(imageBytes, { mimeType: 'image/png' });
16
+ console.log(result.text);
17
+ ```
18
+
19
+ `ImageOcr` replaces SmartOCR's `recognizeImageBufferWithSmartAi`. Pass credentials explicitly; environment lookup belongs to the caller. Browser applications should supply an authenticated server transport instead of embedding a private API key.
20
+
21
+ Constructor and call options accept `engine` or `mistralOptions`. A per-call engine takes precedence over the constructor engine. Otherwise Mistral settings merge, with per-call settings taking precedence. `recognizeOptions` controls each request. `recognizeImage` accepts an existing `{ dataBase64, mimeType }` image; `createMistralOcrEngine` remains available for lower-level integrations.
22
+
23
+ Model-based PDF text extraction lives in `@modelprofile.com/flexharness/documents`. Native `ocrmypdf` processing remains in `@push.rocks/smartocr`.
24
+
25
+ ## Issue Reporting and Security
26
+
27
+ Report issues and security concerns through [community.foss.global](https://community.foss.global).
28
+
29
+ ## License and Legal Information
30
+
31
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.
32
+
33
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
34
+
35
+ ### Trademarks
36
+
37
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
38
+
39
+ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
40
+
41
+ ### Company Information
42
+
43
+ Task Venture Capital GmbH<br>
44
+ Registered at District Court Bremen HRB 35230 HB, Germany
45
+
46
+ For any legal inquiries or further information, please contact us via email at hello@task.vc.
47
+
48
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
@@ -0,0 +1,49 @@
1
+ export { createBrowserTools } from './tool.browser.js';
2
+ export {
3
+ acquireToolExecutionContext,
4
+ ToolExecutionAdapterCleanupError,
5
+ } from '@modelprofile.com/flexharness-agent';
6
+ export type {
7
+ IToolExecutionAdapter,
8
+ IToolExecutionAdapterRequest,
9
+ IToolExecutionContextLease,
10
+ } from '@modelprofile.com/flexharness-agent';
11
+ export type { ICreateBrowserToolsOptions } from './tool.browser.js';
12
+ export { createFilesystemTools } from './tool.filesystem.js';
13
+ export type { ICreateFilesystemToolsOptions } from './tool.filesystem.js';
14
+ export { createShellTools } from './tool.shell.js';
15
+ export type { ICreateShellToolsOptions } from './tool.shell.js';
16
+ export type { ToolSet } from 'ai';
17
+ export { formatShellResult, formatToolOutput } from './tool.context.js';
18
+ export type {
19
+ IBrowserToolInput,
20
+ IShellCommand,
21
+ IShellFinishedResult,
22
+ IShellStartedResult,
23
+ IToolBrowserContext,
24
+ IToolBrowserRunOptions,
25
+ IToolExecutionContext,
26
+ IToolFilesystemContext,
27
+ IToolFilesystemListOptions,
28
+ IToolFilesystemReadOptions,
29
+ IToolInvocationOptions,
30
+ IToolJobContext,
31
+ IToolJobEvent,
32
+ IToolJobOutputEvent,
33
+ IToolJobHandle,
34
+ IToolJobRequest,
35
+ IToolJobState,
36
+ IToolPermissionRequest,
37
+ IToolRunOptions,
38
+ IToolShellContext,
39
+ IToolShellResult,
40
+ TBrowserToolAction,
41
+ TToolJobEvent,
42
+ TToolJobEventListener,
43
+ } from './tool.context.js';
44
+ export { InMemoryToolJobStore, ToolJobStoreConflictError } from '@modelprofile.com/flexharness-agent';
45
+ export type { IToolJobSnapshot, IToolJobStore } from '@modelprofile.com/flexharness-agent';
46
+ export { httpTool } from './tool.http.js';
47
+ export { jsonTool } from './tool.json.js';
48
+ export { truncateOutput } from './plugins.js';
49
+ export type { ITruncateResult } from './plugins.js';
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ import { tool } from 'ai';
3
+ import * as smartrequest from '@push.rocks/smartrequest';
4
+ import { truncateOutput } from './utils.truncation.js';
5
+ export { z, tool, smartrequest, truncateOutput };
6
+ export type { ToolExecutionOptions, ToolSet } from 'ai';
7
+ export type { ITruncateResult } from './utils.truncation.js';
@@ -0,0 +1,37 @@
1
+ Tool factories for host-supplied filesystem, shell and browser contexts, HTTP and JSON.
2
+
3
+ Part of the [FlexHarness toolbox](https://code.foss.global/modelprofile.com/flexharness).
4
+ Install the components your project uses. Provider adapters are registered explicitly;
5
+ the agent and harness do not install or register vendor SDKs.
6
+
7
+ ```sh
8
+ pnpm add @modelprofile.com/flexharness
9
+ ```
10
+
11
+ See the [toolbox usage and migration guide](https://code.foss.global/modelprofile.com/flexharness#readme)
12
+ for composition examples and the SmartAI/SmartAgent migration map.
13
+
14
+ ## Issue Reporting and Security
15
+
16
+ Report issues and security concerns through [community.foss.global](https://community.foss.global).
17
+
18
+ ## License and Legal Information
19
+
20
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.
21
+
22
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
23
+
24
+ ### Trademarks
25
+
26
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
27
+
28
+ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
29
+
30
+ ### Company Information
31
+
32
+ Task Venture Capital GmbH<br>
33
+ Registered at District Court Bremen HRB 35230 HB, Germany
34
+
35
+ For any legal inquiries or further information, please contact us via email at hello@task.vc.
36
+
37
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
@@ -0,0 +1,159 @@
1
+ import * as plugins from './plugins.js';
2
+ import {
3
+ formatToolOutput,
4
+ type IBrowserToolInput,
5
+ type IToolExecutionContext,
6
+ type IToolInvocationOptions,
7
+ type TBrowserToolAction,
8
+ } from './tool.context.js';
9
+
10
+ export interface ICreateBrowserToolsOptions {
11
+ /** Maximum output lines before truncating. */
12
+ maxLines?: number;
13
+ /** Maximum output bytes before truncating. */
14
+ maxBytes?: number;
15
+ /** Browser actions exposed by the tool. Defaults to every supported action. */
16
+ allowedActions?: readonly TBrowserToolAction[];
17
+ }
18
+
19
+ const browserActions = [
20
+ 'navigate',
21
+ 'snapshot',
22
+ 'screenshot',
23
+ 'click',
24
+ 'fill',
25
+ 'press',
26
+ 'evaluate',
27
+ 'close',
28
+ ] as const satisfies readonly TBrowserToolAction[];
29
+
30
+ export function createBrowserTools(context: IToolExecutionContext, options: ICreateBrowserToolsOptions = {}): plugins.ToolSet {
31
+ const allowedActions = normalizeAllowedBrowserActions(options.allowedActions);
32
+ const allowedActionList = [...allowedActions].join(', ');
33
+ const defaultAction = allowedActions.has('snapshot')
34
+ ? 'snapshot'
35
+ : allowedActions.values().next().value!;
36
+ const description = [
37
+ 'Control a browser supplied by the host execution context for web UI inspection and interaction.',
38
+ `Actions: ${allowedActionList}.`,
39
+ ...(allowedActions.has('snapshot')
40
+ ? ['Use snapshot after navigation or interaction to inspect page text and interactive selectors before choosing the next action.']
41
+ : []),
42
+ ...(hasBrowserSideEffectAction(allowedActions)
43
+ ? ['Actions that navigate or modify page state require host permission when configured.']
44
+ : []),
45
+ ].join(' ');
46
+ const inputSchema = plugins.z.object({
47
+ action: plugins.z.string().default(defaultAction).describe(`Action: ${allowedActionList}`),
48
+ url: plugins.z.string().optional().describe('Optional target URL'),
49
+ selector: plugins.z.string().optional().describe('Optional element selector'),
50
+ text: plugins.z.string().optional().describe('Optional text, key, or mode hint'),
51
+ script: plugins.z.string().optional().describe('Optional host-defined script input'),
52
+ timeoutMs: plugins.z.number().optional().describe('Optional action timeout in milliseconds'),
53
+ });
54
+ return {
55
+ browser: plugins.tool({
56
+ description,
57
+ inputSchema,
58
+ execute: async (
59
+ input: IBrowserToolInput,
60
+ invocationOptions?: plugins.ToolExecutionOptions<unknown>,
61
+ ) => {
62
+ if (!context.browser) {
63
+ throw new Error('Browser tool is not available in this execution context.');
64
+ }
65
+ const action = normalizeBrowserAction(input.action, allowedActions, defaultAction);
66
+ const abortSignal = invocationOptions?.abortSignal ?? context.abortSignal;
67
+ await requestBrowserPermission(context, { ...input, action }, {
68
+ toolCallId: invocationOptions?.toolCallId,
69
+ abortSignal,
70
+ });
71
+ const result = await context.browser.execute({ ...input, action }, {
72
+ timeoutMs: input.timeoutMs,
73
+ toolCallId: invocationOptions?.toolCallId,
74
+ abortSignal,
75
+ });
76
+ return plugins.truncateOutput(formatToolOutput(result), {
77
+ maxLines: options.maxLines,
78
+ maxBytes: options.maxBytes,
79
+ }).content;
80
+ },
81
+ }),
82
+ };
83
+ }
84
+
85
+ const normalizeAllowedBrowserActions = (
86
+ actionsArg: readonly TBrowserToolAction[] | undefined,
87
+ ): ReadonlySet<TBrowserToolAction> => {
88
+ const actions = actionsArg ?? browserActions;
89
+ if (!Array.isArray(actions) || actions.length === 0) {
90
+ throw new Error('allowedActions must contain at least one supported browser action.');
91
+ }
92
+ const allowedActions = new Set<TBrowserToolAction>();
93
+ for (const action of actions) {
94
+ if (!browserActions.includes(action)) {
95
+ throw new Error(`Unsupported allowed browser action: ${String(action)}.`);
96
+ }
97
+ allowedActions.add(action);
98
+ }
99
+ return allowedActions;
100
+ };
101
+
102
+ const hasBrowserSideEffectAction = (actionsArg: ReadonlySet<TBrowserToolAction>): boolean => {
103
+ for (const action of ['navigate', 'click', 'fill', 'press', 'evaluate', 'close'] as const) {
104
+ if (actionsArg.has(action)) return true;
105
+ }
106
+ return false;
107
+ };
108
+
109
+ const normalizeBrowserAction = (
110
+ input: unknown,
111
+ allowedActions: ReadonlySet<TBrowserToolAction>,
112
+ defaultAction: TBrowserToolAction,
113
+ ): TBrowserToolAction => {
114
+ const action = typeof input === 'string' && input.trim()
115
+ ? input.trim().toLowerCase()
116
+ : defaultAction;
117
+ if (allowedActions.has(action as TBrowserToolAction)) {
118
+ return action as TBrowserToolAction;
119
+ }
120
+ throw new Error(`Unsupported browser action: ${String(input)}. Use one of: ${[...allowedActions].join(', ')}.`);
121
+ };
122
+
123
+ const requestBrowserPermission = async (
124
+ context: IToolExecutionContext,
125
+ input: IBrowserToolInput & { action: TBrowserToolAction },
126
+ invocationOptions: IToolInvocationOptions,
127
+ ): Promise<void> => {
128
+ if (!context.requestPermission) return;
129
+ if (input.action === 'snapshot' || input.action === 'screenshot') return;
130
+ const titleByAction: Record<TBrowserToolAction, string> = {
131
+ navigate: 'Navigate browser',
132
+ snapshot: 'Inspect browser',
133
+ screenshot: 'Capture browser screenshot',
134
+ click: 'Click browser element',
135
+ fill: 'Fill browser element',
136
+ press: 'Press browser key',
137
+ evaluate: 'Evaluate browser JavaScript',
138
+ close: 'Close browser session',
139
+ };
140
+ await context.requestPermission({
141
+ type: 'browser',
142
+ title: titleByAction[input.action],
143
+ toolCallId: invocationOptions.toolCallId,
144
+ abortSignal: invocationOptions.abortSignal,
145
+ metadata: {
146
+ action: input.action,
147
+ url: input.url,
148
+ selector: input.selector,
149
+ key: input.action === 'press' ? input.text : undefined,
150
+ textLength: input.action === 'fill' ? input.text?.length ?? 0 : undefined,
151
+ scriptPreview: input.action === 'evaluate' && input.script ? compactMetadataText(input.script) : undefined,
152
+ },
153
+ });
154
+ };
155
+
156
+ const compactMetadataText = (text: string): string => {
157
+ const compacted = text.replace(/\s+/g, ' ').trim();
158
+ return compacted.length > 160 ? `${compacted.slice(0, 157)}...` : compacted;
159
+ };
@@ -0,0 +1,23 @@
1
+ import type { IToolShellResult } from '@modelprofile.com/flexharness-agent';
2
+ export type * from '@modelprofile.com/flexharness-agent';
3
+
4
+ export const formatShellResult = (result: IToolShellResult | string): string => {
5
+ if (typeof result === 'string') return result;
6
+ if (result.exitCode === 0) return result.stdout;
7
+ return [
8
+ `Exit code: ${result.exitCode}`,
9
+ result.signal ? `Signal: ${result.signal}` : '',
10
+ `stdout:\n${result.stdout}`,
11
+ `stderr:\n${result.stderr ?? ''}`,
12
+ ].filter(Boolean).join('\n');
13
+ };
14
+
15
+ export const formatToolOutput = (output: unknown): string => {
16
+ if (typeof output === 'string') return output;
17
+ try {
18
+ return JSON.stringify(output, undefined, 2);
19
+ } catch {
20
+ return String(output);
21
+ }
22
+ };
23
+