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