wicked-crew 0.15.8 → 0.16.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 (65) hide show
  1. package/dist/api/chat-attachments.d.ts +102 -0
  2. package/dist/api/chat-attachments.d.ts.map +1 -0
  3. package/dist/api/chat-attachments.js +438 -0
  4. package/dist/api/chat-attachments.js.map +1 -0
  5. package/dist/api/chat-history.d.ts +90 -0
  6. package/dist/api/chat-history.d.ts.map +1 -0
  7. package/dist/api/chat-history.js +279 -0
  8. package/dist/api/chat-history.js.map +1 -0
  9. package/dist/api/chat-transcripts.d.ts +4 -2
  10. package/dist/api/chat-transcripts.d.ts.map +1 -1
  11. package/dist/api/chat-transcripts.js +13 -2
  12. package/dist/api/chat-transcripts.js.map +1 -1
  13. package/dist/api/roster-standing.d.ts.map +1 -1
  14. package/dist/api/roster-standing.js +8 -1
  15. package/dist/api/roster-standing.js.map +1 -1
  16. package/dist/api/routes.d.ts +39 -0
  17. package/dist/api/routes.d.ts.map +1 -1
  18. package/dist/api/routes.js +478 -36
  19. package/dist/api/routes.js.map +1 -1
  20. package/dist/api/seat-agents.d.ts +11 -3
  21. package/dist/api/seat-agents.d.ts.map +1 -1
  22. package/dist/api/seat-agents.js +2 -0
  23. package/dist/api/seat-agents.js.map +1 -1
  24. package/dist/api/seat-bench-trail.d.ts +3 -1
  25. package/dist/api/seat-bench-trail.d.ts.map +1 -1
  26. package/dist/api/seat-bench-trail.js +27 -9
  27. package/dist/api/seat-bench-trail.js.map +1 -1
  28. package/dist/api/seat-health.d.ts +56 -1
  29. package/dist/api/seat-health.d.ts.map +1 -1
  30. package/dist/api/seat-health.js +147 -19
  31. package/dist/api/seat-health.js.map +1 -1
  32. package/dist/api/seat-standing.d.ts +11 -0
  33. package/dist/api/seat-standing.d.ts.map +1 -1
  34. package/dist/api/seat-standing.js +13 -6
  35. package/dist/api/seat-standing.js.map +1 -1
  36. package/dist/api/server.d.ts.map +1 -1
  37. package/dist/api/server.js +18 -0
  38. package/dist/api/server.js.map +1 -1
  39. package/dist/api/stall-watchdog.d.ts +10 -0
  40. package/dist/api/stall-watchdog.d.ts.map +1 -1
  41. package/dist/api/stall-watchdog.js +12 -0
  42. package/dist/api/stall-watchdog.js.map +1 -1
  43. package/dist/api/system-snapshot.d.ts +382 -0
  44. package/dist/api/system-snapshot.d.ts.map +1 -0
  45. package/dist/api/system-snapshot.js +1164 -0
  46. package/dist/api/system-snapshot.js.map +1 -0
  47. package/dist/core/deliver.d.ts.map +1 -1
  48. package/dist/core/deliver.js +5 -3
  49. package/dist/core/deliver.js.map +1 -1
  50. package/dist/editors/registry.d.ts +20 -20
  51. package/dist/studio/assets/{index-Bhwz-oBW.js → index-BnnXv6Ij.js} +242 -226
  52. package/dist/studio/assets/index-Ce_RMQzq.css +32 -0
  53. package/dist/studio/editors/wicked-deck/editor.json +1 -1
  54. package/dist/studio/editors/wicked-deck/index.html +1 -1
  55. package/dist/studio/editors/wicked-doc/editor.json +1 -1
  56. package/dist/studio/editors/wicked-doc/index.html +1 -1
  57. package/dist/studio/editors/wicked-page/editor.json +1 -1
  58. package/dist/studio/editors/wicked-page/index.html +1 -1
  59. package/dist/studio/editors/wicked-video/editor.json +1 -1
  60. package/dist/studio/editors/wicked-video/index.html +1 -1
  61. package/dist/studio/index.html +2 -2
  62. package/dist/studio/testid-inventory.json +569 -88
  63. package/endpoint-manifest.json +47 -1
  64. package/package.json +3 -3
  65. package/dist/studio/assets/index-CmNUtpfw.css +0 -32
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Chat attachments (DES-SYSTEM-CHAT "Crew" §2, api-types 0.137.0).
3
+ *
4
+ * `POST /chats/:id/attachments` takes multipart/form-data file parts: images (png, jpeg, gif, webp),
5
+ * UTF-8 text and pdf. Each file's TYPE is decided from its bytes (a declared type that the bytes do
6
+ * not bear out is refused), and each upload is held to a per-file cap and a total cap. The files are
7
+ * stored under the state home (`<state home>/chats/attachments/<chat>/`, 0700 / 0600) and removed
8
+ * with their chat on `DELETE /chats/:id`.
9
+ *
10
+ * A message names attachment ids. Before the seat's turn, each named file is COPIED read-only (0444)
11
+ * into the chat's private scratch root (`<scratch root>/attachments/`, a read root of the chat's run
12
+ * from its launch), and the turn's instructions list each one: its path (an image opens as an image
13
+ * in a CLI that reads images), and for text and pdf the extracted text. The canonical copy under the
14
+ * state home is never handed to a seat.
15
+ */
16
+ import type { ChatAttachment, ChatAttachmentKind, ChatAttachmentLimits } from '../core/types.js';
17
+ export declare const ATTACHMENT_MAX_FILE_BYTES: number;
18
+ export declare const ATTACHMENT_MAX_MESSAGE_BYTES: number;
19
+ export declare const ATTACHMENT_MAX_FILES = 10;
20
+ /** Extracted text handed to the seat per file, at most. */
21
+ export declare const ATTACHMENT_TEXT_EXCERPT_CHARS = 16000;
22
+ export declare const ATTACHMENT_LIMITS: ChatAttachmentLimits;
23
+ /** A refusal with its HTTP status and wire code (`ChatAttachmentError`). */
24
+ export declare class AttachmentError extends Error {
25
+ readonly status: 400 | 404 | 413 | 415;
26
+ readonly code: 'attachment_too_large' | 'attachments_too_large' | 'attachment_type' | 'attachment_unknown' | 'attachment_malformed';
27
+ readonly name_?: string | undefined;
28
+ readonly bytes?: number | undefined;
29
+ constructor(status: 400 | 404 | 413 | 415, code: 'attachment_too_large' | 'attachments_too_large' | 'attachment_type' | 'attachment_unknown' | 'attachment_malformed', message: string, name_?: string | undefined, bytes?: number | undefined);
30
+ body(): Record<string, unknown>;
31
+ }
32
+ export interface UploadedFile {
33
+ filename: string;
34
+ declaredType: string | null;
35
+ data: Buffer;
36
+ }
37
+ /** The boundary of a `multipart/form-data` content type, or null. */
38
+ export declare function boundaryOf(contentType: string | undefined): string | null;
39
+ /** Parse a buffered multipart body into its FILE parts (a part with a filename); fields are ignored. */
40
+ export declare function parseMultipart(body: Buffer, boundary: string): UploadedFile[];
41
+ /** Decide an upload's kind and media type from its bytes. `null`: not an accepted type. */
42
+ export declare function sniffAttachment(data: Buffer, filename: string): {
43
+ kind: ChatAttachmentKind;
44
+ mediaType: string;
45
+ } | null;
46
+ /** A file name safe to put on disk: no path, no control characters, at most 100 characters. */
47
+ export declare function safeName(filename: string): string;
48
+ /** One pdf content stream inflates to at most this; the whole pdf's streams to at most the total. */
49
+ export declare const PDF_INFLATE_STREAM_BYTES: number;
50
+ export declare const PDF_INFLATE_TOTAL_BYTES: number;
51
+ /** Best-effort text from a pdf: the strings shown by `Tj` / `TJ` in its (Flate or plain) content
52
+ * streams. Good for the common text pdf; a scanned page has none, and says so. */
53
+ export declare function extractPdfText(data: Buffer, maxChars?: number): string;
54
+ export declare function defaultChatAttachmentsDir(): string;
55
+ /** The wire fields of an attachment record (never its stored path). */
56
+ export declare function attachmentWire(m: ChatAttachment): ChatAttachment;
57
+ export declare class ChatAttachmentStore {
58
+ readonly dir: string;
59
+ private readonly now;
60
+ constructor(opts?: {
61
+ dir?: string;
62
+ now?: () => number;
63
+ });
64
+ private chatDir;
65
+ private ensureDir;
66
+ /** Validate every file first (all or nothing), then store them. */
67
+ add(chatId: string, files: UploadedFile[]): ChatAttachment[];
68
+ private readMeta;
69
+ /** The chat's attachments, oldest first. */
70
+ list(chatId: string): ChatAttachment[];
71
+ /** The named attachments of the chat, in the order named — refused when one is unknown or the set
72
+ * is over the per-message caps. */
73
+ resolve(chatId: string, ids: readonly string[]): Array<ChatAttachment & {
74
+ path: string;
75
+ }>;
76
+ count(chatId: string): number;
77
+ /** The chat is deleted: its attachments go with it. */
78
+ removeChat(chatId: string): void;
79
+ /** Whether any attachment directory exists under `chatId`. */
80
+ exists(chatId: string): boolean;
81
+ /** Move a chat's attachments to another id (an archived history entry the id was reused over).
82
+ * Never over an occupied destination. */
83
+ rename(fromChatId: string, toChatId: string): void;
84
+ }
85
+ export interface StagedAttachment extends ChatAttachment {
86
+ /** The read-only copy the seat reads. */
87
+ seatPath: string;
88
+ /** Extracted text for text and pdf (bounded); `null` for images. */
89
+ text: string | null;
90
+ truncated: boolean;
91
+ }
92
+ /**
93
+ * Copy the named attachments read-only (0444) into `stagingDir` (the chat's scratch root's
94
+ * `attachments/`, a read root of its run) and extract their text. The seat never gets the
95
+ * canonical path under the state home.
96
+ */
97
+ export declare function stageForSeat(atts: ReadonlyArray<ChatAttachment & {
98
+ path: string;
99
+ }>, stagingDir: string): StagedAttachment[];
100
+ /** The block a turn's instructions carry for its attachments. */
101
+ export declare function attachmentsBlock(staged: readonly StagedAttachment[]): string;
102
+ //# sourceMappingURL=chat-attachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-attachments.d.ts","sourceRoot":"","sources":["../../src/api/chat-attachments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,438 @@
1
+ /**
2
+ * Chat attachments (DES-SYSTEM-CHAT "Crew" §2, api-types 0.137.0).
3
+ *
4
+ * `POST /chats/:id/attachments` takes multipart/form-data file parts: images (png, jpeg, gif, webp),
5
+ * UTF-8 text and pdf. Each file's TYPE is decided from its bytes (a declared type that the bytes do
6
+ * not bear out is refused), and each upload is held to a per-file cap and a total cap. The files are
7
+ * stored under the state home (`<state home>/chats/attachments/<chat>/`, 0700 / 0600) and removed
8
+ * with their chat on `DELETE /chats/:id`.
9
+ *
10
+ * A message names attachment ids. Before the seat's turn, each named file is COPIED read-only (0444)
11
+ * into the chat's private scratch root (`<scratch root>/attachments/`, a read root of the chat's run
12
+ * from its launch), and the turn's instructions list each one: its path (an image opens as an image
13
+ * in a CLI that reads images), and for text and pdf the extracted text. The canonical copy under the
14
+ * state home is never handed to a seat.
15
+ */
16
+ import { createHash, randomBytes } from 'node:crypto';
17
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { inflateSync } from 'node:zlib';
20
+ import { crewStateHome } from '../projects/state-home.js';
21
+ import { CHAT_ID } from './chat-scope.js';
22
+ export const ATTACHMENT_MAX_FILE_BYTES = 10 * 1024 * 1024;
23
+ export const ATTACHMENT_MAX_MESSAGE_BYTES = 20 * 1024 * 1024;
24
+ export const ATTACHMENT_MAX_FILES = 10;
25
+ /** Extracted text handed to the seat per file, at most. */
26
+ export const ATTACHMENT_TEXT_EXCERPT_CHARS = 16_000;
27
+ const IMAGE_TYPES = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];
28
+ const TEXT_TYPES = ['text/plain', 'text/markdown', 'text/csv', 'application/json'];
29
+ export const ATTACHMENT_LIMITS = {
30
+ maxFileBytes: ATTACHMENT_MAX_FILE_BYTES,
31
+ maxMessageBytes: ATTACHMENT_MAX_MESSAGE_BYTES,
32
+ maxFiles: ATTACHMENT_MAX_FILES,
33
+ mediaTypes: [...IMAGE_TYPES, ...TEXT_TYPES, 'text/*', 'application/pdf'],
34
+ };
35
+ const ATTACHMENT_ID = /^att_[0-9a-f]{20}$/;
36
+ /** A refusal with its HTTP status and wire code (`ChatAttachmentError`). */
37
+ export class AttachmentError extends Error {
38
+ status;
39
+ code;
40
+ name_;
41
+ bytes;
42
+ constructor(status, code, message, name_, bytes) {
43
+ super(message);
44
+ this.status = status;
45
+ this.code = code;
46
+ this.name_ = name_;
47
+ this.bytes = bytes;
48
+ this.name = 'AttachmentError';
49
+ }
50
+ body() {
51
+ return {
52
+ error: this.message,
53
+ code: this.code,
54
+ ...(this.name_ !== undefined ? { name: this.name_ } : {}),
55
+ ...(this.bytes !== undefined ? { bytes: this.bytes } : {}),
56
+ limits: ATTACHMENT_LIMITS,
57
+ };
58
+ }
59
+ }
60
+ const mib = (n) => `${Math.round((n / (1024 * 1024)) * 10) / 10} MiB`;
61
+ /** The boundary of a `multipart/form-data` content type, or null. */
62
+ export function boundaryOf(contentType) {
63
+ if (contentType === undefined || !/^multipart\/form-data\b/i.test(contentType))
64
+ return null;
65
+ const m = /boundary=(?:"([^"]+)"|([^;\s]+))/i.exec(contentType);
66
+ const b = m?.[1] ?? m?.[2];
67
+ return b !== undefined && b.length > 0 && b.length <= 200 ? b : null;
68
+ }
69
+ function filenameOf(disposition) {
70
+ const star = /filename\*\s*=\s*(?:UTF-8|utf-8)''([^;]+)/.exec(disposition);
71
+ if (star?.[1] !== undefined) {
72
+ try {
73
+ return decodeURIComponent(star[1].trim());
74
+ }
75
+ catch {
76
+ /* fall through to the plain parameter */
77
+ }
78
+ }
79
+ const plain = /filename\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^;]+))/.exec(disposition);
80
+ const v = plain?.[1] ?? plain?.[2];
81
+ return v !== undefined ? v.replace(/\\(.)/g, '$1').trim() : null;
82
+ }
83
+ /** Parse a buffered multipart body into its FILE parts (a part with a filename); fields are ignored. */
84
+ export function parseMultipart(body, boundary) {
85
+ const delim = Buffer.from(`--${boundary}`);
86
+ const files = [];
87
+ let pos = body.indexOf(delim);
88
+ if (pos < 0)
89
+ throw new AttachmentError(400, 'attachment_malformed', 'the body is not multipart/form-data with the declared boundary');
90
+ for (;;) {
91
+ pos += delim.length;
92
+ // `--` after a delimiter closes the body.
93
+ if (body[pos] === 0x2d && body[pos + 1] === 0x2d)
94
+ break;
95
+ if (body[pos] === 0x0d && body[pos + 1] === 0x0a)
96
+ pos += 2;
97
+ const headerEnd = body.indexOf('\r\n\r\n', pos);
98
+ if (headerEnd < 0)
99
+ throw new AttachmentError(400, 'attachment_malformed', 'a multipart part has no header end');
100
+ const headers = body.subarray(pos, headerEnd).toString('utf8');
101
+ const dataStart = headerEnd + 4;
102
+ // The part ends at the next CRLF + delimiter that is itself followed by CRLF or `--`: a payload
103
+ // line that merely starts with the delimiter is data (xreview r1 on #1140).
104
+ const crlfDelim = Buffer.concat([Buffer.from('\r\n'), delim]);
105
+ let next = body.indexOf(crlfDelim, dataStart);
106
+ while (next >= 0) {
107
+ const after = next + crlfDelim.length;
108
+ if ((body[after] === 0x0d && body[after + 1] === 0x0a) || (body[after] === 0x2d && body[after + 1] === 0x2d))
109
+ break;
110
+ next = body.indexOf(crlfDelim, next + 1);
111
+ }
112
+ if (next < 0)
113
+ throw new AttachmentError(400, 'attachment_malformed', 'a multipart part is not terminated');
114
+ const disposition = /^content-disposition:\s*(.+)$/im.exec(headers)?.[1] ?? '';
115
+ const filename = filenameOf(disposition);
116
+ if (filename !== null) {
117
+ const declared = /^content-type:\s*([^;\r\n]+)/im.exec(headers)?.[1]?.trim().toLowerCase() ?? null;
118
+ files.push({ filename, declaredType: declared, data: body.subarray(dataStart, next) });
119
+ }
120
+ pos = next + 2;
121
+ }
122
+ return files;
123
+ }
124
+ // ── type decision ───────────────────────────────────────────────────────────
125
+ const startsWith = (b, sig) => sig.every((v, i) => b[i] === v);
126
+ /** Decide an upload's kind and media type from its bytes. `null`: not an accepted type. */
127
+ export function sniffAttachment(data, filename) {
128
+ if (startsWith(data, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))
129
+ return { kind: 'image', mediaType: 'image/png' };
130
+ if (startsWith(data, [0xff, 0xd8, 0xff]))
131
+ return { kind: 'image', mediaType: 'image/jpeg' };
132
+ if (data.subarray(0, 6).toString('latin1') === 'GIF87a' || data.subarray(0, 6).toString('latin1') === 'GIF89a')
133
+ return { kind: 'image', mediaType: 'image/gif' };
134
+ if (data.subarray(0, 4).toString('latin1') === 'RIFF' && data.subarray(8, 12).toString('latin1') === 'WEBP')
135
+ return { kind: 'image', mediaType: 'image/webp' };
136
+ if (data.subarray(0, 5).toString('latin1') === '%PDF-')
137
+ return { kind: 'pdf', mediaType: 'application/pdf' };
138
+ if (data.includes(0))
139
+ return null; // a NUL byte: binary, not text
140
+ try {
141
+ new TextDecoder('utf-8', { fatal: true }).decode(data);
142
+ }
143
+ catch {
144
+ return null;
145
+ }
146
+ const ext = /\.([A-Za-z0-9]+)$/.exec(filename)?.[1]?.toLowerCase();
147
+ const mediaType = ext === 'md' || ext === 'markdown' ? 'text/markdown' : ext === 'csv' ? 'text/csv' : ext === 'json' ? 'application/json' : 'text/plain';
148
+ return { kind: 'text', mediaType };
149
+ }
150
+ /** Whether a declared part type is consistent with what the bytes are (absent / octet-stream = no claim). */
151
+ function declaredFits(declared, sniffed) {
152
+ if (declared === null || declared === '' || declared === 'application/octet-stream')
153
+ return true;
154
+ if (sniffed.kind === 'image')
155
+ return declared === sniffed.mediaType || (declared === 'image/jpg' && sniffed.mediaType === 'image/jpeg');
156
+ if (sniffed.kind === 'pdf')
157
+ return declared === 'application/pdf';
158
+ return declared.startsWith('text/') || declared === 'application/json' || declared === 'application/x-ndjson';
159
+ }
160
+ /** A file name safe to put on disk: no path, no control characters, at most 100 characters. */
161
+ export function safeName(filename) {
162
+ const base = filename.split(/[\\/]/).pop() ?? '';
163
+ const cleaned = base.replace(/[\u0000-\u001f\u007f]/g, '').replace(/[^A-Za-z0-9._ -]/g, '_').replace(/^\.+/, '').trim();
164
+ const name = cleaned === '' ? 'file' : cleaned;
165
+ return name.length > 100 ? name.slice(name.length - 100) : name;
166
+ }
167
+ // ── text extraction ─────────────────────────────────────────────────────────
168
+ /** One pdf content stream inflates to at most this; the whole pdf's streams to at most the total. */
169
+ export const PDF_INFLATE_STREAM_BYTES = 4 * 1024 * 1024;
170
+ export const PDF_INFLATE_TOTAL_BYTES = 16 * 1024 * 1024;
171
+ /** Best-effort text from a pdf: the strings shown by `Tj` / `TJ` in its (Flate or plain) content
172
+ * streams. Good for the common text pdf; a scanned page has none, and says so. */
173
+ export function extractPdfText(data, maxChars = ATTACHMENT_TEXT_EXCERPT_CHARS) {
174
+ const raw = data.toString('latin1');
175
+ const out = [];
176
+ let total = 0;
177
+ let inflated = 0;
178
+ const streamRe = /stream\r?\n/g;
179
+ let m;
180
+ while ((m = streamRe.exec(raw)) !== null && total < maxChars) {
181
+ const start = m.index + m[0].length;
182
+ const end = raw.indexOf('endstream', start);
183
+ if (end < 0)
184
+ break;
185
+ const dict = raw.slice(Math.max(0, m.index - 400), m.index);
186
+ let content = data.subarray(start, end);
187
+ if (/\/FlateDecode/.test(dict.slice(dict.lastIndexOf('<<')))) {
188
+ // Bounded: a small stream that inflates to gigabytes (a decompression bomb) is skipped, and
189
+ // the inflated bytes across the whole pdf are budgeted (xreview r1 on #1140).
190
+ if (inflated >= PDF_INFLATE_TOTAL_BYTES)
191
+ break;
192
+ try {
193
+ content = inflateSync(content, { maxOutputLength: Math.min(PDF_INFLATE_STREAM_BYTES, PDF_INFLATE_TOTAL_BYTES - inflated) });
194
+ inflated += content.length;
195
+ }
196
+ catch {
197
+ streamRe.lastIndex = end;
198
+ continue;
199
+ }
200
+ }
201
+ const text = content.toString('latin1');
202
+ const shown = /\((?:[^()\\]|\\[\s\S])*\)\s*Tj|\[((?:[^\]\\]|\\[\s\S])*)\]\s*TJ/g;
203
+ let t;
204
+ while ((t = shown.exec(text)) !== null && total < maxChars) {
205
+ const strings = t[0].match(/\((?:[^()\\]|\\[\s\S])*\)/g) ?? [];
206
+ const piece = strings
207
+ .map((s) => s
208
+ .slice(1, -1)
209
+ .replace(/\\([nrtbf()\\]|[0-7]{1,3})/g, (_, c) => /^[0-7]+$/.test(c) ? String.fromCharCode(parseInt(c, 8)) : { n: '\n', r: '', t: '\t', b: '', f: '' }[c] ?? c))
210
+ .join('');
211
+ out.push(piece);
212
+ total += piece.length;
213
+ }
214
+ streamRe.lastIndex = end;
215
+ }
216
+ return out.join(' ').replace(/\s+/g, ' ').trim().slice(0, maxChars);
217
+ }
218
+ // ── the store ───────────────────────────────────────────────────────────────
219
+ export function defaultChatAttachmentsDir() {
220
+ return join(crewStateHome(), 'chats', 'attachments');
221
+ }
222
+ /** The wire fields of an attachment record (never its stored path). */
223
+ export function attachmentWire(m) {
224
+ return { id: m.id, chatId: m.chatId, name: m.name, mediaType: m.mediaType, kind: m.kind, bytes: m.bytes, sha256: m.sha256, createdAt: m.createdAt };
225
+ }
226
+ export class ChatAttachmentStore {
227
+ dir;
228
+ now;
229
+ constructor(opts = {}) {
230
+ this.dir = opts.dir ?? defaultChatAttachmentsDir();
231
+ this.now = opts.now ?? Date.now;
232
+ }
233
+ chatDir(chatId) {
234
+ if (!CHAT_ID.test(chatId) || chatId === '.' || chatId === '..')
235
+ throw new AttachmentError(400, 'attachment_malformed', `chat id ${JSON.stringify(chatId)} cannot name an attachments directory`);
236
+ return join(this.dir, chatId);
237
+ }
238
+ ensureDir(path) {
239
+ mkdirSync(path, { recursive: true, mode: 0o700 });
240
+ if (process.platform !== 'win32')
241
+ chmodSync(path, 0o700);
242
+ }
243
+ /** Validate every file first (all or nothing), then store them. */
244
+ add(chatId, files) {
245
+ if (files.length === 0)
246
+ throw new AttachmentError(400, 'attachment_malformed', 'no file part in the upload');
247
+ if (files.length > ATTACHMENT_MAX_FILES) {
248
+ throw new AttachmentError(413, 'attachments_too_large', `${files.length} files is over the limit of ${ATTACHMENT_MAX_FILES} per message`);
249
+ }
250
+ let total = 0;
251
+ const checked = files.map((f) => {
252
+ const name = safeName(f.filename);
253
+ if (f.data.length > ATTACHMENT_MAX_FILE_BYTES) {
254
+ throw new AttachmentError(413, 'attachment_too_large', `${name} is ${mib(f.data.length)}, over the ${mib(ATTACHMENT_MAX_FILE_BYTES)} limit per file`, name, f.data.length);
255
+ }
256
+ if (f.data.length === 0)
257
+ throw new AttachmentError(415, 'attachment_type', `${name} is empty`, name, 0);
258
+ total += f.data.length;
259
+ const sniffed = sniffAttachment(f.data, name);
260
+ if (sniffed === null) {
261
+ throw new AttachmentError(415, 'attachment_type', `${name} is not an image (png, jpeg, gif, webp), UTF-8 text or a pdf`, name, f.data.length);
262
+ }
263
+ if (!declaredFits(f.declaredType, sniffed)) {
264
+ throw new AttachmentError(415, 'attachment_type', `${name} was sent as ${f.declaredType} but its bytes are ${sniffed.mediaType}`, name, f.data.length);
265
+ }
266
+ return { f, name, sniffed };
267
+ });
268
+ if (total > ATTACHMENT_MAX_MESSAGE_BYTES) {
269
+ throw new AttachmentError(413, 'attachments_too_large', `the files total ${mib(total)}, over the ${mib(ATTACHMENT_MAX_MESSAGE_BYTES)} limit per message`, undefined, total);
270
+ }
271
+ const dir = this.chatDir(chatId);
272
+ this.ensureDir(this.dir);
273
+ this.ensureDir(dir);
274
+ return checked.map(({ f, name, sniffed }) => {
275
+ const id = `att_${randomBytes(10).toString('hex')}`;
276
+ const file = `${id}-${name}`;
277
+ writeFileSync(join(dir, file), f.data, { mode: 0o600 });
278
+ const meta = {
279
+ id,
280
+ chatId,
281
+ name,
282
+ mediaType: sniffed.mediaType,
283
+ kind: sniffed.kind,
284
+ bytes: f.data.length,
285
+ sha256: createHash('sha256').update(f.data).digest('hex'),
286
+ createdAt: new Date(this.now()).toISOString(),
287
+ file,
288
+ };
289
+ writeFileSync(join(dir, `${id}.json`), JSON.stringify(meta), { mode: 0o600 });
290
+ return attachmentWire(meta);
291
+ });
292
+ }
293
+ readMeta(chatId, id) {
294
+ if (!ATTACHMENT_ID.test(id))
295
+ return null;
296
+ try {
297
+ return JSON.parse(readFileSync(join(this.chatDir(chatId), `${id}.json`), 'utf8'));
298
+ }
299
+ catch {
300
+ return null;
301
+ }
302
+ }
303
+ /** The chat's attachments, oldest first. */
304
+ list(chatId) {
305
+ let dir;
306
+ try {
307
+ dir = this.chatDir(chatId);
308
+ }
309
+ catch {
310
+ return [];
311
+ }
312
+ if (!existsSync(dir))
313
+ return [];
314
+ return readdirSync(dir)
315
+ .filter((n) => n.endsWith('.json'))
316
+ .map((n) => this.readMeta(chatId, n.slice(0, -5)))
317
+ .filter((m) => m !== null)
318
+ .sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id))
319
+ .map(attachmentWire);
320
+ }
321
+ /** The named attachments of the chat, in the order named — refused when one is unknown or the set
322
+ * is over the per-message caps. */
323
+ resolve(chatId, ids) {
324
+ if (ids.length > ATTACHMENT_MAX_FILES) {
325
+ throw new AttachmentError(413, 'attachments_too_large', `${ids.length} attachments is over the limit of ${ATTACHMENT_MAX_FILES} per message`);
326
+ }
327
+ const out = [];
328
+ let total = 0;
329
+ for (const id of [...new Set(ids)]) {
330
+ const meta = this.readMeta(chatId, id);
331
+ if (meta === null)
332
+ throw new AttachmentError(404, 'attachment_unknown', `chat ${chatId} has no attachment ${id}`);
333
+ total += meta.bytes;
334
+ out.push({ ...attachmentWire(meta), path: join(this.chatDir(chatId), meta.file) });
335
+ }
336
+ if (total > ATTACHMENT_MAX_MESSAGE_BYTES) {
337
+ throw new AttachmentError(413, 'attachments_too_large', `the attachments total ${mib(total)}, over the ${mib(ATTACHMENT_MAX_MESSAGE_BYTES)} limit per message`, undefined, total);
338
+ }
339
+ return out;
340
+ }
341
+ count(chatId) {
342
+ return this.list(chatId).length;
343
+ }
344
+ /** The chat is deleted: its attachments go with it. */
345
+ removeChat(chatId) {
346
+ let dir;
347
+ try {
348
+ dir = this.chatDir(chatId);
349
+ }
350
+ catch {
351
+ return;
352
+ }
353
+ rmSync(dir, { recursive: true, force: true });
354
+ }
355
+ /** Whether any attachment directory exists under `chatId`. */
356
+ exists(chatId) {
357
+ try {
358
+ return existsSync(this.chatDir(chatId));
359
+ }
360
+ catch {
361
+ return false;
362
+ }
363
+ }
364
+ /** Move a chat's attachments to another id (an archived history entry the id was reused over).
365
+ * Never over an occupied destination. */
366
+ rename(fromChatId, toChatId) {
367
+ const from = this.chatDir(fromChatId);
368
+ if (!existsSync(from))
369
+ return;
370
+ const to = this.chatDir(toChatId);
371
+ if (existsSync(to))
372
+ throw new Error(`refusing to move attachments onto ${toChatId}: it already has some`);
373
+ this.ensureDir(this.dir);
374
+ // Rewrite each meta's chatId as it moves — a META file is `<attachment id>.json`; an uploaded
375
+ // payload that merely ends in `.json` is copied byte for byte (xreview r1 on #1140).
376
+ this.ensureDir(to);
377
+ for (const n of readdirSync(from)) {
378
+ if (n.endsWith('.json') && ATTACHMENT_ID.test(n.slice(0, -5))) {
379
+ const meta = JSON.parse(readFileSync(join(from, n), 'utf8'));
380
+ writeFileSync(join(to, n), JSON.stringify({ ...meta, chatId: toChatId }), { mode: 0o600 });
381
+ }
382
+ else {
383
+ copyFileSync(join(from, n), join(to, n));
384
+ }
385
+ }
386
+ rmSync(from, { recursive: true, force: true });
387
+ }
388
+ }
389
+ /**
390
+ * Copy the named attachments read-only (0444) into `stagingDir` (the chat's scratch root's
391
+ * `attachments/`, a read root of its run) and extract their text. The seat never gets the
392
+ * canonical path under the state home.
393
+ */
394
+ export function stageForSeat(atts, stagingDir) {
395
+ mkdirSync(stagingDir, { recursive: true, mode: 0o700 });
396
+ return atts.map((a) => {
397
+ const seatPath = join(stagingDir, `${a.id}-${a.name}`);
398
+ if (!existsSync(seatPath)) {
399
+ copyFileSync(a.path, seatPath);
400
+ if (process.platform !== 'win32')
401
+ chmodSync(seatPath, 0o444);
402
+ }
403
+ let text = null;
404
+ let truncated = false;
405
+ if (a.kind === 'text') {
406
+ const all = readFileSync(a.path, 'utf8');
407
+ truncated = all.length > ATTACHMENT_TEXT_EXCERPT_CHARS;
408
+ text = all.slice(0, ATTACHMENT_TEXT_EXCERPT_CHARS);
409
+ }
410
+ else if (a.kind === 'pdf') {
411
+ text = extractPdfText(readFileSync(a.path));
412
+ truncated = text.length >= ATTACHMENT_TEXT_EXCERPT_CHARS;
413
+ }
414
+ return { ...attachmentWire(a), seatPath, text, truncated };
415
+ });
416
+ }
417
+ /** The block a turn's instructions carry for its attachments. */
418
+ export function attachmentsBlock(staged) {
419
+ if (staged.length === 0)
420
+ return '';
421
+ const lines = ['', '## Attached files (read-only)', '', 'The operator attached these files to this message. Read them at their paths; do not modify them.', ''];
422
+ for (const a of staged) {
423
+ lines.push(`- ${a.name} (${a.mediaType}, ${a.bytes} bytes, sha256 ${a.sha256.slice(0, 12)}): ${a.seatPath}`);
424
+ if (a.kind === 'image')
425
+ lines.push(' An image: open the file to view it.');
426
+ if (a.text !== null) {
427
+ if (a.text === '') {
428
+ lines.push(` No text could be extracted${a.kind === 'pdf' ? ' (a scanned or image-only pdf)' : ''}; open the file.`);
429
+ }
430
+ else {
431
+ const fence = a.text.includes('```') ? '~~~~' : '```';
432
+ lines.push(` Extracted text${a.truncated ? ` (first ${ATTACHMENT_TEXT_EXCERPT_CHARS} characters)` : ''}:`, ` ${fence}`, ...a.text.split('\n').map((l) => ` ${l}`), ` ${fence}`);
433
+ }
434
+ }
435
+ }
436
+ return lines.join('\n');
437
+ }
438
+ //# sourceMappingURL=chat-attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-attachments.js","sourceRoot":"","sources":["../../src/api/chat-attachments.ts"],"names":[],"mappings":"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"}