@0xmaxma/claude-gateway 1.5.7 → 1.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.
- package/README.md +22 -0
- package/dist/agent/runner.d.ts +31 -0
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +224 -16
- package/dist/agent/runner.js.map +1 -1
- package/dist/api/apps-router.d.ts.map +1 -1
- package/dist/api/apps-router.js +7 -2
- package/dist/api/apps-router.js.map +1 -1
- package/dist/api/gateway-router.d.ts.map +1 -1
- package/dist/api/gateway-router.js +27 -0
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/line-webhook-router.d.ts.map +1 -1
- package/dist/api/line-webhook-router.js +68 -0
- package/dist/api/line-webhook-router.js.map +1 -1
- package/dist/api/router.d.ts +2 -0
- package/dist/api/router.d.ts.map +1 -1
- package/dist/api/router.js +60 -4
- package/dist/api/router.js.map +1 -1
- package/dist/api/share-router.d.ts +11 -0
- package/dist/api/share-router.d.ts.map +1 -0
- package/dist/api/share-router.js +402 -0
- package/dist/api/share-router.js.map +1 -0
- package/dist/apps/installer.d.ts +55 -0
- package/dist/apps/installer.d.ts.map +1 -1
- package/dist/apps/installer.js +136 -1
- package/dist/apps/installer.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +9 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/public-url.d.ts +11 -0
- package/dist/config/public-url.d.ts.map +1 -0
- package/dist/config/public-url.js +41 -0
- package/dist/config/public-url.js.map +1 -0
- package/dist/config/watcher.d.ts.map +1 -1
- package/dist/config/watcher.js +1 -0
- package/dist/config/watcher.js.map +1 -1
- package/dist/history/db.d.ts +14 -0
- package/dist/history/db.d.ts.map +1 -1
- package/dist/history/db.js +48 -4
- package/dist/history/db.js.map +1 -1
- package/dist/history/types.d.ts +5 -0
- package/dist/history/types.d.ts.map +1 -1
- package/dist/session/process.d.ts +3 -0
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +27 -1
- package/dist/session/process.js.map +1 -1
- package/dist/session/store.d.ts +2 -1
- package/dist/session/store.d.ts.map +1 -1
- package/dist/session/store.js +10 -2
- package/dist/session/store.js.map +1 -1
- package/dist/share/session-image-catalog.d.ts +22 -0
- package/dist/share/session-image-catalog.d.ts.map +1 -0
- package/dist/share/session-image-catalog.js +151 -0
- package/dist/share/session-image-catalog.js.map +1 -0
- package/dist/share/share-store.d.ts +137 -0
- package/dist/share/share-store.d.ts.map +1 -0
- package/dist/share/share-store.js +340 -0
- package/dist/share/share-store.js.map +1 -0
- package/dist/types.d.ts +19 -7
- package/dist/types.d.ts.map +1 -1
- package/mcp/instructions.ts +1 -0
- package/mcp/server.ts +2 -0
- package/mcp/tools/agent/handlers.ts +55 -4
- package/mcp/tools/image/module.ts +240 -26
- package/mcp/tools/line/module.ts +186 -0
- package/mcp/tools/share-image/module.ts +120 -0
- package/mcp/tools/shared/share-client.ts +197 -0
- package/package.json +3 -1
package/dist/api/router.js
CHANGED
|
@@ -33,6 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.isValidSessionId = isValidSessionId;
|
|
37
|
+
exports.isValidAgentId = isValidAgentId;
|
|
36
38
|
exports.createApiRouter = createApiRouter;
|
|
37
39
|
const express_1 = require("express");
|
|
38
40
|
const crypto_1 = require("crypto");
|
|
@@ -52,6 +54,21 @@ const MAX_MESSAGE_LENGTH = 10000;
|
|
|
52
54
|
const DEFAULT_TIMEOUT_MS = 60000;
|
|
53
55
|
const AGENT_ID_RE = /^[a-z][a-z0-9_-]{1,31}$/;
|
|
54
56
|
const SAFE_FILENAME_RE = /^[a-zA-Z0-9._\-() ]+$/;
|
|
57
|
+
// session_id becomes a filesystem key (sessions/<id>.jsonl, .sessions/<id>/) so it
|
|
58
|
+
// must be constrained to the same safe charset as chat_id — no '/' or '.' that could
|
|
59
|
+
// escape the agent's directory. Clients may pass custom (non-UUID) session ids, so
|
|
60
|
+
// this preserves that while blocking path traversal.
|
|
61
|
+
const SESSION_ID_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
62
|
+
function isValidSessionId(v) {
|
|
63
|
+
return typeof v === 'string' && SESSION_ID_RE.test(v);
|
|
64
|
+
}
|
|
65
|
+
// agent_id likewise becomes a filesystem key (agents/<id>/media/…), so any
|
|
66
|
+
// endpoint that joins it into a path MUST format-validate it first — a bare
|
|
67
|
+
// non-empty check lets "../x" relocate the containment root itself. Exported so
|
|
68
|
+
// sibling routers (image share) apply the identical guard as the /api routes.
|
|
69
|
+
function isValidAgentId(v) {
|
|
70
|
+
return typeof v === 'string' && AGENT_ID_RE.test(v);
|
|
71
|
+
}
|
|
55
72
|
function maskToken(token) {
|
|
56
73
|
if (token.length <= 12)
|
|
57
74
|
return '•'.repeat(token.length);
|
|
@@ -256,8 +273,8 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
256
273
|
res.status(400).json({ error: 'chat_id must be 1-64 alphanumeric characters, hyphens, or underscores' });
|
|
257
274
|
return;
|
|
258
275
|
}
|
|
259
|
-
if (session_id !== undefined &&
|
|
260
|
-
res.status(400).json({ error: 'session_id must be
|
|
276
|
+
if (session_id !== undefined && !isValidSessionId(session_id)) {
|
|
277
|
+
res.status(400).json({ error: 'session_id must be 1-64 alphanumeric characters, hyphens, or underscores' });
|
|
261
278
|
return;
|
|
262
279
|
}
|
|
263
280
|
// Validate media_files
|
|
@@ -306,6 +323,26 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
306
323
|
out[f] = v.trim();
|
|
307
324
|
}
|
|
308
325
|
}
|
|
326
|
+
// image_refs (#73) — reference images explicitly selected in the composer,
|
|
327
|
+
// order-significant. Each entry is a ref from GET /api/v1/image-catalog.
|
|
328
|
+
if (ip.image_refs !== undefined) {
|
|
329
|
+
const refs = ip.image_refs;
|
|
330
|
+
if (!Array.isArray(refs) || refs.some((r) => typeof r !== 'string' || !r.trim())) {
|
|
331
|
+
res.status(400).json({ error: 'image_params.image_refs must be an array of non-empty strings' });
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const trimmedRefs = refs.map((r) => r.trim());
|
|
335
|
+
if (trimmedRefs.length > 5) {
|
|
336
|
+
res.status(400).json({ error: 'image_params.image_refs allows at most 5 references' });
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (new Set(trimmedRefs).size !== trimmedRefs.length) {
|
|
340
|
+
res.status(400).json({ error: 'image_params.image_refs must not contain duplicates' });
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (trimmedRefs.length)
|
|
344
|
+
out.image_refs = trimmedRefs;
|
|
345
|
+
}
|
|
309
346
|
if (ip.n !== undefined) {
|
|
310
347
|
if (typeof ip.n !== 'number' || !Number.isFinite(ip.n) || ip.n < 1) {
|
|
311
348
|
res.status(400).json({ error: 'image_params.n must be a positive number' });
|
|
@@ -566,7 +603,7 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
566
603
|
description: cfg?.description ?? '',
|
|
567
604
|
sessions: sessions.map((s) => {
|
|
568
605
|
const meta = metaMap.get(s.sessionId);
|
|
569
|
-
return { ...s, sessionName: meta?.name ?? null, imageConfig: meta?.imageConfig ?? null };
|
|
606
|
+
return { ...s, sessionName: meta?.name ?? null, imageConfig: meta?.imageConfig ?? null, model: meta?.model ?? null };
|
|
570
607
|
}),
|
|
571
608
|
};
|
|
572
609
|
}));
|
|
@@ -2587,7 +2624,22 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
2587
2624
|
const baseName = path.basename(rawFilename).replace(/\s+/g, '_');
|
|
2588
2625
|
const safeBaseName = SAFE_FILENAME_RE.test(baseName) ? baseName : 'upload';
|
|
2589
2626
|
const rawExt = path.extname(safeBaseName).replace(/[^a-zA-Z0-9.]/g, '').slice(0, 10);
|
|
2590
|
-
|
|
2627
|
+
// No usable extension (clipboard paste, non-ASCII filename sanitized to
|
|
2628
|
+
// 'upload') → derive it from the MIME type. Falling straight to .bin made
|
|
2629
|
+
// pasted images invisible to the session image catalog, which keys off the
|
|
2630
|
+
// file extension — so they could never be referenced (#74).
|
|
2631
|
+
const mimeExt = mimeType.includes('png')
|
|
2632
|
+
? '.png'
|
|
2633
|
+
: mimeType.includes('jpeg') || mimeType.includes('jpg')
|
|
2634
|
+
? '.jpeg'
|
|
2635
|
+
: mimeType.includes('webp')
|
|
2636
|
+
? '.webp'
|
|
2637
|
+
: mimeType.includes('gif')
|
|
2638
|
+
? '.gif'
|
|
2639
|
+
: mimeType.includes('pdf')
|
|
2640
|
+
? '.pdf'
|
|
2641
|
+
: '.bin';
|
|
2642
|
+
const ext = rawExt || mimeExt;
|
|
2591
2643
|
const tmpFile = path.join(os.tmpdir(), `gw-${Date.now()}${ext}`);
|
|
2592
2644
|
try {
|
|
2593
2645
|
await fsp.writeFile(tmpFile, buf);
|
|
@@ -3095,6 +3147,10 @@ function createApiRouter(agentRunners, agentConfigs, apiKeys, configPath, models
|
|
|
3095
3147
|
res.status(400).json({ error: 'session_id is required' });
|
|
3096
3148
|
return;
|
|
3097
3149
|
}
|
|
3150
|
+
if (!isValidSessionId(sessionId)) {
|
|
3151
|
+
res.status(400).json({ error: 'session_id must be 1-64 alphanumeric characters, hyphens, or underscores' });
|
|
3152
|
+
return;
|
|
3153
|
+
}
|
|
3098
3154
|
// chat_id is optional — provide the same value used when creating the session via POST /sessions
|
|
3099
3155
|
// so the greeting message lands in the correct historyDb bucket (api-{chatId}).
|
|
3100
3156
|
// If omitted, sessionId is used as the bucket key, which creates a secondary index entry.
|