@darkiceinteractive/mcp-conductor 2.0.0-alpha.1 → 3.0.0-beta.2
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 +35 -5
- package/dist/bin/cli.d.ts +20 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +260 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bridge/http-server.d.ts +35 -0
- package/dist/bridge/http-server.d.ts.map +1 -1
- package/dist/bridge/http-server.js +51 -2
- package/dist/bridge/http-server.js.map +1 -1
- package/dist/bridge/index.d.ts +1 -0
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/index.js +1 -0
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/pool.d.ts +95 -0
- package/dist/bridge/pool.d.ts.map +1 -0
- package/dist/bridge/pool.js +384 -0
- package/dist/bridge/pool.js.map +1 -0
- package/dist/cache/cache.d.ts +64 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +209 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/delta.d.ts +32 -0
- package/dist/cache/delta.d.ts.map +1 -0
- package/dist/cache/delta.js +131 -0
- package/dist/cache/delta.js.map +1 -0
- package/dist/cache/disk.d.ts +65 -0
- package/dist/cache/disk.d.ts.map +1 -0
- package/dist/cache/disk.js +238 -0
- package/dist/cache/disk.js.map +1 -0
- package/dist/cache/index.d.ts +53 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +12 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/key.d.ts +44 -0
- package/dist/cache/key.d.ts.map +1 -0
- package/dist/cache/key.js +83 -0
- package/dist/cache/key.js.map +1 -0
- package/dist/cache/lru.d.ts +57 -0
- package/dist/cache/lru.d.ts.map +1 -0
- package/dist/cache/lru.js +112 -0
- package/dist/cache/lru.js.map +1 -0
- package/dist/cache/policy.d.ts +34 -0
- package/dist/cache/policy.d.ts.map +1 -0
- package/dist/cache/policy.js +95 -0
- package/dist/cache/policy.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +33 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +135 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export-servers.d.ts +22 -0
- package/dist/cli/commands/export-servers.d.ts.map +1 -0
- package/dist/cli/commands/export-servers.js +45 -0
- package/dist/cli/commands/export-servers.js.map +1 -0
- package/dist/cli/commands/import-servers.d.ts +57 -0
- package/dist/cli/commands/import-servers.d.ts.map +1 -0
- package/dist/cli/commands/import-servers.js +137 -0
- package/dist/cli/commands/import-servers.js.map +1 -0
- package/dist/cli/commands/routing.d.ts +34 -0
- package/dist/cli/commands/routing.d.ts.map +1 -0
- package/dist/cli/commands/routing.js +60 -0
- package/dist/cli/commands/routing.js.map +1 -0
- package/dist/cli/commands/test-server.d.ts +34 -0
- package/dist/cli/commands/test-server.d.ts.map +1 -0
- package/dist/cli/commands/test-server.js +86 -0
- package/dist/cli/commands/test-server.js.map +1 -0
- package/dist/cli/daemon.d.ts +60 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +244 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/replay.d.ts +16 -0
- package/dist/cli/replay.d.ts.map +1 -0
- package/dist/cli/replay.js +89 -0
- package/dist/cli/replay.js.map +1 -0
- package/dist/cli/wizard/setup.d.ts +12 -0
- package/dist/cli/wizard/setup.d.ts.map +1 -0
- package/dist/cli/wizard/setup.js +71 -0
- package/dist/cli/wizard/setup.js.map +1 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +4 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.d.ts +34 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/daemon/client.d.ts +99 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +292 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/discovery.d.ts +50 -0
- package/dist/daemon/discovery.d.ts.map +1 -0
- package/dist/daemon/discovery.js +104 -0
- package/dist/daemon/discovery.js.map +1 -0
- package/dist/daemon/index.d.ts +16 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +11 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/sandbox-api.d.ts +45 -0
- package/dist/daemon/sandbox-api.d.ts.map +1 -0
- package/dist/daemon/sandbox-api.js +74 -0
- package/dist/daemon/sandbox-api.js.map +1 -0
- package/dist/daemon/server.d.ts +65 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +373 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/shared-kv.d.ts +81 -0
- package/dist/daemon/shared-kv.d.ts.map +1 -0
- package/dist/daemon/shared-kv.js +215 -0
- package/dist/daemon/shared-kv.js.map +1 -0
- package/dist/daemon/shared-lock.d.ts +71 -0
- package/dist/daemon/shared-lock.d.ts.map +1 -0
- package/dist/daemon/shared-lock.js +119 -0
- package/dist/daemon/shared-lock.js.map +1 -0
- package/dist/hub/mcp-hub.d.ts +23 -0
- package/dist/hub/mcp-hub.d.ts.map +1 -1
- package/dist/hub/mcp-hub.js +34 -1
- package/dist/hub/mcp-hub.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/observability/anomaly.d.ts +67 -0
- package/dist/observability/anomaly.d.ts.map +1 -0
- package/dist/observability/anomaly.js +141 -0
- package/dist/observability/anomaly.js.map +1 -0
- package/dist/observability/cost-predictor.d.ts +49 -0
- package/dist/observability/cost-predictor.d.ts.map +1 -0
- package/dist/observability/cost-predictor.js +145 -0
- package/dist/observability/cost-predictor.js.map +1 -0
- package/dist/observability/hot-path.d.ts +49 -0
- package/dist/observability/hot-path.d.ts.map +1 -0
- package/dist/observability/hot-path.js +125 -0
- package/dist/observability/hot-path.js.map +1 -0
- package/dist/observability/index.d.ts +10 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +10 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/replay.d.ts +104 -0
- package/dist/observability/replay.d.ts.map +1 -0
- package/dist/observability/replay.js +239 -0
- package/dist/observability/replay.js.map +1 -0
- package/dist/registry/built-in-recommendations.d.ts +54 -0
- package/dist/registry/built-in-recommendations.d.ts.map +1 -0
- package/dist/registry/built-in-recommendations.js +65 -0
- package/dist/registry/built-in-recommendations.js.map +1 -0
- package/dist/registry/events.d.ts +26 -0
- package/dist/registry/events.d.ts.map +1 -0
- package/dist/registry/events.js +22 -0
- package/dist/registry/events.js.map +1 -0
- package/dist/registry/index.d.ts +159 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +12 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/registry.d.ts +87 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/registry.js +294 -0
- package/dist/registry/registry.js.map +1 -0
- package/dist/registry/snapshot.d.ts +42 -0
- package/dist/registry/snapshot.d.ts.map +1 -0
- package/dist/registry/snapshot.js +71 -0
- package/dist/registry/snapshot.js.map +1 -0
- package/dist/registry/typegen.d.ts +48 -0
- package/dist/registry/typegen.d.ts.map +1 -0
- package/dist/registry/typegen.js +200 -0
- package/dist/registry/typegen.js.map +1 -0
- package/dist/registry/validator.d.ts +23 -0
- package/dist/registry/validator.d.ts.map +1 -0
- package/dist/registry/validator.js +50 -0
- package/dist/registry/validator.js.map +1 -0
- package/dist/reliability/breaker.d.ts +57 -0
- package/dist/reliability/breaker.d.ts.map +1 -0
- package/dist/reliability/breaker.js +130 -0
- package/dist/reliability/breaker.js.map +1 -0
- package/dist/reliability/errors.d.ts +78 -0
- package/dist/reliability/errors.d.ts.map +1 -0
- package/dist/reliability/errors.js +160 -0
- package/dist/reliability/errors.js.map +1 -0
- package/dist/reliability/gateway.d.ts +88 -0
- package/dist/reliability/gateway.d.ts.map +1 -0
- package/dist/reliability/gateway.js +180 -0
- package/dist/reliability/gateway.js.map +1 -0
- package/dist/reliability/index.d.ts +20 -0
- package/dist/reliability/index.d.ts.map +1 -0
- package/dist/reliability/index.js +16 -0
- package/dist/reliability/index.js.map +1 -0
- package/dist/reliability/profile.d.ts +49 -0
- package/dist/reliability/profile.d.ts.map +1 -0
- package/dist/reliability/profile.js +58 -0
- package/dist/reliability/profile.js.map +1 -0
- package/dist/reliability/retry.d.ts +39 -0
- package/dist/reliability/retry.d.ts.map +1 -0
- package/dist/reliability/retry.js +51 -0
- package/dist/reliability/retry.js.map +1 -0
- package/dist/reliability/timeout.d.ts +34 -0
- package/dist/reliability/timeout.d.ts.map +1 -0
- package/dist/reliability/timeout.js +53 -0
- package/dist/reliability/timeout.js.map +1 -0
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +122 -14
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/findtool/embed.d.ts +28 -0
- package/dist/runtime/findtool/embed.d.ts.map +1 -0
- package/dist/runtime/findtool/embed.js +85 -0
- package/dist/runtime/findtool/embed.js.map +1 -0
- package/dist/runtime/findtool/index.d.ts +52 -0
- package/dist/runtime/findtool/index.d.ts.map +1 -0
- package/dist/runtime/findtool/index.js +78 -0
- package/dist/runtime/findtool/index.js.map +1 -0
- package/dist/runtime/findtool/vector-index.d.ts +53 -0
- package/dist/runtime/findtool/vector-index.d.ts.map +1 -0
- package/dist/runtime/findtool/vector-index.js +71 -0
- package/dist/runtime/findtool/vector-index.js.map +1 -0
- package/dist/runtime/helpers/budget.d.ts +27 -0
- package/dist/runtime/helpers/budget.d.ts.map +1 -0
- package/dist/runtime/helpers/budget.js +103 -0
- package/dist/runtime/helpers/budget.js.map +1 -0
- package/dist/runtime/helpers/compact.d.ts +32 -0
- package/dist/runtime/helpers/compact.d.ts.map +1 -0
- package/dist/runtime/helpers/compact.js +93 -0
- package/dist/runtime/helpers/compact.js.map +1 -0
- package/dist/runtime/helpers/delta.d.ts +45 -0
- package/dist/runtime/helpers/delta.d.ts.map +1 -0
- package/dist/runtime/helpers/delta.js +116 -0
- package/dist/runtime/helpers/delta.js.map +1 -0
- package/dist/runtime/helpers/index.d.ts +16 -0
- package/dist/runtime/helpers/index.d.ts.map +1 -0
- package/dist/runtime/helpers/index.js +13 -0
- package/dist/runtime/helpers/index.js.map +1 -0
- package/dist/runtime/helpers/summarize.d.ts +24 -0
- package/dist/runtime/helpers/summarize.d.ts.map +1 -0
- package/dist/runtime/helpers/summarize.js +124 -0
- package/dist/runtime/helpers/summarize.js.map +1 -0
- package/dist/runtime/helpers/worker-preload.d.ts +25 -0
- package/dist/runtime/helpers/worker-preload.d.ts.map +1 -0
- package/dist/runtime/helpers/worker-preload.js +223 -0
- package/dist/runtime/helpers/worker-preload.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/pool/index.d.ts +11 -0
- package/dist/runtime/pool/index.d.ts.map +1 -0
- package/dist/runtime/pool/index.js +8 -0
- package/dist/runtime/pool/index.js.map +1 -0
- package/dist/runtime/pool/recycle.d.ts +44 -0
- package/dist/runtime/pool/recycle.d.ts.map +1 -0
- package/dist/runtime/pool/recycle.js +50 -0
- package/dist/runtime/pool/recycle.js.map +1 -0
- package/dist/runtime/pool/worker-pool.d.ts +77 -0
- package/dist/runtime/pool/worker-pool.d.ts.map +1 -0
- package/dist/runtime/pool/worker-pool.js +216 -0
- package/dist/runtime/pool/worker-pool.js.map +1 -0
- package/dist/runtime/pool/worker.d.ts +80 -0
- package/dist/runtime/pool/worker.d.ts.map +1 -0
- package/dist/runtime/pool/worker.js +324 -0
- package/dist/runtime/pool/worker.js.map +1 -0
- package/dist/server/mcp-server.d.ts +3 -0
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +457 -3
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/passthrough-registrar.d.ts +123 -0
- package/dist/server/passthrough-registrar.d.ts.map +1 -0
- package/dist/server/passthrough-registrar.js +199 -0
- package/dist/server/passthrough-registrar.js.map +1 -0
- package/dist/skills/skills-engine.d.ts +9 -1
- package/dist/skills/skills-engine.d.ts.map +1 -1
- package/dist/skills/skills-engine.js +20 -3
- package/dist/skills/skills-engine.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/tokenize.d.ts +55 -0
- package/dist/utils/tokenize.d.ts.map +1 -0
- package/dist/utils/tokenize.js +205 -0
- package/dist/utils/tokenize.js.map +1 -0
- package/dist/version.d.ts +3 -3
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +3 -3
- package/dist/version.js.map +1 -1
- package/package.json +13 -3
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* routing command: heuristic per-tool routing recommendation.
|
|
3
|
+
* @module cli/commands/routing
|
|
4
|
+
*/
|
|
5
|
+
import { loadConductorConfig, saveConductorConfig, getDefaultConductorConfigPath } from '../../config/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Heuristic: servers whose names or typical tool shapes suggest small payloads
|
|
8
|
+
* should be marked passthrough. This is the X1 heuristic adapted for the CLI.
|
|
9
|
+
*
|
|
10
|
+
* Rule: if the server name matches known lightweight patterns (search, calendar,
|
|
11
|
+
* weather, echo, ping) → passthrough. Otherwise → execute_code.
|
|
12
|
+
*
|
|
13
|
+
* A more sophisticated version would sample live tool responses — this is the
|
|
14
|
+
* static heuristic that can be applied without connecting.
|
|
15
|
+
*/
|
|
16
|
+
export function recommendRouting(serverName) {
|
|
17
|
+
const lower = serverName.toLowerCase();
|
|
18
|
+
const passthroughPatterns = [
|
|
19
|
+
/search/, /calendar/, /weather/, /echo/, /ping/, /todo/, /remind/,
|
|
20
|
+
/notes?$/, /contacts?$/, /email$/, /mail$/, /slack$/, /discord$/,
|
|
21
|
+
];
|
|
22
|
+
const isPassthrough = passthroughPatterns.some((p) => p.test(lower));
|
|
23
|
+
return {
|
|
24
|
+
serverName,
|
|
25
|
+
recommendation: isPassthrough ? 'passthrough' : 'execute_code',
|
|
26
|
+
reason: isPassthrough
|
|
27
|
+
? 'Name matches lightweight-payload pattern (responses typically <1KB)'
|
|
28
|
+
: 'Name does not match passthrough patterns; execute_code is safer default',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate routing recommendations for one or all configured servers.
|
|
33
|
+
* Optionally write the recommendations back to the conductor config.
|
|
34
|
+
*/
|
|
35
|
+
export function getRoutingRecommendations(options) {
|
|
36
|
+
const config = loadConductorConfig();
|
|
37
|
+
if (!config) {
|
|
38
|
+
return { recommendations: [], applied: false };
|
|
39
|
+
}
|
|
40
|
+
const serverNames = options.serverName
|
|
41
|
+
? [options.serverName]
|
|
42
|
+
: Object.keys(config.servers);
|
|
43
|
+
const recommendations = serverNames
|
|
44
|
+
.filter((n) => config.servers[n] !== undefined)
|
|
45
|
+
.map(recommendRouting);
|
|
46
|
+
if (options.apply && recommendations.length > 0) {
|
|
47
|
+
// Store routing hint in server env as __routing (lightweight annotation).
|
|
48
|
+
for (const rec of recommendations) {
|
|
49
|
+
const server = config.servers[rec.serverName];
|
|
50
|
+
if (server) {
|
|
51
|
+
server.env = { ...(server.env ?? {}), __routing: rec.recommendation };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const configPath = getDefaultConductorConfigPath();
|
|
55
|
+
saveConductorConfig(config, configPath);
|
|
56
|
+
return { recommendations, applied: true, configPath };
|
|
57
|
+
}
|
|
58
|
+
return { recommendations, applied: false };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=routing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../src/cli/commands/routing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAchH;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IACvC,MAAM,mBAAmB,GAAG;QAC1B,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ;QACjE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU;KACjE,CAAC;IAEF,MAAM,aAAa,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAErE,OAAO;QACL,UAAU;QACV,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc;QAC9D,MAAM,EAAE,aAAa;YACnB,CAAC,CAAC,qEAAqE;YACvE,CAAC,CAAC,yEAAyE;KAC9E,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAGzC;IACC,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU;QACpC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QACtB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEhC,MAAM,eAAe,GAAG,WAAW;SAChC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;SAC9C,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAEzB,IAAI,OAAO,CAAC,KAAK,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,0EAA0E;QAC1E,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,cAAc,EAAE,CAAC;YACxE,CAAC;QACH,CAAC;QACD,MAAM,UAAU,GAAG,6BAA6B,EAAE,CAAC;QACnD,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACxC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* test-server command: transient connect, list tools, latency probe.
|
|
3
|
+
* @module cli/commands/test-server
|
|
4
|
+
*/
|
|
5
|
+
export interface TestServerOptions {
|
|
6
|
+
/** Server name (looks up in conductor config) */
|
|
7
|
+
name?: string;
|
|
8
|
+
/** Directly specify command (bypasses config lookup) */
|
|
9
|
+
command?: string;
|
|
10
|
+
/** Command args */
|
|
11
|
+
args?: string[];
|
|
12
|
+
/** Environment variables */
|
|
13
|
+
env?: Record<string, string>;
|
|
14
|
+
/** Connection timeout ms */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface TestServerResult {
|
|
18
|
+
success: boolean;
|
|
19
|
+
serverName: string;
|
|
20
|
+
connected: boolean;
|
|
21
|
+
toolCount: number;
|
|
22
|
+
tools: Array<{
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
}>;
|
|
26
|
+
latencyMs: number;
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Transiently connect to an MCP server, list its tools and measure latency.
|
|
31
|
+
* The connection is always closed afterwards — no persistent registration.
|
|
32
|
+
*/
|
|
33
|
+
export declare function testServer(options: TestServerOptions): Promise<TestServerResult>;
|
|
34
|
+
//# sourceMappingURL=test-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-server.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/test-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4EtF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* test-server command: transient connect, list tools, latency probe.
|
|
3
|
+
* @module cli/commands/test-server
|
|
4
|
+
*/
|
|
5
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
6
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
7
|
+
import { minimalChildEnv } from '../../utils/index.js';
|
|
8
|
+
import { loadConductorConfig } from '../../config/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Transiently connect to an MCP server, list its tools and measure latency.
|
|
11
|
+
* The connection is always closed afterwards — no persistent registration.
|
|
12
|
+
*/
|
|
13
|
+
export async function testServer(options) {
|
|
14
|
+
const name = options.name ?? 'unnamed';
|
|
15
|
+
let command;
|
|
16
|
+
let args;
|
|
17
|
+
let env;
|
|
18
|
+
if (options.command) {
|
|
19
|
+
command = options.command;
|
|
20
|
+
args = options.args ?? [];
|
|
21
|
+
env = options.env;
|
|
22
|
+
}
|
|
23
|
+
else if (options.name) {
|
|
24
|
+
const config = loadConductorConfig();
|
|
25
|
+
if (!config) {
|
|
26
|
+
return { success: false, serverName: name, connected: false, toolCount: 0, tools: [], latencyMs: 0, error: 'No conductor config found' };
|
|
27
|
+
}
|
|
28
|
+
const serverDef = config.servers[options.name];
|
|
29
|
+
if (!serverDef) {
|
|
30
|
+
return { success: false, serverName: name, connected: false, toolCount: 0, tools: [], latencyMs: 0, error: `Server '${options.name}' not found in conductor config` };
|
|
31
|
+
}
|
|
32
|
+
command = serverDef.command;
|
|
33
|
+
args = serverDef.args ?? [];
|
|
34
|
+
env = serverDef.env;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return { success: false, serverName: name, connected: false, toolCount: 0, tools: [], latencyMs: 0, error: 'Either name or command must be provided' };
|
|
38
|
+
}
|
|
39
|
+
const timeoutMs = options.timeoutMs ?? 15000;
|
|
40
|
+
const t0 = Date.now();
|
|
41
|
+
const client = new Client({ name: 'mcp-conductor-test', version: '1.0.0' });
|
|
42
|
+
const transport = new StdioClientTransport({
|
|
43
|
+
command,
|
|
44
|
+
args,
|
|
45
|
+
env: { ...minimalChildEnv(), ...(env ?? {}) },
|
|
46
|
+
});
|
|
47
|
+
try {
|
|
48
|
+
const connectPromise = client.connect(transport);
|
|
49
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Connection timed out after ${timeoutMs}ms`)), timeoutMs));
|
|
50
|
+
await Promise.race([connectPromise, timeoutPromise]);
|
|
51
|
+
const listResult = await client.listTools();
|
|
52
|
+
const latencyMs = Date.now() - t0;
|
|
53
|
+
const tools = (listResult.tools ?? []).map((t) => ({
|
|
54
|
+
name: t.name,
|
|
55
|
+
description: t.description ?? '',
|
|
56
|
+
}));
|
|
57
|
+
return {
|
|
58
|
+
success: true,
|
|
59
|
+
serverName: name,
|
|
60
|
+
connected: true,
|
|
61
|
+
toolCount: tools.length,
|
|
62
|
+
tools,
|
|
63
|
+
latencyMs,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
return {
|
|
68
|
+
success: false,
|
|
69
|
+
serverName: name,
|
|
70
|
+
connected: false,
|
|
71
|
+
toolCount: 0,
|
|
72
|
+
tools: [],
|
|
73
|
+
latencyMs: Date.now() - t0,
|
|
74
|
+
error: String(err),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
try {
|
|
79
|
+
await client.close();
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// ignore cleanup errors
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=test-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-server.js","sourceRoot":"","sources":["../../../src/cli/commands/test-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon CLI subcommands for MCP Conductor.
|
|
3
|
+
*
|
|
4
|
+
* Designed as a self-contained module so Agent I (X2 lifecycle CLI) can
|
|
5
|
+
* import and register these commands without taking a dependency on the full
|
|
6
|
+
* daemon implementation at the top level.
|
|
7
|
+
*
|
|
8
|
+
* Usage (in the host CLI program):
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { Command } from 'commander';
|
|
12
|
+
* import { registerDaemonCommands } from './cli/daemon.js';
|
|
13
|
+
*
|
|
14
|
+
* const program = new Command();
|
|
15
|
+
* registerDaemonCommands(program);
|
|
16
|
+
* program.parse();
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Available subcommands:
|
|
20
|
+
* daemon start — Start the daemon in the background
|
|
21
|
+
* daemon stop — Stop a running daemon
|
|
22
|
+
* daemon status — Print daemon health and stats
|
|
23
|
+
* daemon logs — Tail the daemon log file
|
|
24
|
+
*
|
|
25
|
+
* @module cli/daemon
|
|
26
|
+
*/
|
|
27
|
+
declare function daemonStart(options: {
|
|
28
|
+
port?: string;
|
|
29
|
+
background?: boolean;
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
declare function daemonStop(): Promise<void>;
|
|
32
|
+
declare function daemonStatus(): Promise<void>;
|
|
33
|
+
declare function daemonLogs(options: {
|
|
34
|
+
lines?: string;
|
|
35
|
+
follow?: boolean;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Register all daemon subcommands onto a Commander `program` instance.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* import { Command } from 'commander';
|
|
43
|
+
* import { registerDaemonCommands } from './cli/daemon.js';
|
|
44
|
+
* const program = new Command('mcp-conductor-cli');
|
|
45
|
+
* registerDaemonCommands(program);
|
|
46
|
+
* program.parse();
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function registerDaemonCommands(program: {
|
|
50
|
+
command: (name: string) => DaemonCommandBuilder;
|
|
51
|
+
}): void;
|
|
52
|
+
/** Minimal interface matching Commander's Command for type safety without the dep. */
|
|
53
|
+
interface DaemonCommandBuilder {
|
|
54
|
+
description: (d: string) => DaemonCommandBuilder;
|
|
55
|
+
option: (flags: string, description?: string, defaultValue?: string) => DaemonCommandBuilder;
|
|
56
|
+
action: (fn: (...args: unknown[]) => void | Promise<void>) => DaemonCommandBuilder;
|
|
57
|
+
command: (name: string) => DaemonCommandBuilder;
|
|
58
|
+
}
|
|
59
|
+
export { daemonStart, daemonStop, daemonStatus, daemonLogs };
|
|
60
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAgDH,iBAAe,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC1F;AAED,iBAAe,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA4BzC;AAED,iBAAe,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAoB3C;AAED,iBAAe,UAAU,CAAC,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCtF;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,oBAAoB,CAAC;CACjD,GAAG,IAAI,CAmCP;AAMD,sFAAsF;AACtF,UAAU,oBAAoB;IAC5B,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,oBAAoB,CAAC;IACjD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,oBAAoB,CAAC;IAC7F,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,oBAAoB,CAAC;IACnF,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,oBAAoB,CAAC;CACjD;AAMD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon CLI subcommands for MCP Conductor.
|
|
3
|
+
*
|
|
4
|
+
* Designed as a self-contained module so Agent I (X2 lifecycle CLI) can
|
|
5
|
+
* import and register these commands without taking a dependency on the full
|
|
6
|
+
* daemon implementation at the top level.
|
|
7
|
+
*
|
|
8
|
+
* Usage (in the host CLI program):
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { Command } from 'commander';
|
|
12
|
+
* import { registerDaemonCommands } from './cli/daemon.js';
|
|
13
|
+
*
|
|
14
|
+
* const program = new Command();
|
|
15
|
+
* registerDaemonCommands(program);
|
|
16
|
+
* program.parse();
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Available subcommands:
|
|
20
|
+
* daemon start — Start the daemon in the background
|
|
21
|
+
* daemon stop — Stop a running daemon
|
|
22
|
+
* daemon status — Print daemon health and stats
|
|
23
|
+
* daemon logs — Tail the daemon log file
|
|
24
|
+
*
|
|
25
|
+
* @module cli/daemon
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, statSync, createReadStream } from 'node:fs';
|
|
28
|
+
import { join } from 'node:path';
|
|
29
|
+
import { homedir } from 'node:os';
|
|
30
|
+
import { spawn } from 'node:child_process';
|
|
31
|
+
import { DaemonClient } from '../daemon/client.js';
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Paths
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
const CONDUCTOR_DIR = join(homedir(), '.mcp-conductor');
|
|
36
|
+
const PID_FILE = join(CONDUCTOR_DIR, 'daemon.pid');
|
|
37
|
+
const LOG_FILE = join(CONDUCTOR_DIR, 'daemon.log');
|
|
38
|
+
const SOCKET_PATH = join(CONDUCTOR_DIR, 'daemon.sock');
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Helpers
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
function ensureDir() {
|
|
43
|
+
mkdirSync(CONDUCTOR_DIR, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
function readPid() {
|
|
46
|
+
if (!existsSync(PID_FILE))
|
|
47
|
+
return null;
|
|
48
|
+
try {
|
|
49
|
+
return parseInt(readFileSync(PID_FILE, 'utf-8').trim(), 10);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function isRunning(pid) {
|
|
56
|
+
try {
|
|
57
|
+
process.kill(pid, 0);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Subcommand implementations
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
async function daemonStart(options) {
|
|
68
|
+
ensureDir();
|
|
69
|
+
const pid = readPid();
|
|
70
|
+
if (pid !== null && isRunning(pid)) {
|
|
71
|
+
console.log(`Daemon is already running (PID ${pid})`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const tcpPort = options.port ? parseInt(options.port, 10) : undefined;
|
|
75
|
+
// Build the daemon entry script args.
|
|
76
|
+
const args = ['--daemon-server'];
|
|
77
|
+
if (tcpPort)
|
|
78
|
+
args.push('--tcp-port', String(tcpPort));
|
|
79
|
+
// Spawn the daemon process detached.
|
|
80
|
+
const out = require('node:fs').openSync(LOG_FILE, 'a');
|
|
81
|
+
const child = spawn(process.execPath, [process.argv[1], ...args], {
|
|
82
|
+
detached: true,
|
|
83
|
+
stdio: ['ignore', out, out],
|
|
84
|
+
});
|
|
85
|
+
child.unref();
|
|
86
|
+
writeFileSync(PID_FILE, String(child.pid), 'utf-8');
|
|
87
|
+
// Brief wait for the socket to appear.
|
|
88
|
+
let ready = false;
|
|
89
|
+
for (let i = 0; i < 20; i++) {
|
|
90
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
91
|
+
if (existsSync(SOCKET_PATH)) {
|
|
92
|
+
ready = true;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (ready) {
|
|
97
|
+
console.log(`Daemon started (PID ${child.pid})`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
console.warn(`Daemon spawned (PID ${child.pid}) but socket not yet visible. Check logs: ${LOG_FILE}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function daemonStop() {
|
|
104
|
+
const pid = readPid();
|
|
105
|
+
if (pid === null) {
|
|
106
|
+
console.log('No PID file found — daemon may not be running.');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!isRunning(pid)) {
|
|
110
|
+
console.log(`Daemon PID ${pid} is not running.`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
process.kill(pid, 'SIGTERM');
|
|
115
|
+
// Wait up to 5 s for the process to exit.
|
|
116
|
+
for (let i = 0; i < 50; i++) {
|
|
117
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
118
|
+
if (!isRunning(pid))
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (!isRunning(pid)) {
|
|
122
|
+
console.log(`Daemon (PID ${pid}) stopped.`);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
console.warn(`Daemon (PID ${pid}) did not exit in 5 s. Sending SIGKILL.`);
|
|
126
|
+
process.kill(pid, 'SIGKILL');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
console.error(`Failed to stop daemon: ${String(err)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function daemonStatus() {
|
|
134
|
+
const pid = readPid();
|
|
135
|
+
if (pid === null || !isRunning(pid)) {
|
|
136
|
+
console.log('Daemon: STOPPED');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
console.log(`Daemon: RUNNING (PID ${pid})`);
|
|
140
|
+
// Try connecting to get live stats.
|
|
141
|
+
try {
|
|
142
|
+
const client = new DaemonClient({ connectTimeoutMs: 2000 });
|
|
143
|
+
await client.connect();
|
|
144
|
+
const stats = await client.stats();
|
|
145
|
+
console.log('Stats:', JSON.stringify(stats, null, 2));
|
|
146
|
+
await client.disconnect();
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
console.log(`(Could not fetch live stats: ${String(err)})`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function daemonLogs(options) {
|
|
153
|
+
if (!existsSync(LOG_FILE)) {
|
|
154
|
+
console.log('No log file found at', LOG_FILE);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const n = parseInt(options.lines ?? '50', 10);
|
|
158
|
+
if (options.follow) {
|
|
159
|
+
// Simple tail -f implementation using a ReadStream.
|
|
160
|
+
const stat = statSync(LOG_FILE);
|
|
161
|
+
const stream = createReadStream(LOG_FILE, {
|
|
162
|
+
start: Math.max(0, stat.size - 8192),
|
|
163
|
+
encoding: 'utf-8',
|
|
164
|
+
});
|
|
165
|
+
stream.pipe(process.stdout);
|
|
166
|
+
stream.on('end', () => {
|
|
167
|
+
// Keep watching by polling — Node.js fs.watch is enough for a dev tool.
|
|
168
|
+
let lastSize = stat.size;
|
|
169
|
+
const interval = setInterval(() => {
|
|
170
|
+
try {
|
|
171
|
+
const newStat = statSync(LOG_FILE);
|
|
172
|
+
if (newStat.size > lastSize) {
|
|
173
|
+
const tail = createReadStream(LOG_FILE, {
|
|
174
|
+
start: lastSize,
|
|
175
|
+
encoding: 'utf-8',
|
|
176
|
+
});
|
|
177
|
+
tail.pipe(process.stdout);
|
|
178
|
+
lastSize = newStat.size;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
clearInterval(interval);
|
|
183
|
+
}
|
|
184
|
+
}, 500);
|
|
185
|
+
process.on('SIGINT', () => { clearInterval(interval); process.exit(0); });
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
const content = readFileSync(LOG_FILE, 'utf-8');
|
|
190
|
+
const lines = content.split('\n').filter(Boolean);
|
|
191
|
+
const tail = lines.slice(-n).join('\n');
|
|
192
|
+
console.log(tail);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
// Registration function (Agent I integration point)
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
/**
|
|
199
|
+
* Register all daemon subcommands onto a Commander `program` instance.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* import { Command } from 'commander';
|
|
204
|
+
* import { registerDaemonCommands } from './cli/daemon.js';
|
|
205
|
+
* const program = new Command('mcp-conductor-cli');
|
|
206
|
+
* registerDaemonCommands(program);
|
|
207
|
+
* program.parse();
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export function registerDaemonCommands(program) {
|
|
211
|
+
const daemon = program.command('daemon').description('Manage the MCP Conductor daemon process');
|
|
212
|
+
// daemon start
|
|
213
|
+
daemon.command('start')
|
|
214
|
+
.description('Start the daemon in the background')
|
|
215
|
+
.option('--port <port>', 'TCP port for Tailscale clients')
|
|
216
|
+
.action(async (...args) => {
|
|
217
|
+
await daemonStart(args[0]);
|
|
218
|
+
});
|
|
219
|
+
// daemon stop
|
|
220
|
+
daemon.command('stop')
|
|
221
|
+
.description('Stop the running daemon')
|
|
222
|
+
.action(async () => {
|
|
223
|
+
await daemonStop();
|
|
224
|
+
});
|
|
225
|
+
// daemon status
|
|
226
|
+
daemon.command('status')
|
|
227
|
+
.description('Show daemon health and statistics')
|
|
228
|
+
.action(async () => {
|
|
229
|
+
await daemonStatus();
|
|
230
|
+
});
|
|
231
|
+
// daemon logs
|
|
232
|
+
daemon.command('logs')
|
|
233
|
+
.description('Show daemon log output')
|
|
234
|
+
.option('-n, --lines <n>', 'Number of lines to show', '50')
|
|
235
|
+
.option('-f, --follow', 'Follow log output')
|
|
236
|
+
.action(async (...args) => {
|
|
237
|
+
await daemonLogs(args[0]);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
// Exported individual action functions (for programmatic use and testing)
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
export { daemonStart, daemonStop, daemonStatus, daemonLogs };
|
|
244
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACzG,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;AACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;AACnD,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAEvD,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,SAAS;IAChB,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,OAAO;IACd,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E,KAAK,UAAU,WAAW,CAAC,OAAgD;IACzE,SAAS,EAAE,CAAC;IAEZ,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,kCAAkC,GAAG,GAAG,CAAC,CAAC;QACtD,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEtE,sCAAsC;IACtC,MAAM,IAAI,GAAa,CAAC,iBAAiB,CAAC,CAAC;IAC3C,IAAI,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAEtD,qCAAqC;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,GAAG,IAAI,CAAC,EAAE;QACjE,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;KAC5B,CAAC,CAAC;IAEH,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IAEpD,uCAAuC;IACvC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7C,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAAC,KAAK,GAAG,IAAI,CAAC;YAAC,MAAM;QAAC,CAAC;IACvD,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,uBAAuB,KAAK,CAAC,GAAG,6CAA6C,QAAQ,EAAE,CAAC,CAAC;IACxG,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,kBAAkB,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7B,0CAA0C;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC7C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;gBAAE,MAAM;QAC7B,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,YAAY,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,eAAe,GAAG,yCAAyC,CAAC,CAAC;YAC1E,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,0BAA0B,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY;IACzB,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IAEtB,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/B,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,GAAG,CAAC,CAAC;IAE5C,oCAAoC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,gCAAgC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAA6C;IACrE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,QAAQ,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;IAE9C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,oDAAoD;QACpD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE;YACxC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YACpC,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACpB,wEAAwE;YACxE,IAAI,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;YACzB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;gBAChC,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACnC,IAAI,OAAO,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC;wBAC5B,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,EAAE;4BACtC,KAAK,EAAE,QAAQ;4BACf,QAAQ,EAAE,OAAO;yBAClB,CAAC,CAAC;wBACH,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;wBAC1B,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;oBAC1B,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAAC,CAAC;YACtC,CAAC,EAAE,GAAG,CAAC,CAAC;YACR,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,oDAAoD;AACpD,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAEtC;IACC,MAAM,MAAM,GAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAqE,CAAC,WAAW,CACvH,yCAAyC,CAC1C,CAAC;IAEF,eAAe;IACd,MAAsE,CAAC,OAAO,CAAC,OAAO,CAAC;SACrF,WAAW,CAAC,oCAAoC,CAAC;SACjD,MAAM,CAAC,eAAe,EAAE,gCAAgC,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;QACnC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,CAAsB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEL,cAAc;IACb,MAAsE,CAAC,OAAO,CAAC,MAAM,CAAC;SACpF,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,UAAU,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEL,gBAAgB;IACf,MAAsE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACtF,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,YAAY,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEL,cAAc;IACb,MAAsE,CAAC,OAAO,CAAC,MAAM,CAAC;SACpF,WAAW,CAAC,wBAAwB,CAAC;SACrC,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,EAAE,IAAI,CAAC;SAC1D,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAAC;SAC3C,MAAM,CAAC,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;QACnC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,CAAyC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACP,CAAC;AAcD,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAE9E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI — replay subcommand
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* mcp-conductor-cli replay <recordingPath> [--at <seq> --op replace|skip [--with <json>]] ...
|
|
6
|
+
* mcp-conductor-cli replay --list
|
|
7
|
+
*
|
|
8
|
+
* Options:
|
|
9
|
+
* --list List all available recordings
|
|
10
|
+
* --at <n> Sequence index for a modification
|
|
11
|
+
* --op replace|skip Operation to apply at that index
|
|
12
|
+
* --with <json> JSON value for replace operation
|
|
13
|
+
* --recordings-dir <path> Override the recordings directory
|
|
14
|
+
*/
|
|
15
|
+
export declare function runReplayCli(argv?: string[]): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/cli/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAyDH,wBAAsB,YAAY,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CxF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI — replay subcommand
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* mcp-conductor-cli replay <recordingPath> [--at <seq> --op replace|skip [--with <json>]] ...
|
|
6
|
+
* mcp-conductor-cli replay --list
|
|
7
|
+
*
|
|
8
|
+
* Options:
|
|
9
|
+
* --list List all available recordings
|
|
10
|
+
* --at <n> Sequence index for a modification
|
|
11
|
+
* --op replace|skip Operation to apply at that index
|
|
12
|
+
* --with <json> JSON value for replace operation
|
|
13
|
+
* --recordings-dir <path> Override the recordings directory
|
|
14
|
+
*/
|
|
15
|
+
import { ReplayRecorder } from '../observability/index.js';
|
|
16
|
+
import { homedir } from 'node:os';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
function parseArgs(argv) {
|
|
19
|
+
const result = { list: false, modifications: [] };
|
|
20
|
+
let i = 0;
|
|
21
|
+
while (i < argv.length) {
|
|
22
|
+
const arg = argv[i];
|
|
23
|
+
if (arg === '--list') {
|
|
24
|
+
result.list = true;
|
|
25
|
+
i++;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (arg === '--recordings-dir') {
|
|
29
|
+
result.recordingsDir = argv[++i];
|
|
30
|
+
i++;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (arg === '--at') {
|
|
34
|
+
const at = parseInt(argv[++i] ?? '0', 10);
|
|
35
|
+
i++;
|
|
36
|
+
const nextArg = argv[i];
|
|
37
|
+
const op = nextArg === '--op' ? (argv[++i] ?? 'replace') : 'replace';
|
|
38
|
+
if (nextArg === '--op')
|
|
39
|
+
i++;
|
|
40
|
+
let withValue;
|
|
41
|
+
if (i < argv.length && argv[i] === '--with') {
|
|
42
|
+
withValue = JSON.parse(argv[++i] ?? 'null');
|
|
43
|
+
i++;
|
|
44
|
+
}
|
|
45
|
+
result.modifications.push({ at, op: op, with: withValue });
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (arg && !arg.startsWith('--')) {
|
|
49
|
+
result.recordingPath = arg;
|
|
50
|
+
}
|
|
51
|
+
i++;
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
export async function runReplayCli(argv = process.argv.slice(2)) {
|
|
56
|
+
const args = parseArgs(argv);
|
|
57
|
+
const recordingsDir = args.recordingsDir
|
|
58
|
+
?? join(homedir(), '.mcp-conductor', 'recordings');
|
|
59
|
+
const recorder = new ReplayRecorder({ recordingsDir });
|
|
60
|
+
if (args.list) {
|
|
61
|
+
const recordings = recorder.listRecordings();
|
|
62
|
+
if (recordings.length === 0) {
|
|
63
|
+
process.stdout.write('No recordings found.\n');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
for (const r of recordings) {
|
|
67
|
+
const kb = (r.sizeBytes / 1024).toFixed(1);
|
|
68
|
+
const date = new Date(r.createdAt).toISOString();
|
|
69
|
+
process.stdout.write(`${r.sessionId} ${kb} KB ${date}\n`);
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!args.recordingPath) {
|
|
74
|
+
process.stderr.write('Usage: replay <recordingPath> [--at <seq> --op replace|skip [--with <json>]] ...\n' +
|
|
75
|
+
' replay --list\n');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
const { result, divergence } = recorder.replay(args.recordingPath, args.modifications);
|
|
79
|
+
if (divergence) {
|
|
80
|
+
process.stderr.write(`Divergence detected at seq ${divergence.at}:\n` +
|
|
81
|
+
` expected: ${JSON.stringify(divergence.expected)}\n` +
|
|
82
|
+
` actual: ${JSON.stringify(divergence.actual)}\n`);
|
|
83
|
+
}
|
|
84
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
85
|
+
if (divergence) {
|
|
86
|
+
process.exit(2);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/cli/replay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive setup wizard using @inquirer/prompts.
|
|
3
|
+
* Guides the user through discovering Claude configs, importing servers,
|
|
4
|
+
* and optionally cleaning up source configs.
|
|
5
|
+
* @module cli/wizard/setup
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Run the full interactive setup wizard.
|
|
9
|
+
* Falls back to non-interactive mode if TTY is not available (CI).
|
|
10
|
+
*/
|
|
11
|
+
export declare function runSetupWizard(): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/wizard/setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAmEpD"}
|