@0xmaxma/claude-gateway 1.7.9 → 1.8.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 +178 -44
- package/dist/agent/builtin-commands.js +2 -2
- package/dist/agent/builtin-commands.js.map +1 -1
- package/dist/agent/dreaming/accept.d.ts.map +1 -1
- package/dist/agent/dreaming/accept.js +4 -1
- package/dist/agent/dreaming/accept.js.map +1 -1
- package/dist/agent/dreaming/config.d.ts.map +1 -1
- package/dist/agent/dreaming/config.js +2 -0
- package/dist/agent/dreaming/config.js.map +1 -1
- package/dist/agent/dreaming/reviewer.d.ts.map +1 -1
- package/dist/agent/dreaming/reviewer.js +9 -2
- package/dist/agent/dreaming/reviewer.js.map +1 -1
- package/dist/agent/dreaming/staleness.d.ts +7 -1
- package/dist/agent/dreaming/staleness.d.ts.map +1 -1
- package/dist/agent/dreaming/staleness.js +17 -2
- package/dist/agent/dreaming/staleness.js.map +1 -1
- package/dist/agent/dreaming/types.d.ts +17 -1
- package/dist/agent/dreaming/types.d.ts.map +1 -1
- package/dist/agent/knowledge/archive-db.d.ts +43 -0
- package/dist/agent/knowledge/archive-db.d.ts.map +1 -1
- package/dist/agent/knowledge/archive-db.js +130 -0
- package/dist/agent/knowledge/archive-db.js.map +1 -1
- package/dist/agent/knowledge/config.d.ts +3 -1
- package/dist/agent/knowledge/config.d.ts.map +1 -1
- package/dist/agent/knowledge/config.js +32 -10
- package/dist/agent/knowledge/config.js.map +1 -1
- package/dist/agent/knowledge/index.d.ts +11 -4
- package/dist/agent/knowledge/index.d.ts.map +1 -1
- package/dist/agent/knowledge/index.js +22 -1
- package/dist/agent/knowledge/index.js.map +1 -1
- package/dist/agent/knowledge/indexer.d.ts +0 -7
- package/dist/agent/knowledge/indexer.d.ts.map +1 -1
- package/dist/agent/knowledge/indexer.js +34 -7
- package/dist/agent/knowledge/indexer.js.map +1 -1
- package/dist/agent/knowledge/lifecycle.d.ts +20 -4
- package/dist/agent/knowledge/lifecycle.d.ts.map +1 -1
- package/dist/agent/knowledge/lifecycle.js +33 -4
- package/dist/agent/knowledge/lifecycle.js.map +1 -1
- package/dist/agent/knowledge/reflection.d.ts +114 -0
- package/dist/agent/knowledge/reflection.d.ts.map +1 -0
- package/dist/agent/knowledge/reflection.js +447 -0
- package/dist/agent/knowledge/reflection.js.map +1 -0
- package/dist/agent/knowledge/shared-dedup.d.ts +85 -0
- package/dist/agent/knowledge/shared-dedup.d.ts.map +1 -0
- package/dist/agent/knowledge/shared-dedup.js +187 -0
- package/dist/agent/knowledge/shared-dedup.js.map +1 -0
- package/dist/agent/knowledge/shared-promote.d.ts +82 -7
- package/dist/agent/knowledge/shared-promote.d.ts.map +1 -1
- package/dist/agent/knowledge/shared-promote.js +244 -11
- package/dist/agent/knowledge/shared-promote.js.map +1 -1
- package/dist/agent/knowledge/shared-staleness.d.ts +51 -0
- package/dist/agent/knowledge/shared-staleness.d.ts.map +1 -0
- package/dist/agent/knowledge/shared-staleness.js +149 -0
- package/dist/agent/knowledge/shared-staleness.js.map +1 -0
- package/dist/agent/knowledge/shared-writer.d.ts +19 -0
- package/dist/agent/knowledge/shared-writer.d.ts.map +1 -1
- package/dist/agent/knowledge/shared-writer.js +42 -0
- package/dist/agent/knowledge/shared-writer.js.map +1 -1
- package/dist/agent/knowledge/types.d.ts +24 -0
- package/dist/agent/knowledge/types.d.ts.map +1 -1
- package/dist/agent/model-catalog.d.ts +62 -0
- package/dist/agent/model-catalog.d.ts.map +1 -0
- package/dist/agent/model-catalog.js +264 -0
- package/dist/agent/model-catalog.js.map +1 -0
- package/dist/agent/runner.d.ts +83 -0
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +281 -51
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/workspace-loader.d.ts +17 -2
- package/dist/agent/workspace-loader.d.ts.map +1 -1
- package/dist/agent/workspace-loader.js +17 -1
- package/dist/agent/workspace-loader.js.map +1 -1
- package/dist/api/cron-router.d.ts +12 -8
- package/dist/api/cron-router.d.ts.map +1 -1
- package/dist/api/cron-router.js +82 -16
- package/dist/api/cron-router.js.map +1 -1
- package/dist/api/gateway-router.d.ts +4 -0
- package/dist/api/gateway-router.d.ts.map +1 -1
- package/dist/api/gateway-router.js +16 -1
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/manifest-sources.d.ts +15 -0
- package/dist/api/manifest-sources.d.ts.map +1 -0
- package/dist/api/manifest-sources.js +27 -0
- package/dist/api/manifest-sources.js.map +1 -0
- package/dist/api/meta-router.d.ts +13 -0
- package/dist/api/meta-router.d.ts.map +1 -0
- package/dist/api/meta-router.js +26 -0
- package/dist/api/meta-router.js.map +1 -0
- package/dist/api/packages.d.ts.map +1 -1
- package/dist/api/packages.js +18 -198
- package/dist/api/packages.js.map +1 -1
- package/dist/api/route-registry.d.ts +81 -0
- package/dist/api/route-registry.d.ts.map +1 -0
- package/dist/api/route-registry.js +44 -0
- package/dist/api/route-registry.js.map +1 -0
- package/dist/api/router.d.ts.map +1 -1
- package/dist/api/router.js +21 -3
- package/dist/api/router.js.map +1 -1
- package/dist/apps/compose-generator.js +7 -4
- package/dist/apps/compose-generator.js.map +1 -1
- package/dist/apps/installer.d.ts +154 -0
- package/dist/apps/installer.d.ts.map +1 -1
- package/dist/apps/installer.js +657 -54
- package/dist/apps/installer.js.map +1 -1
- package/dist/cli/args.d.ts +25 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +55 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/colors.d.ts +37 -0
- package/dist/cli/colors.d.ts.map +1 -0
- package/dist/cli/colors.js +63 -0
- package/dist/cli/colors.js.map +1 -0
- package/dist/cli/command-names.d.ts +98 -0
- package/dist/cli/command-names.d.ts.map +1 -0
- package/dist/cli/command-names.js +109 -0
- package/dist/cli/command-names.js.map +1 -0
- package/dist/cli/commands/agents.d.ts +28 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/agents.js +321 -0
- package/dist/cli/commands/agents.js.map +1 -0
- package/dist/cli/commands/channels.d.ts +17 -0
- package/dist/cli/commands/channels.d.ts.map +1 -0
- package/dist/cli/commands/channels.js +101 -0
- package/dist/cli/commands/channels.js.map +1 -0
- package/dist/cli/commands/debug-bundle.d.ts +6 -0
- package/dist/cli/commands/debug-bundle.d.ts.map +1 -0
- package/dist/cli/commands/debug-bundle.js +220 -0
- package/dist/cli/commands/debug-bundle.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +104 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/gateway.d.ts +12 -0
- package/dist/cli/commands/gateway.d.ts.map +1 -0
- package/dist/cli/commands/gateway.js +145 -0
- package/dist/cli/commands/gateway.js.map +1 -0
- package/dist/cli/commands/service.d.ts +33 -0
- package/dist/cli/commands/service.d.ts.map +1 -0
- package/dist/cli/commands/service.js +513 -0
- package/dist/cli/commands/service.js.map +1 -0
- package/dist/cli/commands/update.d.ts +16 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +149 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands.generated.d.ts +4 -0
- package/dist/cli/commands.generated.d.ts.map +1 -0
- package/dist/cli/commands.generated.js +220 -0
- package/dist/cli/commands.generated.js.map +1 -0
- package/dist/cli/health.d.ts +31 -0
- package/dist/cli/health.d.ts.map +1 -0
- package/dist/cli/health.js +49 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/http-client.d.ts +140 -0
- package/dist/cli/http-client.d.ts.map +1 -0
- package/dist/cli/http-client.js +332 -0
- package/dist/cli/http-client.js.map +1 -0
- package/dist/cli/index.d.ts +27 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +372 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/manager.d.ts +64 -0
- package/dist/cli/manager.d.ts.map +1 -0
- package/dist/cli/manager.js +181 -0
- package/dist/cli/manager.js.map +1 -0
- package/dist/cli/output.d.ts +49 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +101 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/prompt.d.ts +29 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +154 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/redact.d.ts +3 -0
- package/dist/cli/redact.d.ts.map +1 -0
- package/dist/cli/redact.js +33 -0
- package/dist/cli/redact.js.map +1 -0
- package/dist/cli/types.d.ts +22 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +4 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/config/bootstrap.d.ts +33 -0
- package/dist/config/bootstrap.d.ts.map +1 -0
- package/dist/config/bootstrap.js +117 -0
- package/dist/config/bootstrap.js.map +1 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +5 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/config/watcher.d.ts.map +1 -1
- package/dist/config/watcher.js +2 -35
- package/dist/config/watcher.js.map +1 -1
- package/dist/discord/receiver.d.ts +6 -1
- package/dist/discord/receiver.d.ts.map +1 -1
- package/dist/discord/receiver.js +9 -1
- package/dist/discord/receiver.js.map +1 -1
- package/dist/entry.d.ts +3 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +83 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.js +197 -47
- package/dist/index.js.map +1 -1
- package/dist/load-dotenv.d.ts +2 -0
- package/dist/load-dotenv.d.ts.map +1 -0
- package/dist/load-dotenv.js +68 -0
- package/dist/load-dotenv.js.map +1 -0
- package/dist/packages/registry.d.ts +50 -0
- package/dist/packages/registry.d.ts.map +1 -0
- package/dist/packages/registry.js +209 -0
- package/dist/packages/registry.js.map +1 -0
- package/dist/session/process.d.ts +20 -3
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +120 -5
- package/dist/session/process.js.map +1 -1
- package/dist/shell/claude-pty-shell.js +146 -27
- package/dist/shell/claude-pty-shell.js.map +1 -1
- package/dist/shell/draft-phantom.d.ts +49 -0
- package/dist/shell/draft-phantom.d.ts.map +1 -0
- package/dist/shell/draft-phantom.js +59 -0
- package/dist/shell/draft-phantom.js.map +1 -0
- package/dist/shell/submit-diag.d.ts +67 -0
- package/dist/shell/submit-diag.d.ts.map +1 -0
- package/dist/shell/submit-diag.js +69 -0
- package/dist/shell/submit-diag.js.map +1 -0
- package/dist/shutdown-signals.d.ts +47 -0
- package/dist/shutdown-signals.d.ts.map +1 -0
- package/dist/shutdown-signals.js +62 -0
- package/dist/shutdown-signals.js.map +1 -0
- package/dist/telegram/receiver.d.ts +6 -1
- package/dist/telegram/receiver.d.ts.map +1 -1
- package/dist/telegram/receiver.js +9 -1
- package/dist/telegram/receiver.js.map +1 -1
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/orphan-receivers.d.ts +90 -0
- package/dist/utils/orphan-receivers.d.ts.map +1 -0
- package/dist/utils/orphan-receivers.js +218 -0
- package/dist/utils/orphan-receivers.js.map +1 -0
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +60 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/stop-child.d.ts +21 -0
- package/dist/utils/stop-child.d.ts.map +1 -0
- package/dist/utils/stop-child.js +64 -0
- package/dist/utils/stop-child.js.map +1 -0
- package/lib/pairing.ts +1 -1
- package/mcp/tools/agent/handlers.ts +1 -1
- package/mcp/tools/discord/module.ts +23 -15
- package/mcp/tools/discord/receiver-server.ts +4 -0
- package/mcp/tools/memory/archive-reader.test.ts +25 -1
- package/mcp/tools/memory/archive-reader.ts +70 -12
- package/mcp/tools/memory/archive-writer.test.ts +168 -0
- package/mcp/tools/memory/archive-writer.ts +137 -0
- package/mcp/tools/memory/module.test.ts +187 -0
- package/mcp/tools/memory/module.ts +192 -6
- package/mcp/tools/telegram/module.ts +10 -2
- package/mcp/tools/telegram/receiver-server.ts +15 -6
- package/mcp/tools/telegram/typing.ts +178 -34
- package/package.json +6 -4
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PAIRING_CHANNELS = void 0;
|
|
4
|
+
exports.runChannels = runChannels;
|
|
5
|
+
const http_client_1 = require("../http-client");
|
|
6
|
+
const output_1 = require("../output");
|
|
7
|
+
/**
|
|
8
|
+
* `channels pending|approve|deny` — manage incoming Telegram/Discord pairing
|
|
9
|
+
* requests for an agent (replaces `make pair agent=X code=Y channel=Z`).
|
|
10
|
+
*
|
|
11
|
+
* Scoped to the channels that actually expose a code-based pairing queue
|
|
12
|
+
* today (GET .../pending, POST .../approve, POST .../deny — see
|
|
13
|
+
* src/api/router.ts). LINE and Slack use a different model (a "recently
|
|
14
|
+
* dropped senders" list you allowlist directly, no approval code) so they
|
|
15
|
+
* aren't part of this command. Adding a future channel with the same
|
|
16
|
+
* approve/deny-by-code shape only requires adding it to PAIRING_CHANNELS below
|
|
17
|
+
* — no other code here is channel-specific.
|
|
18
|
+
*/
|
|
19
|
+
exports.PAIRING_CHANNELS = ['telegram', 'discord'];
|
|
20
|
+
function isPairingChannel(v) {
|
|
21
|
+
return !!v && exports.PAIRING_CHANNELS.includes(v);
|
|
22
|
+
}
|
|
23
|
+
async function runChannels(positionals, flags, config) {
|
|
24
|
+
const verb = positionals[0];
|
|
25
|
+
if (!verb || flags.help === true) {
|
|
26
|
+
// An explicit `--help` succeeds; a missing verb is a usage error.
|
|
27
|
+
printHelp(flags.help === true);
|
|
28
|
+
return flags.help === true ? 0 : 1;
|
|
29
|
+
}
|
|
30
|
+
const agentId = typeof flags.agent === 'string' ? flags.agent : undefined;
|
|
31
|
+
if (!agentId) {
|
|
32
|
+
process.stderr.write('Missing required flag: --agent <id>\n\n');
|
|
33
|
+
printHelp(false);
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
36
|
+
const channelFlag = typeof flags.channel === 'string' ? flags.channel : undefined;
|
|
37
|
+
if (channelFlag !== undefined && !isPairingChannel(channelFlag)) {
|
|
38
|
+
process.stderr.write(`Invalid --channel '${channelFlag}'. Expected one of: ${exports.PAIRING_CHANNELS.join(', ')}\n`);
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
const baseUrl = await (0, http_client_1.resolveReachableUrl)((0, http_client_1.resolveUrlPlan)({ flagUrl: strFlag(flags.url), env: process.env, config }));
|
|
42
|
+
const key = (0, http_client_1.resolveKey)({ flagKey: strFlag(flags.key), env: process.env, config });
|
|
43
|
+
const compact = flags.json === true;
|
|
44
|
+
switch (verb) {
|
|
45
|
+
case 'pending': {
|
|
46
|
+
const channels = channelFlag ? [channelFlag] : exports.PAIRING_CHANNELS;
|
|
47
|
+
const byChannel = {};
|
|
48
|
+
for (const channel of channels) {
|
|
49
|
+
const result = await (0, http_client_1.request)({ method: 'GET', path: `/v1/agents/${encodeURIComponent(agentId)}/${channel}/pending`, baseUrl, key });
|
|
50
|
+
byChannel[channel] = result.data?.pending ?? [];
|
|
51
|
+
}
|
|
52
|
+
(0, output_1.printResult)(byChannel, compact);
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
case 'approve':
|
|
56
|
+
case 'deny': {
|
|
57
|
+
if (!channelFlag) {
|
|
58
|
+
process.stderr.write(`Missing required flag: --channel <${exports.PAIRING_CHANNELS.join('|')}>\n\n`);
|
|
59
|
+
printHelp(false);
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
const code = typeof flags.code === 'string' ? flags.code : undefined;
|
|
63
|
+
if (!code) {
|
|
64
|
+
process.stderr.write('Missing required flag: --code <code>\n\n');
|
|
65
|
+
printHelp(false);
|
|
66
|
+
return 1;
|
|
67
|
+
}
|
|
68
|
+
const result = await (0, http_client_1.request)({
|
|
69
|
+
method: 'POST',
|
|
70
|
+
path: `/v1/agents/${encodeURIComponent(agentId)}/${channelFlag}/${verb}`,
|
|
71
|
+
baseUrl,
|
|
72
|
+
key,
|
|
73
|
+
body: { code },
|
|
74
|
+
});
|
|
75
|
+
(0, output_1.printResult)(result.data, compact);
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
default:
|
|
79
|
+
process.stderr.write(`Unknown: channels ${verb} (expected pending|approve|deny)\n\n`);
|
|
80
|
+
printHelp(false);
|
|
81
|
+
return 1;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function strFlag(v) {
|
|
85
|
+
return typeof v === 'string' ? v : undefined;
|
|
86
|
+
}
|
|
87
|
+
function printHelp(requested) {
|
|
88
|
+
const ch = exports.PAIRING_CHANNELS.join('|');
|
|
89
|
+
// The channel list is interpolated, so the gap cannot be hand-counted — the
|
|
90
|
+
// rows drifted out of alignment as soon as a channel was added. Pad to the
|
|
91
|
+
// widest usage instead.
|
|
92
|
+
const rows = [
|
|
93
|
+
[`channels pending --agent <id> [--channel ${ch}]`, 'List pending requests (both channels if omitted)'],
|
|
94
|
+
[`channels approve --agent <id> --channel <${ch}> --code <code>`, 'Approve a pending request'],
|
|
95
|
+
[`channels deny --agent <id> --channel <${ch}> --code <code>`, 'Deny and remove a pending request'],
|
|
96
|
+
];
|
|
97
|
+
const width = Math.max(...rows.map(([usage]) => usage.length)) + 2;
|
|
98
|
+
const lines = rows.map(([usage, desc]) => ` ${usage.padEnd(width)}${desc}`);
|
|
99
|
+
(0, output_1.writeCommandHelp)(requested, 'channels', 'manage incoming Telegram/Discord pairing requests', 'claude-gateway channels <pending|approve|deny> --agent <id> [--flags]', lines);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=channels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels.js","sourceRoot":"","sources":["../../../src/cli/commands/channels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Pure: pick the diagnostic lines (warn/error/submit-diag) from a log's text,
|
|
2
|
+
* redact them, cap each line's length, and keep at most `maxLines` (from the
|
|
3
|
+
* tail — most recent). */
|
|
4
|
+
export declare function selectDiagnosticLines(content: string, maxLines?: number, maxLineLength?: number): string[];
|
|
5
|
+
export declare function runDebugBundle(flags: Record<string, string | boolean>): Promise<number>;
|
|
6
|
+
//# sourceMappingURL=debug-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-bundle.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/debug-bundle.ts"],"names":[],"mappings":"AA8BA;;2BAE2B;AAC3B,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAiB,EAAE,aAAa,SAAkB,GAAG,MAAM,EAAE,CAQ3H;AAgFD,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAyE7F"}
|
|
@@ -0,0 +1,220 @@
|
|
|
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.selectDiagnosticLines = selectDiagnosticLines;
|
|
37
|
+
exports.runDebugBundle = runDebugBundle;
|
|
38
|
+
const child_process_1 = require("child_process");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const os = __importStar(require("os"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const http_client_1 = require("../http-client");
|
|
43
|
+
const redact_1 = require("../redact");
|
|
44
|
+
const output_1 = require("../output");
|
|
45
|
+
/**
|
|
46
|
+
* `debug-bundle` — collect a small, redacted diagnostics bundle for a session
|
|
47
|
+
* that went silent, so a user can attach ONE file to an issue/Telegram instead
|
|
48
|
+
* of a multi-MB raw log (which may contain prompts/secrets).
|
|
49
|
+
*
|
|
50
|
+
* Reads the log directory directly, so it works even when the gateway is wedged
|
|
51
|
+
* or dead. Includes only warn/error and submit-diag lines, redacted, plus an
|
|
52
|
+
* environment header.
|
|
53
|
+
*/
|
|
54
|
+
const MAX_DIAG_LINES = 4000;
|
|
55
|
+
/** Cap on a single kept line's length. Guards against one giant serialized
|
|
56
|
+
* object/stack trace blowing past the "small bundle" goal, and limits how much
|
|
57
|
+
* of any one line's content (which redaction cannot fully guarantee is clean —
|
|
58
|
+
* see the banner below) ends up in the file. */
|
|
59
|
+
const MAX_LINE_LENGTH = 2000;
|
|
60
|
+
function truncateLine(line, maxLength) {
|
|
61
|
+
if (line.length <= maxLength)
|
|
62
|
+
return line;
|
|
63
|
+
return `${line.slice(0, maxLength)} …[truncated, ${line.length - maxLength} more chars]`;
|
|
64
|
+
}
|
|
65
|
+
/** Pure: pick the diagnostic lines (warn/error/submit-diag) from a log's text,
|
|
66
|
+
* redact them, cap each line's length, and keep at most `maxLines` (from the
|
|
67
|
+
* tail — most recent). */
|
|
68
|
+
function selectDiagnosticLines(content, maxLines = MAX_DIAG_LINES, maxLineLength = MAX_LINE_LENGTH) {
|
|
69
|
+
const picked = [];
|
|
70
|
+
for (const line of content.split('\n')) {
|
|
71
|
+
if (/\bWARN\b|\bERROR\b|submit-diag/i.test(line)) {
|
|
72
|
+
picked.push(truncateLine((0, redact_1.redactLine)(line), maxLineLength));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return picked.length > maxLines ? picked.slice(picked.length - maxLines) : picked;
|
|
76
|
+
}
|
|
77
|
+
/** The config file stores `logDir` exactly as written, and the shipped template
|
|
78
|
+
* writes `~/.claude-gateway/logs`. The server expands that itself on boot, so
|
|
79
|
+
* the literal tilde survives on disk and only bites a reader that forgets to
|
|
80
|
+
* expand it — `readdirSync('~/...')` throws ENOENT and looks like "no logs". */
|
|
81
|
+
function resolveLogDir(flags) {
|
|
82
|
+
if (typeof flags.logDir === 'string')
|
|
83
|
+
return (0, http_client_1.expandHome)(flags.logDir);
|
|
84
|
+
const cfg = (0, http_client_1.loadCliConfig)(typeof flags.config === 'string' ? flags.config : undefined);
|
|
85
|
+
if (cfg.logDir)
|
|
86
|
+
return (0, http_client_1.expandHome)(cfg.logDir);
|
|
87
|
+
return path.join(os.homedir(), '.claude-gateway', 'logs');
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Session logs in `dir`, or the reason the directory could not be read.
|
|
91
|
+
*
|
|
92
|
+
* The read used to be wrapped in a bare `catch { return [] }`, which reported
|
|
93
|
+
* every failure as "no session logs found". That is how the unexpanded `~`
|
|
94
|
+
* stayed invisible: an ENOENT on a path that was never resolved looked exactly
|
|
95
|
+
* like an empty directory, and a permission problem still would. The caller
|
|
96
|
+
* needs the errno to say anything useful, so it is returned rather than eaten.
|
|
97
|
+
*/
|
|
98
|
+
function listSessionLogs(dir) {
|
|
99
|
+
let names;
|
|
100
|
+
try {
|
|
101
|
+
names = fs.readdirSync(dir);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const e = err;
|
|
105
|
+
if (e.code === 'ENOENT')
|
|
106
|
+
return { logs: [], error: `${dir} does not exist` };
|
|
107
|
+
if (e.code === 'ENOTDIR')
|
|
108
|
+
return { logs: [], error: `${dir} is not a directory` };
|
|
109
|
+
return { logs: [], error: `${dir} could not be read (${e.code ?? e.message})` };
|
|
110
|
+
}
|
|
111
|
+
const logs = names
|
|
112
|
+
.filter((n) => n.endsWith('.log') && /session/i.test(n))
|
|
113
|
+
.map((n) => {
|
|
114
|
+
const file = path.join(dir, n);
|
|
115
|
+
let mtimeMs = 0;
|
|
116
|
+
try {
|
|
117
|
+
mtimeMs = fs.statSync(file).mtimeMs;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
/* ignore */
|
|
121
|
+
}
|
|
122
|
+
return { file, mtimeMs };
|
|
123
|
+
});
|
|
124
|
+
return { logs };
|
|
125
|
+
}
|
|
126
|
+
function claudeCodeVersion() {
|
|
127
|
+
try {
|
|
128
|
+
return (0, child_process_1.execSync)('claude --version', { stdio: ['ignore', 'pipe', 'ignore'], timeout: 3000 }).toString().trim();
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return 'unknown';
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function gatewayVersion() {
|
|
135
|
+
try {
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
137
|
+
return require(path.join(__dirname, '..', '..', '..', 'package.json')).version;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return 'unknown';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function printHelp() {
|
|
144
|
+
(0, output_1.writeCommandHelp)(true, 'debug-bundle', 'write a small redacted diagnostics bundle', 'claude-gateway debug-bundle [--session <id>] [--logDir <path>] [--config <path>]', [
|
|
145
|
+
' --session <id> Bundle this session instead of the most recent one',
|
|
146
|
+
' --logDir <path> Read logs from here instead of the configured directory',
|
|
147
|
+
' --config <path> Read logDir from this config file',
|
|
148
|
+
'',
|
|
149
|
+
' Writes debug-bundle-<stamp>.txt into the current directory.',
|
|
150
|
+
]);
|
|
151
|
+
}
|
|
152
|
+
async function runDebugBundle(flags) {
|
|
153
|
+
// `--help` must stay read-only: every other command prints and returns, and
|
|
154
|
+
// this one writes a file into the working directory as its side effect.
|
|
155
|
+
if (flags.help === true) {
|
|
156
|
+
printHelp();
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
const logDir = resolveLogDir(flags);
|
|
160
|
+
const sessionFilter = typeof flags.session === 'string' ? flags.session : undefined;
|
|
161
|
+
const found = listSessionLogs(logDir);
|
|
162
|
+
// A directory that could not be read is a different answer from one holding
|
|
163
|
+
// no logs, and only one of them is the operator's to fix.
|
|
164
|
+
if (found.error) {
|
|
165
|
+
process.stderr.write(`Cannot read session logs: ${found.error}\n`);
|
|
166
|
+
return 1;
|
|
167
|
+
}
|
|
168
|
+
let logs = found.logs;
|
|
169
|
+
if (sessionFilter) {
|
|
170
|
+
logs = logs.filter((l) => path.basename(l.file).includes(sessionFilter));
|
|
171
|
+
if (!logs.length) {
|
|
172
|
+
process.stderr.write(`No session log matching "${sessionFilter}" in ${logDir}\n`);
|
|
173
|
+
return 1;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// Most recently modified session log.
|
|
178
|
+
logs.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
179
|
+
logs = logs.slice(0, 1);
|
|
180
|
+
if (!logs.length) {
|
|
181
|
+
process.stderr.write(`No session logs found in ${logDir}\n`);
|
|
182
|
+
return 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const sections = [];
|
|
186
|
+
sections.push('=== claude-gateway debug bundle ===');
|
|
187
|
+
sections.push('⚠ Please skim this file before sharing it. Redaction masks common secret ' +
|
|
188
|
+
'patterns (bearer tokens, api-key/secret/password assignments, provider-style ' +
|
|
189
|
+
'keys, long opaque tokens) but cannot guarantee removal of arbitrary free-form ' +
|
|
190
|
+
'text that happened to land in a WARN/ERROR log line.');
|
|
191
|
+
sections.push(`generatedAt: ${new Date().toISOString()}`);
|
|
192
|
+
sections.push(`gatewayVersion: ${gatewayVersion()}`);
|
|
193
|
+
sections.push(`claudeCodeVersion: ${claudeCodeVersion()}`);
|
|
194
|
+
sections.push(`node: ${process.version}`);
|
|
195
|
+
sections.push(`os: ${os.platform()} ${os.release()} (${os.arch()})`);
|
|
196
|
+
sections.push(`logDir: ${logDir}`);
|
|
197
|
+
sections.push('');
|
|
198
|
+
for (const { file } of logs) {
|
|
199
|
+
let content = '';
|
|
200
|
+
try {
|
|
201
|
+
content = fs.readFileSync(file, 'utf8');
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
sections.push(`--- ${path.basename(file)} (unreadable: ${err.message}) ---`);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const lines = selectDiagnosticLines(content);
|
|
208
|
+
sections.push(`--- ${path.basename(file)} (${lines.length} diagnostic lines) ---`);
|
|
209
|
+
sections.push(lines.join('\n'));
|
|
210
|
+
sections.push('');
|
|
211
|
+
}
|
|
212
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
213
|
+
const outFile = path.join(process.cwd(), `debug-bundle-${stamp}.txt`);
|
|
214
|
+
fs.writeFileSync(outFile, sections.join('\n'));
|
|
215
|
+
process.stdout.write(`${outFile}\n`);
|
|
216
|
+
process.stderr.write(`Wrote debug bundle: ${outFile}\n` +
|
|
217
|
+
'Redaction covers common secret patterns, not all free-form text — please skim it before attaching to a GitHub issue or sending it to the team.\n');
|
|
218
|
+
return 0;
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=debug-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-bundle.js","sourceRoot":"","sources":["../../../src/cli/commands/debug-bundle.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,sDAQC;AAgFD,wCAyEC;AAlMD,iDAAyC;AACzC,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAC7B,gDAA2D;AAC3D,sCAAuC;AACvC,sCAA6C;AAE7C;;;;;;;;GAQG;AAEH,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B;;;iDAGiD;AACjD,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB;IACnD,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,iBAAiB,IAAI,CAAC,MAAM,GAAG,SAAS,cAAc,CAAC;AAC3F,CAAC;AAED;;2BAE2B;AAC3B,SAAgB,qBAAqB,CAAC,OAAe,EAAE,QAAQ,GAAG,cAAc,EAAE,aAAa,GAAG,eAAe;IAC/G,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,IAAI,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAA,mBAAU,EAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACpF,CAAC;AAED;;;iFAGiF;AACjF,SAAS,aAAa,CAAC,KAAuC;IAC5D,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAA,wBAAU,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtE,MAAM,GAAG,GAAG,IAAA,2BAAa,EAAC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACvF,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,IAAA,wBAAU,EAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,GAA4B,CAAC;QACvC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,GAAG,iBAAiB,EAAE,CAAC;QAC7E,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,GAAG,qBAAqB,EAAE,CAAC;QAClF,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,GAAG,uBAAuB,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC;IAClF,CAAC;IACD,MAAM,IAAI,GAAG,KAAK;SACf,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACvD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IACL,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,OAAO,IAAA,wBAAQ,EAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;IAChH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,8DAA8D;QAC9D,OAAQ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAyB,CAAC,OAAO,CAAC;IAC1G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,IAAA,yBAAgB,EACd,IAAI,EACJ,cAAc,EACd,2CAA2C,EAC3C,kFAAkF,EAClF;QACE,uEAAuE;QACvE,4EAA4E;QAC5E,sDAAsD;QACtD,EAAE;QACF,+DAA+D;KAChE,CACF,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,KAAuC;IAC1E,4EAA4E;IAC5E,wEAAwE;IACxE,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACxB,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAEpF,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACtC,4EAA4E;IAC5E,0DAA0D;IAC1D,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACnE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACtB,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,aAAa,QAAQ,MAAM,IAAI,CAAC,CAAC;YAClF,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;SAAM,CAAC;QACN,sCAAsC;QACtC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3C,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,MAAM,IAAI,CAAC,CAAC;YAC7D,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IACrD,QAAQ,CAAC,IAAI,CACX,2EAA2E;QACzE,+EAA+E;QAC/E,gFAAgF;QAChF,sDAAsD,CACzD,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC1D,QAAQ,CAAC,IAAI,CAAC,mBAAmB,cAAc,EAAE,EAAE,CAAC,CAAC;IACrD,QAAQ,CAAC,IAAI,CAAC,sBAAsB,iBAAiB,EAAE,EAAE,CAAC,CAAC;IAC3D,QAAQ,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrE,QAAQ,CAAC,IAAI,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAElB,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,iBAAkB,GAAa,CAAC,OAAO,OAAO,CAAC,CAAC;YACxF,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,MAAM,wBAAwB,CAAC,CAAC;QACnF,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,KAAK,MAAM,CAAC,CAAC;IACtE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,OAAO,IAAI;QAChC,kJAAkJ,CACrJ,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA2C,MAAM,gBAAgB,CAAC;AAmCxF,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAwG/G"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runDoctor = runDoctor;
|
|
4
|
+
const http_client_1 = require("../http-client");
|
|
5
|
+
const health_1 = require("../health");
|
|
6
|
+
const manager_1 = require("../manager");
|
|
7
|
+
const output_1 = require("../output");
|
|
8
|
+
const colors_1 = require("../colors");
|
|
9
|
+
function printHelp() {
|
|
10
|
+
const c = (0, colors_1.paletteFor)((0, output_1.helpStream)(true));
|
|
11
|
+
(0, output_1.writeCommandHelp)(true, 'doctor', 'check config, key resolution, manager and connectivity', 'claude-gateway doctor [--url <url>] [--key <key>] [--config <path>] [--json]', [
|
|
12
|
+
` Exits 0 when every check passes. Rows marked ${c.dim('[--]')} are informational and`,
|
|
13
|
+
' never fail the command. The key itself is never printed.',
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
16
|
+
async function runDoctor(flags, config) {
|
|
17
|
+
if (flags.help === true) {
|
|
18
|
+
printHelp();
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
const checks = [];
|
|
22
|
+
const hasKeys = !!(config.keys && config.keys.length);
|
|
23
|
+
checks.push({ name: 'config', ok: hasKeys, detail: hasKeys ? `${config.keys.length} api key(s)` : 'no config / no api keys found' });
|
|
24
|
+
const key = (0, http_client_1.resolveKey)({ flagKey: typeof flags.key === 'string' ? flags.key : undefined, env: process.env, config });
|
|
25
|
+
checks.push({ name: 'apiKey', ok: !!key, detail: key ? 'resolved (hidden)' : 'none resolved (set --key or $CLAUDE_GATEWAY_API_KEY)' });
|
|
26
|
+
const flagUrl = typeof flags.url === 'string' ? flags.url : undefined;
|
|
27
|
+
// The URL the CLI's own API calls will use — that is what `doctor` diagnoses,
|
|
28
|
+
// so `health` reports on this one and only this one decides the exit code.
|
|
29
|
+
const baseUrl = (0, http_client_1.resolveUrl)({ flagUrl, env: process.env, config });
|
|
30
|
+
checks.push({ name: 'url', ok: true, detail: baseUrl });
|
|
31
|
+
// Resolved once and shared with the alt-address block below: both ask the
|
|
32
|
+
// same question ("where does the gateway on this host listen?") and reading
|
|
33
|
+
// the pidfile twice could answer it two different ways mid-command.
|
|
34
|
+
const localUrl = (0, http_client_1.resolveLocalUrl)({ env: process.env, config });
|
|
35
|
+
const manager = (0, manager_1.detectManager)();
|
|
36
|
+
// How the gateway on THIS host is supervised is a verdict only while this
|
|
37
|
+
// host is what is being diagnosed. Pointed at another gateway (--url or
|
|
38
|
+
// $CLAUDE_GATEWAY_URL), a laptop with no local install reports `unknown` and
|
|
39
|
+
// used to fail the whole command even though config, key, url and health all
|
|
40
|
+
// passed — the same false verdict this command already avoids for the
|
|
41
|
+
// publicHealth row.
|
|
42
|
+
const diagnosingThisHost = baseUrl === localUrl;
|
|
43
|
+
checks.push({
|
|
44
|
+
name: 'manager',
|
|
45
|
+
ok: manager !== 'unknown',
|
|
46
|
+
detail: diagnosingThisHost ? manager : `${manager} (local; not the target of this check)`,
|
|
47
|
+
info: !diagnosingThisHost,
|
|
48
|
+
});
|
|
49
|
+
const health = await (0, health_1.probeHealth)(baseUrl);
|
|
50
|
+
checks.push({ name: 'health', ok: health.ok, detail: health.detail });
|
|
51
|
+
// A gateway fronted by a reverse proxy has two addresses for one process.
|
|
52
|
+
// Probe the one the CLI is *not* using as well: without it, the most
|
|
53
|
+
// confusing states — proxy down while the gateway is healthy, or the reverse
|
|
54
|
+
// — appear as a single contradictory line with nothing to explain it. The
|
|
55
|
+
// second probe is informational: the CLI does not use that address, so its
|
|
56
|
+
// state must not decide this command's exit code.
|
|
57
|
+
// Deliberately resolved without `flagUrl`: this is the address of the gateway
|
|
58
|
+
// *on this host*, which is the useful context when the CLI has been pointed
|
|
59
|
+
// somewhere else. Passing the flag through would make it echo the target back
|
|
60
|
+
// as its own alternative, and then offer this host's publicUrl as context for
|
|
61
|
+
// a question about another host entirely.
|
|
62
|
+
const publicUrl = (config.publicUrl ?? '').replace(/\/+$/, '');
|
|
63
|
+
const alt = baseUrl === localUrl
|
|
64
|
+
? publicUrl && publicUrl !== baseUrl
|
|
65
|
+
? { urlName: 'publicUrl', healthName: 'publicHealth', url: publicUrl }
|
|
66
|
+
: undefined
|
|
67
|
+
: manager !== 'unknown'
|
|
68
|
+
? { urlName: 'localUrl', healthName: 'localHealth', url: localUrl }
|
|
69
|
+
: undefined;
|
|
70
|
+
let altHealth;
|
|
71
|
+
if (alt) {
|
|
72
|
+
checks.push({ name: alt.urlName, ok: true, detail: alt.url, info: true });
|
|
73
|
+
altHealth = await (0, health_1.probeHealth)(alt.url);
|
|
74
|
+
checks.push({ name: alt.healthName, ok: altHealth.ok, detail: altHealth.detail, info: true });
|
|
75
|
+
}
|
|
76
|
+
const allOk = checks.every((c) => c.info || c.ok);
|
|
77
|
+
const c = (0, colors_1.paletteFor)(process.stderr);
|
|
78
|
+
// Pad before colouring so escape codes never count toward the column width.
|
|
79
|
+
const lines = checks.map((chk) => {
|
|
80
|
+
// `info` is checked first: an advisory row is marked `[--]` whether it
|
|
81
|
+
// passed or not, so the reader can tell the verdict rows from the context.
|
|
82
|
+
const mark = chk.info ? c.dim('[--]') : chk.ok ? c.green('[ok]') : c.red('[!!]');
|
|
83
|
+
return ` ${mark} ${c.bold(chk.name.padEnd(12))} ${chk.detail}`;
|
|
84
|
+
});
|
|
85
|
+
// Name the right component. A public URL that answered with a status is not
|
|
86
|
+
// an unreachable proxy, it is a reachable one rejecting the request — and a
|
|
87
|
+
// proxy that requires its own credentials is doing its job, not failing.
|
|
88
|
+
if (alt && altHealth) {
|
|
89
|
+
if (alt.urlName === 'publicUrl' && health.ok && !altHealth.ok) {
|
|
90
|
+
lines.push(` ${c.yellow(altHealth.answered
|
|
91
|
+
? `note: the CLI is using the local address; the public URL answered HTTP ${altHealth.status}, so the proxy in front of the gateway rejected an unauthenticated request. External clients are unaffected if they authenticate with the proxy.`
|
|
92
|
+
: 'note: the CLI is using the local address; the public URL did not answer at all — external clients would not reach the gateway.')}`);
|
|
93
|
+
}
|
|
94
|
+
else if (alt.urlName === 'localUrl' && altHealth.ok && !health.ok) {
|
|
95
|
+
lines.push(` ${c.yellow(health.answered
|
|
96
|
+
? `note: the gateway is up locally, but the URL the CLI was told to use answered HTTP ${health.status} — the proxy in front of it rejected this request. Drop --url / $CLAUDE_GATEWAY_URL to use ${localUrl} instead.`
|
|
97
|
+
: `note: the gateway is up locally but the URL the CLI was told to use did not answer. Drop --url / $CLAUDE_GATEWAY_URL to use ${localUrl} instead.`)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
process.stderr.write([`${c.bold('claude-gateway doctor')}`, ...lines, ''].join('\n'));
|
|
101
|
+
(0, output_1.printJson)({ ok: allOk, checks }, flags);
|
|
102
|
+
return allOk ? 0 : 1;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CliConfigView } from '../http-client';
|
|
2
|
+
/**
|
|
3
|
+
* `gateway start|status|restart|stop` — whole-process lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* `start` is handled by the boot entry point (src/index.ts), which recognises
|
|
6
|
+
* it before the CLI is ever imported; it is listed here only so the usage text
|
|
7
|
+
* and an unknown-verb error stay honest. Restart/stop must be performed by
|
|
8
|
+
* whatever manager owns the process (it has to stop the very process serving
|
|
9
|
+
* HTTP), so detection resolves the manager and the action is delegated to it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function runGatewayLifecycle(positionals: string[], flags: Record<string, string | boolean>, config: CliConfigView): Promise<number>;
|
|
12
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/gateway.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAmB,MAAM,gBAAgB,CAAC;AAMhE;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EAAE,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
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.runGatewayLifecycle = runGatewayLifecycle;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const http_client_1 = require("../http-client");
|
|
40
|
+
const health_1 = require("../health");
|
|
41
|
+
const manager_1 = require("../manager");
|
|
42
|
+
const output_1 = require("../output");
|
|
43
|
+
const output_2 = require("../output");
|
|
44
|
+
/**
|
|
45
|
+
* `gateway start|status|restart|stop` — whole-process lifecycle.
|
|
46
|
+
*
|
|
47
|
+
* `start` is handled by the boot entry point (src/index.ts), which recognises
|
|
48
|
+
* it before the CLI is ever imported; it is listed here only so the usage text
|
|
49
|
+
* and an unknown-verb error stay honest. Restart/stop must be performed by
|
|
50
|
+
* whatever manager owns the process (it has to stop the very process serving
|
|
51
|
+
* HTTP), so detection resolves the manager and the action is delegated to it.
|
|
52
|
+
*/
|
|
53
|
+
async function runGatewayLifecycle(positionals, flags, config) {
|
|
54
|
+
const verb = positionals[0];
|
|
55
|
+
if (!verb) {
|
|
56
|
+
// `gateway --help` is a help request (0); a bare `gateway` is a usage error (1).
|
|
57
|
+
(0, output_2.writeCommandHelp)(flags.help === true, 'gateway', 'manage the gateway process on this host', 'claude-gateway gateway <start|status|restart|stop>', [' start is the only command that boots a server; the rest are manager-aware.']);
|
|
58
|
+
return flags.help === true ? 0 : 1;
|
|
59
|
+
}
|
|
60
|
+
switch (verb) {
|
|
61
|
+
case 'start':
|
|
62
|
+
// Only reachable when runCli() is called directly (tests, embedding) —
|
|
63
|
+
// the installed binary routes `gateway start` straight into the server.
|
|
64
|
+
process.stderr.write('`gateway start` is handled by the claude-gateway entry point, not the CLI runner.\n');
|
|
65
|
+
return 1;
|
|
66
|
+
case 'status':
|
|
67
|
+
return gatewayStatus(flags, config);
|
|
68
|
+
case 'restart':
|
|
69
|
+
return gatewayAction('restart');
|
|
70
|
+
case 'stop':
|
|
71
|
+
return gatewayAction('stop');
|
|
72
|
+
default:
|
|
73
|
+
process.stderr.write(`Unknown: gateway ${verb} (expected start|status|restart|stop)\n`);
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function gatewayStatus(flags, config) {
|
|
78
|
+
const manager = (0, manager_1.detectManager)();
|
|
79
|
+
// `manager` describes the process on this host, so `health` must too:
|
|
80
|
+
// probing config.publicUrl would report a reverse proxy (possibly fronting a
|
|
81
|
+
// different instance) rather than the gateway this command just detected.
|
|
82
|
+
const baseUrl = (0, http_client_1.resolveLocalUrl)({ flagUrl: typeof flags.url === 'string' ? flags.url : undefined, env: process.env, config });
|
|
83
|
+
// `detail` carries what `health` cannot: an address answering 401 or 500 is
|
|
84
|
+
// not the same failure as one answering nothing, and collapsing both into
|
|
85
|
+
// "down" throws away the only clue about which one it is.
|
|
86
|
+
const probe = await (0, health_1.probeHealth)(baseUrl);
|
|
87
|
+
(0, output_1.printJson)({ manager, url: baseUrl, health: probe.ok ? 'up' : 'down', detail: probe.detail }, flags);
|
|
88
|
+
return probe.ok ? 0 : 1;
|
|
89
|
+
}
|
|
90
|
+
function gatewayAction(action) {
|
|
91
|
+
const manager = (0, manager_1.detectManager)();
|
|
92
|
+
try {
|
|
93
|
+
switch (manager) {
|
|
94
|
+
case 'systemd-user':
|
|
95
|
+
(0, child_process_1.execFileSync)('systemctl', ['--user', action, 'claude-gateway.service'], { stdio: 'inherit' });
|
|
96
|
+
return Promise.resolve(0);
|
|
97
|
+
case 'systemd-system': {
|
|
98
|
+
// A system-scoped unit needs root; announce the escalation instead of
|
|
99
|
+
// silently invoking sudo, and skip it entirely when already root.
|
|
100
|
+
const needsSudo = typeof process.getuid === 'function' && process.getuid() !== 0;
|
|
101
|
+
if (needsSudo) {
|
|
102
|
+
process.stderr.write(`Using the system service (may require sudo): systemctl ${action} claude-gateway.service\n`);
|
|
103
|
+
(0, child_process_1.execFileSync)('sudo', ['systemctl', action, 'claude-gateway.service'], { stdio: 'inherit' });
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
(0, child_process_1.execFileSync)('systemctl', [action, 'claude-gateway.service'], { stdio: 'inherit' });
|
|
107
|
+
}
|
|
108
|
+
return Promise.resolve(0);
|
|
109
|
+
}
|
|
110
|
+
case 'pm2':
|
|
111
|
+
(0, child_process_1.execFileSync)('pm2', [action, 'gateway'], { stdio: 'inherit' });
|
|
112
|
+
return Promise.resolve(0);
|
|
113
|
+
case 'foreground': {
|
|
114
|
+
const pid = parseInt(fs.readFileSync((0, manager_1.defaultPidfilePath)(), 'utf8').trim(), 10);
|
|
115
|
+
// The pidfile only proves some process holds this pid. A gateway lost
|
|
116
|
+
// to SIGKILL or the OOM killer leaves the file behind, and once the pid
|
|
117
|
+
// is recycled this branch would SIGTERM an unrelated process and report
|
|
118
|
+
// success. Confirm it is a gateway before signalling it.
|
|
119
|
+
if (!(0, manager_1.pidLooksLikeGateway)(pid)) {
|
|
120
|
+
process.stderr.write(`Pidfile names pid ${pid}, but that process does not look like a gateway — refusing to signal it. ` +
|
|
121
|
+
`The gateway likely died without cleaning up; remove ${(0, manager_1.defaultPidfilePath)()} if it is stale.\n`);
|
|
122
|
+
return Promise.resolve(1);
|
|
123
|
+
}
|
|
124
|
+
process.kill(pid, 'SIGTERM');
|
|
125
|
+
if (action === 'restart') {
|
|
126
|
+
process.stderr.write('Stopped the foreground gateway (SIGTERM) but a bare foreground process has no supervisor to respawn it — ' +
|
|
127
|
+
'start it again with `claude-gateway gateway start`, or install a service with `claude-gateway service install`.\n');
|
|
128
|
+
// Only the "stop" half of restart happened — a caller/script checking
|
|
129
|
+
// the exit code should see this as incomplete, not a successful restart.
|
|
130
|
+
return Promise.resolve(1);
|
|
131
|
+
}
|
|
132
|
+
process.stderr.write(`Sent SIGTERM to gateway (pid ${pid}).\n`);
|
|
133
|
+
return Promise.resolve(0);
|
|
134
|
+
}
|
|
135
|
+
default:
|
|
136
|
+
process.stderr.write('Could not detect how the gateway is running (systemd-user/systemd-system/pm2/foreground). Nothing done.\n');
|
|
137
|
+
return Promise.resolve(1);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
process.stderr.write(`gateway ${action} failed: ${err.message}\n`);
|
|
142
|
+
return Promise.resolve(1);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=gateway.js.map
|