cleargate 0.7.0 → 0.8.1
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/dist/MANIFEST.json +2 -2
- package/dist/cli.cjs +256 -29
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +252 -29
- package/dist/cli.js.map +1 -1
- package/dist/templates/cleargate-planning/MANIFEST.json +2 -2
- package/package.json +1 -1
- package/templates/cleargate-planning/MANIFEST.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ import { Command } from "commander";
|
|
|
14
14
|
// package.json
|
|
15
15
|
var package_default = {
|
|
16
16
|
name: "cleargate",
|
|
17
|
-
version: "0.
|
|
17
|
+
version: "0.8.1",
|
|
18
18
|
private: false,
|
|
19
19
|
type: "module",
|
|
20
20
|
description: "Planning framework for Claude Code agents \u2014 sprint/epic/story protocol, four-agent loop (architect/developer/qa/reporter), Karpathy-style awareness wiki.",
|
|
@@ -1423,9 +1423,16 @@ function mergeMcpJson(existing, entry) {
|
|
|
1423
1423
|
next.mcpServers = servers;
|
|
1424
1424
|
return JSON.stringify(next, null, 2) + "\n";
|
|
1425
1425
|
}
|
|
1426
|
-
function
|
|
1426
|
+
function buildStdioEntry(pinVersion) {
|
|
1427
|
+
return {
|
|
1428
|
+
command: "npx",
|
|
1429
|
+
args: ["-y", `cleargate@${pinVersion}`, "mcp", "serve"]
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
var STDIO_ENTRY_DEFAULT = buildStdioEntry("latest");
|
|
1433
|
+
function injectMcpJson(cwd, pinVersion = "latest") {
|
|
1427
1434
|
const dst = path5.join(cwd, ".mcp.json");
|
|
1428
|
-
const entry =
|
|
1435
|
+
const entry = buildStdioEntry(pinVersion);
|
|
1429
1436
|
let existing = null;
|
|
1430
1437
|
let existingRaw = null;
|
|
1431
1438
|
if (fs6.existsSync(dst)) {
|
|
@@ -2518,7 +2525,7 @@ async function initHandler(opts = {}) {
|
|
|
2518
2525
|
`);
|
|
2519
2526
|
}
|
|
2520
2527
|
try {
|
|
2521
|
-
const action = injectMcpJson(cwd, "
|
|
2528
|
+
const action = injectMcpJson(cwd, pinVersion ?? "latest");
|
|
2522
2529
|
if (action === "created") {
|
|
2523
2530
|
stdout(
|
|
2524
2531
|
`[cleargate init] Created .mcp.json (cleargate MCP server registered) \u2014 restart Claude Code to load it.
|
|
@@ -7335,7 +7342,7 @@ function extractFrontmatterBlock(raw) {
|
|
|
7335
7342
|
// src/lib/intake.ts
|
|
7336
7343
|
async function runIntakeBranch(opts) {
|
|
7337
7344
|
const {
|
|
7338
|
-
mcp,
|
|
7345
|
+
mcp: mcp2,
|
|
7339
7346
|
identity,
|
|
7340
7347
|
sprintRoot,
|
|
7341
7348
|
projectRoot,
|
|
@@ -7346,7 +7353,7 @@ async function runIntakeBranch(opts) {
|
|
|
7346
7353
|
const pendingSyncDir = path36.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
7347
7354
|
let remoteItems = [];
|
|
7348
7355
|
try {
|
|
7349
|
-
remoteItems = await
|
|
7356
|
+
remoteItems = await mcp2.call(
|
|
7350
7357
|
"cleargate_detect_new_items",
|
|
7351
7358
|
{ label: labelFilter }
|
|
7352
7359
|
);
|
|
@@ -7705,9 +7712,9 @@ async function syncCheckHandler(opts = {}) {
|
|
|
7705
7712
|
}
|
|
7706
7713
|
} catch {
|
|
7707
7714
|
}
|
|
7708
|
-
let
|
|
7715
|
+
let mcp2;
|
|
7709
7716
|
if (opts.mcp) {
|
|
7710
|
-
|
|
7717
|
+
mcp2 = opts.mcp;
|
|
7711
7718
|
} else {
|
|
7712
7719
|
let baseUrl = env["CLEARGATE_MCP_URL"];
|
|
7713
7720
|
if (!baseUrl || !baseUrl.trim()) {
|
|
@@ -7736,10 +7743,10 @@ async function syncCheckHandler(opts = {}) {
|
|
|
7736
7743
|
await emitError("adapter-not-configured", nowIso);
|
|
7737
7744
|
return;
|
|
7738
7745
|
}
|
|
7739
|
-
|
|
7746
|
+
mcp2 = createMcpClient({ baseUrl: baseUrl.trim(), token: accessToken });
|
|
7740
7747
|
}
|
|
7741
7748
|
try {
|
|
7742
|
-
const adapterInfo = await
|
|
7749
|
+
const adapterInfo = await mcp2.adapterInfo();
|
|
7743
7750
|
if (!adapterInfo.configured || adapterInfo.name === "no-adapter-configured") {
|
|
7744
7751
|
await emitError("adapter-not-configured", nowIso);
|
|
7745
7752
|
return;
|
|
@@ -7748,7 +7755,7 @@ async function syncCheckHandler(opts = {}) {
|
|
|
7748
7755
|
}
|
|
7749
7756
|
let refs;
|
|
7750
7757
|
try {
|
|
7751
|
-
refs = await
|
|
7758
|
+
refs = await mcp2.call("cleargate_list_remote_updates", { since });
|
|
7752
7759
|
} catch (err) {
|
|
7753
7760
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7754
7761
|
await emitError(msg, nowIso);
|
|
@@ -7768,9 +7775,9 @@ async function syncHandler(opts = {}) {
|
|
|
7768
7775
|
const identity = resolveIdentity(projectRoot);
|
|
7769
7776
|
const sprintRoot = resolveActiveSprintDir(projectRoot);
|
|
7770
7777
|
const sprintId = path40.basename(sprintRoot);
|
|
7771
|
-
let
|
|
7778
|
+
let mcp2;
|
|
7772
7779
|
if (opts.mcp) {
|
|
7773
|
-
|
|
7780
|
+
mcp2 = opts.mcp;
|
|
7774
7781
|
} else {
|
|
7775
7782
|
let baseUrl = env["CLEARGATE_MCP_URL"];
|
|
7776
7783
|
if (!baseUrl || !baseUrl.trim()) {
|
|
@@ -7813,11 +7820,11 @@ async function syncHandler(opts = {}) {
|
|
|
7813
7820
|
exit(2);
|
|
7814
7821
|
return;
|
|
7815
7822
|
}
|
|
7816
|
-
|
|
7823
|
+
mcp2 = createMcpClient({ baseUrl: baseUrl.trim(), token: accessToken });
|
|
7817
7824
|
}
|
|
7818
7825
|
let adapterInfo;
|
|
7819
7826
|
try {
|
|
7820
|
-
adapterInfo = await
|
|
7827
|
+
adapterInfo = await mcp2.adapterInfo();
|
|
7821
7828
|
} catch {
|
|
7822
7829
|
adapterInfo = { configured: true, name: "unknown" };
|
|
7823
7830
|
}
|
|
@@ -7838,13 +7845,13 @@ async function syncHandler(opts = {}) {
|
|
|
7838
7845
|
}
|
|
7839
7846
|
} catch {
|
|
7840
7847
|
}
|
|
7841
|
-
const remoteRefs = await
|
|
7848
|
+
const remoteRefs = await mcp2.call(
|
|
7842
7849
|
"cleargate_list_remote_updates",
|
|
7843
7850
|
{ since: lastRemoteSync }
|
|
7844
7851
|
);
|
|
7845
7852
|
const pulled = [];
|
|
7846
7853
|
for (const ref of remoteRefs) {
|
|
7847
|
-
const item = await
|
|
7854
|
+
const item = await mcp2.call(
|
|
7848
7855
|
"cleargate_pull_item",
|
|
7849
7856
|
{ remote_id: ref.remote_id }
|
|
7850
7857
|
);
|
|
@@ -7856,7 +7863,7 @@ async function syncHandler(opts = {}) {
|
|
|
7856
7863
|
let intakeResult = { created: 0, items: [] };
|
|
7857
7864
|
try {
|
|
7858
7865
|
intakeResult = await runIntakeBranch({
|
|
7859
|
-
mcp,
|
|
7866
|
+
mcp: mcp2,
|
|
7860
7867
|
identity,
|
|
7861
7868
|
sprintRoot,
|
|
7862
7869
|
projectRoot,
|
|
@@ -7882,7 +7889,7 @@ async function syncHandler(opts = {}) {
|
|
|
7882
7889
|
const activeSet = await resolveActiveItems(projectRoot, localRefs, nowFn);
|
|
7883
7890
|
for (const remoteId of activeSet) {
|
|
7884
7891
|
try {
|
|
7885
|
-
const comments = await
|
|
7892
|
+
const comments = await mcp2.call(
|
|
7886
7893
|
"cleargate_pull_comments",
|
|
7887
7894
|
{ remote_id: remoteId }
|
|
7888
7895
|
);
|
|
@@ -8036,7 +8043,7 @@ async function syncHandler(opts = {}) {
|
|
|
8036
8043
|
await appendSyncLog(sprintRoot, entry);
|
|
8037
8044
|
}
|
|
8038
8045
|
for (const { localPath, fm, body, itemId } of pushQueue) {
|
|
8039
|
-
await
|
|
8046
|
+
await mcp2.call("push_item", {
|
|
8040
8047
|
cleargate_id: itemId,
|
|
8041
8048
|
type: typeof fm["story_id"] === "string" ? "story" : typeof fm["epic_id"] === "string" ? "epic" : typeof fm["proposal_id"] === "string" ? "proposal" : "story",
|
|
8042
8049
|
payload: fm
|
|
@@ -8166,9 +8173,9 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8166
8173
|
const nowFn = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
8167
8174
|
const identity = resolveIdentity(projectRoot);
|
|
8168
8175
|
const sprintRoot = resolveActiveSprintDir(projectRoot);
|
|
8169
|
-
let
|
|
8176
|
+
let mcp2;
|
|
8170
8177
|
if (opts.mcp) {
|
|
8171
|
-
|
|
8178
|
+
mcp2 = opts.mcp;
|
|
8172
8179
|
} else {
|
|
8173
8180
|
let baseUrl = env["CLEARGATE_MCP_URL"];
|
|
8174
8181
|
if (!baseUrl || !baseUrl.trim()) {
|
|
@@ -8203,7 +8210,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8203
8210
|
exit(2);
|
|
8204
8211
|
return;
|
|
8205
8212
|
}
|
|
8206
|
-
|
|
8213
|
+
mcp2 = createMcpClient({ baseUrl: baseUrl.trim(), token: accessToken });
|
|
8207
8214
|
}
|
|
8208
8215
|
const remoteId = await resolveRemoteId(idOrRemoteId, projectRoot);
|
|
8209
8216
|
if (!remoteId) {
|
|
@@ -8212,7 +8219,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8212
8219
|
exit(1);
|
|
8213
8220
|
return;
|
|
8214
8221
|
}
|
|
8215
|
-
const remoteItem = await
|
|
8222
|
+
const remoteItem = await mcp2.call("cleargate_pull_item", { remote_id: remoteId });
|
|
8216
8223
|
if (!remoteItem) {
|
|
8217
8224
|
stderr(`Error: item ${remoteId} not found on MCP server.
|
|
8218
8225
|
`);
|
|
@@ -8272,7 +8279,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8272
8279
|
stdout(`pull: ${remoteId} applied to ${path41.relative(projectRoot, localPath)}
|
|
8273
8280
|
`);
|
|
8274
8281
|
if (opts.comments) {
|
|
8275
|
-
const comments = await
|
|
8282
|
+
const comments = await mcp2.call(
|
|
8276
8283
|
"cleargate_pull_comments",
|
|
8277
8284
|
{ remote_id: remoteId }
|
|
8278
8285
|
);
|
|
@@ -8467,10 +8474,10 @@ async function handlePush(filePath, ctx) {
|
|
|
8467
8474
|
if (h1) payloadForPush["title"] = h1;
|
|
8468
8475
|
}
|
|
8469
8476
|
payloadForPush["body"] = body;
|
|
8470
|
-
const
|
|
8477
|
+
const mcp2 = await resolveMcp();
|
|
8471
8478
|
let result;
|
|
8472
8479
|
try {
|
|
8473
|
-
result = await
|
|
8480
|
+
result = await mcp2.call("push_item", {
|
|
8474
8481
|
cleargate_id: itemId,
|
|
8475
8482
|
type,
|
|
8476
8483
|
payload: payloadForPush,
|
|
@@ -8522,9 +8529,9 @@ async function handleRevert(idOrRemoteId, ctx) {
|
|
|
8522
8529
|
exit(1);
|
|
8523
8530
|
return;
|
|
8524
8531
|
}
|
|
8525
|
-
const
|
|
8532
|
+
const mcp2 = await resolveMcp();
|
|
8526
8533
|
try {
|
|
8527
|
-
await
|
|
8534
|
+
await mcp2.call("sync_status", {
|
|
8528
8535
|
cleargate_id: itemId,
|
|
8529
8536
|
new_status: "archived-without-shipping"
|
|
8530
8537
|
});
|
|
@@ -8957,6 +8964,214 @@ function hotfixNewHandler(opts, cli) {
|
|
|
8957
8964
|
return exitFn(0);
|
|
8958
8965
|
}
|
|
8959
8966
|
|
|
8967
|
+
// src/commands/mcp-serve.ts
|
|
8968
|
+
import * as readline5 from "readline";
|
|
8969
|
+
|
|
8970
|
+
// src/auth/refresh.ts
|
|
8971
|
+
async function refreshAccessToken(baseUrl, refreshToken, deps = {}) {
|
|
8972
|
+
const fetchFn = deps.fetch ?? globalThis.fetch;
|
|
8973
|
+
const res = await fetchFn(`${baseUrl}/auth/refresh`, {
|
|
8974
|
+
method: "POST",
|
|
8975
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
8976
|
+
body: JSON.stringify({ refresh_token: refreshToken })
|
|
8977
|
+
});
|
|
8978
|
+
if (!res.ok) {
|
|
8979
|
+
const body = await res.json().catch(() => ({}));
|
|
8980
|
+
throw new RefreshError(res.status, body.error ?? "unknown_error");
|
|
8981
|
+
}
|
|
8982
|
+
const json = await res.json();
|
|
8983
|
+
if (typeof json.access_token !== "string" || typeof json.refresh_token !== "string" || typeof json.expires_in !== "number") {
|
|
8984
|
+
throw new RefreshError(500, "malformed_response");
|
|
8985
|
+
}
|
|
8986
|
+
return json;
|
|
8987
|
+
}
|
|
8988
|
+
var RefreshError = class extends Error {
|
|
8989
|
+
constructor(status, code) {
|
|
8990
|
+
super(`refresh failed: ${status} ${code}`);
|
|
8991
|
+
this.status = status;
|
|
8992
|
+
this.code = code;
|
|
8993
|
+
this.name = "RefreshError";
|
|
8994
|
+
}
|
|
8995
|
+
status;
|
|
8996
|
+
code;
|
|
8997
|
+
};
|
|
8998
|
+
var AuthFetcher = class {
|
|
8999
|
+
constructor(opts) {
|
|
9000
|
+
this.opts = opts;
|
|
9001
|
+
}
|
|
9002
|
+
opts;
|
|
9003
|
+
accessToken = null;
|
|
9004
|
+
accessExpiresAt = 0;
|
|
9005
|
+
inflight = null;
|
|
9006
|
+
/** Returns a fresh access token, refreshing if needed. */
|
|
9007
|
+
async getAccessToken() {
|
|
9008
|
+
const now = (this.opts.now ?? (() => Date.now()))();
|
|
9009
|
+
const skewMs = (this.opts.skewSeconds ?? 60) * 1e3;
|
|
9010
|
+
if (this.accessToken && now < this.accessExpiresAt - skewMs) {
|
|
9011
|
+
return this.accessToken;
|
|
9012
|
+
}
|
|
9013
|
+
if (this.inflight) return this.inflight;
|
|
9014
|
+
this.inflight = this.refreshNow().finally(() => {
|
|
9015
|
+
this.inflight = null;
|
|
9016
|
+
});
|
|
9017
|
+
return this.inflight;
|
|
9018
|
+
}
|
|
9019
|
+
/** Force the next call to refresh. Used after a 401. */
|
|
9020
|
+
invalidate() {
|
|
9021
|
+
this.accessToken = null;
|
|
9022
|
+
this.accessExpiresAt = 0;
|
|
9023
|
+
}
|
|
9024
|
+
async refreshNow() {
|
|
9025
|
+
const stored = await this.opts.loadRefresh();
|
|
9026
|
+
if (!stored) {
|
|
9027
|
+
throw new RefreshError(401, "no_refresh_token");
|
|
9028
|
+
}
|
|
9029
|
+
const exchanged = await refreshAccessToken(this.opts.baseUrl, stored, {
|
|
9030
|
+
...this.opts.fetch ? { fetch: this.opts.fetch } : {},
|
|
9031
|
+
...this.opts.now ? { now: this.opts.now } : {}
|
|
9032
|
+
});
|
|
9033
|
+
await this.opts.saveRefresh(exchanged.refresh_token);
|
|
9034
|
+
const now = (this.opts.now ?? (() => Date.now()))();
|
|
9035
|
+
this.accessToken = exchanged.access_token;
|
|
9036
|
+
this.accessExpiresAt = now + exchanged.expires_in * 1e3;
|
|
9037
|
+
return exchanged.access_token;
|
|
9038
|
+
}
|
|
9039
|
+
};
|
|
9040
|
+
|
|
9041
|
+
// src/commands/mcp-serve.ts
|
|
9042
|
+
var DEFAULT_BASE_URL = "https://cleargate-mcp.soula.ge";
|
|
9043
|
+
async function mcpServeHandler(opts) {
|
|
9044
|
+
const fetchFn = opts.fetch ?? globalThis.fetch;
|
|
9045
|
+
const stdout = opts.stdout ?? ((s) => process.stdout.write(s));
|
|
9046
|
+
const stderr = opts.stderr ?? ((s) => process.stderr.write(s));
|
|
9047
|
+
const exit = opts.exit ?? ((c) => process.exit(c));
|
|
9048
|
+
const cfg = loadConfig({
|
|
9049
|
+
flags: { profile: opts.profile, mcpUrl: opts.mcpUrlFlag }
|
|
9050
|
+
});
|
|
9051
|
+
const baseUrl = cfg.mcpUrl ?? DEFAULT_BASE_URL;
|
|
9052
|
+
const store = await (opts.createStore ?? createTokenStore)({
|
|
9053
|
+
...opts.keychainService !== void 0 ? { keychainService: opts.keychainService } : {},
|
|
9054
|
+
...opts.forceBackend !== void 0 ? { forceBackend: opts.forceBackend } : {}
|
|
9055
|
+
});
|
|
9056
|
+
const fetcher = new AuthFetcher({
|
|
9057
|
+
baseUrl,
|
|
9058
|
+
loadRefresh: () => store.load(opts.profile),
|
|
9059
|
+
saveRefresh: (t) => store.save(opts.profile, t),
|
|
9060
|
+
...opts.fetch !== void 0 ? { fetch: opts.fetch } : {},
|
|
9061
|
+
...opts.now !== void 0 ? { now: opts.now } : {}
|
|
9062
|
+
});
|
|
9063
|
+
try {
|
|
9064
|
+
await fetcher.getAccessToken();
|
|
9065
|
+
} catch (err) {
|
|
9066
|
+
if (err instanceof RefreshError) {
|
|
9067
|
+
stderr(
|
|
9068
|
+
`cleargate mcp serve: refresh failed (${err.status} ${err.code}). Run \`cleargate join <invite-url>\` to re-authenticate.
|
|
9069
|
+
`
|
|
9070
|
+
);
|
|
9071
|
+
} else {
|
|
9072
|
+
stderr(
|
|
9073
|
+
`cleargate mcp serve: ${err instanceof Error ? err.message : String(err)}
|
|
9074
|
+
`
|
|
9075
|
+
);
|
|
9076
|
+
}
|
|
9077
|
+
return exit(1);
|
|
9078
|
+
}
|
|
9079
|
+
const inputStream = opts.stdin ?? process.stdin;
|
|
9080
|
+
const rl = readline5.createInterface({
|
|
9081
|
+
input: inputStream,
|
|
9082
|
+
output: void 0,
|
|
9083
|
+
terminal: false
|
|
9084
|
+
});
|
|
9085
|
+
for await (const line of rl) {
|
|
9086
|
+
if (!line.trim()) continue;
|
|
9087
|
+
try {
|
|
9088
|
+
await proxyOne(line, baseUrl, fetcher, fetchFn, stdout, stderr);
|
|
9089
|
+
} catch (err) {
|
|
9090
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
9091
|
+
stderr(`cleargate mcp serve: proxy error: ${errMsg}
|
|
9092
|
+
`);
|
|
9093
|
+
const id = extractId(line);
|
|
9094
|
+
if (id !== void 0) {
|
|
9095
|
+
stdout(
|
|
9096
|
+
JSON.stringify({
|
|
9097
|
+
jsonrpc: "2.0",
|
|
9098
|
+
id,
|
|
9099
|
+
error: { code: -32603, message: `proxy error: ${errMsg}` }
|
|
9100
|
+
}) + "\n"
|
|
9101
|
+
);
|
|
9102
|
+
}
|
|
9103
|
+
}
|
|
9104
|
+
}
|
|
9105
|
+
}
|
|
9106
|
+
async function proxyOne(line, baseUrl, fetcher, fetchFn, stdout, stderr) {
|
|
9107
|
+
let parsed;
|
|
9108
|
+
try {
|
|
9109
|
+
parsed = JSON.parse(line);
|
|
9110
|
+
} catch {
|
|
9111
|
+
stderr(`cleargate mcp serve: ignoring non-JSON line: ${line.slice(0, 80)}
|
|
9112
|
+
`);
|
|
9113
|
+
return;
|
|
9114
|
+
}
|
|
9115
|
+
const isNotification = !("id" in parsed) || parsed.id === void 0 || parsed.id === null;
|
|
9116
|
+
let access = await fetcher.getAccessToken();
|
|
9117
|
+
let res = await postFrame(baseUrl, line, access, fetchFn);
|
|
9118
|
+
if (res.status === 401) {
|
|
9119
|
+
fetcher.invalidate();
|
|
9120
|
+
access = await fetcher.getAccessToken();
|
|
9121
|
+
res = await postFrame(baseUrl, line, access, fetchFn);
|
|
9122
|
+
}
|
|
9123
|
+
if (isNotification) {
|
|
9124
|
+
await res.arrayBuffer().catch(() => void 0);
|
|
9125
|
+
return;
|
|
9126
|
+
}
|
|
9127
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
9128
|
+
if (ct.includes("text/event-stream")) {
|
|
9129
|
+
await streamSse(res, stdout);
|
|
9130
|
+
} else {
|
|
9131
|
+
const text = await res.text();
|
|
9132
|
+
if (text.length > 0) stdout(text + "\n");
|
|
9133
|
+
}
|
|
9134
|
+
}
|
|
9135
|
+
async function postFrame(baseUrl, body, accessToken, fetchFn) {
|
|
9136
|
+
return fetchFn(`${baseUrl}/mcp`, {
|
|
9137
|
+
method: "POST",
|
|
9138
|
+
headers: {
|
|
9139
|
+
"Content-Type": "application/json",
|
|
9140
|
+
Accept: "application/json, text/event-stream",
|
|
9141
|
+
Authorization: `Bearer ${accessToken}`
|
|
9142
|
+
},
|
|
9143
|
+
body
|
|
9144
|
+
});
|
|
9145
|
+
}
|
|
9146
|
+
async function streamSse(res, stdout) {
|
|
9147
|
+
if (!res.body) return;
|
|
9148
|
+
const reader = res.body.getReader();
|
|
9149
|
+
const decoder = new TextDecoder("utf-8");
|
|
9150
|
+
let buf = "";
|
|
9151
|
+
for (; ; ) {
|
|
9152
|
+
const { value, done } = await reader.read();
|
|
9153
|
+
if (done) break;
|
|
9154
|
+
buf += decoder.decode(value, { stream: true });
|
|
9155
|
+
let nl;
|
|
9156
|
+
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
9157
|
+
const ln = buf.slice(0, nl);
|
|
9158
|
+
buf = buf.slice(nl + 1);
|
|
9159
|
+
if (ln.startsWith("data:")) {
|
|
9160
|
+
const payload = ln.slice(5).trim();
|
|
9161
|
+
if (payload) stdout(payload + "\n");
|
|
9162
|
+
}
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
}
|
|
9166
|
+
function extractId(line) {
|
|
9167
|
+
try {
|
|
9168
|
+
const obj = JSON.parse(line);
|
|
9169
|
+
return "id" in obj ? obj.id : void 0;
|
|
9170
|
+
} catch {
|
|
9171
|
+
return void 0;
|
|
9172
|
+
}
|
|
9173
|
+
}
|
|
9174
|
+
|
|
8960
9175
|
// src/cli.ts
|
|
8961
9176
|
var program = new Command();
|
|
8962
9177
|
program.name("cleargate").description("ClearGate CLI \u2014 connects AI agent teams to the ClearGate MCP server").version(package_default.version, "-V, --version").option("--profile <name>", "configuration profile to use", "default").option("--mcp-url <url>", "MCP server URL (overrides config file and env)").showHelpAfterError("(use `cleargate --help`)");
|
|
@@ -9199,5 +9414,13 @@ var hotfix = program.command("hotfix").description("hotfix lane commands (off-sp
|
|
|
9199
9414
|
hotfix.command("new <slug>").description("scaffold a new HOTFIX-NNN_<slug>.md in pending-sync/").action((slug) => {
|
|
9200
9415
|
hotfixNewHandler({ slug });
|
|
9201
9416
|
});
|
|
9417
|
+
var mcp = program.command("mcp").description("MCP-server bridge commands (stdio shim, registration helpers)");
|
|
9418
|
+
mcp.command("serve").description("run a stdio MCP server that proxies to the cleargate HTTP /mcp endpoint with auto-refresh Bearer auth").action(async (_opts, command) => {
|
|
9419
|
+
const globals = command.parent.parent.opts();
|
|
9420
|
+
await mcpServeHandler({
|
|
9421
|
+
profile: globals.profile,
|
|
9422
|
+
...globals.mcpUrl !== void 0 ? { mcpUrlFlag: globals.mcpUrl } : {}
|
|
9423
|
+
});
|
|
9424
|
+
});
|
|
9202
9425
|
void program.parseAsync(process.argv);
|
|
9203
9426
|
//# sourceMappingURL=cli.js.map
|