zcode-acp-server 0.1.0 → 0.3.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 +192 -9
- package/README.zh-CN.md +143 -8
- package/dist/backend/client.d.ts +12 -4
- package/dist/backend/client.d.ts.map +1 -1
- package/dist/backend/client.js +72 -7
- package/dist/backend/client.js.map +1 -1
- package/dist/backend/credentials.d.ts.map +1 -1
- package/dist/backend/credentials.js +2 -1
- package/dist/backend/credentials.js.map +1 -1
- package/dist/backend/listener.d.ts +12 -4
- package/dist/backend/listener.d.ts.map +1 -1
- package/dist/backend/listener.js +68 -12
- package/dist/backend/listener.js.map +1 -1
- package/dist/backend/types.d.ts +1 -1
- package/dist/backend/types.d.ts.map +1 -1
- package/dist/bin/hub.d.ts +16 -0
- package/dist/bin/hub.d.ts.map +1 -0
- package/dist/bin/hub.js +41 -0
- package/dist/bin/hub.js.map +1 -0
- package/dist/bin/quota.d.ts +54 -0
- package/dist/bin/quota.d.ts.map +1 -0
- package/dist/bin/quota.js +333 -0
- package/dist/bin/quota.js.map +1 -0
- package/dist/config/auto-compact.d.ts +23 -0
- package/dist/config/auto-compact.d.ts.map +1 -0
- package/dist/config/auto-compact.js +67 -0
- package/dist/config/auto-compact.js.map +1 -0
- package/dist/config/mcp-discovery.d.ts +34 -0
- package/dist/config/mcp-discovery.d.ts.map +1 -0
- package/dist/config/mcp-discovery.js +153 -0
- package/dist/config/mcp-discovery.js.map +1 -0
- package/dist/config/model-cache.d.ts +12 -1
- package/dist/config/model-cache.d.ts.map +1 -1
- package/dist/config/model-cache.js +30 -8
- package/dist/config/model-cache.js.map +1 -1
- package/dist/config/options.d.ts +87 -9
- package/dist/config/options.d.ts.map +1 -1
- package/dist/config/options.js +248 -45
- package/dist/config/options.js.map +1 -1
- package/dist/config/plugin-commands.d.ts +24 -0
- package/dist/config/plugin-commands.d.ts.map +1 -0
- package/dist/config/plugin-commands.js +107 -0
- package/dist/config/plugin-commands.js.map +1 -0
- package/dist/config/provider-registry.d.ts +60 -0
- package/dist/config/provider-registry.d.ts.map +1 -0
- package/dist/config/provider-registry.js +128 -0
- package/dist/config/provider-registry.js.map +1 -0
- package/dist/config/runtime-model.d.ts +54 -18
- package/dist/config/runtime-model.d.ts.map +1 -1
- package/dist/config/runtime-model.js +105 -61
- package/dist/config/runtime-model.js.map +1 -1
- package/dist/config/skill-discovery.d.ts +35 -0
- package/dist/config/skill-discovery.d.ts.map +1 -0
- package/dist/config/skill-discovery.js +188 -0
- package/dist/config/skill-discovery.js.map +1 -0
- package/dist/handlers/account.d.ts +43 -0
- package/dist/handlers/account.d.ts.map +1 -0
- package/dist/handlers/account.js +59 -0
- package/dist/handlers/account.js.map +1 -0
- package/dist/handlers/background-tasks.d.ts +72 -0
- package/dist/handlers/background-tasks.d.ts.map +1 -0
- package/dist/handlers/background-tasks.js +330 -0
- package/dist/handlers/background-tasks.js.map +1 -0
- package/dist/handlers/dispatch.d.ts.map +1 -1
- package/dist/handlers/dispatch.js +134 -22
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/extensions.d.ts +15 -0
- package/dist/handlers/extensions.d.ts.map +1 -1
- package/dist/handlers/extensions.js +43 -27
- package/dist/handlers/extensions.js.map +1 -1
- package/dist/handlers/io.d.ts +31 -3
- package/dist/handlers/io.d.ts.map +1 -1
- package/dist/handlers/io.js +108 -9
- package/dist/handlers/io.js.map +1 -1
- package/dist/handlers/replay.d.ts +79 -0
- package/dist/handlers/replay.d.ts.map +1 -0
- package/dist/handlers/replay.js +252 -0
- package/dist/handlers/replay.js.map +1 -0
- package/dist/handlers/server-requests.d.ts +20 -4
- package/dist/handlers/server-requests.d.ts.map +1 -1
- package/dist/handlers/server-requests.js +293 -63
- package/dist/handlers/server-requests.js.map +1 -1
- package/dist/handlers/session.d.ts +113 -10
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +932 -277
- package/dist/handlers/session.js.map +1 -1
- package/dist/handlers/slash.d.ts +37 -1
- package/dist/handlers/slash.d.ts.map +1 -1
- package/dist/handlers/slash.js +143 -8
- package/dist/handlers/slash.js.map +1 -1
- package/dist/index.js +76 -12
- package/dist/index.js.map +1 -1
- package/dist/interaction/adapter.d.ts +19 -33
- package/dist/interaction/adapter.d.ts.map +1 -1
- package/dist/interaction/adapter.js +80 -79
- package/dist/interaction/adapter.js.map +1 -1
- package/dist/lazy-sessions.d.ts +35 -0
- package/dist/lazy-sessions.d.ts.map +1 -0
- package/dist/lazy-sessions.js +98 -0
- package/dist/lazy-sessions.js.map +1 -0
- package/dist/quota/cache.d.ts +18 -0
- package/dist/quota/cache.d.ts.map +1 -0
- package/dist/quota/cache.js +32 -0
- package/dist/quota/cache.js.map +1 -0
- package/dist/quota/client.d.ts +30 -0
- package/dist/quota/client.d.ts.map +1 -0
- package/dist/quota/client.js +57 -0
- package/dist/quota/client.js.map +1 -0
- package/dist/quota/color.d.ts +58 -0
- package/dist/quota/color.d.ts.map +1 -0
- package/dist/quota/color.js +95 -0
- package/dist/quota/color.js.map +1 -0
- package/dist/quota/combined.d.ts +66 -0
- package/dist/quota/combined.d.ts.map +1 -0
- package/dist/quota/combined.js +179 -0
- package/dist/quota/combined.js.map +1 -0
- package/dist/quota/format.d.ts +105 -0
- package/dist/quota/format.d.ts.map +1 -0
- package/dist/quota/format.js +219 -0
- package/dist/quota/format.js.map +1 -0
- package/dist/quota/index.d.ts +23 -0
- package/dist/quota/index.d.ts.map +1 -0
- package/dist/quota/index.js +42 -0
- package/dist/quota/index.js.map +1 -0
- package/dist/quota/opencode-go/cache.d.ts +17 -0
- package/dist/quota/opencode-go/cache.d.ts.map +1 -0
- package/dist/quota/opencode-go/cache.js +31 -0
- package/dist/quota/opencode-go/cache.js.map +1 -0
- package/dist/quota/opencode-go/client.d.ts +28 -0
- package/dist/quota/opencode-go/client.d.ts.map +1 -0
- package/dist/quota/opencode-go/client.js +48 -0
- package/dist/quota/opencode-go/client.js.map +1 -0
- package/dist/quota/opencode-go/config.d.ts +37 -0
- package/dist/quota/opencode-go/config.d.ts.map +1 -0
- package/dist/quota/opencode-go/config.js +58 -0
- package/dist/quota/opencode-go/config.js.map +1 -0
- package/dist/quota/opencode-go/format.d.ts +36 -0
- package/dist/quota/opencode-go/format.d.ts.map +1 -0
- package/dist/quota/opencode-go/format.js +87 -0
- package/dist/quota/opencode-go/format.js.map +1 -0
- package/dist/quota/opencode-go/index.d.ts +30 -0
- package/dist/quota/opencode-go/index.d.ts.map +1 -0
- package/dist/quota/opencode-go/index.js +108 -0
- package/dist/quota/opencode-go/index.js.map +1 -0
- package/dist/quota/opencode-go/parse.d.ts +41 -0
- package/dist/quota/opencode-go/parse.d.ts.map +1 -0
- package/dist/quota/opencode-go/parse.js +75 -0
- package/dist/quota/opencode-go/parse.js.map +1 -0
- package/dist/quota/opencode-go/types.d.ts +48 -0
- package/dist/quota/opencode-go/types.d.ts.map +1 -0
- package/dist/quota/opencode-go/types.js +11 -0
- package/dist/quota/opencode-go/types.js.map +1 -0
- package/dist/quota/parse.d.ts +33 -0
- package/dist/quota/parse.d.ts.map +1 -0
- package/dist/quota/parse.js +200 -0
- package/dist/quota/parse.js.map +1 -0
- package/dist/quota/types.d.ts +72 -0
- package/dist/quota/types.d.ts.map +1 -0
- package/dist/quota/types.js +10 -0
- package/dist/quota/types.js.map +1 -0
- package/dist/remote/broadcast.d.ts +47 -0
- package/dist/remote/broadcast.d.ts.map +1 -0
- package/dist/remote/broadcast.js +121 -0
- package/dist/remote/broadcast.js.map +1 -0
- package/dist/remote/config.d.ts +32 -0
- package/dist/remote/config.d.ts.map +1 -0
- package/dist/remote/config.js +65 -0
- package/dist/remote/config.js.map +1 -0
- package/dist/remote/endpoint.d.ts +30 -0
- package/dist/remote/endpoint.d.ts.map +1 -0
- package/dist/remote/endpoint.js +213 -0
- package/dist/remote/endpoint.js.map +1 -0
- package/dist/remote/hub-server.d.ts +41 -0
- package/dist/remote/hub-server.d.ts.map +1 -0
- package/dist/remote/hub-server.js +346 -0
- package/dist/remote/hub-server.js.map +1 -0
- package/dist/server.d.ts +139 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +179 -4
- package/dist/server.js.map +1 -1
- package/dist/tasks-index.d.ts +14 -4
- package/dist/tasks-index.d.ts.map +1 -1
- package/dist/tasks-index.js +145 -46
- package/dist/tasks-index.js.map +1 -1
- package/dist/translators/event-translator.d.ts +33 -0
- package/dist/translators/event-translator.d.ts.map +1 -1
- package/dist/translators/event-translator.js +101 -0
- package/dist/translators/event-translator.js.map +1 -1
- package/dist/translators/index.d.ts +1 -1
- package/dist/translators/index.d.ts.map +1 -1
- package/dist/translators/index.js +1 -1
- package/dist/translators/index.js.map +1 -1
- package/dist/translators/projection-differ.d.ts +8 -0
- package/dist/translators/projection-differ.d.ts.map +1 -1
- package/dist/translators/projection-differ.js +19 -9
- package/dist/translators/projection-differ.js.map +1 -1
- package/dist/translators/tool-helpers.d.ts +28 -0
- package/dist/translators/tool-helpers.d.ts.map +1 -1
- package/dist/translators/tool-helpers.js +104 -0
- package/dist/translators/tool-helpers.js.map +1 -1
- package/dist/translators/types.d.ts +38 -1
- package/dist/translators/types.d.ts.map +1 -1
- package/dist/translators/types.js.map +1 -1
- package/dist/utils.d.ts +36 -7
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +69 -5
- package/dist/utils.js.map +1 -1
- package/docs/ARCHITECTURE.md +130 -40
- package/docs/BACKLOG.md +59 -0
- package/docs/DEVELOPMENT.md +31 -0
- package/docs/PROTOCOL.md +328 -23
- package/docs/REMOTE-CLIENTS.md +260 -0
- package/docs/REPLAY-GUIDE.md +131 -0
- package/docs/TROUBLESHOOTING.md +131 -14
- package/docs/adr/0001-bridge-lifetime-follows-primary-client.md +14 -0
- package/docs/adr/0002-stateless-hub-over-per-bridge-acp-endpoints.md +23 -0
- package/docs/adr/0003-tail-replay-meta-and-cursor-pagination.md +40 -0
- package/docs/agents/domain.md +51 -0
- package/docs/agents/issue-tracker.md +22 -0
- package/docs/agents/triage-labels.md +15 -0
- package/docs/proposals/0001-tail-session-replay.md +136 -0
- package/docs/proposals/0002-plan-quota-usage.md +81 -0
- package/package.json +10 -6
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Standalone CLI for querying GLM Coding Plan usage — a thin wrapper over the
|
|
4
|
+
* same `queryQuota()` + `formatQuotaPlain()` the `/quota` slash command uses.
|
|
5
|
+
*
|
|
6
|
+
* No ACP server, no zcode subprocess: only reads `~/.zcode/v2/config.json` for
|
|
7
|
+
* credentials and hits the quota HTTP API directly.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* zcode-quota one-shot: print the card and exit
|
|
11
|
+
* zcode-quota -w watch mode (default 30s refresh)
|
|
12
|
+
* zcode-quota -w -i 60 watch with a 60s interval
|
|
13
|
+
* zcode-quota -d show per-model MCP detail sub-lines
|
|
14
|
+
* zcode-quota --watch --interval 15
|
|
15
|
+
* zcode-quota -h | --help show help
|
|
16
|
+
*
|
|
17
|
+
* The refresh interval has a 10s floor: the in-memory quota cache TTL is 10s,
|
|
18
|
+
* and a shorter interval would just keep returning the cached value.
|
|
19
|
+
*/
|
|
20
|
+
import process from "node:process";
|
|
21
|
+
import { clearCache as clearGlmCache } from "../quota/cache.js";
|
|
22
|
+
import { defaultGoWindows, formatCombinedCardPlain, queryCombined, } from "../quota/combined.js";
|
|
23
|
+
import { clearGoCache } from "../quota/opencode-go/index.js";
|
|
24
|
+
/** Clear both provider caches — used by watch mode per tick for live values. */
|
|
25
|
+
function clearAllCaches() {
|
|
26
|
+
clearGlmCache();
|
|
27
|
+
clearGoCache();
|
|
28
|
+
}
|
|
29
|
+
/** Minimum watch interval (ms). Equals the quota cache TTL. */
|
|
30
|
+
const MIN_INTERVAL_MS = 10_000;
|
|
31
|
+
/** Default watch interval (ms). */
|
|
32
|
+
const DEFAULT_INTERVAL_MS = 30_000;
|
|
33
|
+
// ANSI escape sequences used by watch mode (no external dep — Local First).
|
|
34
|
+
const ANSI = {
|
|
35
|
+
clearScreen: "\x1B[2J\x1B[H", // clear + cursor home
|
|
36
|
+
clearLine: "\x1B[2K", // clear the entire current line
|
|
37
|
+
hideCursor: "\x1B[?25l",
|
|
38
|
+
showCursor: "\x1B[?25h",
|
|
39
|
+
};
|
|
40
|
+
/** Human-readable usage text. */
|
|
41
|
+
const HELP_TEXT = `Usage: zcode-quota [provider] [options]
|
|
42
|
+
|
|
43
|
+
Query usage from the terminal. By default shows both GLM Coding Plan and
|
|
44
|
+
Opencode Go in one card; pass a provider to focus on one.
|
|
45
|
+
|
|
46
|
+
Providers:
|
|
47
|
+
(none) Both GLM + Opencode Go (rolling + weekly + monthly).
|
|
48
|
+
glm GLM Coding Plan only.
|
|
49
|
+
go Opencode Go only (rolling + weekly + monthly).
|
|
50
|
+
|
|
51
|
+
GLM credentials: read from ~/.zcode/v2/config.json (created by the ZCode app).
|
|
52
|
+
Opencode Go credentials (env vars override the config file, field by field):
|
|
53
|
+
Config file ~/.pi/agent/opencode-go.json {"workspaceId":"wrk_…","authCookie":"Fe26.2**…"}
|
|
54
|
+
OPENCODE_GO_WORKSPACE_ID e.g. wrk_abc123 (from the opencode.ai workspace URL)
|
|
55
|
+
OPENCODE_GO_AUTH_COOKIE the "auth" cookie value (starts with Fe26.2**)
|
|
56
|
+
Get the cookie via browser DevTools → Application → Cookies → opencode.ai.
|
|
57
|
+
|
|
58
|
+
Options:
|
|
59
|
+
-w, --watch Watch mode: clear the screen and refresh periodically.
|
|
60
|
+
-i, --interval <seconds> Refresh interval for watch mode (default 30, min 10).
|
|
61
|
+
-d, --detail Show per-model MCP usage detail sub-lines (GLM only).
|
|
62
|
+
-p, --plain Plain monochrome bars (no color, no in-bar overlay).
|
|
63
|
+
Color is the default on a terminal; disabled
|
|
64
|
+
automatically when stdout is piped or redirected.
|
|
65
|
+
-h, --help Show this help and exit.
|
|
66
|
+
|
|
67
|
+
Examples:
|
|
68
|
+
zcode-quota # both providers, print once and exit (color bars)
|
|
69
|
+
zcode-quota go # Opencode Go only (3 windows)
|
|
70
|
+
zcode-quota glm -w # GLM only, live monitor every 30s
|
|
71
|
+
zcode-quota -w -i 60 # both, refresh every 60s
|
|
72
|
+
zcode-quota -d # both, include per-model MCP breakdown
|
|
73
|
+
zcode-quota --plain # both, classic monochrome bars`;
|
|
74
|
+
/**
|
|
75
|
+
* Clamp a raw interval (seconds, optional) to a valid ms value. Returns the
|
|
76
|
+
* clamped value plus whether a user-supplied value was raised to the floor.
|
|
77
|
+
*
|
|
78
|
+
* Exported for unit testing.
|
|
79
|
+
*/
|
|
80
|
+
export function resolveIntervalMs(seconds) {
|
|
81
|
+
const requested = (seconds ?? DEFAULT_INTERVAL_MS / 1000) * 1000;
|
|
82
|
+
if (requested < MIN_INTERVAL_MS) {
|
|
83
|
+
return { ms: MIN_INTERVAL_MS, clamped: seconds !== undefined };
|
|
84
|
+
}
|
|
85
|
+
return { ms: requested, clamped: false };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Parse argv into {@link CliOptions}. Supports `-w`/`--watch`, `-h`/`--help`,
|
|
89
|
+
* `-i <n>`/`--interval <n>` (space), `--interval=<n>`, and `-i<n>` (attached).
|
|
90
|
+
* The first non-flag positional arg is the provider (`glm`/`go`); any other
|
|
91
|
+
* value is ignored (treated as `all`). Unknown flags are ignored.
|
|
92
|
+
*
|
|
93
|
+
* Exported for unit testing.
|
|
94
|
+
*/
|
|
95
|
+
export function parseArgs(argv) {
|
|
96
|
+
let watch = false;
|
|
97
|
+
let help = false;
|
|
98
|
+
let detail = false;
|
|
99
|
+
let plain = false;
|
|
100
|
+
let interval;
|
|
101
|
+
let provider = "all";
|
|
102
|
+
for (let i = 0; i < argv.length; i++) {
|
|
103
|
+
const arg = argv[i];
|
|
104
|
+
switch (arg) {
|
|
105
|
+
case "-w":
|
|
106
|
+
case "--watch":
|
|
107
|
+
watch = true;
|
|
108
|
+
break;
|
|
109
|
+
case "-d":
|
|
110
|
+
case "--detail":
|
|
111
|
+
detail = true;
|
|
112
|
+
break;
|
|
113
|
+
case "-p":
|
|
114
|
+
case "--plain":
|
|
115
|
+
plain = true;
|
|
116
|
+
break;
|
|
117
|
+
case "-h":
|
|
118
|
+
case "--help":
|
|
119
|
+
help = true;
|
|
120
|
+
break;
|
|
121
|
+
case "-i":
|
|
122
|
+
case "--interval": {
|
|
123
|
+
const next = argv[i + 1];
|
|
124
|
+
if (next !== undefined) {
|
|
125
|
+
const n = Number(next);
|
|
126
|
+
if (Number.isFinite(n))
|
|
127
|
+
interval = n;
|
|
128
|
+
i++; // consume the value
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
default:
|
|
133
|
+
// Support `-i<value>` / `--interval=<value>` attached forms.
|
|
134
|
+
if (arg?.startsWith("--interval=")) {
|
|
135
|
+
const n = Number(arg.slice("--interval=".length));
|
|
136
|
+
if (Number.isFinite(n))
|
|
137
|
+
interval = n;
|
|
138
|
+
}
|
|
139
|
+
else if (arg?.startsWith("-i") && arg.length > 2) {
|
|
140
|
+
const n = Number(arg.slice(2));
|
|
141
|
+
if (Number.isFinite(n))
|
|
142
|
+
interval = n;
|
|
143
|
+
}
|
|
144
|
+
else if (arg === "glm" || arg === "go") {
|
|
145
|
+
// First positional provider token. Only honor the first; a second
|
|
146
|
+
// (e.g. `zcode-quota glm go`) is ignored to keep parsing simple.
|
|
147
|
+
if (provider === "all")
|
|
148
|
+
provider = arg;
|
|
149
|
+
}
|
|
150
|
+
// Other non-flag tokens are ignored (forward-compat / typos).
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const resolved = resolveIntervalMs(interval);
|
|
155
|
+
return {
|
|
156
|
+
watch,
|
|
157
|
+
detail,
|
|
158
|
+
help,
|
|
159
|
+
plain,
|
|
160
|
+
provider,
|
|
161
|
+
intervalMs: resolved.ms,
|
|
162
|
+
intervalClamped: resolved.clamped,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Sleep helper. Accepts an AbortSignal so SIGINT can break the wait early.
|
|
167
|
+
*
|
|
168
|
+
* NOTE: the timer is deliberately NOT `unref()`-ed. In watch mode this sleep
|
|
169
|
+
* is the only thing keeping the event loop alive between ticks; an unref'd
|
|
170
|
+
* timer lets Node exit immediately after the first frame renders, which
|
|
171
|
+
* silently kills the monitor. Only a real abort (Ctrl-C) should end the wait.
|
|
172
|
+
*/
|
|
173
|
+
function sleep(ms, signal) {
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
const t = setTimeout(resolve, ms);
|
|
176
|
+
signal?.addEventListener("abort", () => {
|
|
177
|
+
clearTimeout(t);
|
|
178
|
+
reject(new Error("aborted"));
|
|
179
|
+
}, { once: true });
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/** Format the watch-mode countdown suffix appended to the first header. */
|
|
183
|
+
function refreshSuffix(remainingSec) {
|
|
184
|
+
return `refresh in ${remainingSec}s`;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Render the card for a given provider selection. Centralises the
|
|
188
|
+
* combined-card formatting so watch and one-shot share one code path. In watch
|
|
189
|
+
* mode the refresh countdown is rendered on the separator row after the first
|
|
190
|
+
* section (its position is fixed whether or not a second section appears).
|
|
191
|
+
*
|
|
192
|
+
* `color` switches the bars to a heat-colored (green→red) 24-bit ANSI layout
|
|
193
|
+
* with the usage numbers overlaid inside. The CLI caller gates this on
|
|
194
|
+
* `stdout.isTTY && !plain`.
|
|
195
|
+
*/
|
|
196
|
+
function renderCard(combined, provider, detail, color, refresh) {
|
|
197
|
+
const text = formatCombinedCardPlain(combined, {
|
|
198
|
+
provider,
|
|
199
|
+
glm: { detail },
|
|
200
|
+
goWindows: defaultGoWindows(provider),
|
|
201
|
+
color,
|
|
202
|
+
refreshSuffix: refresh,
|
|
203
|
+
});
|
|
204
|
+
// The refresh line is the one carrying the countdown text. Without a refresh
|
|
205
|
+
// suffix there is no such line. When present it sits right after the first
|
|
206
|
+
// section, so we can find it by matching the suffix.
|
|
207
|
+
let refreshRow = null;
|
|
208
|
+
if (refresh) {
|
|
209
|
+
const lines = text.split("\n");
|
|
210
|
+
const idx = lines.findIndex((l) => l.includes(refresh));
|
|
211
|
+
refreshRow = idx >= 0 ? idx : null;
|
|
212
|
+
}
|
|
213
|
+
return { text, refreshRow };
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Full redraw of one watch frame: clear screen, then the card (with the
|
|
217
|
+
* refresh countdown on the separator row after the first section).
|
|
218
|
+
*/
|
|
219
|
+
function renderFrame(text) {
|
|
220
|
+
return `${ANSI.clearScreen}${text}`;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Run the watch loop until the process is interrupted. Each tick clears both
|
|
224
|
+
* caches (so the displayed values are fresh, not stale cache hits), queries,
|
|
225
|
+
* and redraws. Between ticks a per-second countdown rewrites only the footer
|
|
226
|
+
* line so the card body doesn't flicker. The combined query never throws —
|
|
227
|
+
* each provider degrades internally — so this loop is robust.
|
|
228
|
+
*/
|
|
229
|
+
async function runWatch(intervalMs, provider, detail, color) {
|
|
230
|
+
const intervalSec = Math.round(intervalMs / 1000);
|
|
231
|
+
const controller = new AbortController();
|
|
232
|
+
const restore = () => {
|
|
233
|
+
process.stdout.write(ANSI.showCursor);
|
|
234
|
+
process.stdout.write("\n");
|
|
235
|
+
};
|
|
236
|
+
// Ctrl-C: stop the loop, restore the cursor, exit cleanly.
|
|
237
|
+
const onInt = () => {
|
|
238
|
+
controller.abort();
|
|
239
|
+
restore();
|
|
240
|
+
process.exit(0);
|
|
241
|
+
};
|
|
242
|
+
process.on("SIGINT", onInt);
|
|
243
|
+
process.stdout.write(ANSI.hideCursor);
|
|
244
|
+
try {
|
|
245
|
+
while (!controller.signal.aborted) {
|
|
246
|
+
clearAllCaches(); // bypass caches — always show live values
|
|
247
|
+
const combined = await queryCombined(provider);
|
|
248
|
+
// Full redraw with the countdown starting at the interval max.
|
|
249
|
+
const first = renderCard(combined, provider, detail, color, refreshSuffix(intervalSec));
|
|
250
|
+
process.stdout.write(renderFrame(first.text));
|
|
251
|
+
// Per-second countdown: rewrite only the refresh row (the separator line
|
|
252
|
+
// after the first section), leaving the card body untouched. Its row is
|
|
253
|
+
// fixed for the lifetime of this `combined` result, so we re-render the
|
|
254
|
+
// card with the new countdown purely to extract the refreshed line text,
|
|
255
|
+
// then blast it to that row via cursor-position + clear-line.
|
|
256
|
+
for (let remaining = intervalSec - 1; remaining > 0; remaining--) {
|
|
257
|
+
await sleep(1000, controller.signal).catch(() => undefined);
|
|
258
|
+
if (controller.signal.aborted)
|
|
259
|
+
break;
|
|
260
|
+
const next = renderCard(combined, provider, detail, color, refreshSuffix(remaining));
|
|
261
|
+
if (first.refreshRow !== null && next.refreshRow !== null) {
|
|
262
|
+
const row = first.refreshRow + 1; // ANSI rows are 1-based
|
|
263
|
+
const line = next.text.split("\n")[next.refreshRow] ?? "";
|
|
264
|
+
// Move to (row, col 1), clear the line, write the refreshed countdown.
|
|
265
|
+
process.stdout.write(`\x1B[${row};1H${ANSI.clearLine}${line}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
finally {
|
|
271
|
+
restore();
|
|
272
|
+
process.off("SIGINT", onInt);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Print the card once and exit. A fully-unavailable result (no provider could
|
|
277
|
+
* produce data) → stderr + exit 1, so scripts can detect failure. A partial
|
|
278
|
+
* result (at least one provider succeeded or is merely not_configured) goes
|
|
279
|
+
* to stdout with exit 0.
|
|
280
|
+
*/
|
|
281
|
+
async function runOnce(provider, detail, color) {
|
|
282
|
+
const combined = await queryCombined(provider);
|
|
283
|
+
const out = renderCard(combined, provider, detail, color).text;
|
|
284
|
+
// Failure = every selected provider ended up unavailable (not merely
|
|
285
|
+
// not_configured, which is a deliberate "skip me" state).
|
|
286
|
+
const glmFailed = combined.glm.kind === "unavailable";
|
|
287
|
+
const goFailed = combined.go.kind === "unavailable";
|
|
288
|
+
const glmSelected = provider === "all" || provider === "glm";
|
|
289
|
+
const goSelected = provider === "all" || provider === "go";
|
|
290
|
+
const selectedFailed = (glmSelected && glmFailed && (!goSelected || goFailed)) ||
|
|
291
|
+
(goSelected && goFailed && (!glmSelected || glmFailed));
|
|
292
|
+
if (selectedFailed) {
|
|
293
|
+
process.stderr.write(out + "\n");
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
|
296
|
+
process.stdout.write(out + "\n");
|
|
297
|
+
}
|
|
298
|
+
async function main() {
|
|
299
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
300
|
+
if (opts.help) {
|
|
301
|
+
process.stdout.write(HELP_TEXT + "\n");
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (opts.intervalClamped) {
|
|
305
|
+
process.stderr.write(`zcode-quota: interval below 10s raised to 10s (cache TTL is 10s)\n`);
|
|
306
|
+
}
|
|
307
|
+
// Color is on by default on a real terminal; turn it off when piped/
|
|
308
|
+
// redirected (isTTY is only `true` on a real TTY — Node leaves it
|
|
309
|
+
// `undefined` for pipes/files) or when the user asks for --plain. This
|
|
310
|
+
// matches the common CLI convention (ls, git, grep) and keeps raw escape
|
|
311
|
+
// codes out of captured output.
|
|
312
|
+
const color = process.stdout.isTTY === true && !opts.plain;
|
|
313
|
+
if (opts.watch) {
|
|
314
|
+
await runWatch(opts.intervalMs, opts.provider, opts.detail, color);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
await runOnce(opts.provider, opts.detail, color);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
// Only auto-run when invoked directly (not when imported by tests). In an ESM
|
|
321
|
+
// build there is no `require.main`, so fall back to a heuristic: if argv[1]
|
|
322
|
+
// (the executed script) ends with this file's path, we are the entry point.
|
|
323
|
+
const invokedDirectly = (() => {
|
|
324
|
+
const entry = process.argv[1] ?? "";
|
|
325
|
+
return entry.endsWith("bin/quota.js") || entry.endsWith("bin/quota.ts");
|
|
326
|
+
})();
|
|
327
|
+
if (invokedDirectly) {
|
|
328
|
+
main().catch((err) => {
|
|
329
|
+
process.stderr.write(`zcode-quota: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=quota.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/bin/quota.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-compact: when the session's context-window usage exceeds a threshold,
|
|
3
|
+
* automatically invoke `session/compact` so the next prompt has room.
|
|
4
|
+
*
|
|
5
|
+
* Configured via `ZCODE_ACP_AUTO_COMPACT_THRESHOLD` (absolute token count;
|
|
6
|
+
* 0/unset = disabled). The compaction target is decided by the zcode backend
|
|
7
|
+
* — we only control *when* to trigger.
|
|
8
|
+
*
|
|
9
|
+
* Triggered from `prompt()` after a successful `end_turn`, before the response
|
|
10
|
+
* returns. Failures are best-effort (logged, never thrown) so they never break
|
|
11
|
+
* the prompt response.
|
|
12
|
+
*/
|
|
13
|
+
import type * as acp from "@agentclientprotocol/sdk";
|
|
14
|
+
import type { ZcodeAcpServer } from "../server.js";
|
|
15
|
+
/** ENV: `ZCODE_ACP_AUTO_COMPACT_THRESHOLD` — absolute token count (0 = disabled). */
|
|
16
|
+
export declare function autoCompactThreshold(): number;
|
|
17
|
+
/**
|
|
18
|
+
* If the threshold is configured and the session's current context usage meets
|
|
19
|
+
* or exceeds it, invoke `compact()`. No-op when the threshold is unset/zero,
|
|
20
|
+
* when usage is below the threshold, or on any error (best-effort).
|
|
21
|
+
*/
|
|
22
|
+
export declare function maybeAutoCompact(server: ZcodeAcpServer, cx: acp.AgentContext, acpSid: string, zcodeSid: string): Promise<void>;
|
|
23
|
+
//# sourceMappingURL=auto-compact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-compact.d.ts","sourceRoot":"","sources":["../../src/config/auto-compact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAInD,qFAAqF;AACrF,wBAAgB,oBAAoB,IAAI,MAAM,CAG7C;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA2Df"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-compact: when the session's context-window usage exceeds a threshold,
|
|
3
|
+
* automatically invoke `session/compact` so the next prompt has room.
|
|
4
|
+
*
|
|
5
|
+
* Configured via `ZCODE_ACP_AUTO_COMPACT_THRESHOLD` (absolute token count;
|
|
6
|
+
* 0/unset = disabled). The compaction target is decided by the zcode backend
|
|
7
|
+
* — we only control *when* to trigger.
|
|
8
|
+
*
|
|
9
|
+
* Triggered from `prompt()` after a successful `end_turn`, before the response
|
|
10
|
+
* returns. Failures are best-effort (logged, never thrown) so they never break
|
|
11
|
+
* the prompt response.
|
|
12
|
+
*/
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { compact } from "../handlers/extensions.js";
|
|
15
|
+
import { log, warn } from "../utils.js";
|
|
16
|
+
import { sendTextChunk } from "../handlers/io.js";
|
|
17
|
+
/** ENV: `ZCODE_ACP_AUTO_COMPACT_THRESHOLD` — absolute token count (0 = disabled). */
|
|
18
|
+
export function autoCompactThreshold() {
|
|
19
|
+
const raw = Number(process.env.ZCODE_ACP_AUTO_COMPACT_THRESHOLD ?? "0");
|
|
20
|
+
return Number.isFinite(raw) && raw > 0 ? raw : 0;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* If the threshold is configured and the session's current context usage meets
|
|
24
|
+
* or exceeds it, invoke `compact()`. No-op when the threshold is unset/zero,
|
|
25
|
+
* when usage is below the threshold, or on any error (best-effort).
|
|
26
|
+
*/
|
|
27
|
+
export async function maybeAutoCompact(server, cx, acpSid, zcodeSid) {
|
|
28
|
+
const threshold = autoCompactThreshold();
|
|
29
|
+
if (threshold <= 0)
|
|
30
|
+
return; // disabled
|
|
31
|
+
const msgId = randomUUID();
|
|
32
|
+
try {
|
|
33
|
+
// Read current context usage via session/read.
|
|
34
|
+
let used = 0;
|
|
35
|
+
try {
|
|
36
|
+
const backend = server.ensureBackend();
|
|
37
|
+
const resp = await backend.request(server.nextId(), "session/read", { sessionId: zcodeSid }, 5000);
|
|
38
|
+
if (resp.error)
|
|
39
|
+
return;
|
|
40
|
+
const result = (resp.result ?? {});
|
|
41
|
+
used = result.projection?.contextUsed ?? 0;
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
warn(`auto-compact: session/read failed (${e instanceof Error ? e.message : String(e)})`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (used < threshold)
|
|
48
|
+
return;
|
|
49
|
+
log(`auto-compact: contextUsed=${used} >= threshold=${threshold}, compacting…`);
|
|
50
|
+
await sendTextChunk(cx, acpSid, `🔄 auto-compact: context usage ${used.toLocaleString()} ≥ threshold ${threshold.toLocaleString()}, compressing…`, msgId);
|
|
51
|
+
// compact() handles: session/compact → waitForTurnIdle → emitInitialUsage.
|
|
52
|
+
const result = (await compact(server, { sessionId: acpSid }, cx));
|
|
53
|
+
if (result.__lockTimeout) {
|
|
54
|
+
await sendTextChunk(cx, acpSid, "⚠ auto-compact timed out (300s) — backend may still be processing", msgId);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
await sendTextChunk(cx, acpSid, "✓ auto-compact: context compressed", msgId);
|
|
58
|
+
}
|
|
59
|
+
log("auto-compact: done");
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
warn(`auto-compact: compact failed (${e instanceof Error ? e.message : String(e)})`);
|
|
63
|
+
await sendTextChunk(cx, acpSid, `⚠ auto-compact failed: ${e instanceof Error ? e.message : String(e)}`, msgId);
|
|
64
|
+
// Best-effort: never break the prompt response.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=auto-compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-compact.js","sourceRoot":"","sources":["../../src/config/auto-compact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEpD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,qFAAqF;AACrF,MAAM,UAAU,oBAAoB;IAClC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,IAAI,GAAG,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAsB,EACtB,EAAoB,EACpB,MAAc,EACd,QAAgB;IAEhB,MAAM,SAAS,GAAG,oBAAoB,EAAE,CAAC;IACzC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,CAAC,WAAW;IAEvC,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,+CAA+C;QAC/C,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAChC,MAAM,CAAC,MAAM,EAAE,EACf,cAAc,EACd,EAAE,SAAS,EAAE,QAAQ,EAAE,EACvB,IAAI,CACL,CAAC;YACF,IAAI,IAAI,CAAC,KAAK;gBAAE,OAAO;YACvB,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAA8C,CAAC;YAChF,IAAI,GAAG,MAAM,CAAC,UAAU,EAAE,WAAW,IAAI,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,sCAAsC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1F,OAAO;QACT,CAAC;QAED,IAAI,IAAI,GAAG,SAAS;YAAE,OAAO;QAE7B,GAAG,CAAC,6BAA6B,IAAI,iBAAiB,SAAS,eAAe,CAAC,CAAC;QAChF,MAAM,aAAa,CACjB,EAAE,EACF,MAAM,EACN,kCAAkC,IAAI,CAAC,cAAc,EAAE,gBAAgB,SAAS,CAAC,cAAc,EAAE,gBAAgB,EACjH,KAAK,CACN,CAAC;QAEF,2EAA2E;QAC3E,MAAM,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAE/D,CAAC;QACF,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,MAAM,aAAa,CACjB,EAAE,EACF,MAAM,EACN,mEAAmE,EACnE,KAAK,CACN,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,oCAAoC,EAAE,KAAK,CAAC,CAAC;QAC/E,CAAC;QACD,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,iCAAiC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACrF,MAAM,aAAa,CACjB,EAAE,EACF,MAAM,EACN,0BAA0B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EACtE,KAAK,CACN,CAAC;QACF,gDAAgD;IAClD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server discovery — reads MCP server configurations from the same sources
|
|
3
|
+
* ZCode uses, so `/mcp` can show users exactly which servers are available.
|
|
4
|
+
*
|
|
5
|
+
* Sources:
|
|
6
|
+
* 1. ~/.zcode/cli/config.json → mcp.servers (user-configured)
|
|
7
|
+
* 2. Enabled plugin .mcp.json files (two formats: flat and nested)
|
|
8
|
+
*
|
|
9
|
+
* The ZCode backend loads these automatically and exposes their tools to the
|
|
10
|
+
* model. This module is purely informational — it lists what's configured so
|
|
11
|
+
* users know what's available without needing the TUI.
|
|
12
|
+
*/
|
|
13
|
+
/** Information about a discovered MCP server. */
|
|
14
|
+
export interface McpServerInfo {
|
|
15
|
+
name: string;
|
|
16
|
+
type: string;
|
|
17
|
+
command?: string;
|
|
18
|
+
args?: string[];
|
|
19
|
+
url?: string;
|
|
20
|
+
source: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Discover all MCP servers from config.json and enabled plugins.
|
|
24
|
+
*
|
|
25
|
+
* Best-effort: failures are logged and swallowed.
|
|
26
|
+
*/
|
|
27
|
+
export declare function loadMcpServers(): McpServerInfo[];
|
|
28
|
+
/**
|
|
29
|
+
* Format MCP servers into a human-readable card for the `/mcp` command.
|
|
30
|
+
*
|
|
31
|
+
* Groups by source (config vs plugins) and aligns columns for readability.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatMcpServers(servers: McpServerInfo[]): string;
|
|
34
|
+
//# sourceMappingURL=mcp-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-discovery.d.ts","sourceRoot":"","sources":["../../src/config/mcp-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAsBD;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,aAAa,EAAE,CAmFhD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,CA2BjE"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server discovery — reads MCP server configurations from the same sources
|
|
3
|
+
* ZCode uses, so `/mcp` can show users exactly which servers are available.
|
|
4
|
+
*
|
|
5
|
+
* Sources:
|
|
6
|
+
* 1. ~/.zcode/cli/config.json → mcp.servers (user-configured)
|
|
7
|
+
* 2. Enabled plugin .mcp.json files (two formats: flat and nested)
|
|
8
|
+
*
|
|
9
|
+
* The ZCode backend loads these automatically and exposes their tools to the
|
|
10
|
+
* model. This module is purely informational — it lists what's configured so
|
|
11
|
+
* users know what's available without needing the TUI.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { compareVersions, log } from "../utils.js";
|
|
17
|
+
const HOME = homedir();
|
|
18
|
+
const CLI_CONFIG_PATH = path.join(HOME, ".zcode", "cli", "config.json");
|
|
19
|
+
const PLUGIN_CACHE_DIR = path.join(HOME, ".zcode", "cli", "plugins", "cache");
|
|
20
|
+
/**
|
|
21
|
+
* Discover all MCP servers from config.json and enabled plugins.
|
|
22
|
+
*
|
|
23
|
+
* Best-effort: failures are logged and swallowed.
|
|
24
|
+
*/
|
|
25
|
+
export function loadMcpServers() {
|
|
26
|
+
const results = [];
|
|
27
|
+
let config = null;
|
|
28
|
+
try {
|
|
29
|
+
if (existsSync(CLI_CONFIG_PATH)) {
|
|
30
|
+
config = JSON.parse(readFileSync(CLI_CONFIG_PATH, "utf8"));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
log(`mcp-discovery: config read failed (${e instanceof Error ? e.message : String(e)})`);
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
37
|
+
// 1. User-configured servers from config.json.
|
|
38
|
+
const servers = config?.mcp?.servers ?? {};
|
|
39
|
+
for (const [name, cfg] of Object.entries(servers)) {
|
|
40
|
+
results.push({
|
|
41
|
+
name,
|
|
42
|
+
type: cfg.type ?? "stdio",
|
|
43
|
+
command: cfg.command,
|
|
44
|
+
args: cfg.args,
|
|
45
|
+
url: cfg.url,
|
|
46
|
+
source: "config",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
// 2. Plugin-provided servers from .mcp.json files.
|
|
50
|
+
const enabledPlugins = config?.plugins?.enabledPlugins ?? {};
|
|
51
|
+
for (const [pluginKey, enabledFlag] of Object.entries(enabledPlugins)) {
|
|
52
|
+
if (!enabledFlag)
|
|
53
|
+
continue;
|
|
54
|
+
const atIdx = pluginKey.indexOf("@");
|
|
55
|
+
if (atIdx <= 0)
|
|
56
|
+
continue;
|
|
57
|
+
const pluginName = pluginKey.slice(0, atIdx);
|
|
58
|
+
const marketplace = pluginKey.slice(atIdx + 1);
|
|
59
|
+
const pluginDir = path.join(PLUGIN_CACHE_DIR, marketplace, pluginName);
|
|
60
|
+
if (!existsSync(pluginDir))
|
|
61
|
+
continue;
|
|
62
|
+
// Find the latest version directory.
|
|
63
|
+
let latestVersion = "";
|
|
64
|
+
try {
|
|
65
|
+
for (const entry of readdirSync(pluginDir)) {
|
|
66
|
+
const vDir = path.join(pluginDir, entry);
|
|
67
|
+
if (statSync(vDir).isDirectory() && compareVersions(entry, latestVersion) > 0) {
|
|
68
|
+
latestVersion = entry;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (!latestVersion)
|
|
76
|
+
continue;
|
|
77
|
+
const mcpFile = path.join(pluginDir, latestVersion, ".mcp.json");
|
|
78
|
+
if (!existsSync(mcpFile))
|
|
79
|
+
continue;
|
|
80
|
+
try {
|
|
81
|
+
const mcpConfig = JSON.parse(readFileSync(mcpFile, "utf8"));
|
|
82
|
+
// Two formats:
|
|
83
|
+
// Flat: { "server-name": { "command": "..." } }
|
|
84
|
+
// Nested: { "mcpServers": { "server-name": { ... } } }
|
|
85
|
+
const serverMap = mcpConfig["mcpServers"] ?? mcpConfig;
|
|
86
|
+
for (const [name, cfg] of Object.entries(serverMap)) {
|
|
87
|
+
results.push({
|
|
88
|
+
name,
|
|
89
|
+
type: cfg.type ?? "stdio",
|
|
90
|
+
command: cfg.command,
|
|
91
|
+
args: cfg.args,
|
|
92
|
+
url: cfg.url,
|
|
93
|
+
source: `plugin: ${pluginName}`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
log(`mcp-discovery: failed to read ${mcpFile} (${e instanceof Error ? e.message : String(e)})`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
log(`mcp-discovery: found ${results.length} MCP server(s)`);
|
|
102
|
+
return results;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Format MCP servers into a human-readable card for the `/mcp` command.
|
|
106
|
+
*
|
|
107
|
+
* Groups by source (config vs plugins) and aligns columns for readability.
|
|
108
|
+
*/
|
|
109
|
+
export function formatMcpServers(servers) {
|
|
110
|
+
if (servers.length === 0) {
|
|
111
|
+
return "📡 No MCP servers configured.\nUse the ZCode desktop app to add MCP servers.";
|
|
112
|
+
}
|
|
113
|
+
const configServers = servers.filter((s) => s.source === "config");
|
|
114
|
+
const pluginServers = servers.filter((s) => s.source !== "config");
|
|
115
|
+
const lines = [`📡 MCP Servers (${servers.length})`];
|
|
116
|
+
if (configServers.length > 0) {
|
|
117
|
+
lines.push("", "From config.json:");
|
|
118
|
+
for (const s of configServers) {
|
|
119
|
+
lines.push(` ${pad(s.name, 16)} ${pad(s.type, 6)} ${formatEndpoint(s)}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (pluginServers.length > 0) {
|
|
123
|
+
lines.push("", "From plugins:");
|
|
124
|
+
for (const s of pluginServers) {
|
|
125
|
+
const pluginLabel = `[${s.source.replace("plugin: ", "")}]`;
|
|
126
|
+
lines.push(` ${pad(s.name, 16)} ${pad(s.type, 6)} ${formatEndpoint(s)} ${pluginLabel}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
lines.push("", "MCP tools are auto-invoked by the model when needed.");
|
|
130
|
+
return lines.join("\n");
|
|
131
|
+
}
|
|
132
|
+
/** Format the endpoint/command string for display. */
|
|
133
|
+
function formatEndpoint(s) {
|
|
134
|
+
if (s.url) {
|
|
135
|
+
try {
|
|
136
|
+
const u = new URL(s.url);
|
|
137
|
+
return u.host + u.pathname;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return s.url;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (s.command) {
|
|
144
|
+
const args = s.args?.length ? " " + s.args.join(" ") : "";
|
|
145
|
+
return s.command + args;
|
|
146
|
+
}
|
|
147
|
+
return "?";
|
|
148
|
+
}
|
|
149
|
+
/** Pad a string to the given width for column alignment. */
|
|
150
|
+
function pad(s, width) {
|
|
151
|
+
return s.length >= width ? s : s + " ".repeat(width - s.length);
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=mcp-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-discovery.js","sourceRoot":"","sources":["../../src/config/mcp-discovery.ts"],"names":[],"mappings":"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"}
|