@sideboard-ai/core 0.1.311 → 0.1.312
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/{agents-XXXRQJJO.js → agents-IOJRGGK3.js} +1 -1
- package/dist/{agents-QIIZYNOM.js → agents-XDI6QHBA.js} +1 -1
- package/dist/{chunk-GQJOLTZU.js → chunk-2P2HYXA2.js} +620 -18
- package/dist/{chunk-4YBQBVYL.js → chunk-4FZUUH6W.js} +514 -22
- package/dist/{chunk-7ORMOP3D.js → chunk-LLTWP4PK.js} +12 -2
- package/dist/{chunk-2ER7DQJP.js → chunk-VIVXKN5N.js} +19 -3
- package/dist/index.cjs +743 -384
- package/dist/index.d.cts +42 -8
- package/dist/index.d.ts +42 -8
- package/dist/index.js +27 -216
- package/dist/mcp/run-stdio.cjs +759 -116
- package/dist/mcp/run-stdio.js +2 -2
- package/dist/{orchestrator-2CCFGYAA.js → orchestrator-BYTSILLH.js} +2 -2
- package/dist/{orchestrator-3W5S6TNP.js → orchestrator-S44BMNN7.js} +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -13869,18 +13869,18 @@ function mcpUiContentSecurityPolicy(csp) {
|
|
|
13869
13869
|
const connect = (csp?.connectDomains ?? []).join(" ");
|
|
13870
13870
|
const frames = csp?.frameDomains?.length ? csp.frameDomains.join(" ") : "'none'";
|
|
13871
13871
|
const base = csp?.baseUriDomains?.length ? csp.baseUriDomains.join(" ") : "'none'";
|
|
13872
|
+
const connectSrc = connect ? `'self' ${connect}`.trim() : "'none'";
|
|
13872
13873
|
return [
|
|
13873
13874
|
"default-src 'none'",
|
|
13874
|
-
`script-src 'self' 'unsafe-inline'
|
|
13875
|
+
`script-src 'self' 'unsafe-inline' ${resource}`.trim(),
|
|
13875
13876
|
`style-src 'self' 'unsafe-inline' ${resource}`.trim(),
|
|
13876
|
-
`img-src 'self' data:
|
|
13877
|
-
`font-src 'self'
|
|
13878
|
-
`connect-src
|
|
13879
|
-
`media-src 'self' data:
|
|
13877
|
+
`img-src 'self' data: ${resource}`.trim(),
|
|
13878
|
+
`font-src 'self' ${resource}`.trim(),
|
|
13879
|
+
`connect-src ${connectSrc}`,
|
|
13880
|
+
`media-src 'self' data: ${resource}`.trim(),
|
|
13880
13881
|
`frame-src ${frames}`,
|
|
13881
13882
|
`base-uri ${base}`,
|
|
13882
|
-
"object-src 'none'"
|
|
13883
|
-
"form-action 'self'"
|
|
13883
|
+
"object-src 'none'"
|
|
13884
13884
|
].join("; ");
|
|
13885
13885
|
}
|
|
13886
13886
|
function htmlText(text7, blob) {
|
|
@@ -13917,8 +13917,10 @@ function originList(value) {
|
|
|
13917
13917
|
return out;
|
|
13918
13918
|
}
|
|
13919
13919
|
function originToken(value) {
|
|
13920
|
+
const trimmed = value.trim();
|
|
13921
|
+
if (/^(https?|wss?):\/\/\*\.[a-z0-9.-]+(?::\d+)?$/i.test(trimmed)) return trimmed;
|
|
13920
13922
|
try {
|
|
13921
|
-
const url = new URL(
|
|
13923
|
+
const url = new URL(trimmed);
|
|
13922
13924
|
if (url.protocol !== "https:" && url.protocol !== "http:" && url.protocol !== "wss:" && url.protocol !== "ws:") {
|
|
13923
13925
|
return null;
|
|
13924
13926
|
}
|
|
@@ -15279,6 +15281,524 @@ var init_orch_mcp_isolation = __esm({
|
|
|
15279
15281
|
}
|
|
15280
15282
|
});
|
|
15281
15283
|
|
|
15284
|
+
// src/mcp-ui/visibility.ts
|
|
15285
|
+
function visibilityFromMeta(meta) {
|
|
15286
|
+
const rec = asRecord4(meta);
|
|
15287
|
+
const ui = asRecord4(rec.ui);
|
|
15288
|
+
const raw = ui.visibility;
|
|
15289
|
+
if (!Array.isArray(raw)) return ["model", "app"];
|
|
15290
|
+
const out = [];
|
|
15291
|
+
for (const item of raw) {
|
|
15292
|
+
if (item !== "model" && item !== "app") continue;
|
|
15293
|
+
if (!out.includes(item)) out.push(item);
|
|
15294
|
+
}
|
|
15295
|
+
return out.length ? out : ["model", "app"];
|
|
15296
|
+
}
|
|
15297
|
+
function toolVisibleTo(visibility, audience) {
|
|
15298
|
+
const vis = visibility?.length ? visibility : ["model", "app"];
|
|
15299
|
+
return vis.includes(audience);
|
|
15300
|
+
}
|
|
15301
|
+
function asRecord4(value) {
|
|
15302
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
15303
|
+
return value;
|
|
15304
|
+
}
|
|
15305
|
+
var init_visibility = __esm({
|
|
15306
|
+
"src/mcp-ui/visibility.ts"() {
|
|
15307
|
+
"use strict";
|
|
15308
|
+
}
|
|
15309
|
+
});
|
|
15310
|
+
|
|
15311
|
+
// src/mcp-ui/proxy-server.ts
|
|
15312
|
+
function attachMcpUiProxyHandlers(server, session) {
|
|
15313
|
+
server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
|
|
15314
|
+
const tools = await session.listTools();
|
|
15315
|
+
return { tools: tools.filter((tool) => toolVisibleTo(tool.visibility, "model")).map(listedTool) };
|
|
15316
|
+
});
|
|
15317
|
+
server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
15318
|
+
const name = request.params.name;
|
|
15319
|
+
const tools = await session.listTools();
|
|
15320
|
+
const tool = tools.find((item) => item.name === name);
|
|
15321
|
+
if (!tool || !toolVisibleTo(tool.visibility, "model")) {
|
|
15322
|
+
throw new Error(`Tool ${name} is not available to the model`);
|
|
15323
|
+
}
|
|
15324
|
+
return await session.callTool(name, request.params.arguments ?? {});
|
|
15325
|
+
});
|
|
15326
|
+
server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
|
|
15327
|
+
const resource = await session.readResource(request.params.uri);
|
|
15328
|
+
if (!resource) throw new Error(`Resource ${request.params.uri} was empty`);
|
|
15329
|
+
return {
|
|
15330
|
+
contents: [
|
|
15331
|
+
{
|
|
15332
|
+
uri: resource.uri,
|
|
15333
|
+
...resource.mimeType ? { mimeType: resource.mimeType } : {},
|
|
15334
|
+
...resource.text != null ? { text: resource.text } : {},
|
|
15335
|
+
...resource.blob != null ? { blob: resource.blob } : {}
|
|
15336
|
+
}
|
|
15337
|
+
]
|
|
15338
|
+
};
|
|
15339
|
+
});
|
|
15340
|
+
server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => session.listResources());
|
|
15341
|
+
server.setRequestHandler(
|
|
15342
|
+
import_types.ListResourceTemplatesRequestSchema,
|
|
15343
|
+
async () => session.listResourceTemplates()
|
|
15344
|
+
);
|
|
15345
|
+
server.setRequestHandler(import_types.ListPromptsRequestSchema, async () => session.listPrompts());
|
|
15346
|
+
server.setRequestHandler(import_types.GetPromptRequestSchema, async (request) => {
|
|
15347
|
+
return await session.getPrompt(request.params.name, request.params.arguments);
|
|
15348
|
+
});
|
|
15349
|
+
server.fallbackRequestHandler = async (request) => {
|
|
15350
|
+
return await session.forward(request.method, request.params);
|
|
15351
|
+
};
|
|
15352
|
+
}
|
|
15353
|
+
function listedTool(tool) {
|
|
15354
|
+
return {
|
|
15355
|
+
name: tool.name,
|
|
15356
|
+
...tool.description ? { description: tool.description } : {},
|
|
15357
|
+
inputSchema: tool.inputSchema ?? { type: "object", properties: {} },
|
|
15358
|
+
_meta: {
|
|
15359
|
+
ui: {
|
|
15360
|
+
...tool.resourceUri ? { resourceUri: tool.resourceUri } : {},
|
|
15361
|
+
visibility: tool.visibility
|
|
15362
|
+
}
|
|
15363
|
+
}
|
|
15364
|
+
};
|
|
15365
|
+
}
|
|
15366
|
+
var import_server, import_types;
|
|
15367
|
+
var init_proxy_server = __esm({
|
|
15368
|
+
"src/mcp-ui/proxy-server.ts"() {
|
|
15369
|
+
"use strict";
|
|
15370
|
+
import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
15371
|
+
import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
15372
|
+
init_visibility();
|
|
15373
|
+
}
|
|
15374
|
+
});
|
|
15375
|
+
|
|
15376
|
+
// src/mcp-ui/proxy-http.ts
|
|
15377
|
+
async function listenMcpUiProxy(opts) {
|
|
15378
|
+
const token = (0, import_node_crypto11.randomBytes)(24).toString("hex");
|
|
15379
|
+
const transports = /* @__PURE__ */ new Map();
|
|
15380
|
+
const httpServer = (0, import_node_http.createServer)((req, res) => {
|
|
15381
|
+
void handle(req, res);
|
|
15382
|
+
});
|
|
15383
|
+
await new Promise((resolve3, reject) => {
|
|
15384
|
+
httpServer.once("error", reject);
|
|
15385
|
+
httpServer.listen(0, "127.0.0.1", () => resolve3());
|
|
15386
|
+
});
|
|
15387
|
+
const addr = httpServer.address();
|
|
15388
|
+
if (!addr || typeof addr === "string") throw new Error("mcp-ui proxy failed to bind");
|
|
15389
|
+
const origin = `http://127.0.0.1:${addr.port}`;
|
|
15390
|
+
async function handle(req, res) {
|
|
15391
|
+
if (req.headers.authorization !== `Bearer ${token}`) {
|
|
15392
|
+
res.writeHead(401).end();
|
|
15393
|
+
return;
|
|
15394
|
+
}
|
|
15395
|
+
const target = parseMcpUiProxyPath(req.url);
|
|
15396
|
+
if (!target) {
|
|
15397
|
+
res.writeHead(404).end();
|
|
15398
|
+
return;
|
|
15399
|
+
}
|
|
15400
|
+
try {
|
|
15401
|
+
const session = await opts.sessionFor(target.server, target.dirsKey);
|
|
15402
|
+
if (!session) {
|
|
15403
|
+
res.writeHead(404).end();
|
|
15404
|
+
return;
|
|
15405
|
+
}
|
|
15406
|
+
const header = req.headers["mcp-session-id"];
|
|
15407
|
+
const sid = typeof header === "string" ? header : "";
|
|
15408
|
+
const sessionKey = `${target.server}:${target.dirsKey}`;
|
|
15409
|
+
let transport = sid ? transports.get(`${sessionKey}:${sid}`) : void 0;
|
|
15410
|
+
if (!transport) {
|
|
15411
|
+
if (req.method !== "POST") {
|
|
15412
|
+
res.writeHead(400).end();
|
|
15413
|
+
return;
|
|
15414
|
+
}
|
|
15415
|
+
const created = new import_streamableHttp.StreamableHTTPServerTransport({
|
|
15416
|
+
sessionIdGenerator: () => (0, import_node_crypto11.randomUUID)(),
|
|
15417
|
+
allowedHosts: ["127.0.0.1", "localhost"],
|
|
15418
|
+
onsessioninitialized: (id) => {
|
|
15419
|
+
transports.set(`${sessionKey}:${id}`, created);
|
|
15420
|
+
},
|
|
15421
|
+
onsessionclosed: (id) => {
|
|
15422
|
+
transports.delete(`${sessionKey}:${id}`);
|
|
15423
|
+
}
|
|
15424
|
+
});
|
|
15425
|
+
transport = created;
|
|
15426
|
+
const mcp = new import_server2.Server(
|
|
15427
|
+
{ name: `sideboard-ui-proxy-${target.server}`, version: "1.0.0" },
|
|
15428
|
+
{ capabilities: session.capabilities() }
|
|
15429
|
+
);
|
|
15430
|
+
attachMcpUiProxyHandlers(mcp, session);
|
|
15431
|
+
await mcp.connect(created);
|
|
15432
|
+
}
|
|
15433
|
+
await transport.handleRequest(req, res);
|
|
15434
|
+
} catch {
|
|
15435
|
+
if (!res.headersSent) res.writeHead(500).end();
|
|
15436
|
+
}
|
|
15437
|
+
}
|
|
15438
|
+
return {
|
|
15439
|
+
urlFor(server, dirsKey) {
|
|
15440
|
+
const base = `${origin}/s/${encodeURIComponent(server)}`;
|
|
15441
|
+
return dirsKey ? `${base}/d/${dirsKey}` : base;
|
|
15442
|
+
},
|
|
15443
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
15444
|
+
async close() {
|
|
15445
|
+
await Promise.all([...transports.values()].map((item) => item.close().catch(() => void 0)));
|
|
15446
|
+
transports.clear();
|
|
15447
|
+
await new Promise((resolve3) => httpServer.close(() => resolve3()));
|
|
15448
|
+
}
|
|
15449
|
+
};
|
|
15450
|
+
}
|
|
15451
|
+
function parseMcpUiProxyPath(url) {
|
|
15452
|
+
const path2 = (url ?? "").split("?")[0] ?? "";
|
|
15453
|
+
if (!path2.startsWith("/s/")) return null;
|
|
15454
|
+
const rest = path2.slice(3).replace(/\/$/, "");
|
|
15455
|
+
const split = rest.indexOf("/d/");
|
|
15456
|
+
try {
|
|
15457
|
+
if (split < 0) {
|
|
15458
|
+
const server2 = decodeURIComponent(rest).trim();
|
|
15459
|
+
return server2 ? { server: server2, dirsKey: "" } : null;
|
|
15460
|
+
}
|
|
15461
|
+
const server = decodeURIComponent(rest.slice(0, split)).trim();
|
|
15462
|
+
const dirsKey = rest.slice(split + 3);
|
|
15463
|
+
if (!server || !/^[a-f0-9]{16}$/.test(dirsKey)) return null;
|
|
15464
|
+
return { server, dirsKey };
|
|
15465
|
+
} catch {
|
|
15466
|
+
return null;
|
|
15467
|
+
}
|
|
15468
|
+
}
|
|
15469
|
+
var import_node_crypto11, import_node_http, import_server2, import_streamableHttp;
|
|
15470
|
+
var init_proxy_http = __esm({
|
|
15471
|
+
"src/mcp-ui/proxy-http.ts"() {
|
|
15472
|
+
"use strict";
|
|
15473
|
+
import_node_crypto11 = require("crypto");
|
|
15474
|
+
import_node_http = require("http");
|
|
15475
|
+
import_server2 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
15476
|
+
import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
15477
|
+
init_proxy_server();
|
|
15478
|
+
}
|
|
15479
|
+
});
|
|
15480
|
+
|
|
15481
|
+
// src/mcp-ui/session.ts
|
|
15482
|
+
async function orEmpty(run2, fallback) {
|
|
15483
|
+
try {
|
|
15484
|
+
return await run2();
|
|
15485
|
+
} catch {
|
|
15486
|
+
return fallback;
|
|
15487
|
+
}
|
|
15488
|
+
}
|
|
15489
|
+
async function openMcpUiSession(launch) {
|
|
15490
|
+
return openMcpUiSessionFromTransport(transportForLaunch(launch));
|
|
15491
|
+
}
|
|
15492
|
+
async function openMcpUiSessionFromTransport(transport) {
|
|
15493
|
+
const client = new import_client.Client(
|
|
15494
|
+
{ name: "sideboard", version: "1.0.0" },
|
|
15495
|
+
{ capabilities: UI_CAPABILITIES }
|
|
15496
|
+
);
|
|
15497
|
+
await client.connect(transport, { timeout: REQUEST_TIMEOUT_MS });
|
|
15498
|
+
return {
|
|
15499
|
+
async listTools() {
|
|
15500
|
+
const listed = await client.listTools(void 0, { timeout: REQUEST_TIMEOUT_MS });
|
|
15501
|
+
return listed.tools.map((tool) => {
|
|
15502
|
+
const meta = tool._meta;
|
|
15503
|
+
return {
|
|
15504
|
+
name: tool.name,
|
|
15505
|
+
...tool.description ? { description: tool.description } : {},
|
|
15506
|
+
...tool.inputSchema ? { inputSchema: tool.inputSchema } : {},
|
|
15507
|
+
resourceUri: uiResourceUriFromMeta(meta),
|
|
15508
|
+
visibility: visibilityFromMeta(meta),
|
|
15509
|
+
...cspFromMeta(meta) ? { csp: cspFromMeta(meta) } : {}
|
|
15510
|
+
};
|
|
15511
|
+
});
|
|
15512
|
+
},
|
|
15513
|
+
listResources: () => orEmpty(
|
|
15514
|
+
() => client.listResources(void 0, { timeout: REQUEST_TIMEOUT_MS }),
|
|
15515
|
+
{ resources: [] }
|
|
15516
|
+
),
|
|
15517
|
+
listResourceTemplates: () => orEmpty(
|
|
15518
|
+
() => client.listResourceTemplates(void 0, { timeout: REQUEST_TIMEOUT_MS }),
|
|
15519
|
+
{ resourceTemplates: [] }
|
|
15520
|
+
),
|
|
15521
|
+
listPrompts: () => orEmpty(
|
|
15522
|
+
() => client.listPrompts(void 0, { timeout: REQUEST_TIMEOUT_MS }),
|
|
15523
|
+
{ prompts: [] }
|
|
15524
|
+
),
|
|
15525
|
+
getPrompt(name, args) {
|
|
15526
|
+
return client.getPrompt({ name, arguments: args }, { timeout: REQUEST_TIMEOUT_MS });
|
|
15527
|
+
},
|
|
15528
|
+
async readResource(uri) {
|
|
15529
|
+
const result = await client.readResource({ uri }, { timeout: REQUEST_TIMEOUT_MS });
|
|
15530
|
+
const content = result.contents?.[0];
|
|
15531
|
+
if (!content) return null;
|
|
15532
|
+
const text7 = "text" in content && typeof content.text === "string" ? content.text : void 0;
|
|
15533
|
+
const blob = "blob" in content && typeof content.blob === "string" ? content.blob : void 0;
|
|
15534
|
+
return {
|
|
15535
|
+
uri: content.uri,
|
|
15536
|
+
...content.mimeType ? { mimeType: content.mimeType } : {},
|
|
15537
|
+
...text7 != null ? { text: text7 } : {},
|
|
15538
|
+
...blob != null ? { blob } : {},
|
|
15539
|
+
...cspFromMeta(content._meta) ? { csp: cspFromMeta(content._meta) } : {}
|
|
15540
|
+
};
|
|
15541
|
+
},
|
|
15542
|
+
async callTool(name, args) {
|
|
15543
|
+
return client.callTool({ name, arguments: args }, void 0, { timeout: REQUEST_TIMEOUT_MS });
|
|
15544
|
+
},
|
|
15545
|
+
capabilities() {
|
|
15546
|
+
const caps = client.getServerCapabilities() ?? {};
|
|
15547
|
+
return {
|
|
15548
|
+
tools: caps.tools ?? {},
|
|
15549
|
+
resources: caps.resources ?? {},
|
|
15550
|
+
prompts: caps.prompts ?? {},
|
|
15551
|
+
completions: caps.completions ?? {},
|
|
15552
|
+
...caps.logging ? { logging: caps.logging } : {}
|
|
15553
|
+
};
|
|
15554
|
+
},
|
|
15555
|
+
forward(method, params) {
|
|
15556
|
+
return client.request(
|
|
15557
|
+
{ method, params },
|
|
15558
|
+
import_types2.ResultSchema,
|
|
15559
|
+
{ timeout: REQUEST_TIMEOUT_MS }
|
|
15560
|
+
);
|
|
15561
|
+
},
|
|
15562
|
+
async close() {
|
|
15563
|
+
await client.close();
|
|
15564
|
+
}
|
|
15565
|
+
};
|
|
15566
|
+
}
|
|
15567
|
+
function transportForLaunch(launch) {
|
|
15568
|
+
if (launch.kind === "stdio") {
|
|
15569
|
+
return new import_stdio.StdioClientTransport({
|
|
15570
|
+
command: launch.command,
|
|
15571
|
+
args: launch.args,
|
|
15572
|
+
env: { ...(0, import_stdio.getDefaultEnvironment)(), ...launch.env },
|
|
15573
|
+
stderr: "ignore",
|
|
15574
|
+
...launch.cwd ? { cwd: launch.cwd } : {}
|
|
15575
|
+
});
|
|
15576
|
+
}
|
|
15577
|
+
const url = new URL(launch.url);
|
|
15578
|
+
const requestInit = launch.headers ? { headers: launch.headers } : void 0;
|
|
15579
|
+
if (launch.kind === "sse") {
|
|
15580
|
+
return new import_sse.SSEClientTransport(url, requestInit ? { requestInit } : void 0);
|
|
15581
|
+
}
|
|
15582
|
+
return new import_streamableHttp2.StreamableHTTPClientTransport(url, requestInit ? { requestInit } : void 0);
|
|
15583
|
+
}
|
|
15584
|
+
var import_client, import_sse, import_stdio, import_streamableHttp2, import_types2, REQUEST_TIMEOUT_MS, UI_CAPABILITIES;
|
|
15585
|
+
var init_session = __esm({
|
|
15586
|
+
"src/mcp-ui/session.ts"() {
|
|
15587
|
+
"use strict";
|
|
15588
|
+
import_client = require("@modelcontextprotocol/sdk/client/index.js");
|
|
15589
|
+
import_sse = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
15590
|
+
import_stdio = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
15591
|
+
import_streamableHttp2 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
15592
|
+
import_types2 = require("@modelcontextprotocol/sdk/types.js");
|
|
15593
|
+
init_meta();
|
|
15594
|
+
init_visibility();
|
|
15595
|
+
REQUEST_TIMEOUT_MS = 2e4;
|
|
15596
|
+
UI_CAPABILITIES = {
|
|
15597
|
+
extensions: {
|
|
15598
|
+
"io.modelcontextprotocol/ui": {
|
|
15599
|
+
mimeTypes: ["text/html;profile=mcp-app"]
|
|
15600
|
+
}
|
|
15601
|
+
}
|
|
15602
|
+
};
|
|
15603
|
+
}
|
|
15604
|
+
});
|
|
15605
|
+
|
|
15606
|
+
// src/mcp-ui/host.ts
|
|
15607
|
+
function getMcpUiHost() {
|
|
15608
|
+
if (!singleton) {
|
|
15609
|
+
singleton = new McpUiHost({
|
|
15610
|
+
entries: (projectDirs) => listUserClaudeMcpServerEntries((0, import_node_os16.homedir)(), projectDirs)
|
|
15611
|
+
});
|
|
15612
|
+
}
|
|
15613
|
+
return singleton;
|
|
15614
|
+
}
|
|
15615
|
+
async function proxyClaudeUserMcp(orchestrator, projectDirs) {
|
|
15616
|
+
if (orchestrator) return {};
|
|
15617
|
+
const dirs = projectDirs.filter((d) => typeof d === "string" && d.length > 0);
|
|
15618
|
+
return getMcpUiHost().proxyEntries(listUserClaudeMcpServerEntries((0, import_node_os16.homedir)(), dirs), dirs);
|
|
15619
|
+
}
|
|
15620
|
+
function closeMcpUiHost() {
|
|
15621
|
+
const host = singleton;
|
|
15622
|
+
singleton = void 0;
|
|
15623
|
+
if (host) void host.closeAll();
|
|
15624
|
+
}
|
|
15625
|
+
function dirsKeyFor(projectDirs) {
|
|
15626
|
+
if (!projectDirs?.length) return "";
|
|
15627
|
+
return (0, import_node_crypto12.createHash)("sha256").update(projectDirs.join("\0")).digest("hex").slice(0, 16);
|
|
15628
|
+
}
|
|
15629
|
+
var import_node_crypto12, import_node_os16, TOOL_TTL_MS, McpUiHost, singleton;
|
|
15630
|
+
var init_host = __esm({
|
|
15631
|
+
"src/mcp-ui/host.ts"() {
|
|
15632
|
+
"use strict";
|
|
15633
|
+
import_node_crypto12 = require("crypto");
|
|
15634
|
+
import_node_os16 = require("os");
|
|
15635
|
+
init_orch_mcp_isolation();
|
|
15636
|
+
init_meta();
|
|
15637
|
+
init_proxy_http();
|
|
15638
|
+
init_session();
|
|
15639
|
+
init_visibility();
|
|
15640
|
+
TOOL_TTL_MS = 5 * 60 * 1e3;
|
|
15641
|
+
McpUiHost = class {
|
|
15642
|
+
constructor(opts) {
|
|
15643
|
+
this.opts = opts;
|
|
15644
|
+
}
|
|
15645
|
+
opts;
|
|
15646
|
+
sessions = /* @__PURE__ */ new Map();
|
|
15647
|
+
toolLists = /* @__PURE__ */ new Map();
|
|
15648
|
+
proxy;
|
|
15649
|
+
proxyDirs = /* @__PURE__ */ new Map();
|
|
15650
|
+
async viewForClaudeTool(toolName, projectDirs) {
|
|
15651
|
+
const entries = this.userEntries(projectDirs);
|
|
15652
|
+
const match = matchClaudeMcpTool(toolName, Object.keys(entries));
|
|
15653
|
+
if (!match) return null;
|
|
15654
|
+
const launch = parseMcpServerLaunch(entries[match.server] ?? {});
|
|
15655
|
+
if (!launch) return null;
|
|
15656
|
+
try {
|
|
15657
|
+
const session = await this.sessionFor(match.server, launch);
|
|
15658
|
+
const tools = await this.toolsFor(match.server, launch, session);
|
|
15659
|
+
const tool = tools.find((item) => item.name === match.tool);
|
|
15660
|
+
if (!tool?.resourceUri) return null;
|
|
15661
|
+
const resource = await session.readResource(tool.resourceUri);
|
|
15662
|
+
if (!resource) return null;
|
|
15663
|
+
const html = htmlFromResourceContent(resource);
|
|
15664
|
+
if (!html) return null;
|
|
15665
|
+
const csp = resource.csp ?? tool.csp;
|
|
15666
|
+
return {
|
|
15667
|
+
server: match.server,
|
|
15668
|
+
tool: match.tool,
|
|
15669
|
+
uri: html.uri,
|
|
15670
|
+
mimeType: html.mimeType,
|
|
15671
|
+
html: html.html,
|
|
15672
|
+
csp: mcpUiContentSecurityPolicy(csp)
|
|
15673
|
+
};
|
|
15674
|
+
} catch (err) {
|
|
15675
|
+
console.error(
|
|
15676
|
+
`[mcp-ui] ${match.server}/${match.tool}:`,
|
|
15677
|
+
err instanceof Error ? err.message : err
|
|
15678
|
+
);
|
|
15679
|
+
return null;
|
|
15680
|
+
}
|
|
15681
|
+
}
|
|
15682
|
+
/**
|
|
15683
|
+
* Point Claude at loopback HTTP so it shares this host's upstream session
|
|
15684
|
+
* and never sees `visibility: ["app"]` tools.
|
|
15685
|
+
*/
|
|
15686
|
+
async proxyEntries(entries, projectDirs) {
|
|
15687
|
+
const names = Object.keys(entries).filter((name) => name.trim());
|
|
15688
|
+
if (names.length === 0) return {};
|
|
15689
|
+
const dirsKey = dirsKeyFor(projectDirs);
|
|
15690
|
+
this.proxyDirs.set(dirsKey, projectDirs);
|
|
15691
|
+
try {
|
|
15692
|
+
const listen = await this.ensureProxy();
|
|
15693
|
+
const out = {};
|
|
15694
|
+
for (const name of names) {
|
|
15695
|
+
out[name] = {
|
|
15696
|
+
type: "http",
|
|
15697
|
+
url: listen.urlFor(name, dirsKey),
|
|
15698
|
+
headers: listen.headers
|
|
15699
|
+
};
|
|
15700
|
+
}
|
|
15701
|
+
return out;
|
|
15702
|
+
} catch (err) {
|
|
15703
|
+
console.error("[mcp-ui] proxy:", err instanceof Error ? err.message : err);
|
|
15704
|
+
return { ...entries };
|
|
15705
|
+
}
|
|
15706
|
+
}
|
|
15707
|
+
async callTool(server, tool, args, projectDirs) {
|
|
15708
|
+
const entry = this.userEntries(projectDirs)[server];
|
|
15709
|
+
if (!entry) throw new Error(`MCP server ${server} is not available`);
|
|
15710
|
+
const launch = parseMcpServerLaunch(entry);
|
|
15711
|
+
if (!launch) throw new Error(`MCP server ${server} is not available`);
|
|
15712
|
+
const session = await this.sessionFor(server, launch);
|
|
15713
|
+
const tools = await this.toolsFor(server, launch, session);
|
|
15714
|
+
const info = tools.find((item) => item.name === tool);
|
|
15715
|
+
if (!info || !toolVisibleTo(info.visibility, "app")) {
|
|
15716
|
+
throw new Error(`Tool ${tool} is not available to the app`);
|
|
15717
|
+
}
|
|
15718
|
+
return session.callTool(tool, args);
|
|
15719
|
+
}
|
|
15720
|
+
async readResource(server, uri, projectDirs) {
|
|
15721
|
+
const session = await this.sessionForName(server, projectDirs);
|
|
15722
|
+
if (!session) throw new Error(`MCP server ${server} is not available`);
|
|
15723
|
+
const resource = await session.readResource(uri);
|
|
15724
|
+
if (!resource) throw new Error(`Resource ${uri} was empty`);
|
|
15725
|
+
return {
|
|
15726
|
+
contents: [
|
|
15727
|
+
{
|
|
15728
|
+
uri: resource.uri,
|
|
15729
|
+
...resource.mimeType ? { mimeType: resource.mimeType } : {},
|
|
15730
|
+
...resource.text != null ? { text: resource.text } : {},
|
|
15731
|
+
...resource.blob != null ? { blob: resource.blob } : {}
|
|
15732
|
+
}
|
|
15733
|
+
]
|
|
15734
|
+
};
|
|
15735
|
+
}
|
|
15736
|
+
async closeAll() {
|
|
15737
|
+
const pending = [...this.sessions.values()];
|
|
15738
|
+
const proxy = this.proxy;
|
|
15739
|
+
this.sessions.clear();
|
|
15740
|
+
this.toolLists.clear();
|
|
15741
|
+
this.proxyDirs.clear();
|
|
15742
|
+
this.proxy = void 0;
|
|
15743
|
+
await Promise.all([
|
|
15744
|
+
...pending.map((session) => session.then((open) => open.close()).catch(() => void 0)),
|
|
15745
|
+
proxy ? proxy.then((listen) => listen.close()).catch(() => void 0) : Promise.resolve()
|
|
15746
|
+
]);
|
|
15747
|
+
}
|
|
15748
|
+
ensureProxy() {
|
|
15749
|
+
if (this.proxy) return this.proxy;
|
|
15750
|
+
this.proxy = listenMcpUiProxy({
|
|
15751
|
+
sessionFor: (server, dirsKey) => {
|
|
15752
|
+
if (dirsKey && !this.proxyDirs.has(dirsKey)) return Promise.resolve(null);
|
|
15753
|
+
return this.sessionForName(server, this.proxyDirs.get(dirsKey));
|
|
15754
|
+
}
|
|
15755
|
+
}).catch((err) => {
|
|
15756
|
+
this.proxy = void 0;
|
|
15757
|
+
throw err;
|
|
15758
|
+
});
|
|
15759
|
+
return this.proxy;
|
|
15760
|
+
}
|
|
15761
|
+
userEntries(projectDirs) {
|
|
15762
|
+
const out = {};
|
|
15763
|
+
for (const [name, entry] of Object.entries(this.opts.entries(projectDirs))) {
|
|
15764
|
+
if (!name.trim() || isInjectedOrchMcpName(name) || !entry) continue;
|
|
15765
|
+
out[name] = entry;
|
|
15766
|
+
}
|
|
15767
|
+
return out;
|
|
15768
|
+
}
|
|
15769
|
+
async sessionForName(server, projectDirs) {
|
|
15770
|
+
const entry = this.userEntries(projectDirs)[server];
|
|
15771
|
+
if (!entry) return null;
|
|
15772
|
+
const launch = parseMcpServerLaunch(entry);
|
|
15773
|
+
if (!launch) return null;
|
|
15774
|
+
return this.sessionFor(server, launch);
|
|
15775
|
+
}
|
|
15776
|
+
sessionFor(server, launch) {
|
|
15777
|
+
const key = `${server}
|
|
15778
|
+
${JSON.stringify(launch)}`;
|
|
15779
|
+
const existing = this.sessions.get(key);
|
|
15780
|
+
if (existing) return existing;
|
|
15781
|
+
const open = this.opts.openSession ?? openMcpUiSession;
|
|
15782
|
+
const pending = open(launch).catch((err) => {
|
|
15783
|
+
this.sessions.delete(key);
|
|
15784
|
+
throw err;
|
|
15785
|
+
});
|
|
15786
|
+
this.sessions.set(key, pending);
|
|
15787
|
+
return pending;
|
|
15788
|
+
}
|
|
15789
|
+
async toolsFor(server, launch, session) {
|
|
15790
|
+
const key = `${server}
|
|
15791
|
+
${JSON.stringify(launch)}`;
|
|
15792
|
+
const cached2 = this.toolLists.get(key);
|
|
15793
|
+
if (cached2 && cached2.key === key && Date.now() - cached2.at < TOOL_TTL_MS) return cached2.tools;
|
|
15794
|
+
const tools = await session.listTools();
|
|
15795
|
+
this.toolLists.set(key, { at: Date.now(), key, tools });
|
|
15796
|
+
return tools;
|
|
15797
|
+
}
|
|
15798
|
+
};
|
|
15799
|
+
}
|
|
15800
|
+
});
|
|
15801
|
+
|
|
15282
15802
|
// src/agents/types.ts
|
|
15283
15803
|
function planModeTurnInstruction(planMode) {
|
|
15284
15804
|
return planMode ? PLAN_MODE_INSTRUCTION : PLAN_MODE_OFF_INSTRUCTION;
|
|
@@ -15474,7 +15994,7 @@ function entryDir() {
|
|
|
15474
15994
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
15475
15995
|
if (cjsDir) return cjsDir;
|
|
15476
15996
|
try {
|
|
15477
|
-
return (0, import_node_path41.dirname)((0, import_node_url2.fileURLToPath)(
|
|
15997
|
+
return (0, import_node_path41.dirname)((0, import_node_url2.fileURLToPath)(import_meta5.url));
|
|
15478
15998
|
} catch {
|
|
15479
15999
|
try {
|
|
15480
16000
|
const req = (0, import_node_module2.createRequire)(process.cwd() + "/");
|
|
@@ -15524,7 +16044,7 @@ async function buildClaudeRpcTurnCommand(req) {
|
|
|
15524
16044
|
}
|
|
15525
16045
|
};
|
|
15526
16046
|
}
|
|
15527
|
-
var import_node_fs38, import_node_module2, import_node_path41, import_node_url2,
|
|
16047
|
+
var import_node_fs38, import_node_module2, import_node_path41, import_node_url2, import_meta5;
|
|
15528
16048
|
var init_claude_host = __esm({
|
|
15529
16049
|
"src/agents/claude-host.ts"() {
|
|
15530
16050
|
"use strict";
|
|
@@ -15536,7 +16056,7 @@ var init_claude_host = __esm({
|
|
|
15536
16056
|
init_pilot_tools();
|
|
15537
16057
|
init_node_launch();
|
|
15538
16058
|
init_packaged_runtime();
|
|
15539
|
-
|
|
16059
|
+
import_meta5 = {};
|
|
15540
16060
|
}
|
|
15541
16061
|
});
|
|
15542
16062
|
|
|
@@ -15939,16 +16459,15 @@ function parseIssuesJson(raw) {
|
|
|
15939
16459
|
}
|
|
15940
16460
|
return [];
|
|
15941
16461
|
}
|
|
15942
|
-
var import_node_fs39,
|
|
16462
|
+
var import_node_fs39, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
15943
16463
|
var init_claude = __esm({
|
|
15944
16464
|
"src/agents/claude.ts"() {
|
|
15945
16465
|
"use strict";
|
|
15946
16466
|
import_node_fs39 = require("fs");
|
|
15947
|
-
import_node_os16 = require("os");
|
|
15948
16467
|
init_run();
|
|
15949
16468
|
init_app_settings();
|
|
15950
16469
|
init_claude_mcp();
|
|
15951
|
-
|
|
16470
|
+
init_host();
|
|
15952
16471
|
init_error_detail();
|
|
15953
16472
|
init_message_parts();
|
|
15954
16473
|
init_injected_mcp();
|
|
@@ -16025,7 +16544,7 @@ var init_claude = __esm({
|
|
|
16025
16544
|
});
|
|
16026
16545
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
16027
16546
|
const chromeOn = claudeChromeEnabled();
|
|
16028
|
-
const userMcpEntries =
|
|
16547
|
+
const userMcpEntries = await proxyClaudeUserMcp(isOrchestrator, [thread.repoPath, thread.worktreePath]);
|
|
16029
16548
|
let allowedTools;
|
|
16030
16549
|
if (isOrchestrator) {
|
|
16031
16550
|
allowedTools = [
|
|
@@ -16327,7 +16846,7 @@ function unwrapCodexMcpResult(result) {
|
|
|
16327
16846
|
return String(result);
|
|
16328
16847
|
}
|
|
16329
16848
|
}
|
|
16330
|
-
function
|
|
16849
|
+
function asRecord5(value) {
|
|
16331
16850
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
16332
16851
|
return value;
|
|
16333
16852
|
}
|
|
@@ -16507,7 +17026,7 @@ var init_codex = __esm({
|
|
|
16507
17026
|
}
|
|
16508
17027
|
if (itemType === "mcp_tool_call" && item.id && item.server && item.tool) {
|
|
16509
17028
|
const name = `mcp__${item.server}__${item.tool}`;
|
|
16510
|
-
const input =
|
|
17029
|
+
const input = asRecord5(item.arguments);
|
|
16511
17030
|
const events = [
|
|
16512
17031
|
{ type: "tool_use", id: item.id, name, input }
|
|
16513
17032
|
];
|
|
@@ -16654,7 +17173,7 @@ function thisModuleFile() {
|
|
|
16654
17173
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
16655
17174
|
if (cjsDir) return (0, import_node_path43.join)(cjsDir, "cursor-sdk-resolve.js");
|
|
16656
17175
|
try {
|
|
16657
|
-
return (0, import_node_url3.fileURLToPath)(
|
|
17176
|
+
return (0, import_node_url3.fileURLToPath)(import_meta6.url);
|
|
16658
17177
|
} catch {
|
|
16659
17178
|
return (0, import_node_path43.join)(process.cwd(), "package.json");
|
|
16660
17179
|
}
|
|
@@ -16753,7 +17272,7 @@ function cursorSdkRipgrepCandidate(opts) {
|
|
|
16753
17272
|
const nested = (0, import_node_path43.join)(root, "node_modules", pkg, "bin", bin);
|
|
16754
17273
|
return (0, import_node_fs41.existsSync)(nested) ? nested : null;
|
|
16755
17274
|
}
|
|
16756
|
-
var import_node_fs41, import_node_module3, import_node_path43, import_node_url3,
|
|
17275
|
+
var import_node_fs41, import_node_module3, import_node_path43, import_node_url3, import_meta6, CURSOR_SDK_INSTALL_HINT;
|
|
16757
17276
|
var init_cursor_sdk_resolve = __esm({
|
|
16758
17277
|
"src/agents/cursor-sdk-resolve.ts"() {
|
|
16759
17278
|
"use strict";
|
|
@@ -16762,7 +17281,7 @@ var init_cursor_sdk_resolve = __esm({
|
|
|
16762
17281
|
import_node_path43 = require("path");
|
|
16763
17282
|
import_node_url3 = require("url");
|
|
16764
17283
|
init_path();
|
|
16765
|
-
|
|
17284
|
+
import_meta6 = {};
|
|
16766
17285
|
CURSOR_SDK_INSTALL_HINT = "Cursor SDK is not installed. Settings \u2192 Agents \u2192 Cursor \u2192 Install (`npm i -g @cursor/sdk`). Sideboard does not ship the SDK \u2014 update it anytime without a new Sideboard build.";
|
|
16767
17286
|
}
|
|
16768
17287
|
});
|
|
@@ -16812,20 +17331,20 @@ function turnCostUsdFromCursorUsage(before, after) {
|
|
|
16812
17331
|
if (!(delta >= 0) || !Number.isFinite(delta)) return void 0;
|
|
16813
17332
|
return delta / 100;
|
|
16814
17333
|
}
|
|
16815
|
-
function
|
|
17334
|
+
function asRecord6(value) {
|
|
16816
17335
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
16817
17336
|
return value;
|
|
16818
17337
|
}
|
|
16819
17338
|
return void 0;
|
|
16820
17339
|
}
|
|
16821
17340
|
function normalizeCursorToolCall(name, args) {
|
|
16822
|
-
const raw =
|
|
17341
|
+
const raw = asRecord6(args);
|
|
16823
17342
|
const toolName = typeof raw?.toolName === "string" && raw.toolName.trim() ? raw.toolName.trim() : null;
|
|
16824
|
-
const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" ||
|
|
17343
|
+
const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord6(raw?.args) != null);
|
|
16825
17344
|
if (looksLikeMcp && toolName) {
|
|
16826
17345
|
const providerRaw = typeof raw.providerIdentifier === "string" && raw.providerIdentifier.trim() ? raw.providerIdentifier.trim() : "sideboard";
|
|
16827
17346
|
const provider = providerRaw.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
16828
|
-
const nested =
|
|
17347
|
+
const nested = asRecord6(raw.args);
|
|
16829
17348
|
return {
|
|
16830
17349
|
name: `mcp__${provider}__${toolName}`,
|
|
16831
17350
|
input: nested ?? { toolName }
|
|
@@ -16836,7 +17355,7 @@ function normalizeCursorToolCall(name, args) {
|
|
|
16836
17355
|
function unwrapCursorToolResult(result) {
|
|
16837
17356
|
if (result == null) return void 0;
|
|
16838
17357
|
if (typeof result === "string") return result;
|
|
16839
|
-
const rec =
|
|
17358
|
+
const rec = asRecord6(result);
|
|
16840
17359
|
if (!rec) {
|
|
16841
17360
|
try {
|
|
16842
17361
|
return JSON.stringify(result);
|
|
@@ -16847,18 +17366,18 @@ function unwrapCursorToolResult(result) {
|
|
|
16847
17366
|
const collectTexts = (items) => {
|
|
16848
17367
|
const texts = [];
|
|
16849
17368
|
for (const item of items) {
|
|
16850
|
-
const row2 =
|
|
17369
|
+
const row2 = asRecord6(item);
|
|
16851
17370
|
if (!row2) continue;
|
|
16852
17371
|
if (typeof row2.text === "string") {
|
|
16853
17372
|
texts.push(row2.text);
|
|
16854
17373
|
continue;
|
|
16855
17374
|
}
|
|
16856
|
-
const nested =
|
|
17375
|
+
const nested = asRecord6(row2.text);
|
|
16857
17376
|
if (typeof nested?.text === "string") texts.push(nested.text);
|
|
16858
17377
|
}
|
|
16859
17378
|
return texts;
|
|
16860
17379
|
};
|
|
16861
|
-
const value =
|
|
17380
|
+
const value = asRecord6(rec.value);
|
|
16862
17381
|
if (value && Array.isArray(value.content)) {
|
|
16863
17382
|
const texts = collectTexts(value.content);
|
|
16864
17383
|
if (texts.length) return texts.join("\n");
|
|
@@ -16875,10 +17394,10 @@ function unwrapCursorToolResult(result) {
|
|
|
16875
17394
|
}
|
|
16876
17395
|
function cursorToolResultIsError(status, result) {
|
|
16877
17396
|
if (status === "error") return true;
|
|
16878
|
-
const rec =
|
|
17397
|
+
const rec = asRecord6(result);
|
|
16879
17398
|
if (!rec) return false;
|
|
16880
17399
|
if (rec.status === "error") return true;
|
|
16881
|
-
const value =
|
|
17400
|
+
const value = asRecord6(rec.value);
|
|
16882
17401
|
return value?.isError === true;
|
|
16883
17402
|
}
|
|
16884
17403
|
function cursorSdkMessageToEvents(msg) {
|
|
@@ -17097,7 +17616,7 @@ function entryDir2() {
|
|
|
17097
17616
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
17098
17617
|
if (cjsDir) return cjsDir;
|
|
17099
17618
|
try {
|
|
17100
|
-
return (0, import_node_path45.dirname)((0, import_node_url4.fileURLToPath)(
|
|
17619
|
+
return (0, import_node_path45.dirname)((0, import_node_url4.fileURLToPath)(import_meta7.url));
|
|
17101
17620
|
} catch {
|
|
17102
17621
|
try {
|
|
17103
17622
|
const req = (0, import_node_module5.createRequire)(process.cwd() + "/");
|
|
@@ -17126,7 +17645,7 @@ function cursorRunnerPath() {
|
|
|
17126
17645
|
}
|
|
17127
17646
|
return candidates[0];
|
|
17128
17647
|
}
|
|
17129
|
-
var import_node_fs43, import_node_module5, import_node_path45, import_node_url4,
|
|
17648
|
+
var import_node_fs43, import_node_module5, import_node_path45, import_node_url4, import_meta7, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
17130
17649
|
var init_cursor = __esm({
|
|
17131
17650
|
"src/agents/cursor.ts"() {
|
|
17132
17651
|
"use strict";
|
|
@@ -17146,7 +17665,7 @@ var init_cursor = __esm({
|
|
|
17146
17665
|
init_packaged_runtime();
|
|
17147
17666
|
init_turn_input();
|
|
17148
17667
|
init_cursor_events();
|
|
17149
|
-
|
|
17668
|
+
import_meta7 = {};
|
|
17150
17669
|
FALLBACK_CURSOR_MODELS = [
|
|
17151
17670
|
{ id: "default", displayName: "Auto" },
|
|
17152
17671
|
{ id: "composer-2.5", displayName: "Composer 2.5" },
|
|
@@ -17420,7 +17939,7 @@ var init_opencode_host = __esm({
|
|
|
17420
17939
|
});
|
|
17421
17940
|
|
|
17422
17941
|
// src/agents/opencode.ts
|
|
17423
|
-
function
|
|
17942
|
+
function asRecord7(value) {
|
|
17424
17943
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
17425
17944
|
return value;
|
|
17426
17945
|
}
|
|
@@ -17616,7 +18135,7 @@ var init_opencode = __esm({
|
|
|
17616
18135
|
const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
|
|
17617
18136
|
const state = part?.state;
|
|
17618
18137
|
const input = (state?.input && typeof state.input === "object" ? state.input : void 0) ?? part?.input ?? obj.input;
|
|
17619
|
-
const metadata =
|
|
18138
|
+
const metadata = asRecord7(state?.metadata);
|
|
17620
18139
|
const id = opencodeToolId(
|
|
17621
18140
|
name,
|
|
17622
18141
|
part?.callID ?? part?.id ?? obj.id,
|
|
@@ -17651,7 +18170,7 @@ var init_opencode = __esm({
|
|
|
17651
18170
|
}
|
|
17652
18171
|
if (obj.type === "subtask_event") {
|
|
17653
18172
|
const parentId = str4(obj.childSessionID) ?? str4(obj.childSessionId);
|
|
17654
|
-
const part =
|
|
18173
|
+
const part = asRecord7(obj.part);
|
|
17655
18174
|
if (!parentId || !part) return null;
|
|
17656
18175
|
if (part.type === "text" && str4(part.text)) {
|
|
17657
18176
|
return withTaskParent(
|
|
@@ -17662,8 +18181,8 @@ var init_opencode = __esm({
|
|
|
17662
18181
|
if (part.type === "tool" || str4(part.tool)) {
|
|
17663
18182
|
const name = str4(part.tool) ?? str4(part.name) ?? "tool";
|
|
17664
18183
|
const id = str4(part.callID) ?? str4(part.id) ?? `${parentId}-${name}`;
|
|
17665
|
-
const state =
|
|
17666
|
-
const input =
|
|
18184
|
+
const state = asRecord7(part.state);
|
|
18185
|
+
const input = asRecord7(state?.input) ?? asRecord7(part.input);
|
|
17667
18186
|
const nested = [
|
|
17668
18187
|
withEventParentId({ type: "tool_use", id, name, input }, parentId)
|
|
17669
18188
|
];
|
|
@@ -20081,7 +20600,7 @@ function forkMessageSlice(from, throughIndex) {
|
|
|
20081
20600
|
function buildForkTranscriptAttachment(baseTitle, messages) {
|
|
20082
20601
|
const title = baseTitle || "Chat";
|
|
20083
20602
|
return {
|
|
20084
|
-
id: (0,
|
|
20603
|
+
id: (0, import_node_crypto13.randomUUID)(),
|
|
20085
20604
|
name: `Transcript of ${title}.md`,
|
|
20086
20605
|
kind: "transcript",
|
|
20087
20606
|
content: formatTranscriptMarkdown(title, messages)
|
|
@@ -20140,11 +20659,11 @@ function forkChatTab(input) {
|
|
|
20140
20659
|
}
|
|
20141
20660
|
return tab;
|
|
20142
20661
|
}
|
|
20143
|
-
var
|
|
20662
|
+
var import_node_crypto13;
|
|
20144
20663
|
var init_chat_tabs = __esm({
|
|
20145
20664
|
"src/threads/chat-tabs.ts"() {
|
|
20146
20665
|
"use strict";
|
|
20147
|
-
|
|
20666
|
+
import_node_crypto13 = require("crypto");
|
|
20148
20667
|
init_context_compact();
|
|
20149
20668
|
init_teams();
|
|
20150
20669
|
init_worktree_labels();
|
|
@@ -20443,7 +20962,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
20443
20962
|
const path2 = opts?.path ?? REVIEW_SKILL_PATH;
|
|
20444
20963
|
const name = opts?.name ?? (path2 === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path2 === REPO_REVIEW_PATH || path2 === CONTEXT_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
|
|
20445
20964
|
return {
|
|
20446
|
-
id: (0,
|
|
20965
|
+
id: (0, import_node_crypto14.randomUUID)(),
|
|
20447
20966
|
name,
|
|
20448
20967
|
kind: "file",
|
|
20449
20968
|
path: path2,
|
|
@@ -20499,11 +21018,11 @@ async function requestReview(threadRef, send3) {
|
|
|
20499
21018
|
const started = await send3(tab.id, REVIEW_REQUEST_PREFILL);
|
|
20500
21019
|
return { tab: started, from };
|
|
20501
21020
|
}
|
|
20502
|
-
var
|
|
21021
|
+
var import_node_crypto14, import_node_fs49, import_node_path50, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
|
|
20503
21022
|
var init_request_review = __esm({
|
|
20504
21023
|
"src/review/request-review.ts"() {
|
|
20505
21024
|
"use strict";
|
|
20506
|
-
|
|
21025
|
+
import_node_crypto14 = require("crypto");
|
|
20507
21026
|
import_node_fs49 = require("fs");
|
|
20508
21027
|
import_node_path50 = require("path");
|
|
20509
21028
|
init_global_workspace();
|
|
@@ -22052,8 +22571,28 @@ var init_clone_repo = __esm({
|
|
|
22052
22571
|
}
|
|
22053
22572
|
});
|
|
22054
22573
|
|
|
22574
|
+
// src/mcp-ui/model-context.ts
|
|
22575
|
+
function stashMcpAppModelContext(threadId, text7) {
|
|
22576
|
+
const body = text7.trim().slice(0, 8e3);
|
|
22577
|
+
if (!body) return;
|
|
22578
|
+
updateThread(threadId, { mcpAppModelContext: body });
|
|
22579
|
+
}
|
|
22580
|
+
function takeMcpAppModelContext(threadId) {
|
|
22581
|
+
const thread = readThread(threadId);
|
|
22582
|
+
const text7 = thread?.mcpAppModelContext?.trim();
|
|
22583
|
+
if (!text7) return void 0;
|
|
22584
|
+
updateThread(threadId, { mcpAppModelContext: null });
|
|
22585
|
+
return text7;
|
|
22586
|
+
}
|
|
22587
|
+
var init_model_context = __esm({
|
|
22588
|
+
"src/mcp-ui/model-context.ts"() {
|
|
22589
|
+
"use strict";
|
|
22590
|
+
init_thread_store();
|
|
22591
|
+
}
|
|
22592
|
+
});
|
|
22593
|
+
|
|
22055
22594
|
// src/plan/plan-present.ts
|
|
22056
|
-
function
|
|
22595
|
+
function asRecord8(v) {
|
|
22057
22596
|
return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
22058
22597
|
}
|
|
22059
22598
|
function isPresentPlanToolName(name) {
|
|
@@ -22072,7 +22611,7 @@ function extractPresentedPlan(parts) {
|
|
|
22072
22611
|
for (let i = parts.length - 1; i >= 0; i--) {
|
|
22073
22612
|
const p = parts[i];
|
|
22074
22613
|
if (p.type !== "tool" || !isPresentPlanToolName(p.name)) continue;
|
|
22075
|
-
const input =
|
|
22614
|
+
const input = asRecord8(p.input) ?? {};
|
|
22076
22615
|
const content = typeof input.content === "string" ? input.content : typeof input.plan === "string" ? input.plan : typeof input.markdown === "string" ? input.markdown : "";
|
|
22077
22616
|
if (!content.trim()) continue;
|
|
22078
22617
|
const title = typeof input.title === "string" && input.title.trim() ? input.title.trim() : "Plan";
|
|
@@ -22527,7 +23066,7 @@ function isUnclaimedSteerRequest(req) {
|
|
|
22527
23066
|
}
|
|
22528
23067
|
function nextSteerRequest(existing) {
|
|
22529
23068
|
if (existing?.requestId && !existing.claimedAt) return existing;
|
|
22530
|
-
return { requestId: (0,
|
|
23069
|
+
return { requestId: (0, import_node_crypto15.randomUUID)(), requestedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
22531
23070
|
}
|
|
22532
23071
|
function claimSteerRequest(threadId) {
|
|
22533
23072
|
const pending = readThread(threadId)?.steerRequest;
|
|
@@ -22536,11 +23075,11 @@ function claimSteerRequest(threadId) {
|
|
|
22536
23075
|
steerRequest: { ...pending, claimedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
22537
23076
|
});
|
|
22538
23077
|
}
|
|
22539
|
-
var
|
|
23078
|
+
var import_node_crypto15;
|
|
22540
23079
|
var init_steer_request = __esm({
|
|
22541
23080
|
"src/orchestrator/steer-request.ts"() {
|
|
22542
23081
|
"use strict";
|
|
22543
|
-
|
|
23082
|
+
import_node_crypto15 = require("crypto");
|
|
22544
23083
|
init_thread_store();
|
|
22545
23084
|
}
|
|
22546
23085
|
});
|
|
@@ -22785,8 +23324,8 @@ function resolveAbleTimeOAuthHost(requested, saved) {
|
|
|
22785
23324
|
return fromSaved || void 0;
|
|
22786
23325
|
}
|
|
22787
23326
|
function createAbleTimePkce() {
|
|
22788
|
-
const verifier = (0,
|
|
22789
|
-
const challenge = (0,
|
|
23327
|
+
const verifier = (0, import_node_crypto16.randomBytes)(32).toString("base64url");
|
|
23328
|
+
const challenge = (0, import_node_crypto16.createHash)("sha256").update(verifier).digest("base64url");
|
|
22790
23329
|
return { verifier, challenge };
|
|
22791
23330
|
}
|
|
22792
23331
|
function ableTimeOAuthAuthorizeUrl(clientId, state, codeChallenge, host) {
|
|
@@ -22891,7 +23430,7 @@ async function startAbleTimeOAuth(opts) {
|
|
|
22891
23430
|
opts?.host,
|
|
22892
23431
|
loadAppSettings().integrations.abletimeHost
|
|
22893
23432
|
);
|
|
22894
|
-
const state = (0,
|
|
23433
|
+
const state = (0, import_node_crypto16.randomBytes)(16).toString("hex");
|
|
22895
23434
|
const pkce = createAbleTimePkce();
|
|
22896
23435
|
const authorizeUrl = ableTimeOAuthAuthorizeUrl(clientId, state, pkce.challenge, host);
|
|
22897
23436
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
@@ -22904,7 +23443,7 @@ async function startAbleTimeOAuth(opts) {
|
|
|
22904
23443
|
if (err) reject(err);
|
|
22905
23444
|
else resolve3(value);
|
|
22906
23445
|
};
|
|
22907
|
-
const server = (0,
|
|
23446
|
+
const server = (0, import_node_http2.createServer)((req, res) => {
|
|
22908
23447
|
try {
|
|
22909
23448
|
const url = new URL(req.url || "/", `http://127.0.0.1:${ABLETIME_OAUTH_PORT}`);
|
|
22910
23449
|
if (url.pathname !== "/callback") {
|
|
@@ -22991,12 +23530,12 @@ async function startAbleTimeOAuth(opts) {
|
|
|
22991
23530
|
return loadAppSettings();
|
|
22992
23531
|
}
|
|
22993
23532
|
}
|
|
22994
|
-
var
|
|
23533
|
+
var import_node_crypto16, import_node_http2, ABLETIME_OAUTH_CALLBACK_PATH, ABLETIME_OAUTH_PORT, ABLETIME_OAUTH_LOCAL_CALLBACK, ABLETIME_OAUTH_REDIRECT, BOUNCE_QUERY_KEYS, BAKED_ABLETIME_OAUTH_CLIENT_ID, ABLETIME_OAUTH_RESOURCE, REFRESH_SKEW_MS2, refreshInFlight2, ABLETIME_OAUTH_CANCELLED, AbleTimeOAuthCancelledError;
|
|
22995
23534
|
var init_abletime_oauth = __esm({
|
|
22996
23535
|
"src/integrations/abletime-oauth.ts"() {
|
|
22997
23536
|
"use strict";
|
|
22998
|
-
|
|
22999
|
-
|
|
23537
|
+
import_node_crypto16 = require("crypto");
|
|
23538
|
+
import_node_http2 = require("http");
|
|
23000
23539
|
init_fetch();
|
|
23001
23540
|
init_app_settings();
|
|
23002
23541
|
init_abletime_mcp();
|
|
@@ -23029,7 +23568,7 @@ __export(abletime_rest_exports, {
|
|
|
23029
23568
|
looksLikeAbleTimeUlid: () => looksLikeAbleTimeUlid,
|
|
23030
23569
|
textFromAbleTimeDoc: () => textFromAbleTimeDoc
|
|
23031
23570
|
});
|
|
23032
|
-
function
|
|
23571
|
+
function asRecord9(value) {
|
|
23033
23572
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
23034
23573
|
}
|
|
23035
23574
|
function asString(value) {
|
|
@@ -23037,7 +23576,7 @@ function asString(value) {
|
|
|
23037
23576
|
}
|
|
23038
23577
|
function asList(value) {
|
|
23039
23578
|
if (Array.isArray(value)) return value;
|
|
23040
|
-
const record =
|
|
23579
|
+
const record = asRecord9(value);
|
|
23041
23580
|
if (!record) return [];
|
|
23042
23581
|
for (const key of ["data", "tasks", "projects", "users", "items", "results"]) {
|
|
23043
23582
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -23054,12 +23593,12 @@ function ableTimeDocFromText(text7) {
|
|
|
23054
23593
|
}
|
|
23055
23594
|
function textFromAbleTimeDoc(value) {
|
|
23056
23595
|
if (typeof value === "string") return value.trim();
|
|
23057
|
-
const record =
|
|
23596
|
+
const record = asRecord9(value);
|
|
23058
23597
|
if (!record) return "";
|
|
23059
23598
|
if (typeof record.text === "string" && record.text.trim()) return record.text.trim();
|
|
23060
23599
|
const chunks = [];
|
|
23061
23600
|
const walk = (node) => {
|
|
23062
|
-
const rec =
|
|
23601
|
+
const rec = asRecord9(node);
|
|
23063
23602
|
if (!rec) return;
|
|
23064
23603
|
if (typeof rec.text === "string" && rec.text) chunks.push(rec.text);
|
|
23065
23604
|
if (Array.isArray(rec.content)) rec.content.forEach(walk);
|
|
@@ -23121,7 +23660,7 @@ async function restPages(path2, opts, maxPages = 20) {
|
|
|
23121
23660
|
query: { ...opts.query, ...cursor ? { cursor } : {} }
|
|
23122
23661
|
});
|
|
23123
23662
|
items.push(...asList(raw));
|
|
23124
|
-
const page =
|
|
23663
|
+
const page = asRecord9(asRecord9(raw)?.page);
|
|
23125
23664
|
const next = page ? asString(page.nextCursor) : "";
|
|
23126
23665
|
if (!next) break;
|
|
23127
23666
|
cursor = next;
|
|
@@ -23129,7 +23668,7 @@ async function restPages(path2, opts, maxPages = 20) {
|
|
|
23129
23668
|
return items;
|
|
23130
23669
|
}
|
|
23131
23670
|
function userDisplayName(raw) {
|
|
23132
|
-
const rec =
|
|
23671
|
+
const rec = asRecord9(raw);
|
|
23133
23672
|
if (!rec) return null;
|
|
23134
23673
|
const id = asString(rec.userId) || asString(rec.id);
|
|
23135
23674
|
const name = [asString(rec.firstName), asString(rec.lastName)].filter(Boolean).join(" ") || asString(rec.username) || asString(rec.email) || asString(rec.name);
|
|
@@ -23137,7 +23676,7 @@ function userDisplayName(raw) {
|
|
|
23137
23676
|
return { id: id || void 0, name };
|
|
23138
23677
|
}
|
|
23139
23678
|
function restTaskToRaw(raw, users) {
|
|
23140
|
-
const rec =
|
|
23679
|
+
const rec = asRecord9(raw);
|
|
23141
23680
|
if (!rec) return null;
|
|
23142
23681
|
const id = asString(rec.timeflowTaskId) || asString(rec.taskId) || asString(rec.id);
|
|
23143
23682
|
const identifier = asString(rec.taskRef) || asString(rec.reference) || id;
|
|
@@ -23145,7 +23684,7 @@ function restTaskToRaw(raw, users) {
|
|
|
23145
23684
|
if (!id && !identifier && !title) return null;
|
|
23146
23685
|
const assignee = users.get(asString(rec.assignedUserId));
|
|
23147
23686
|
const comments = asList(rec.comments).map((item) => {
|
|
23148
|
-
const comment =
|
|
23687
|
+
const comment = asRecord9(item) ?? {};
|
|
23149
23688
|
const user = userDisplayName(comment);
|
|
23150
23689
|
return {
|
|
23151
23690
|
id: asString(comment.commentId) || asString(comment.id),
|
|
@@ -23175,13 +23714,13 @@ function restTaskToRaw(raw, users) {
|
|
|
23175
23714
|
};
|
|
23176
23715
|
}
|
|
23177
23716
|
function restProjectToRaw(raw) {
|
|
23178
|
-
const rec =
|
|
23717
|
+
const rec = asRecord9(raw);
|
|
23179
23718
|
if (!rec) return null;
|
|
23180
23719
|
const id = asString(rec.projectId) || asString(rec.id);
|
|
23181
23720
|
const name = asString(rec.projectName) || asString(rec.name);
|
|
23182
23721
|
if (!id && !name) return null;
|
|
23183
23722
|
const categories = asList(rec.categories).map((item) => {
|
|
23184
|
-
const cat =
|
|
23723
|
+
const cat = asRecord9(item) ?? {};
|
|
23185
23724
|
return {
|
|
23186
23725
|
id: asString(cat.projectCategoryId) || asString(cat.categoryId) || asString(cat.id),
|
|
23187
23726
|
name: asString(cat.categoryName) || asString(cat.name)
|
|
@@ -23193,7 +23732,7 @@ async function listUsers(opts) {
|
|
|
23193
23732
|
const users = /* @__PURE__ */ new Map();
|
|
23194
23733
|
for (const item of await restPages("/users", opts).catch(() => [])) {
|
|
23195
23734
|
const user = userDisplayName(item);
|
|
23196
|
-
const rec =
|
|
23735
|
+
const rec = asRecord9(item);
|
|
23197
23736
|
const id = user?.id || (rec ? asString(rec.userId) : "");
|
|
23198
23737
|
if (user && id) users.set(id, user);
|
|
23199
23738
|
}
|
|
@@ -23319,10 +23858,10 @@ async function callAbleTimeRestTool(name, args = {}, opts) {
|
|
|
23319
23858
|
if (!project) throw new Error("AbleTime has no projects to create a task in");
|
|
23320
23859
|
const categories = asList(project.categories);
|
|
23321
23860
|
const wantedCategory = firstStringArg(args, ["category_id", "categoryId", "category"]);
|
|
23322
|
-
const category = categories.map((item) =>
|
|
23861
|
+
const category = categories.map((item) => asRecord9(item)).find((item) => {
|
|
23323
23862
|
if (!item || !wantedCategory) return false;
|
|
23324
23863
|
return asString(item.id).toLowerCase() === wantedCategory.toLowerCase() || asString(item.name).toLowerCase() === wantedCategory.toLowerCase();
|
|
23325
|
-
}) ??
|
|
23864
|
+
}) ?? asRecord9(categories[0]);
|
|
23326
23865
|
const parentArg = firstStringArg(args, ["parent", "parent_id", "parentId", "related_task_id"]);
|
|
23327
23866
|
const parentTaskId = parentArg ? await resolveRestParentTaskId(parentArg, requestOpts) : void 0;
|
|
23328
23867
|
const created = await abletimeRestRequest("/tasks", {
|
|
@@ -23336,7 +23875,7 @@ async function callAbleTimeRestTool(name, args = {}, opts) {
|
|
|
23336
23875
|
}
|
|
23337
23876
|
});
|
|
23338
23877
|
const state = firstStringArg(args, ["state"]);
|
|
23339
|
-
const createdId = asString(
|
|
23878
|
+
const createdId = asString(asRecord9(created)?.timeflowTaskId);
|
|
23340
23879
|
const description = asString(args.description);
|
|
23341
23880
|
if (createdId && description) {
|
|
23342
23881
|
await abletimeRestRequest(`/tasks/${encodeURIComponent(createdId)}`, {
|
|
@@ -23409,7 +23948,7 @@ async function callAbleTimeRestTool(name, args = {}, opts) {
|
|
|
23409
23948
|
method: "POST",
|
|
23410
23949
|
body: { content: ableTimeDocFromText(body) }
|
|
23411
23950
|
});
|
|
23412
|
-
const rec =
|
|
23951
|
+
const rec = asRecord9(created) ?? {};
|
|
23413
23952
|
return {
|
|
23414
23953
|
id: asString(rec.commentId) || void 0,
|
|
23415
23954
|
body: textFromAbleTimeDoc(rec.content) || body
|
|
@@ -23504,7 +24043,7 @@ function rewriteAbleTimeError(message) {
|
|
|
23504
24043
|
}
|
|
23505
24044
|
return message;
|
|
23506
24045
|
}
|
|
23507
|
-
function
|
|
24046
|
+
function asRecord10(value) {
|
|
23508
24047
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
23509
24048
|
}
|
|
23510
24049
|
function parseSseJson(body) {
|
|
@@ -23526,12 +24065,12 @@ function parseSseJson(body) {
|
|
|
23526
24065
|
}
|
|
23527
24066
|
}
|
|
23528
24067
|
function unwrapToolResult(result) {
|
|
23529
|
-
const record =
|
|
24068
|
+
const record = asRecord10(result);
|
|
23530
24069
|
if (!record) return result;
|
|
23531
24070
|
const content = record.content;
|
|
23532
24071
|
if (Array.isArray(content)) {
|
|
23533
24072
|
const texts = content.map((part) => {
|
|
23534
|
-
const item =
|
|
24073
|
+
const item = asRecord10(part);
|
|
23535
24074
|
if (!item) return "";
|
|
23536
24075
|
return typeof item.text === "string" ? item.text : "";
|
|
23537
24076
|
}).filter(Boolean);
|
|
@@ -23553,7 +24092,7 @@ function unwrapToolResult(result) {
|
|
|
23553
24092
|
return result;
|
|
23554
24093
|
}
|
|
23555
24094
|
function textsFromUnknown(value) {
|
|
23556
|
-
const record =
|
|
24095
|
+
const record = asRecord10(value);
|
|
23557
24096
|
if (!record) return "";
|
|
23558
24097
|
if (typeof record.message === "string") return record.message;
|
|
23559
24098
|
if (typeof record.error === "string") return record.error;
|
|
@@ -23600,7 +24139,7 @@ async function abletimeMcpRequest(method, params, opts) {
|
|
|
23600
24139
|
return parseSseJson(body);
|
|
23601
24140
|
}
|
|
23602
24141
|
})();
|
|
23603
|
-
const rpc =
|
|
24142
|
+
const rpc = asRecord10(parsed);
|
|
23604
24143
|
if (rpc?.error) {
|
|
23605
24144
|
const detail = typeof rpc.error.message === "string" && rpc.error.message.trim() ? rpc.error.message : `AbleTime MCP error ${rpc.error.code ?? ""}`.trim();
|
|
23606
24145
|
throw new Error(rewriteAbleTimeError(detail));
|
|
@@ -23755,7 +24294,7 @@ function uniqueAttachmentFileName(dir, originalName) {
|
|
|
23755
24294
|
const candidate = `${stem}-${i}${ext}`;
|
|
23756
24295
|
if (!(0, import_node_fs55.existsSync)((0, import_node_path56.join)(dir, candidate))) return candidate;
|
|
23757
24296
|
}
|
|
23758
|
-
return `${stem}-${(0,
|
|
24297
|
+
return `${stem}-${(0, import_node_crypto17.randomUUID)()}${ext}`;
|
|
23759
24298
|
}
|
|
23760
24299
|
function extractHttpUrls(markdown) {
|
|
23761
24300
|
const text7 = markdown ?? "";
|
|
@@ -23861,13 +24400,13 @@ async function downloadAuthenticatedFile(opts) {
|
|
|
23861
24400
|
...contentType ? { contentType } : {}
|
|
23862
24401
|
};
|
|
23863
24402
|
}
|
|
23864
|
-
var import_node_fs55, import_node_path56,
|
|
24403
|
+
var import_node_fs55, import_node_path56, import_node_crypto17, ISSUE_ATTACHMENT_MAX_BYTES, MARKDOWN_IMAGE_RE, MARKDOWN_LINK_RE, HTML_SRC_RE, BARE_URL_RE, EXT_BY_MIME;
|
|
23865
24404
|
var init_issue_attachments = __esm({
|
|
23866
24405
|
"src/integrations/issue-attachments.ts"() {
|
|
23867
24406
|
"use strict";
|
|
23868
24407
|
import_node_fs55 = require("fs");
|
|
23869
24408
|
import_node_path56 = require("path");
|
|
23870
|
-
|
|
24409
|
+
import_node_crypto17 = require("crypto");
|
|
23871
24410
|
init_fetch();
|
|
23872
24411
|
init_workspace_scratch();
|
|
23873
24412
|
ISSUE_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
|
|
@@ -23892,7 +24431,7 @@ var init_issue_attachments = __esm({
|
|
|
23892
24431
|
});
|
|
23893
24432
|
|
|
23894
24433
|
// src/integrations/abletime-attachments.ts
|
|
23895
|
-
function
|
|
24434
|
+
function asRecord11(value) {
|
|
23896
24435
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
23897
24436
|
}
|
|
23898
24437
|
function asString2(value) {
|
|
@@ -23900,7 +24439,7 @@ function asString2(value) {
|
|
|
23900
24439
|
}
|
|
23901
24440
|
function asList2(value) {
|
|
23902
24441
|
if (Array.isArray(value)) return value;
|
|
23903
|
-
const record =
|
|
24442
|
+
const record = asRecord11(value);
|
|
23904
24443
|
if (!record) return [];
|
|
23905
24444
|
for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
|
|
23906
24445
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -23919,9 +24458,9 @@ function filesFromAbleTimeDoc(value) {
|
|
|
23919
24458
|
const out = [];
|
|
23920
24459
|
const seen = /* @__PURE__ */ new Set();
|
|
23921
24460
|
const walk = (node) => {
|
|
23922
|
-
const rec =
|
|
24461
|
+
const rec = asRecord11(node);
|
|
23923
24462
|
if (!rec) return;
|
|
23924
|
-
const attrs =
|
|
24463
|
+
const attrs = asRecord11(rec.attrs) ?? rec;
|
|
23925
24464
|
const url = asString2(attrs.src) || asString2(attrs.href) || asString2(attrs.url) || asString2(attrs.fileUrl) || asString2(attrs.downloadUrl);
|
|
23926
24465
|
if (url && !seen.has(url)) {
|
|
23927
24466
|
seen.add(url);
|
|
@@ -23939,7 +24478,7 @@ function filesFromAbleTimeDoc(value) {
|
|
|
23939
24478
|
function listedAbleTimeFiles(raw) {
|
|
23940
24479
|
const out = [];
|
|
23941
24480
|
for (const item of asList2(raw)) {
|
|
23942
|
-
const rec =
|
|
24481
|
+
const rec = asRecord11(item);
|
|
23943
24482
|
if (!rec) continue;
|
|
23944
24483
|
const url = firstString(rec, ["url", "href", "src", "fileUrl", "downloadUrl", "permalink"]);
|
|
23945
24484
|
if (!url) continue;
|
|
@@ -23959,7 +24498,7 @@ function mapAbleTimeAttachments(record) {
|
|
|
23959
24498
|
...filesFromAbleTimeDoc(record.description),
|
|
23960
24499
|
...filesFromAbleTimeDoc(record.content),
|
|
23961
24500
|
...asList2(record.comments).flatMap((item) => {
|
|
23962
|
-
const rec =
|
|
24501
|
+
const rec = asRecord11(item);
|
|
23963
24502
|
return rec ? filesFromAbleTimeDoc(rec.content ?? rec.body) : [];
|
|
23964
24503
|
})
|
|
23965
24504
|
].map((file) => ({
|
|
@@ -24001,7 +24540,7 @@ async function resolveAbleTimeAttachmentUrl(id, opts) {
|
|
|
24001
24540
|
const json = await res.json().catch(() => null);
|
|
24002
24541
|
const rec = json && typeof json === "object" && !Array.isArray(json) ? json.data && typeof json.data === "object" ? json.data : json : null;
|
|
24003
24542
|
if (!rec) continue;
|
|
24004
|
-
const url = firstString(rec, ["url", "href", "src", "fileUrl", "downloadUrl"]) || firstString(
|
|
24543
|
+
const url = firstString(rec, ["url", "href", "src", "fileUrl", "downloadUrl"]) || firstString(asRecord11(rec.file), ["url", "href"]);
|
|
24005
24544
|
if (url) {
|
|
24006
24545
|
return {
|
|
24007
24546
|
url,
|
|
@@ -24043,7 +24582,7 @@ var init_abletime_attachments = __esm({
|
|
|
24043
24582
|
});
|
|
24044
24583
|
|
|
24045
24584
|
// src/integrations/abletime-projects.ts
|
|
24046
|
-
function
|
|
24585
|
+
function asRecord12(value) {
|
|
24047
24586
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
24048
24587
|
}
|
|
24049
24588
|
function firstString2(record, keys) {
|
|
@@ -24056,7 +24595,7 @@ function firstString2(record, keys) {
|
|
|
24056
24595
|
}
|
|
24057
24596
|
function asList3(value) {
|
|
24058
24597
|
if (Array.isArray(value)) return value;
|
|
24059
|
-
const record =
|
|
24598
|
+
const record = asRecord12(value);
|
|
24060
24599
|
if (!record) return [];
|
|
24061
24600
|
for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
|
|
24062
24601
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -24064,7 +24603,7 @@ function asList3(value) {
|
|
|
24064
24603
|
return [];
|
|
24065
24604
|
}
|
|
24066
24605
|
function ableTimeProjectFields(nested) {
|
|
24067
|
-
const projectRecord =
|
|
24606
|
+
const projectRecord = asRecord12(nested.project);
|
|
24068
24607
|
const projectId = firstString2(nested, ["project_id", "projectId"]) || firstString2(projectRecord, ["id"]) || void 0;
|
|
24069
24608
|
const projectName = firstString2(nested, ["project_name", "projectName"]) || firstString2(projectRecord, ["name", "title"]) || void 0;
|
|
24070
24609
|
if (!projectId && !projectName) return {};
|
|
@@ -24077,13 +24616,13 @@ function ableTimeProjectFields(nested) {
|
|
|
24077
24616
|
};
|
|
24078
24617
|
}
|
|
24079
24618
|
function mapAbleTimeProject(raw) {
|
|
24080
|
-
const record =
|
|
24619
|
+
const record = asRecord12(raw);
|
|
24081
24620
|
if (!record) return null;
|
|
24082
24621
|
const id = firstString2(record, ["id", "project_id", "projectId"]);
|
|
24083
24622
|
const name = firstString2(record, ["name", "title", "projectName"]);
|
|
24084
24623
|
if (!id && !name) return null;
|
|
24085
24624
|
const categories = asList3(record.categories ?? record.category).map((item) => {
|
|
24086
|
-
const rec =
|
|
24625
|
+
const rec = asRecord12(item);
|
|
24087
24626
|
if (!rec) return null;
|
|
24088
24627
|
const categoryId = firstString2(rec, ["id", "category_id", "projectCategoryId", "categoryId"]);
|
|
24089
24628
|
const categoryName = firstString2(rec, ["name", "title", "categoryName"]);
|
|
@@ -24119,7 +24658,7 @@ __export(abletime_exports, {
|
|
|
24119
24658
|
updateAbleTimeTask: () => updateAbleTimeTask,
|
|
24120
24659
|
verifyAbleTimeConnection: () => verifyAbleTimeConnection
|
|
24121
24660
|
});
|
|
24122
|
-
function
|
|
24661
|
+
function asRecord13(value) {
|
|
24123
24662
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
24124
24663
|
}
|
|
24125
24664
|
function asString3(value) {
|
|
@@ -24136,14 +24675,14 @@ function firstString3(record, keys) {
|
|
|
24136
24675
|
function firstRecord(record, keys) {
|
|
24137
24676
|
if (!record) return null;
|
|
24138
24677
|
for (const key of keys) {
|
|
24139
|
-
const value =
|
|
24678
|
+
const value = asRecord13(record[key]);
|
|
24140
24679
|
if (value) return value;
|
|
24141
24680
|
}
|
|
24142
24681
|
return null;
|
|
24143
24682
|
}
|
|
24144
24683
|
function asList4(value) {
|
|
24145
24684
|
if (Array.isArray(value)) return value;
|
|
24146
|
-
const record =
|
|
24685
|
+
const record = asRecord13(value);
|
|
24147
24686
|
if (!record) return [];
|
|
24148
24687
|
for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
|
|
24149
24688
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -24155,18 +24694,18 @@ function labelsOf(record) {
|
|
|
24155
24694
|
if (!Array.isArray(raw)) return [];
|
|
24156
24695
|
return raw.map((item) => {
|
|
24157
24696
|
if (typeof item === "string") return item.trim();
|
|
24158
|
-
const rec =
|
|
24697
|
+
const rec = asRecord13(item);
|
|
24159
24698
|
return rec ? firstString3(rec, ["name", "title", "label"]) : "";
|
|
24160
24699
|
}).filter(Boolean);
|
|
24161
24700
|
}
|
|
24162
24701
|
function commentsOf(record) {
|
|
24163
24702
|
const out = [];
|
|
24164
24703
|
for (const item of asList4(record.comments ?? record.notes ?? record.discussion)) {
|
|
24165
|
-
const rec =
|
|
24704
|
+
const rec = asRecord13(item);
|
|
24166
24705
|
if (!rec) continue;
|
|
24167
24706
|
const body = firstString3(rec, ["body", "text", "comment", "message", "contentSanitized"]) || textFromAbleTimeDoc(rec.content);
|
|
24168
24707
|
if (!body) continue;
|
|
24169
|
-
const user = firstString3(
|
|
24708
|
+
const user = firstString3(asRecord13(rec.user) ?? asRecord13(rec.author), ["name", "display_name", "username"]) || firstString3(rec, ["user_name", "author", "username"]);
|
|
24170
24709
|
const id = firstString3(rec, ["id", "comment_id", "commentId"]);
|
|
24171
24710
|
const url = firstString3(rec, ["url", "permalink"]);
|
|
24172
24711
|
const createdAt = firstString3(rec, ["created_at", "createdAt", "created"]);
|
|
@@ -24193,7 +24732,7 @@ function taskUrl(task, host) {
|
|
|
24193
24732
|
return `${base}/tasks/${slug}`;
|
|
24194
24733
|
}
|
|
24195
24734
|
function mapAbleTimeTask(raw, host) {
|
|
24196
|
-
const record =
|
|
24735
|
+
const record = asRecord13(raw);
|
|
24197
24736
|
if (!record) return null;
|
|
24198
24737
|
const nested = firstRecord(record, ["task", "data"]) ?? record;
|
|
24199
24738
|
const id = firstString3(nested, ["id", "task_id", "taskId", "timeflowTaskId"]);
|
|
@@ -24211,7 +24750,7 @@ function mapAbleTimeTask(raw, host) {
|
|
|
24211
24750
|
description: firstString3(nested, ["description", "body", "details", "descriptionSanitized"]) || textFromAbleTimeDoc(nested.description) || void 0,
|
|
24212
24751
|
state: firstString3(nested, ["state", "board_state", "boardState", "status", "taskState"]) || void 0,
|
|
24213
24752
|
...ableTimeProjectFields(nested),
|
|
24214
|
-
categoryId: firstString3(nested, ["category_id", "categoryId", "projectCategoryId"]) || firstString3(
|
|
24753
|
+
categoryId: firstString3(nested, ["category_id", "categoryId", "projectCategoryId"]) || firstString3(asRecord13(nested.category), ["id"]) || void 0,
|
|
24215
24754
|
assignee: assigneeOf(nested),
|
|
24216
24755
|
labels: labelsOf(nested),
|
|
24217
24756
|
comments: commentsOf(nested),
|
|
@@ -24261,7 +24800,7 @@ function isOpenTask(task) {
|
|
|
24261
24800
|
}
|
|
24262
24801
|
async function getAbleTimeOrientation(opts) {
|
|
24263
24802
|
const raw = await callAbleTimeTool("orientation", {}, opts);
|
|
24264
|
-
const record =
|
|
24803
|
+
const record = asRecord13(raw);
|
|
24265
24804
|
const viewerRec = firstRecord(record, ["viewer", "principal", "user", "actor", "me", "person"]) ?? record;
|
|
24266
24805
|
const viewer = {
|
|
24267
24806
|
id: firstString3(viewerRec, ["id", "user_id"]) || void 0,
|
|
@@ -24340,7 +24879,7 @@ async function commentAbleTimeTask(input, opts) {
|
|
|
24340
24879
|
{ id, task_id: id, task: id, body, comment: body, text: body },
|
|
24341
24880
|
opts
|
|
24342
24881
|
);
|
|
24343
|
-
const rec =
|
|
24882
|
+
const rec = asRecord13(raw);
|
|
24344
24883
|
return {
|
|
24345
24884
|
id: rec ? firstString3(rec, ["id", "comment_id"]) || void 0 : void 0,
|
|
24346
24885
|
body: rec ? firstString3(rec, ["body", "text", "comment"]) || body : body
|
|
@@ -25493,7 +26032,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
25493
26032
|
...instructions
|
|
25494
26033
|
].join("\n");
|
|
25495
26034
|
return {
|
|
25496
|
-
id: (0,
|
|
26035
|
+
id: (0, import_node_crypto18.randomUUID)(),
|
|
25497
26036
|
name: orch ? "Orchestration quota handoff.md" : "Quota handoff.md",
|
|
25498
26037
|
kind: "transcript",
|
|
25499
26038
|
content: body
|
|
@@ -25525,11 +26064,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
|
|
|
25525
26064
|
}
|
|
25526
26065
|
return updateThread(tab.id, patch);
|
|
25527
26066
|
}
|
|
25528
|
-
var
|
|
26067
|
+
var import_node_crypto18, QUOTA_CONTINUE_PROMPT, QUOTA_CONTINUE_ACCOUNT_PROMPT, QUOTA_RESUME_PROMPT;
|
|
25529
26068
|
var init_quota_failover = __esm({
|
|
25530
26069
|
"src/orchestrator/quota-failover.ts"() {
|
|
25531
26070
|
"use strict";
|
|
25532
|
-
|
|
26071
|
+
import_node_crypto18 = require("crypto");
|
|
25533
26072
|
init_session_quota();
|
|
25534
26073
|
init_app_settings();
|
|
25535
26074
|
init_managed_accounts();
|
|
@@ -27605,7 +28144,7 @@ function compiledModuleDir() {
|
|
|
27605
28144
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
27606
28145
|
if (cjsDir) return cjsDir;
|
|
27607
28146
|
try {
|
|
27608
|
-
const url =
|
|
28147
|
+
const url = import_meta8.url;
|
|
27609
28148
|
if (typeof url === "string" && url.length > 0) {
|
|
27610
28149
|
return (0, import_node_path62.dirname)((0, import_node_url5.fileURLToPath)(url));
|
|
27611
28150
|
}
|
|
@@ -27644,7 +28183,7 @@ function formatDetachedJobInvoke(scriptPath) {
|
|
|
27644
28183
|
if (resolved) return `node ${JSON.stringify(resolved)}`;
|
|
27645
28184
|
return "node scripts/detached-job.cjs";
|
|
27646
28185
|
}
|
|
27647
|
-
var import_node_fs63, import_node_path62, import_node_url5,
|
|
28186
|
+
var import_node_fs63, import_node_path62, import_node_url5, import_meta8, DETACHED_JOB_FILENAMES;
|
|
27648
28187
|
var init_detached_job_path = __esm({
|
|
27649
28188
|
"src/skills/detached-job-path.ts"() {
|
|
27650
28189
|
"use strict";
|
|
@@ -27652,7 +28191,7 @@ var init_detached_job_path = __esm({
|
|
|
27652
28191
|
import_node_path62 = require("path");
|
|
27653
28192
|
import_node_url5 = require("url");
|
|
27654
28193
|
init_packaged_runtime();
|
|
27655
|
-
|
|
28194
|
+
import_meta8 = {};
|
|
27656
28195
|
DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
|
|
27657
28196
|
}
|
|
27658
28197
|
});
|
|
@@ -28052,7 +28591,7 @@ function normalizeServiceOrigin(raw, fallback) {
|
|
|
28052
28591
|
return fallback;
|
|
28053
28592
|
}
|
|
28054
28593
|
}
|
|
28055
|
-
function
|
|
28594
|
+
function asRecord14(value) {
|
|
28056
28595
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
28057
28596
|
}
|
|
28058
28597
|
function asString4(value) {
|
|
@@ -28085,7 +28624,7 @@ async function authorizedGet(url, token) {
|
|
|
28085
28624
|
});
|
|
28086
28625
|
const body = await readJson2(res);
|
|
28087
28626
|
if (!res.ok) {
|
|
28088
|
-
const record =
|
|
28627
|
+
const record = asRecord14(body);
|
|
28089
28628
|
const message = firstString4(record, ["message", "error", "error_description", "detail"]) || (typeof body === "string" ? body.trim().slice(0, 160) : "");
|
|
28090
28629
|
throw new Error(
|
|
28091
28630
|
message ? `${res.status}: ${message}` : `Request failed (${res.status})`
|
|
@@ -28099,28 +28638,28 @@ async function verifyOptionalService(input) {
|
|
|
28099
28638
|
const spec = optionalServiceSpec(input.id);
|
|
28100
28639
|
try {
|
|
28101
28640
|
if (input.id === "vercel") {
|
|
28102
|
-
const body2 =
|
|
28103
|
-
const user =
|
|
28641
|
+
const body2 = asRecord14(await authorizedGet("https://api.vercel.com/v2/user", token));
|
|
28642
|
+
const user = asRecord14(body2?.user) ?? body2;
|
|
28104
28643
|
const name2 = firstString4(user, ["username", "name", "email"]) || "Vercel user";
|
|
28105
28644
|
return { viewerName: name2 };
|
|
28106
28645
|
}
|
|
28107
28646
|
if (input.id === "supabase") {
|
|
28108
28647
|
const body2 = await authorizedGet("https://api.supabase.com/v1/organizations", token);
|
|
28109
28648
|
const list2 = Array.isArray(body2) ? body2 : [];
|
|
28110
|
-
const first2 =
|
|
28649
|
+
const first2 = asRecord14(list2[0]);
|
|
28111
28650
|
const name2 = firstString4(first2, ["name", "slug"]) || "Supabase";
|
|
28112
28651
|
return { viewerName: list2.length > 1 ? `${name2} +${list2.length - 1}` : name2 };
|
|
28113
28652
|
}
|
|
28114
28653
|
if (input.id === "posthog") {
|
|
28115
28654
|
const host2 = normalizeServiceOrigin(input.host, spec.defaultHost ?? "https://us.posthog.com");
|
|
28116
|
-
const body2 =
|
|
28655
|
+
const body2 = asRecord14(await authorizedGet(`${host2}/api/users/@me/`, token));
|
|
28117
28656
|
const name2 = firstString4(body2, ["email", "distinct_id"]) || [firstString4(body2, ["first_name"]), firstString4(body2, ["last_name"])].filter(Boolean).join(" ") || "PostHog user";
|
|
28118
28657
|
return { viewerName: name2, host: host2 };
|
|
28119
28658
|
}
|
|
28120
28659
|
const host = normalizeServiceOrigin(input.host, spec.defaultHost ?? "https://sentry.io");
|
|
28121
28660
|
const body = await authorizedGet(`${host}/api/0/organizations/`, token);
|
|
28122
28661
|
const list = Array.isArray(body) ? body : [];
|
|
28123
|
-
const first =
|
|
28662
|
+
const first = asRecord14(list[0]);
|
|
28124
28663
|
const name = firstString4(first, ["slug", "name"]) || "Sentry";
|
|
28125
28664
|
return { viewerName: list.length > 1 ? `${name} +${list.length - 1}` : name, host };
|
|
28126
28665
|
} catch (err) {
|
|
@@ -28994,10 +29533,10 @@ function collectActiveRunPorts(runs) {
|
|
|
28994
29533
|
return [...ports];
|
|
28995
29534
|
}
|
|
28996
29535
|
function getOrchestrator() {
|
|
28997
|
-
if (!
|
|
28998
|
-
|
|
29536
|
+
if (!singleton2) {
|
|
29537
|
+
singleton2 = new Orchestrator();
|
|
28999
29538
|
}
|
|
29000
|
-
return
|
|
29539
|
+
return singleton2;
|
|
29001
29540
|
}
|
|
29002
29541
|
async function startOrchestration(opts) {
|
|
29003
29542
|
const repoPath = opts.repoPath?.trim();
|
|
@@ -29057,7 +29596,7 @@ async function startOrchestration(opts) {
|
|
|
29057
29596
|
}
|
|
29058
29597
|
return updated;
|
|
29059
29598
|
}
|
|
29060
|
-
var import_node_events,
|
|
29599
|
+
var import_node_events, import_node_crypto19, import_node_fs67, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton2;
|
|
29061
29600
|
var init_orchestrator = __esm({
|
|
29062
29601
|
"src/orchestrator/orchestrator.ts"() {
|
|
29063
29602
|
"use strict";
|
|
@@ -29065,7 +29604,7 @@ var init_orchestrator = __esm({
|
|
|
29065
29604
|
init_injected_notices();
|
|
29066
29605
|
init_task_state();
|
|
29067
29606
|
init_wait_for_turn();
|
|
29068
|
-
|
|
29607
|
+
import_node_crypto19 = require("crypto");
|
|
29069
29608
|
import_node_fs67 = require("fs");
|
|
29070
29609
|
init_error_detail();
|
|
29071
29610
|
init_run();
|
|
@@ -29091,6 +29630,7 @@ var init_orchestrator = __esm({
|
|
|
29091
29630
|
init_usage();
|
|
29092
29631
|
init_thread_store();
|
|
29093
29632
|
init_desktop_host();
|
|
29633
|
+
init_model_context();
|
|
29094
29634
|
init_agent_block();
|
|
29095
29635
|
init_child_halt();
|
|
29096
29636
|
init_stop_reason();
|
|
@@ -30089,6 +30629,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
30089
30629
|
orchestrationReminder,
|
|
30090
30630
|
prGateDirective,
|
|
30091
30631
|
injectedNoticeContext,
|
|
30632
|
+
takeMcpAppModelContext(threadId),
|
|
30092
30633
|
expandedPrompt
|
|
30093
30634
|
].filter(Boolean).join("\n\n");
|
|
30094
30635
|
if (!autoContinue && sentAttachments) {
|
|
@@ -30717,7 +31258,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
30717
31258
|
const request = sameIntent ? pending : {
|
|
30718
31259
|
op,
|
|
30719
31260
|
scriptName: scriptName ?? null,
|
|
30720
|
-
requestId: (0,
|
|
31261
|
+
requestId: (0, import_node_crypto19.randomUUID)(),
|
|
30721
31262
|
requestedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
30722
31263
|
};
|
|
30723
31264
|
if (!sameIntent) {
|
|
@@ -31838,7 +32379,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
31838
32379
|
return thread;
|
|
31839
32380
|
}
|
|
31840
32381
|
};
|
|
31841
|
-
|
|
32382
|
+
singleton2 = null;
|
|
31842
32383
|
}
|
|
31843
32384
|
});
|
|
31844
32385
|
|
|
@@ -32955,6 +33496,7 @@ __export(index_exports, {
|
|
|
32955
33496
|
startRelayServer: () => startRelayServer,
|
|
32956
33497
|
startRemoteAccountLogin: () => startRemoteAccountLogin,
|
|
32957
33498
|
startSlackOAuth: () => startSlackOAuth,
|
|
33499
|
+
stashMcpAppModelContext: () => stashMcpAppModelContext,
|
|
32958
33500
|
statWorktreePath: () => statWorktreePath,
|
|
32959
33501
|
stopAgentRpcServer: () => stopAgentRpcServer,
|
|
32960
33502
|
stripBrightsyNdjsonNoise: () => stripBrightsyNdjsonNoise,
|
|
@@ -33521,7 +34063,7 @@ init_schedule_runner();
|
|
|
33521
34063
|
|
|
33522
34064
|
// src/host/serve.ts
|
|
33523
34065
|
var import_node_child_process7 = require("child_process");
|
|
33524
|
-
var
|
|
34066
|
+
var import_node_os21 = require("os");
|
|
33525
34067
|
init_system_ca();
|
|
33526
34068
|
init_app_settings();
|
|
33527
34069
|
init_desktop_host();
|
|
@@ -33534,7 +34076,7 @@ init_system_ca();
|
|
|
33534
34076
|
|
|
33535
34077
|
// src/slack/public-dns.ts
|
|
33536
34078
|
var import_node_dns = require("dns");
|
|
33537
|
-
var
|
|
34079
|
+
var import_node_http3 = require("http");
|
|
33538
34080
|
var import_node_https = require("https");
|
|
33539
34081
|
var PUBLIC_DNS = ["1.1.1.1", "8.8.8.8"];
|
|
33540
34082
|
function finishLookup(options, callback, address, family) {
|
|
@@ -33664,213 +34206,12 @@ function buildPathRefAttachment(input) {
|
|
|
33664
34206
|
init_stage_files();
|
|
33665
34207
|
init_orchestrator();
|
|
33666
34208
|
|
|
33667
|
-
// src/mcp-ui
|
|
33668
|
-
|
|
33669
|
-
|
|
33670
|
-
init_meta();
|
|
33671
|
-
|
|
33672
|
-
// src/mcp-ui/session.ts
|
|
33673
|
-
var import_client2 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
33674
|
-
var import_sse = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
33675
|
-
var import_stdio = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
33676
|
-
var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
33677
|
-
init_meta();
|
|
33678
|
-
var REQUEST_TIMEOUT_MS = 2e4;
|
|
33679
|
-
var UI_CAPABILITIES = {
|
|
33680
|
-
extensions: {
|
|
33681
|
-
"io.modelcontextprotocol/ui": {
|
|
33682
|
-
mimeTypes: ["text/html;profile=mcp-app"]
|
|
33683
|
-
}
|
|
33684
|
-
}
|
|
33685
|
-
};
|
|
33686
|
-
async function openMcpUiSession(launch) {
|
|
33687
|
-
return openMcpUiSessionFromTransport(transportForLaunch(launch));
|
|
33688
|
-
}
|
|
33689
|
-
async function openMcpUiSessionFromTransport(transport) {
|
|
33690
|
-
const client = new import_client2.Client(
|
|
33691
|
-
{ name: "sideboard", version: "1.0.0" },
|
|
33692
|
-
{ capabilities: UI_CAPABILITIES }
|
|
33693
|
-
);
|
|
33694
|
-
await client.connect(transport, { timeout: REQUEST_TIMEOUT_MS });
|
|
33695
|
-
return {
|
|
33696
|
-
async listTools() {
|
|
33697
|
-
const listed = await client.listTools(void 0, { timeout: REQUEST_TIMEOUT_MS });
|
|
33698
|
-
return listed.tools.map((tool) => {
|
|
33699
|
-
const meta = tool._meta;
|
|
33700
|
-
return {
|
|
33701
|
-
name: tool.name,
|
|
33702
|
-
...tool.description ? { description: tool.description } : {},
|
|
33703
|
-
...tool.inputSchema ? { inputSchema: tool.inputSchema } : {},
|
|
33704
|
-
resourceUri: uiResourceUriFromMeta(meta),
|
|
33705
|
-
...cspFromMeta(meta) ? { csp: cspFromMeta(meta) } : {}
|
|
33706
|
-
};
|
|
33707
|
-
});
|
|
33708
|
-
},
|
|
33709
|
-
async readResource(uri) {
|
|
33710
|
-
const result = await client.readResource({ uri }, { timeout: REQUEST_TIMEOUT_MS });
|
|
33711
|
-
const content = result.contents?.[0];
|
|
33712
|
-
if (!content) return null;
|
|
33713
|
-
const text7 = "text" in content && typeof content.text === "string" ? content.text : void 0;
|
|
33714
|
-
const blob = "blob" in content && typeof content.blob === "string" ? content.blob : void 0;
|
|
33715
|
-
return {
|
|
33716
|
-
uri: content.uri,
|
|
33717
|
-
...content.mimeType ? { mimeType: content.mimeType } : {},
|
|
33718
|
-
...text7 != null ? { text: text7 } : {},
|
|
33719
|
-
...blob != null ? { blob } : {},
|
|
33720
|
-
...cspFromMeta(content._meta) ? { csp: cspFromMeta(content._meta) } : {}
|
|
33721
|
-
};
|
|
33722
|
-
},
|
|
33723
|
-
async callTool(name, args) {
|
|
33724
|
-
return client.callTool({ name, arguments: args }, void 0, { timeout: REQUEST_TIMEOUT_MS });
|
|
33725
|
-
},
|
|
33726
|
-
async close() {
|
|
33727
|
-
await client.close();
|
|
33728
|
-
}
|
|
33729
|
-
};
|
|
33730
|
-
}
|
|
33731
|
-
function transportForLaunch(launch) {
|
|
33732
|
-
if (launch.kind === "stdio") {
|
|
33733
|
-
return new import_stdio.StdioClientTransport({
|
|
33734
|
-
command: launch.command,
|
|
33735
|
-
args: launch.args,
|
|
33736
|
-
env: { ...(0, import_stdio.getDefaultEnvironment)(), ...launch.env },
|
|
33737
|
-
stderr: "ignore",
|
|
33738
|
-
...launch.cwd ? { cwd: launch.cwd } : {}
|
|
33739
|
-
});
|
|
33740
|
-
}
|
|
33741
|
-
const url = new URL(launch.url);
|
|
33742
|
-
const requestInit = launch.headers ? { headers: launch.headers } : void 0;
|
|
33743
|
-
if (launch.kind === "sse") {
|
|
33744
|
-
return new import_sse.SSEClientTransport(url, requestInit ? { requestInit } : void 0);
|
|
33745
|
-
}
|
|
33746
|
-
return new import_streamableHttp.StreamableHTTPClientTransport(url, requestInit ? { requestInit } : void 0);
|
|
33747
|
-
}
|
|
33748
|
-
|
|
33749
|
-
// src/mcp-ui/host.ts
|
|
33750
|
-
var TOOL_TTL_MS = 5 * 60 * 1e3;
|
|
33751
|
-
var McpUiHost = class {
|
|
33752
|
-
constructor(opts) {
|
|
33753
|
-
this.opts = opts;
|
|
33754
|
-
}
|
|
33755
|
-
opts;
|
|
33756
|
-
sessions = /* @__PURE__ */ new Map();
|
|
33757
|
-
toolLists = /* @__PURE__ */ new Map();
|
|
33758
|
-
async viewForClaudeTool(toolName, projectDirs) {
|
|
33759
|
-
const entries = this.userEntries(projectDirs);
|
|
33760
|
-
const match = matchClaudeMcpTool(toolName, Object.keys(entries));
|
|
33761
|
-
if (!match) return null;
|
|
33762
|
-
const launch = parseMcpServerLaunch(entries[match.server] ?? {});
|
|
33763
|
-
if (!launch) return null;
|
|
33764
|
-
try {
|
|
33765
|
-
const session = await this.sessionFor(match.server, launch);
|
|
33766
|
-
const tools = await this.toolsFor(match.server, launch, session);
|
|
33767
|
-
const tool = tools.find((item) => item.name === match.tool);
|
|
33768
|
-
if (!tool?.resourceUri) return null;
|
|
33769
|
-
const resource = await session.readResource(tool.resourceUri);
|
|
33770
|
-
if (!resource) return null;
|
|
33771
|
-
const html = htmlFromResourceContent(resource);
|
|
33772
|
-
if (!html) return null;
|
|
33773
|
-
const csp = resource.csp ?? tool.csp;
|
|
33774
|
-
return {
|
|
33775
|
-
server: match.server,
|
|
33776
|
-
tool: match.tool,
|
|
33777
|
-
uri: html.uri,
|
|
33778
|
-
mimeType: html.mimeType,
|
|
33779
|
-
html: html.html,
|
|
33780
|
-
csp: mcpUiContentSecurityPolicy(csp)
|
|
33781
|
-
};
|
|
33782
|
-
} catch (err) {
|
|
33783
|
-
console.error(
|
|
33784
|
-
`[mcp-ui] ${match.server}/${match.tool}:`,
|
|
33785
|
-
err instanceof Error ? err.message : err
|
|
33786
|
-
);
|
|
33787
|
-
return null;
|
|
33788
|
-
}
|
|
33789
|
-
}
|
|
33790
|
-
async callTool(server, tool, args, projectDirs) {
|
|
33791
|
-
const session = await this.sessionForName(server, projectDirs);
|
|
33792
|
-
if (!session) throw new Error(`MCP server ${server} is not available`);
|
|
33793
|
-
return session.callTool(tool, args);
|
|
33794
|
-
}
|
|
33795
|
-
async readResource(server, uri, projectDirs) {
|
|
33796
|
-
const session = await this.sessionForName(server, projectDirs);
|
|
33797
|
-
if (!session) throw new Error(`MCP server ${server} is not available`);
|
|
33798
|
-
const resource = await session.readResource(uri);
|
|
33799
|
-
if (!resource) throw new Error(`Resource ${uri} was empty`);
|
|
33800
|
-
return {
|
|
33801
|
-
contents: [
|
|
33802
|
-
{
|
|
33803
|
-
uri: resource.uri,
|
|
33804
|
-
...resource.mimeType ? { mimeType: resource.mimeType } : {},
|
|
33805
|
-
...resource.text != null ? { text: resource.text } : {},
|
|
33806
|
-
...resource.blob != null ? { blob: resource.blob } : {}
|
|
33807
|
-
}
|
|
33808
|
-
]
|
|
33809
|
-
};
|
|
33810
|
-
}
|
|
33811
|
-
async closeAll() {
|
|
33812
|
-
const pending = [...this.sessions.values()];
|
|
33813
|
-
this.sessions.clear();
|
|
33814
|
-
this.toolLists.clear();
|
|
33815
|
-
await Promise.all(
|
|
33816
|
-
pending.map((session) => session.then((open) => open.close()).catch(() => void 0))
|
|
33817
|
-
);
|
|
33818
|
-
}
|
|
33819
|
-
userEntries(projectDirs) {
|
|
33820
|
-
const out = {};
|
|
33821
|
-
for (const [name, entry] of Object.entries(this.opts.entries(projectDirs))) {
|
|
33822
|
-
if (!name.trim() || isInjectedOrchMcpName(name) || !entry) continue;
|
|
33823
|
-
out[name] = entry;
|
|
33824
|
-
}
|
|
33825
|
-
return out;
|
|
33826
|
-
}
|
|
33827
|
-
async sessionForName(server, projectDirs) {
|
|
33828
|
-
const entry = this.userEntries(projectDirs)[server];
|
|
33829
|
-
if (!entry) return null;
|
|
33830
|
-
const launch = parseMcpServerLaunch(entry);
|
|
33831
|
-
if (!launch) return null;
|
|
33832
|
-
return this.sessionFor(server, launch);
|
|
33833
|
-
}
|
|
33834
|
-
sessionFor(server, launch) {
|
|
33835
|
-
const key = `${server}
|
|
33836
|
-
${JSON.stringify(launch)}`;
|
|
33837
|
-
const existing = this.sessions.get(key);
|
|
33838
|
-
if (existing) return existing;
|
|
33839
|
-
const open = this.opts.openSession ?? openMcpUiSession;
|
|
33840
|
-
const pending = open(launch).catch((err) => {
|
|
33841
|
-
this.sessions.delete(key);
|
|
33842
|
-
throw err;
|
|
33843
|
-
});
|
|
33844
|
-
this.sessions.set(key, pending);
|
|
33845
|
-
return pending;
|
|
33846
|
-
}
|
|
33847
|
-
async toolsFor(server, launch, session) {
|
|
33848
|
-
const key = `${server}
|
|
33849
|
-
${JSON.stringify(launch)}`;
|
|
33850
|
-
const cached2 = this.toolLists.get(key);
|
|
33851
|
-
if (cached2 && cached2.key === key && Date.now() - cached2.at < TOOL_TTL_MS) return cached2.tools;
|
|
33852
|
-
const tools = await session.listTools();
|
|
33853
|
-
this.toolLists.set(key, { at: Date.now(), key, tools });
|
|
33854
|
-
return tools;
|
|
33855
|
-
}
|
|
33856
|
-
};
|
|
33857
|
-
var singleton2;
|
|
33858
|
-
function getMcpUiHost() {
|
|
33859
|
-
if (!singleton2) {
|
|
33860
|
-
singleton2 = new McpUiHost({
|
|
33861
|
-
entries: (projectDirs) => listUserClaudeMcpServerEntries((0, import_node_os21.homedir)(), projectDirs)
|
|
33862
|
-
});
|
|
33863
|
-
}
|
|
33864
|
-
return singleton2;
|
|
33865
|
-
}
|
|
33866
|
-
function closeMcpUiHost() {
|
|
33867
|
-
const host = singleton2;
|
|
33868
|
-
singleton2 = void 0;
|
|
33869
|
-
if (host) void host.closeAll();
|
|
33870
|
-
}
|
|
34209
|
+
// src/remote/phone-mcp-ui-listen.ts
|
|
34210
|
+
init_host();
|
|
34211
|
+
init_model_context();
|
|
33871
34212
|
|
|
33872
34213
|
// src/remote/phone-chats.ts
|
|
33873
|
-
var
|
|
34214
|
+
var import_node_crypto20 = require("crypto");
|
|
33874
34215
|
init_list_models();
|
|
33875
34216
|
init_home_board();
|
|
33876
34217
|
init_stage_files();
|
|
@@ -33892,10 +34233,10 @@ var MIN_MD_CHARS = 120;
|
|
|
33892
34233
|
function oneLine2(value, max) {
|
|
33893
34234
|
return value.replace(/[`\r\n]/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
|
|
33894
34235
|
}
|
|
33895
|
-
function
|
|
34236
|
+
function asRecord15(value) {
|
|
33896
34237
|
if (typeof value === "string") {
|
|
33897
34238
|
try {
|
|
33898
|
-
return
|
|
34239
|
+
return asRecord15(JSON.parse(value));
|
|
33899
34240
|
} catch {
|
|
33900
34241
|
return void 0;
|
|
33901
34242
|
}
|
|
@@ -33970,7 +34311,7 @@ function toolContent(input) {
|
|
|
33970
34311
|
if (!input) return "";
|
|
33971
34312
|
const direct = input.content;
|
|
33972
34313
|
if (typeof direct === "string") return direct;
|
|
33973
|
-
const nested =
|
|
34314
|
+
const nested = asRecord15(direct);
|
|
33974
34315
|
if (!nested) return "";
|
|
33975
34316
|
for (const key of ["html", "markup", "text", "source", "content", "code"]) {
|
|
33976
34317
|
if (typeof nested[key] === "string") return nested[key];
|
|
@@ -33993,7 +34334,7 @@ function phoneArtifactText(text7, parts, limit = Number.POSITIVE_INFINITY) {
|
|
|
33993
34334
|
const extras = [];
|
|
33994
34335
|
for (const part of parts ?? []) {
|
|
33995
34336
|
if (part.type !== "tool" || part.parentId || !isArtifactTool(part.name)) continue;
|
|
33996
|
-
const input =
|
|
34337
|
+
const input = asRecord15(part.input);
|
|
33997
34338
|
const content = toolContent(input);
|
|
33998
34339
|
const hint = artifactHint(content);
|
|
33999
34340
|
if (hint && hints.has(hint)) continue;
|
|
@@ -34012,7 +34353,7 @@ function phoneArtifactText(text7, parts, limit = Number.POSITIVE_INFINITY) {
|
|
|
34012
34353
|
${tail}` : tail;
|
|
34013
34354
|
}
|
|
34014
34355
|
function parseOpenArtifact(value, chatId) {
|
|
34015
|
-
const record =
|
|
34356
|
+
const record = asRecord15(value);
|
|
34016
34357
|
if (!record) return "invalid";
|
|
34017
34358
|
const title = oneLine2(str5(record.title), 200);
|
|
34018
34359
|
if (!title) return "invalid";
|
|
@@ -34035,7 +34376,7 @@ function phoneArtifactDocuments(sources) {
|
|
|
34035
34376
|
}
|
|
34036
34377
|
for (const part of source.parts ?? []) {
|
|
34037
34378
|
if (part.type !== "tool" || part.parentId || !isArtifactTool(part.name)) continue;
|
|
34038
|
-
const input =
|
|
34379
|
+
const input = asRecord15(part.input);
|
|
34039
34380
|
const content = toolContent(input);
|
|
34040
34381
|
const hint = artifactHint(content);
|
|
34041
34382
|
if (hint && hints.has(hint)) continue;
|
|
@@ -34480,13 +34821,21 @@ function parsePhoneMcpUi(value, op, chatId) {
|
|
|
34480
34821
|
}
|
|
34481
34822
|
return { op: "mcp-ui", chatId, tool: tool2, callId, reqId: reqId2 };
|
|
34482
34823
|
}
|
|
34824
|
+
if (op === "mcp-ui-context") {
|
|
34825
|
+
const reqId2 = controlText(value, "reqId");
|
|
34826
|
+
const text7 = controlText(value, "text");
|
|
34827
|
+
if (!reqId2 || reqId2.length > 40 || !text7 || text7.length > 8e3) return "invalid";
|
|
34828
|
+
return { op, chatId, reqId: reqId2, text: text7 };
|
|
34829
|
+
}
|
|
34483
34830
|
if (op !== "mcp-ui-call" && op !== "mcp-ui-read") return "invalid";
|
|
34484
34831
|
const reqId = controlText(value, "reqId");
|
|
34485
34832
|
const server = controlText(value, "server");
|
|
34486
34833
|
if (!reqId || reqId.length > 40 || !server || server.length > 120) return "invalid";
|
|
34487
34834
|
if (op === "mcp-ui-read") {
|
|
34488
34835
|
const uri = controlText(value, "uri");
|
|
34489
|
-
if (!uri
|
|
34836
|
+
if (!uri || uri.length > 500 || /\s/.test(uri) || /^(javascript|data):/i.test(uri)) {
|
|
34837
|
+
return "invalid";
|
|
34838
|
+
}
|
|
34490
34839
|
return { op, chatId, reqId, server, uri };
|
|
34491
34840
|
}
|
|
34492
34841
|
const tool = controlText(value, "tool");
|
|
@@ -34708,7 +35057,7 @@ function parsePhoneControl(value) {
|
|
|
34708
35057
|
}
|
|
34709
35058
|
if (op === "pane") return parsePhonePane(value, chatId);
|
|
34710
35059
|
if (op === "open-artifact") return parseOpenArtifact(value, chatId);
|
|
34711
|
-
if (op === "mcp-ui" || op === "mcp-ui-call" || op === "mcp-ui-read") return parsePhoneMcpUi(value, op, chatId);
|
|
35060
|
+
if (op === "mcp-ui" || op === "mcp-ui-call" || op === "mcp-ui-read" || op === "mcp-ui-context") return parsePhoneMcpUi(value, op, chatId);
|
|
34712
35061
|
if (op === "open-file" || op === "media") {
|
|
34713
35062
|
const path2 = textField(value, "path");
|
|
34714
35063
|
if (!path2 || path2.length > 2e3) return "invalid";
|
|
@@ -34975,13 +35324,13 @@ function phoneComposerOptions(thread) {
|
|
|
34975
35324
|
}
|
|
34976
35325
|
function phoneTurnAttachments(draft) {
|
|
34977
35326
|
const links = (draft.links ?? []).map((link) => ({
|
|
34978
|
-
id: (0,
|
|
35327
|
+
id: (0, import_node_crypto20.randomUUID)(),
|
|
34979
35328
|
name: link.ref,
|
|
34980
35329
|
kind: "issue",
|
|
34981
35330
|
content: [`Linked issue: ${link.ref} \u2014 ${link.title}`, link.url ? `URL: ${link.url}` : null].filter(Boolean).join("\n")
|
|
34982
35331
|
}));
|
|
34983
35332
|
const files = (draft.files ?? []).map((file) => ({
|
|
34984
|
-
id: (0,
|
|
35333
|
+
id: (0, import_node_crypto20.randomUUID)(),
|
|
34985
35334
|
name: file.name,
|
|
34986
35335
|
kind: "file",
|
|
34987
35336
|
previewDataUrl: `data:application/octet-stream;base64,${file.dataBase64}`,
|
|
@@ -35317,7 +35666,9 @@ function deliverPhoneTurn(opts, chatId) {
|
|
|
35317
35666
|
// src/remote/phone-mcp-ui-listen.ts
|
|
35318
35667
|
var PHONE_HTML_CAP = 7e5;
|
|
35319
35668
|
function dispatchPhoneMcpUi(cmd, opts) {
|
|
35320
|
-
if (cmd.op !== "mcp-ui" && cmd.op !== "mcp-ui-call" && cmd.op !== "mcp-ui-read")
|
|
35669
|
+
if (cmd.op !== "mcp-ui" && cmd.op !== "mcp-ui-call" && cmd.op !== "mcp-ui-read" && cmd.op !== "mcp-ui-context") {
|
|
35670
|
+
return false;
|
|
35671
|
+
}
|
|
35321
35672
|
const thread = readPhoneThread(cmd.chatId);
|
|
35322
35673
|
const reqId = cmd.reqId;
|
|
35323
35674
|
const chatId = cmd.chatId;
|
|
@@ -35327,6 +35678,11 @@ function dispatchPhoneMcpUi(cmd, opts) {
|
|
|
35327
35678
|
return true;
|
|
35328
35679
|
}
|
|
35329
35680
|
const projectDirs = [thread.repoPath, thread.worktreePath];
|
|
35681
|
+
if (cmd.op === "mcp-ui-context") {
|
|
35682
|
+
stashMcpAppModelContext(thread.id, cmd.text);
|
|
35683
|
+
emitControl(opts, { op: "mcp-ui-context", chatId, reqId, result: {} });
|
|
35684
|
+
return true;
|
|
35685
|
+
}
|
|
35330
35686
|
if (cmd.op === "mcp-ui-call") {
|
|
35331
35687
|
void getMcpUiHost().callTool(cmd.server, cmd.tool, cmd.args, projectDirs).then((result) => emitControl(opts, { op: "mcp-ui-call", chatId, reqId, result })).catch(
|
|
35332
35688
|
(err) => emitControl(opts, { op: "mcp-ui-call", chatId, reqId, error: phoneError(err) })
|
|
@@ -36163,8 +36519,8 @@ init_fetch();
|
|
|
36163
36519
|
init_issue_attachments();
|
|
36164
36520
|
|
|
36165
36521
|
// src/integrations/linear-oauth.ts
|
|
36166
|
-
var
|
|
36167
|
-
var
|
|
36522
|
+
var import_node_crypto21 = require("crypto");
|
|
36523
|
+
var import_node_http4 = require("http");
|
|
36168
36524
|
init_app_settings();
|
|
36169
36525
|
init_fetch();
|
|
36170
36526
|
|
|
@@ -36195,8 +36551,8 @@ function linearOAuthCredentials() {
|
|
|
36195
36551
|
return { clientId, clientSecret };
|
|
36196
36552
|
}
|
|
36197
36553
|
function createLinearPkce() {
|
|
36198
|
-
const verifier = (0,
|
|
36199
|
-
const challenge = (0,
|
|
36554
|
+
const verifier = (0, import_node_crypto21.randomBytes)(32).toString("base64url");
|
|
36555
|
+
const challenge = (0, import_node_crypto21.createHash)("sha256").update(verifier).digest("base64url");
|
|
36200
36556
|
return { verifier, challenge };
|
|
36201
36557
|
}
|
|
36202
36558
|
function linearOAuthAuthorizeUrl(clientId, state, codeChallenge) {
|
|
@@ -36327,7 +36683,7 @@ async function startLinearOAuth(opts) {
|
|
|
36327
36683
|
throw new LinearOAuthCancelledError();
|
|
36328
36684
|
}
|
|
36329
36685
|
const { clientId, clientSecret } = linearOAuthCredentials();
|
|
36330
|
-
const state = (0,
|
|
36686
|
+
const state = (0, import_node_crypto21.randomBytes)(16).toString("hex");
|
|
36331
36687
|
const pkce = createLinearPkce();
|
|
36332
36688
|
const authorizeUrl = linearOAuthAuthorizeUrl(clientId, state, pkce.challenge);
|
|
36333
36689
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
@@ -36340,7 +36696,7 @@ async function startLinearOAuth(opts) {
|
|
|
36340
36696
|
if (err) reject(err);
|
|
36341
36697
|
else resolve3(value);
|
|
36342
36698
|
};
|
|
36343
|
-
const server = (0,
|
|
36699
|
+
const server = (0, import_node_http4.createServer)((req, res) => {
|
|
36344
36700
|
try {
|
|
36345
36701
|
const url = new URL(req.url || "/", `http://127.0.0.1:${LINEAR_OAUTH_PORT}`);
|
|
36346
36702
|
if (url.pathname !== "/callback") {
|
|
@@ -38753,7 +39109,7 @@ function runRemoteHost(opts) {
|
|
|
38753
39109
|
init_protocol();
|
|
38754
39110
|
|
|
38755
39111
|
// src/relay/server.ts
|
|
38756
|
-
var
|
|
39112
|
+
var import_node_http5 = require("http");
|
|
38757
39113
|
var import_ws4 = require("ws");
|
|
38758
39114
|
|
|
38759
39115
|
// src/slack/oauth-redirect.ts
|
|
@@ -39162,7 +39518,7 @@ function connectSession(ws, opts, log) {
|
|
|
39162
39518
|
}
|
|
39163
39519
|
|
|
39164
39520
|
// src/slack/relay-protocol.ts
|
|
39165
|
-
var
|
|
39521
|
+
var import_node_crypto22 = require("crypto");
|
|
39166
39522
|
var SLACK_RELAY_PING_INTERVAL_MS = 2e4;
|
|
39167
39523
|
var SLACK_RELAY_PONG_TIMEOUT_MS = 15e3;
|
|
39168
39524
|
function slackRelaySessionKey(teamId, userId, deviceId) {
|
|
@@ -39172,7 +39528,7 @@ function slackRelayUserKey(teamId, userId) {
|
|
|
39172
39528
|
return `${teamId.trim()}:${userId.trim()}`;
|
|
39173
39529
|
}
|
|
39174
39530
|
function newSlackRelayEventId() {
|
|
39175
|
-
return (0,
|
|
39531
|
+
return (0, import_node_crypto22.randomBytes)(12).toString("hex");
|
|
39176
39532
|
}
|
|
39177
39533
|
function parseSlackRelayClientMessage(raw) {
|
|
39178
39534
|
try {
|
|
@@ -39700,7 +40056,7 @@ async function tryServeStatic(req, res, root) {
|
|
|
39700
40056
|
}
|
|
39701
40057
|
|
|
39702
40058
|
// src/remote/hub.ts
|
|
39703
|
-
var
|
|
40059
|
+
var import_node_crypto23 = require("crypto");
|
|
39704
40060
|
init_protocol();
|
|
39705
40061
|
var CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
39706
40062
|
var CODE_TTL_MS = 10 * 60 * 1e3;
|
|
@@ -39711,7 +40067,7 @@ function send(socket, msg) {
|
|
|
39711
40067
|
}
|
|
39712
40068
|
}
|
|
39713
40069
|
function newCode() {
|
|
39714
|
-
const bytes = (0,
|
|
40070
|
+
const bytes = (0, import_node_crypto23.randomBytes)(6);
|
|
39715
40071
|
let code = "";
|
|
39716
40072
|
for (let i = 0; i < 6; i++) code += CODE_ALPHABET[bytes[i] % CODE_ALPHABET.length];
|
|
39717
40073
|
return code;
|
|
@@ -39970,7 +40326,7 @@ var RemoteHub = class {
|
|
|
39970
40326
|
host.phone = null;
|
|
39971
40327
|
}
|
|
39972
40328
|
const created = sessionToken == null;
|
|
39973
|
-
const token = sessionToken ?? (0,
|
|
40329
|
+
const token = sessionToken ?? (0, import_node_crypto23.randomBytes)(24).toString("hex");
|
|
39974
40330
|
if (host.sessionToken && host.sessionToken !== token) {
|
|
39975
40331
|
this.phonesByToken.delete(host.sessionToken);
|
|
39976
40332
|
}
|
|
@@ -40022,7 +40378,7 @@ var RemoteHub = class {
|
|
|
40022
40378
|
init_protocol();
|
|
40023
40379
|
|
|
40024
40380
|
// src/relay/accounts.ts
|
|
40025
|
-
var
|
|
40381
|
+
var import_node_crypto24 = require("crypto");
|
|
40026
40382
|
var import_node_fs70 = require("fs");
|
|
40027
40383
|
var import_node_module7 = require("module");
|
|
40028
40384
|
var import_node_path68 = require("path");
|
|
@@ -40041,12 +40397,12 @@ function openDatabase(filePath) {
|
|
|
40041
40397
|
return db;
|
|
40042
40398
|
}
|
|
40043
40399
|
function sha2562(value) {
|
|
40044
|
-
return (0,
|
|
40400
|
+
return (0, import_node_crypto24.createHash)("sha256").update(value).digest("hex");
|
|
40045
40401
|
}
|
|
40046
40402
|
function sameHash(a, b) {
|
|
40047
40403
|
const left = Buffer.from(a);
|
|
40048
40404
|
const right = Buffer.from(b);
|
|
40049
|
-
return left.length === right.length && (0,
|
|
40405
|
+
return left.length === right.length && (0, import_node_crypto24.timingSafeEqual)(left, right);
|
|
40050
40406
|
}
|
|
40051
40407
|
function normalizeEmail(email) {
|
|
40052
40408
|
const trimmed = email?.trim().toLowerCase() ?? "";
|
|
@@ -40151,7 +40507,7 @@ var RelayAccountStore = class {
|
|
|
40151
40507
|
this.insertIdentity(issuer, subject, accountId, email, verified);
|
|
40152
40508
|
} else {
|
|
40153
40509
|
const byEmail = verified ? this.accountIdForVerifiedEmail(email) : void 0;
|
|
40154
|
-
accountId = byEmail ?? (0,
|
|
40510
|
+
accountId = byEmail ?? (0, import_node_crypto24.randomUUID)();
|
|
40155
40511
|
if (!byEmail) {
|
|
40156
40512
|
this.db.prepare("INSERT INTO accounts (id, created_at, device_cap) VALUES (?, ?, ?)").run(accountId, Date.now(), RELAY_DEVICE_CAP);
|
|
40157
40513
|
}
|
|
@@ -40273,7 +40629,7 @@ var RelayAccountStore = class {
|
|
|
40273
40629
|
).run(issuer, subject, accountId, email, verified ? 1 : 0);
|
|
40274
40630
|
}
|
|
40275
40631
|
mintCredential(accountId) {
|
|
40276
|
-
const credential = (0,
|
|
40632
|
+
const credential = (0, import_node_crypto24.randomBytes)(32).toString("hex");
|
|
40277
40633
|
this.db.prepare("INSERT INTO credentials (token_hash, account_id, created_at) VALUES (?, ?, ?)").run(sha2562(credential), accountId, Date.now());
|
|
40278
40634
|
return credential;
|
|
40279
40635
|
}
|
|
@@ -40748,7 +41104,7 @@ async function startRelayServer(opts) {
|
|
|
40748
41104
|
sendJson2(res, 200, { ok: true, ...value.payload });
|
|
40749
41105
|
return true;
|
|
40750
41106
|
};
|
|
40751
|
-
const httpServer = (0,
|
|
41107
|
+
const httpServer = (0, import_node_http5.createServer)((req, res) => {
|
|
40752
41108
|
void (async () => {
|
|
40753
41109
|
const reqUrl = req.url || "/";
|
|
40754
41110
|
if (accountStore && await handleRelayAccountHttp({
|
|
@@ -41085,7 +41441,7 @@ async function bindAbort(signal, stop) {
|
|
|
41085
41441
|
}
|
|
41086
41442
|
function flatInterfaces() {
|
|
41087
41443
|
const out = [];
|
|
41088
|
-
for (const rows of Object.values((0,
|
|
41444
|
+
for (const rows of Object.values((0, import_node_os21.networkInterfaces)())) {
|
|
41089
41445
|
if (!rows) continue;
|
|
41090
41446
|
out.push(...rows);
|
|
41091
41447
|
}
|
|
@@ -41182,7 +41538,7 @@ init_stage_files();
|
|
|
41182
41538
|
init_consume_attachments();
|
|
41183
41539
|
|
|
41184
41540
|
// src/composer/pasted-text.ts
|
|
41185
|
-
var
|
|
41541
|
+
var import_node_crypto25 = require("crypto");
|
|
41186
41542
|
var PASTE_ATTACH_MIN_CHARS = 1200;
|
|
41187
41543
|
var PASTE_ATTACH_MIN_LINES = 15;
|
|
41188
41544
|
var PASTED_NAME_RE = /^Pasted text #(\d+)\.txt$/i;
|
|
@@ -41209,7 +41565,7 @@ function nextPastedTextName(existing) {
|
|
|
41209
41565
|
}
|
|
41210
41566
|
function buildPastedTextAttachment(text7, opts) {
|
|
41211
41567
|
return {
|
|
41212
|
-
id: opts?.id ?? (0,
|
|
41568
|
+
id: opts?.id ?? (0, import_node_crypto25.randomUUID)(),
|
|
41213
41569
|
name: opts?.name ?? "Pasted text #1.txt",
|
|
41214
41570
|
kind: "file",
|
|
41215
41571
|
path: opts?.path,
|
|
@@ -41385,7 +41741,7 @@ function createClippedMcpServer() {
|
|
|
41385
41741
|
|
|
41386
41742
|
// src/mcp/server.ts
|
|
41387
41743
|
var import_zod11 = require("zod");
|
|
41388
|
-
var
|
|
41744
|
+
var import_node_crypto28 = require("crypto");
|
|
41389
41745
|
var import_node_path73 = require("path");
|
|
41390
41746
|
init_orchestrator();
|
|
41391
41747
|
init_task_state();
|
|
@@ -42977,7 +43333,7 @@ function registerScheduleTools(server) {
|
|
|
42977
43333
|
}
|
|
42978
43334
|
|
|
42979
43335
|
// src/agent-rpc/handlers.ts
|
|
42980
|
-
var
|
|
43336
|
+
var import_node_crypto26 = require("crypto");
|
|
42981
43337
|
var import_node_path70 = require("path");
|
|
42982
43338
|
init_wait_for_job();
|
|
42983
43339
|
init_wait_for_turn();
|
|
@@ -43008,7 +43364,7 @@ setToolPermissionPublisher({
|
|
|
43008
43364
|
}
|
|
43009
43365
|
}
|
|
43010
43366
|
});
|
|
43011
|
-
function
|
|
43367
|
+
function asRecord16(value) {
|
|
43012
43368
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
43013
43369
|
return value;
|
|
43014
43370
|
}
|
|
@@ -43019,12 +43375,12 @@ function invalidParams(message) {
|
|
|
43019
43375
|
return Object.assign(new Error(message), { rpcCode: -32602 });
|
|
43020
43376
|
}
|
|
43021
43377
|
var handlePermissionAsk = async (params, _ctx) => {
|
|
43022
|
-
const rec =
|
|
43378
|
+
const rec = asRecord16(params);
|
|
43023
43379
|
const threadId = str6(rec.threadId).trim();
|
|
43024
43380
|
const toolName = str6(rec.toolName).trim();
|
|
43025
43381
|
if (!threadId) throw invalidParams("threadId is required");
|
|
43026
43382
|
if (!toolName) throw invalidParams("toolName is required");
|
|
43027
|
-
const input =
|
|
43383
|
+
const input = asRecord16(rec.input);
|
|
43028
43384
|
const ask = {
|
|
43029
43385
|
threadId,
|
|
43030
43386
|
toolName,
|
|
@@ -43060,7 +43416,7 @@ var handlePermissionAsk = async (params, _ctx) => {
|
|
|
43060
43416
|
// src/agent-rpc/handlers.ts
|
|
43061
43417
|
init_protocol2();
|
|
43062
43418
|
function presentArtifactResult(input) {
|
|
43063
|
-
const id = input.artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${(0,
|
|
43419
|
+
const id = input.artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${(0, import_node_crypto26.randomUUID)().slice(0, 8)}`;
|
|
43064
43420
|
return {
|
|
43065
43421
|
ok: true,
|
|
43066
43422
|
artifact_id: id,
|
|
@@ -43072,7 +43428,7 @@ function presentArtifactResult(input) {
|
|
|
43072
43428
|
message: input.type === "log" ? "Log accepted. Same artifact_id appends; send only new lines next time." : "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
|
|
43073
43429
|
};
|
|
43074
43430
|
}
|
|
43075
|
-
function
|
|
43431
|
+
function asRecord17(value) {
|
|
43076
43432
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
43077
43433
|
return value;
|
|
43078
43434
|
}
|
|
@@ -43096,7 +43452,7 @@ async function handleRuntimePing(_params, _ctx) {
|
|
|
43096
43452
|
};
|
|
43097
43453
|
}
|
|
43098
43454
|
async function handlePresentArtifact(params, _ctx) {
|
|
43099
|
-
const rec =
|
|
43455
|
+
const rec = asRecord17(params);
|
|
43100
43456
|
const title = str7(rec.title).trim();
|
|
43101
43457
|
const type = str7(rec.type).trim();
|
|
43102
43458
|
const allowed = ["html", "svg", "markdown", "react", "log"];
|
|
@@ -43120,7 +43476,7 @@ async function handlePresentArtifact(params, _ctx) {
|
|
|
43120
43476
|
});
|
|
43121
43477
|
}
|
|
43122
43478
|
async function handleJobWait(params, ctx, waitFn = waitForDetachedJob) {
|
|
43123
|
-
const rec =
|
|
43479
|
+
const rec = asRecord17(params);
|
|
43124
43480
|
const id = str7(rec.id).trim();
|
|
43125
43481
|
if (!id) throw invalidParams2("id is required");
|
|
43126
43482
|
const cwd = jobCwd(rec);
|
|
@@ -43144,7 +43500,7 @@ async function handleJobWait(params, ctx, waitFn = waitForDetachedJob) {
|
|
|
43144
43500
|
};
|
|
43145
43501
|
}
|
|
43146
43502
|
async function handleJobStop(params, _ctx) {
|
|
43147
|
-
const rec =
|
|
43503
|
+
const rec = asRecord17(params);
|
|
43148
43504
|
const id = str7(rec.id).trim();
|
|
43149
43505
|
if (!id) throw invalidParams2("id is required");
|
|
43150
43506
|
const reason = str7(rec.reason).trim() || void 0;
|
|
@@ -43172,7 +43528,7 @@ async function defaultTurnWait(ref, timeoutMs) {
|
|
|
43172
43528
|
});
|
|
43173
43529
|
}
|
|
43174
43530
|
async function handleTurnWait(params, ctx, waitFn = defaultTurnWait) {
|
|
43175
|
-
const rec =
|
|
43531
|
+
const rec = asRecord17(params);
|
|
43176
43532
|
const ref = str7(rec.ref).trim();
|
|
43177
43533
|
if (!ref) throw invalidParams2("ref is required");
|
|
43178
43534
|
const requested = typeof rec.timeoutMs === "number" && Number.isFinite(rec.timeoutMs) ? rec.timeoutMs : void 0;
|
|
@@ -43224,7 +43580,7 @@ init_worktree();
|
|
|
43224
43580
|
init_paths();
|
|
43225
43581
|
|
|
43226
43582
|
// src/board/board-pins.ts
|
|
43227
|
-
var
|
|
43583
|
+
var import_node_crypto27 = require("crypto");
|
|
43228
43584
|
var import_node_fs72 = require("fs");
|
|
43229
43585
|
var import_node_path71 = require("path");
|
|
43230
43586
|
init_paths();
|
|
@@ -43256,7 +43612,7 @@ function addBoardPin(input) {
|
|
|
43256
43612
|
const ref = input.ref.trim();
|
|
43257
43613
|
if (!ref) throw new Error("Board item needs a ref");
|
|
43258
43614
|
const pin = {
|
|
43259
|
-
id: (0,
|
|
43615
|
+
id: (0, import_node_crypto27.randomUUID)(),
|
|
43260
43616
|
kind: input.kind,
|
|
43261
43617
|
ref,
|
|
43262
43618
|
repoPath: input.repoPath.trim(),
|
|
@@ -44189,7 +44545,7 @@ async function startMcpServer() {
|
|
|
44189
44545
|
const ident = issue?.identifier ?? ref.trim();
|
|
44190
44546
|
const attachments = issue ? [
|
|
44191
44547
|
{
|
|
44192
|
-
id: (0,
|
|
44548
|
+
id: (0, import_node_crypto28.randomUUID)(),
|
|
44193
44549
|
name: issue.identifier,
|
|
44194
44550
|
kind: "issue",
|
|
44195
44551
|
content: [
|
|
@@ -44751,8 +45107,8 @@ init_protocol2();
|
|
|
44751
45107
|
init_metadata();
|
|
44752
45108
|
|
|
44753
45109
|
// src/agent-rpc/server.ts
|
|
44754
|
-
var
|
|
44755
|
-
var
|
|
45110
|
+
var import_node_crypto29 = require("crypto");
|
|
45111
|
+
var import_node_http6 = require("http");
|
|
44756
45112
|
var import_ws5 = require("ws");
|
|
44757
45113
|
init_protocol2();
|
|
44758
45114
|
init_metadata();
|
|
@@ -44760,7 +45116,7 @@ function tokensEqual(a, b) {
|
|
|
44760
45116
|
const left = Buffer.from(a);
|
|
44761
45117
|
const right = Buffer.from(b);
|
|
44762
45118
|
if (left.length !== right.length) return false;
|
|
44763
|
-
return (0,
|
|
45119
|
+
return (0, import_node_crypto29.timingSafeEqual)(left, right);
|
|
44764
45120
|
}
|
|
44765
45121
|
function authTokenFromUpgrade(req) {
|
|
44766
45122
|
try {
|
|
@@ -44793,16 +45149,16 @@ var AgentRpcServer = class {
|
|
|
44793
45149
|
async listen(opts = {}) {
|
|
44794
45150
|
const host = opts.host ?? "127.0.0.1";
|
|
44795
45151
|
const port = opts.port ?? 0;
|
|
44796
|
-
const authToken = (0,
|
|
45152
|
+
const authToken = (0, import_node_crypto29.randomBytes)(24).toString("base64url");
|
|
44797
45153
|
this.meta = {
|
|
44798
|
-
runtimeId: (0,
|
|
45154
|
+
runtimeId: (0, import_node_crypto29.randomUUID)(),
|
|
44799
45155
|
pid: process.pid,
|
|
44800
45156
|
protocolVersion: AGENT_RPC_PROTOCOL_VERSION,
|
|
44801
45157
|
authToken,
|
|
44802
45158
|
startedAt: Date.now(),
|
|
44803
45159
|
transports: []
|
|
44804
45160
|
};
|
|
44805
|
-
const http = (0,
|
|
45161
|
+
const http = (0, import_node_http6.createServer)((_req, res) => {
|
|
44806
45162
|
res.statusCode = 404;
|
|
44807
45163
|
res.end();
|
|
44808
45164
|
});
|
|
@@ -45288,6 +45644,8 @@ init_oauth();
|
|
|
45288
45644
|
init_injected_mcp();
|
|
45289
45645
|
init_user_mcp_config();
|
|
45290
45646
|
init_orch_mcp_isolation();
|
|
45647
|
+
init_host();
|
|
45648
|
+
init_model_context();
|
|
45291
45649
|
init_meta();
|
|
45292
45650
|
|
|
45293
45651
|
// src/slack/workspaces.ts
|
|
@@ -45386,7 +45744,7 @@ function slackTokenFor(ws, kind = "read") {
|
|
|
45386
45744
|
}
|
|
45387
45745
|
|
|
45388
45746
|
// src/slack/oauth.ts
|
|
45389
|
-
var
|
|
45747
|
+
var import_node_crypto30 = require("crypto");
|
|
45390
45748
|
init_app_settings();
|
|
45391
45749
|
var SLACK_BOT_SCOPES = [
|
|
45392
45750
|
"app_mentions:read",
|
|
@@ -45480,7 +45838,7 @@ async function startSlackOAuth(opts) {
|
|
|
45480
45838
|
throw new SlackOAuthCancelledError();
|
|
45481
45839
|
}
|
|
45482
45840
|
const { clientId } = slackOAuthCredentials();
|
|
45483
|
-
const state = (0,
|
|
45841
|
+
const state = (0, import_node_crypto30.randomBytes)(16).toString("hex");
|
|
45484
45842
|
const authorizeUrl = slackOAuthAuthorizeUrl(clientId, state);
|
|
45485
45843
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
45486
45844
|
const pollIntervalMs = opts?.pollIntervalMs ?? 400;
|
|
@@ -46389,7 +46747,7 @@ function resolveSlackListenMode(opts) {
|
|
|
46389
46747
|
init_protocol();
|
|
46390
46748
|
|
|
46391
46749
|
// src/relay/account-login.ts
|
|
46392
|
-
var
|
|
46750
|
+
var import_node_crypto31 = require("crypto");
|
|
46393
46751
|
init_fetch();
|
|
46394
46752
|
init_protocol();
|
|
46395
46753
|
var RemoteAccountLoginCancelled = class extends Error {
|
|
@@ -46457,7 +46815,7 @@ async function readJson4(res, url) {
|
|
|
46457
46815
|
async function startRemoteAccountLogin(opts) {
|
|
46458
46816
|
if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
|
|
46459
46817
|
const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
|
|
46460
|
-
const state = (0,
|
|
46818
|
+
const state = (0, import_node_crypto31.randomBytes)(16).toString("hex");
|
|
46461
46819
|
const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
|
|
46462
46820
|
const pollIntervalMs = opts.pollIntervalMs ?? 400;
|
|
46463
46821
|
const linkToken = opts.linkToken?.trim() ?? "";
|
|
@@ -47853,6 +48211,7 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
47853
48211
|
startRelayServer,
|
|
47854
48212
|
startRemoteAccountLogin,
|
|
47855
48213
|
startSlackOAuth,
|
|
48214
|
+
stashMcpAppModelContext,
|
|
47856
48215
|
statWorktreePath,
|
|
47857
48216
|
stopAgentRpcServer,
|
|
47858
48217
|
stripBrightsyNdjsonNoise,
|