noumen 0.4.0 → 0.6.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 (73) hide show
  1. package/README.md +63 -8
  2. package/dist/a2a/index.d.ts +6 -4
  3. package/dist/acp/index.d.ts +7 -5
  4. package/dist/{agent-1nFVUP9E.d.ts → agent-DWE4_P5X.d.ts} +169 -485
  5. package/dist/{cache-DsRqxx6v.d.ts → cache-BlBwXXPS.d.ts} +1 -1
  6. package/dist/{chunk-4HW6LN6D.js → chunk-6MMYCGJQ.js} +366 -1227
  7. package/dist/chunk-6MMYCGJQ.js.map +1 -0
  8. package/dist/{chunk-5JN4SPI7.js → chunk-7IQCQI2G.js} +1 -1
  9. package/dist/{chunk-L3L3FG5T.js → chunk-CCM2AXZG.js} +1 -1
  10. package/dist/{chunk-L3L3FG5T.js.map → chunk-CCM2AXZG.js.map} +1 -1
  11. package/dist/{chunk-CS6WNDCF.js → chunk-I3JTUFPK.js} +2 -2
  12. package/dist/chunk-I3JTUFPK.js.map +1 -0
  13. package/dist/chunk-I5SBSOS6.js +40 -0
  14. package/dist/chunk-I5SBSOS6.js.map +1 -0
  15. package/dist/{chunk-HL6JCRZJ.js → chunk-XZN4QZLK.js} +4 -4
  16. package/dist/{chunk-EKOGVTBT.js → chunk-ZXSDKBYB.js} +4 -2
  17. package/dist/chunk-ZXSDKBYB.js.map +1 -0
  18. package/dist/cli/index.js +11 -11
  19. package/dist/client/index.d.ts +1 -1
  20. package/dist/computer-BPdxSo6X.d.ts +88 -0
  21. package/dist/docker.d.ts +129 -0
  22. package/dist/docker.js +401 -0
  23. package/dist/docker.js.map +1 -0
  24. package/dist/e2b.d.ts +157 -0
  25. package/dist/e2b.js +202 -0
  26. package/dist/e2b.js.map +1 -0
  27. package/dist/freestyle.d.ts +174 -0
  28. package/dist/freestyle.js +240 -0
  29. package/dist/freestyle.js.map +1 -0
  30. package/dist/index.d.ts +19 -204
  31. package/dist/index.js +38 -48
  32. package/dist/lsp/index.d.ts +4 -3
  33. package/dist/mcp/index.d.ts +5 -4
  34. package/dist/mcp/index.js +2 -2
  35. package/dist/{provider-factory-KCLIF34X.js → provider-factory-TUHU3DIG.js} +2 -2
  36. package/dist/providers/anthropic.d.ts +3 -3
  37. package/dist/providers/anthropic.js +4 -3
  38. package/dist/providers/anthropic.js.map +1 -1
  39. package/dist/providers/bedrock.d.ts +3 -3
  40. package/dist/providers/bedrock.js +2 -2
  41. package/dist/providers/bedrock.js.map +1 -1
  42. package/dist/providers/gemini.d.ts +2 -2
  43. package/dist/providers/gemini.js +1 -1
  44. package/dist/providers/gemini.js.map +1 -1
  45. package/dist/providers/ollama.d.ts +1 -1
  46. package/dist/providers/ollama.js +2 -2
  47. package/dist/providers/openai.d.ts +2 -2
  48. package/dist/providers/openai.js +2 -2
  49. package/dist/providers/openrouter.d.ts +1 -1
  50. package/dist/providers/openrouter.js +2 -2
  51. package/dist/providers/vertex.d.ts +3 -3
  52. package/dist/providers/vertex.js +4 -3
  53. package/dist/providers/vertex.js.map +1 -1
  54. package/dist/{resolve-4JA2BBDA.js → resolve-6KUZNEYW.js} +2 -2
  55. package/dist/sandbox-9qeMTNrD.d.ts +126 -0
  56. package/dist/server/index.d.ts +6 -4
  57. package/dist/{server-CHMxuWKq.d.ts → server-BzNGKTP6.d.ts} +1 -1
  58. package/dist/sprites.d.ts +136 -0
  59. package/dist/sprites.js +334 -0
  60. package/dist/sprites.js.map +1 -0
  61. package/dist/ssh.d.ts +187 -0
  62. package/dist/ssh.js +392 -0
  63. package/dist/ssh.js.map +1 -0
  64. package/dist/{types-RPKUTu1k.d.ts → types-DhXwOQwD.d.ts} +3 -89
  65. package/dist/{types-LrU4LRmX.d.ts → types-kiGBF35b.d.ts} +40 -2
  66. package/package.json +25 -1
  67. package/dist/chunk-4HW6LN6D.js.map +0 -1
  68. package/dist/chunk-CS6WNDCF.js.map +0 -1
  69. package/dist/chunk-EKOGVTBT.js.map +0 -1
  70. /package/dist/{chunk-5JN4SPI7.js.map → chunk-7IQCQI2G.js.map} +0 -0
  71. /package/dist/{chunk-HL6JCRZJ.js.map → chunk-XZN4QZLK.js.map} +0 -0
  72. /package/dist/{provider-factory-KCLIF34X.js.map → provider-factory-TUHU3DIG.js.map} +0 -0
  73. /package/dist/{resolve-4JA2BBDA.js.map → resolve-6KUZNEYW.js.map} +0 -0
package/dist/ssh.js ADDED
@@ -0,0 +1,392 @@
1
+ import {
2
+ createComputerProxy,
3
+ createFsProxy
4
+ } from "./chunk-I5SBSOS6.js";
5
+ import "./chunk-DGUM43GV.js";
6
+
7
+ // src/virtual/ssh-fs.ts
8
+ import * as pathMod from "path";
9
+ var SshFs = class {
10
+ client;
11
+ workingDir;
12
+ sftpSession = null;
13
+ sftpPromise = null;
14
+ constructor(opts) {
15
+ this.client = opts.client;
16
+ this.workingDir = opts.workingDir ?? "/";
17
+ }
18
+ getSftp() {
19
+ if (this.sftpSession) return Promise.resolve(this.sftpSession);
20
+ if (this.sftpPromise) return this.sftpPromise;
21
+ this.sftpPromise = new Promise((resolve2, reject) => {
22
+ this.client.sftp((err, sftp) => {
23
+ if (err) {
24
+ this.sftpPromise = null;
25
+ reject(err);
26
+ } else {
27
+ this.sftpSession = sftp;
28
+ resolve2(sftp);
29
+ }
30
+ });
31
+ });
32
+ return this.sftpPromise;
33
+ }
34
+ resolvePath(p) {
35
+ if (p.includes("\0")) {
36
+ throw new Error("Path contains null bytes");
37
+ }
38
+ const normalizedBase = this.workingDir.endsWith("/") ? this.workingDir : this.workingDir + "/";
39
+ if (p.startsWith("/")) {
40
+ const normalized = pathMod.normalize(p);
41
+ if (normalized !== this.workingDir && !normalized.startsWith(normalizedBase)) {
42
+ throw new Error(
43
+ `Absolute path "${p}" is outside working directory "${this.workingDir}"`
44
+ );
45
+ }
46
+ return normalized;
47
+ }
48
+ const resolved = pathMod.resolve(this.workingDir, p);
49
+ if (resolved !== this.workingDir && !resolved.startsWith(normalizedBase)) {
50
+ throw new Error(
51
+ `Path "${p}" escapes working directory "${this.workingDir}"`
52
+ );
53
+ }
54
+ return resolved;
55
+ }
56
+ async readFile(path, _opts) {
57
+ const resolved = this.resolvePath(path);
58
+ const sftp = await this.getSftp();
59
+ return new Promise((resolve2, reject) => {
60
+ sftp.readFile(resolved, { encoding: "utf8" }, (err, data) => {
61
+ if (err) reject(new Error(`SshFs readFile failed: ${err.message}`));
62
+ else resolve2(data);
63
+ });
64
+ });
65
+ }
66
+ async readFileBytes(path, maxBytes) {
67
+ const resolved = this.resolvePath(path);
68
+ const sftp = await this.getSftp();
69
+ if (maxBytes === void 0) {
70
+ return new Promise((resolve2, reject) => {
71
+ sftp.readFile(resolved, (err, data) => {
72
+ if (err) reject(new Error(`SshFs readFileBytes failed: ${err.message}`));
73
+ else resolve2(data);
74
+ });
75
+ });
76
+ }
77
+ return new Promise((resolve2, reject) => {
78
+ sftp.open(resolved, "r", (err, handle) => {
79
+ if (err) {
80
+ reject(new Error(`SshFs readFileBytes failed: ${err.message}`));
81
+ return;
82
+ }
83
+ const buf = Buffer.alloc(maxBytes);
84
+ sftp.read(handle, buf, 0, maxBytes, 0, (readErr, bytesRead, readBuf) => {
85
+ sftp.close(handle, () => {
86
+ });
87
+ if (readErr) {
88
+ reject(new Error(`SshFs readFileBytes failed: ${readErr.message}`));
89
+ } else {
90
+ resolve2(readBuf.subarray(0, bytesRead));
91
+ }
92
+ });
93
+ });
94
+ });
95
+ }
96
+ async writeFile(path, content) {
97
+ const resolved = this.resolvePath(path);
98
+ const sftp = await this.getSftp();
99
+ const dir = pathMod.dirname(resolved);
100
+ await this.mkdirRecursive(sftp, dir);
101
+ return new Promise((resolve2, reject) => {
102
+ sftp.writeFile(resolved, content, (err) => {
103
+ if (err) reject(new Error(`SshFs writeFile failed: ${err.message}`));
104
+ else resolve2();
105
+ });
106
+ });
107
+ }
108
+ async appendFile(path, content) {
109
+ const resolved = this.resolvePath(path);
110
+ const sftp = await this.getSftp();
111
+ const dir = pathMod.dirname(resolved);
112
+ await this.mkdirRecursive(sftp, dir);
113
+ return new Promise((resolve2, reject) => {
114
+ sftp.appendFile(resolved, content, (err) => {
115
+ if (err) reject(new Error(`SshFs appendFile failed: ${err.message}`));
116
+ else resolve2();
117
+ });
118
+ });
119
+ }
120
+ async deleteFile(path, opts) {
121
+ const resolved = this.resolvePath(path);
122
+ if (opts?.recursive) {
123
+ const sftp2 = await this.getSftp();
124
+ await this.rmRecursive(sftp2, resolved);
125
+ return;
126
+ }
127
+ const sftp = await this.getSftp();
128
+ return new Promise((resolve2, reject) => {
129
+ sftp.unlink(resolved, (err) => {
130
+ if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));
131
+ else resolve2();
132
+ });
133
+ });
134
+ }
135
+ async mkdir(path, opts) {
136
+ const resolved = this.resolvePath(path);
137
+ const sftp = await this.getSftp();
138
+ if (opts?.recursive) {
139
+ await this.mkdirRecursive(sftp, resolved);
140
+ return;
141
+ }
142
+ return new Promise((resolve2, reject) => {
143
+ sftp.mkdir(resolved, (err) => {
144
+ if (err) reject(new Error(`SshFs mkdir failed: ${err.message}`));
145
+ else resolve2();
146
+ });
147
+ });
148
+ }
149
+ async readdir(path, _opts) {
150
+ const resolved = this.resolvePath(path);
151
+ const sftp = await this.getSftp();
152
+ return new Promise((resolve2, reject) => {
153
+ sftp.readdir(resolved, (err, list) => {
154
+ if (err) {
155
+ reject(new Error(`SshFs readdir failed: ${err.message}`));
156
+ return;
157
+ }
158
+ const entries = list.map((item) => ({
159
+ name: item.filename,
160
+ path: pathMod.join(resolved, item.filename),
161
+ isDirectory: item.attrs.isDirectory(),
162
+ isFile: item.attrs.isFile()
163
+ }));
164
+ resolve2(entries);
165
+ });
166
+ });
167
+ }
168
+ async exists(path) {
169
+ const resolved = this.resolvePath(path);
170
+ const sftp = await this.getSftp();
171
+ return new Promise((resolve2) => {
172
+ sftp.stat(resolved, (err) => {
173
+ resolve2(!err);
174
+ });
175
+ });
176
+ }
177
+ async stat(path) {
178
+ const resolved = this.resolvePath(path);
179
+ const sftp = await this.getSftp();
180
+ return new Promise((resolve2, reject) => {
181
+ sftp.stat(resolved, (err, stats) => {
182
+ if (err) {
183
+ reject(new Error(`SshFs stat failed: ${err.message}`));
184
+ return;
185
+ }
186
+ resolve2({
187
+ size: stats.size,
188
+ isDirectory: stats.isDirectory(),
189
+ isFile: stats.isFile(),
190
+ modifiedAt: stats.mtime > 0 ? new Date(stats.mtime * 1e3) : void 0
191
+ });
192
+ });
193
+ });
194
+ }
195
+ async mkdirRecursive(sftp, dir) {
196
+ const parts = dir.split("/").filter(Boolean);
197
+ let current = "/";
198
+ for (const part of parts) {
199
+ current = pathMod.join(current, part);
200
+ await new Promise((resolve2) => {
201
+ sftp.mkdir(current, () => {
202
+ resolve2();
203
+ });
204
+ });
205
+ }
206
+ }
207
+ async rmRecursive(sftp, target) {
208
+ const isDir = await new Promise((resolve2) => {
209
+ sftp.stat(target, (err, stats) => {
210
+ if (err) resolve2(false);
211
+ else resolve2(stats.isDirectory());
212
+ });
213
+ });
214
+ if (!isDir) {
215
+ return new Promise((resolve2, reject) => {
216
+ sftp.unlink(target, (err) => {
217
+ if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));
218
+ else resolve2();
219
+ });
220
+ });
221
+ }
222
+ const entries = await new Promise(
223
+ (resolve2, reject) => {
224
+ sftp.readdir(target, (err, list) => {
225
+ if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));
226
+ else resolve2(list);
227
+ });
228
+ }
229
+ );
230
+ for (const entry of entries) {
231
+ await this.rmRecursive(sftp, pathMod.join(target, entry.filename));
232
+ }
233
+ return new Promise((resolve2, reject) => {
234
+ sftp.rmdir(target, (err) => {
235
+ if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));
236
+ else resolve2();
237
+ });
238
+ });
239
+ }
240
+ };
241
+
242
+ // src/virtual/ssh-computer.ts
243
+ var SshComputer = class {
244
+ client;
245
+ defaultCwd;
246
+ defaultTimeout;
247
+ constructor(opts) {
248
+ this.client = opts.client;
249
+ this.defaultCwd = opts.defaultCwd ?? "/";
250
+ this.defaultTimeout = opts.defaultTimeout ?? 3e4;
251
+ }
252
+ async executeCommand(command, opts) {
253
+ const cwd = opts?.cwd ?? this.defaultCwd;
254
+ const timeout = opts?.timeout ?? this.defaultTimeout;
255
+ let envPrefix = "";
256
+ if (opts?.env) {
257
+ envPrefix = Object.entries(opts.env).map(([k, v]) => `${k}=${shellEscape(v)}`).join(" ") + " ";
258
+ }
259
+ const fullCommand = `cd ${shellEscape(cwd)} && ${envPrefix}${command}`;
260
+ return new Promise((resolve2, reject) => {
261
+ this.client.exec(fullCommand, (err, channel) => {
262
+ if (err) {
263
+ reject(err);
264
+ return;
265
+ }
266
+ const stdoutBufs = [];
267
+ const stderrBufs = [];
268
+ const timer = setTimeout(() => {
269
+ channel.destroy?.();
270
+ resolve2({
271
+ exitCode: 1,
272
+ stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
273
+ stderr: Buffer.concat(stderrBufs).toString("utf-8") + "\n[timeout after " + timeout + "ms]"
274
+ });
275
+ }, timeout);
276
+ channel.on("data", (chunk) => {
277
+ stdoutBufs.push(Buffer.from(chunk));
278
+ });
279
+ channel.stderr.on("data", (chunk) => {
280
+ stderrBufs.push(Buffer.from(chunk));
281
+ });
282
+ channel.on("close", (code) => {
283
+ clearTimeout(timer);
284
+ resolve2({
285
+ exitCode: code ?? 0,
286
+ stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
287
+ stderr: Buffer.concat(stderrBufs).toString("utf-8")
288
+ });
289
+ });
290
+ channel.on("error", (channelErr) => {
291
+ clearTimeout(timer);
292
+ reject(channelErr);
293
+ });
294
+ });
295
+ });
296
+ }
297
+ };
298
+ function shellEscape(s) {
299
+ return `'${s.replace(/'/g, "'\\''")}'`;
300
+ }
301
+
302
+ // src/virtual/ssh-sandbox.ts
303
+ function SshSandbox(opts) {
304
+ if (opts.client) {
305
+ const c = opts.client;
306
+ return {
307
+ fs: new SshFs({ client: c, workingDir: opts.cwd }),
308
+ computer: new SshComputer({
309
+ client: c,
310
+ defaultCwd: opts.cwd,
311
+ defaultTimeout: opts.defaultTimeout
312
+ }),
313
+ sandboxId: () => opts.host ? `${opts.host}:${opts.port ?? 22}` : void 0
314
+ };
315
+ }
316
+ if (!opts.host) {
317
+ throw new Error("SshSandbox requires either `client` or `host`");
318
+ }
319
+ const fsProxy = createFsProxy();
320
+ const computerProxy = createComputerProxy();
321
+ const identifier = `${opts.host}:${opts.port ?? 22}`;
322
+ let clientRef = null;
323
+ let autoCreated = false;
324
+ let initPromise = null;
325
+ async function doInit() {
326
+ const modName = "ssh2";
327
+ const ssh2 = await import(
328
+ /* webpackIgnore: true */
329
+ modName
330
+ );
331
+ const ClientClass = ssh2.Client ?? ssh2.default?.Client;
332
+ if (!ClientClass) {
333
+ throw new Error(
334
+ "Could not resolve Client class from 'ssh2' package"
335
+ );
336
+ }
337
+ const client = new ClientClass();
338
+ await new Promise((resolve2, reject) => {
339
+ client.on("ready", () => resolve2());
340
+ client.on("error", (err) => reject(err));
341
+ client.connect({
342
+ host: opts.host,
343
+ port: opts.port ?? 22,
344
+ username: opts.username ?? "root",
345
+ password: opts.password,
346
+ privateKey: opts.privateKey,
347
+ passphrase: opts.passphrase
348
+ });
349
+ });
350
+ clientRef = client;
351
+ autoCreated = true;
352
+ fsProxy.setTarget(new SshFs({ client, workingDir: opts.cwd }));
353
+ computerProxy.setTarget(
354
+ new SshComputer({
355
+ client,
356
+ defaultCwd: opts.cwd,
357
+ defaultTimeout: opts.defaultTimeout
358
+ })
359
+ );
360
+ }
361
+ return {
362
+ fs: fsProxy,
363
+ computer: computerProxy,
364
+ sandboxId: () => identifier,
365
+ init() {
366
+ if (!initPromise) {
367
+ initPromise = doInit().catch((err) => {
368
+ initPromise = null;
369
+ throw err;
370
+ });
371
+ }
372
+ return initPromise;
373
+ },
374
+ async dispose() {
375
+ if (initPromise) {
376
+ await initPromise.catch(() => {
377
+ });
378
+ }
379
+ if (!autoCreated || !clientRef) return;
380
+ try {
381
+ clientRef.end();
382
+ } catch {
383
+ }
384
+ }
385
+ };
386
+ }
387
+ export {
388
+ SshComputer,
389
+ SshFs,
390
+ SshSandbox
391
+ };
392
+ //# sourceMappingURL=ssh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/virtual/ssh-fs.ts","../src/virtual/ssh-computer.ts","../src/virtual/ssh-sandbox.ts"],"sourcesContent":["import * as pathMod from \"node:path\";\nimport type { VirtualFs, FileEntry, FileStat, ReadOptions } from \"./fs.js\";\nimport type { SshClient, SshSftpSession } from \"./ssh-computer.js\";\n\nexport interface SshFsOptions {\n /** A connected ssh2 Client instance. */\n client: SshClient;\n /** Working directory for relative path resolution (default: /). */\n workingDir?: string;\n}\n\n/**\n * VirtualFs backed by SFTP file operations over SSH.\n *\n * Uses the ssh2 Client's SFTP subsystem for all file I/O. The SFTP session\n * is opened lazily on the first operation and reused for the lifetime of\n * the SshFs instance.\n *\n * Requires `ssh2` as an optional peer dependency.\n * The caller is responsible for the Client lifecycle.\n */\nexport class SshFs implements VirtualFs {\n private client: SshClient;\n private workingDir: string;\n private sftpSession: SshSftpSession | null = null;\n private sftpPromise: Promise<SshSftpSession> | null = null;\n\n constructor(opts: SshFsOptions) {\n this.client = opts.client;\n this.workingDir = opts.workingDir ?? \"/\";\n }\n\n private getSftp(): Promise<SshSftpSession> {\n if (this.sftpSession) return Promise.resolve(this.sftpSession);\n if (this.sftpPromise) return this.sftpPromise;\n this.sftpPromise = new Promise<SshSftpSession>((resolve, reject) => {\n this.client.sftp((err, sftp) => {\n if (err) {\n this.sftpPromise = null;\n reject(err);\n } else {\n this.sftpSession = sftp;\n resolve(sftp);\n }\n });\n });\n return this.sftpPromise;\n }\n\n private resolvePath(p: string): string {\n if (p.includes(\"\\0\")) {\n throw new Error(\"Path contains null bytes\");\n }\n const normalizedBase = this.workingDir.endsWith(\"/\")\n ? this.workingDir\n : this.workingDir + \"/\";\n if (p.startsWith(\"/\")) {\n const normalized = pathMod.normalize(p);\n if (\n normalized !== this.workingDir &&\n !normalized.startsWith(normalizedBase)\n ) {\n throw new Error(\n `Absolute path \"${p}\" is outside working directory \"${this.workingDir}\"`,\n );\n }\n return normalized;\n }\n const resolved = pathMod.resolve(this.workingDir, p);\n if (\n resolved !== this.workingDir &&\n !resolved.startsWith(normalizedBase)\n ) {\n throw new Error(\n `Path \"${p}\" escapes working directory \"${this.workingDir}\"`,\n );\n }\n return resolved;\n }\n\n async readFile(path: string, _opts?: ReadOptions): Promise<string> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<string>((resolve, reject) => {\n sftp.readFile(resolved, { encoding: \"utf8\" }, (err, data) => {\n if (err) reject(new Error(`SshFs readFile failed: ${err.message}`));\n else resolve(data as string);\n });\n });\n }\n\n async readFileBytes(path: string, maxBytes?: number): Promise<Buffer> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n\n if (maxBytes === undefined) {\n return new Promise<Buffer>((resolve, reject) => {\n sftp.readFile(resolved, (err, data) => {\n if (err) reject(new Error(`SshFs readFileBytes failed: ${err.message}`));\n else resolve(data);\n });\n });\n }\n\n return new Promise<Buffer>((resolve, reject) => {\n sftp.open(resolved, \"r\", (err, handle) => {\n if (err) {\n reject(new Error(`SshFs readFileBytes failed: ${err.message}`));\n return;\n }\n const buf = Buffer.alloc(maxBytes);\n sftp.read(handle, buf, 0, maxBytes, 0, (readErr, bytesRead, readBuf) => {\n sftp.close(handle, () => {});\n if (readErr) {\n reject(new Error(`SshFs readFileBytes failed: ${readErr.message}`));\n } else {\n resolve(readBuf.subarray(0, bytesRead));\n }\n });\n });\n });\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n const dir = pathMod.dirname(resolved);\n await this.mkdirRecursive(sftp, dir);\n return new Promise<void>((resolve, reject) => {\n sftp.writeFile(resolved, content, (err) => {\n if (err) reject(new Error(`SshFs writeFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async appendFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n const dir = pathMod.dirname(resolved);\n await this.mkdirRecursive(sftp, dir);\n return new Promise<void>((resolve, reject) => {\n sftp.appendFile(resolved, content, (err) => {\n if (err) reject(new Error(`SshFs appendFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async deleteFile(\n path: string,\n opts?: { recursive?: boolean },\n ): Promise<void> {\n const resolved = this.resolvePath(path);\n if (opts?.recursive) {\n const sftp = await this.getSftp();\n await this.rmRecursive(sftp, resolved);\n return;\n }\n const sftp = await this.getSftp();\n return new Promise<void>((resolve, reject) => {\n sftp.unlink(resolved, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n if (opts?.recursive) {\n await this.mkdirRecursive(sftp, resolved);\n return;\n }\n return new Promise<void>((resolve, reject) => {\n sftp.mkdir(resolved, (err) => {\n if (err) reject(new Error(`SshFs mkdir failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async readdir(\n path: string,\n _opts?: { recursive?: boolean },\n ): Promise<FileEntry[]> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<FileEntry[]>((resolve, reject) => {\n sftp.readdir(resolved, (err, list) => {\n if (err) {\n reject(new Error(`SshFs readdir failed: ${err.message}`));\n return;\n }\n const entries: FileEntry[] = list.map((item) => ({\n name: item.filename,\n path: pathMod.join(resolved, item.filename),\n isDirectory: item.attrs.isDirectory(),\n isFile: item.attrs.isFile(),\n }));\n resolve(entries);\n });\n });\n }\n\n async exists(path: string): Promise<boolean> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<boolean>((resolve) => {\n sftp.stat(resolved, (err) => {\n resolve(!err);\n });\n });\n }\n\n async stat(path: string): Promise<FileStat> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<FileStat>((resolve, reject) => {\n sftp.stat(resolved, (err, stats) => {\n if (err) {\n reject(new Error(`SshFs stat failed: ${err.message}`));\n return;\n }\n resolve({\n size: stats.size,\n isDirectory: stats.isDirectory(),\n isFile: stats.isFile(),\n modifiedAt: stats.mtime > 0 ? new Date(stats.mtime * 1000) : undefined,\n });\n });\n });\n }\n\n private async mkdirRecursive(\n sftp: SshSftpSession,\n dir: string,\n ): Promise<void> {\n const parts = dir.split(\"/\").filter(Boolean);\n let current = \"/\";\n for (const part of parts) {\n current = pathMod.join(current, part);\n await new Promise<void>((resolve) => {\n sftp.mkdir(current, () => {\n resolve();\n });\n });\n }\n }\n\n private async rmRecursive(\n sftp: SshSftpSession,\n target: string,\n ): Promise<void> {\n const isDir = await new Promise<boolean>((resolve) => {\n sftp.stat(target, (err, stats) => {\n if (err) resolve(false);\n else resolve(stats.isDirectory());\n });\n });\n\n if (!isDir) {\n return new Promise<void>((resolve, reject) => {\n sftp.unlink(target, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n const entries = await new Promise<Array<{ filename: string; attrs: { isDirectory(): boolean } }>>(\n (resolve, reject) => {\n sftp.readdir(target, (err, list) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve(list);\n });\n },\n );\n\n for (const entry of entries) {\n await this.rmRecursive(sftp, pathMod.join(target, entry.filename));\n }\n\n return new Promise<void>((resolve, reject) => {\n sftp.rmdir(target, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n}\n","import type { VirtualComputer, ExecOptions, CommandResult } from \"./computer.js\";\n\n/**\n * Minimal subset of the ssh2 Channel interface used by SshComputer / SshFs.\n * Avoids a hard import of ssh2 at the module level.\n */\nexport interface SshChannel {\n on(event: string, listener: (...args: any[]) => void): SshChannel;\n stderr: { on(event: string, listener: (...args: any[]) => void): unknown };\n destroy?(): void;\n}\n\n/**\n * Minimal subset of the ssh2 SFTPWrapper interface used by SshFs.\n */\nexport interface SshSftpSession {\n readFile(\n path: string,\n callback: (err: Error | undefined, data: Buffer) => void,\n ): void;\n readFile(\n path: string,\n opts: { encoding: string },\n callback: (err: Error | undefined, data: string) => void,\n ): void;\n writeFile(\n path: string,\n data: string | Buffer,\n callback: (err: Error | undefined) => void,\n ): void;\n appendFile(\n path: string,\n data: string | Buffer,\n callback: (err: Error | undefined) => void,\n ): void;\n unlink(path: string, callback: (err: Error | undefined) => void): void;\n rmdir(path: string, callback: (err: Error | undefined) => void): void;\n mkdir(path: string, callback: (err: Error | undefined) => void): void;\n readdir(\n path: string,\n callback: (\n err: Error | undefined,\n list: Array<{\n filename: string;\n longname: string;\n attrs: { size: number; isDirectory(): boolean; isFile(): boolean; mtime: number; atime: number };\n }>,\n ) => void,\n ): void;\n stat(\n path: string,\n callback: (\n err: Error | undefined,\n stats: { size: number; isDirectory(): boolean; isFile(): boolean; mtime: number; atime: number },\n ) => void,\n ): void;\n open(\n path: string,\n flags: string,\n callback: (err: Error | undefined, handle: Buffer) => void,\n ): void;\n read(\n handle: Buffer,\n buffer: Buffer,\n offset: number,\n length: number,\n position: number,\n callback: (err: Error | undefined, bytesRead: number, buf: Buffer) => void,\n ): void;\n close(handle: Buffer, callback: (err: Error | undefined) => void): void;\n end(): void;\n}\n\n/**\n * Minimal subset of the ssh2 Client interface used by SshComputer and SshFs.\n * Avoids a hard import of ssh2 at the module level.\n */\nexport interface SshClient {\n exec(\n command: string,\n callback: (err: Error | undefined, channel: SshChannel) => void,\n ): void;\n exec(\n command: string,\n opts: Record<string, unknown>,\n callback: (err: Error | undefined, channel: SshChannel) => void,\n ): void;\n sftp(\n callback: (err: Error | undefined, sftp: SshSftpSession) => void,\n ): void;\n end(): void;\n on(event: string, listener: (...args: any[]) => void): this;\n}\n\nexport interface SshComputerOptions {\n /** A connected ssh2 Client instance. */\n client: SshClient;\n /** Default working directory for commands (default: /). */\n defaultCwd?: string;\n /** Default timeout in ms for commands (default: 30000). */\n defaultTimeout?: number;\n}\n\n/**\n * VirtualComputer backed by command execution over SSH.\n *\n * Requires `ssh2` as an optional peer dependency.\n * The caller is responsible for the Client lifecycle (connect, end).\n */\nexport class SshComputer implements VirtualComputer {\n private client: SshClient;\n private defaultCwd: string;\n private defaultTimeout: number;\n\n constructor(opts: SshComputerOptions) {\n this.client = opts.client;\n this.defaultCwd = opts.defaultCwd ?? \"/\";\n this.defaultTimeout = opts.defaultTimeout ?? 30_000;\n }\n\n async executeCommand(\n command: string,\n opts?: ExecOptions,\n ): Promise<CommandResult> {\n const cwd = opts?.cwd ?? this.defaultCwd;\n const timeout = opts?.timeout ?? this.defaultTimeout;\n\n let envPrefix = \"\";\n if (opts?.env) {\n envPrefix = Object.entries(opts.env)\n .map(([k, v]) => `${k}=${shellEscape(v)}`)\n .join(\" \") + \" \";\n }\n\n const fullCommand = `cd ${shellEscape(cwd)} && ${envPrefix}${command}`;\n\n return new Promise<CommandResult>((resolve, reject) => {\n this.client.exec(fullCommand, (err, channel) => {\n if (err) {\n reject(err);\n return;\n }\n\n const stdoutBufs: Buffer[] = [];\n const stderrBufs: Buffer[] = [];\n\n const timer = setTimeout(() => {\n channel.destroy?.();\n resolve({\n exitCode: 1,\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr:\n Buffer.concat(stderrBufs).toString(\"utf-8\") +\n \"\\n[timeout after \" + timeout + \"ms]\",\n });\n }, timeout);\n\n channel.on(\"data\", (chunk: Buffer) => {\n stdoutBufs.push(Buffer.from(chunk));\n });\n\n channel.stderr.on(\"data\", (chunk: Buffer) => {\n stderrBufs.push(Buffer.from(chunk));\n });\n\n channel.on(\"close\", (code: number) => {\n clearTimeout(timer);\n resolve({\n exitCode: code ?? 0,\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr: Buffer.concat(stderrBufs).toString(\"utf-8\"),\n });\n });\n\n channel.on(\"error\", (channelErr: Error) => {\n clearTimeout(timer);\n reject(channelErr);\n });\n });\n });\n }\n}\n\nfunction shellEscape(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n","import type { Sandbox } from \"./sandbox.js\";\nimport { SshFs } from \"./ssh-fs.js\";\nimport { SshComputer, type SshClient } from \"./ssh-computer.js\";\nimport { createFsProxy, createComputerProxy } from \"./proxy.js\";\n\nexport interface SshSandboxOptions {\n /**\n * A pre-connected ssh2 Client instance. When provided the sandbox uses\n * this client directly — no auto-connect occurs and `dispose()` will\n * **not** call `client.end()`.\n *\n * When omitted, a new ssh2 Client is created and connected on the first\n * `init()` call using `host`, `port`, `username`, and the provided\n * credentials. The client is ended when `dispose()` is called.\n */\n client?: SshClient;\n /**\n * SSH hostname. Required when `client` is omitted; ignored when `client`\n * is provided.\n */\n host?: string;\n /** SSH port (default: 22). Only used during auto-connect. */\n port?: number;\n /** SSH username (default: \"root\"). Only used during auto-connect. */\n username?: string;\n /** Password for password-based authentication. Only used during auto-connect. */\n password?: string;\n /** Private key for key-based authentication (PEM string or Buffer). Only used during auto-connect. */\n privateKey?: string | Buffer;\n /** Passphrase for an encrypted private key. Only used during auto-connect. */\n passphrase?: string;\n /** Working directory on the remote host. */\n cwd?: string;\n /** Default timeout (ms) for shell commands. */\n defaultTimeout?: number;\n}\n\n/**\n * Create a `Sandbox` backed by a remote host over SSH.\n * Requires `ssh2` as an optional peer dependency.\n *\n * **Auto-connect:** When `client` is omitted and `host` is provided,\n * an ssh2 Client is created and connected lazily on the first `init()`\n * call. The connection identifier (`host:port`) is available through\n * `sandboxId()` for session persistence.\n *\n * **Explicit client:** When `client` is provided, `init()` binds it\n * immediately. `dispose()` is a no-op — the caller owns the client's\n * lifecycle.\n *\n * @example\n * ```ts\n * // Auto-connect with private key\n * const sandbox = SshSandbox({\n * host: \"dev.example.com\",\n * username: \"deploy\",\n * privateKey: fs.readFileSync(\"~/.ssh/id_ed25519\"),\n * cwd: \"/home/deploy/project\",\n * });\n *\n * // Explicit client (lifecycle managed externally)\n * const sandbox = SshSandbox({ client: myConnectedClient, cwd: \"/workspace\" });\n * ```\n */\nexport function SshSandbox(opts: SshSandboxOptions): Sandbox {\n if (opts.client) {\n const c = opts.client;\n return {\n fs: new SshFs({ client: c, workingDir: opts.cwd }),\n computer: new SshComputer({\n client: c,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }),\n sandboxId: () =>\n opts.host ? `${opts.host}:${opts.port ?? 22}` : undefined,\n };\n }\n\n if (!opts.host) {\n throw new Error(\"SshSandbox requires either `client` or `host`\");\n }\n\n const fsProxy = createFsProxy();\n const computerProxy = createComputerProxy();\n const identifier = `${opts.host}:${opts.port ?? 22}`;\n let clientRef: SshClient | null = null;\n let autoCreated = false;\n let initPromise: Promise<void> | null = null;\n\n async function doInit(): Promise<void> {\n const modName = \"ssh2\";\n const ssh2 = await import(/* webpackIgnore: true */ modName);\n const ClientClass =\n (ssh2 as any).Client ?? (ssh2 as any).default?.Client;\n if (!ClientClass) {\n throw new Error(\n \"Could not resolve Client class from 'ssh2' package\",\n );\n }\n\n const client: SshClient = new ClientClass();\n await new Promise<void>((resolve, reject) => {\n client.on(\"ready\", () => resolve());\n client.on(\"error\", (err: Error) => reject(err));\n (client as any).connect({\n host: opts.host,\n port: opts.port ?? 22,\n username: opts.username ?? \"root\",\n password: opts.password,\n privateKey: opts.privateKey,\n passphrase: opts.passphrase,\n });\n });\n\n clientRef = client;\n autoCreated = true;\n fsProxy.setTarget(new SshFs({ client, workingDir: opts.cwd }));\n computerProxy.setTarget(\n new SshComputer({\n client,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }),\n );\n }\n\n return {\n fs: fsProxy,\n computer: computerProxy,\n sandboxId: () => identifier,\n\n init(): Promise<void> {\n if (!initPromise) {\n initPromise = doInit().catch((err) => {\n initPromise = null;\n throw err;\n });\n }\n return initPromise;\n },\n\n async dispose(): Promise<void> {\n if (initPromise) {\n await initPromise.catch(() => {});\n }\n if (!autoCreated || !clientRef) return;\n try {\n clientRef.end();\n } catch {\n /* best-effort */\n }\n },\n };\n}\n"],"mappings":"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","names":["resolve","sftp","resolve","resolve"]}
@@ -1,93 +1,7 @@
1
- import { c as CheckpointConfig, F as FileCheckpointState, D as DiffStats, d as FileCheckpointSnapshot, S as StreamEvent, e as ContentPart } from './types-LrU4LRmX.js';
1
+ import { c as CheckpointConfig, F as FileCheckpointState, D as DiffStats, d as FileCheckpointSnapshot, S as StreamEvent, e as ContentPart } from './types-kiGBF35b.js';
2
+ import { a as VirtualFs, V as VirtualComputer } from './computer-BPdxSo6X.js';
2
3
  import { a as PermissionMode, b as PermissionResult } from './types-CD0rUKKT.js';
3
4
 
4
- interface FileEntry {
5
- name: string;
6
- path: string;
7
- isDirectory: boolean;
8
- isFile: boolean;
9
- size?: number;
10
- }
11
- interface FileStat {
12
- size: number;
13
- isDirectory: boolean;
14
- isFile: boolean;
15
- createdAt?: Date;
16
- modifiedAt?: Date;
17
- }
18
- interface ReadOptions {
19
- encoding?: BufferEncoding;
20
- /**
21
- * Maximum number of bytes to read. When set, only the first `maxBytes`
22
- * bytes are returned (decoded as a string). Implementations that do not
23
- * support this option may ignore it and return the full content.
24
- */
25
- maxBytes?: number;
26
- }
27
- /**
28
- * Sandboxed filesystem interface.
29
- *
30
- * `VirtualFs` is noumen's primary isolation boundary for file I/O. Every
31
- * built-in tool that touches the filesystem (ReadFile, WriteFile, EditFile)
32
- * delegates to this interface — the agent never accesses `node:fs` directly.
33
- *
34
- * Swap implementations to control where files live and what the agent can reach:
35
- * - `LocalFs` — reads/writes on the host filesystem (no isolation, for local dev)
36
- * - `SpritesFs` — reads/writes inside a remote sprites.dev container (full sandbox)
37
- * - Custom — implement this interface for Docker volumes, E2B, S3, in-memory, etc.
38
- */
39
- interface VirtualFs {
40
- readFile(path: string, opts?: ReadOptions): Promise<string>;
41
- /**
42
- * Read raw bytes from a file. Used for binary content (images, PDFs).
43
- * Implementations SHOULD cap the read at `maxBytes` to prevent OOM on
44
- * very large files. When `maxBytes` is omitted, the entire file is read.
45
- *
46
- * Returns a Buffer (Node.js) or Uint8Array.
47
- */
48
- readFileBytes?(path: string, maxBytes?: number): Promise<Buffer>;
49
- writeFile(path: string, content: string): Promise<void>;
50
- appendFile(path: string, content: string): Promise<void>;
51
- deleteFile(path: string, opts?: {
52
- recursive?: boolean;
53
- }): Promise<void>;
54
- mkdir(path: string, opts?: {
55
- recursive?: boolean;
56
- }): Promise<void>;
57
- readdir(path: string, opts?: {
58
- recursive?: boolean;
59
- }): Promise<FileEntry[]>;
60
- exists(path: string): Promise<boolean>;
61
- stat(path: string): Promise<FileStat>;
62
- }
63
-
64
- interface ExecOptions {
65
- timeout?: number;
66
- cwd?: string;
67
- env?: Record<string, string>;
68
- signal?: AbortSignal;
69
- }
70
- interface CommandResult {
71
- exitCode: number;
72
- stdout: string;
73
- stderr: string;
74
- }
75
- /**
76
- * Sandboxed shell execution interface.
77
- *
78
- * `VirtualComputer` is noumen's primary isolation boundary for command
79
- * execution. Every built-in tool that runs shell commands (Bash, Glob, Grep)
80
- * delegates to this interface — the agent never spawns processes directly.
81
- *
82
- * Swap implementations to control where and how commands run:
83
- * - `LocalComputer` — runs on the host machine (no isolation, for local dev)
84
- * - `SpritesComputer` — runs in a remote sprites.dev container (full sandbox)
85
- * - Custom — implement this interface for Docker, E2B, Daytona, etc.
86
- */
87
- interface VirtualComputer {
88
- executeCommand(command: string, opts?: ExecOptions): Promise<CommandResult>;
89
- }
90
-
91
5
  /**
92
6
  * Zod integration utilities. Users bring their own `zod` dependency — these
93
7
  * helpers accept duck-typed schemas so we don't force a hard dependency.
@@ -642,4 +556,4 @@ interface Tool {
642
556
  call(args: Record<string, unknown>, ctx: ToolContext): Promise<ToolResult>;
643
557
  }
644
558
 
645
- export { type ZodLikeSchema as $, type PermissionDeniedHookInput as A, type PermissionRequestHookInput as B, type CommandResult as C, DiagnosticRegistry as D, type ExecOptions as E, type FileEntry as F, type RetryAttemptHookInput as G, type HookDefinition as H, type SafeParseResult as I, type JsonSchemaType as J, type SessionEndHookInput as K, type LspServerConfig as L, type MemoryUpdateHookInput as M, type NotificationHookInput as N, type SessionStartHookInput as O, type PostToolUseFailureHookInput as P, type SubagentStartHookInput as Q, type ReadOptions as R, type SubagentConfig as S, type Tool as T, type SubagentStopHookInput as U, type VirtualFs as V, type Task as W, type TaskCreateInput as X, type TaskStatus as Y, type TaskUpdateInput as Z, type ToolParameters as _, type LspServerState as a, formatZodValidationError as a0, registerZodToJsonSchema as a1, zodToJsonSchema as a2, type LspDiagnostic as b, type LspLocation as c, type LspOperation as d, LspServerManager as e, type LspSymbol as f, type ToolResult as g, type ToolContext as h, type FileStat as i, type VirtualComputer as j, type SubagentRun as k, TaskStore as l, FileCheckpointManager as m, type FileStateCacheConfig as n, type HookEvent as o, type HookInput as p, type PostToolUseFailureHookOutput as q, type PostToolUseHookInput as r, type PostToolUseHookOutput as s, type PreToolUseHookInput as t, type PreToolUseHookOutput as u, type FileState as v, FileStateCache as w, type FileWriteHookInput as x, type HookOutput as y, type ModelSwitchHookInput as z };
559
+ export { type SessionEndHookInput as A, type SessionStartHookInput as B, type SubagentStartHookInput as C, DiagnosticRegistry as D, type SubagentStopHookInput as E, FileCheckpointManager as F, type Task as G, type HookDefinition as H, type TaskCreateInput as I, type JsonSchemaType as J, type TaskStatus as K, type LspServerConfig as L, type MemoryUpdateHookInput as M, type NotificationHookInput as N, type TaskUpdateInput as O, type PostToolUseFailureHookInput as P, type ToolParameters as Q, type RetryAttemptHookInput as R, type SubagentConfig as S, type Tool as T, formatZodValidationError as U, registerZodToJsonSchema as V, zodToJsonSchema as W, type ZodLikeSchema as Z, type LspServerState as a, type LspDiagnostic as b, type LspLocation as c, type LspOperation as d, LspServerManager as e, type LspSymbol as f, type ToolResult as g, type ToolContext as h, type SubagentRun as i, TaskStore as j, type FileStateCacheConfig as k, type HookEvent as l, type HookInput as m, type PostToolUseFailureHookOutput as n, type PostToolUseHookInput as o, type PostToolUseHookOutput as p, type PreToolUseHookInput as q, type PreToolUseHookOutput as r, type FileState as s, FileStateCache as t, type FileWriteHookInput as u, type HookOutput as v, type ModelSwitchHookInput as w, type PermissionDeniedHookInput as x, type PermissionRequestHookInput as y, type SafeParseResult as z };
@@ -225,6 +225,17 @@ interface CustomTitleEntry {
225
225
  title: string;
226
226
  timestamp: string;
227
227
  }
228
+ /**
229
+ * AI-generated session title. Persisted separately from `custom-title`
230
+ * so user-set titles always win regardless of write order. Reader logic
231
+ * prefers `custom-title` over `ai-title`.
232
+ */
233
+ interface AiTitleEntry {
234
+ type: "ai-title";
235
+ sessionId: string;
236
+ title: string;
237
+ timestamp: string;
238
+ }
228
239
  interface MetadataEntry {
229
240
  type: "metadata";
230
241
  sessionId: string;
@@ -265,12 +276,20 @@ interface ContentReplacementEntry {
265
276
  timestamp: string;
266
277
  replacements: ContentReplacementRecord[];
267
278
  }
268
- type Entry = MessageEntry | CompactBoundaryEntry | SummaryEntry | CustomTitleEntry | MetadataEntry | ToolResultOverflowEntry | FileCheckpointEntry | ContentReplacementEntry | SnipBoundaryEntry;
279
+ type Entry = MessageEntry | CompactBoundaryEntry | SummaryEntry | CustomTitleEntry | AiTitleEntry | MetadataEntry | ToolResultOverflowEntry | FileCheckpointEntry | ContentReplacementEntry | SnipBoundaryEntry;
269
280
  interface SessionInfo {
270
281
  sessionId: string;
271
282
  createdAt: string;
272
283
  lastMessageAt: string;
284
+ /**
285
+ * Effective title for display. When both a user-set (`custom-title`) and
286
+ * an AI-generated (`ai-title`) entry exist, the user-set one wins.
287
+ */
273
288
  title?: string;
289
+ /** User-set title, if any. */
290
+ customTitle?: string;
291
+ /** AI-generated title, if any. */
292
+ aiTitle?: string;
274
293
  messageCount: number;
275
294
  }
276
295
  interface ToolResult {
@@ -388,6 +407,18 @@ type StreamEvent = {
388
407
  type: "session_resumed";
389
408
  sessionId: string;
390
409
  messageCount: number;
410
+ }
411
+ /**
412
+ * Title change event. `noumen` defines the shape so consumers can wire
413
+ * renames + auto-titles into the same stream as other StreamEvents, but
414
+ * does not emit it internally: callers synthesize it after
415
+ * `Agent.setCustomTitle` / `Agent.autoTitleIfMissing` resolves.
416
+ */
417
+ | {
418
+ type: "title_updated";
419
+ sessionId: string;
420
+ title: string;
421
+ source: "custom" | "ai";
391
422
  } | {
392
423
  type: "checkpoint_snapshot";
393
424
  messageId: string;
@@ -556,6 +587,13 @@ interface ChatParams {
556
587
  }
557
588
  interface AIProvider {
558
589
  chat(params: ChatParams): AsyncIterable<ChatStreamChunk>;
590
+ /**
591
+ * Optional fallback model name, used when no `model` is provided at the
592
+ * Thread / Agent level. Consumers should pass explicit models when they
593
+ * can, but this lets each provider ship a sensible default without
594
+ * forcing Thread to hardcode provider-specific strings.
595
+ */
596
+ readonly defaultModel?: string;
559
597
  }
560
598
  /**
561
599
  * Extended error type that providers can throw to convey retry-relevant metadata.
@@ -572,4 +610,4 @@ declare class ChatStreamError extends Error {
572
610
  });
573
611
  }
574
612
 
575
- export { createCheckpointState as $, type AIProvider as A, type FileCheckpointBackup as B, type ChatParams as C, type DiffStats as D, type Entry as E, type FileCheckpointState as F, type FileCheckpointEntry as G, type ImageUrlContent as H, type ImageContent as I, type JsonSchemaOutputFormat as J, type JsonObjectOutputFormat as K, type MemoryType as L, type ModelPricing as M, type MessageEntry as N, type OutputFormat as O, type MetadataEntry as P, type SerializedMessage as Q, type RunOptions as R, type StreamEvent as S, type ToolDefinition as T, type UUID as U, type SnipBoundaryEntry as V, type SummaryEntry as W, type SystemMessage as X, type TextContent as Y, type ToolParameterProperty as Z, type UserMessage as _, type ChatStreamChunk as a, type ChatMessage as b, type CheckpointConfig as c, type FileCheckpointSnapshot as d, type ContentPart as e, type ContentReplacementRecord as f, type SessionInfo as g, type UsageRecord as h, type CostSummary as i, type ModelUsageSummary as j, type ChatCompletionUsage as k, type ThinkingConfig as l, type MemoryConfig as m, type ToolResult as n, type ToolCallContent as o, type MemoryProvider as p, type MemoryEntry as q, type AssistantMessage as r, type ToolResultMessage as s, type ToolResultOverflowEntry as t, type ChatStreamChoice as u, type ChatStreamDelta as v, ChatStreamError as w, type CompactBoundaryEntry as x, type ContentReplacementEntry as y, type CustomTitleEntry as z };
613
+ export { type UserMessage as $, type AIProvider as A, type CustomTitleEntry as B, type ChatParams as C, type DiffStats as D, type Entry as E, type FileCheckpointState as F, type FileCheckpointBackup as G, type FileCheckpointEntry as H, type ImageContent as I, type JsonSchemaOutputFormat as J, type ImageUrlContent as K, type JsonObjectOutputFormat as L, type ModelPricing as M, type MemoryType as N, type OutputFormat as O, type MessageEntry as P, type MetadataEntry as Q, type RunOptions as R, type StreamEvent as S, type ToolDefinition as T, type UUID as U, type SerializedMessage as V, type SnipBoundaryEntry as W, type SummaryEntry as X, type SystemMessage as Y, type TextContent as Z, type ToolParameterProperty as _, type ChatStreamChunk as a, createCheckpointState as a0, type ChatMessage as b, type CheckpointConfig as c, type FileCheckpointSnapshot as d, type ContentPart as e, type ContentReplacementRecord as f, type SessionInfo as g, type UsageRecord as h, type CostSummary as i, type ModelUsageSummary as j, type ChatCompletionUsage as k, type ThinkingConfig as l, type MemoryConfig as m, type ToolResult as n, type ToolCallContent as o, type MemoryProvider as p, type MemoryEntry as q, type AssistantMessage as r, type ToolResultMessage as s, type ToolResultOverflowEntry as t, type AiTitleEntry as u, type ChatStreamChoice as v, type ChatStreamDelta as w, ChatStreamError as x, type CompactBoundaryEntry as y, type ContentReplacementEntry as z };