@0xmaxma/claude-gateway 1.8.2 → 1.8.3
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 +7 -2
- package/config.template.json +4 -0
- package/dist/agent/dreaming/config.d.ts +6 -0
- package/dist/agent/dreaming/config.d.ts.map +1 -1
- package/dist/agent/dreaming/config.js +17 -24
- package/dist/agent/dreaming/config.js.map +1 -1
- package/dist/agent/knowledge/config.d.ts.map +1 -1
- package/dist/agent/knowledge/config.js +7 -13
- package/dist/agent/knowledge/config.js.map +1 -1
- package/dist/agent/runner.d.ts +87 -13
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +342 -117
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/turn-stream.d.ts +202 -0
- package/dist/agent/turn-stream.d.ts.map +1 -0
- package/dist/agent/turn-stream.js +322 -0
- package/dist/agent/turn-stream.js.map +1 -0
- package/dist/api/apps-router.d.ts.map +1 -1
- package/dist/api/apps-router.js +14 -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 +2 -3
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/line-webhook-router.d.ts +43 -1
- package/dist/api/line-webhook-router.d.ts.map +1 -1
- package/dist/api/line-webhook-router.js +286 -38
- package/dist/api/line-webhook-router.js.map +1 -1
- package/dist/api/router.d.ts +7 -1
- package/dist/api/router.d.ts.map +1 -1
- package/dist/api/router.js +328 -114
- package/dist/api/router.js.map +1 -1
- package/dist/apps/agent-manager.d.ts.map +1 -1
- package/dist/apps/agent-manager.js +4 -1
- package/dist/apps/agent-manager.js.map +1 -1
- package/dist/apps/installer.d.ts +75 -2
- package/dist/apps/installer.d.ts.map +1 -1
- package/dist/apps/installer.js +198 -13
- package/dist/apps/installer.js.map +1 -1
- package/dist/config/agent-env.d.ts +41 -0
- package/dist/config/agent-env.d.ts.map +1 -0
- package/dist/config/agent-env.js +154 -0
- package/dist/config/agent-env.js.map +1 -0
- package/dist/config/loader.d.ts +33 -2
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +33 -9
- package/dist/config/loader.js.map +1 -1
- package/dist/config/watcher.d.ts +1 -0
- package/dist/config/watcher.d.ts.map +1 -1
- package/dist/config/watcher.js +17 -1
- package/dist/config/watcher.js.map +1 -1
- package/dist/index.js +24 -51
- package/dist/index.js.map +1 -1
- package/dist/load-dotenv.d.ts +17 -0
- package/dist/load-dotenv.d.ts.map +1 -1
- package/dist/load-dotenv.js +32 -9
- package/dist/load-dotenv.js.map +1 -1
- package/dist/session/store.d.ts +9 -0
- package/dist/session/store.d.ts.map +1 -1
- package/dist/session/store.js +12 -0
- package/dist/session/store.js.map +1 -1
- package/dist/shell/bypass-dialog.d.ts +142 -0
- package/dist/shell/bypass-dialog.d.ts.map +1 -0
- package/dist/shell/bypass-dialog.js +207 -0
- package/dist/shell/bypass-dialog.js.map +1 -0
- package/dist/shell/claude-pty-shell.js +42 -3
- package/dist/shell/claude-pty-shell.js.map +1 -1
- package/dist/shell/screen.d.ts +7 -0
- package/dist/shell/screen.d.ts.map +1 -1
- package/dist/shell/screen.js +10 -1
- package/dist/shell/screen.js.map +1 -1
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/config-num.d.ts +22 -0
- package/dist/utils/config-num.d.ts.map +1 -0
- package/dist/utils/config-num.js +34 -0
- package/dist/utils/config-num.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.agentsDirForConfig = agentsDirForConfig;
|
|
37
|
+
exports.loadAgentEnvFiles = loadAgentEnvFiles;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const load_dotenv_1 = require("../load-dotenv");
|
|
42
|
+
/**
|
|
43
|
+
* Per-agent `.env` loading.
|
|
44
|
+
*
|
|
45
|
+
* Agent secrets (bot tokens above all) live in
|
|
46
|
+
* `~/.claude-gateway/agents/<id>/.env` and are referenced from `config.json`
|
|
47
|
+
* as `${VAR}` placeholders. `loadConfig()` resolves those placeholders from
|
|
48
|
+
* `process.env` alone, so the `.env` files must be folded into `process.env`
|
|
49
|
+
* *before* every config load — not just the one at startup.
|
|
50
|
+
*
|
|
51
|
+
* Issue #427: `agent_create` writes a new `agents/<id>/.env` and a `${VAR}`
|
|
52
|
+
* placeholder into `config.json` while the gateway is already running. Without
|
|
53
|
+
* a refresh on reload, that variable is never in `process.env`, the agent is
|
|
54
|
+
* silently dropped from the reloaded snapshot, and `agent.added` never fires —
|
|
55
|
+
* so the handler that *would* have loaded the `.env` is itself unreachable.
|
|
56
|
+
*
|
|
57
|
+
* The same one-way copy makes `process.env` a cache that outlives the file it
|
|
58
|
+
* came from: once a token is in there, a rotated value on disk cannot displace
|
|
59
|
+
* it. That is why this module tracks which variables it injected — see
|
|
60
|
+
* `injected` below.
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* The gateway's agents directory — the sibling `agents/` of `config.json`,
|
|
64
|
+
* which is where per-agent workspaces and their `.env` files live.
|
|
65
|
+
*
|
|
66
|
+
* Falls back to `~/.claude-gateway/agents` when there is no config path: the
|
|
67
|
+
* API routers serve requests whose `configPath` may be unset, and the apps
|
|
68
|
+
* agent manager has no config path at all.
|
|
69
|
+
*/
|
|
70
|
+
function agentsDirForConfig(configPath) {
|
|
71
|
+
return configPath
|
|
72
|
+
? path.join(path.dirname(configPath), 'agents')
|
|
73
|
+
: path.join(os.homedir(), '.claude-gateway', 'agents');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Variables this module injected, and the file each one came from.
|
|
77
|
+
*
|
|
78
|
+
* `process.env` is the only thing `loadConfig()` interpolates from, and it is
|
|
79
|
+
* process-lifetime state — so without this ledger there is no way to tell a
|
|
80
|
+
* value the *operator* exported (which must never be clobbered) from one we
|
|
81
|
+
* ourselves copied out of a `.env` on an earlier reload (which is just a stale
|
|
82
|
+
* cache of a file that may since have changed). Both look identical in
|
|
83
|
+
* `process.env`.
|
|
84
|
+
*/
|
|
85
|
+
const injected = new Map();
|
|
86
|
+
/**
|
|
87
|
+
* Fold a single agent's `.env` file into `process.env`.
|
|
88
|
+
*
|
|
89
|
+
* A variable the process already had — exported by the operator, or provided
|
|
90
|
+
* by a *different* agent's `.env` — always wins; the file never clobbers it.
|
|
91
|
+
* A variable this module injected from *this* file is refreshed when the file
|
|
92
|
+
* changes, so a rotated token takes effect on reload instead of the process
|
|
93
|
+
* serving the revoked one until it is restarted.
|
|
94
|
+
*
|
|
95
|
+
* The `value === current` check is what keeps those two cases apart after the
|
|
96
|
+
* first load: if anything else has since assigned to the variable, the ledger
|
|
97
|
+
* no longer matches, ownership is dropped, and the file goes back to losing.
|
|
98
|
+
* Re-loading an unchanged file remains a no-op.
|
|
99
|
+
*
|
|
100
|
+
* Line syntax is `parseDotenv`'s, shared with `~/.claude-gateway/.env`, so a
|
|
101
|
+
* quoted token means the same thing in both places.
|
|
102
|
+
*/
|
|
103
|
+
function loadAgentEnvFile(envFile) {
|
|
104
|
+
for (const { key, value } of (0, load_dotenv_1.parseDotenv)(fs.readFileSync(envFile, 'utf8'))) {
|
|
105
|
+
const current = process.env[key];
|
|
106
|
+
if (current === undefined) {
|
|
107
|
+
process.env[key] = value;
|
|
108
|
+
injected.set(key, { file: envFile, value });
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const owned = injected.get(key);
|
|
112
|
+
if (owned && owned.file === envFile && owned.value === current) {
|
|
113
|
+
if (value !== current) {
|
|
114
|
+
process.env[key] = value;
|
|
115
|
+
injected.set(key, { file: envFile, value });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Fold every `agents/<id>/.env` under `gatewayAgentsDir` into `process.env`.
|
|
122
|
+
*
|
|
123
|
+
* Safe to run before each config load: it picks up agents that appeared since
|
|
124
|
+
* the last one, and re-reading an unchanged file changes nothing.
|
|
125
|
+
* A missing directory, an unreadable file, or a `.env` belonging to an agent
|
|
126
|
+
* that is not in the config are all non-fatal: config loading has its own
|
|
127
|
+
* per-agent error handling, and failing here would take the whole gateway down
|
|
128
|
+
* over one bad file.
|
|
129
|
+
*/
|
|
130
|
+
function loadAgentEnvFiles(gatewayAgentsDir) {
|
|
131
|
+
let entries;
|
|
132
|
+
try {
|
|
133
|
+
if (!fs.existsSync(gatewayAgentsDir))
|
|
134
|
+
return;
|
|
135
|
+
entries = fs.readdirSync(gatewayAgentsDir);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
for (const agentId of entries) {
|
|
141
|
+
const envFile = path.join(gatewayAgentsDir, agentId, '.env');
|
|
142
|
+
try {
|
|
143
|
+
if (!fs.existsSync(envFile))
|
|
144
|
+
continue;
|
|
145
|
+
loadAgentEnvFile(envFile);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Unreadable .env (permissions, race with a concurrent write): skip it
|
|
149
|
+
// and let loadConfig() report the resulting unresolvable ${VAR}.
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=agent-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-env.js","sourceRoot":"","sources":["../../src/config/agent-env.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,gDAIC;AA4DD,8CAmBC;AArHD,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAC7B,gDAA6C;AAE7C;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,UAAmB;IACpD,OAAO,UAAU;QACf,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC;QAC/C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2C,CAAC;AAEpE;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,IAAA,yBAAW,EAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QAC3E,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACzB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YAC/D,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACzB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,iBAAiB,CAAC,gBAAwB;IACxD,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC;YAAE,OAAO;QAC7C,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,iEAAiE;YACjE,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GatewayConfig } from '../types';
|
|
1
|
+
import { GatewayConfig, Logger } from '../types';
|
|
2
2
|
export declare class ConfigValidationError extends Error {
|
|
3
3
|
constructor(message: string);
|
|
4
4
|
}
|
|
@@ -6,11 +6,42 @@ export declare class DuplicateAgentIdError extends Error {
|
|
|
6
6
|
constructor(id: string);
|
|
7
7
|
}
|
|
8
8
|
export declare class MissingEnvVarError extends Error {
|
|
9
|
+
/**
|
|
10
|
+
* The unresolved variable, exposed separately so callers can log it as a
|
|
11
|
+
* field instead of scraping it back out of `message`.
|
|
12
|
+
*/
|
|
13
|
+
readonly varName: string;
|
|
9
14
|
constructor(varName: string);
|
|
10
15
|
}
|
|
16
|
+
/** An agent that was dropped from the loaded config rather than started. */
|
|
17
|
+
export interface SkippedAgent {
|
|
18
|
+
/** The agent's id, or `index N` when the entry was too malformed to have one. */
|
|
19
|
+
id: string;
|
|
20
|
+
/** Human-readable cause, e.g. `Missing environment variable: ACME_BOT_TOKEN`. */
|
|
21
|
+
reason: string;
|
|
22
|
+
/** Set only when the agent was dropped because a `${VAR}` did not resolve. */
|
|
23
|
+
missingVar?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface LoadConfigOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Called once per dropped agent. Skipping is deliberately non-fatal (one bad
|
|
28
|
+
* agent must not take the gateway down), which historically made it invisible:
|
|
29
|
+
* the only signal was a `console.warn` that never reaches `logs/gateway.log`.
|
|
30
|
+
* Callers that have a structured logger should pass this so a dropped agent
|
|
31
|
+
* is diagnosable — see issue #427.
|
|
32
|
+
*/
|
|
33
|
+
onSkippedAgent?: (skipped: SkippedAgent) => void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Emit one `SkippedAgent` through a caller's structured logger.
|
|
37
|
+
*
|
|
38
|
+
* Shared by the startup load and every reload so both write the same fields
|
|
39
|
+
* under the same key — `grep "Agent skipped" logs/gateway.log` finds either.
|
|
40
|
+
*/
|
|
41
|
+
export declare function logSkippedAgents(logger: Logger, skipped: readonly SkippedAgent[], message: string): void;
|
|
11
42
|
/**
|
|
12
43
|
* Load and validate config.json from the given path.
|
|
13
44
|
* Interpolates ${VAR} env vars throughout the config.
|
|
14
45
|
*/
|
|
15
|
-
export declare function loadConfig(configPath: string): GatewayConfig;
|
|
46
|
+
export declare function loadConfig(configPath: string, options?: LoadConfigOptions): GatewayConfig;
|
|
16
47
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGjD,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,EAAE,EAAE,MAAM;CAIvB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAK5B;AAuED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,EAAE,MAAM,GACd,IAAI,CAQN;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAwJzF"}
|
package/dist/config/loader.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.MissingEnvVarError = exports.DuplicateAgentIdError = exports.ConfigValidationError = void 0;
|
|
37
|
+
exports.logSkippedAgents = logSkippedAgents;
|
|
37
38
|
exports.loadConfig = loadConfig;
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const public_url_1 = require("./public-url");
|
|
@@ -55,6 +56,7 @@ class MissingEnvVarError extends Error {
|
|
|
55
56
|
constructor(varName) {
|
|
56
57
|
super(`Missing environment variable: ${varName}`);
|
|
57
58
|
this.name = 'MissingEnvVarError';
|
|
59
|
+
this.varName = varName;
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
exports.MissingEnvVarError = MissingEnvVarError;
|
|
@@ -123,11 +125,38 @@ function validateAgent(agent, index) {
|
|
|
123
125
|
}
|
|
124
126
|
return null;
|
|
125
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Emit one `SkippedAgent` through a caller's structured logger.
|
|
130
|
+
*
|
|
131
|
+
* Shared by the startup load and every reload so both write the same fields
|
|
132
|
+
* under the same key — `grep "Agent skipped" logs/gateway.log` finds either.
|
|
133
|
+
*/
|
|
134
|
+
function logSkippedAgents(logger, skipped, message) {
|
|
135
|
+
for (const s of skipped) {
|
|
136
|
+
logger.warn(message, {
|
|
137
|
+
id: s.id,
|
|
138
|
+
reason: s.reason,
|
|
139
|
+
...(s.missingVar ? { missingVar: s.missingVar } : {}),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
126
143
|
/**
|
|
127
144
|
* Load and validate config.json from the given path.
|
|
128
145
|
* Interpolates ${VAR} env vars throughout the config.
|
|
129
146
|
*/
|
|
130
|
-
function loadConfig(configPath) {
|
|
147
|
+
function loadConfig(configPath, options) {
|
|
148
|
+
const skippedAgents = [];
|
|
149
|
+
/**
|
|
150
|
+
* The single place an agent is dropped. Both the console warning and the
|
|
151
|
+
* structured-logger callback go through here on purpose: when they were two
|
|
152
|
+
* parallel statements per call site, a new skip site could easily carry one
|
|
153
|
+
* and not the other — reintroducing exactly the invisible drop of #427.
|
|
154
|
+
*/
|
|
155
|
+
const skipAgent = (id, reason, missingVar) => {
|
|
156
|
+
console.warn(`[gateway] Skipping agent "${id}": ${reason}`);
|
|
157
|
+
skippedAgents.push(id);
|
|
158
|
+
options?.onSkippedAgent?.({ id, reason, ...(missingVar ? { missingVar } : {}) });
|
|
159
|
+
};
|
|
131
160
|
let raw;
|
|
132
161
|
try {
|
|
133
162
|
raw = fs.readFileSync(configPath, 'utf-8');
|
|
@@ -154,19 +183,15 @@ function loadConfig(configPath) {
|
|
|
154
183
|
}
|
|
155
184
|
// Validate each agent before interpolation — skip invalid agents with a warning
|
|
156
185
|
const validAgents = [];
|
|
157
|
-
const skippedAgents = [];
|
|
158
186
|
for (let i = 0; i < config.agents.length; i++) {
|
|
159
187
|
const agent = config.agents[i];
|
|
160
188
|
if (typeof agent !== 'object' || agent === null) {
|
|
161
|
-
|
|
162
|
-
skippedAgents.push(`index ${i}`);
|
|
189
|
+
skipAgent(`index ${i}`, 'Config entry must be an object');
|
|
163
190
|
continue;
|
|
164
191
|
}
|
|
165
192
|
const error = validateAgent(agent, i);
|
|
166
193
|
if (error) {
|
|
167
|
-
|
|
168
|
-
console.warn(`[gateway] Skipping agent "${agentId}": ${error}`);
|
|
169
|
-
skippedAgents.push(String(agentId));
|
|
194
|
+
skipAgent(String(agent.id || `index ${i}`), error);
|
|
170
195
|
continue;
|
|
171
196
|
}
|
|
172
197
|
validAgents.push(agent);
|
|
@@ -230,8 +255,7 @@ function loadConfig(configPath) {
|
|
|
230
255
|
}
|
|
231
256
|
catch (err) {
|
|
232
257
|
if (err instanceof MissingEnvVarError) {
|
|
233
|
-
|
|
234
|
-
skippedAgents.push(String(agent.id));
|
|
258
|
+
skipAgent(String(agent.id), err.message, err.varName);
|
|
235
259
|
continue;
|
|
236
260
|
}
|
|
237
261
|
throw err;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgIA,4CAYC;AAMD,gCAwJC;AA1SD,uCAAyB;AAEzB,6CAAuD;AAEvD,MAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AALD,sDAKC;AAED,MAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,EAAU;QACpB,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AALD,sDAKC;AAED,MAAa,kBAAmB,SAAQ,KAAK;IAO3C,YAAY,OAAe;QACzB,KAAK,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAZD,gDAYC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,OAAe,EAAE,EAAE;QAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,GAAY;IACrC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;YACxE,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,KAA8B,EAAE,KAAa;IAClE,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,kBAAkB,KAAK,iCAAiC,CAAC;IAClE,CAAC;IACD,MAAM,WAAW,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACzE,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC;IACtE,kFAAkF;IAClF,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAmC,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChE,OAAO,UAAU,KAAK,CAAC,EAAE,kCAAkC,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,CAAC,OAAkC,CAAC;QACzD,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC9D,OAAO,UAAU,KAAK,CAAC,EAAE,iCAAiC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACrE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAkC,CAAC;QACzD,IAAI,OAAO,CAAC,kBAAkB,KAAK,SAAS,IAAI,CAAC,OAAO,OAAO,CAAC,kBAAkB,KAAK,QAAQ,IAAI,OAAO,CAAC,kBAAkB,IAAI,CAAC,CAAC,EAAE,CAAC;YACpI,OAAO,UAAU,KAAK,CAAC,EAAE,2CAA2C,CAAC;QACvE,CAAC;QACD,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS,IAAI,CAAC,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ,IAAI,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC,EAAE,CAAC;YACrH,OAAO,UAAU,KAAK,CAAC,EAAE,sCAAsC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAuBD;;;;;GAKG;AACH,SAAgB,gBAAgB,CAC9B,MAAc,EACd,OAAgC,EAChC,OAAe;IAEf,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;YACnB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,UAAU,CAAC,UAAkB,EAAE,OAA2B;IACxE,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC;;;;;OAKG;IACH,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,MAAc,EAAE,UAAmB,EAAQ,EAAE;QAC1E,OAAO,CAAC,IAAI,CAAC,6BAA6B,EAAE,MAAM,MAAM,EAAE,CAAC,CAAC;QAC5D,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC,CAAC;IAEF,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,qBAAqB,CAAC,+BAA+B,UAAU,MAAO,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3G,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,qBAAqB,CAAC,kCAAmC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,qBAAqB,CAAC,8BAA8B,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,MAAM,GAAG,MAAiC,CAAC;IAEjD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,qBAAqB,CAAC,2CAA2C,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,qBAAqB,CAAC,6CAA6C,CAAC,CAAC;IACjF,CAAC;IAED,gFAAgF;IAChF,MAAM,WAAW,GAA8B,EAAE,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAI,MAAM,CAAC,MAAoB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAI,MAAM,CAAC,MAAoB,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,SAAS,CAAC,SAAS,CAAC,EAAE,EAAE,gCAAgC,CAAC,CAAC;YAC1D,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAgC,EAAE,CAAC,CAAC,CAAC;QACjE,IAAI,KAAK,EAAE,CAAC;YACV,SAAS,CAAC,MAAM,CAAE,KAAiC,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;YAChF,SAAS;QACX,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC;IACrD,CAAC;IAED,6CAA6C;IAC7C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,EAAE,GAAG,KAAK,CAAC,EAAY,CAAC;QAC9B,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAChB,MAAM,IAAI,qBAAqB,CAAC,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAkC,CAAC;IAC1D,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAA8B,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,qBAAqB,CAAC,mCAAmC,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAiB,EAAE,CAAC;YACtC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,qBAAqB,CAAC,kDAAkD,CAAC,CAAC;YACtF,CAAC;YACD,MAAM,KAAK,GAAG,CAA4B,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAChD,MAAM,IAAI,qBAAqB,CAAC,iDAAiD,CAAC,CAAC;YACrF,CAAC;YACD,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAa,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,qBAAqB,CAAC,kCAAkC,CAAC,CAAC;YACtE,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAa,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,qBAAqB,CAC7B,YAAY,KAAK,CAAC,GAAG,6DAA6D,CACnF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAA4B,CAAC;IACzF,MAAM,YAAY,GAAG,mBAAmB,CAAC,SAAS,CAAC;IACnD,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;QAC7D,yEAAyE;QACzE,0EAA0E;QAC1E,0EAA0E;QAC1E,mBAAmB,CAAC,SAAS,GAAG,SAAS,CAAC;IAC5C,CAAC;SAAM,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,mBAAmB,GAAG,IAAA,oCAAuB,EAAC,YAAY,CAAC,CAAC;QAClE,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,MAAM,IAAI,qBAAqB,CAC7B,oGAAoG;gBACpG,+EAA+E,CAChF,CAAC;QACJ,CAAC;QACD,mBAAmB,CAAC,SAAS,GAAG,mBAAmB,CAAC;IACtD,CAAC;IAED,0EAA0E;IAC1E,MAAM,kBAAkB,GAAc,EAAE,CAAC;IACzC,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,kBAAkB,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;gBACtC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBACtD,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,gFAAgF;IAChF,iFAAiF;IACjF,6EAA6E;IAC7E,8EAA8E;IAC9E,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,IAAK,MAAM,CAAC,MAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/E,MAAM,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;QACpC,MAAM,aAAa,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;YAC1C,CAAC,CAAC,kCAAkC,OAAO,+IAA+I;YAC1L,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,qBAAqB,CAC7B,wFAAwF,aAAa,EAAE,CACxG,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,aAAa,aAAa,CAAC,MAAM,sBAAsB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,OAAO;QACL,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,mBAAmB;KACZ,CAAC;AACrB,CAAC"}
|
package/dist/config/watcher.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare class ConfigWatcher extends EventEmitter {
|
|
|
17
17
|
on(event: 'channel.removed', listener: (agentId: string, channel: string) => void): this;
|
|
18
18
|
private watchHandle;
|
|
19
19
|
private currentConfig;
|
|
20
|
+
private readonly agentsDir;
|
|
20
21
|
constructor(configPath: string, initialConfig: GatewayConfig, logger: Logger);
|
|
21
22
|
start(): void;
|
|
22
23
|
stop(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/config/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/config/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAK9D,QAAA,MAAM,2BAA2B,EAAE,MAAM,EAMxC,CAAC;AAOF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;CACxB;AAOD,qBAAa,aAAc,SAAQ,YAAY;IAe3C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAE3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAhBzB,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IACrH,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IACtE,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IACtF,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAMxF,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGhB,UAAU,EAAE,MAAM,EACnC,aAAa,EAAE,aAAa,EACX,MAAM,EAAE,MAAM;IAOjC,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,IAAI;IAKZ,kCAAkC;IAClC,SAAS,IAAI,aAAa;IAI1B,MAAM,IAAI,IAAI;IAgGd,OAAO,CAAC,UAAU;CAoEnB;AAED,2EAA2E;AAC3E,iBAAS,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAoBlD;AAGD,OAAO,EAAE,SAAS,IAAI,UAAU,EAAE,2BAA2B,EAAE,CAAC"}
|
package/dist/config/watcher.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.HOT_RELOADABLE_AGENT_FIELDS = exports.ConfigWatcher = void 0;
|
|
|
4
4
|
exports._deepEqual = deepEqual;
|
|
5
5
|
const events_1 = require("events");
|
|
6
6
|
const loader_1 = require("./loader");
|
|
7
|
+
const agent_env_1 = require("./agent-env");
|
|
7
8
|
const factory_1 = require("../watch/factory");
|
|
8
9
|
const paths_1 = require("../utils/paths");
|
|
9
10
|
// Fields that can be hot-reloaded without restarting the gateway
|
|
@@ -30,6 +31,7 @@ class ConfigWatcher extends events_1.EventEmitter {
|
|
|
30
31
|
this.logger = logger;
|
|
31
32
|
this.watchHandle = null;
|
|
32
33
|
this.currentConfig = structuredClone(initialConfig);
|
|
34
|
+
this.agentsDir = (0, agent_env_1.agentsDirForConfig)(configPath);
|
|
33
35
|
}
|
|
34
36
|
start() {
|
|
35
37
|
this.watchHandle = (0, factory_1.createWatcher)({
|
|
@@ -48,9 +50,20 @@ class ConfigWatcher extends events_1.EventEmitter {
|
|
|
48
50
|
return this.currentConfig;
|
|
49
51
|
}
|
|
50
52
|
reload() {
|
|
53
|
+
// Fold any per-agent .env files into process.env BEFORE interpolation.
|
|
54
|
+
// An agent added while the gateway is running (MCP `agent_create`) writes
|
|
55
|
+
// its token to a brand-new agents/<id>/.env and only a ${VAR} placeholder
|
|
56
|
+
// into config.json. Without this refresh that variable is absent from
|
|
57
|
+
// process.env, loadConfig() drops the agent, the diff below sees nothing,
|
|
58
|
+
// and `agent.added` — whose handler is what used to load the .env — never
|
|
59
|
+
// fires. Issue #427.
|
|
60
|
+
(0, agent_env_1.loadAgentEnvFiles)(this.agentsDir);
|
|
51
61
|
let newConfig;
|
|
62
|
+
const skipped = [];
|
|
52
63
|
try {
|
|
53
|
-
newConfig = (0, loader_1.loadConfig)(this.configPath
|
|
64
|
+
newConfig = (0, loader_1.loadConfig)(this.configPath, {
|
|
65
|
+
onSkippedAgent: (s) => skipped.push(s),
|
|
66
|
+
});
|
|
54
67
|
newConfig.gateway.logDir = (0, paths_1.expandHome)(newConfig.gateway.logDir);
|
|
55
68
|
}
|
|
56
69
|
catch (err) {
|
|
@@ -59,6 +72,9 @@ class ConfigWatcher extends events_1.EventEmitter {
|
|
|
59
72
|
});
|
|
60
73
|
return;
|
|
61
74
|
}
|
|
75
|
+
// Report drops before the no-change bail-out below: a silently dropped
|
|
76
|
+
// agent produces exactly zero diff, so this is the only trace it leaves.
|
|
77
|
+
(0, loader_1.logSkippedAgents)(this.logger, skipped, 'Agent skipped during config reload');
|
|
62
78
|
const { fieldChanges, addedAgents } = this.diffConfig(this.currentConfig, newConfig);
|
|
63
79
|
if (fieldChanges.length === 0 && addedAgents.length === 0) {
|
|
64
80
|
this.logger.info('Config file changed but no effective differences detected');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/config/watcher.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/config/watcher.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ const load_dotenv_1 = require("./load-dotenv");
|
|
|
45
45
|
// which does the same before dispatching to the CLI.
|
|
46
46
|
(0, load_dotenv_1.loadGatewayDotenv)();
|
|
47
47
|
const loader_1 = require("./config/loader");
|
|
48
|
+
const agent_env_1 = require("./config/agent-env");
|
|
48
49
|
const migrator_1 = require("./config/migrator");
|
|
49
50
|
const bootstrap_1 = require("./config/bootstrap");
|
|
50
51
|
const workspace_loader_1 = require("./agent/workspace-loader");
|
|
@@ -132,40 +133,6 @@ function validateWorkspaceFast(workspacePath) {
|
|
|
132
133
|
}
|
|
133
134
|
return { ok: true };
|
|
134
135
|
}
|
|
135
|
-
/**
|
|
136
|
-
* Load .env from a single agent's env file into process.env.
|
|
137
|
-
* Values already in process.env win (existing env vars take priority).
|
|
138
|
-
*/
|
|
139
|
-
function loadAgentEnvFile(envFile) {
|
|
140
|
-
for (const line of fs.readFileSync(envFile, 'utf8').split('\n')) {
|
|
141
|
-
const trimmed = line.trim();
|
|
142
|
-
if (!trimmed || trimmed.startsWith('#'))
|
|
143
|
-
continue;
|
|
144
|
-
const eq = trimmed.indexOf('=');
|
|
145
|
-
if (eq < 1)
|
|
146
|
-
continue;
|
|
147
|
-
const key = trimmed.slice(0, eq).trim();
|
|
148
|
-
const val = trimmed.slice(eq + 1).trim();
|
|
149
|
-
if (key && process.env[key] === undefined) {
|
|
150
|
-
process.env[key] = val;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Load .env files from the gateway agents directory into process.env.
|
|
156
|
-
* Each agent may have a .env at ~/.claude-gateway/agents/<id>/.env
|
|
157
|
-
* containing bot tokens and other secrets. Values already in process.env win.
|
|
158
|
-
*/
|
|
159
|
-
function loadAgentEnvFiles(gatewayAgentsDir) {
|
|
160
|
-
if (!fs.existsSync(gatewayAgentsDir))
|
|
161
|
-
return;
|
|
162
|
-
for (const agentId of fs.readdirSync(gatewayAgentsDir)) {
|
|
163
|
-
const envFile = path.join(gatewayAgentsDir, agentId, '.env');
|
|
164
|
-
if (!fs.existsSync(envFile))
|
|
165
|
-
continue;
|
|
166
|
-
loadAgentEnvFile(envFile);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
136
|
async function startAgent(agentConfig, gatewayConfig, ctx) {
|
|
170
137
|
const { agentRunners, agentConfigs, schedulers, startupResults, mcpToolsDir, sharedSkillsDir, logDir } = ctx;
|
|
171
138
|
const logger = (0, logger_1.createLogger)(agentConfig.id, logDir);
|
|
@@ -528,9 +495,10 @@ async function restoreSockets(registry, socketServer) {
|
|
|
528
495
|
let isShuttingDown = false;
|
|
529
496
|
let registeredShutdown = null;
|
|
530
497
|
async function main() {
|
|
531
|
-
// Load agent .env files before config interpolation so ${TOKEN} vars resolve
|
|
532
|
-
|
|
533
|
-
|
|
498
|
+
// Load agent .env files before config interpolation so ${TOKEN} vars resolve.
|
|
499
|
+
// ConfigWatcher repeats this before every reload, so agents that appear later
|
|
500
|
+
// resolve too — see src/config/agent-env.ts.
|
|
501
|
+
(0, agent_env_1.loadAgentEnvFiles)((0, agent_env_1.agentsDirForConfig)(CONFIG_PATH));
|
|
534
502
|
// ── First run: create config.json with a fresh admin key if none exists ───
|
|
535
503
|
const templatePath = path.join(__dirname, '..', 'config.template.json');
|
|
536
504
|
const bootstrap = (0, bootstrap_1.ensureConfigExists)(CONFIG_PATH, templatePath);
|
|
@@ -563,8 +531,21 @@ async function main() {
|
|
|
563
531
|
console.warn(`[gateway] Config migration skipped: ${err.message}`);
|
|
564
532
|
}
|
|
565
533
|
console.log(`[gateway] Loading config from ${CONFIG_PATH}`);
|
|
566
|
-
|
|
534
|
+
// Skips are collected rather than logged inline: the structured logger needs
|
|
535
|
+
// config.gateway.logDir, so it cannot exist until this call returns. They are
|
|
536
|
+
// replayed through globalLogger below so a dropped agent is diagnosable from
|
|
537
|
+
// logs/gateway.log at startup too, not only on reload (#427).
|
|
538
|
+
const startupSkips = [];
|
|
539
|
+
const config = (0, loader_1.loadConfig)(CONFIG_PATH, {
|
|
540
|
+
onSkippedAgent: (s) => startupSkips.push(s),
|
|
541
|
+
});
|
|
567
542
|
config.gateway.logDir = (0, paths_1.expandHome)(config.gateway.logDir);
|
|
543
|
+
// Created as early as logDir allows, and before the isolation guard below:
|
|
544
|
+
// a config bad enough to drop an agent is exactly the config likely to fail
|
|
545
|
+
// validation too, and a guard throw must not swallow the reason an agent
|
|
546
|
+
// went missing.
|
|
547
|
+
const globalLogger = (0, logger_1.createLogger)('gateway', (0, paths_1.expandHome)(config.gateway.logDir));
|
|
548
|
+
(0, loader_1.logSkippedAgents)(globalLogger, startupSkips, 'Agent skipped at startup');
|
|
568
549
|
// ── Context isolation check ──────────────────────────────────────────────
|
|
569
550
|
const guard = new context_isolation_1.ContextIsolationGuard();
|
|
570
551
|
guard.validate(config.agents);
|
|
@@ -574,7 +555,6 @@ async function main() {
|
|
|
574
555
|
const startupResults = [];
|
|
575
556
|
const sharedSkillsDir = path.join(os.homedir(), '.claude-gateway', 'shared-skills');
|
|
576
557
|
const personalSkillsDir = path.join(os.homedir(), '.claude', 'skills');
|
|
577
|
-
const globalLogger = (0, logger_1.createLogger)('gateway', (0, paths_1.expandHome)(config.gateway.logDir));
|
|
578
558
|
const mcpToolsDir = path.resolve(__dirname, '..', 'mcp', 'tools');
|
|
579
559
|
const logDir = (0, paths_1.expandHome)(config.gateway.logDir);
|
|
580
560
|
// Signals are wired HERE, not after startup finishes. Boot spawns receivers
|
|
@@ -681,7 +661,7 @@ async function main() {
|
|
|
681
661
|
const appsConfigPath = path.join(path.dirname(CONFIG_PATH), 'apps.json');
|
|
682
662
|
const appsRegistry = new registry_1.AppsRegistry(appsConfigPath);
|
|
683
663
|
const registryClient = new registry_client_1.RegistryClient();
|
|
684
|
-
const agentManager = new agent_manager_1.AgentManager(CONFIG_PATH,
|
|
664
|
+
const agentManager = new agent_manager_1.AgentManager(CONFIG_PATH, (0, agent_env_1.agentsDirForConfig)(CONFIG_PATH));
|
|
685
665
|
const socketServer = new socket_server_1.SocketServer();
|
|
686
666
|
// Callbacks that bridge installer events to the router (filled in after router is created)
|
|
687
667
|
const installerCallbacks = {
|
|
@@ -717,7 +697,7 @@ async function main() {
|
|
|
717
697
|
}
|
|
718
698
|
},
|
|
719
699
|
};
|
|
720
|
-
const appInstaller = new installer_1.AppInstaller(appsRegistry, registryClient, installerCallbacks, undefined, undefined, agentManager, undefined, config.gateway.appHousekeeping, config.gateway?.appBackup);
|
|
700
|
+
const appInstaller = new installer_1.AppInstaller(appsRegistry, registryClient, installerCallbacks, undefined, undefined, agentManager, undefined, config.gateway.appHousekeeping, config.gateway?.appBackup, undefined, config.gateway?.appRestore);
|
|
721
701
|
// Reclaim update scratch dirs a previous crash left beside an install path.
|
|
722
702
|
// Must run at boot, before any update can claim one of those names.
|
|
723
703
|
try {
|
|
@@ -854,11 +834,9 @@ async function main() {
|
|
|
854
834
|
});
|
|
855
835
|
configWatcher.on('agent.added', async (newAgentConfig) => {
|
|
856
836
|
globalLogger.info('New agent detected in config, starting dynamically', { id: newAgentConfig.id });
|
|
857
|
-
//
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
loadAgentEnvFile(agentEnvFile);
|
|
861
|
-
}
|
|
837
|
+
// The agent's .env is already in process.env: ConfigWatcher.reload() folds
|
|
838
|
+
// agents/<id>/.env in before interpolating, which is the only reason this
|
|
839
|
+
// event can fire for a ${VAR}-token agent at all (#427).
|
|
862
840
|
newAgentConfig.workspace = (0, paths_1.expandHome)(newAgentConfig.workspace);
|
|
863
841
|
await startAgent(newAgentConfig, configWatcher.getConfig(), ctx);
|
|
864
842
|
globalLogger.info('Agent hot-added successfully', { id: newAgentConfig.id });
|
|
@@ -867,11 +845,6 @@ async function main() {
|
|
|
867
845
|
const runner = ctx.agentRunners.get(agentId);
|
|
868
846
|
if (!runner)
|
|
869
847
|
return;
|
|
870
|
-
// Load fresh .env so new token is available before starting receiver
|
|
871
|
-
const agentEnvFile = path.join(gatewayAgentsDir, agentId, '.env');
|
|
872
|
-
if (fs.existsSync(agentEnvFile)) {
|
|
873
|
-
loadAgentEnvFile(agentEnvFile);
|
|
874
|
-
}
|
|
875
848
|
// Reload the agent config so runner has the new token
|
|
876
849
|
const freshConfig = configWatcher.getConfig();
|
|
877
850
|
const freshAgent = freshConfig.agents.find(a => a.id === agentId);
|