@amaster.ai/pi-attachments 0.1.2-beta.1 → 0.1.2-beta.11

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 (62) hide show
  1. package/dist/classify.d.ts +18 -7
  2. package/dist/classify.d.ts.map +1 -1
  3. package/dist/classify.js +172 -93
  4. package/dist/classify.js.map +1 -1
  5. package/dist/extension.d.ts +3 -0
  6. package/dist/extension.d.ts.map +1 -0
  7. package/dist/extension.js +150 -0
  8. package/dist/extension.js.map +1 -0
  9. package/dist/index.d.ts +2 -7
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -5
  12. package/dist/index.js.map +1 -1
  13. package/package.json +29 -6
  14. package/README.md +0 -37
  15. package/dist/diagnostics.d.ts +0 -8
  16. package/dist/diagnostics.d.ts.map +0 -1
  17. package/dist/diagnostics.js +0 -30
  18. package/dist/diagnostics.js.map +0 -1
  19. package/dist/http.d.ts +0 -10
  20. package/dist/http.d.ts.map +0 -1
  21. package/dist/http.js +0 -44
  22. package/dist/http.js.map +0 -1
  23. package/dist/local-store.d.ts +0 -20
  24. package/dist/local-store.d.ts.map +0 -1
  25. package/dist/local-store.js +0 -121
  26. package/dist/local-store.js.map +0 -1
  27. package/dist/multipart.d.ts +0 -9
  28. package/dist/multipart.d.ts.map +0 -1
  29. package/dist/multipart.js +0 -48
  30. package/dist/multipart.js.map +0 -1
  31. package/dist/normalize.d.ts +0 -7
  32. package/dist/normalize.d.ts.map +0 -1
  33. package/dist/normalize.js +0 -83
  34. package/dist/normalize.js.map +0 -1
  35. package/dist/parser.d.ts +0 -12
  36. package/dist/parser.d.ts.map +0 -1
  37. package/dist/parser.js +0 -168
  38. package/dist/parser.js.map +0 -1
  39. package/dist/prompt.d.ts +0 -10
  40. package/dist/prompt.d.ts.map +0 -1
  41. package/dist/prompt.js +0 -38
  42. package/dist/prompt.js.map +0 -1
  43. package/dist/remote-fetch.d.ts +0 -10
  44. package/dist/remote-fetch.d.ts.map +0 -1
  45. package/dist/remote-fetch.js +0 -35
  46. package/dist/remote-fetch.js.map +0 -1
  47. package/dist/routes.d.ts +0 -14
  48. package/dist/routes.d.ts.map +0 -1
  49. package/dist/routes.js +0 -91
  50. package/dist/routes.js.map +0 -1
  51. package/dist/service.d.ts +0 -9
  52. package/dist/service.d.ts.map +0 -1
  53. package/dist/service.js +0 -140
  54. package/dist/service.js.map +0 -1
  55. package/dist/types.d.ts +0 -85
  56. package/dist/types.d.ts.map +0 -1
  57. package/dist/types.js +0 -2
  58. package/dist/types.js.map +0 -1
  59. package/dist/upload-proxy.d.ts +0 -19
  60. package/dist/upload-proxy.d.ts.map +0 -1
  61. package/dist/upload-proxy.js +0 -105
  62. package/dist/upload-proxy.js.map +0 -1
package/dist/parser.js DELETED
@@ -1,168 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import JSZip from 'jszip';
3
- import { isTextLikeAttachment } from './classify.js';
4
- export class BasicAttachmentParser {
5
- async parse(input) {
6
- if (isPptxAttachment(input.name, input.mimeType)) {
7
- return parsePptxText(input.path);
8
- }
9
- if (isLegacyPptAttachment(input.name, input.mimeType)) {
10
- return parseLegacyPptText(input.path);
11
- }
12
- if (!isTextLikeAttachment(input.name, input.mimeType)) {
13
- throw new Error(`No basic parser available for ${input.name}`);
14
- }
15
- const raw = await readFile(input.path, 'utf8');
16
- if (isDelimitedFile(input.name, input.mimeType)) {
17
- return {
18
- text: delimitedTextToMarkdown(raw, input.name.toLowerCase().endsWith('.tsv') ? '\t' : ','),
19
- };
20
- }
21
- return { text: raw };
22
- }
23
- }
24
- export class LiteParseAttachmentParser {
25
- fallback = new BasicAttachmentParser();
26
- async parse(input) {
27
- if (isPptxAttachment(input.name, input.mimeType)) {
28
- return parsePptxText(input.path);
29
- }
30
- if (isTextLikeAttachment(input.name, input.mimeType)) {
31
- return this.fallback.parse(input);
32
- }
33
- const { LiteParse } = await import('@llamaindex/liteparse');
34
- const parser = new LiteParse({
35
- outputFormat: input.format ?? 'text',
36
- ocrEnabled: input.ocr !== 'off',
37
- maxPages: input.maxPages,
38
- preciseBoundingBox: input.format === 'json',
39
- });
40
- try {
41
- const result = await parser.parse(input.path, true);
42
- return {
43
- text: result.text,
44
- pageCount: result.pages.length,
45
- };
46
- }
47
- catch (error) {
48
- if (isLegacyPptAttachment(input.name, input.mimeType)) {
49
- return parseLegacyPptText(input.path);
50
- }
51
- throw error;
52
- }
53
- }
54
- }
55
- function isDelimitedFile(name, mimeType) {
56
- const lowerMime = mimeType?.toLowerCase();
57
- return (lowerMime === 'text/csv' ||
58
- lowerMime === 'application/csv' ||
59
- lowerMime === 'text/tab-separated-values' ||
60
- /\.(csv|tsv)$/i.test(name));
61
- }
62
- function isPptxAttachment(name, mimeType) {
63
- const lowerMime = mimeType?.split(';')[0]?.trim().toLowerCase();
64
- return (lowerMime === 'application/vnd.openxmlformats-officedocument.presentationml.presentation' ||
65
- /\.pptx$/i.test(name));
66
- }
67
- function isLegacyPptAttachment(name, mimeType) {
68
- const lowerMime = mimeType?.split(';')[0]?.trim().toLowerCase();
69
- return lowerMime === 'application/vnd.ms-powerpoint' || /\.ppt$/i.test(name);
70
- }
71
- async function parsePptxText(filePath) {
72
- const zip = await JSZip.loadAsync(await readFile(filePath));
73
- const slideEntries = Object.values(zip.files)
74
- .filter((entry) => /^ppt\/slides\/slide\d+\.xml$/i.test(entry.name))
75
- .sort((a, b) => slideNumber(a.name) - slideNumber(b.name));
76
- const slides = [];
77
- for (const entry of slideEntries) {
78
- const xml = await entry.async('text');
79
- const textRuns = extractPresentationText(xml);
80
- const text = textRuns.join('\n').trim();
81
- if (text) {
82
- slides.push(`Slide ${slideNumber(entry.name)}:\n${text}`);
83
- }
84
- }
85
- return {
86
- text: slides.join('\n\n') || '[No readable text found in presentation slides]',
87
- pageCount: slideEntries.length,
88
- };
89
- }
90
- async function parseLegacyPptText(filePath) {
91
- const data = await readFile(filePath);
92
- const text = data
93
- .toString('latin1')
94
- .match(/[ -~\t]{4,}/g)
95
- ?.map((value) => value.trim())
96
- .filter((value, index, all) => value.length > 3 && all.indexOf(value) === index)
97
- .slice(0, 400)
98
- .join('\n') ?? '';
99
- return {
100
- text: text || '[No readable text found in legacy PowerPoint file]',
101
- };
102
- }
103
- function slideNumber(name) {
104
- return Number(name.match(/slide(\d+)\.xml$/i)?.[1] ?? 0);
105
- }
106
- function extractPresentationText(xml) {
107
- return [...xml.matchAll(/<a:t[^>]*>([\s\S]*?)<\/a:t>/g)]
108
- .map((match) => decodeXmlText(match[1] ?? '').trim())
109
- .filter(Boolean);
110
- }
111
- function decodeXmlText(value) {
112
- return value
113
- .replace(/&lt;/g, '<')
114
- .replace(/&gt;/g, '>')
115
- .replace(/&quot;/g, '"')
116
- .replace(/&apos;/g, "'")
117
- .replace(/&amp;/g, '&');
118
- }
119
- function delimitedTextToMarkdown(value, delimiter) {
120
- const rows = value
121
- .split(/\r?\n/)
122
- .filter((line) => line.length > 0)
123
- .map((line) => splitDelimitedLine(line, delimiter));
124
- if (rows.length === 0) {
125
- return '';
126
- }
127
- const width = Math.max(...rows.map((row) => row.length), 1);
128
- const normalized = rows.map((row) => Array.from({ length: width }, (_value, index) => formatMarkdownCell(row[index])));
129
- const header = normalized[0] ?? [];
130
- const body = normalized.slice(1);
131
- return [
132
- `| ${header.join(' | ')} |`,
133
- `| ${header.map(() => '---').join(' | ')} |`,
134
- ...body.map((row) => `| ${row.join(' | ')} |`),
135
- ].join('\n');
136
- }
137
- function splitDelimitedLine(line, delimiter) {
138
- const cells = [];
139
- let current = '';
140
- let quoted = false;
141
- for (let index = 0; index < line.length; index += 1) {
142
- const char = line[index];
143
- if (char === '"') {
144
- if (quoted && line[index + 1] === '"') {
145
- current += '"';
146
- index += 1;
147
- }
148
- else {
149
- quoted = !quoted;
150
- }
151
- continue;
152
- }
153
- if (!quoted && char === delimiter) {
154
- cells.push(current);
155
- current = '';
156
- continue;
157
- }
158
- current += char;
159
- }
160
- cells.push(current);
161
- return cells;
162
- }
163
- function formatMarkdownCell(value) {
164
- return String(value ?? '')
165
- .replace(/\r?\n/g, ' ')
166
- .replace(/\|/g, '\\|');
167
- }
168
- //# sourceMappingURL=parser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
package/dist/prompt.d.ts DELETED
@@ -1,10 +0,0 @@
1
- import type { PreparedAttachmentBundle } from './types.js';
2
- export declare function renderAttachmentPrompt(message: string, bundle: PreparedAttachmentBundle): string;
3
- export declare function attachmentHeader(input: {
4
- index: number;
5
- name: string;
6
- mimeType?: string;
7
- size?: number;
8
- }): string;
9
- export declare function truncateText(value: string, maxChars: number): string;
10
- //# sourceMappingURL=prompt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAuBhG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,MAAM,CAQT;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKpE"}
package/dist/prompt.js DELETED
@@ -1,38 +0,0 @@
1
- export function renderAttachmentPrompt(message, bundle) {
2
- if (bundle.attachments.length === 0) {
3
- return message;
4
- }
5
- const blocks = bundle.promptBlocks.length > 0 ? bundle.promptBlocks : ['No attachment content was available.'];
6
- const currentTurnImageGuidance = bundle.images.length > 0
7
- ? [
8
- 'Current-turn image inputs are attached as model-visible image content.',
9
- 'Ignore stale earlier statements that images were unsupported, unavailable, or could only be inspected with file tools.',
10
- ].join(' ')
11
- : undefined;
12
- return [
13
- message,
14
- '',
15
- 'Uploaded attachments for this turn:',
16
- currentTurnImageGuidance,
17
- blocks.join('\n\n---\n\n'),
18
- ]
19
- .filter(Boolean)
20
- .join('\n')
21
- .trim();
22
- }
23
- export function attachmentHeader(input) {
24
- return [
25
- `Attachment ${input.index + 1}: ${input.name}`,
26
- input.mimeType ? `mimeType=${input.mimeType}` : undefined,
27
- input.size !== undefined ? `size=${input.size}` : undefined,
28
- ]
29
- .filter(Boolean)
30
- .join(' ');
31
- }
32
- export function truncateText(value, maxChars) {
33
- if (value.length <= maxChars) {
34
- return value;
35
- }
36
- return `${value.slice(0, maxChars)}\n\n[truncated after ${maxChars} characters]`;
37
- }
38
- //# sourceMappingURL=prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,sBAAsB,CAAC,OAAe,EAAE,MAAgC;IACtF,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,MAAM,GACV,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC;IAClG,MAAM,wBAAwB,GAC5B,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACtB,CAAC,CAAC;YACE,wEAAwE;YACxE,wHAAwH;SACzH,CAAC,IAAI,CAAC,GAAG,CAAC;QACb,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO;QACL,OAAO;QACP,EAAE;QACF,qCAAqC;QACrC,wBAAwB;QACxB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;KAC3B;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC;SACV,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAKhC;IACC,OAAO;QACL,cAAc,KAAK,CAAC,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,EAAE;QAC9C,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;QACzD,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;KAC5D;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,QAAgB;IAC1D,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,wBAAwB,QAAQ,cAAc,CAAC;AACnF,CAAC"}
@@ -1,10 +0,0 @@
1
- export declare function fetchRemoteAttachment(input: {
2
- url: string;
3
- fallbackMimeType?: string;
4
- maxBytes: number;
5
- timeoutMs: number;
6
- }): Promise<{
7
- data: Buffer;
8
- mimeType?: string;
9
- }>;
10
- //# sourceMappingURL=remote-fetch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-fetch.d.ts","sourceRoot":"","sources":["../src/remote-fetch.ts"],"names":[],"mappings":"AAAA,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA4B/C"}
@@ -1,35 +0,0 @@
1
- export async function fetchRemoteAttachment(input) {
2
- const controller = new AbortController();
3
- const timer = setTimeout(() => controller.abort(), input.timeoutMs);
4
- try {
5
- const response = await fetch(input.url, { signal: controller.signal });
6
- if (!response.ok) {
7
- throw new Error(`HTTP ${response.status}`);
8
- }
9
- const contentLength = Number(response.headers.get('content-length') ?? 0);
10
- if (contentLength > input.maxBytes) {
11
- throw new Error(`attachment exceeds ${input.maxBytes} bytes`);
12
- }
13
- const data = Buffer.from(await response.arrayBuffer());
14
- if (data.byteLength > input.maxBytes) {
15
- throw new Error(`attachment exceeds ${input.maxBytes} bytes`);
16
- }
17
- const mimeType = trimToUndefined(response.headers.get('content-type')?.split(';')[0]) ??
18
- input.fallbackMimeType;
19
- return { data, ...(mimeType ? { mimeType } : {}) };
20
- }
21
- catch (error) {
22
- if (error instanceof Error && error.name === 'AbortError') {
23
- throw new Error(`attachment fetch timed out after ${input.timeoutMs}ms`);
24
- }
25
- throw error;
26
- }
27
- finally {
28
- clearTimeout(timer);
29
- }
30
- }
31
- function trimToUndefined(value) {
32
- const trimmed = value?.trim();
33
- return trimmed ? trimmed : undefined;
34
- }
35
- //# sourceMappingURL=remote-fetch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-fetch.js","sourceRoot":"","sources":["../src/remote-fetch.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAK3C;IACC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1E,IAAI,aAAa,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,CAAC,QAAQ,QAAQ,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;QACvD,IAAI,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,CAAC,QAAQ,QAAQ,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,QAAQ,GACZ,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACpE,KAAK,CAAC,gBAAgB,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAyB;IAChD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACvC,CAAC"}
package/dist/routes.d.ts DELETED
@@ -1,14 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import type { AttachmentService } from './service.js';
3
- import type { AttachmentContext } from './types.js';
4
- import { type AttachmentUploadAuth } from './upload-proxy.js';
5
- export declare function handleAttachmentRoutes(input: {
6
- request: IncomingMessage;
7
- response: ServerResponse;
8
- url: URL;
9
- service: AttachmentService;
10
- uploadAuth: AttachmentUploadAuth;
11
- maxUploadBodyBytes: number;
12
- context: AttachmentContext;
13
- }): Promise<boolean>;
14
- //# sourceMappingURL=routes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,KAAK,oBAAoB,EAAyB,MAAM,mBAAmB,CAAC;AAErF,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAClD,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,EAAE,GAAG,CAAC;IACT,OAAO,EAAE,iBAAiB,CAAC;IAC3B,UAAU,EAAE,oBAAoB,CAAC;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,iBAAiB,CAAC;CAC5B,GAAG,OAAO,CAAC,OAAO,CAAC,CAmEnB"}
package/dist/routes.js DELETED
@@ -1,91 +0,0 @@
1
- import { AttachmentHttpError, readRequestBody, writeJson } from './http.js';
2
- import { parseMultipartBoundary, parseMultipartFiles } from './multipart.js';
3
- import { proxyAttachmentUpload } from './upload-proxy.js';
4
- export async function handleAttachmentRoutes(input) {
5
- if (input.request.method === 'POST' && input.url.pathname === '/v1/attachments/upload') {
6
- if (input.service.config.storageMode === 'platform') {
7
- await proxyAttachmentUpload({
8
- request: input.request,
9
- response: input.response,
10
- uploadEndpoint: input.service.config.uploadEndpoint,
11
- allowInsecureLocalTls: input.service.config.allowInsecureLocalUploadTls,
12
- auth: input.uploadAuth,
13
- maxBodyBytes: input.maxUploadBodyBytes,
14
- });
15
- return true;
16
- }
17
- try {
18
- const files = await readMultipartFiles(input.request, input.maxUploadBodyBytes);
19
- const attachments = [];
20
- for (const file of files) {
21
- const record = await input.service.store.putBuffer({
22
- data: file.data,
23
- name: file.fileName,
24
- ...(file.contentType ? { mimeType: file.contentType } : {}),
25
- sessionId: input.context.sessionId,
26
- });
27
- attachments.push(toStoredAttachment(record));
28
- }
29
- writeJson(input.response, 200, { attachments, attachment: attachments[0] });
30
- }
31
- catch (error) {
32
- writeRouteError(input.response, error);
33
- }
34
- return true;
35
- }
36
- if (input.request.method === 'POST' && input.url.pathname === '/v1/attachments/register-local') {
37
- if (!input.service.config.desktopEnabled) {
38
- writeJson(input.response, 404, {
39
- error: 'local attachment registration is only available in desktop mode',
40
- });
41
- return true;
42
- }
43
- try {
44
- const body = JSON.parse((await readRequestBody(input.request, input.maxUploadBodyBytes)).toString('utf8'));
45
- const files = Array.isArray(body.files) ? body.files : [];
46
- const attachments = [];
47
- for (const file of files) {
48
- if (!file.path) {
49
- throw new Error('file path is required');
50
- }
51
- const record = await input.service.store.putFile({
52
- sourcePath: file.path,
53
- ...(file.name ? { name: file.name } : {}),
54
- ...(file.mimeType ? { mimeType: file.mimeType } : {}),
55
- sessionId: input.context.sessionId,
56
- });
57
- attachments.push(toStoredAttachment(record));
58
- }
59
- writeJson(input.response, 200, { attachments });
60
- }
61
- catch (error) {
62
- writeRouteError(input.response, error);
63
- }
64
- return true;
65
- }
66
- return false;
67
- }
68
- async function readMultipartFiles(request, maxBytes) {
69
- const boundary = parseMultipartBoundary(request.headers['content-type']);
70
- if (!boundary) {
71
- throw new AttachmentHttpError(400, 'multipart_boundary_required', 'multipart boundary is required');
72
- }
73
- return parseMultipartFiles(await readRequestBody(request, maxBytes), boundary);
74
- }
75
- function toStoredAttachment(record) {
76
- return {
77
- id: record.attachmentId,
78
- name: record.name,
79
- ...(record.mimeType ? { mimeType: record.mimeType } : {}),
80
- size: record.size,
81
- source: { kind: 'storedFile', attachmentId: record.attachmentId },
82
- };
83
- }
84
- function writeRouteError(response, error) {
85
- if (error instanceof AttachmentHttpError) {
86
- writeJson(response, error.statusCode, { error: error.message, code: error.code });
87
- return;
88
- }
89
- writeJson(response, 400, { error: error instanceof Error ? error.message : String(error) });
90
- }
91
- //# sourceMappingURL=routes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
package/dist/service.d.ts DELETED
@@ -1,9 +0,0 @@
1
- import { LocalAttachmentStore } from './local-store.js';
2
- import type { AttachmentContext, AttachmentServiceConfig, PreparedAttachmentBundle } from './types.js';
3
- export type AttachmentService = {
4
- readonly config: AttachmentServiceConfig;
5
- readonly store: LocalAttachmentStore;
6
- prepareForPrompt(attachments: unknown, context: AttachmentContext): Promise<PreparedAttachmentBundle>;
7
- };
8
- export declare function createAttachmentService(config: AttachmentServiceConfig): AttachmentService;
9
- //# sourceMappingURL=service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AASxD,OAAO,KAAK,EACV,iBAAiB,EAGjB,uBAAuB,EAEvB,wBAAwB,EAEzB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IACrC,gBAAgB,CACd,WAAW,EAAE,OAAO,EACpB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACtC,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,uBAAuB,GAAG,iBAAiB,CAK1F"}
package/dist/service.js DELETED
@@ -1,140 +0,0 @@
1
- import { isDocumentAttachment, isImageMimeType, resolveAttachmentMimeType } from './classify.js';
2
- import { LocalAttachmentStore } from './local-store.js';
3
- import { normalizeAttachments } from './normalize.js';
4
- import { BasicAttachmentParser, LiteParseAttachmentParser, } from './parser.js';
5
- import { attachmentHeader, truncateText } from './prompt.js';
6
- import { fetchRemoteAttachment } from './remote-fetch.js';
7
- export function createAttachmentService(config) {
8
- const store = new LocalAttachmentStore(config.localStoreDir);
9
- const parser = config.parser === 'liteparse' ? new LiteParseAttachmentParser() : new BasicAttachmentParser();
10
- return new DefaultAttachmentService(config, store, parser);
11
- }
12
- class DefaultAttachmentService {
13
- config;
14
- store;
15
- parser;
16
- constructor(config, store, parser) {
17
- this.config = config;
18
- this.store = store;
19
- this.parser = parser;
20
- }
21
- async prepareForPrompt(attachmentsInput, context) {
22
- const attachments = normalizeAttachments(attachmentsInput, this.config.maxAttachmentCount);
23
- const images = [];
24
- const promptBlocks = [];
25
- const failures = [];
26
- const telemetry = [];
27
- for (const [index, attachment] of attachments.entries()) {
28
- try {
29
- const result = await this.prepareAttachment(attachment, index, context);
30
- if (result.image) {
31
- images.push(result.image);
32
- }
33
- if (result.promptBlock) {
34
- promptBlocks.push(result.promptBlock);
35
- }
36
- telemetry.push(result.telemetry);
37
- }
38
- catch (error) {
39
- const reason = error instanceof Error ? error.message : String(error);
40
- failures.push({ attachmentId: attachment.id, name: attachment.name, reason });
41
- promptBlocks.push(`${attachmentHeader({ index, ...attachment })}\nContent: attachment could not be processed (${reason}).`);
42
- telemetry.push({
43
- id: attachment.id,
44
- name: attachment.name,
45
- status: 'failed',
46
- error: reason,
47
- });
48
- }
49
- }
50
- return { attachments, images, promptBlocks, failures, telemetry };
51
- }
52
- async prepareAttachment(attachment, index, context) {
53
- const header = attachmentHeader({ index, ...attachment });
54
- if (attachment.source.kind === 'inlineText') {
55
- const text = truncateText(attachment.source.text, this.config.maxTextChars);
56
- return {
57
- promptBlock: `${header}\nContent:\n${text}`,
58
- telemetry: attachmentTelemetry(attachment, {
59
- status: 'inline_text',
60
- textBytes: text.length,
61
- }),
62
- };
63
- }
64
- const local = await this.resolveToLocalFile(attachment, context);
65
- const mimeType = resolveAttachmentMimeType(local.name, local.mimeType ?? attachment.mimeType);
66
- if (isImageMimeType(mimeType)) {
67
- const { readFile } = await import('node:fs/promises');
68
- const data = await readFile(local.path);
69
- if (data.byteLength > this.config.maxBytes) {
70
- throw new Error(`attachment exceeds ${this.config.maxBytes} bytes`);
71
- }
72
- return {
73
- image: {
74
- type: 'image',
75
- data: data.toString('base64'),
76
- mimeType,
77
- },
78
- promptBlock: `${header}\nContent: image upload is attached directly as model-visible image content. Do not call file tools for this uploaded image.`,
79
- telemetry: attachmentTelemetry(attachment, { status: 'image', bytes: data.byteLength }),
80
- };
81
- }
82
- if (this.config.parseEnabled && isDocumentAttachment(local.name, mimeType)) {
83
- const parsed = await this.parser.parse({
84
- path: local.path,
85
- name: local.name,
86
- ...(mimeType ? { mimeType } : {}),
87
- format: 'text',
88
- ocr: this.config.ocr,
89
- maxPages: this.config.maxPages,
90
- });
91
- const text = truncateText(parsed.text, this.config.maxTextChars);
92
- return {
93
- promptBlock: `${header}\nContent:\n${text}`,
94
- telemetry: attachmentTelemetry(attachment, {
95
- status: 'parsed',
96
- textBytes: text.length,
97
- ...(parsed.pageCount !== undefined ? { pageCount: parsed.pageCount } : {}),
98
- }),
99
- };
100
- }
101
- return {
102
- promptBlock: `${header}\nContent: non-text attachment is available as metadata only.`,
103
- telemetry: attachmentTelemetry(attachment, { status: 'metadata_only' }),
104
- };
105
- }
106
- async resolveToLocalFile(attachment, context) {
107
- if (attachment.source.kind === 'storedFile') {
108
- return this.store.readRecord(attachment.source.attachmentId);
109
- }
110
- if (attachment.source.kind === 'remoteObject') {
111
- const fetched = await fetchRemoteAttachment({
112
- url: attachment.source.url,
113
- maxBytes: this.config.maxBytes,
114
- timeoutMs: this.config.fetchTimeoutMs,
115
- ...(attachment.mimeType ? { fallbackMimeType: attachment.mimeType } : {}),
116
- });
117
- return this.store.putBuffer({
118
- data: fetched.data,
119
- name: attachment.name,
120
- sessionId: context.sessionId,
121
- ...optionalMimeType(fetched.mimeType ?? attachment.mimeType),
122
- });
123
- }
124
- throw new Error('inline text attachment does not resolve to a local file');
125
- }
126
- }
127
- function optionalMimeType(mimeType) {
128
- return mimeType ? { mimeType } : {};
129
- }
130
- function attachmentTelemetry(attachment, extra) {
131
- return {
132
- id: attachment.id,
133
- name: attachment.name,
134
- ...(attachment.mimeType ? { mimeType: attachment.mimeType } : {}),
135
- ...(attachment.size !== undefined ? { size: attachment.size } : {}),
136
- sourceKind: attachment.source.kind,
137
- ...extra,
138
- };
139
- }
140
- //# sourceMappingURL=service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}