@ottocode/server 0.1.198 → 0.1.200
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ottocode/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.200",
|
|
4
4
|
"description": "HTTP API server for ottocode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"typecheck": "tsc --noEmit"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@ottocode/sdk": "0.1.
|
|
53
|
-
"@ottocode/database": "0.1.
|
|
52
|
+
"@ottocode/sdk": "0.1.200",
|
|
53
|
+
"@ottocode/database": "0.1.200",
|
|
54
54
|
"drizzle-orm": "^0.44.5",
|
|
55
55
|
"hono": "^4.9.9",
|
|
56
56
|
"zod": "^4.1.8"
|
package/src/events/types.ts
CHANGED
|
@@ -61,6 +61,7 @@ export function registerModelsRoutes(app: Hono) {
|
|
|
61
61
|
toolCall: m.toolCall,
|
|
62
62
|
reasoningText: m.reasoningText,
|
|
63
63
|
vision: m.modalities?.input?.includes('image') ?? false,
|
|
64
|
+
attachment: m.attachment ?? false,
|
|
64
65
|
})),
|
|
65
66
|
default: getDefault(
|
|
66
67
|
embeddedConfig?.model,
|
|
@@ -124,6 +125,7 @@ export function registerModelsRoutes(app: Hono) {
|
|
|
124
125
|
toolCall: m.toolCall,
|
|
125
126
|
reasoningText: m.reasoningText,
|
|
126
127
|
vision: m.modalities?.input?.includes('image') ?? false,
|
|
128
|
+
attachment: m.attachment ?? false,
|
|
127
129
|
})),
|
|
128
130
|
};
|
|
129
131
|
}
|
package/src/routes/files.ts
CHANGED
|
@@ -279,4 +279,71 @@ export function registerFilesRoutes(app: Hono) {
|
|
|
279
279
|
return c.json({ error: serializeError(err) }, 500);
|
|
280
280
|
}
|
|
281
281
|
});
|
|
282
|
+
|
|
283
|
+
app.get('/v1/files/tree', async (c) => {
|
|
284
|
+
try {
|
|
285
|
+
const projectRoot = c.req.query('project') || process.cwd();
|
|
286
|
+
const dirPath = c.req.query('path') || '.';
|
|
287
|
+
const targetDir = join(projectRoot, dirPath);
|
|
288
|
+
|
|
289
|
+
const gitignorePatterns = await parseGitignore(projectRoot);
|
|
290
|
+
const entries = await readdir(targetDir, { withFileTypes: true });
|
|
291
|
+
|
|
292
|
+
const items: Array<{
|
|
293
|
+
name: string;
|
|
294
|
+
path: string;
|
|
295
|
+
type: 'file' | 'directory';
|
|
296
|
+
}> = [];
|
|
297
|
+
|
|
298
|
+
for (const entry of entries) {
|
|
299
|
+
if (entry.name.startsWith('.') && entry.name !== '.otto') continue;
|
|
300
|
+
const relPath = relative(projectRoot, join(targetDir, entry.name));
|
|
301
|
+
|
|
302
|
+
if (entry.isDirectory()) {
|
|
303
|
+
if (shouldExcludeDir(entry.name)) continue;
|
|
304
|
+
if (matchesGitignorePattern(relPath, gitignorePatterns)) continue;
|
|
305
|
+
items.push({ name: entry.name, path: relPath, type: 'directory' });
|
|
306
|
+
} else if (entry.isFile()) {
|
|
307
|
+
if (shouldExcludeFile(entry.name)) continue;
|
|
308
|
+
if (matchesGitignorePattern(relPath, gitignorePatterns)) continue;
|
|
309
|
+
items.push({ name: entry.name, path: relPath, type: 'file' });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
items.sort((a, b) => {
|
|
314
|
+
if (a.type !== b.type) return a.type === 'directory' ? -1 : 1;
|
|
315
|
+
return a.name.localeCompare(b.name);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
return c.json({ items, path: dirPath });
|
|
319
|
+
} catch (err) {
|
|
320
|
+
logger.error('Files tree route error:', err);
|
|
321
|
+
return c.json({ error: serializeError(err) }, 500);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
app.get('/v1/files/read', async (c) => {
|
|
326
|
+
try {
|
|
327
|
+
const projectRoot = c.req.query('project') || process.cwd();
|
|
328
|
+
const filePath = c.req.query('path');
|
|
329
|
+
|
|
330
|
+
if (!filePath) {
|
|
331
|
+
return c.json({ error: 'Missing required query parameter: path' }, 400);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const absPath = join(projectRoot, filePath);
|
|
335
|
+
if (!absPath.startsWith(projectRoot)) {
|
|
336
|
+
return c.json({ error: 'Path traversal not allowed' }, 403);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const content = await readFile(absPath, 'utf-8');
|
|
340
|
+
const extension = filePath.split('.').pop()?.toLowerCase() ?? '';
|
|
341
|
+
const lineCount = content.split('\n').length;
|
|
342
|
+
|
|
343
|
+
return c.json({ content, path: filePath, extension, lineCount });
|
|
344
|
+
} catch (err) {
|
|
345
|
+
logger.error('Files read route error:', err);
|
|
346
|
+
return c.json({ error: serializeError(err) }, 500);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
282
349
|
}
|
package/src/routes/git/diff.ts
CHANGED
|
@@ -73,6 +73,12 @@ export function registerDiffRoute(app: Hono) {
|
|
|
73
73
|
const diffArgs = query.staged
|
|
74
74
|
? ['diff', '--cached', '--', query.file]
|
|
75
75
|
: ['diff', '--', query.file];
|
|
76
|
+
|
|
77
|
+
const fullFile = c.req.query('fullFile') === 'true';
|
|
78
|
+
if (fullFile) {
|
|
79
|
+
diffArgs.splice(1, 0, '-U99999');
|
|
80
|
+
}
|
|
81
|
+
|
|
76
82
|
const numstatArgs = query.staged
|
|
77
83
|
? ['diff', '--cached', '--numstat', '--', query.file]
|
|
78
84
|
: ['diff', '--numstat', '--', query.file];
|
|
@@ -116,6 +122,7 @@ export function registerDiffRoute(app: Hono) {
|
|
|
116
122
|
file: query.file,
|
|
117
123
|
absPath,
|
|
118
124
|
diff: diffText,
|
|
125
|
+
fullFile,
|
|
119
126
|
isNewFile: false,
|
|
120
127
|
isBinary: binary,
|
|
121
128
|
insertions,
|
|
@@ -82,6 +82,13 @@ export async function resolveSetuModel(
|
|
|
82
82
|
payload: { error },
|
|
83
83
|
});
|
|
84
84
|
},
|
|
85
|
+
onBalanceUpdate: (update) => {
|
|
86
|
+
publish({
|
|
87
|
+
type: 'setu.balance.updated',
|
|
88
|
+
sessionId,
|
|
89
|
+
payload: update,
|
|
90
|
+
});
|
|
91
|
+
},
|
|
85
92
|
onPaymentApproval: async (info): Promise<TopupMethod | 'cancel'> => {
|
|
86
93
|
const suggestedTopupUsd = Math.max(
|
|
87
94
|
MIN_TOPUP_USD,
|