@hivefloor/cli 0.1.4 → 0.1.8
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/LICENSE +6 -20
- package/README.md +31 -9
- package/dist/chunk-2ERPDCOT.js +38 -0
- package/dist/chunk-4G362W6G.js +19 -0
- package/dist/chunk-5OJUJCE3.js +817 -0
- package/dist/chunk-5XXYQQG6.js +274 -0
- package/dist/chunk-AGIYVFDQ.js +10984 -0
- package/dist/{chunk-2BSA7LFD.js → chunk-BLLPDPTL.js} +7 -3
- package/dist/{chunk-R5KDI4WI.js → chunk-FPJNGKT5.js} +9 -3
- package/dist/chunk-HW3KRNCO.js +201 -0
- package/dist/{chunk-ZC2DAKB5.js → chunk-HWBUESB4.js} +1500 -316
- package/dist/{chunk-DNG5CRT3.js → chunk-K2IRTZH5.js} +8 -7
- package/dist/chunk-KQMPCV57.js +122 -0
- package/dist/{chunk-UJ4BQFWV.js → chunk-L6EFW2SJ.js} +53 -31
- package/dist/{chunk-T7TG6WA4.js → chunk-LX5A25O6.js} +4 -2
- package/dist/{chunk-W7DROKC7.js → chunk-MYJCU5JL.js} +89 -13
- package/dist/chunk-NMUH5NXN.js +52 -0
- package/dist/chunk-NRJONTFT.js +67 -0
- package/dist/chunk-QBBKGORP.js +327 -0
- package/dist/chunk-QGULSOQ2.js +142 -0
- package/dist/{chunk-PDXYOREI.js → chunk-QLMLB7RB.js} +110 -31
- package/dist/{chunk-TKMIV7BG.js → chunk-QPAFN47B.js} +3 -1
- package/dist/chunk-SBOEAOHD.js +48 -0
- package/dist/{chunk-SD65CIIY.js → chunk-TIR4CV3P.js} +117 -33
- package/dist/{chunk-QHYZBHXO.js → chunk-X2KH6AR4.js} +195 -251
- package/dist/chunk-XAXKZ572.js +106 -0
- package/dist/{chunk-VNCQFFQO.js → chunk-XPGL7VYE.js} +114 -1
- package/dist/cli-BFOJWJNG.js +279 -0
- package/dist/connect-ZJ4JXBAJ.js +27 -0
- package/dist/control-6GHTZQJV.js +25 -0
- package/dist/{disconnect-MKRHK4CX.js → disconnect-3T25NTKX.js} +55 -34
- package/dist/hook-TPSHBCWU.js +575 -0
- package/dist/index.js +9 -6
- package/dist/{link-HXBMMSG3.js → link-EAS5F5PC.js} +34 -18
- package/dist/{machine-connect-BYHZRRRB.js → machine-connect-KEI4BRWF.js} +30 -24
- package/dist/mcp-LVIYR3EN.js +1882 -0
- package/dist/orch-KVRL2YA2.js +137 -0
- package/dist/{run-336BSU72.js → run-JL2OZWK3.js} +1933 -29
- package/dist/{status-KBBSAADD.js → status-QXOOJGGN.js} +29 -14
- package/dist/token-BFWWQIDA.js +44 -0
- package/dist/voice-QXHFXRWG.js +264 -0
- package/dist/{where-KR7VWSEC.js → where-CMUORQIO.js} +20 -8
- package/package.json +6 -7
- package/dist/chunk-2IMJECYD.js +0 -71
- package/dist/chunk-7KF7IQJN.js +0 -30
- package/dist/chunk-GT3HFFT4.js +0 -132
- package/dist/chunk-JCLWCMEM.js +0 -8
- package/dist/chunk-K3NQKI34.js +0 -10
- package/dist/chunk-O2TC3WSS.js +0 -303
- package/dist/chunk-PY74LT2W.js +0 -41
- package/dist/cli-P3DYE5IR.js +0 -103
- package/dist/connect-ACNM5DQG.js +0 -23
- package/dist/hook-KR2HGVAR.js +0 -301
- package/dist/mcp-N2TMD4GR.js +0 -121
- package/dist/token-JDRLEV5D.js +0 -32
package/dist/hook-KR2HGVAR.js
DELETED
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
HARD_EXIT_MS
|
|
4
|
-
} from "./chunk-JCLWCMEM.js";
|
|
5
|
-
import {
|
|
6
|
-
detectRepo
|
|
7
|
-
} from "./chunk-2BSA7LFD.js";
|
|
8
|
-
import {
|
|
9
|
-
defaultHost,
|
|
10
|
-
loadToken
|
|
11
|
-
} from "./chunk-PDXYOREI.js";
|
|
12
|
-
import {
|
|
13
|
-
appendToSpool,
|
|
14
|
-
contextEventName,
|
|
15
|
-
contextOutput,
|
|
16
|
-
nudgesOf,
|
|
17
|
-
releaseSpool,
|
|
18
|
-
stashNudges,
|
|
19
|
-
takeSpool,
|
|
20
|
-
takeStashed
|
|
21
|
-
} from "./chunk-O2TC3WSS.js";
|
|
22
|
-
import {
|
|
23
|
-
readMachine,
|
|
24
|
-
serviceAlive
|
|
25
|
-
} from "./chunk-T7TG6WA4.js";
|
|
26
|
-
import {
|
|
27
|
-
configDir,
|
|
28
|
-
machineSpoolFile
|
|
29
|
-
} from "./chunk-VNCQFFQO.js";
|
|
30
|
-
import {
|
|
31
|
-
DEFAULT_HOST,
|
|
32
|
-
HOOK_BATCH_MAX,
|
|
33
|
-
PROFILE_KEY_RE,
|
|
34
|
-
SESSION_ACCOUNT_RE,
|
|
35
|
-
hostFromEnv,
|
|
36
|
-
redact
|
|
37
|
-
} from "./chunk-ZC2DAKB5.js";
|
|
38
|
-
import "./chunk-K3NQKI34.js";
|
|
39
|
-
|
|
40
|
-
// src/hook.ts
|
|
41
|
-
import fs from "fs";
|
|
42
|
-
|
|
43
|
-
// src/hookmap.ts
|
|
44
|
-
var NAMES = {
|
|
45
|
-
sessionstart: "session_start",
|
|
46
|
-
sessionend: "session_end",
|
|
47
|
-
userpromptsubmit: "prompt",
|
|
48
|
-
beforesubmitprompt: "prompt",
|
|
49
|
-
stop: "stop",
|
|
50
|
-
afteragent: "stop",
|
|
51
|
-
notification: "waiting",
|
|
52
|
-
subagentstart: "subagent_start",
|
|
53
|
-
subagentstop: "subagent_stop",
|
|
54
|
-
pretooluse: "tool_agent_pre",
|
|
55
|
-
posttooluse: "tool_agent_post"
|
|
56
|
-
};
|
|
57
|
-
var WAITING_TYPES = /* @__PURE__ */ new Set(["permission_prompt", "idle_prompt"]);
|
|
58
|
-
var LINE_MAX = 140;
|
|
59
|
-
var str = (v) => typeof v === "string" && v.trim() !== "" ? v : void 0;
|
|
60
|
-
var rec = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
|
|
61
|
-
function statusLine(text) {
|
|
62
|
-
const t = str(text);
|
|
63
|
-
if (!t) return void 0;
|
|
64
|
-
const first = t.split(/\r?\n/).map((l) => l.trim()).find((l) => l !== "");
|
|
65
|
-
if (!first) return void 0;
|
|
66
|
-
return redact(first).text.slice(0, LINE_MAX).trim() || void 0;
|
|
67
|
-
}
|
|
68
|
-
function oneLine(text) {
|
|
69
|
-
const t = str(text);
|
|
70
|
-
return t ? redact(t.replace(/\s+/g, " ").trim()).text.slice(0, LINE_MAX) : void 0;
|
|
71
|
-
}
|
|
72
|
-
function mapHookEvent(tool, native, input) {
|
|
73
|
-
const event = NAMES[native.toLowerCase()];
|
|
74
|
-
if (!event) return null;
|
|
75
|
-
const session_id = str(input.conversation_id) ?? str(input.session_id);
|
|
76
|
-
if (!session_id) return null;
|
|
77
|
-
const out = { tool, event, session_id };
|
|
78
|
-
const model = str(input.model) ?? str(input.subagent_model);
|
|
79
|
-
if (model) out.model = model;
|
|
80
|
-
switch (event) {
|
|
81
|
-
case "waiting": {
|
|
82
|
-
if (tool !== "claude" || !WAITING_TYPES.has(String(input.notification_type))) return null;
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
case "subagent_start":
|
|
86
|
-
case "subagent_stop": {
|
|
87
|
-
const id = str(input.subagent_id) ?? str(input.agent_id);
|
|
88
|
-
if (!id) return null;
|
|
89
|
-
out.subagent_id = id;
|
|
90
|
-
const type = str(input.subagent_type) ?? str(input.agent_type);
|
|
91
|
-
if (type) out.subagent_type = type;
|
|
92
|
-
if (event === "subagent_start") {
|
|
93
|
-
const d = oneLine(input.description) ?? oneLine(input.task);
|
|
94
|
-
if (d) out.description = d;
|
|
95
|
-
} else {
|
|
96
|
-
const s = statusLine(input.last_assistant_message) ?? statusLine(input.summary);
|
|
97
|
-
if (s) out.status_line = s;
|
|
98
|
-
}
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
case "tool_agent_pre":
|
|
102
|
-
case "tool_agent_post": {
|
|
103
|
-
if (input.tool_name !== "Agent" && input.tool_name !== "Task") return null;
|
|
104
|
-
const ti = rec(input.tool_input);
|
|
105
|
-
const type = str(ti.subagent_type);
|
|
106
|
-
if (type) out.subagent_type = type;
|
|
107
|
-
const d = oneLine(ti.description);
|
|
108
|
-
if (d) out.description = d;
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
case "stop": {
|
|
112
|
-
const s = statusLine(input.last_assistant_message) ?? statusLine(input.prompt_response);
|
|
113
|
-
if (s) out.status_line = s;
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
default:
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
return out;
|
|
120
|
-
}
|
|
121
|
-
function cwdOf(input) {
|
|
122
|
-
const roots = Array.isArray(input.workspace_roots) ? input.workspace_roots : [];
|
|
123
|
-
return str(input.cwd) ?? str(roots[0]);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// src/hook.ts
|
|
127
|
-
import path from "path";
|
|
128
|
-
var POST_TIMEOUT_MS = 2e3;
|
|
129
|
-
var EXIT_MARGIN_MS = 400;
|
|
130
|
-
var MIN_POST_MS = 250;
|
|
131
|
-
var TOOLS = /* @__PURE__ */ new Set(["claude", "codex", "cursor", "gemini", "grok"]);
|
|
132
|
-
var DEDUPE_WINDOW_MS = 2e3;
|
|
133
|
-
function dedupeFile() {
|
|
134
|
-
return path.join(configDir(), "dedupe.json");
|
|
135
|
-
}
|
|
136
|
-
function isDuplicate(key, nowMs) {
|
|
137
|
-
let seen = {};
|
|
138
|
-
try {
|
|
139
|
-
seen = JSON.parse(fs.readFileSync(dedupeFile(), "utf8"));
|
|
140
|
-
} catch {
|
|
141
|
-
}
|
|
142
|
-
const fresh = Object.fromEntries(Object.entries(seen).filter(([, t]) => nowMs - t < 1e4));
|
|
143
|
-
const dup = key in fresh && nowMs - fresh[key] < DEDUPE_WINDOW_MS;
|
|
144
|
-
if (!dup) {
|
|
145
|
-
fresh[key] = nowMs;
|
|
146
|
-
try {
|
|
147
|
-
fs.mkdirSync(configDir(), { recursive: true, mode: 448 });
|
|
148
|
-
fs.writeFileSync(dedupeFile(), JSON.stringify(fresh), { mode: 384 });
|
|
149
|
-
} catch {
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return dup;
|
|
153
|
-
}
|
|
154
|
-
async function post(deps, host, token, events, timeoutMs, route = "/api/v1/hooks", nudges) {
|
|
155
|
-
try {
|
|
156
|
-
const res = await deps.fetch(`${host}${route}`, {
|
|
157
|
-
method: "POST",
|
|
158
|
-
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
159
|
-
body: JSON.stringify({ events }),
|
|
160
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
161
|
-
});
|
|
162
|
-
const text = await res.text().catch(() => "");
|
|
163
|
-
if (res.status >= 200 && res.status < 300) {
|
|
164
|
-
if (nudges && text.includes('"nudges"')) {
|
|
165
|
-
try {
|
|
166
|
-
nudges.push(...nudgesOf(JSON.parse(text)));
|
|
167
|
-
} catch {
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return "ok";
|
|
171
|
-
}
|
|
172
|
-
if (res.status === 429 || res.status >= 500) return "retry";
|
|
173
|
-
return "drop";
|
|
174
|
-
} catch {
|
|
175
|
-
return "retry";
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
async function runHook(args, deps) {
|
|
179
|
-
try {
|
|
180
|
-
await runHookInner(args, deps, deps.now());
|
|
181
|
-
} catch {
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function machineCoversTool(tool) {
|
|
185
|
-
const m = readMachine();
|
|
186
|
-
if (!m || m.revoked) return false;
|
|
187
|
-
if (tool === "claude") return m.installed.claude_dirs.length > 0;
|
|
188
|
-
if (tool === "codex") return m.installed.codex_dir !== void 0;
|
|
189
|
-
return false;
|
|
190
|
-
}
|
|
191
|
-
async function runHookInner(args, deps, startedAt) {
|
|
192
|
-
const [toolArg, native] = args;
|
|
193
|
-
if (!toolArg || !native || !TOOLS.has(toolArg)) return;
|
|
194
|
-
const pi = args.indexOf("--profile");
|
|
195
|
-
const profile = pi >= 0 ? args[pi + 1] : void 0;
|
|
196
|
-
const machine = profile !== void 0 ? readMachine() : void 0;
|
|
197
|
-
if (profile !== void 0 && (!machine || machine.revoked || !PROFILE_KEY_RE.test(profile))) return;
|
|
198
|
-
if (profile === void 0 && machineCoversTool(toolArg)) return;
|
|
199
|
-
const host = machine ? machine.host : deps.env.HIVEFLOOR_URL ? hostFromEnv(deps.env) : defaultHost() ?? DEFAULT_HOST;
|
|
200
|
-
const grokId = deps.env.GROK_SESSION_ID;
|
|
201
|
-
const tool = grokId ? "grok" : toolArg;
|
|
202
|
-
const envToken = deps.env.HIVEFLOOR_TOKEN;
|
|
203
|
-
const stored = !machine && !envToken ? await loadToken(host, tool) : void 0;
|
|
204
|
-
const token = machine ? machine.token : envToken || stored?.token;
|
|
205
|
-
if (!token) return;
|
|
206
|
-
let input = {};
|
|
207
|
-
try {
|
|
208
|
-
const raw = await deps.readStdin();
|
|
209
|
-
const parsed = raw.trim() ? JSON.parse(raw) : {};
|
|
210
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) input = parsed;
|
|
211
|
-
} catch {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
if (grokId && !input.session_id && !input.conversation_id) input = { ...input, session_id: grokId };
|
|
215
|
-
const mapped = mapHookEvent(toolArg === "grok" ? "claude" : toolArg, native, input);
|
|
216
|
-
if (!mapped) return;
|
|
217
|
-
const nowMs = deps.now();
|
|
218
|
-
const event = { ...mapped, tool, client_at: new Date(nowMs).toISOString() };
|
|
219
|
-
const contextName = grokId ? null : contextEventName(toolArg, native);
|
|
220
|
-
if (contextName) event.deliver = true;
|
|
221
|
-
const nudges = [];
|
|
222
|
-
const show = () => printNudges(deps, contextName, event.session_id, nudges, nowMs);
|
|
223
|
-
if (grokId && isDuplicate(`${tool}|${event.session_id}|${event.event}|${event.subagent_id ?? ""}`, nowMs)) return;
|
|
224
|
-
const repo = await detectRepo(cwdOf(input) ?? deps.cwd);
|
|
225
|
-
if (repo) event.repo = { remote: repo.remote, ...repo.branch ? { branch: repo.branch } : {}, ...repo.path ? { path: repo.path } : {} };
|
|
226
|
-
if (machine && profile !== void 0) {
|
|
227
|
-
const account = deps.env.FLEET_PROFILE?.trim();
|
|
228
|
-
const mevent = { ...event, profile, ...account && SESSION_ACCOUNT_RE.test(account) ? { account } : {} };
|
|
229
|
-
if (serviceAlive(deps.now())) {
|
|
230
|
-
appendToSpool(mevent, machineSpoolFile());
|
|
231
|
-
if (contextName) nudges.push(...takeStashed(event.session_id, nowMs).map((text) => ({ session_id: event.session_id, text })));
|
|
232
|
-
show();
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
const claim2 = takeSpool(machineSpoolFile());
|
|
236
|
-
await sendBatches(deps, host, token, [...claim2?.events ?? [], mevent], startedAt, "/api/v1/machine/hooks", claim2, machineSpoolFile(), nudges);
|
|
237
|
-
show();
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
const claim = takeSpool();
|
|
241
|
-
await sendBatches(deps, host, token, [...claim?.events ?? [], event], startedAt, "/api/v1/hooks", claim, void 0, nudges);
|
|
242
|
-
show();
|
|
243
|
-
}
|
|
244
|
-
function printNudges(deps, contextName, sessionId, nudges, nowMs) {
|
|
245
|
-
if (nudges.length === 0) return;
|
|
246
|
-
const mine = contextName ? nudges.filter((n) => n.session_id === sessionId) : [];
|
|
247
|
-
const others = nudges.filter((n) => !mine.includes(n));
|
|
248
|
-
if (others.length > 0) stashNudges(others, nowMs);
|
|
249
|
-
if (!contextName || mine.length === 0) return;
|
|
250
|
-
const out = contextOutput(contextName, mine.map((n) => n.text));
|
|
251
|
-
try {
|
|
252
|
-
(deps.write ?? ((t) => void process.stdout.write(`${t}
|
|
253
|
-
`)))(out);
|
|
254
|
-
} catch {
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
async function sendBatches(deps, host, token, pending, startedAt, route, claim, spool, nudges) {
|
|
258
|
-
const batches = [];
|
|
259
|
-
for (let k = 0; k < pending.length; k += HOOK_BATCH_MAX) batches.push(pending.slice(k, k + HOOK_BATCH_MAX));
|
|
260
|
-
const unsent = [];
|
|
261
|
-
let down = false;
|
|
262
|
-
for (const batch of batches) {
|
|
263
|
-
const left = HARD_EXIT_MS - EXIT_MARGIN_MS - (deps.now() - startedAt);
|
|
264
|
-
if (down || left < MIN_POST_MS) {
|
|
265
|
-
unsent.push(...batch);
|
|
266
|
-
down = true;
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
const r = await post(deps, host, token, batch, Math.min(POST_TIMEOUT_MS, left), route, nudges);
|
|
270
|
-
if (r === "retry") {
|
|
271
|
-
unsent.push(...batch);
|
|
272
|
-
down = true;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
releaseSpool(claim, unsent, spool);
|
|
276
|
-
}
|
|
277
|
-
async function readStdin(timeoutMs = 1e3) {
|
|
278
|
-
if (process.stdin.isTTY) return "";
|
|
279
|
-
return await new Promise((resolve) => {
|
|
280
|
-
const chunks = [];
|
|
281
|
-
const done = () => resolve(Buffer.concat(chunks).toString("utf8"));
|
|
282
|
-
const timer = setTimeout(done, timeoutMs);
|
|
283
|
-
process.stdin.on("data", (c) => chunks.push(c));
|
|
284
|
-
process.stdin.on("end", () => {
|
|
285
|
-
clearTimeout(timer);
|
|
286
|
-
done();
|
|
287
|
-
});
|
|
288
|
-
process.stdin.on("error", () => {
|
|
289
|
-
clearTimeout(timer);
|
|
290
|
-
done();
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
function runHookCli(args) {
|
|
295
|
-
return runHook(args, { env: process.env, cwd: process.cwd(), fetch: (...a) => fetch(...a), now: () => Date.now(), readStdin });
|
|
296
|
-
}
|
|
297
|
-
export {
|
|
298
|
-
readStdin,
|
|
299
|
-
runHook,
|
|
300
|
-
runHookCli
|
|
301
|
-
};
|
package/dist/mcp-N2TMD4GR.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
detectRepo
|
|
4
|
-
} from "./chunk-2BSA7LFD.js";
|
|
5
|
-
import {
|
|
6
|
-
resolveSession
|
|
7
|
-
} from "./chunk-7KF7IQJN.js";
|
|
8
|
-
import {
|
|
9
|
-
toolFromEnv
|
|
10
|
-
} from "./chunk-2IMJECYD.js";
|
|
11
|
-
import {
|
|
12
|
-
flagStr
|
|
13
|
-
} from "./chunk-TKMIV7BG.js";
|
|
14
|
-
import {
|
|
15
|
-
loadToken
|
|
16
|
-
} from "./chunk-PDXYOREI.js";
|
|
17
|
-
import "./chunk-VNCQFFQO.js";
|
|
18
|
-
import {
|
|
19
|
-
cliNpxCommand,
|
|
20
|
-
isSecureUrl,
|
|
21
|
-
normalizeHost
|
|
22
|
-
} from "./chunk-ZC2DAKB5.js";
|
|
23
|
-
import "./chunk-K3NQKI34.js";
|
|
24
|
-
|
|
25
|
-
// src/mcp.ts
|
|
26
|
-
import os from "os";
|
|
27
|
-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
28
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
29
|
-
async function contextHeaders(ctx, token, toolName) {
|
|
30
|
-
const h = { Authorization: `Bearer ${token}`, "X-HF-Tool": ctx.env.HIVEFLOOR_TOOL || toolFromEnv(ctx.env) || toolName, "X-HF-Machine": os.hostname().split(".")[0] ?? "machine" };
|
|
31
|
-
const session = ctx.env.HIVEFLOOR_SESSION || ctx.env.CLAUDE_SESSION_ID || ctx.env.GROK_SESSION_ID || ctx.env.CODEX_SESSION_ID;
|
|
32
|
-
if (session) h["X-HF-Session"] = session;
|
|
33
|
-
const model = ctx.env.HIVEFLOOR_MODEL || ctx.env.ANTHROPIC_MODEL;
|
|
34
|
-
if (model) h["X-HF-Model"] = model;
|
|
35
|
-
const repo = await detectRepo(ctx.cwd);
|
|
36
|
-
if (repo) {
|
|
37
|
-
h["X-HF-Repo"] = repo.remote;
|
|
38
|
-
if (repo.branch) h["X-HF-Branch"] = repo.branch;
|
|
39
|
-
if (repo.path) h["X-HF-Path"] = repo.path;
|
|
40
|
-
}
|
|
41
|
-
return h;
|
|
42
|
-
}
|
|
43
|
-
var isRequest = (m) => "method" in m && "id" in m;
|
|
44
|
-
function mcpTargetUrl(flagUrl, host) {
|
|
45
|
-
if (!flagUrl) return new URL(`${host}/mcp`);
|
|
46
|
-
let u;
|
|
47
|
-
try {
|
|
48
|
-
u = new URL(flagUrl);
|
|
49
|
-
} catch {
|
|
50
|
-
throw new Error("--url is not a URL");
|
|
51
|
-
}
|
|
52
|
-
if (!isSecureUrl(u)) throw new Error(`--url must be https (http is only allowed on localhost): ${u.origin}`);
|
|
53
|
-
return u;
|
|
54
|
-
}
|
|
55
|
-
async function runMcpProxy(ctx, p, io = { stdin: process.stdin, stdout: process.stdout }) {
|
|
56
|
-
const s = await resolveSession(ctx, p);
|
|
57
|
-
if (!s) {
|
|
58
|
-
ctx.err(`hivefloor: not connected. Run: ${cliNpxCommand("connect")}
|
|
59
|
-
`);
|
|
60
|
-
return 1;
|
|
61
|
-
}
|
|
62
|
-
let url;
|
|
63
|
-
try {
|
|
64
|
-
url = mcpTargetUrl(flagStr(p, "url"), s.host);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
ctx.err(`hivefloor mcp: ${e.message}
|
|
67
|
-
`);
|
|
68
|
-
return 1;
|
|
69
|
-
}
|
|
70
|
-
let token = s.token;
|
|
71
|
-
let tool = s.tool;
|
|
72
|
-
if (url.origin !== new URL(s.host).origin) {
|
|
73
|
-
const other = await loadToken(normalizeHost(url.origin));
|
|
74
|
-
if (!other) {
|
|
75
|
-
ctx.err(`hivefloor mcp: refusing to send the token of ${s.host} to ${url.origin}; connect to that host first
|
|
76
|
-
`);
|
|
77
|
-
return 1;
|
|
78
|
-
}
|
|
79
|
-
token = other.token;
|
|
80
|
-
tool = other.tool;
|
|
81
|
-
}
|
|
82
|
-
const headers = await contextHeaders(ctx, token, tool);
|
|
83
|
-
const upstream = new StreamableHTTPClientTransport(url, { requestInit: { headers } });
|
|
84
|
-
const downstream = new StdioServerTransport(io.stdin, io.stdout);
|
|
85
|
-
return await new Promise((resolve) => {
|
|
86
|
-
let closing = false;
|
|
87
|
-
const finish = (code) => {
|
|
88
|
-
if (closing) return;
|
|
89
|
-
closing = true;
|
|
90
|
-
void Promise.allSettled([upstream.close(), downstream.close()]).then(() => resolve(code));
|
|
91
|
-
};
|
|
92
|
-
downstream.onmessage = (msg) => {
|
|
93
|
-
upstream.send(msg).catch((e) => {
|
|
94
|
-
if (isRequest(msg)) void downstream.send({ jsonrpc: "2.0", id: msg.id, error: { code: -32e3, message: `Hivefloor is not reachable: ${e.message}` } });
|
|
95
|
-
});
|
|
96
|
-
};
|
|
97
|
-
upstream.onmessage = (msg) => {
|
|
98
|
-
const result = msg.result;
|
|
99
|
-
if (result && typeof result.protocolVersion === "string") upstream.setProtocolVersion?.(result.protocolVersion);
|
|
100
|
-
void downstream.send(msg);
|
|
101
|
-
};
|
|
102
|
-
upstream.onerror = (e) => ctx.err(`hivefloor mcp: ${e.message}
|
|
103
|
-
`);
|
|
104
|
-
downstream.onerror = (e) => ctx.err(`hivefloor mcp: ${e.message}
|
|
105
|
-
`);
|
|
106
|
-
downstream.onclose = () => finish(0);
|
|
107
|
-
io.stdin.once("end", () => finish(0));
|
|
108
|
-
io.stdin.once("close", () => finish(0));
|
|
109
|
-
upstream.onclose = () => finish(0);
|
|
110
|
-
upstream.start().then(() => downstream.start()).catch((e) => {
|
|
111
|
-
ctx.err(`hivefloor mcp: ${e.message}
|
|
112
|
-
`);
|
|
113
|
-
finish(1);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
export {
|
|
118
|
-
contextHeaders,
|
|
119
|
-
mcpTargetUrl,
|
|
120
|
-
runMcpProxy
|
|
121
|
-
};
|
package/dist/token-JDRLEV5D.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
resolveSession
|
|
4
|
-
} from "./chunk-7KF7IQJN.js";
|
|
5
|
-
import "./chunk-2IMJECYD.js";
|
|
6
|
-
import "./chunk-TKMIV7BG.js";
|
|
7
|
-
import "./chunk-PDXYOREI.js";
|
|
8
|
-
import "./chunk-VNCQFFQO.js";
|
|
9
|
-
import {
|
|
10
|
-
cliNpxCommand
|
|
11
|
-
} from "./chunk-ZC2DAKB5.js";
|
|
12
|
-
import "./chunk-K3NQKI34.js";
|
|
13
|
-
|
|
14
|
-
// src/token.ts
|
|
15
|
-
async function token(ctx, p) {
|
|
16
|
-
const s = await resolveSession(ctx, p);
|
|
17
|
-
if (!s) {
|
|
18
|
-
ctx.err(`hivefloor: no token stored. Run: ${cliNpxCommand("connect")}
|
|
19
|
-
`);
|
|
20
|
-
return 1;
|
|
21
|
-
}
|
|
22
|
-
if (ctx.stdoutIsTTY && !p.flags.reveal) {
|
|
23
|
-
ctx.err("hivefloor: refusing to print the token to a terminal. Use it in a pipe or $(...), or pass --reveal.\n");
|
|
24
|
-
return 1;
|
|
25
|
-
}
|
|
26
|
-
ctx.out(`${s.token}
|
|
27
|
-
`);
|
|
28
|
-
return 0;
|
|
29
|
-
}
|
|
30
|
-
export {
|
|
31
|
-
token
|
|
32
|
-
};
|