@luckydraw/cumulus 0.27.41 → 0.28.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/dist/gateway/adapters/webchat.d.ts +5 -7
- package/dist/gateway/adapters/webchat.d.ts.map +1 -1
- package/dist/gateway/adapters/webchat.js +204 -57
- package/dist/gateway/adapters/webchat.js.map +1 -1
- package/dist/gateway/config.d.ts +48 -0
- package/dist/gateway/config.d.ts.map +1 -1
- package/dist/gateway/config.js +90 -0
- package/dist/gateway/config.js.map +1 -1
- package/dist/gateway/daemon.d.ts.map +1 -1
- package/dist/gateway/daemon.js +268 -27
- package/dist/gateway/daemon.js.map +1 -1
- package/dist/gateway/gateway-agents-mcp.js +570 -31
- package/dist/gateway/gateway-agents-mcp.js.map +1 -1
- package/dist/gateway/hooks.d.ts +101 -0
- package/dist/gateway/hooks.d.ts.map +1 -0
- package/dist/gateway/hooks.js +200 -0
- package/dist/gateway/hooks.js.map +1 -0
- package/dist/gateway/scheduler.d.ts +50 -0
- package/dist/gateway/scheduler.d.ts.map +1 -0
- package/dist/gateway/scheduler.js +263 -0
- package/dist/gateway/scheduler.js.map +1 -0
- package/dist/gateway/server.d.ts +16 -1
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/gateway/server.js +451 -22
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/static/blex.min.js +74 -17
- package/dist/gateway/static/chat.html +1 -4
- package/dist/gateway/static/dashboard.html +151 -0
- package/dist/gateway/static/dashboard.js +229 -0
- package/dist/gateway/static/widget.js +656 -460
- package/dist/index.d.ts +13 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/agentic-loop.d.ts +124 -0
- package/dist/lib/agentic-loop.d.ts.map +1 -0
- package/dist/lib/agentic-loop.js +338 -0
- package/dist/lib/agentic-loop.js.map +1 -0
- package/dist/lib/config.d.ts +28 -15
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +47 -41
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/gateway.d.ts +34 -3
- package/dist/lib/gateway.d.ts.map +1 -1
- package/dist/lib/gateway.js +584 -37
- package/dist/lib/gateway.js.map +1 -1
- package/dist/lib/huggingface-provider.d.ts +26 -0
- package/dist/lib/huggingface-provider.d.ts.map +1 -0
- package/dist/lib/huggingface-provider.js +338 -0
- package/dist/lib/huggingface-provider.js.map +1 -0
- package/dist/lib/provider.d.ts +71 -0
- package/dist/lib/provider.d.ts.map +1 -0
- package/dist/lib/provider.js +90 -0
- package/dist/lib/provider.js.map +1 -0
- package/dist/lib/tools/ask-user-question.d.ts +14 -0
- package/dist/lib/tools/ask-user-question.d.ts.map +1 -0
- package/dist/lib/tools/ask-user-question.js +74 -0
- package/dist/lib/tools/ask-user-question.js.map +1 -0
- package/dist/lib/tools/bash.d.ts +6 -0
- package/dist/lib/tools/bash.d.ts.map +1 -0
- package/dist/lib/tools/bash.js +85 -0
- package/dist/lib/tools/bash.js.map +1 -0
- package/dist/lib/tools/edit.d.ts +6 -0
- package/dist/lib/tools/edit.d.ts.map +1 -0
- package/dist/lib/tools/edit.js +79 -0
- package/dist/lib/tools/edit.js.map +1 -0
- package/dist/lib/tools/glob.d.ts +6 -0
- package/dist/lib/tools/glob.d.ts.map +1 -0
- package/dist/lib/tools/glob.js +91 -0
- package/dist/lib/tools/glob.js.map +1 -0
- package/dist/lib/tools/grep.d.ts +6 -0
- package/dist/lib/tools/grep.d.ts.map +1 -0
- package/dist/lib/tools/grep.js +110 -0
- package/dist/lib/tools/grep.js.map +1 -0
- package/dist/lib/tools/index.d.ts +29 -0
- package/dist/lib/tools/index.d.ts.map +1 -0
- package/dist/lib/tools/index.js +52 -0
- package/dist/lib/tools/index.js.map +1 -0
- package/dist/lib/tools/read.d.ts +6 -0
- package/dist/lib/tools/read.d.ts.map +1 -0
- package/dist/lib/tools/read.js +80 -0
- package/dist/lib/tools/read.js.map +1 -0
- package/dist/lib/tools/tool-search.d.ts +30 -0
- package/dist/lib/tools/tool-search.d.ts.map +1 -0
- package/dist/lib/tools/tool-search.js +108 -0
- package/dist/lib/tools/tool-search.js.map +1 -0
- package/dist/lib/tools/web-fetch.d.ts +9 -0
- package/dist/lib/tools/web-fetch.d.ts.map +1 -0
- package/dist/lib/tools/web-fetch.js +114 -0
- package/dist/lib/tools/web-fetch.js.map +1 -0
- package/dist/lib/tools/web-search.d.ts +12 -0
- package/dist/lib/tools/web-search.d.ts.map +1 -0
- package/dist/lib/tools/web-search.js +89 -0
- package/dist/lib/tools/web-search.js.map +1 -0
- package/dist/lib/tools/write.d.ts +6 -0
- package/dist/lib/tools/write.d.ts.map +1 -0
- package/dist/lib/tools/write.js +44 -0
- package/dist/lib/tools/write.js.map +1 -0
- package/package.json +3 -2
package/dist/gateway/config.d.ts
CHANGED
|
@@ -20,6 +20,31 @@ export interface VapidConfig {
|
|
|
20
20
|
privateKey: string;
|
|
21
21
|
email: string;
|
|
22
22
|
}
|
|
23
|
+
export interface HooksConfig {
|
|
24
|
+
email?: {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
provider: 'resend';
|
|
27
|
+
signingSecret?: string;
|
|
28
|
+
threadMapping: string;
|
|
29
|
+
defaultTemplate?: string;
|
|
30
|
+
};
|
|
31
|
+
form?: {
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
threadMapping: string;
|
|
34
|
+
defaultTemplate?: string;
|
|
35
|
+
};
|
|
36
|
+
webhooks?: Record<string, {
|
|
37
|
+
thread: string;
|
|
38
|
+
template?: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
export interface ResendConfig {
|
|
42
|
+
apiKey: string;
|
|
43
|
+
defaultFrom: string;
|
|
44
|
+
replyTo?: string;
|
|
45
|
+
/** Max emails per hour per thread (default: 10) */
|
|
46
|
+
rateLimit?: number;
|
|
47
|
+
}
|
|
23
48
|
export interface GatewayConfig {
|
|
24
49
|
apiKeys: string[];
|
|
25
50
|
port: number;
|
|
@@ -39,6 +64,29 @@ export interface GatewayConfig {
|
|
|
39
64
|
defaultMode?: 'local' | 'remote';
|
|
40
65
|
/** Optional: VAPID config for web push notifications */
|
|
41
66
|
vapid?: VapidConfig;
|
|
67
|
+
/** Optional: inbound webhook configurations */
|
|
68
|
+
hooks?: HooksConfig;
|
|
69
|
+
/** Optional: Resend email API configuration */
|
|
70
|
+
resend?: ResendConfig;
|
|
71
|
+
/** Optional: HuggingFace API key for non-Claude models */
|
|
72
|
+
hfApiKey?: string;
|
|
73
|
+
/** Optional: available models for per-thread selection */
|
|
74
|
+
models?: ModelEntry[];
|
|
75
|
+
/** Optional: default model ID for new threads (e.g., "claude" or "zai-org/GLM-5") */
|
|
76
|
+
model?: string;
|
|
77
|
+
}
|
|
78
|
+
/** Model entry for per-thread selection */
|
|
79
|
+
export interface ModelEntry {
|
|
80
|
+
/** Model ID — "claude" for CLI, or HuggingFace model ID like "zai-org/GLM-5" */
|
|
81
|
+
id: string;
|
|
82
|
+
/** Display label for the widget dropdown */
|
|
83
|
+
label: string;
|
|
84
|
+
/** Provider — "claude-cli" or "huggingface" */
|
|
85
|
+
provider: 'claude-cli' | 'huggingface';
|
|
86
|
+
/** Whether this is the default model */
|
|
87
|
+
default?: boolean;
|
|
88
|
+
/** Context window size in tokens (for HuggingFace models) */
|
|
89
|
+
contextWindow?: number;
|
|
42
90
|
}
|
|
43
91
|
/**
|
|
44
92
|
* Load gateway config from ~/.cumulus/gateway.config.json.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACjC,wDAAwD;IACxD,KAAK,CAAC,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"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"}
|
package/dist/gateway/config.js
CHANGED
|
@@ -52,8 +52,44 @@ function validateConfig(raw) {
|
|
|
52
52
|
projectRoot: typeof raw.projectRoot === 'string' && raw.projectRoot ? raw.projectRoot : undefined,
|
|
53
53
|
defaultMode: raw.defaultMode === 'local' ? 'local' : undefined,
|
|
54
54
|
vapid: validateVapid(raw.vapid),
|
|
55
|
+
hooks: validateHooks(raw.hooks),
|
|
56
|
+
resend: validateResend(raw.resend),
|
|
57
|
+
hfApiKey: typeof raw.hfApiKey === 'string' && raw.hfApiKey ? raw.hfApiKey : undefined,
|
|
58
|
+
models: validateModels(raw.models),
|
|
59
|
+
model: typeof raw.model === 'string' && raw.model ? raw.model : undefined,
|
|
55
60
|
};
|
|
56
61
|
}
|
|
62
|
+
function validateResend(raw) {
|
|
63
|
+
if (!raw || typeof raw !== 'object')
|
|
64
|
+
return undefined;
|
|
65
|
+
const r = raw;
|
|
66
|
+
if (typeof r.apiKey !== 'string' || !r.apiKey) {
|
|
67
|
+
throw new Error('gateway.config.json: resend.apiKey is required');
|
|
68
|
+
}
|
|
69
|
+
if (typeof r.defaultFrom !== 'string' || !r.defaultFrom) {
|
|
70
|
+
throw new Error('gateway.config.json: resend.defaultFrom is required');
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
apiKey: r.apiKey,
|
|
74
|
+
defaultFrom: r.defaultFrom,
|
|
75
|
+
replyTo: typeof r.replyTo === 'string' ? r.replyTo : undefined,
|
|
76
|
+
rateLimit: typeof r.rateLimit === 'number' ? r.rateLimit : undefined,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function validateModels(raw) {
|
|
80
|
+
if (!raw || !Array.isArray(raw))
|
|
81
|
+
return undefined;
|
|
82
|
+
return raw
|
|
83
|
+
.filter((m) => m && typeof m === 'object')
|
|
84
|
+
.map(m => ({
|
|
85
|
+
id: String(m.id || ''),
|
|
86
|
+
label: String(m.label || m.id || ''),
|
|
87
|
+
provider: m.provider === 'huggingface' ? 'huggingface' : 'claude-cli',
|
|
88
|
+
default: m.default === true ? true : undefined,
|
|
89
|
+
contextWindow: typeof m.contextWindow === 'number' ? m.contextWindow : undefined,
|
|
90
|
+
}))
|
|
91
|
+
.filter(m => m.id.length > 0);
|
|
92
|
+
}
|
|
57
93
|
function validateChannels(raw) {
|
|
58
94
|
if (!raw || typeof raw !== 'object')
|
|
59
95
|
return undefined;
|
|
@@ -105,6 +141,60 @@ function validateVapid(raw) {
|
|
|
105
141
|
email: typeof v.email === 'string' ? v.email : 'mailto:noreply@example.com',
|
|
106
142
|
};
|
|
107
143
|
}
|
|
144
|
+
function validateHooks(raw) {
|
|
145
|
+
if (!raw || typeof raw !== 'object')
|
|
146
|
+
return undefined;
|
|
147
|
+
const h = raw;
|
|
148
|
+
const result = {};
|
|
149
|
+
if (h.email && typeof h.email === 'object') {
|
|
150
|
+
const email = h.email;
|
|
151
|
+
if (email.enabled === true) {
|
|
152
|
+
if (typeof email.threadMapping !== 'string' || !email.threadMapping) {
|
|
153
|
+
throw new Error('gateway.config.json: hooks.email.threadMapping is required when enabled');
|
|
154
|
+
}
|
|
155
|
+
result.email = {
|
|
156
|
+
enabled: true,
|
|
157
|
+
provider: 'resend',
|
|
158
|
+
signingSecret: typeof email.signingSecret === 'string' ? email.signingSecret : undefined,
|
|
159
|
+
threadMapping: email.threadMapping,
|
|
160
|
+
defaultTemplate: typeof email.defaultTemplate === 'string' ? email.defaultTemplate : undefined,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (h.form && typeof h.form === 'object') {
|
|
165
|
+
const form = h.form;
|
|
166
|
+
if (form.enabled === true) {
|
|
167
|
+
if (typeof form.threadMapping !== 'string' || !form.threadMapping) {
|
|
168
|
+
throw new Error('gateway.config.json: hooks.form.threadMapping is required when enabled');
|
|
169
|
+
}
|
|
170
|
+
result.form = {
|
|
171
|
+
enabled: true,
|
|
172
|
+
threadMapping: form.threadMapping,
|
|
173
|
+
defaultTemplate: typeof form.defaultTemplate === 'string' ? form.defaultTemplate : undefined,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (h.webhooks && typeof h.webhooks === 'object') {
|
|
178
|
+
const webhooks = h.webhooks;
|
|
179
|
+
const validated = {};
|
|
180
|
+
for (const [name, cfg] of Object.entries(webhooks)) {
|
|
181
|
+
if (cfg && typeof cfg === 'object') {
|
|
182
|
+
const wh = cfg;
|
|
183
|
+
if (typeof wh.thread !== 'string' || !wh.thread) {
|
|
184
|
+
throw new Error(`gateway.config.json: hooks.webhooks.${name}.thread is required`);
|
|
185
|
+
}
|
|
186
|
+
validated[name] = {
|
|
187
|
+
thread: wh.thread,
|
|
188
|
+
template: typeof wh.template === 'string' ? wh.template : undefined,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (Object.keys(validated).length > 0) {
|
|
193
|
+
result.webhooks = validated;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
197
|
+
}
|
|
108
198
|
export function getConfigPath() {
|
|
109
199
|
return CONFIG_PATH;
|
|
110
200
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACxD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/gateway/daemon.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/gateway/daemon.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AA4BH,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAoB,GAAG,IAAI,CAG5D;AAED,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAQ3C;AAED,wBAAgB,aAAa,IAAI,IAAI,CAMpC;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAID,UAAU,UAAU;IAClB,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1D,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAoDpD"}
|
package/dist/gateway/daemon.js
CHANGED
|
@@ -12,11 +12,13 @@
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as os from 'os';
|
|
14
14
|
import * as path from 'path';
|
|
15
|
+
import { drainActiveSubprocesses, getActiveSubprocessCount, getActiveThreadNames, recoverStreamingBuffers, sendMessage, } from '../lib/gateway.js';
|
|
15
16
|
import { createDiscordAdapter } from './adapters/discord.js';
|
|
16
17
|
import { createSlackAdapter } from './adapters/slack.js';
|
|
17
|
-
import { createWebChatAdapter
|
|
18
|
+
import { createWebChatAdapter } from './adapters/webchat.js';
|
|
18
19
|
import { loadGatewayConfig, getConfigPath } from './config.js';
|
|
19
20
|
import { createLogger, getDefaultLogPath } from './logger.js';
|
|
21
|
+
import { createScheduler } from './scheduler.js';
|
|
20
22
|
import { startGatewayServer } from './server.js';
|
|
21
23
|
const CUMULUS_DIR = path.join(os.homedir(), '.cumulus');
|
|
22
24
|
const PID_FILE = path.join(CUMULUS_DIR, 'gateway.pid');
|
|
@@ -178,9 +180,21 @@ async function cmdStart(args) {
|
|
|
178
180
|
sharedMcpPort: config.sharedMcpPort,
|
|
179
181
|
projectRoot: config.projectRoot,
|
|
180
182
|
vapid: config.vapid,
|
|
183
|
+
hooks: config.hooks,
|
|
184
|
+
hfApiKey: config.hfApiKey,
|
|
185
|
+
models: config.models,
|
|
186
|
+
model: config.model,
|
|
181
187
|
gatewayAgentsConfig: {
|
|
182
188
|
apiUrl: `http://127.0.0.1:${port}`,
|
|
183
189
|
apiKey: config.apiKeys[0],
|
|
190
|
+
...(config.resend
|
|
191
|
+
? {
|
|
192
|
+
resendApiKey: config.resend.apiKey,
|
|
193
|
+
resendDefaultFrom: config.resend.defaultFrom,
|
|
194
|
+
resendReplyTo: config.resend.replyTo,
|
|
195
|
+
resendRateLimit: config.resend.rateLimit,
|
|
196
|
+
}
|
|
197
|
+
: {}),
|
|
184
198
|
},
|
|
185
199
|
});
|
|
186
200
|
}
|
|
@@ -250,8 +264,17 @@ async function cmdStart(args) {
|
|
|
250
264
|
gatewayAgentsConfig: {
|
|
251
265
|
apiUrl: `http://127.0.0.1:${port}`,
|
|
252
266
|
apiKey: config.apiKeys[0],
|
|
267
|
+
...(config.resend
|
|
268
|
+
? {
|
|
269
|
+
resendApiKey: config.resend.apiKey,
|
|
270
|
+
resendDefaultFrom: config.resend.defaultFrom,
|
|
271
|
+
resendReplyTo: config.resend.replyTo,
|
|
272
|
+
resendRateLimit: config.resend.rateLimit,
|
|
273
|
+
}
|
|
274
|
+
: {}),
|
|
253
275
|
},
|
|
254
276
|
executorRegistry: handle.executorRegistry,
|
|
277
|
+
hfApiKey: config.hfApiKey,
|
|
255
278
|
},
|
|
256
279
|
});
|
|
257
280
|
// Wire broadcast so agent inject messages reach connected web clients
|
|
@@ -265,6 +288,39 @@ async function cmdStart(args) {
|
|
|
265
288
|
if (foreground)
|
|
266
289
|
console.error(`[Gateway] WebChat adapter failed: ${err}`);
|
|
267
290
|
}
|
|
291
|
+
// Start scheduler engine (scans thread configs for schedules, manages timers)
|
|
292
|
+
let schedulerHandle;
|
|
293
|
+
try {
|
|
294
|
+
schedulerHandle = createScheduler({
|
|
295
|
+
pipelineOpts: {
|
|
296
|
+
claudePath: config.claudePath,
|
|
297
|
+
sharedMcpPort: config.sharedMcpPort,
|
|
298
|
+
projectRoot: config.projectRoot,
|
|
299
|
+
gatewayAgentsConfig: {
|
|
300
|
+
apiUrl: `http://127.0.0.1:${port}`,
|
|
301
|
+
apiKey: config.apiKeys[0],
|
|
302
|
+
...(config.resend
|
|
303
|
+
? {
|
|
304
|
+
resendApiKey: config.resend.apiKey,
|
|
305
|
+
resendDefaultFrom: config.resend.defaultFrom,
|
|
306
|
+
resendReplyTo: config.resend.replyTo,
|
|
307
|
+
resendRateLimit: config.resend.rateLimit,
|
|
308
|
+
}
|
|
309
|
+
: {}),
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
log: (msg, data) => logger.info(`[Scheduler] ${msg}`, data),
|
|
313
|
+
});
|
|
314
|
+
handle.setScheduler(schedulerHandle);
|
|
315
|
+
logger.info('Scheduler started');
|
|
316
|
+
if (foreground)
|
|
317
|
+
console.log('[Gateway] Scheduler started');
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
logger.error('Failed to start scheduler', { error: String(err) });
|
|
321
|
+
if (foreground)
|
|
322
|
+
console.error(`[Gateway] Scheduler failed: ${err}`);
|
|
323
|
+
}
|
|
268
324
|
const activeChannels = [slackAdapter && 'slack', discordAdapter && 'discord', webChatAdapter && 'webchat']
|
|
269
325
|
.filter(Boolean)
|
|
270
326
|
.join(', ') || 'none';
|
|
@@ -282,17 +338,23 @@ async function cmdStart(args) {
|
|
|
282
338
|
if (shuttingDown)
|
|
283
339
|
return;
|
|
284
340
|
shuttingDown = true;
|
|
285
|
-
|
|
341
|
+
const activeCount = getActiveSubprocessCount();
|
|
342
|
+
logger.info('Shutdown initiated', { signal, activeSubprocesses: activeCount });
|
|
286
343
|
if (foreground)
|
|
287
|
-
console.log(`\n[Gateway] ${signal} received,
|
|
288
|
-
// Stop
|
|
289
|
-
if (
|
|
344
|
+
console.log(`\n[Gateway] ${signal} received, draining ${activeCount} active streams...`);
|
|
345
|
+
// 0. Stop scheduler (no new triggers should fire during shutdown)
|
|
346
|
+
if (schedulerHandle) {
|
|
347
|
+
schedulerHandle.stop();
|
|
348
|
+
logger.info('Scheduler stopped');
|
|
349
|
+
}
|
|
350
|
+
// 1. Stop accepting new messages via channel adapters
|
|
351
|
+
if (slackAdapter) {
|
|
290
352
|
try {
|
|
291
|
-
await
|
|
292
|
-
logger.info('
|
|
353
|
+
await slackAdapter.stop();
|
|
354
|
+
logger.info('Slack adapter stopped');
|
|
293
355
|
}
|
|
294
356
|
catch (err) {
|
|
295
|
-
logger.error('Error stopping
|
|
357
|
+
logger.error('Error stopping Slack adapter', { error: String(err) });
|
|
296
358
|
}
|
|
297
359
|
}
|
|
298
360
|
if (discordAdapter) {
|
|
@@ -304,15 +366,58 @@ async function cmdStart(args) {
|
|
|
304
366
|
logger.error('Error stopping Discord adapter', { error: String(err) });
|
|
305
367
|
}
|
|
306
368
|
}
|
|
307
|
-
|
|
369
|
+
// 2. Wait for active Claude subprocesses to complete (up to 120s)
|
|
370
|
+
if (getActiveSubprocessCount() > 0) {
|
|
371
|
+
logger.info('Waiting for active subprocesses to complete...', {
|
|
372
|
+
count: getActiveSubprocessCount(),
|
|
373
|
+
});
|
|
374
|
+
if (foreground)
|
|
375
|
+
console.log(`[Gateway] Waiting for ${getActiveSubprocessCount()} active streams...`);
|
|
376
|
+
const drained = await drainActiveSubprocesses(120_000);
|
|
377
|
+
logger.info('Subprocess drain complete', { drained, remaining: getActiveSubprocessCount() });
|
|
378
|
+
if (foreground)
|
|
379
|
+
console.log(`[Gateway] Drained ${drained} streams, ${getActiveSubprocessCount()} remaining`);
|
|
380
|
+
}
|
|
381
|
+
// 2b. Record interrupted threads for auto-resume on next startup
|
|
382
|
+
const interruptedThreads = getActiveThreadNames();
|
|
383
|
+
const activeThreadsPath = path.join(CUMULUS_DIR, 'active-threads.json');
|
|
384
|
+
if (interruptedThreads.length > 0) {
|
|
385
|
+
const record = interruptedThreads.map(name => ({
|
|
386
|
+
threadName: name,
|
|
387
|
+
timestamp: new Date().toISOString(),
|
|
388
|
+
}));
|
|
308
389
|
try {
|
|
309
|
-
|
|
310
|
-
logger.info('
|
|
390
|
+
fs.writeFileSync(activeThreadsPath, JSON.stringify(record, null, 2));
|
|
391
|
+
logger.info('Recorded interrupted threads for auto-resume', {
|
|
392
|
+
threads: interruptedThreads,
|
|
393
|
+
});
|
|
394
|
+
if (foreground)
|
|
395
|
+
console.log(`[Gateway] Recorded ${interruptedThreads.length} interrupted thread(s) for auto-resume`);
|
|
311
396
|
}
|
|
312
397
|
catch (err) {
|
|
313
|
-
logger.error('
|
|
398
|
+
logger.error('Failed to write active-threads.json', { error: String(err) });
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
// Clean up stale file if no interrupted threads
|
|
403
|
+
try {
|
|
404
|
+
fs.unlinkSync(activeThreadsPath);
|
|
405
|
+
}
|
|
406
|
+
catch {
|
|
407
|
+
// File didn't exist — fine
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
// 3. Stop webchat adapter (closes WebSocket connections)
|
|
411
|
+
if (webChatAdapter) {
|
|
412
|
+
try {
|
|
413
|
+
await webChatAdapter.stop();
|
|
414
|
+
logger.info('WebChat adapter stopped');
|
|
415
|
+
}
|
|
416
|
+
catch (err) {
|
|
417
|
+
logger.error('Error stopping WebChat adapter', { error: String(err) });
|
|
314
418
|
}
|
|
315
419
|
}
|
|
420
|
+
// 4. Close HTTP server
|
|
316
421
|
try {
|
|
317
422
|
await handle.close();
|
|
318
423
|
logger.info('Server closed');
|
|
@@ -320,8 +425,6 @@ async function cmdStart(args) {
|
|
|
320
425
|
catch (err) {
|
|
321
426
|
logger.error('Error during shutdown', { error: String(err) });
|
|
322
427
|
}
|
|
323
|
-
// Wait for in-flight messages to persist before exiting
|
|
324
|
-
await drainInflightMessages(30000);
|
|
325
428
|
removePidFile();
|
|
326
429
|
logger.info('Gateway stopped');
|
|
327
430
|
logger.close();
|
|
@@ -329,25 +432,163 @@ async function cmdStart(args) {
|
|
|
329
432
|
};
|
|
330
433
|
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
331
434
|
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
332
|
-
// SIGHUP =
|
|
435
|
+
// SIGHUP = graceful restart (drain active streams, then exit — systemd Restart=always brings it back with fresh code)
|
|
333
436
|
process.on('SIGHUP', async () => {
|
|
334
|
-
|
|
437
|
+
const activeCount = getActiveSubprocessCount();
|
|
438
|
+
logger.info('SIGHUP received — graceful restart', { activeSubprocesses: activeCount });
|
|
335
439
|
if (foreground)
|
|
336
|
-
console.log(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
handle.updateApiKeys?.(newConfig.apiKeys);
|
|
341
|
-
logger.info('Config reloaded', { apiKeys: newConfig.apiKeys.length });
|
|
440
|
+
console.log(`\n[Gateway] SIGHUP received — graceful restart (${activeCount} active streams)`);
|
|
441
|
+
if (activeCount === 0) {
|
|
442
|
+
// No active streams — exit immediately, systemd restarts with fresh code
|
|
443
|
+
logger.info('No active streams, exiting for restart');
|
|
342
444
|
if (foreground)
|
|
343
|
-
console.log(
|
|
445
|
+
console.log('[Gateway] No active streams — restarting now');
|
|
446
|
+
removePidFile();
|
|
447
|
+
logger.close();
|
|
448
|
+
process.exit(0);
|
|
449
|
+
return;
|
|
344
450
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
451
|
+
// Active streams exist — drain them first
|
|
452
|
+
logger.info('Waiting for active subprocesses to drain before restart...', {
|
|
453
|
+
count: activeCount,
|
|
454
|
+
});
|
|
455
|
+
if (foreground)
|
|
456
|
+
console.log(`[Gateway] Waiting for ${activeCount} active stream(s) to complete...`);
|
|
457
|
+
const drained = await drainActiveSubprocesses(120_000);
|
|
458
|
+
const remaining = getActiveSubprocessCount();
|
|
459
|
+
logger.info('Drain complete, exiting for restart', { drained, remaining });
|
|
460
|
+
if (foreground)
|
|
461
|
+
console.log(`[Gateway] Drained ${drained} streams (${remaining} remaining) — restarting`);
|
|
462
|
+
// Record any threads that didn't complete for auto-resume
|
|
463
|
+
if (remaining > 0) {
|
|
464
|
+
const interruptedThreads = getActiveThreadNames();
|
|
465
|
+
const activeThreadsPath = path.join(CUMULUS_DIR, 'active-threads.json');
|
|
466
|
+
const record = interruptedThreads.map(name => ({
|
|
467
|
+
threadName: name,
|
|
468
|
+
timestamp: new Date().toISOString(),
|
|
469
|
+
}));
|
|
470
|
+
try {
|
|
471
|
+
fs.writeFileSync(activeThreadsPath, JSON.stringify(record, null, 2));
|
|
472
|
+
logger.info('Recorded interrupted threads for auto-resume', {
|
|
473
|
+
threads: interruptedThreads,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
catch (err) {
|
|
477
|
+
logger.error('Failed to write active-threads.json', { error: String(err) });
|
|
478
|
+
}
|
|
349
479
|
}
|
|
480
|
+
removePidFile();
|
|
481
|
+
logger.close();
|
|
482
|
+
process.exit(0);
|
|
350
483
|
});
|
|
484
|
+
// ─── Recover partial streaming responses from previous crash/restart ────────
|
|
485
|
+
try {
|
|
486
|
+
const recoveredCount = await recoverStreamingBuffers();
|
|
487
|
+
if (recoveredCount > 0) {
|
|
488
|
+
logger.info('Recovered partial streaming responses', { count: recoveredCount });
|
|
489
|
+
if (foreground)
|
|
490
|
+
console.log(`[Gateway] Recovered ${recoveredCount} partial streaming response(s) from disk`);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
catch (err) {
|
|
494
|
+
logger.error('Failed to recover streaming buffers', { error: String(err) });
|
|
495
|
+
// Non-fatal — gateway continues
|
|
496
|
+
}
|
|
497
|
+
// ─── Auto-resume interrupted threads from previous shutdown ────────
|
|
498
|
+
const resumedThreadNames = new Set(); // tracks threads that got full resume messages
|
|
499
|
+
const activeThreadsPath = path.join(CUMULUS_DIR, 'active-threads.json');
|
|
500
|
+
try {
|
|
501
|
+
if (fs.existsSync(activeThreadsPath)) {
|
|
502
|
+
const raw = JSON.parse(fs.readFileSync(activeThreadsPath, 'utf-8'));
|
|
503
|
+
const threads = Array.isArray(raw)
|
|
504
|
+
? raw
|
|
505
|
+
: [];
|
|
506
|
+
if (threads.length > 0) {
|
|
507
|
+
logger.info('Found interrupted threads from previous shutdown', {
|
|
508
|
+
count: threads.length,
|
|
509
|
+
threads: threads.map(t => t.threadName),
|
|
510
|
+
});
|
|
511
|
+
if (foreground)
|
|
512
|
+
console.log(`[Gateway] Resuming ${threads.length} interrupted thread(s): ${threads.map(t => t.threadName).join(', ')}`);
|
|
513
|
+
// Inject resume message into each interrupted thread (fire-and-forget)
|
|
514
|
+
for (const { threadName, timestamp } of threads) {
|
|
515
|
+
resumedThreadNames.add(threadName);
|
|
516
|
+
const resumeMsg = `[System] Gateway restarted at ${new Date().toISOString()}. ` +
|
|
517
|
+
`Your previous response was interrupted mid-stream (at ${timestamp}). ` +
|
|
518
|
+
`Please resume where you left off.`;
|
|
519
|
+
sendMessage({
|
|
520
|
+
threadName,
|
|
521
|
+
message: resumeMsg,
|
|
522
|
+
claudePath: config.claudePath,
|
|
523
|
+
sharedMcpPort: config.sharedMcpPort,
|
|
524
|
+
projectRoot: config.projectRoot,
|
|
525
|
+
hfApiKey: config.hfApiKey,
|
|
526
|
+
gatewayAgentsConfig: {
|
|
527
|
+
apiUrl: `http://127.0.0.1:${port}`,
|
|
528
|
+
apiKey: config.apiKeys[0],
|
|
529
|
+
},
|
|
530
|
+
})
|
|
531
|
+
.then(result => {
|
|
532
|
+
logger.info('Auto-resume completed', {
|
|
533
|
+
threadName,
|
|
534
|
+
responseChars: result?.response?.length ?? 0,
|
|
535
|
+
});
|
|
536
|
+
})
|
|
537
|
+
.catch(err => {
|
|
538
|
+
logger.error('Auto-resume failed', {
|
|
539
|
+
threadName,
|
|
540
|
+
error: String(err),
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
// Clean up the file regardless of outcome
|
|
546
|
+
fs.unlinkSync(activeThreadsPath);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
catch (err) {
|
|
550
|
+
logger.error('Failed to process active-threads.json', { error: String(err) });
|
|
551
|
+
// Non-fatal — gateway continues without resume
|
|
552
|
+
}
|
|
553
|
+
// Delayed restart notification for threads that reconnect but weren't actively streaming.
|
|
554
|
+
// Covers both cases: active-threads.json existed (some threads already got resume) or didn't.
|
|
555
|
+
setTimeout(() => {
|
|
556
|
+
if (!webChatAdapter)
|
|
557
|
+
return;
|
|
558
|
+
const connectedThreads = webChatAdapter.getConnectedThreadNames();
|
|
559
|
+
if (connectedThreads.length === 0)
|
|
560
|
+
return;
|
|
561
|
+
const restartTimestamp = new Date().toISOString();
|
|
562
|
+
let notified = 0;
|
|
563
|
+
for (const threadName of connectedThreads) {
|
|
564
|
+
// Skip threads that already got a full sendMessage resume from active-threads.json
|
|
565
|
+
if (resumedThreadNames.has(threadName))
|
|
566
|
+
continue;
|
|
567
|
+
const notifyMsg = `[System] Gateway restarted at ${restartTimestamp}. ` +
|
|
568
|
+
`If your previous response was interrupted, please let me know and I'll resume.`;
|
|
569
|
+
sendMessage({
|
|
570
|
+
threadName,
|
|
571
|
+
message: notifyMsg,
|
|
572
|
+
claudePath: config.claudePath,
|
|
573
|
+
sharedMcpPort: config.sharedMcpPort,
|
|
574
|
+
projectRoot: config.projectRoot,
|
|
575
|
+
hfApiKey: config.hfApiKey,
|
|
576
|
+
gatewayAgentsConfig: {
|
|
577
|
+
apiUrl: `http://127.0.0.1:${port}`,
|
|
578
|
+
apiKey: config.apiKeys[0],
|
|
579
|
+
},
|
|
580
|
+
}).catch(err => {
|
|
581
|
+
logger.error('Restart notification failed', { threadName, error: String(err) });
|
|
582
|
+
});
|
|
583
|
+
notified++;
|
|
584
|
+
}
|
|
585
|
+
if (notified > 0) {
|
|
586
|
+
logger.info('Sent restart notifications to reconnected threads', {
|
|
587
|
+
count: notified,
|
|
588
|
+
threads: connectedThreads.filter(t => !resumedThreadNames.has(t)),
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}, 5000);
|
|
351
592
|
}
|
|
352
593
|
function cmdStop() {
|
|
353
594
|
const pid = readPidFile();
|