@0xmaxma/claude-gateway 1.0.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 +791 -0
- package/config.template.json +87 -0
- package/dist/agent/context-isolation.d.ts +28 -0
- package/dist/agent/context-isolation.d.ts.map +1 -0
- package/dist/agent/context-isolation.js +80 -0
- package/dist/agent/context-isolation.js.map +1 -0
- package/dist/agent/runner.d.ts +211 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +1802 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/workspace-loader.d.ts +31 -0
- package/dist/agent/workspace-loader.d.ts.map +1 -0
- package/dist/agent/workspace-loader.js +207 -0
- package/dist/agent/workspace-loader.js.map +1 -0
- package/dist/api/auth.d.ts +25 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +77 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/cron-router.d.ts +22 -0
- package/dist/api/cron-router.d.ts.map +1 -0
- package/dist/api/cron-router.js +197 -0
- package/dist/api/cron-router.js.map +1 -0
- package/dist/api/gateway-router.d.ts +52 -0
- package/dist/api/gateway-router.d.ts.map +1 -0
- package/dist/api/gateway-router.js +215 -0
- package/dist/api/gateway-router.js.map +1 -0
- package/dist/api/router.d.ts +5 -0
- package/dist/api/router.d.ts.map +1 -0
- package/dist/api/router.js +1098 -0
- package/dist/api/router.js.map +1 -0
- package/dist/api/skills-router.d.ts +5 -0
- package/dist/api/skills-router.d.ts.map +1 -0
- package/dist/api/skills-router.js +424 -0
- package/dist/api/skills-router.js.map +1 -0
- package/dist/api/workspace-router.d.ts +4 -0
- package/dist/api/workspace-router.d.ts.map +1 -0
- package/dist/api/workspace-router.js +149 -0
- package/dist/api/workspace-router.js.map +1 -0
- package/dist/config/loader.d.ts +16 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +235 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/migrator.d.ts +70 -0
- package/dist/config/migrator.d.ts.map +1 -0
- package/dist/config/migrator.js +343 -0
- package/dist/config/migrator.js.map +1 -0
- package/dist/config/watcher.d.ts +30 -0
- package/dist/config/watcher.d.ts.map +1 -0
- package/dist/config/watcher.js +170 -0
- package/dist/config/watcher.js.map +1 -0
- package/dist/cron/manager.d.ts +48 -0
- package/dist/cron/manager.d.ts.map +1 -0
- package/dist/cron/manager.js +580 -0
- package/dist/cron/manager.js.map +1 -0
- package/dist/cron/scheduler.d.ts +50 -0
- package/dist/cron/scheduler.d.ts.map +1 -0
- package/dist/cron/scheduler.js +231 -0
- package/dist/cron/scheduler.js.map +1 -0
- package/dist/discord/receiver.d.ts +17 -0
- package/dist/discord/receiver.d.ts.map +1 -0
- package/dist/discord/receiver.js +108 -0
- package/dist/discord/receiver.js.map +1 -0
- package/dist/heartbeat/history.d.ts +24 -0
- package/dist/heartbeat/history.d.ts.map +1 -0
- package/dist/heartbeat/history.js +50 -0
- package/dist/heartbeat/history.js.map +1 -0
- package/dist/heartbeat/parser.d.ts +26 -0
- package/dist/heartbeat/parser.d.ts.map +1 -0
- package/dist/heartbeat/parser.js +283 -0
- package/dist/heartbeat/parser.js.map +1 -0
- package/dist/history/cleanup.d.ts +21 -0
- package/dist/history/cleanup.d.ts.map +1 -0
- package/dist/history/cleanup.js +171 -0
- package/dist/history/cleanup.js.map +1 -0
- package/dist/history/db.d.ts +27 -0
- package/dist/history/db.d.ts.map +1 -0
- package/dist/history/db.js +323 -0
- package/dist/history/db.js.map +1 -0
- package/dist/history/media-store.d.ts +27 -0
- package/dist/history/media-store.d.ts.map +1 -0
- package/dist/history/media-store.js +158 -0
- package/dist/history/media-store.js.map +1 -0
- package/dist/history/types.d.ts +62 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/history/types.js +3 -0
- package/dist/history/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +483 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +81 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory/manager.d.ts +45 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +178 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/session/compactor.d.ts +22 -0
- package/dist/session/compactor.d.ts.map +1 -0
- package/dist/session/compactor.js +151 -0
- package/dist/session/compactor.js.map +1 -0
- package/dist/session/process.d.ts +76 -0
- package/dist/session/process.d.ts.map +1 -0
- package/dist/session/process.js +729 -0
- package/dist/session/process.js.map +1 -0
- package/dist/session/store.d.ts +102 -0
- package/dist/session/store.d.ts.map +1 -0
- package/dist/session/store.js +533 -0
- package/dist/session/store.js.map +1 -0
- package/dist/skills/index.d.ts +9 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +15 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/invoker.d.ts +16 -0
- package/dist/skills/invoker.d.ts.map +1 -0
- package/dist/skills/invoker.js +36 -0
- package/dist/skills/invoker.js.map +1 -0
- package/dist/skills/loader.d.ts +23 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +183 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/parser.d.ts +55 -0
- package/dist/skills/parser.d.ts.map +1 -0
- package/dist/skills/parser.js +178 -0
- package/dist/skills/parser.js.map +1 -0
- package/dist/skills/sync.d.ts +10 -0
- package/dist/skills/sync.d.ts.map +1 -0
- package/dist/skills/sync.js +130 -0
- package/dist/skills/sync.js.map +1 -0
- package/dist/skills/watcher.d.ts +16 -0
- package/dist/skills/watcher.d.ts.map +1 -0
- package/dist/skills/watcher.js +25 -0
- package/dist/skills/watcher.js.map +1 -0
- package/dist/telegram/markdown.d.ts +25 -0
- package/dist/telegram/markdown.d.ts.map +1 -0
- package/dist/telegram/markdown.js +237 -0
- package/dist/telegram/markdown.js.map +1 -0
- package/dist/telegram/receiver.d.ts +17 -0
- package/dist/telegram/receiver.d.ts.map +1 -0
- package/dist/telegram/receiver.js +104 -0
- package/dist/telegram/receiver.js.map +1 -0
- package/dist/types.d.ts +224 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/web-ui.d.ts +6 -0
- package/dist/ui/web-ui.d.ts.map +1 -0
- package/dist/ui/web-ui.js +227 -0
- package/dist/ui/web-ui.js.map +1 -0
- package/dist/watch/factory.d.ts +26 -0
- package/dist/watch/factory.d.ts.map +1 -0
- package/dist/watch/factory.js +43 -0
- package/dist/watch/factory.js.map +1 -0
- package/dist/webhook/manager.d.ts +34 -0
- package/dist/webhook/manager.d.ts.map +1 -0
- package/dist/webhook/manager.js +120 -0
- package/dist/webhook/manager.js.map +1 -0
- package/mcp/bun.lock +264 -0
- package/mcp/channel-manager.ts +115 -0
- package/mcp/package.json +15 -0
- package/mcp/router.ts +69 -0
- package/mcp/server.ts +129 -0
- package/mcp/tools/agent/handlers.ts +578 -0
- package/mcp/tools/agent/module.ts +163 -0
- package/mcp/tools/browser/module.ts +321 -0
- package/mcp/tools/browser/skills/open-browser/SKILL.md +89 -0
- package/mcp/tools/cron/client.ts +65 -0
- package/mcp/tools/cron/module.ts +158 -0
- package/mcp/tools/cron/skills/cron/SKILL.md +46 -0
- package/mcp/tools/discord/access.ts +197 -0
- package/mcp/tools/discord/client.ts +31 -0
- package/mcp/tools/discord/commands.ts +48 -0
- package/mcp/tools/discord/inbound.ts +53 -0
- package/mcp/tools/discord/module.ts +442 -0
- package/mcp/tools/discord/outbound.ts +90 -0
- package/mcp/tools/discord/receiver-server.ts +58 -0
- package/mcp/tools/discord/skills/access/SKILL.md +86 -0
- package/mcp/tools/discord/skills/configure/SKILL.md +53 -0
- package/mcp/tools/discord/threading.ts +37 -0
- package/mcp/tools/discord/types.ts +106 -0
- package/mcp/tools/skills/handlers.ts +196 -0
- package/mcp/tools/skills/module.ts +163 -0
- package/mcp/tools/telegram/module.ts +454 -0
- package/mcp/tools/telegram/pure.ts +224 -0
- package/mcp/tools/telegram/receiver-server.ts +1656 -0
- package/mcp/tools/telegram/skills/access/SKILL.md +169 -0
- package/mcp/tools/telegram/skills/configure/SKILL.md +118 -0
- package/mcp/tools/telegram/typing.ts +327 -0
- package/mcp/types.ts +128 -0
- package/package.json +62 -0
- package/resource/claude_gateway.svg +112 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_migration": {
|
|
3
|
+
"ignorePaths": [
|
|
4
|
+
"gateway.api",
|
|
5
|
+
"gateway.api.keys"
|
|
6
|
+
],
|
|
7
|
+
"removePaths": [
|
|
8
|
+
"telegram.allowedUsers",
|
|
9
|
+
"telegram.dmPolicy"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"configVersion": "1.0.5",
|
|
13
|
+
"gateway": {
|
|
14
|
+
"logDir": "~/.claude-gateway/logs",
|
|
15
|
+
"timezone": "Asia/Bangkok",
|
|
16
|
+
"models": [
|
|
17
|
+
{ "id": "claude-opus-4-7", "label": "Opus 4.7", "alias": "opus", "contextWindow": 1000000 },
|
|
18
|
+
{ "id": "claude-opus-4-6", "label": "Opus 4.6", "alias": "opus46", "contextWindow": 1000000 },
|
|
19
|
+
{ "id": "claude-sonnet-4-6", "label": "Sonnet 4.6", "alias": "sonnet", "contextWindow": 1000000 },
|
|
20
|
+
{ "id": "claude-haiku-4-5-20251001", "label": "Haiku 4.5", "alias": "haiku", "contextWindow": 200000 }
|
|
21
|
+
],
|
|
22
|
+
"api": {
|
|
23
|
+
"keys": [
|
|
24
|
+
{
|
|
25
|
+
"key": "${MY_API_KEY}",
|
|
26
|
+
"description": "Internal app",
|
|
27
|
+
"agents": ["alfred"]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"key": "${ADMIN_API_KEY}",
|
|
31
|
+
"description": "Admin — full access",
|
|
32
|
+
"agents": "*"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"history": {
|
|
37
|
+
"retentionDays": 60,
|
|
38
|
+
"cleanupHour": 0,
|
|
39
|
+
"cleanupTimezone": "UTC"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"agents": [
|
|
43
|
+
{
|
|
44
|
+
"id": "alfred",
|
|
45
|
+
"description": "Personal assistant — handles private messages from the owner",
|
|
46
|
+
"workspace": "~/.claude-gateway/agents/alfred/workspace",
|
|
47
|
+
"env": "~/.claude-gateway/agents/alfred/.env",
|
|
48
|
+
"telegram": {
|
|
49
|
+
"botToken": "${ALFRED_BOT_TOKEN}"
|
|
50
|
+
},
|
|
51
|
+
"claude": {
|
|
52
|
+
"model": "claude-opus-4-6",
|
|
53
|
+
"dangerouslySkipPermissions": true,
|
|
54
|
+
"extraFlags": []
|
|
55
|
+
},
|
|
56
|
+
"signatureEmoji": "",
|
|
57
|
+
"heartbeat": {
|
|
58
|
+
"rateLimitMinutes": 30
|
|
59
|
+
},
|
|
60
|
+
"session": {
|
|
61
|
+
"idleTimeoutMinutes": 30,
|
|
62
|
+
"maxConcurrent": 20
|
|
63
|
+
},
|
|
64
|
+
"history": {
|
|
65
|
+
"retentionDays": 90
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "baerbel",
|
|
70
|
+
"description": "Team support bot — open to all users",
|
|
71
|
+
"workspace": "~/.claude-gateway/agents/baerbel/workspace",
|
|
72
|
+
"env": "~/.claude-gateway/agents/baerbel/.env",
|
|
73
|
+
"telegram": {
|
|
74
|
+
"botToken": "${BAERBEL_BOT_TOKEN}"
|
|
75
|
+
},
|
|
76
|
+
"claude": {
|
|
77
|
+
"model": "claude-sonnet-4-6",
|
|
78
|
+
"dangerouslySkipPermissions": false,
|
|
79
|
+
"extraFlags": []
|
|
80
|
+
},
|
|
81
|
+
"session": {
|
|
82
|
+
"idleTimeoutMinutes": 30,
|
|
83
|
+
"maxConcurrent": 20
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AgentConfig } from '../types';
|
|
2
|
+
export declare class WorkspaceConflictError extends Error {
|
|
3
|
+
readonly agentIds: [string, string];
|
|
4
|
+
readonly workspace: string;
|
|
5
|
+
constructor(agentIds: [string, string], workspace: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class TokenConflictError extends Error {
|
|
8
|
+
readonly agentIds: [string, string];
|
|
9
|
+
readonly token: string;
|
|
10
|
+
constructor(agentIds: [string, string], token: string);
|
|
11
|
+
}
|
|
12
|
+
export declare class SessionDirConflictError extends Error {
|
|
13
|
+
readonly agentIds: [string, string];
|
|
14
|
+
readonly sessionDir: string;
|
|
15
|
+
constructor(agentIds: [string, string], sessionDir: string);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* ContextIsolationGuard ensures that no two agents share workspace path,
|
|
19
|
+
* session directory, or bot token. Call `validate()` at startup with all agent configs.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ContextIsolationGuard {
|
|
22
|
+
/**
|
|
23
|
+
* Validate all agent configs for isolation conflicts.
|
|
24
|
+
* Throws the first conflict found.
|
|
25
|
+
*/
|
|
26
|
+
validate(agents: AgentConfig[]): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=context-isolation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-isolation.d.ts","sourceRoot":"","sources":["../../src/agent/context-isolation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,qBAAa,sBAAuB,SAAQ,KAAK;aACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;aAAkB,SAAS,EAAE,MAAM;gBAA7D,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAkB,SAAS,EAAE,MAAM;CAM1F;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aACf,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;aAAkB,KAAK,EAAE,MAAM;gBAAzD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAkB,KAAK,EAAE,MAAM;CAMtF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;aACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;aAAkB,UAAU,EAAE,MAAM;gBAA9D,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAkB,UAAU,EAAE,MAAM;CAM3F;AAED;;;GAGG;AACH,qBAAa,qBAAqB;IAChC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI;CAyCtC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContextIsolationGuard = exports.SessionDirConflictError = exports.TokenConflictError = exports.WorkspaceConflictError = void 0;
|
|
4
|
+
class WorkspaceConflictError extends Error {
|
|
5
|
+
constructor(agentIds, workspace) {
|
|
6
|
+
super(`Workspace conflict: agents "${agentIds[0]}" and "${agentIds[1]}" share the same workspace path: "${workspace}"`);
|
|
7
|
+
this.agentIds = agentIds;
|
|
8
|
+
this.workspace = workspace;
|
|
9
|
+
this.name = 'WorkspaceConflictError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.WorkspaceConflictError = WorkspaceConflictError;
|
|
13
|
+
class TokenConflictError extends Error {
|
|
14
|
+
constructor(agentIds, token) {
|
|
15
|
+
super(`Token conflict: agents "${agentIds[0]}" and "${agentIds[1]}" share the same bot token`);
|
|
16
|
+
this.agentIds = agentIds;
|
|
17
|
+
this.token = token;
|
|
18
|
+
this.name = 'TokenConflictError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.TokenConflictError = TokenConflictError;
|
|
22
|
+
class SessionDirConflictError extends Error {
|
|
23
|
+
constructor(agentIds, sessionDir) {
|
|
24
|
+
super(`Session directory conflict: agents "${agentIds[0]}" and "${agentIds[1]}" share the same session directory: "${sessionDir}"`);
|
|
25
|
+
this.agentIds = agentIds;
|
|
26
|
+
this.sessionDir = sessionDir;
|
|
27
|
+
this.name = 'SessionDirConflictError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.SessionDirConflictError = SessionDirConflictError;
|
|
31
|
+
/**
|
|
32
|
+
* ContextIsolationGuard ensures that no two agents share workspace path,
|
|
33
|
+
* session directory, or bot token. Call `validate()` at startup with all agent configs.
|
|
34
|
+
*/
|
|
35
|
+
class ContextIsolationGuard {
|
|
36
|
+
/**
|
|
37
|
+
* Validate all agent configs for isolation conflicts.
|
|
38
|
+
* Throws the first conflict found.
|
|
39
|
+
*/
|
|
40
|
+
validate(agents) {
|
|
41
|
+
const workspaces = new Map(); // workspace → agentId
|
|
42
|
+
const tokens = new Map(); // token → agentId
|
|
43
|
+
const sessionDirs = new Map(); // sessionDir → agentId
|
|
44
|
+
for (const agent of agents) {
|
|
45
|
+
// Workspace check
|
|
46
|
+
const ws = agent.workspace;
|
|
47
|
+
if (workspaces.has(ws)) {
|
|
48
|
+
throw new WorkspaceConflictError([workspaces.get(ws), agent.id], ws);
|
|
49
|
+
}
|
|
50
|
+
workspaces.set(ws, agent.id);
|
|
51
|
+
// Token check — skip if token is empty (agent has no telegram channel configured)
|
|
52
|
+
const token = agent.telegram?.botToken ?? '';
|
|
53
|
+
if (token) {
|
|
54
|
+
if (tokens.has(token)) {
|
|
55
|
+
throw new TokenConflictError([tokens.get(token), agent.id], token);
|
|
56
|
+
}
|
|
57
|
+
tokens.set(token, agent.id);
|
|
58
|
+
}
|
|
59
|
+
// Session dir: derived as <workspace>/../sessions (by convention),
|
|
60
|
+
// but we also check the agent id-based session path if it were the same.
|
|
61
|
+
// The key insight is: if two agents have the same id they'd share session dir.
|
|
62
|
+
// We derive the session dir from workspace parent + "sessions" (per design.md).
|
|
63
|
+
// For safety, treat agentId as the session namespace key.
|
|
64
|
+
// Two agents with identical workspace already caught above.
|
|
65
|
+
// We additionally check if agent.env paths conflict as a proxy for session dir,
|
|
66
|
+
// but session dir is actually determined by the SessionStore base path + agentId.
|
|
67
|
+
// Since session dirs are namespaced by agentId, two agents with different IDs
|
|
68
|
+
// cannot share session dirs. We check explicit sessionDir if provided.
|
|
69
|
+
const sessionDir = agent.sessionDir;
|
|
70
|
+
if (sessionDir) {
|
|
71
|
+
if (sessionDirs.has(sessionDir)) {
|
|
72
|
+
throw new SessionDirConflictError([sessionDirs.get(sessionDir), agent.id], sessionDir);
|
|
73
|
+
}
|
|
74
|
+
sessionDirs.set(sessionDir, agent.id);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.ContextIsolationGuard = ContextIsolationGuard;
|
|
80
|
+
//# sourceMappingURL=context-isolation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-isolation.js","sourceRoot":"","sources":["../../src/agent/context-isolation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { AgentConfig, GatewayConfig, Logger, StreamEvent } from '../types';
|
|
3
|
+
import { type SkillRegistry } from '../skills';
|
|
4
|
+
import { HistoryDB } from '../history/db';
|
|
5
|
+
export declare const MAX_IMAGE_SIZE_BYTES: number;
|
|
6
|
+
export declare class AgentRunner extends EventEmitter {
|
|
7
|
+
private readonly agentConfig;
|
|
8
|
+
private readonly gatewayConfig;
|
|
9
|
+
private readonly logger;
|
|
10
|
+
private stopping;
|
|
11
|
+
private callbackServer;
|
|
12
|
+
private callbackPort;
|
|
13
|
+
private readonly imageSizePerChat;
|
|
14
|
+
private readonly pendingRestarts;
|
|
15
|
+
private statQueue;
|
|
16
|
+
imageSize(chatId: string): number;
|
|
17
|
+
restartPending(chatId: string): boolean;
|
|
18
|
+
private channelFor;
|
|
19
|
+
private readonly sessions;
|
|
20
|
+
private readonly channelSourceMap;
|
|
21
|
+
private receiver;
|
|
22
|
+
private discordReceiver;
|
|
23
|
+
private readonly sessionStore;
|
|
24
|
+
private readonly idleTimeoutMs;
|
|
25
|
+
private readonly maxConcurrent;
|
|
26
|
+
private idleCleanerTimer;
|
|
27
|
+
private readonly pendingApiSessions;
|
|
28
|
+
private readonly pendingImagePaths;
|
|
29
|
+
private skillRegistry;
|
|
30
|
+
private readonly configPath;
|
|
31
|
+
private readonly historyDb;
|
|
32
|
+
private readonly agentsBaseDir;
|
|
33
|
+
private readonly agentDir;
|
|
34
|
+
private cancelCleanup;
|
|
35
|
+
constructor(agentConfig: AgentConfig, gatewayConfig: GatewayConfig, logger?: Logger);
|
|
36
|
+
/**
|
|
37
|
+
* Update the skill registry used for detecting /skill-name commands.
|
|
38
|
+
*/
|
|
39
|
+
setSkillRegistry(registry: SkillRegistry): void;
|
|
40
|
+
getSkillRegistry(): SkillRegistry;
|
|
41
|
+
/**
|
|
42
|
+
* Bind a local HTTP server that receives POST /channel from TelegramReceiver.
|
|
43
|
+
* Each payload is routed to the appropriate SessionProcess by chat_id.
|
|
44
|
+
*/
|
|
45
|
+
private startCallbackServer;
|
|
46
|
+
/**
|
|
47
|
+
* Handle POST /command requests from the receiver process.
|
|
48
|
+
* Supports: get_model, set_model, restart.
|
|
49
|
+
*/
|
|
50
|
+
private handleCommandRequest;
|
|
51
|
+
/**
|
|
52
|
+
* Persist the current model to config.json using atomic write (tmp + rename).
|
|
53
|
+
*/
|
|
54
|
+
private persistModelToConfig;
|
|
55
|
+
private static escapeXmlAttr;
|
|
56
|
+
private resolveMediaPaths;
|
|
57
|
+
private static buildChannelXml;
|
|
58
|
+
private getOrSpawnSession;
|
|
59
|
+
/**
|
|
60
|
+
* Returns true if the message content is a session management command.
|
|
61
|
+
*/
|
|
62
|
+
private isSessionCommand;
|
|
63
|
+
/**
|
|
64
|
+
* Dispatch a session management command to the appropriate handler.
|
|
65
|
+
*/
|
|
66
|
+
private handleSessionCommand;
|
|
67
|
+
/**
|
|
68
|
+
* /sessions — list all sessions for this chat.
|
|
69
|
+
*/
|
|
70
|
+
private handleCommandSessions;
|
|
71
|
+
/**
|
|
72
|
+
* /session — show info about the current active session.
|
|
73
|
+
*/
|
|
74
|
+
private handleCommandSessionInfo;
|
|
75
|
+
/**
|
|
76
|
+
* /new [name] — create a new session and switch to it.
|
|
77
|
+
*/
|
|
78
|
+
private handleCommandNew;
|
|
79
|
+
/**
|
|
80
|
+
* /rename <name> — rename the current session.
|
|
81
|
+
*/
|
|
82
|
+
private handleCommandRename;
|
|
83
|
+
/**
|
|
84
|
+
* /stop — interrupt the in-flight turn for this chat by sending SIGINT to the subprocess.
|
|
85
|
+
* Leaves session history and metadata intact. Queued messages still process afterwards.
|
|
86
|
+
*/
|
|
87
|
+
private handleCommandStop;
|
|
88
|
+
/**
|
|
89
|
+
* /clear — clear history of the current session and restart the process.
|
|
90
|
+
* Also clears the permanent history DB and media files for this chat.
|
|
91
|
+
*/
|
|
92
|
+
private handleCommandClear;
|
|
93
|
+
/**
|
|
94
|
+
* /compact — summarise old history and keep only recent messages.
|
|
95
|
+
*/
|
|
96
|
+
private handleCommandCompact;
|
|
97
|
+
/**
|
|
98
|
+
* Switch the active session for a chat: stop the existing process and update the store.
|
|
99
|
+
* The new process will be lazily spawned on the next incoming message.
|
|
100
|
+
*/
|
|
101
|
+
private switchSession;
|
|
102
|
+
/**
|
|
103
|
+
* Restart the process for a given chatId (stop + remove from map).
|
|
104
|
+
* The process will be lazily re-spawned on the next incoming message.
|
|
105
|
+
*/
|
|
106
|
+
private restartProcess;
|
|
107
|
+
/**
|
|
108
|
+
* Stop all idle session subprocesses so they re-spawn with the latest
|
|
109
|
+
* system prompt on the next incoming message.
|
|
110
|
+
*
|
|
111
|
+
* - "Idle" = no activity for {@link IDLE_THRESHOLD_MS}ms (enough to exclude an in-flight turn).
|
|
112
|
+
* - Busy sessions are left alone; they will be picked up by the idle cleaner
|
|
113
|
+
* (every 5m) or naturally on the next spawn after timeout.
|
|
114
|
+
* - Does NOT stop the receiver; incoming messages keep flowing.
|
|
115
|
+
*
|
|
116
|
+
* Used by the skills hot-reload path so that SKILL.md changes take effect
|
|
117
|
+
* without kicking users out of in-flight turns.
|
|
118
|
+
*/
|
|
119
|
+
restartOrDefer(): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Format a timestamp as a human-readable age string (e.g. "5m ago", "2h ago").
|
|
122
|
+
*/
|
|
123
|
+
private formatAge;
|
|
124
|
+
/**
|
|
125
|
+
* Write an error code to the typing signal directory so the receiver's
|
|
126
|
+
* typing loop can pick it up and notify the user via Telegram.
|
|
127
|
+
* Non-fatal: if the write fails the typing loop will stop via stalled timer.
|
|
128
|
+
*/
|
|
129
|
+
private getTypingDir;
|
|
130
|
+
private writeTypingError;
|
|
131
|
+
private writeTypingDone;
|
|
132
|
+
private triggerSummaryAndRestart;
|
|
133
|
+
private writeAutoForward;
|
|
134
|
+
private startIdleCleaner;
|
|
135
|
+
start(): Promise<void>;
|
|
136
|
+
startDiscordReceiver(): void;
|
|
137
|
+
stop(): Promise<void>;
|
|
138
|
+
private _startCleanupScheduler;
|
|
139
|
+
restart(): Promise<void>;
|
|
140
|
+
isRunning(): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Send a message to an API session and wait for the response.
|
|
143
|
+
*
|
|
144
|
+
* - Spawns a new SessionProcess (source='api') if none exists for sessionId.
|
|
145
|
+
* - Rejects with code 'CONFLICT' if a prior request is still in-flight for this session.
|
|
146
|
+
* - Rejects with code 'TIMEOUT' if Claude does not respond within timeoutMs.
|
|
147
|
+
* - Appends user message and assistant reply to SessionStore for history persistence.
|
|
148
|
+
*/
|
|
149
|
+
sendApiMessage(sessionId: string, chatId: string, message: string, opts: {
|
|
150
|
+
timeoutMs: number;
|
|
151
|
+
allowTools?: boolean;
|
|
152
|
+
mediaFiles?: string[];
|
|
153
|
+
}): Promise<string>;
|
|
154
|
+
/**
|
|
155
|
+
* Send a message to an API session and stream back events via callbacks.
|
|
156
|
+
*
|
|
157
|
+
* Returns a cleanup function that removes all listeners and frees the session slot.
|
|
158
|
+
* The caller MUST invoke cleanup on client disconnect or when done.
|
|
159
|
+
*/
|
|
160
|
+
sendApiMessageStream(sessionId: string, chatId: string, message: string, callbacks: {
|
|
161
|
+
onChunk: (event: StreamEvent) => void;
|
|
162
|
+
onDone: (fullText: string) => void;
|
|
163
|
+
onError: (err: Error) => void;
|
|
164
|
+
}, opts: {
|
|
165
|
+
timeoutMs: number;
|
|
166
|
+
allowTools?: boolean;
|
|
167
|
+
mediaFiles?: string[];
|
|
168
|
+
}): Promise<() => void>;
|
|
169
|
+
/**
|
|
170
|
+
* Check if a session has a pending API request (for preflight conflict check).
|
|
171
|
+
*/
|
|
172
|
+
hasActiveApiSession(sessionId: string): boolean;
|
|
173
|
+
getAgentsBaseDir(): string;
|
|
174
|
+
getAgentDir(): string;
|
|
175
|
+
getHistoryDb(): HistoryDB;
|
|
176
|
+
getAllSessionNames(): Promise<Map<string, string>>;
|
|
177
|
+
listSessionsForChat(chatId: string, channel: 'telegram' | 'discord'): Promise<import('../types').SessionIndex>;
|
|
178
|
+
executeApiCommand(sessionId: string, chatId: string, command: string): Promise<Record<string, unknown>>;
|
|
179
|
+
setModel(newModel: string): Promise<void>;
|
|
180
|
+
listApiSessions(chatId: string): Promise<import('../types').SessionIndex>;
|
|
181
|
+
createApiSession(chatId: string, prompt?: string, name?: string): Promise<import('../types').SessionMeta>;
|
|
182
|
+
getApiSessionInfo(chatId: string, sessionId: string): Promise<Record<string, unknown> | null>;
|
|
183
|
+
renameApiSession(chatId: string, sessionId: string, sessionName: string): Promise<void>;
|
|
184
|
+
deleteApiSession(chatId: string, sessionId: string): Promise<void>;
|
|
185
|
+
/**
|
|
186
|
+
* Send a message into an existing channel session (cross-channel continuation from UI).
|
|
187
|
+
* The session process receives full history context from the session JSON (Layer 1).
|
|
188
|
+
* The reply is streamed back via SSE callbacks and persisted to history DB.
|
|
189
|
+
*/
|
|
190
|
+
sendMessageToSession(rawChatId: string, channel: 'telegram' | 'discord', sessionId: string, message: string, senderName: string | undefined, callbacks: {
|
|
191
|
+
onChunk: (event: StreamEvent) => void;
|
|
192
|
+
onDone: (fullText: string) => void;
|
|
193
|
+
onError: (err: Error) => void;
|
|
194
|
+
}, opts: {
|
|
195
|
+
timeoutMs: number;
|
|
196
|
+
}): Promise<() => void>;
|
|
197
|
+
/**
|
|
198
|
+
* Expose the callback server port for integration tests that need to simulate
|
|
199
|
+
* incoming Telegram messages by POSTing directly to the channel endpoint.
|
|
200
|
+
*/
|
|
201
|
+
getCallbackPort(): number;
|
|
202
|
+
/**
|
|
203
|
+
* Send a message to all active sessions.
|
|
204
|
+
* Used for heartbeat/cron tasks delivered out-of-band.
|
|
205
|
+
*
|
|
206
|
+
* If no Telegram sessions are active, a transient `__heartbeat__` API session is
|
|
207
|
+
* spawned so that CronScheduler tasks can always run regardless of active user sessions.
|
|
208
|
+
*/
|
|
209
|
+
sendMessage(message: string): void;
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/agent/runner.ts"],"names":[],"mappings":"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"}
|