cleargate 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MANIFEST.json +2 -2
- package/dist/cli.cjs +253 -29
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +249 -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/MANIFEST.json
CHANGED
package/dist/cli.cjs
CHANGED
|
@@ -627,7 +627,7 @@ var import_commander = require("commander");
|
|
|
627
627
|
// package.json
|
|
628
628
|
var package_default = {
|
|
629
629
|
name: "cleargate",
|
|
630
|
-
version: "0.
|
|
630
|
+
version: "0.8.0",
|
|
631
631
|
private: false,
|
|
632
632
|
type: "module",
|
|
633
633
|
description: "Planning framework for Claude Code agents \u2014 sprint/epic/story protocol, four-agent loop (architect/developer/qa/reporter), Karpathy-style awareness wiki.",
|
|
@@ -2052,9 +2052,13 @@ function mergeMcpJson(existing, entry) {
|
|
|
2052
2052
|
next.mcpServers = servers;
|
|
2053
2053
|
return JSON.stringify(next, null, 2) + "\n";
|
|
2054
2054
|
}
|
|
2055
|
-
|
|
2055
|
+
var STDIO_ENTRY = {
|
|
2056
|
+
command: "cleargate",
|
|
2057
|
+
args: ["mcp", "serve"]
|
|
2058
|
+
};
|
|
2059
|
+
function injectMcpJson(cwd, _unusedUrl) {
|
|
2056
2060
|
const dst = path8.join(cwd, ".mcp.json");
|
|
2057
|
-
const entry =
|
|
2061
|
+
const entry = STDIO_ENTRY;
|
|
2058
2062
|
let existing = null;
|
|
2059
2063
|
let existingRaw = null;
|
|
2060
2064
|
if (fs8.existsSync(dst)) {
|
|
@@ -3162,7 +3166,7 @@ async function initHandler(opts = {}) {
|
|
|
3162
3166
|
`);
|
|
3163
3167
|
}
|
|
3164
3168
|
try {
|
|
3165
|
-
const action = injectMcpJson(cwd
|
|
3169
|
+
const action = injectMcpJson(cwd);
|
|
3166
3170
|
if (action === "created") {
|
|
3167
3171
|
stdout(
|
|
3168
3172
|
`[cleargate init] Created .mcp.json (cleargate MCP server registered) \u2014 restart Claude Code to load it.
|
|
@@ -8016,7 +8020,7 @@ function extractFrontmatterBlock(raw) {
|
|
|
8016
8020
|
// src/lib/intake.ts
|
|
8017
8021
|
async function runIntakeBranch(opts) {
|
|
8018
8022
|
const {
|
|
8019
|
-
mcp,
|
|
8023
|
+
mcp: mcp2,
|
|
8020
8024
|
identity,
|
|
8021
8025
|
sprintRoot,
|
|
8022
8026
|
projectRoot,
|
|
@@ -8027,7 +8031,7 @@ async function runIntakeBranch(opts) {
|
|
|
8027
8031
|
const pendingSyncDir = path39.join(projectRoot, ".cleargate", "delivery", "pending-sync");
|
|
8028
8032
|
let remoteItems = [];
|
|
8029
8033
|
try {
|
|
8030
|
-
remoteItems = await
|
|
8034
|
+
remoteItems = await mcp2.call(
|
|
8031
8035
|
"cleargate_detect_new_items",
|
|
8032
8036
|
{ label: labelFilter }
|
|
8033
8037
|
);
|
|
@@ -8389,9 +8393,9 @@ async function syncCheckHandler(opts = {}) {
|
|
|
8389
8393
|
}
|
|
8390
8394
|
} catch {
|
|
8391
8395
|
}
|
|
8392
|
-
let
|
|
8396
|
+
let mcp2;
|
|
8393
8397
|
if (opts.mcp) {
|
|
8394
|
-
|
|
8398
|
+
mcp2 = opts.mcp;
|
|
8395
8399
|
} else {
|
|
8396
8400
|
let baseUrl = env["CLEARGATE_MCP_URL"];
|
|
8397
8401
|
if (!baseUrl || !baseUrl.trim()) {
|
|
@@ -8420,10 +8424,10 @@ async function syncCheckHandler(opts = {}) {
|
|
|
8420
8424
|
await emitError("adapter-not-configured", nowIso);
|
|
8421
8425
|
return;
|
|
8422
8426
|
}
|
|
8423
|
-
|
|
8427
|
+
mcp2 = createMcpClient({ baseUrl: baseUrl.trim(), token: accessToken });
|
|
8424
8428
|
}
|
|
8425
8429
|
try {
|
|
8426
|
-
const adapterInfo = await
|
|
8430
|
+
const adapterInfo = await mcp2.adapterInfo();
|
|
8427
8431
|
if (!adapterInfo.configured || adapterInfo.name === "no-adapter-configured") {
|
|
8428
8432
|
await emitError("adapter-not-configured", nowIso);
|
|
8429
8433
|
return;
|
|
@@ -8432,7 +8436,7 @@ async function syncCheckHandler(opts = {}) {
|
|
|
8432
8436
|
}
|
|
8433
8437
|
let refs;
|
|
8434
8438
|
try {
|
|
8435
|
-
refs = await
|
|
8439
|
+
refs = await mcp2.call("cleargate_list_remote_updates", { since });
|
|
8436
8440
|
} catch (err) {
|
|
8437
8441
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8438
8442
|
await emitError(msg, nowIso);
|
|
@@ -8452,9 +8456,9 @@ async function syncHandler(opts = {}) {
|
|
|
8452
8456
|
const identity = resolveIdentity(projectRoot);
|
|
8453
8457
|
const sprintRoot = resolveActiveSprintDir(projectRoot);
|
|
8454
8458
|
const sprintId = path43.basename(sprintRoot);
|
|
8455
|
-
let
|
|
8459
|
+
let mcp2;
|
|
8456
8460
|
if (opts.mcp) {
|
|
8457
|
-
|
|
8461
|
+
mcp2 = opts.mcp;
|
|
8458
8462
|
} else {
|
|
8459
8463
|
let baseUrl = env["CLEARGATE_MCP_URL"];
|
|
8460
8464
|
if (!baseUrl || !baseUrl.trim()) {
|
|
@@ -8497,11 +8501,11 @@ async function syncHandler(opts = {}) {
|
|
|
8497
8501
|
exit(2);
|
|
8498
8502
|
return;
|
|
8499
8503
|
}
|
|
8500
|
-
|
|
8504
|
+
mcp2 = createMcpClient({ baseUrl: baseUrl.trim(), token: accessToken });
|
|
8501
8505
|
}
|
|
8502
8506
|
let adapterInfo;
|
|
8503
8507
|
try {
|
|
8504
|
-
adapterInfo = await
|
|
8508
|
+
adapterInfo = await mcp2.adapterInfo();
|
|
8505
8509
|
} catch {
|
|
8506
8510
|
adapterInfo = { configured: true, name: "unknown" };
|
|
8507
8511
|
}
|
|
@@ -8522,13 +8526,13 @@ async function syncHandler(opts = {}) {
|
|
|
8522
8526
|
}
|
|
8523
8527
|
} catch {
|
|
8524
8528
|
}
|
|
8525
|
-
const remoteRefs = await
|
|
8529
|
+
const remoteRefs = await mcp2.call(
|
|
8526
8530
|
"cleargate_list_remote_updates",
|
|
8527
8531
|
{ since: lastRemoteSync }
|
|
8528
8532
|
);
|
|
8529
8533
|
const pulled = [];
|
|
8530
8534
|
for (const ref of remoteRefs) {
|
|
8531
|
-
const item = await
|
|
8535
|
+
const item = await mcp2.call(
|
|
8532
8536
|
"cleargate_pull_item",
|
|
8533
8537
|
{ remote_id: ref.remote_id }
|
|
8534
8538
|
);
|
|
@@ -8540,7 +8544,7 @@ async function syncHandler(opts = {}) {
|
|
|
8540
8544
|
let intakeResult = { created: 0, items: [] };
|
|
8541
8545
|
try {
|
|
8542
8546
|
intakeResult = await runIntakeBranch({
|
|
8543
|
-
mcp,
|
|
8547
|
+
mcp: mcp2,
|
|
8544
8548
|
identity,
|
|
8545
8549
|
sprintRoot,
|
|
8546
8550
|
projectRoot,
|
|
@@ -8566,7 +8570,7 @@ async function syncHandler(opts = {}) {
|
|
|
8566
8570
|
const activeSet = await resolveActiveItems(projectRoot, localRefs, nowFn);
|
|
8567
8571
|
for (const remoteId of activeSet) {
|
|
8568
8572
|
try {
|
|
8569
|
-
const comments = await
|
|
8573
|
+
const comments = await mcp2.call(
|
|
8570
8574
|
"cleargate_pull_comments",
|
|
8571
8575
|
{ remote_id: remoteId }
|
|
8572
8576
|
);
|
|
@@ -8720,7 +8724,7 @@ async function syncHandler(opts = {}) {
|
|
|
8720
8724
|
await appendSyncLog(sprintRoot, entry);
|
|
8721
8725
|
}
|
|
8722
8726
|
for (const { localPath, fm, body, itemId } of pushQueue) {
|
|
8723
|
-
await
|
|
8727
|
+
await mcp2.call("push_item", {
|
|
8724
8728
|
cleargate_id: itemId,
|
|
8725
8729
|
type: typeof fm["story_id"] === "string" ? "story" : typeof fm["epic_id"] === "string" ? "epic" : typeof fm["proposal_id"] === "string" ? "proposal" : "story",
|
|
8726
8730
|
payload: fm
|
|
@@ -8853,9 +8857,9 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8853
8857
|
const nowFn = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
8854
8858
|
const identity = resolveIdentity(projectRoot);
|
|
8855
8859
|
const sprintRoot = resolveActiveSprintDir(projectRoot);
|
|
8856
|
-
let
|
|
8860
|
+
let mcp2;
|
|
8857
8861
|
if (opts.mcp) {
|
|
8858
|
-
|
|
8862
|
+
mcp2 = opts.mcp;
|
|
8859
8863
|
} else {
|
|
8860
8864
|
let baseUrl = env["CLEARGATE_MCP_URL"];
|
|
8861
8865
|
if (!baseUrl || !baseUrl.trim()) {
|
|
@@ -8890,7 +8894,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8890
8894
|
exit(2);
|
|
8891
8895
|
return;
|
|
8892
8896
|
}
|
|
8893
|
-
|
|
8897
|
+
mcp2 = createMcpClient({ baseUrl: baseUrl.trim(), token: accessToken });
|
|
8894
8898
|
}
|
|
8895
8899
|
const remoteId = await resolveRemoteId(idOrRemoteId, projectRoot);
|
|
8896
8900
|
if (!remoteId) {
|
|
@@ -8899,7 +8903,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8899
8903
|
exit(1);
|
|
8900
8904
|
return;
|
|
8901
8905
|
}
|
|
8902
|
-
const remoteItem = await
|
|
8906
|
+
const remoteItem = await mcp2.call("cleargate_pull_item", { remote_id: remoteId });
|
|
8903
8907
|
if (!remoteItem) {
|
|
8904
8908
|
stderr(`Error: item ${remoteId} not found on MCP server.
|
|
8905
8909
|
`);
|
|
@@ -8959,7 +8963,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
|
|
|
8959
8963
|
stdout(`pull: ${remoteId} applied to ${path44.relative(projectRoot, localPath)}
|
|
8960
8964
|
`);
|
|
8961
8965
|
if (opts.comments) {
|
|
8962
|
-
const comments = await
|
|
8966
|
+
const comments = await mcp2.call(
|
|
8963
8967
|
"cleargate_pull_comments",
|
|
8964
8968
|
{ remote_id: remoteId }
|
|
8965
8969
|
);
|
|
@@ -9157,10 +9161,10 @@ async function handlePush(filePath, ctx) {
|
|
|
9157
9161
|
if (h1) payloadForPush["title"] = h1;
|
|
9158
9162
|
}
|
|
9159
9163
|
payloadForPush["body"] = body;
|
|
9160
|
-
const
|
|
9164
|
+
const mcp2 = await resolveMcp();
|
|
9161
9165
|
let result;
|
|
9162
9166
|
try {
|
|
9163
|
-
result = await
|
|
9167
|
+
result = await mcp2.call("push_item", {
|
|
9164
9168
|
cleargate_id: itemId,
|
|
9165
9169
|
type,
|
|
9166
9170
|
payload: payloadForPush,
|
|
@@ -9212,9 +9216,9 @@ async function handleRevert(idOrRemoteId, ctx) {
|
|
|
9212
9216
|
exit(1);
|
|
9213
9217
|
return;
|
|
9214
9218
|
}
|
|
9215
|
-
const
|
|
9219
|
+
const mcp2 = await resolveMcp();
|
|
9216
9220
|
try {
|
|
9217
|
-
await
|
|
9221
|
+
await mcp2.call("sync_status", {
|
|
9218
9222
|
cleargate_id: itemId,
|
|
9219
9223
|
new_status: "archived-without-shipping"
|
|
9220
9224
|
});
|
|
@@ -9653,6 +9657,218 @@ function hotfixNewHandler(opts, cli) {
|
|
|
9653
9657
|
return exitFn(0);
|
|
9654
9658
|
}
|
|
9655
9659
|
|
|
9660
|
+
// src/commands/mcp-serve.ts
|
|
9661
|
+
init_cjs_shims();
|
|
9662
|
+
var readline5 = __toESM(require("readline"), 1);
|
|
9663
|
+
init_config();
|
|
9664
|
+
init_factory();
|
|
9665
|
+
|
|
9666
|
+
// src/auth/refresh.ts
|
|
9667
|
+
init_cjs_shims();
|
|
9668
|
+
async function refreshAccessToken(baseUrl, refreshToken, deps = {}) {
|
|
9669
|
+
const fetchFn = deps.fetch ?? globalThis.fetch;
|
|
9670
|
+
const res = await fetchFn(`${baseUrl}/auth/refresh`, {
|
|
9671
|
+
method: "POST",
|
|
9672
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
9673
|
+
body: JSON.stringify({ refresh_token: refreshToken })
|
|
9674
|
+
});
|
|
9675
|
+
if (!res.ok) {
|
|
9676
|
+
const body = await res.json().catch(() => ({}));
|
|
9677
|
+
throw new RefreshError(res.status, body.error ?? "unknown_error");
|
|
9678
|
+
}
|
|
9679
|
+
const json = await res.json();
|
|
9680
|
+
if (typeof json.access_token !== "string" || typeof json.refresh_token !== "string" || typeof json.expires_in !== "number") {
|
|
9681
|
+
throw new RefreshError(500, "malformed_response");
|
|
9682
|
+
}
|
|
9683
|
+
return json;
|
|
9684
|
+
}
|
|
9685
|
+
var RefreshError = class extends Error {
|
|
9686
|
+
constructor(status, code) {
|
|
9687
|
+
super(`refresh failed: ${status} ${code}`);
|
|
9688
|
+
this.status = status;
|
|
9689
|
+
this.code = code;
|
|
9690
|
+
this.name = "RefreshError";
|
|
9691
|
+
}
|
|
9692
|
+
status;
|
|
9693
|
+
code;
|
|
9694
|
+
};
|
|
9695
|
+
var AuthFetcher = class {
|
|
9696
|
+
constructor(opts) {
|
|
9697
|
+
this.opts = opts;
|
|
9698
|
+
}
|
|
9699
|
+
opts;
|
|
9700
|
+
accessToken = null;
|
|
9701
|
+
accessExpiresAt = 0;
|
|
9702
|
+
inflight = null;
|
|
9703
|
+
/** Returns a fresh access token, refreshing if needed. */
|
|
9704
|
+
async getAccessToken() {
|
|
9705
|
+
const now = (this.opts.now ?? (() => Date.now()))();
|
|
9706
|
+
const skewMs = (this.opts.skewSeconds ?? 60) * 1e3;
|
|
9707
|
+
if (this.accessToken && now < this.accessExpiresAt - skewMs) {
|
|
9708
|
+
return this.accessToken;
|
|
9709
|
+
}
|
|
9710
|
+
if (this.inflight) return this.inflight;
|
|
9711
|
+
this.inflight = this.refreshNow().finally(() => {
|
|
9712
|
+
this.inflight = null;
|
|
9713
|
+
});
|
|
9714
|
+
return this.inflight;
|
|
9715
|
+
}
|
|
9716
|
+
/** Force the next call to refresh. Used after a 401. */
|
|
9717
|
+
invalidate() {
|
|
9718
|
+
this.accessToken = null;
|
|
9719
|
+
this.accessExpiresAt = 0;
|
|
9720
|
+
}
|
|
9721
|
+
async refreshNow() {
|
|
9722
|
+
const stored = await this.opts.loadRefresh();
|
|
9723
|
+
if (!stored) {
|
|
9724
|
+
throw new RefreshError(401, "no_refresh_token");
|
|
9725
|
+
}
|
|
9726
|
+
const exchanged = await refreshAccessToken(this.opts.baseUrl, stored, {
|
|
9727
|
+
...this.opts.fetch ? { fetch: this.opts.fetch } : {},
|
|
9728
|
+
...this.opts.now ? { now: this.opts.now } : {}
|
|
9729
|
+
});
|
|
9730
|
+
await this.opts.saveRefresh(exchanged.refresh_token);
|
|
9731
|
+
const now = (this.opts.now ?? (() => Date.now()))();
|
|
9732
|
+
this.accessToken = exchanged.access_token;
|
|
9733
|
+
this.accessExpiresAt = now + exchanged.expires_in * 1e3;
|
|
9734
|
+
return exchanged.access_token;
|
|
9735
|
+
}
|
|
9736
|
+
};
|
|
9737
|
+
|
|
9738
|
+
// src/commands/mcp-serve.ts
|
|
9739
|
+
var DEFAULT_BASE_URL = "https://cleargate-mcp.soula.ge";
|
|
9740
|
+
async function mcpServeHandler(opts) {
|
|
9741
|
+
const fetchFn = opts.fetch ?? globalThis.fetch;
|
|
9742
|
+
const stdout = opts.stdout ?? ((s) => process.stdout.write(s));
|
|
9743
|
+
const stderr = opts.stderr ?? ((s) => process.stderr.write(s));
|
|
9744
|
+
const exit = opts.exit ?? ((c) => process.exit(c));
|
|
9745
|
+
const cfg = loadConfig({
|
|
9746
|
+
flags: { profile: opts.profile, mcpUrl: opts.mcpUrlFlag }
|
|
9747
|
+
});
|
|
9748
|
+
const baseUrl = cfg.mcpUrl ?? DEFAULT_BASE_URL;
|
|
9749
|
+
const store = await (opts.createStore ?? createTokenStore)({
|
|
9750
|
+
...opts.keychainService !== void 0 ? { keychainService: opts.keychainService } : {},
|
|
9751
|
+
...opts.forceBackend !== void 0 ? { forceBackend: opts.forceBackend } : {}
|
|
9752
|
+
});
|
|
9753
|
+
const fetcher = new AuthFetcher({
|
|
9754
|
+
baseUrl,
|
|
9755
|
+
loadRefresh: () => store.load(opts.profile),
|
|
9756
|
+
saveRefresh: (t) => store.save(opts.profile, t),
|
|
9757
|
+
...opts.fetch !== void 0 ? { fetch: opts.fetch } : {},
|
|
9758
|
+
...opts.now !== void 0 ? { now: opts.now } : {}
|
|
9759
|
+
});
|
|
9760
|
+
try {
|
|
9761
|
+
await fetcher.getAccessToken();
|
|
9762
|
+
} catch (err) {
|
|
9763
|
+
if (err instanceof RefreshError) {
|
|
9764
|
+
stderr(
|
|
9765
|
+
`cleargate mcp serve: refresh failed (${err.status} ${err.code}). Run \`cleargate join <invite-url>\` to re-authenticate.
|
|
9766
|
+
`
|
|
9767
|
+
);
|
|
9768
|
+
} else {
|
|
9769
|
+
stderr(
|
|
9770
|
+
`cleargate mcp serve: ${err instanceof Error ? err.message : String(err)}
|
|
9771
|
+
`
|
|
9772
|
+
);
|
|
9773
|
+
}
|
|
9774
|
+
return exit(1);
|
|
9775
|
+
}
|
|
9776
|
+
const inputStream = opts.stdin ?? process.stdin;
|
|
9777
|
+
const rl = readline5.createInterface({
|
|
9778
|
+
input: inputStream,
|
|
9779
|
+
output: void 0,
|
|
9780
|
+
terminal: false
|
|
9781
|
+
});
|
|
9782
|
+
for await (const line of rl) {
|
|
9783
|
+
if (!line.trim()) continue;
|
|
9784
|
+
try {
|
|
9785
|
+
await proxyOne(line, baseUrl, fetcher, fetchFn, stdout, stderr);
|
|
9786
|
+
} catch (err) {
|
|
9787
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
9788
|
+
stderr(`cleargate mcp serve: proxy error: ${errMsg}
|
|
9789
|
+
`);
|
|
9790
|
+
const id = extractId(line);
|
|
9791
|
+
if (id !== void 0) {
|
|
9792
|
+
stdout(
|
|
9793
|
+
JSON.stringify({
|
|
9794
|
+
jsonrpc: "2.0",
|
|
9795
|
+
id,
|
|
9796
|
+
error: { code: -32603, message: `proxy error: ${errMsg}` }
|
|
9797
|
+
}) + "\n"
|
|
9798
|
+
);
|
|
9799
|
+
}
|
|
9800
|
+
}
|
|
9801
|
+
}
|
|
9802
|
+
}
|
|
9803
|
+
async function proxyOne(line, baseUrl, fetcher, fetchFn, stdout, stderr) {
|
|
9804
|
+
let parsed;
|
|
9805
|
+
try {
|
|
9806
|
+
parsed = JSON.parse(line);
|
|
9807
|
+
} catch {
|
|
9808
|
+
stderr(`cleargate mcp serve: ignoring non-JSON line: ${line.slice(0, 80)}
|
|
9809
|
+
`);
|
|
9810
|
+
return;
|
|
9811
|
+
}
|
|
9812
|
+
const isNotification = !("id" in parsed) || parsed.id === void 0 || parsed.id === null;
|
|
9813
|
+
let access = await fetcher.getAccessToken();
|
|
9814
|
+
let res = await postFrame(baseUrl, line, access, fetchFn);
|
|
9815
|
+
if (res.status === 401) {
|
|
9816
|
+
fetcher.invalidate();
|
|
9817
|
+
access = await fetcher.getAccessToken();
|
|
9818
|
+
res = await postFrame(baseUrl, line, access, fetchFn);
|
|
9819
|
+
}
|
|
9820
|
+
if (isNotification) {
|
|
9821
|
+
await res.arrayBuffer().catch(() => void 0);
|
|
9822
|
+
return;
|
|
9823
|
+
}
|
|
9824
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
9825
|
+
if (ct.includes("text/event-stream")) {
|
|
9826
|
+
await streamSse(res, stdout);
|
|
9827
|
+
} else {
|
|
9828
|
+
const text = await res.text();
|
|
9829
|
+
if (text.length > 0) stdout(text + "\n");
|
|
9830
|
+
}
|
|
9831
|
+
}
|
|
9832
|
+
async function postFrame(baseUrl, body, accessToken, fetchFn) {
|
|
9833
|
+
return fetchFn(`${baseUrl}/mcp`, {
|
|
9834
|
+
method: "POST",
|
|
9835
|
+
headers: {
|
|
9836
|
+
"Content-Type": "application/json",
|
|
9837
|
+
Accept: "application/json, text/event-stream",
|
|
9838
|
+
Authorization: `Bearer ${accessToken}`
|
|
9839
|
+
},
|
|
9840
|
+
body
|
|
9841
|
+
});
|
|
9842
|
+
}
|
|
9843
|
+
async function streamSse(res, stdout) {
|
|
9844
|
+
if (!res.body) return;
|
|
9845
|
+
const reader = res.body.getReader();
|
|
9846
|
+
const decoder = new TextDecoder("utf-8");
|
|
9847
|
+
let buf = "";
|
|
9848
|
+
for (; ; ) {
|
|
9849
|
+
const { value, done } = await reader.read();
|
|
9850
|
+
if (done) break;
|
|
9851
|
+
buf += decoder.decode(value, { stream: true });
|
|
9852
|
+
let nl;
|
|
9853
|
+
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
9854
|
+
const ln = buf.slice(0, nl);
|
|
9855
|
+
buf = buf.slice(nl + 1);
|
|
9856
|
+
if (ln.startsWith("data:")) {
|
|
9857
|
+
const payload = ln.slice(5).trim();
|
|
9858
|
+
if (payload) stdout(payload + "\n");
|
|
9859
|
+
}
|
|
9860
|
+
}
|
|
9861
|
+
}
|
|
9862
|
+
}
|
|
9863
|
+
function extractId(line) {
|
|
9864
|
+
try {
|
|
9865
|
+
const obj = JSON.parse(line);
|
|
9866
|
+
return "id" in obj ? obj.id : void 0;
|
|
9867
|
+
} catch {
|
|
9868
|
+
return void 0;
|
|
9869
|
+
}
|
|
9870
|
+
}
|
|
9871
|
+
|
|
9656
9872
|
// src/cli.ts
|
|
9657
9873
|
var program = new import_commander.Command();
|
|
9658
9874
|
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`)");
|
|
@@ -9895,5 +10111,13 @@ var hotfix = program.command("hotfix").description("hotfix lane commands (off-sp
|
|
|
9895
10111
|
hotfix.command("new <slug>").description("scaffold a new HOTFIX-NNN_<slug>.md in pending-sync/").action((slug) => {
|
|
9896
10112
|
hotfixNewHandler({ slug });
|
|
9897
10113
|
});
|
|
10114
|
+
var mcp = program.command("mcp").description("MCP-server bridge commands (stdio shim, registration helpers)");
|
|
10115
|
+
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) => {
|
|
10116
|
+
const globals = command.parent.parent.opts();
|
|
10117
|
+
await mcpServeHandler({
|
|
10118
|
+
profile: globals.profile,
|
|
10119
|
+
...globals.mcpUrl !== void 0 ? { mcpUrlFlag: globals.mcpUrl } : {}
|
|
10120
|
+
});
|
|
10121
|
+
});
|
|
9898
10122
|
void program.parseAsync(process.argv);
|
|
9899
10123
|
//# sourceMappingURL=cli.cjs.map
|