@zhixuan92/multi-model-agent 5.0.2 → 5.1.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 +14 -23
- package/dist/cli/index.d.ts +62 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +345 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/info.d.ts +22 -0
- package/dist/cli/info.d.ts.map +1 -0
- package/dist/cli/info.js +100 -0
- package/dist/cli/info.js.map +1 -0
- package/dist/cli/logs.d.ts +15 -0
- package/dist/cli/logs.d.ts.map +1 -0
- package/dist/cli/logs.js +102 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/print-token.d.ts +18 -0
- package/dist/cli/print-token.d.ts.map +1 -0
- package/dist/cli/print-token.js +60 -0
- package/dist/cli/print-token.js.map +1 -0
- package/dist/cli/serve.d.ts +28 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +405 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/status.d.ts +49 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +155 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/sync-skills.d.ts +58 -0
- package/dist/cli/sync-skills.d.ts.map +1 -0
- package/dist/cli/sync-skills.js +266 -0
- package/dist/cli/sync-skills.js.map +1 -0
- package/dist/cli/telemetry.d.ts +10 -0
- package/dist/cli/telemetry.d.ts.map +1 -0
- package/dist/cli/telemetry.js +161 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/toggle.d.ts +26 -0
- package/dist/cli/toggle.d.ts.map +1 -0
- package/dist/cli/toggle.js +185 -0
- package/dist/cli/toggle.js.map +1 -0
- package/dist/http/async-dispatch.d.ts +44 -0
- package/dist/http/async-dispatch.d.ts.map +1 -0
- package/dist/http/async-dispatch.js +175 -0
- package/dist/http/async-dispatch.js.map +1 -0
- package/dist/http/auth.d.ts +20 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +56 -0
- package/dist/http/auth.js.map +1 -0
- package/dist/http/canonicalize-file-paths.d.ts +8 -0
- package/dist/http/canonicalize-file-paths.d.ts.map +1 -0
- package/dist/http/canonicalize-file-paths.js +43 -0
- package/dist/http/canonicalize-file-paths.js.map +1 -0
- package/dist/http/cwd-validator.d.ts +11 -0
- package/dist/http/cwd-validator.d.ts.map +1 -0
- package/dist/http/cwd-validator.js +130 -0
- package/dist/http/cwd-validator.js.map +1 -0
- package/dist/http/errors.d.ts +4 -0
- package/dist/http/errors.d.ts.map +1 -0
- package/dist/http/errors.js +9 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/http/execution-context.d.ts +18 -0
- package/dist/http/execution-context.d.ts.map +1 -0
- package/dist/http/execution-context.js +61 -0
- package/dist/http/execution-context.js.map +1 -0
- package/dist/http/handler-deps.d.ts +19 -0
- package/dist/http/handler-deps.d.ts.map +1 -0
- package/dist/http/handler-deps.js +2 -0
- package/dist/http/handler-deps.js.map +1 -0
- package/dist/http/handlers/control/batch-slice.d.ts +4 -0
- package/dist/http/handlers/control/batch-slice.d.ts.map +1 -0
- package/dist/http/handlers/control/batch-slice.js +40 -0
- package/dist/http/handlers/control/batch-slice.js.map +1 -0
- package/dist/http/handlers/control/batch.d.ts +23 -0
- package/dist/http/handlers/control/batch.d.ts.map +1 -0
- package/dist/http/handlers/control/batch.js +332 -0
- package/dist/http/handlers/control/batch.js.map +1 -0
- package/dist/http/handlers/control/context-blocks.d.ts +22 -0
- package/dist/http/handlers/control/context-blocks.d.ts.map +1 -0
- package/dist/http/handlers/control/context-blocks.js +111 -0
- package/dist/http/handlers/control/context-blocks.js.map +1 -0
- package/dist/http/handlers/introspection/health.d.ts +20 -0
- package/dist/http/handlers/introspection/health.d.ts.map +1 -0
- package/dist/http/handlers/introspection/health.js +18 -0
- package/dist/http/handlers/introspection/health.js.map +1 -0
- package/dist/http/handlers/introspection/status.d.ts +26 -0
- package/dist/http/handlers/introspection/status.d.ts.map +1 -0
- package/dist/http/handlers/introspection/status.js +136 -0
- package/dist/http/handlers/introspection/status.js.map +1 -0
- package/dist/http/handlers/tools/audit.d.ts +4 -0
- package/dist/http/handlers/tools/audit.d.ts.map +1 -0
- package/dist/http/handlers/tools/audit.js +43 -0
- package/dist/http/handlers/tools/audit.js.map +1 -0
- package/dist/http/handlers/tools/debug.d.ts +4 -0
- package/dist/http/handlers/tools/debug.d.ts.map +1 -0
- package/dist/http/handlers/tools/debug.js +43 -0
- package/dist/http/handlers/tools/debug.js.map +1 -0
- package/dist/http/handlers/tools/delegate.d.ts +4 -0
- package/dist/http/handlers/tools/delegate.d.ts.map +1 -0
- package/dist/http/handlers/tools/delegate.js +43 -0
- package/dist/http/handlers/tools/delegate.js.map +1 -0
- package/dist/http/handlers/tools/execute-plan.d.ts +4 -0
- package/dist/http/handlers/tools/execute-plan.d.ts.map +1 -0
- package/dist/http/handlers/tools/execute-plan.js +45 -0
- package/dist/http/handlers/tools/execute-plan.js.map +1 -0
- package/dist/http/handlers/tools/investigate.d.ts +4 -0
- package/dist/http/handlers/tools/investigate.d.ts.map +1 -0
- package/dist/http/handlers/tools/investigate.js +64 -0
- package/dist/http/handlers/tools/investigate.js.map +1 -0
- package/dist/http/handlers/tools/journal-recall.d.ts +4 -0
- package/dist/http/handlers/tools/journal-recall.d.ts.map +1 -0
- package/dist/http/handlers/tools/journal-recall.js +40 -0
- package/dist/http/handlers/tools/journal-recall.js.map +1 -0
- package/dist/http/handlers/tools/journal-record.d.ts +12 -0
- package/dist/http/handlers/tools/journal-record.d.ts.map +1 -0
- package/dist/http/handlers/tools/journal-record.js +43 -0
- package/dist/http/handlers/tools/journal-record.js.map +1 -0
- package/dist/http/handlers/tools/research.d.ts +4 -0
- package/dist/http/handlers/tools/research.d.ts.map +1 -0
- package/dist/http/handlers/tools/research.js +64 -0
- package/dist/http/handlers/tools/research.js.map +1 -0
- package/dist/http/handlers/tools/retry.d.ts +4 -0
- package/dist/http/handlers/tools/retry.d.ts.map +1 -0
- package/dist/http/handlers/tools/retry.js +49 -0
- package/dist/http/handlers/tools/retry.js.map +1 -0
- package/dist/http/handlers/tools/review.d.ts +4 -0
- package/dist/http/handlers/tools/review.d.ts.map +1 -0
- package/dist/http/handlers/tools/review.js +43 -0
- package/dist/http/handlers/tools/review.js.map +1 -0
- package/dist/http/middleware/body-reader.d.ts +16 -0
- package/dist/http/middleware/body-reader.d.ts.map +1 -0
- package/dist/http/middleware/body-reader.js +44 -0
- package/dist/http/middleware/body-reader.js.map +1 -0
- package/dist/http/middleware/caller-identity.d.ts +16 -0
- package/dist/http/middleware/caller-identity.d.ts.map +1 -0
- package/dist/http/middleware/caller-identity.js +16 -0
- package/dist/http/middleware/caller-identity.js.map +1 -0
- package/dist/http/middleware/decompress.d.ts +14 -0
- package/dist/http/middleware/decompress.d.ts.map +1 -0
- package/dist/http/middleware/decompress.js +51 -0
- package/dist/http/middleware/decompress.js.map +1 -0
- package/dist/http/project-registry.d.ts +54 -0
- package/dist/http/project-registry.d.ts.map +1 -0
- package/dist/http/project-registry.js +130 -0
- package/dist/http/project-registry.js.map +1 -0
- package/dist/http/request-observability.d.ts +8 -0
- package/dist/http/request-observability.d.ts.map +1 -0
- package/dist/http/request-observability.js +20 -0
- package/dist/http/request-observability.js.map +1 -0
- package/dist/http/request-pipeline.d.ts +16 -0
- package/dist/http/request-pipeline.d.ts.map +1 -0
- package/dist/http/request-pipeline.js +144 -0
- package/dist/http/request-pipeline.js.map +1 -0
- package/dist/http/server.d.ts +17 -0
- package/dist/http/server.d.ts.map +1 -0
- package/dist/http/server.js +300 -0
- package/dist/http/server.js.map +1 -0
- package/dist/http/types.d.ts +20 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +2 -0
- package/dist/http/types.js.map +1 -0
- package/dist/skill-install/disabled-state.d.ts +35 -0
- package/dist/skill-install/disabled-state.d.ts.map +1 -0
- package/dist/skill-install/disabled-state.js +96 -0
- package/dist/skill-install/disabled-state.js.map +1 -0
- package/dist/skill-install/discover.d.ts +29 -0
- package/dist/skill-install/discover.d.ts.map +1 -0
- package/dist/skill-install/discover.js +104 -0
- package/dist/skill-install/discover.js.map +1 -0
- package/dist/skill-install/include-utils.d.ts +27 -0
- package/dist/skill-install/include-utils.d.ts.map +1 -0
- package/dist/skill-install/include-utils.js +90 -0
- package/dist/skill-install/include-utils.js.map +1 -0
- package/dist/skill-install/manifest.d.ts +82 -0
- package/dist/skill-install/manifest.d.ts.map +1 -0
- package/dist/skill-install/manifest.js +215 -0
- package/dist/skill-install/manifest.js.map +1 -0
- package/dist/skill-install/skill-installer-common.d.ts +26 -0
- package/dist/skill-install/skill-installer-common.d.ts.map +1 -0
- package/dist/skill-install/skill-installer-common.js +139 -0
- package/dist/skill-install/skill-installer-common.js.map +1 -0
- package/dist/skill-install/skill-installers/claude-code.d.ts +43 -0
- package/dist/skill-install/skill-installers/claude-code.d.ts.map +1 -0
- package/dist/skill-install/skill-installers/claude-code.js +65 -0
- package/dist/skill-install/skill-installers/claude-code.js.map +1 -0
- package/dist/skill-install/skill-installers/codex-cli.d.ts +27 -0
- package/dist/skill-install/skill-installers/codex-cli.d.ts.map +1 -0
- package/dist/skill-install/skill-installers/codex-cli.js +84 -0
- package/dist/skill-install/skill-installers/codex-cli.js.map +1 -0
- package/dist/skill-install/skill-installers/cursor.d.ts +72 -0
- package/dist/skill-install/skill-installers/cursor.d.ts.map +1 -0
- package/dist/skill-install/skill-installers/cursor.js +81 -0
- package/dist/skill-install/skill-installers/cursor.js.map +1 -0
- package/dist/skill-install/skill-installers/gemini-cli.d.ts +50 -0
- package/dist/skill-install/skill-installers/gemini-cli.d.ts.map +1 -0
- package/dist/skill-install/skill-installers/gemini-cli.js +72 -0
- package/dist/skill-install/skill-installers/gemini-cli.js.map +1 -0
- package/dist/skill-install/skill-manifest-sync.d.ts +11 -0
- package/dist/skill-install/skill-manifest-sync.d.ts.map +1 -0
- package/dist/skill-install/skill-manifest-sync.js +65 -0
- package/dist/skill-install/skill-manifest-sync.js.map +1 -0
- package/dist/skills/_shared/auth.md +41 -0
- package/dist/skills/_shared/error-handling.md +31 -0
- package/dist/skills/_shared/polling.md +88 -0
- package/dist/skills/_shared/response-shape.md +55 -0
- package/dist/skills/_shared/review-policy.md +15 -0
- package/dist/skills/mma-audit/SKILL.md +270 -0
- package/dist/skills/mma-context-blocks/SKILL.md +148 -0
- package/dist/skills/mma-debug/SKILL.md +208 -0
- package/dist/skills/mma-delegate/SKILL.md +216 -0
- package/dist/skills/mma-execute-plan/SKILL.md +214 -0
- package/dist/skills/mma-explore/SKILL.md +190 -0
- package/dist/skills/mma-investigate/SKILL.md +258 -0
- package/dist/skills/mma-journal-recall/SKILL.md +242 -0
- package/dist/skills/mma-journal-record/SKILL.md +202 -0
- package/dist/skills/mma-research/SKILL.md +223 -0
- package/dist/skills/mma-retry/SKILL.md +221 -0
- package/dist/skills/mma-review/SKILL.md +209 -0
- package/dist/skills/multi-model-agent/SKILL.md +206 -0
- package/dist/telemetry/consent.d.ts +4 -0
- package/dist/telemetry/consent.d.ts.map +1 -0
- package/dist/telemetry/consent.js +40 -0
- package/dist/telemetry/consent.js.map +1 -0
- package/dist/telemetry/flusher.d.ts +19 -0
- package/dist/telemetry/flusher.d.ts.map +1 -0
- package/dist/telemetry/flusher.js +277 -0
- package/dist/telemetry/flusher.js.map +1 -0
- package/dist/telemetry/generation.d.ts +9 -0
- package/dist/telemetry/generation.d.ts.map +1 -0
- package/dist/telemetry/generation.js +33 -0
- package/dist/telemetry/generation.js.map +1 -0
- package/dist/telemetry/identity.d.ts +9 -0
- package/dist/telemetry/identity.d.ts.map +1 -0
- package/dist/telemetry/identity.js +35 -0
- package/dist/telemetry/identity.js.map +1 -0
- package/dist/telemetry/install-id.d.ts +13 -0
- package/dist/telemetry/install-id.d.ts.map +1 -0
- package/dist/telemetry/install-id.js +49 -0
- package/dist/telemetry/install-id.js.map +1 -0
- package/dist/telemetry/install-meta.d.ts +10 -0
- package/dist/telemetry/install-meta.d.ts.map +1 -0
- package/dist/telemetry/install-meta.js +15 -0
- package/dist/telemetry/install-meta.js.map +1 -0
- package/dist/telemetry/queue.d.ts +35 -0
- package/dist/telemetry/queue.d.ts.map +1 -0
- package/dist/telemetry/queue.js +287 -0
- package/dist/telemetry/queue.js.map +1 -0
- package/dist/telemetry/recorder.d.ts +39 -0
- package/dist/telemetry/recorder.d.ts.map +1 -0
- package/dist/telemetry/recorder.js +173 -0
- package/dist/telemetry/recorder.js.map +1 -0
- package/package.json +43 -24
- package/scripts/postinstall.js +36 -0
- package/bin/mmagent.mjs +0 -47
- package/postinstall.mjs +0 -8
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* serve.ts — starts the HTTP server and manages its signal lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* This module owns the complete serve lifecycle: starting the HTTP server,
|
|
5
|
+
* registering SIGTERM/SIGINT handlers, draining in-flight requests, and
|
|
6
|
+
* cleanly exiting the process. The CLI entry point (cli/index.ts) delegates
|
|
7
|
+
* to this module and does not manage signals directly.
|
|
8
|
+
*
|
|
9
|
+
* Usage (library):
|
|
10
|
+
* const handle = await startServe(config);
|
|
11
|
+
* // server is running on handle.port
|
|
12
|
+
* await handle.stop(); // graceful shutdown; no process.exit
|
|
13
|
+
*
|
|
14
|
+
* Usage (CLI):
|
|
15
|
+
* mmagent serve [--config <path>]
|
|
16
|
+
* // this module owns signal handling and process.exit
|
|
17
|
+
*/
|
|
18
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import * as fs from 'node:fs';
|
|
21
|
+
import * as os from 'node:os';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { collectInlineApiKeyOffenders, loadAuthToken } from '@zhixuan92/multi-model-agent-core';
|
|
24
|
+
import { startServer } from '../http/server.js';
|
|
25
|
+
import { setDraining } from '../http/request-pipeline.js';
|
|
26
|
+
import { createRecorder } from '../telemetry/recorder.js';
|
|
27
|
+
import { Flusher } from '../telemetry/flusher.js';
|
|
28
|
+
import { Queue } from '../telemetry/queue.js';
|
|
29
|
+
import { runSyncSkills } from './sync-skills.js';
|
|
30
|
+
import { listEntries, FutureManifestError } from '../skill-install/manifest.js';
|
|
31
|
+
import { readSkillContent, SUPPORTED_SKILLS } from '../skill-install/discover.js';
|
|
32
|
+
import { findMissingSkills } from '../skill-install/skill-installer-common.js';
|
|
33
|
+
import matter from 'gray-matter';
|
|
34
|
+
function isSkillBehind(entryName, entrySkillVersion) {
|
|
35
|
+
const src = readSkillContent(entryName);
|
|
36
|
+
if (src === null)
|
|
37
|
+
return false; // skill removed from bundle — sync-skills will drop it
|
|
38
|
+
try {
|
|
39
|
+
const parsed = matter(src);
|
|
40
|
+
const v = parsed.data['version'];
|
|
41
|
+
return typeof v === 'string' && v !== entrySkillVersion;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function maybeAutoUpdateSkills(config, stderr) {
|
|
48
|
+
let entries;
|
|
49
|
+
try {
|
|
50
|
+
entries = listEntries();
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err instanceof FutureManifestError) {
|
|
54
|
+
stderr(`[mmagent] warning: ${err.message}; skipping skill auto-sync\n`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
return; // best-effort — never let manifest IO issues block serve
|
|
58
|
+
}
|
|
59
|
+
const behind = entries.filter((e) => isSkillBehind(e.name, e.skillVersion));
|
|
60
|
+
const missing = findMissingSkills(entries, SUPPORTED_SKILLS);
|
|
61
|
+
if (behind.length === 0 && missing.length === 0)
|
|
62
|
+
return;
|
|
63
|
+
if (!config.server.autoUpdateSkills) {
|
|
64
|
+
const drift = [];
|
|
65
|
+
if (behind.length > 0)
|
|
66
|
+
drift.push(`${behind.length} out of date (${behind.map((e) => e.name).join(', ')})`);
|
|
67
|
+
if (missing.length > 0)
|
|
68
|
+
drift.push(`${missing.length} new (${missing.map((m) => m.name).join(', ')})`);
|
|
69
|
+
stderr(`[mmagent] skill drift: ${drift.join('; ')}. ` +
|
|
70
|
+
`Run 'mmagent sync-skills' to reconcile (or set server.autoUpdateSkills=true in config).\n`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const deadlineMs = 5000;
|
|
74
|
+
try {
|
|
75
|
+
await Promise.race([
|
|
76
|
+
runSyncSkills({ silent: true, bestEffort: true, ifExists: true }),
|
|
77
|
+
new Promise((resolve) => setTimeout(() => resolve(), deadlineMs)),
|
|
78
|
+
]);
|
|
79
|
+
if (behind.length > 0)
|
|
80
|
+
process.stdout.write(`[mmagent] auto-synced ${behind.length} updated skill(s)\n`);
|
|
81
|
+
if (missing.length > 0)
|
|
82
|
+
process.stdout.write(`[mmagent] auto-synced ${missing.length} new skill(s): ${missing.map((m) => m.name).join(', ')}\n`);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// bestEffort swallows inside; extra safety here.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function readServerVersion() {
|
|
89
|
+
try {
|
|
90
|
+
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
91
|
+
const pkgPath = path.join(thisDir, '..', '..', 'package.json');
|
|
92
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
93
|
+
return pkg.version ?? '0.0.0';
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return '0.0.0';
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function envVarHint(agentName) {
|
|
100
|
+
return `${agentName.toUpperCase().replace(/[^A-Z0-9]/g, '_')}_API_KEY`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Shared signal-state used to deduplicate shutdown if two signals arrive
|
|
104
|
+
* before stop() resolves.
|
|
105
|
+
*/
|
|
106
|
+
let stopInFlight = false;
|
|
107
|
+
// Stored so they can be removed when stop() is called programmatically
|
|
108
|
+
let onSigterm;
|
|
109
|
+
let onSigint;
|
|
110
|
+
let onStdoutErrorRef;
|
|
111
|
+
let onStderrErrorRef;
|
|
112
|
+
let onUncaughtRef;
|
|
113
|
+
let onUnhandledRejectionRef;
|
|
114
|
+
/**
|
|
115
|
+
* Start the HTTP server with the given config.
|
|
116
|
+
*
|
|
117
|
+
* Registers SIGTERM and SIGINT handlers that drain in-flight requests and
|
|
118
|
+
* exit the process cleanly. If config includes `server.limits.shutdownDrainMs`,
|
|
119
|
+
* the server will wait up to that duration for in-flight requests to finish.
|
|
120
|
+
*
|
|
121
|
+
* @param config Full MultiModelConfig (includes agents.*, defaults, diagnostics,
|
|
122
|
+
* and server block). startServer() inspects the agents.* field
|
|
123
|
+
* and enables real tool handlers when present.
|
|
124
|
+
* @param exit Process exit function — defaults to process.exit.
|
|
125
|
+
* Exposed so tests can suppress actual exits.
|
|
126
|
+
*/
|
|
127
|
+
export async function startServe(config, exit = process.exit.bind(process)) {
|
|
128
|
+
const stderr = process.stderr.write.bind(process.stderr);
|
|
129
|
+
// Auto-update installed skills before bind (bounded 5s; never blocks indefinitely).
|
|
130
|
+
await maybeAutoUpdateSkills(config, stderr);
|
|
131
|
+
// Drift check — warn if installed skills don't match the canonical manifest.
|
|
132
|
+
try {
|
|
133
|
+
const { makeSkillManifestSync } = await import('../skill-install/skill-manifest-sync.js');
|
|
134
|
+
const { discoverPerClientInstallDirs } = await import('../skill-install/discover.js');
|
|
135
|
+
const sync = makeSkillManifestSync(discoverPerClientInstallDirs());
|
|
136
|
+
const drift = sync.driftReport();
|
|
137
|
+
if (drift.length > 0) {
|
|
138
|
+
const summary = drift.map(d => `${d.client}/${d.skill}=${d.issue}`).join(', ');
|
|
139
|
+
stderr(`[mmagent] WARN: skill manifest drift detected: ${summary}. Re-run 'mmagent sync-skills' to reconcile.\n`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// best-effort — never let drift check block serve
|
|
144
|
+
}
|
|
145
|
+
// Create the telemetry recorder BEFORE startServer. The server's bus
|
|
146
|
+
// subscriber (TelemetryUploader) calls getRecorder() during startServer →
|
|
147
|
+
// if recorder is null at that moment, the uploader is wired with
|
|
148
|
+
// recorder=null and silently drops every event for the daemon's lifetime.
|
|
149
|
+
const homeDir = path.join(os.homedir(), '.multi-model');
|
|
150
|
+
const mmagentVersion = readServerVersion();
|
|
151
|
+
createRecorder({ homeDir, mmagentVersion });
|
|
152
|
+
// Pass the full MultiModelConfig (not just the server block) so
|
|
153
|
+
// registerToolHandlers sees `agents` and registers real tool endpoints.
|
|
154
|
+
// Stripping to { server } here caused a 3.1.0 regression where tool
|
|
155
|
+
// endpoints returned 503 'no_agent_config' even when agents were set.
|
|
156
|
+
const running = await startServer(config);
|
|
157
|
+
// ── stdout/stderr error + uncaught/unhandled rejection guards ────────
|
|
158
|
+
const logShutdown = (_cause) => {
|
|
159
|
+
// Option A: no diagnostics surface today. Cause name routed via stderr only.
|
|
160
|
+
// Option B (follow-up): wire running.diagnostics?.shutdown(_cause) here.
|
|
161
|
+
};
|
|
162
|
+
const onStdoutError = (err) => {
|
|
163
|
+
if (err.code === 'EPIPE') {
|
|
164
|
+
logShutdown('stdout_epipe');
|
|
165
|
+
exit(0);
|
|
166
|
+
}
|
|
167
|
+
logShutdown('stdout_other_error');
|
|
168
|
+
try {
|
|
169
|
+
process.stderr.write(`[mmagent] stdout error: ${err.message}\n`);
|
|
170
|
+
}
|
|
171
|
+
catch { /* stderr may also be dead */ }
|
|
172
|
+
exit(1);
|
|
173
|
+
};
|
|
174
|
+
const onStderrError = (err) => {
|
|
175
|
+
if (err.code === 'EPIPE') {
|
|
176
|
+
logShutdown('stdout_epipe');
|
|
177
|
+
exit(0);
|
|
178
|
+
}
|
|
179
|
+
logShutdown('stdout_other_error');
|
|
180
|
+
exit(1);
|
|
181
|
+
};
|
|
182
|
+
const onUncaught = (err) => {
|
|
183
|
+
const errno = err?.code;
|
|
184
|
+
if (errno === 'EPIPE') {
|
|
185
|
+
logShutdown('stdout_epipe');
|
|
186
|
+
exit(0);
|
|
187
|
+
}
|
|
188
|
+
logShutdown('uncaughtException');
|
|
189
|
+
try {
|
|
190
|
+
const msg = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
191
|
+
process.stderr.write(`[mmagent] uncaught exception: ${msg}\n`);
|
|
192
|
+
}
|
|
193
|
+
catch { /* best-effort */ }
|
|
194
|
+
exit(1);
|
|
195
|
+
};
|
|
196
|
+
const onUnhandledRejection = (reason) => {
|
|
197
|
+
const errno = reason?.code;
|
|
198
|
+
if (errno === 'EPIPE') {
|
|
199
|
+
logShutdown('stdout_epipe');
|
|
200
|
+
exit(0);
|
|
201
|
+
}
|
|
202
|
+
logShutdown('unhandledRejection');
|
|
203
|
+
try {
|
|
204
|
+
const msg = reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);
|
|
205
|
+
process.stderr.write(`[mmagent] unhandled rejection: ${msg}\n`);
|
|
206
|
+
}
|
|
207
|
+
catch { /* best-effort */ }
|
|
208
|
+
exit(1);
|
|
209
|
+
};
|
|
210
|
+
process.stdout.on('error', onStdoutError);
|
|
211
|
+
process.stderr.on('error', onStderrError);
|
|
212
|
+
process.on('uncaughtException', onUncaught);
|
|
213
|
+
process.on('unhandledRejection', onUnhandledRejection);
|
|
214
|
+
onStdoutErrorRef = onStdoutError;
|
|
215
|
+
onStderrErrorRef = onStderrError;
|
|
216
|
+
onUncaughtRef = onUncaught;
|
|
217
|
+
onUnhandledRejectionRef = onUnhandledRejection;
|
|
218
|
+
// Recorder was created above (BEFORE startServer). homeDir + mmagentVersion
|
|
219
|
+
// are computed there and reused here for the version-pin file + Flusher.
|
|
220
|
+
const lastVersionPath = path.join(homeDir, 'last-version');
|
|
221
|
+
let lastVersion = null;
|
|
222
|
+
try {
|
|
223
|
+
lastVersion = fs.readFileSync(lastVersionPath, 'utf8').trim();
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// first run — no last-version file yet
|
|
227
|
+
}
|
|
228
|
+
if (lastVersion !== mmagentVersion) {
|
|
229
|
+
try {
|
|
230
|
+
fs.mkdirSync(homeDir, { recursive: true });
|
|
231
|
+
fs.writeFileSync(lastVersionPath, mmagentVersion + '\n', { mode: 0o600 });
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
stderr(`[mmagent] warning: failed to write last-version at ${lastVersionPath}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Telemetry uploader. Default endpoint ships to the project's hosted
|
|
238
|
+
// dashboard. MMAGENT_TELEMETRY_ENDPOINT overrides for self-hosted backends;
|
|
239
|
+
// setting it to an empty string disables shipping entirely (events stay in
|
|
240
|
+
// ~/.multi-model/telemetry-queue.ndjson). The real off-switch for telemetry
|
|
241
|
+
// is the consent flag (MMAGENT_TELEMETRY=0 / config.telemetry.enabled =
|
|
242
|
+
// false) — when consent is off the recorder enqueues nothing, so the
|
|
243
|
+
// flusher's tick is a no-op even with the default endpoint set.
|
|
244
|
+
const DEFAULT_TELEMETRY_ENDPOINT = 'https://mma-telemetry-frontend.x1.lucazhang.work/v1/events';
|
|
245
|
+
const envEndpoint = process.env.MMAGENT_TELEMETRY_ENDPOINT;
|
|
246
|
+
const telemetryEndpoint = envEndpoint === undefined
|
|
247
|
+
? DEFAULT_TELEMETRY_ENDPOINT
|
|
248
|
+
: envEndpoint.trim();
|
|
249
|
+
let flusher = null;
|
|
250
|
+
if (telemetryEndpoint) {
|
|
251
|
+
flusher = new Flusher({
|
|
252
|
+
queue: new Queue(homeDir),
|
|
253
|
+
dir: homeDir,
|
|
254
|
+
endpoint: telemetryEndpoint,
|
|
255
|
+
});
|
|
256
|
+
flusher.start();
|
|
257
|
+
}
|
|
258
|
+
// Fire once at serve startup. Lives here (not in loadConfigFromFile) so
|
|
259
|
+
// print-token / info / status don't re-emit the same warning repeatedly.
|
|
260
|
+
const inlineOffenders = collectInlineApiKeyOffenders(config);
|
|
261
|
+
if (inlineOffenders.length > 0) {
|
|
262
|
+
const firstHint = envVarHint(inlineOffenders[0]);
|
|
263
|
+
stderr(`[mmagent] WARNING: inline apiKey in config for agent(s): ${inlineOffenders.join(', ')}.\n` +
|
|
264
|
+
` Fix:\n` +
|
|
265
|
+
` export ${firstHint}='<your-key>'\n` +
|
|
266
|
+
` # then in config.json, replace\n` +
|
|
267
|
+
` # "apiKey": "..."\n` +
|
|
268
|
+
` # with\n` +
|
|
269
|
+
` # "apiKeyEnv": "${firstHint}"\n`);
|
|
270
|
+
}
|
|
271
|
+
const cleanupSignal = (sig) => {
|
|
272
|
+
if (stopInFlight)
|
|
273
|
+
return;
|
|
274
|
+
stopInFlight = true;
|
|
275
|
+
stderr(`[mmagent] received ${sig}, shutting down gracefully\u2026\n`);
|
|
276
|
+
// 1) Refuse new dispatches immediately so they don't compound the drain.
|
|
277
|
+
setDraining(true);
|
|
278
|
+
// 2) Walk BatchRegistry: close every in-flight task's sessions in parallel
|
|
279
|
+
// with a 5-second wall clock. After the grace window, SIGKILL any
|
|
280
|
+
// subprocess still alive whose session exposes a pid. Without this,
|
|
281
|
+
// SIGTERM-killed daemons leaked codex children as orphans (see 2026-05-16
|
|
282
|
+
// OOM post-mortem).
|
|
283
|
+
const SHUTDOWN_GRACE_MS = 5000;
|
|
284
|
+
const inflight = running.batchRegistry?.allInFlight?.() ?? [];
|
|
285
|
+
const closeAll = Promise.allSettled(inflight.flatMap((entry) => {
|
|
286
|
+
const ctxs = entry.executionContexts ? Array.from(entry.executionContexts.values()) : [];
|
|
287
|
+
return ctxs.map(async (ec) => {
|
|
288
|
+
try {
|
|
289
|
+
await ec.closeSessions();
|
|
290
|
+
}
|
|
291
|
+
catch { /* swallow */ }
|
|
292
|
+
});
|
|
293
|
+
}));
|
|
294
|
+
const drainSessions = Promise.race([
|
|
295
|
+
closeAll,
|
|
296
|
+
new Promise((resolve) => setTimeout(resolve, SHUTDOWN_GRACE_MS).unref()),
|
|
297
|
+
]).then(() => {
|
|
298
|
+
// Belt-and-suspenders: SIGKILL anything still alive whose pid we know.
|
|
299
|
+
for (const entry of inflight) {
|
|
300
|
+
const ctxs = entry.executionContexts ? Array.from(entry.executionContexts.values()) : [];
|
|
301
|
+
for (const ec of ctxs) {
|
|
302
|
+
for (const pid of ec.getActivePids?.() ?? []) {
|
|
303
|
+
try {
|
|
304
|
+
process.kill(pid, 'SIGKILL');
|
|
305
|
+
}
|
|
306
|
+
catch { /* already dead */ }
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
const drainTelemetry = flusher ? flusher.drain() : Promise.resolve();
|
|
312
|
+
drainSessions
|
|
313
|
+
.catch(() => { })
|
|
314
|
+
.then(() => drainTelemetry)
|
|
315
|
+
.catch(() => { })
|
|
316
|
+
.then(() => running.stop())
|
|
317
|
+
.then(() => exit(0))
|
|
318
|
+
.catch((err) => {
|
|
319
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
320
|
+
stderr(`[mmagent] shutdown failed: ${msg}\n`);
|
|
321
|
+
exit(1);
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
// Register handlers using named references so they can be removed correctly.
|
|
325
|
+
// Using anonymous wrappers (e.g. `process.once('SIGTERM', () => fn(sig))`)
|
|
326
|
+
// would make process.off(sig, fn) unable to find and remove the listener.
|
|
327
|
+
onSigterm = () => cleanupSignal('SIGTERM');
|
|
328
|
+
onSigint = () => cleanupSignal('SIGINT');
|
|
329
|
+
process.once('SIGTERM', onSigterm);
|
|
330
|
+
process.once('SIGINT', onSigint);
|
|
331
|
+
// Print the actual bound address so operators see what the kernel assigned
|
|
332
|
+
// (useful when port=0 selects an ephemeral port).
|
|
333
|
+
const host = running.serverAddress ?? config.server.bind;
|
|
334
|
+
// Emit a single structured startup line before the "listening" line.
|
|
335
|
+
// Fingerprint the auth token (first 8 hex of sha256) so operators can verify
|
|
336
|
+
// the running instance matches what their clients are using, without ever
|
|
337
|
+
// revealing the token. bootId discriminates successive startups from the same pid.
|
|
338
|
+
try {
|
|
339
|
+
const token = loadAuthToken({ tokenFile: config.server.auth.tokenFile });
|
|
340
|
+
const fp = createHash('sha256').update(token).digest('hex').slice(0, 8);
|
|
341
|
+
const bootId = randomUUID();
|
|
342
|
+
const version = readServerVersion();
|
|
343
|
+
process.stdout.write(`[mmagent] started | version=${version} | bind=${host}:${running.port} | pid=${process.pid} | token=${fp} | boot=${bootId}\n`);
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// Token load shouldn't fail here (startServer already validated it), but
|
|
347
|
+
// if it does, skip the startup line rather than crash the server.
|
|
348
|
+
}
|
|
349
|
+
// Per-tier model lines so operators can see which provider is wired to
|
|
350
|
+
// each agent slot. The complex tier handles read-only sub-workers + most
|
|
351
|
+
// implementer work; the standard tier handles annotator/reviewer + the
|
|
352
|
+
// explore route's internal half. When a tier is unconfigured, log it as
|
|
353
|
+
// "(not configured)" so a misconfigured slot is visible at boot time.
|
|
354
|
+
const fmtTier = (slot) => {
|
|
355
|
+
const cfg = config.agents[slot];
|
|
356
|
+
if (!cfg || !cfg.model)
|
|
357
|
+
return '(not configured)';
|
|
358
|
+
return `${cfg.model} [${cfg.type ?? 'unknown'}]`;
|
|
359
|
+
};
|
|
360
|
+
process.stdout.write(`[mmagent] tiers | complex=${fmtTier('complex')} | standard=${fmtTier('standard')}\n`);
|
|
361
|
+
// A4a.4 (4.2.2+): warn when stale Claude Code project siblings exist
|
|
362
|
+
// under /tmp/claude/G--*. These come from prior Claude Code test runs
|
|
363
|
+
// and confuse worker cwd resolution if a caller passes one as ?cwd=.
|
|
364
|
+
// The validator already rejects them at request time (A4a.1); this
|
|
365
|
+
// startup scan surfaces the contamination so operators clean it up.
|
|
366
|
+
// Pure log behavior — does NOT block startup.
|
|
367
|
+
for (const root of ['/tmp/claude', '/private/tmp/claude']) {
|
|
368
|
+
try {
|
|
369
|
+
if (!fs.existsSync(root))
|
|
370
|
+
continue;
|
|
371
|
+
const stale = fs.readdirSync(root).filter(e => e.startsWith('G--'));
|
|
372
|
+
if (stale.length > 0) {
|
|
373
|
+
process.stdout.write(`[mmagent] WARNING: ${stale.length} stale Claude Code project sibling(s) under ${root}/G--*. ` +
|
|
374
|
+
`These can confuse cwd resolution; clean up with: rm -rf ${root}/G--*\n`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
catch { /* swallow — log-only */ }
|
|
378
|
+
}
|
|
379
|
+
process.stdout.write(`[mmagent] listening on ${host}:${running.port}\n`);
|
|
380
|
+
return {
|
|
381
|
+
port: running.port,
|
|
382
|
+
stop: async () => {
|
|
383
|
+
// Clean up signal listeners to prevent leaks when stop() is called
|
|
384
|
+
// programmatically (i.e. not via a signal).
|
|
385
|
+
if (onSigterm)
|
|
386
|
+
process.off('SIGTERM', onSigterm);
|
|
387
|
+
if (onSigint)
|
|
388
|
+
process.off('SIGINT', onSigint);
|
|
389
|
+
if (onStdoutErrorRef)
|
|
390
|
+
process.stdout.off('error', onStdoutErrorRef);
|
|
391
|
+
if (onStderrErrorRef)
|
|
392
|
+
process.stderr.off('error', onStderrErrorRef);
|
|
393
|
+
if (onUncaughtRef)
|
|
394
|
+
process.off('uncaughtException', onUncaughtRef);
|
|
395
|
+
if (onUnhandledRejectionRef)
|
|
396
|
+
process.off('unhandledRejection', onUnhandledRejectionRef);
|
|
397
|
+
onStdoutErrorRef = onStderrErrorRef = onUncaughtRef = onUnhandledRejectionRef = undefined;
|
|
398
|
+
if (flusher) {
|
|
399
|
+
await flusher.drain().catch(() => { });
|
|
400
|
+
}
|
|
401
|
+
await running.stop();
|
|
402
|
+
},
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/cli/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export interface StatusDeps {
|
|
2
|
+
/** Server URL (e.g. 'http://127.0.0.1:7337'). */
|
|
3
|
+
serverUrl: string;
|
|
4
|
+
/** Bearer auth token. */
|
|
5
|
+
token: string;
|
|
6
|
+
/** Output as raw JSON instead of pretty-printed summary. */
|
|
7
|
+
json?: boolean;
|
|
8
|
+
/** Write to stdout. */
|
|
9
|
+
stdout?: (s: string) => boolean;
|
|
10
|
+
/** Write to stderr. */
|
|
11
|
+
stderr?: (s: string) => boolean;
|
|
12
|
+
/** Inject fetch for testability. Defaults to global fetch. */
|
|
13
|
+
fetch?: typeof fetch;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Fetch GET /status and print a summary (or raw JSON).
|
|
17
|
+
* Returns an exit code: 0 on success, 1 on error.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fetchStatus(deps: StatusDeps): Promise<number>;
|
|
20
|
+
/**
|
|
21
|
+
* Build the server URL from a bind address and port.
|
|
22
|
+
* Handles '0.0.0.0' / '::' by converting to '127.0.0.1' since /status
|
|
23
|
+
* is loopback-only.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildServerUrl(bind: string, port: number): string;
|
|
26
|
+
export interface RunStatusDeps {
|
|
27
|
+
/** Config with server.bind + server.port. */
|
|
28
|
+
serverUrl: string;
|
|
29
|
+
/** Token file path (already resolved). */
|
|
30
|
+
tokenFile: string;
|
|
31
|
+
/** Whether to output raw JSON. */
|
|
32
|
+
json?: boolean;
|
|
33
|
+
/** Environment variable accessor (for MMAGENT_AUTH_TOKEN override). */
|
|
34
|
+
env?: Record<string, string | undefined>;
|
|
35
|
+
/** Write to stdout. */
|
|
36
|
+
stdout?: (s: string) => boolean;
|
|
37
|
+
/** Write to stderr. */
|
|
38
|
+
stderr?: (s: string) => boolean;
|
|
39
|
+
/** Inject fetch for testability. */
|
|
40
|
+
fetch?: typeof fetch;
|
|
41
|
+
/** Home directory (used to expand token file paths). */
|
|
42
|
+
homeDir?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Read the token and then call fetchStatus.
|
|
46
|
+
* Returns exit code.
|
|
47
|
+
*/
|
|
48
|
+
export declare function runStatus(deps: RunStatusDeps): Promise<number>;
|
|
49
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uBAAuB;IACvB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,uBAAuB;IACvB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,8DAA8D;IAC9D,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAiBD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAuEnE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,uBAAuB;IACvB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,uBAAuB;IACvB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAuCpE"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* status.ts — `mmagent status` subcommand.
|
|
3
|
+
*
|
|
4
|
+
* Fetches GET /status from a running server and pretty-prints a summary.
|
|
5
|
+
* Supports --json to dump the raw JSON response.
|
|
6
|
+
* Exits 1 if the server is unreachable or returns an error status.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* mmagent status [--config <path>] [--json]
|
|
10
|
+
*/
|
|
11
|
+
import * as os from 'node:os';
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
/**
|
|
14
|
+
* Format uptime in ms as a human-readable string.
|
|
15
|
+
*/
|
|
16
|
+
function formatUptime(ms) {
|
|
17
|
+
const seconds = Math.floor(ms / 1000);
|
|
18
|
+
const minutes = Math.floor(seconds / 60);
|
|
19
|
+
const hours = Math.floor(minutes / 60);
|
|
20
|
+
const days = Math.floor(hours / 24);
|
|
21
|
+
if (days > 0)
|
|
22
|
+
return `${days}d ${hours % 24}h ${minutes % 60}m`;
|
|
23
|
+
if (hours > 0)
|
|
24
|
+
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
|
25
|
+
if (minutes > 0)
|
|
26
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
27
|
+
return `${seconds}s`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetch GET /status and print a summary (or raw JSON).
|
|
31
|
+
* Returns an exit code: 0 on success, 1 on error.
|
|
32
|
+
*/
|
|
33
|
+
export async function fetchStatus(deps) {
|
|
34
|
+
const { serverUrl, token, json = false } = deps;
|
|
35
|
+
const stdout = deps.stdout ?? process.stdout.write.bind(process.stdout);
|
|
36
|
+
const stderr = deps.stderr ?? process.stderr.write.bind(process.stderr);
|
|
37
|
+
const fetcher = deps.fetch ?? fetch;
|
|
38
|
+
const url = `${serverUrl.replace(/\/$/, '')}/status`;
|
|
39
|
+
let res;
|
|
40
|
+
try {
|
|
41
|
+
res = await fetcher(url, {
|
|
42
|
+
method: 'GET',
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${token}`,
|
|
45
|
+
Accept: 'application/json',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
51
|
+
stderr(`mmagent status: cannot reach server at ${serverUrl}: ${msg}\n`);
|
|
52
|
+
stderr(`Is the server running? Start it with 'mmagent serve'.\n`);
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
stderr(`mmagent status: server returned HTTP ${res.status} ${res.statusText}\n`);
|
|
57
|
+
return 1;
|
|
58
|
+
}
|
|
59
|
+
let body;
|
|
60
|
+
try {
|
|
61
|
+
body = (await res.json());
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
stderr(`mmagent status: invalid JSON response from server\n`);
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
if (json) {
|
|
68
|
+
stdout(JSON.stringify(body, null, 2) + '\n');
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
// Pretty-print summary
|
|
72
|
+
const lines = [];
|
|
73
|
+
lines.push(`mmagent server status`);
|
|
74
|
+
lines.push(`─────────────────────────────`);
|
|
75
|
+
if (body.version)
|
|
76
|
+
lines.push(` version: ${body.version}`);
|
|
77
|
+
if (body.pid !== undefined)
|
|
78
|
+
lines.push(` pid: ${body.pid}`);
|
|
79
|
+
if (body.bind)
|
|
80
|
+
lines.push(` bind: ${body.bind}`);
|
|
81
|
+
if (body.uptimeMs !== undefined)
|
|
82
|
+
lines.push(` uptime: ${formatUptime(body.uptimeMs)}`);
|
|
83
|
+
const c = body.counters;
|
|
84
|
+
if (c) {
|
|
85
|
+
lines.push(` projects: ${c.projectCount ?? 0}`);
|
|
86
|
+
lines.push(` active batches: ${c.activeBatches ?? 0}`);
|
|
87
|
+
lines.push(` active reqs: ${c.activeRequests ?? 0}`);
|
|
88
|
+
}
|
|
89
|
+
const inflightCount = Array.isArray(body.inflight) ? body.inflight.length : 0;
|
|
90
|
+
lines.push(` in-flight: ${inflightCount}`);
|
|
91
|
+
if (body.skillVersion !== undefined) {
|
|
92
|
+
const sv = body.skillVersion ?? 'none';
|
|
93
|
+
const compat = body.skillCompatible === true ? ' (compatible)'
|
|
94
|
+
: body.skillCompatible === false ? ' (incompatible — run mmagent sync-skills to reconcile)'
|
|
95
|
+
: '';
|
|
96
|
+
lines.push(` skill version: ${sv}${compat}`);
|
|
97
|
+
}
|
|
98
|
+
stdout(lines.join('\n') + '\n');
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Build the server URL from a bind address and port.
|
|
103
|
+
* Handles '0.0.0.0' / '::' by converting to '127.0.0.1' since /status
|
|
104
|
+
* is loopback-only.
|
|
105
|
+
*/
|
|
106
|
+
export function buildServerUrl(bind, port) {
|
|
107
|
+
const host = (bind === '0.0.0.0' || bind === '::') ? '127.0.0.1' : bind;
|
|
108
|
+
return `http://${host}:${port}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Read the token and then call fetchStatus.
|
|
112
|
+
* Returns exit code.
|
|
113
|
+
*/
|
|
114
|
+
export async function runStatus(deps) {
|
|
115
|
+
const { serverUrl, tokenFile, json = false } = deps;
|
|
116
|
+
const env = deps.env ?? process.env;
|
|
117
|
+
const stderr = deps.stderr ?? process.stderr.write.bind(process.stderr);
|
|
118
|
+
const homeDir = deps.homeDir ?? os.homedir();
|
|
119
|
+
// Read the token (env wins)
|
|
120
|
+
let token;
|
|
121
|
+
const envToken = (env['MMAGENT_AUTH_TOKEN'] ?? '').trim();
|
|
122
|
+
if (envToken.length > 0) {
|
|
123
|
+
token = envToken;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const { readFileSync } = await import('node:fs');
|
|
127
|
+
const resolvedTokenFile = tokenFile.startsWith('~/')
|
|
128
|
+
? path.join(homeDir, tokenFile.slice(2))
|
|
129
|
+
: tokenFile;
|
|
130
|
+
try {
|
|
131
|
+
token = readFileSync(resolvedTokenFile, 'utf-8').trim();
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
const code = err.code;
|
|
135
|
+
if (code === 'ENOENT') {
|
|
136
|
+
stderr(`mmagent status: token file not found: ${resolvedTokenFile}\n`);
|
|
137
|
+
stderr(`Run 'mmagent print-token' or set MMAGENT_AUTH_TOKEN.\n`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
141
|
+
stderr(`mmagent status: cannot read token file: ${msg}\n`);
|
|
142
|
+
}
|
|
143
|
+
return 1;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return fetchStatus({
|
|
147
|
+
serverUrl,
|
|
148
|
+
token,
|
|
149
|
+
json,
|
|
150
|
+
stdout: deps.stdout,
|
|
151
|
+
stderr: deps.stderr,
|
|
152
|
+
fetch: deps.fetch,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"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"}
|