@sideboard-ai/core 0.1.310 → 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-JXOW5JAW.js → chunk-LLTWP4PK.js} +53 -3
- package/dist/{chunk-VBVSJUM2.js → chunk-QC2TQMPJ.js} +31 -20
- package/dist/{chunk-IT6A4FZF.js → chunk-VIVXKN5N.js} +60 -4
- package/dist/{chunk-AILQRQ26.js → chunk-ZW7RSQHY.js} +25 -9
- package/dist/{conductor-AMZ5SKG2.js → conductor-CTWR6NH4.js} +1 -1
- package/dist/{conductor-OFXA5BST.js → conductor-YOBSYPLT.js} +1 -1
- package/dist/index.cjs +993 -570
- package/dist/index.d.cts +83 -17
- package/dist/index.d.ts +83 -17
- package/dist/index.js +51 -226
- package/dist/mcp/run-stdio.cjs +823 -124
- package/dist/mcp/run-stdio.js +3 -3
- package/dist/{orchestrator-XFE3U3RP.js → orchestrator-BYTSILLH.js} +3 -3
- package/dist/{orchestrator-7374OI7T.js → orchestrator-S44BMNN7.js} +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6720,6 +6720,191 @@ var init_message_parts = __esm({
|
|
|
6720
6720
|
}
|
|
6721
6721
|
});
|
|
6722
6722
|
|
|
6723
|
+
// src/plan/ask-user.ts
|
|
6724
|
+
function planQuestionsSignature(questions2) {
|
|
6725
|
+
return questions2.map((q) => {
|
|
6726
|
+
const opts = q.options.map((o) => o.label).join("");
|
|
6727
|
+
return `${q.question}${opts}`;
|
|
6728
|
+
}).join("");
|
|
6729
|
+
}
|
|
6730
|
+
function asRecord2(v) {
|
|
6731
|
+
return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
6732
|
+
}
|
|
6733
|
+
function parseOptions(raw) {
|
|
6734
|
+
if (!Array.isArray(raw)) return [];
|
|
6735
|
+
const out = [];
|
|
6736
|
+
for (const item of raw) {
|
|
6737
|
+
if (typeof item === "string" && item.trim()) {
|
|
6738
|
+
out.push({ label: item.trim() });
|
|
6739
|
+
continue;
|
|
6740
|
+
}
|
|
6741
|
+
const o = asRecord2(item);
|
|
6742
|
+
if (!o) continue;
|
|
6743
|
+
const label = typeof o.label === "string" ? o.label.trim() : typeof o.text === "string" ? o.text.trim() : typeof o.title === "string" ? o.title.trim() : "";
|
|
6744
|
+
if (!label) continue;
|
|
6745
|
+
const description = typeof o.description === "string" && o.description.trim() ? o.description.trim() : void 0;
|
|
6746
|
+
out.push({ label, description });
|
|
6747
|
+
}
|
|
6748
|
+
return out;
|
|
6749
|
+
}
|
|
6750
|
+
function parseOneQuestion(raw) {
|
|
6751
|
+
const o = asRecord2(raw);
|
|
6752
|
+
if (!o) return null;
|
|
6753
|
+
const question = typeof o.question === "string" ? o.question.trim() : typeof o.text === "string" ? o.text.trim() : typeof o.prompt === "string" ? o.prompt.trim() : "";
|
|
6754
|
+
if (!question) return null;
|
|
6755
|
+
const options = parseOptions(o.options);
|
|
6756
|
+
if (options.length < 1) return null;
|
|
6757
|
+
const header = typeof o.header === "string" && o.header.trim() ? o.header.trim() : void 0;
|
|
6758
|
+
const multiSelect = Boolean(o.multiSelect ?? o.multi_select);
|
|
6759
|
+
return { question, header, multiSelect, options };
|
|
6760
|
+
}
|
|
6761
|
+
function parsePlanQuestionsInput(input) {
|
|
6762
|
+
const root = asRecord2(input);
|
|
6763
|
+
if (!root) return [];
|
|
6764
|
+
const list = Array.isArray(root.questions) ? root.questions : Array.isArray(root.question) ? root.question : root.question || root.prompt ? [root] : [];
|
|
6765
|
+
const out = [];
|
|
6766
|
+
for (const item of list) {
|
|
6767
|
+
const q = parseOneQuestion(item);
|
|
6768
|
+
if (q) out.push(q);
|
|
6769
|
+
}
|
|
6770
|
+
return out;
|
|
6771
|
+
}
|
|
6772
|
+
function isAskUserToolName(name) {
|
|
6773
|
+
if (!name) return false;
|
|
6774
|
+
const base = name.replace(/^mcp__sideboard__/i, "");
|
|
6775
|
+
return ASK_USER_TOOL_RE.test(name) || /^ask_user$/i.test(base);
|
|
6776
|
+
}
|
|
6777
|
+
function lastTopLevelToolIsAskUser(parts) {
|
|
6778
|
+
if (!parts?.length) return false;
|
|
6779
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
6780
|
+
const part = parts[i];
|
|
6781
|
+
if (part.type === "tool" && !part.parentId) {
|
|
6782
|
+
return isAskUserToolName(part.name);
|
|
6783
|
+
}
|
|
6784
|
+
}
|
|
6785
|
+
return false;
|
|
6786
|
+
}
|
|
6787
|
+
function hasTopLevelTool(parts) {
|
|
6788
|
+
return Boolean(parts?.some((part) => part.type === "tool" && !part.parentId));
|
|
6789
|
+
}
|
|
6790
|
+
function questionsFromToolPart(part) {
|
|
6791
|
+
const fromInput = parsePlanQuestionsInput(part.input);
|
|
6792
|
+
if (fromInput.length) return fromInput;
|
|
6793
|
+
const raw = part.result?.trim();
|
|
6794
|
+
if (!raw || !raw.startsWith("{")) return [];
|
|
6795
|
+
try {
|
|
6796
|
+
return parsePlanQuestionsInput(JSON.parse(raw));
|
|
6797
|
+
} catch {
|
|
6798
|
+
return [];
|
|
6799
|
+
}
|
|
6800
|
+
}
|
|
6801
|
+
function extractPendingPlanQuestions(parts) {
|
|
6802
|
+
if (!parts?.length) return null;
|
|
6803
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
6804
|
+
const p = parts[i];
|
|
6805
|
+
if (p.type !== "tool" || !isAskUserToolName(p.name)) continue;
|
|
6806
|
+
const questions2 = questionsFromToolPart(p);
|
|
6807
|
+
if (!questions2.length) continue;
|
|
6808
|
+
return {
|
|
6809
|
+
id: p.id || `ask-${i}`,
|
|
6810
|
+
signature: planQuestionsSignature(questions2),
|
|
6811
|
+
questions: questions2,
|
|
6812
|
+
source: p.name || "ask_user"
|
|
6813
|
+
};
|
|
6814
|
+
}
|
|
6815
|
+
return null;
|
|
6816
|
+
}
|
|
6817
|
+
function pendingFromAskBlock(block, dismissedQuestionSignature) {
|
|
6818
|
+
if (!block || block.source !== "ask_user" || !block.questions?.length) return null;
|
|
6819
|
+
const dismissed = dismissedQuestionSignature?.trim();
|
|
6820
|
+
if (dismissed && (!block.questionSignature || block.questionSignature === dismissed)) {
|
|
6821
|
+
return null;
|
|
6822
|
+
}
|
|
6823
|
+
const signature = block.questionSignature?.trim() || planQuestionsSignature(block.questions);
|
|
6824
|
+
return {
|
|
6825
|
+
id: `ask-block:${signature}`,
|
|
6826
|
+
signature,
|
|
6827
|
+
questions: block.questions,
|
|
6828
|
+
source: "ask_user"
|
|
6829
|
+
};
|
|
6830
|
+
}
|
|
6831
|
+
function askBlockStillWaiting(block, messages) {
|
|
6832
|
+
if (!messages?.length) return Boolean(block?.at);
|
|
6833
|
+
const askedAt = block?.at;
|
|
6834
|
+
if (!askedAt) return false;
|
|
6835
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
6836
|
+
const message = messages[i];
|
|
6837
|
+
if (message.role !== "user" || message.origin === "continue") continue;
|
|
6838
|
+
if (!message.ts) return true;
|
|
6839
|
+
return askedAt > message.ts;
|
|
6840
|
+
}
|
|
6841
|
+
return true;
|
|
6842
|
+
}
|
|
6843
|
+
function latestPendingPlanQuestions(input) {
|
|
6844
|
+
if (input.userReplied) return null;
|
|
6845
|
+
const fromBlock = () => pendingFromAskBlock(input.agentBlock, input.dismissedQuestionSignature);
|
|
6846
|
+
if (lastTopLevelToolIsAskUser(input.liveParts)) {
|
|
6847
|
+
return extractPendingPlanQuestions(input.liveParts) ?? fromBlock();
|
|
6848
|
+
}
|
|
6849
|
+
const last = input.messages[input.messages.length - 1];
|
|
6850
|
+
if (last?.role === "agent" && lastTopLevelToolIsAskUser(last.parts)) {
|
|
6851
|
+
return extractPendingPlanQuestions(last.parts) ?? fromBlock();
|
|
6852
|
+
}
|
|
6853
|
+
if (hasTopLevelTool(input.liveParts) || last?.role === "agent" && hasTopLevelTool(last.parts)) {
|
|
6854
|
+
return null;
|
|
6855
|
+
}
|
|
6856
|
+
if (input.status === "running" || input.status === "queued") return null;
|
|
6857
|
+
const stamped = fromBlock();
|
|
6858
|
+
if (stamped && askBlockStillWaiting(input.agentBlock, input.messages)) {
|
|
6859
|
+
return stamped;
|
|
6860
|
+
}
|
|
6861
|
+
return null;
|
|
6862
|
+
}
|
|
6863
|
+
function isPlanQuestionAnswersMessage(text7) {
|
|
6864
|
+
return text7.startsWith(PLAN_QUESTION_ANSWERS_PREFIX);
|
|
6865
|
+
}
|
|
6866
|
+
function formatPlanQuestionAnswers(questions2, answers) {
|
|
6867
|
+
const lines = [PLAN_QUESTION_ANSWERS_PREFIX, ""];
|
|
6868
|
+
for (let i = 0; i < questions2.length; i++) {
|
|
6869
|
+
const q = questions2[i];
|
|
6870
|
+
const a = answers.find((x) => x.questionIndex === i);
|
|
6871
|
+
const header = q.header ? `**${q.header}** \u2014 ` : "";
|
|
6872
|
+
const parts = [];
|
|
6873
|
+
if (a?.selected.length) parts.push(a.selected.join(", "));
|
|
6874
|
+
if (a?.other?.trim()) parts.push(a.other.trim());
|
|
6875
|
+
const body = parts.length ? parts.join(" \xB7 ") : "(no answer)";
|
|
6876
|
+
lines.push(`${i + 1}. ${header}${q.question} `);
|
|
6877
|
+
lines.push(` \u2192 ${body}`);
|
|
6878
|
+
}
|
|
6879
|
+
return lines.join("\n");
|
|
6880
|
+
}
|
|
6881
|
+
function formatPlanQuestionsForChat(questions2) {
|
|
6882
|
+
const lines = ["### Questions for you", ""];
|
|
6883
|
+
for (let i = 0; i < questions2.length; i++) {
|
|
6884
|
+
const q = questions2[i];
|
|
6885
|
+
const header = q.header ? `**${q.header}** \u2014 ` : "";
|
|
6886
|
+
lines.push(`${i + 1}. ${header}${q.question}`);
|
|
6887
|
+
for (let oi = 0; oi < q.options.length; oi++) {
|
|
6888
|
+
const opt = q.options[oi];
|
|
6889
|
+
const desc = opt.description?.trim();
|
|
6890
|
+
lines.push(
|
|
6891
|
+
desc ? ` - **${opt.label}** \u2014 ${desc}` : ` - **${opt.label}**`
|
|
6892
|
+
);
|
|
6893
|
+
}
|
|
6894
|
+
lines.push("");
|
|
6895
|
+
}
|
|
6896
|
+
lines.push("_Answer in the composer below._");
|
|
6897
|
+
return lines.join("\n").trimEnd();
|
|
6898
|
+
}
|
|
6899
|
+
var ASK_USER_TOOL_RE, PLAN_QUESTION_ANSWERS_PREFIX;
|
|
6900
|
+
var init_ask_user = __esm({
|
|
6901
|
+
"src/plan/ask-user.ts"() {
|
|
6902
|
+
"use strict";
|
|
6903
|
+
ASK_USER_TOOL_RE = /^(AskUserQuestion|ask_user|mcp__sideboard__ask_user)$/i;
|
|
6904
|
+
PLAN_QUESTION_ANSWERS_PREFIX = "Answers to your questions:";
|
|
6905
|
+
}
|
|
6906
|
+
});
|
|
6907
|
+
|
|
6723
6908
|
// src/board/agent-block-view.ts
|
|
6724
6909
|
function worktreeBoardStatus(group) {
|
|
6725
6910
|
const order = ["running", "queued", "error", "broken"];
|
|
@@ -6742,6 +6927,11 @@ function visibleAgentBlock(thread) {
|
|
|
6742
6927
|
const block = thread.agentBlock;
|
|
6743
6928
|
if (!block?.reason?.trim()) return null;
|
|
6744
6929
|
if (isDismissedAskUserBlock(block, thread.dismissedQuestionSignature)) return null;
|
|
6930
|
+
if (block.source === "ask_user") {
|
|
6931
|
+
const inFlight = thread.status === "running" || thread.status === "queued";
|
|
6932
|
+
if (inFlight && !block.onScreen) return null;
|
|
6933
|
+
if (!askBlockStillWaiting(block, thread.messages)) return null;
|
|
6934
|
+
}
|
|
6745
6935
|
return block;
|
|
6746
6936
|
}
|
|
6747
6937
|
function worktreeAgentBlock(group) {
|
|
@@ -6777,6 +6967,7 @@ function threadCardBlockFields(group) {
|
|
|
6777
6967
|
var init_agent_block_view = __esm({
|
|
6778
6968
|
"src/board/agent-block-view.ts"() {
|
|
6779
6969
|
"use strict";
|
|
6970
|
+
init_ask_user();
|
|
6780
6971
|
}
|
|
6781
6972
|
});
|
|
6782
6973
|
|
|
@@ -8309,175 +8500,6 @@ var init_injected_notices = __esm({
|
|
|
8309
8500
|
}
|
|
8310
8501
|
});
|
|
8311
8502
|
|
|
8312
|
-
// src/plan/ask-user.ts
|
|
8313
|
-
function planQuestionsSignature(questions2) {
|
|
8314
|
-
return questions2.map((q) => {
|
|
8315
|
-
const opts = q.options.map((o) => o.label).join("");
|
|
8316
|
-
return `${q.question}${opts}`;
|
|
8317
|
-
}).join("");
|
|
8318
|
-
}
|
|
8319
|
-
function asRecord2(v) {
|
|
8320
|
-
return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
8321
|
-
}
|
|
8322
|
-
function parseOptions(raw) {
|
|
8323
|
-
if (!Array.isArray(raw)) return [];
|
|
8324
|
-
const out = [];
|
|
8325
|
-
for (const item of raw) {
|
|
8326
|
-
if (typeof item === "string" && item.trim()) {
|
|
8327
|
-
out.push({ label: item.trim() });
|
|
8328
|
-
continue;
|
|
8329
|
-
}
|
|
8330
|
-
const o = asRecord2(item);
|
|
8331
|
-
if (!o) continue;
|
|
8332
|
-
const label = typeof o.label === "string" ? o.label.trim() : typeof o.text === "string" ? o.text.trim() : typeof o.title === "string" ? o.title.trim() : "";
|
|
8333
|
-
if (!label) continue;
|
|
8334
|
-
const description = typeof o.description === "string" && o.description.trim() ? o.description.trim() : void 0;
|
|
8335
|
-
out.push({ label, description });
|
|
8336
|
-
}
|
|
8337
|
-
return out;
|
|
8338
|
-
}
|
|
8339
|
-
function parseOneQuestion(raw) {
|
|
8340
|
-
const o = asRecord2(raw);
|
|
8341
|
-
if (!o) return null;
|
|
8342
|
-
const question = typeof o.question === "string" ? o.question.trim() : typeof o.text === "string" ? o.text.trim() : typeof o.prompt === "string" ? o.prompt.trim() : "";
|
|
8343
|
-
if (!question) return null;
|
|
8344
|
-
const options = parseOptions(o.options);
|
|
8345
|
-
if (options.length < 1) return null;
|
|
8346
|
-
const header = typeof o.header === "string" && o.header.trim() ? o.header.trim() : void 0;
|
|
8347
|
-
const multiSelect = Boolean(o.multiSelect ?? o.multi_select);
|
|
8348
|
-
return { question, header, multiSelect, options };
|
|
8349
|
-
}
|
|
8350
|
-
function parsePlanQuestionsInput(input) {
|
|
8351
|
-
const root = asRecord2(input);
|
|
8352
|
-
if (!root) return [];
|
|
8353
|
-
const list = Array.isArray(root.questions) ? root.questions : Array.isArray(root.question) ? root.question : root.question || root.prompt ? [root] : [];
|
|
8354
|
-
const out = [];
|
|
8355
|
-
for (const item of list) {
|
|
8356
|
-
const q = parseOneQuestion(item);
|
|
8357
|
-
if (q) out.push(q);
|
|
8358
|
-
}
|
|
8359
|
-
return out;
|
|
8360
|
-
}
|
|
8361
|
-
function isAskUserToolName(name) {
|
|
8362
|
-
if (!name) return false;
|
|
8363
|
-
const base = name.replace(/^mcp__sideboard__/i, "");
|
|
8364
|
-
return ASK_USER_TOOL_RE.test(name) || /^ask_user$/i.test(base);
|
|
8365
|
-
}
|
|
8366
|
-
function questionsFromToolPart(part) {
|
|
8367
|
-
const fromInput = parsePlanQuestionsInput(part.input);
|
|
8368
|
-
if (fromInput.length) return fromInput;
|
|
8369
|
-
const raw = part.result?.trim();
|
|
8370
|
-
if (!raw || !raw.startsWith("{")) return [];
|
|
8371
|
-
try {
|
|
8372
|
-
return parsePlanQuestionsInput(JSON.parse(raw));
|
|
8373
|
-
} catch {
|
|
8374
|
-
return [];
|
|
8375
|
-
}
|
|
8376
|
-
}
|
|
8377
|
-
function extractPendingPlanQuestions(parts) {
|
|
8378
|
-
if (!parts?.length) return null;
|
|
8379
|
-
for (let i = parts.length - 1; i >= 0; i--) {
|
|
8380
|
-
const p = parts[i];
|
|
8381
|
-
if (p.type !== "tool" || !isAskUserToolName(p.name)) continue;
|
|
8382
|
-
const questions2 = questionsFromToolPart(p);
|
|
8383
|
-
if (!questions2.length) continue;
|
|
8384
|
-
return {
|
|
8385
|
-
id: p.id || `ask-${i}`,
|
|
8386
|
-
signature: planQuestionsSignature(questions2),
|
|
8387
|
-
questions: questions2,
|
|
8388
|
-
source: p.name || "ask_user"
|
|
8389
|
-
};
|
|
8390
|
-
}
|
|
8391
|
-
return null;
|
|
8392
|
-
}
|
|
8393
|
-
function pendingFromAskBlock(block, dismissedQuestionSignature) {
|
|
8394
|
-
if (!block || block.source !== "ask_user" || !block.questions?.length) return null;
|
|
8395
|
-
const dismissed = dismissedQuestionSignature?.trim();
|
|
8396
|
-
if (dismissed && (!block.questionSignature || block.questionSignature === dismissed)) {
|
|
8397
|
-
return null;
|
|
8398
|
-
}
|
|
8399
|
-
const signature = block.questionSignature?.trim() || planQuestionsSignature(block.questions);
|
|
8400
|
-
return {
|
|
8401
|
-
id: `ask-block:${signature}`,
|
|
8402
|
-
signature,
|
|
8403
|
-
questions: block.questions,
|
|
8404
|
-
source: "ask_user"
|
|
8405
|
-
};
|
|
8406
|
-
}
|
|
8407
|
-
function askBlockStillWaiting(block, messages) {
|
|
8408
|
-
const askedAt = block?.at;
|
|
8409
|
-
if (!askedAt) return false;
|
|
8410
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8411
|
-
const message = messages[i];
|
|
8412
|
-
if (message.role !== "user" || message.origin === "continue") continue;
|
|
8413
|
-
if (!message.ts) return true;
|
|
8414
|
-
return askedAt > message.ts;
|
|
8415
|
-
}
|
|
8416
|
-
return true;
|
|
8417
|
-
}
|
|
8418
|
-
function latestPendingPlanQuestions(input) {
|
|
8419
|
-
if (input.userReplied) return null;
|
|
8420
|
-
const fromLive = extractPendingPlanQuestions(input.liveParts);
|
|
8421
|
-
if (fromLive) return fromLive;
|
|
8422
|
-
const last = input.messages[input.messages.length - 1];
|
|
8423
|
-
if (last?.role === "agent") {
|
|
8424
|
-
const fromParts = extractPendingPlanQuestions(last.parts);
|
|
8425
|
-
if (fromParts) return fromParts;
|
|
8426
|
-
}
|
|
8427
|
-
const fromBlock = pendingFromAskBlock(
|
|
8428
|
-
input.agentBlock,
|
|
8429
|
-
input.dismissedQuestionSignature
|
|
8430
|
-
);
|
|
8431
|
-
if (fromBlock && askBlockStillWaiting(input.agentBlock, input.messages)) {
|
|
8432
|
-
return fromBlock;
|
|
8433
|
-
}
|
|
8434
|
-
return null;
|
|
8435
|
-
}
|
|
8436
|
-
function isPlanQuestionAnswersMessage(text7) {
|
|
8437
|
-
return text7.startsWith(PLAN_QUESTION_ANSWERS_PREFIX);
|
|
8438
|
-
}
|
|
8439
|
-
function formatPlanQuestionAnswers(questions2, answers) {
|
|
8440
|
-
const lines = [PLAN_QUESTION_ANSWERS_PREFIX, ""];
|
|
8441
|
-
for (let i = 0; i < questions2.length; i++) {
|
|
8442
|
-
const q = questions2[i];
|
|
8443
|
-
const a = answers.find((x) => x.questionIndex === i);
|
|
8444
|
-
const header = q.header ? `**${q.header}** \u2014 ` : "";
|
|
8445
|
-
const parts = [];
|
|
8446
|
-
if (a?.selected.length) parts.push(a.selected.join(", "));
|
|
8447
|
-
if (a?.other?.trim()) parts.push(a.other.trim());
|
|
8448
|
-
const body = parts.length ? parts.join(" \xB7 ") : "(no answer)";
|
|
8449
|
-
lines.push(`${i + 1}. ${header}${q.question} `);
|
|
8450
|
-
lines.push(` \u2192 ${body}`);
|
|
8451
|
-
}
|
|
8452
|
-
return lines.join("\n");
|
|
8453
|
-
}
|
|
8454
|
-
function formatPlanQuestionsForChat(questions2) {
|
|
8455
|
-
const lines = ["### Questions for you", ""];
|
|
8456
|
-
for (let i = 0; i < questions2.length; i++) {
|
|
8457
|
-
const q = questions2[i];
|
|
8458
|
-
const header = q.header ? `**${q.header}** \u2014 ` : "";
|
|
8459
|
-
lines.push(`${i + 1}. ${header}${q.question}`);
|
|
8460
|
-
for (let oi = 0; oi < q.options.length; oi++) {
|
|
8461
|
-
const opt = q.options[oi];
|
|
8462
|
-
const desc = opt.description?.trim();
|
|
8463
|
-
lines.push(
|
|
8464
|
-
desc ? ` - **${opt.label}** \u2014 ${desc}` : ` - **${opt.label}**`
|
|
8465
|
-
);
|
|
8466
|
-
}
|
|
8467
|
-
lines.push("");
|
|
8468
|
-
}
|
|
8469
|
-
lines.push("_Answer in the composer below._");
|
|
8470
|
-
return lines.join("\n").trimEnd();
|
|
8471
|
-
}
|
|
8472
|
-
var ASK_USER_TOOL_RE, PLAN_QUESTION_ANSWERS_PREFIX;
|
|
8473
|
-
var init_ask_user = __esm({
|
|
8474
|
-
"src/plan/ask-user.ts"() {
|
|
8475
|
-
"use strict";
|
|
8476
|
-
ASK_USER_TOOL_RE = /^(AskUserQuestion|ask_user|mcp__sideboard__ask_user)$/i;
|
|
8477
|
-
PLAN_QUESTION_ANSWERS_PREFIX = "Answers to your questions:";
|
|
8478
|
-
}
|
|
8479
|
-
});
|
|
8480
|
-
|
|
8481
8503
|
// src/orchestrator/task-state.ts
|
|
8482
8504
|
function isTerminalTaskState(state) {
|
|
8483
8505
|
return state !== "submitted" && state !== "working";
|
|
@@ -8489,14 +8511,7 @@ function needsCoordinatorAction(state) {
|
|
|
8489
8511
|
return isIncompleteTaskState(state) || state === "input-required";
|
|
8490
8512
|
}
|
|
8491
8513
|
function endedOnAskUser(parts) {
|
|
8492
|
-
|
|
8493
|
-
for (let i = parts.length - 1; i >= 0; i--) {
|
|
8494
|
-
const p = parts[i];
|
|
8495
|
-
if (p.type === "tool" && !p.parentId) {
|
|
8496
|
-
return isAskUserToolName(p.name);
|
|
8497
|
-
}
|
|
8498
|
-
}
|
|
8499
|
-
return false;
|
|
8514
|
+
return lastTopLevelToolIsAskUser(parts);
|
|
8500
8515
|
}
|
|
8501
8516
|
function deriveTaskState(input) {
|
|
8502
8517
|
if (input.stillRunning) {
|
|
@@ -13854,18 +13869,18 @@ function mcpUiContentSecurityPolicy(csp) {
|
|
|
13854
13869
|
const connect = (csp?.connectDomains ?? []).join(" ");
|
|
13855
13870
|
const frames = csp?.frameDomains?.length ? csp.frameDomains.join(" ") : "'none'";
|
|
13856
13871
|
const base = csp?.baseUriDomains?.length ? csp.baseUriDomains.join(" ") : "'none'";
|
|
13872
|
+
const connectSrc = connect ? `'self' ${connect}`.trim() : "'none'";
|
|
13857
13873
|
return [
|
|
13858
13874
|
"default-src 'none'",
|
|
13859
|
-
`script-src 'self' 'unsafe-inline'
|
|
13875
|
+
`script-src 'self' 'unsafe-inline' ${resource}`.trim(),
|
|
13860
13876
|
`style-src 'self' 'unsafe-inline' ${resource}`.trim(),
|
|
13861
|
-
`img-src 'self' data:
|
|
13862
|
-
`font-src 'self'
|
|
13863
|
-
`connect-src
|
|
13864
|
-
`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(),
|
|
13865
13881
|
`frame-src ${frames}`,
|
|
13866
13882
|
`base-uri ${base}`,
|
|
13867
|
-
"object-src 'none'"
|
|
13868
|
-
"form-action 'self'"
|
|
13883
|
+
"object-src 'none'"
|
|
13869
13884
|
].join("; ");
|
|
13870
13885
|
}
|
|
13871
13886
|
function htmlText(text7, blob) {
|
|
@@ -13902,8 +13917,10 @@ function originList(value) {
|
|
|
13902
13917
|
return out;
|
|
13903
13918
|
}
|
|
13904
13919
|
function originToken(value) {
|
|
13920
|
+
const trimmed = value.trim();
|
|
13921
|
+
if (/^(https?|wss?):\/\/\*\.[a-z0-9.-]+(?::\d+)?$/i.test(trimmed)) return trimmed;
|
|
13905
13922
|
try {
|
|
13906
|
-
const url = new URL(
|
|
13923
|
+
const url = new URL(trimmed);
|
|
13907
13924
|
if (url.protocol !== "https:" && url.protocol !== "http:" && url.protocol !== "wss:" && url.protocol !== "ws:") {
|
|
13908
13925
|
return null;
|
|
13909
13926
|
}
|
|
@@ -15264,6 +15281,524 @@ var init_orch_mcp_isolation = __esm({
|
|
|
15264
15281
|
}
|
|
15265
15282
|
});
|
|
15266
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
|
+
|
|
15267
15802
|
// src/agents/types.ts
|
|
15268
15803
|
function planModeTurnInstruction(planMode) {
|
|
15269
15804
|
return planMode ? PLAN_MODE_INSTRUCTION : PLAN_MODE_OFF_INSTRUCTION;
|
|
@@ -15459,7 +15994,7 @@ function entryDir() {
|
|
|
15459
15994
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
15460
15995
|
if (cjsDir) return cjsDir;
|
|
15461
15996
|
try {
|
|
15462
|
-
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));
|
|
15463
15998
|
} catch {
|
|
15464
15999
|
try {
|
|
15465
16000
|
const req = (0, import_node_module2.createRequire)(process.cwd() + "/");
|
|
@@ -15509,7 +16044,7 @@ async function buildClaudeRpcTurnCommand(req) {
|
|
|
15509
16044
|
}
|
|
15510
16045
|
};
|
|
15511
16046
|
}
|
|
15512
|
-
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;
|
|
15513
16048
|
var init_claude_host = __esm({
|
|
15514
16049
|
"src/agents/claude-host.ts"() {
|
|
15515
16050
|
"use strict";
|
|
@@ -15521,7 +16056,7 @@ var init_claude_host = __esm({
|
|
|
15521
16056
|
init_pilot_tools();
|
|
15522
16057
|
init_node_launch();
|
|
15523
16058
|
init_packaged_runtime();
|
|
15524
|
-
|
|
16059
|
+
import_meta5 = {};
|
|
15525
16060
|
}
|
|
15526
16061
|
});
|
|
15527
16062
|
|
|
@@ -15924,16 +16459,15 @@ function parseIssuesJson(raw) {
|
|
|
15924
16459
|
}
|
|
15925
16460
|
return [];
|
|
15926
16461
|
}
|
|
15927
|
-
var import_node_fs39,
|
|
16462
|
+
var import_node_fs39, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
15928
16463
|
var init_claude = __esm({
|
|
15929
16464
|
"src/agents/claude.ts"() {
|
|
15930
16465
|
"use strict";
|
|
15931
16466
|
import_node_fs39 = require("fs");
|
|
15932
|
-
import_node_os16 = require("os");
|
|
15933
16467
|
init_run();
|
|
15934
16468
|
init_app_settings();
|
|
15935
16469
|
init_claude_mcp();
|
|
15936
|
-
|
|
16470
|
+
init_host();
|
|
15937
16471
|
init_error_detail();
|
|
15938
16472
|
init_message_parts();
|
|
15939
16473
|
init_injected_mcp();
|
|
@@ -16010,7 +16544,7 @@ var init_claude = __esm({
|
|
|
16010
16544
|
});
|
|
16011
16545
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
16012
16546
|
const chromeOn = claudeChromeEnabled();
|
|
16013
|
-
const userMcpEntries =
|
|
16547
|
+
const userMcpEntries = await proxyClaudeUserMcp(isOrchestrator, [thread.repoPath, thread.worktreePath]);
|
|
16014
16548
|
let allowedTools;
|
|
16015
16549
|
if (isOrchestrator) {
|
|
16016
16550
|
allowedTools = [
|
|
@@ -16312,7 +16846,7 @@ function unwrapCodexMcpResult(result) {
|
|
|
16312
16846
|
return String(result);
|
|
16313
16847
|
}
|
|
16314
16848
|
}
|
|
16315
|
-
function
|
|
16849
|
+
function asRecord5(value) {
|
|
16316
16850
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
16317
16851
|
return value;
|
|
16318
16852
|
}
|
|
@@ -16492,7 +17026,7 @@ var init_codex = __esm({
|
|
|
16492
17026
|
}
|
|
16493
17027
|
if (itemType === "mcp_tool_call" && item.id && item.server && item.tool) {
|
|
16494
17028
|
const name = `mcp__${item.server}__${item.tool}`;
|
|
16495
|
-
const input =
|
|
17029
|
+
const input = asRecord5(item.arguments);
|
|
16496
17030
|
const events = [
|
|
16497
17031
|
{ type: "tool_use", id: item.id, name, input }
|
|
16498
17032
|
];
|
|
@@ -16639,7 +17173,7 @@ function thisModuleFile() {
|
|
|
16639
17173
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
16640
17174
|
if (cjsDir) return (0, import_node_path43.join)(cjsDir, "cursor-sdk-resolve.js");
|
|
16641
17175
|
try {
|
|
16642
|
-
return (0, import_node_url3.fileURLToPath)(
|
|
17176
|
+
return (0, import_node_url3.fileURLToPath)(import_meta6.url);
|
|
16643
17177
|
} catch {
|
|
16644
17178
|
return (0, import_node_path43.join)(process.cwd(), "package.json");
|
|
16645
17179
|
}
|
|
@@ -16738,7 +17272,7 @@ function cursorSdkRipgrepCandidate(opts) {
|
|
|
16738
17272
|
const nested = (0, import_node_path43.join)(root, "node_modules", pkg, "bin", bin);
|
|
16739
17273
|
return (0, import_node_fs41.existsSync)(nested) ? nested : null;
|
|
16740
17274
|
}
|
|
16741
|
-
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;
|
|
16742
17276
|
var init_cursor_sdk_resolve = __esm({
|
|
16743
17277
|
"src/agents/cursor-sdk-resolve.ts"() {
|
|
16744
17278
|
"use strict";
|
|
@@ -16747,7 +17281,7 @@ var init_cursor_sdk_resolve = __esm({
|
|
|
16747
17281
|
import_node_path43 = require("path");
|
|
16748
17282
|
import_node_url3 = require("url");
|
|
16749
17283
|
init_path();
|
|
16750
|
-
|
|
17284
|
+
import_meta6 = {};
|
|
16751
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.";
|
|
16752
17286
|
}
|
|
16753
17287
|
});
|
|
@@ -16797,20 +17331,20 @@ function turnCostUsdFromCursorUsage(before, after) {
|
|
|
16797
17331
|
if (!(delta >= 0) || !Number.isFinite(delta)) return void 0;
|
|
16798
17332
|
return delta / 100;
|
|
16799
17333
|
}
|
|
16800
|
-
function
|
|
17334
|
+
function asRecord6(value) {
|
|
16801
17335
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
16802
17336
|
return value;
|
|
16803
17337
|
}
|
|
16804
17338
|
return void 0;
|
|
16805
17339
|
}
|
|
16806
17340
|
function normalizeCursorToolCall(name, args) {
|
|
16807
|
-
const raw =
|
|
17341
|
+
const raw = asRecord6(args);
|
|
16808
17342
|
const toolName = typeof raw?.toolName === "string" && raw.toolName.trim() ? raw.toolName.trim() : null;
|
|
16809
|
-
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);
|
|
16810
17344
|
if (looksLikeMcp && toolName) {
|
|
16811
17345
|
const providerRaw = typeof raw.providerIdentifier === "string" && raw.providerIdentifier.trim() ? raw.providerIdentifier.trim() : "sideboard";
|
|
16812
17346
|
const provider = providerRaw.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
16813
|
-
const nested =
|
|
17347
|
+
const nested = asRecord6(raw.args);
|
|
16814
17348
|
return {
|
|
16815
17349
|
name: `mcp__${provider}__${toolName}`,
|
|
16816
17350
|
input: nested ?? { toolName }
|
|
@@ -16821,7 +17355,7 @@ function normalizeCursorToolCall(name, args) {
|
|
|
16821
17355
|
function unwrapCursorToolResult(result) {
|
|
16822
17356
|
if (result == null) return void 0;
|
|
16823
17357
|
if (typeof result === "string") return result;
|
|
16824
|
-
const rec =
|
|
17358
|
+
const rec = asRecord6(result);
|
|
16825
17359
|
if (!rec) {
|
|
16826
17360
|
try {
|
|
16827
17361
|
return JSON.stringify(result);
|
|
@@ -16832,18 +17366,18 @@ function unwrapCursorToolResult(result) {
|
|
|
16832
17366
|
const collectTexts = (items) => {
|
|
16833
17367
|
const texts = [];
|
|
16834
17368
|
for (const item of items) {
|
|
16835
|
-
const row2 =
|
|
17369
|
+
const row2 = asRecord6(item);
|
|
16836
17370
|
if (!row2) continue;
|
|
16837
17371
|
if (typeof row2.text === "string") {
|
|
16838
17372
|
texts.push(row2.text);
|
|
16839
17373
|
continue;
|
|
16840
17374
|
}
|
|
16841
|
-
const nested =
|
|
17375
|
+
const nested = asRecord6(row2.text);
|
|
16842
17376
|
if (typeof nested?.text === "string") texts.push(nested.text);
|
|
16843
17377
|
}
|
|
16844
17378
|
return texts;
|
|
16845
17379
|
};
|
|
16846
|
-
const value =
|
|
17380
|
+
const value = asRecord6(rec.value);
|
|
16847
17381
|
if (value && Array.isArray(value.content)) {
|
|
16848
17382
|
const texts = collectTexts(value.content);
|
|
16849
17383
|
if (texts.length) return texts.join("\n");
|
|
@@ -16860,10 +17394,10 @@ function unwrapCursorToolResult(result) {
|
|
|
16860
17394
|
}
|
|
16861
17395
|
function cursorToolResultIsError(status, result) {
|
|
16862
17396
|
if (status === "error") return true;
|
|
16863
|
-
const rec =
|
|
17397
|
+
const rec = asRecord6(result);
|
|
16864
17398
|
if (!rec) return false;
|
|
16865
17399
|
if (rec.status === "error") return true;
|
|
16866
|
-
const value =
|
|
17400
|
+
const value = asRecord6(rec.value);
|
|
16867
17401
|
return value?.isError === true;
|
|
16868
17402
|
}
|
|
16869
17403
|
function cursorSdkMessageToEvents(msg) {
|
|
@@ -17082,7 +17616,7 @@ function entryDir2() {
|
|
|
17082
17616
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
17083
17617
|
if (cjsDir) return cjsDir;
|
|
17084
17618
|
try {
|
|
17085
|
-
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));
|
|
17086
17620
|
} catch {
|
|
17087
17621
|
try {
|
|
17088
17622
|
const req = (0, import_node_module5.createRequire)(process.cwd() + "/");
|
|
@@ -17111,7 +17645,7 @@ function cursorRunnerPath() {
|
|
|
17111
17645
|
}
|
|
17112
17646
|
return candidates[0];
|
|
17113
17647
|
}
|
|
17114
|
-
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;
|
|
17115
17649
|
var init_cursor = __esm({
|
|
17116
17650
|
"src/agents/cursor.ts"() {
|
|
17117
17651
|
"use strict";
|
|
@@ -17131,7 +17665,7 @@ var init_cursor = __esm({
|
|
|
17131
17665
|
init_packaged_runtime();
|
|
17132
17666
|
init_turn_input();
|
|
17133
17667
|
init_cursor_events();
|
|
17134
|
-
|
|
17668
|
+
import_meta7 = {};
|
|
17135
17669
|
FALLBACK_CURSOR_MODELS = [
|
|
17136
17670
|
{ id: "default", displayName: "Auto" },
|
|
17137
17671
|
{ id: "composer-2.5", displayName: "Composer 2.5" },
|
|
@@ -17405,7 +17939,7 @@ var init_opencode_host = __esm({
|
|
|
17405
17939
|
});
|
|
17406
17940
|
|
|
17407
17941
|
// src/agents/opencode.ts
|
|
17408
|
-
function
|
|
17942
|
+
function asRecord7(value) {
|
|
17409
17943
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
17410
17944
|
return value;
|
|
17411
17945
|
}
|
|
@@ -17601,7 +18135,7 @@ var init_opencode = __esm({
|
|
|
17601
18135
|
const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
|
|
17602
18136
|
const state = part?.state;
|
|
17603
18137
|
const input = (state?.input && typeof state.input === "object" ? state.input : void 0) ?? part?.input ?? obj.input;
|
|
17604
|
-
const metadata =
|
|
18138
|
+
const metadata = asRecord7(state?.metadata);
|
|
17605
18139
|
const id = opencodeToolId(
|
|
17606
18140
|
name,
|
|
17607
18141
|
part?.callID ?? part?.id ?? obj.id,
|
|
@@ -17636,7 +18170,7 @@ var init_opencode = __esm({
|
|
|
17636
18170
|
}
|
|
17637
18171
|
if (obj.type === "subtask_event") {
|
|
17638
18172
|
const parentId = str4(obj.childSessionID) ?? str4(obj.childSessionId);
|
|
17639
|
-
const part =
|
|
18173
|
+
const part = asRecord7(obj.part);
|
|
17640
18174
|
if (!parentId || !part) return null;
|
|
17641
18175
|
if (part.type === "text" && str4(part.text)) {
|
|
17642
18176
|
return withTaskParent(
|
|
@@ -17647,8 +18181,8 @@ var init_opencode = __esm({
|
|
|
17647
18181
|
if (part.type === "tool" || str4(part.tool)) {
|
|
17648
18182
|
const name = str4(part.tool) ?? str4(part.name) ?? "tool";
|
|
17649
18183
|
const id = str4(part.callID) ?? str4(part.id) ?? `${parentId}-${name}`;
|
|
17650
|
-
const state =
|
|
17651
|
-
const input =
|
|
18184
|
+
const state = asRecord7(part.state);
|
|
18185
|
+
const input = asRecord7(state?.input) ?? asRecord7(part.input);
|
|
17652
18186
|
const nested = [
|
|
17653
18187
|
withEventParentId({ type: "tool_use", id, name, input }, parentId)
|
|
17654
18188
|
];
|
|
@@ -20066,7 +20600,7 @@ function forkMessageSlice(from, throughIndex) {
|
|
|
20066
20600
|
function buildForkTranscriptAttachment(baseTitle, messages) {
|
|
20067
20601
|
const title = baseTitle || "Chat";
|
|
20068
20602
|
return {
|
|
20069
|
-
id: (0,
|
|
20603
|
+
id: (0, import_node_crypto13.randomUUID)(),
|
|
20070
20604
|
name: `Transcript of ${title}.md`,
|
|
20071
20605
|
kind: "transcript",
|
|
20072
20606
|
content: formatTranscriptMarkdown(title, messages)
|
|
@@ -20125,11 +20659,11 @@ function forkChatTab(input) {
|
|
|
20125
20659
|
}
|
|
20126
20660
|
return tab;
|
|
20127
20661
|
}
|
|
20128
|
-
var
|
|
20662
|
+
var import_node_crypto13;
|
|
20129
20663
|
var init_chat_tabs = __esm({
|
|
20130
20664
|
"src/threads/chat-tabs.ts"() {
|
|
20131
20665
|
"use strict";
|
|
20132
|
-
|
|
20666
|
+
import_node_crypto13 = require("crypto");
|
|
20133
20667
|
init_context_compact();
|
|
20134
20668
|
init_teams();
|
|
20135
20669
|
init_worktree_labels();
|
|
@@ -20428,7 +20962,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
20428
20962
|
const path2 = opts?.path ?? REVIEW_SKILL_PATH;
|
|
20429
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);
|
|
20430
20964
|
return {
|
|
20431
|
-
id: (0,
|
|
20965
|
+
id: (0, import_node_crypto14.randomUUID)(),
|
|
20432
20966
|
name,
|
|
20433
20967
|
kind: "file",
|
|
20434
20968
|
path: path2,
|
|
@@ -20484,11 +21018,11 @@ async function requestReview(threadRef, send3) {
|
|
|
20484
21018
|
const started = await send3(tab.id, REVIEW_REQUEST_PREFILL);
|
|
20485
21019
|
return { tab: started, from };
|
|
20486
21020
|
}
|
|
20487
|
-
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;
|
|
20488
21022
|
var init_request_review = __esm({
|
|
20489
21023
|
"src/review/request-review.ts"() {
|
|
20490
21024
|
"use strict";
|
|
20491
|
-
|
|
21025
|
+
import_node_crypto14 = require("crypto");
|
|
20492
21026
|
import_node_fs49 = require("fs");
|
|
20493
21027
|
import_node_path50 = require("path");
|
|
20494
21028
|
init_global_workspace();
|
|
@@ -22037,8 +22571,28 @@ var init_clone_repo = __esm({
|
|
|
22037
22571
|
}
|
|
22038
22572
|
});
|
|
22039
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
|
+
|
|
22040
22594
|
// src/plan/plan-present.ts
|
|
22041
|
-
function
|
|
22595
|
+
function asRecord8(v) {
|
|
22042
22596
|
return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
22043
22597
|
}
|
|
22044
22598
|
function isPresentPlanToolName(name) {
|
|
@@ -22057,7 +22611,7 @@ function extractPresentedPlan(parts) {
|
|
|
22057
22611
|
for (let i = parts.length - 1; i >= 0; i--) {
|
|
22058
22612
|
const p = parts[i];
|
|
22059
22613
|
if (p.type !== "tool" || !isPresentPlanToolName(p.name)) continue;
|
|
22060
|
-
const input =
|
|
22614
|
+
const input = asRecord8(p.input) ?? {};
|
|
22061
22615
|
const content = typeof input.content === "string" ? input.content : typeof input.plan === "string" ? input.plan : typeof input.markdown === "string" ? input.markdown : "";
|
|
22062
22616
|
if (!content.trim()) continue;
|
|
22063
22617
|
const title = typeof input.title === "string" && input.title.trim() ? input.title.trim() : "Plan";
|
|
@@ -22259,6 +22813,7 @@ function decisionBlockFromParts(parts, planMode, at = (/* @__PURE__ */ new Date(
|
|
|
22259
22813
|
const reason = pending ? formatAskUserNotifyMessage(pending.questions) : "Waiting for an answer in that chat.";
|
|
22260
22814
|
return {
|
|
22261
22815
|
...makeAgentBlock("ask_user", reason, at),
|
|
22816
|
+
onScreen: true,
|
|
22262
22817
|
...pending ? { questionSignature: pending.signature, questions: pending.questions } : {}
|
|
22263
22818
|
};
|
|
22264
22819
|
}
|
|
@@ -22316,6 +22871,38 @@ function dismissAskUserQuestion(threadId, signature) {
|
|
|
22316
22871
|
...clearBlock ? { agentBlock: null } : {}
|
|
22317
22872
|
});
|
|
22318
22873
|
}
|
|
22874
|
+
function askBlocksEqual(a, b) {
|
|
22875
|
+
if (a === b) return true;
|
|
22876
|
+
if (!a || !b) return false;
|
|
22877
|
+
return a.source === b.source && a.reason === b.reason && a.at === b.at && a.onScreen === b.onScreen && a.questionSignature === b.questionSignature;
|
|
22878
|
+
}
|
|
22879
|
+
function askBlockAfterLiveParts(existing, parts) {
|
|
22880
|
+
const last = lastTopLevelTool(parts);
|
|
22881
|
+
if (last?.type === "tool" && isAskUserToolName(last.name)) {
|
|
22882
|
+
if (existing?.source === "ask_user" && existing.onScreen) return existing;
|
|
22883
|
+
const pending = extractPendingPlanQuestions(parts);
|
|
22884
|
+
const questions2 = pending?.questions ?? existing?.questions;
|
|
22885
|
+
if (!questions2?.length) {
|
|
22886
|
+
return existing?.source === "ask_user" ? { ...existing, onScreen: true } : existing ?? null;
|
|
22887
|
+
}
|
|
22888
|
+
const at = existing?.source === "ask_user" ? existing.at : void 0;
|
|
22889
|
+
return {
|
|
22890
|
+
...makeAgentBlock("ask_user", formatAskUserNotifyMessage(questions2), at),
|
|
22891
|
+
onScreen: true,
|
|
22892
|
+
questionSignature: pending?.signature ?? existing?.questionSignature,
|
|
22893
|
+
questions: questions2
|
|
22894
|
+
};
|
|
22895
|
+
}
|
|
22896
|
+
if (last && existing?.source === "ask_user") return null;
|
|
22897
|
+
return existing ?? null;
|
|
22898
|
+
}
|
|
22899
|
+
function syncAskUserBlockFromLive(threadId, parts) {
|
|
22900
|
+
const thread = readThread(threadId);
|
|
22901
|
+
if (!thread || thread.status === "archived") return;
|
|
22902
|
+
const next = askBlockAfterLiveParts(thread.agentBlock, parts);
|
|
22903
|
+
if (askBlocksEqual(thread.agentBlock, next)) return;
|
|
22904
|
+
updateThread(threadId, { agentBlock: next });
|
|
22905
|
+
}
|
|
22319
22906
|
function writeAgentBlock(threadId, block) {
|
|
22320
22907
|
const thread = readThread(threadId);
|
|
22321
22908
|
if (!thread || thread.status === "archived") return;
|
|
@@ -22479,7 +23066,7 @@ function isUnclaimedSteerRequest(req) {
|
|
|
22479
23066
|
}
|
|
22480
23067
|
function nextSteerRequest(existing) {
|
|
22481
23068
|
if (existing?.requestId && !existing.claimedAt) return existing;
|
|
22482
|
-
return { requestId: (0,
|
|
23069
|
+
return { requestId: (0, import_node_crypto15.randomUUID)(), requestedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
22483
23070
|
}
|
|
22484
23071
|
function claimSteerRequest(threadId) {
|
|
22485
23072
|
const pending = readThread(threadId)?.steerRequest;
|
|
@@ -22488,11 +23075,11 @@ function claimSteerRequest(threadId) {
|
|
|
22488
23075
|
steerRequest: { ...pending, claimedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
22489
23076
|
});
|
|
22490
23077
|
}
|
|
22491
|
-
var
|
|
23078
|
+
var import_node_crypto15;
|
|
22492
23079
|
var init_steer_request = __esm({
|
|
22493
23080
|
"src/orchestrator/steer-request.ts"() {
|
|
22494
23081
|
"use strict";
|
|
22495
|
-
|
|
23082
|
+
import_node_crypto15 = require("crypto");
|
|
22496
23083
|
init_thread_store();
|
|
22497
23084
|
}
|
|
22498
23085
|
});
|
|
@@ -22737,8 +23324,8 @@ function resolveAbleTimeOAuthHost(requested, saved) {
|
|
|
22737
23324
|
return fromSaved || void 0;
|
|
22738
23325
|
}
|
|
22739
23326
|
function createAbleTimePkce() {
|
|
22740
|
-
const verifier = (0,
|
|
22741
|
-
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");
|
|
22742
23329
|
return { verifier, challenge };
|
|
22743
23330
|
}
|
|
22744
23331
|
function ableTimeOAuthAuthorizeUrl(clientId, state, codeChallenge, host) {
|
|
@@ -22843,7 +23430,7 @@ async function startAbleTimeOAuth(opts) {
|
|
|
22843
23430
|
opts?.host,
|
|
22844
23431
|
loadAppSettings().integrations.abletimeHost
|
|
22845
23432
|
);
|
|
22846
|
-
const state = (0,
|
|
23433
|
+
const state = (0, import_node_crypto16.randomBytes)(16).toString("hex");
|
|
22847
23434
|
const pkce = createAbleTimePkce();
|
|
22848
23435
|
const authorizeUrl = ableTimeOAuthAuthorizeUrl(clientId, state, pkce.challenge, host);
|
|
22849
23436
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
@@ -22856,7 +23443,7 @@ async function startAbleTimeOAuth(opts) {
|
|
|
22856
23443
|
if (err) reject(err);
|
|
22857
23444
|
else resolve3(value);
|
|
22858
23445
|
};
|
|
22859
|
-
const server = (0,
|
|
23446
|
+
const server = (0, import_node_http2.createServer)((req, res) => {
|
|
22860
23447
|
try {
|
|
22861
23448
|
const url = new URL(req.url || "/", `http://127.0.0.1:${ABLETIME_OAUTH_PORT}`);
|
|
22862
23449
|
if (url.pathname !== "/callback") {
|
|
@@ -22943,12 +23530,12 @@ async function startAbleTimeOAuth(opts) {
|
|
|
22943
23530
|
return loadAppSettings();
|
|
22944
23531
|
}
|
|
22945
23532
|
}
|
|
22946
|
-
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;
|
|
22947
23534
|
var init_abletime_oauth = __esm({
|
|
22948
23535
|
"src/integrations/abletime-oauth.ts"() {
|
|
22949
23536
|
"use strict";
|
|
22950
|
-
|
|
22951
|
-
|
|
23537
|
+
import_node_crypto16 = require("crypto");
|
|
23538
|
+
import_node_http2 = require("http");
|
|
22952
23539
|
init_fetch();
|
|
22953
23540
|
init_app_settings();
|
|
22954
23541
|
init_abletime_mcp();
|
|
@@ -22981,7 +23568,7 @@ __export(abletime_rest_exports, {
|
|
|
22981
23568
|
looksLikeAbleTimeUlid: () => looksLikeAbleTimeUlid,
|
|
22982
23569
|
textFromAbleTimeDoc: () => textFromAbleTimeDoc
|
|
22983
23570
|
});
|
|
22984
|
-
function
|
|
23571
|
+
function asRecord9(value) {
|
|
22985
23572
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
22986
23573
|
}
|
|
22987
23574
|
function asString(value) {
|
|
@@ -22989,7 +23576,7 @@ function asString(value) {
|
|
|
22989
23576
|
}
|
|
22990
23577
|
function asList(value) {
|
|
22991
23578
|
if (Array.isArray(value)) return value;
|
|
22992
|
-
const record =
|
|
23579
|
+
const record = asRecord9(value);
|
|
22993
23580
|
if (!record) return [];
|
|
22994
23581
|
for (const key of ["data", "tasks", "projects", "users", "items", "results"]) {
|
|
22995
23582
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -23006,12 +23593,12 @@ function ableTimeDocFromText(text7) {
|
|
|
23006
23593
|
}
|
|
23007
23594
|
function textFromAbleTimeDoc(value) {
|
|
23008
23595
|
if (typeof value === "string") return value.trim();
|
|
23009
|
-
const record =
|
|
23596
|
+
const record = asRecord9(value);
|
|
23010
23597
|
if (!record) return "";
|
|
23011
23598
|
if (typeof record.text === "string" && record.text.trim()) return record.text.trim();
|
|
23012
23599
|
const chunks = [];
|
|
23013
23600
|
const walk = (node) => {
|
|
23014
|
-
const rec =
|
|
23601
|
+
const rec = asRecord9(node);
|
|
23015
23602
|
if (!rec) return;
|
|
23016
23603
|
if (typeof rec.text === "string" && rec.text) chunks.push(rec.text);
|
|
23017
23604
|
if (Array.isArray(rec.content)) rec.content.forEach(walk);
|
|
@@ -23073,7 +23660,7 @@ async function restPages(path2, opts, maxPages = 20) {
|
|
|
23073
23660
|
query: { ...opts.query, ...cursor ? { cursor } : {} }
|
|
23074
23661
|
});
|
|
23075
23662
|
items.push(...asList(raw));
|
|
23076
|
-
const page =
|
|
23663
|
+
const page = asRecord9(asRecord9(raw)?.page);
|
|
23077
23664
|
const next = page ? asString(page.nextCursor) : "";
|
|
23078
23665
|
if (!next) break;
|
|
23079
23666
|
cursor = next;
|
|
@@ -23081,7 +23668,7 @@ async function restPages(path2, opts, maxPages = 20) {
|
|
|
23081
23668
|
return items;
|
|
23082
23669
|
}
|
|
23083
23670
|
function userDisplayName(raw) {
|
|
23084
|
-
const rec =
|
|
23671
|
+
const rec = asRecord9(raw);
|
|
23085
23672
|
if (!rec) return null;
|
|
23086
23673
|
const id = asString(rec.userId) || asString(rec.id);
|
|
23087
23674
|
const name = [asString(rec.firstName), asString(rec.lastName)].filter(Boolean).join(" ") || asString(rec.username) || asString(rec.email) || asString(rec.name);
|
|
@@ -23089,7 +23676,7 @@ function userDisplayName(raw) {
|
|
|
23089
23676
|
return { id: id || void 0, name };
|
|
23090
23677
|
}
|
|
23091
23678
|
function restTaskToRaw(raw, users) {
|
|
23092
|
-
const rec =
|
|
23679
|
+
const rec = asRecord9(raw);
|
|
23093
23680
|
if (!rec) return null;
|
|
23094
23681
|
const id = asString(rec.timeflowTaskId) || asString(rec.taskId) || asString(rec.id);
|
|
23095
23682
|
const identifier = asString(rec.taskRef) || asString(rec.reference) || id;
|
|
@@ -23097,7 +23684,7 @@ function restTaskToRaw(raw, users) {
|
|
|
23097
23684
|
if (!id && !identifier && !title) return null;
|
|
23098
23685
|
const assignee = users.get(asString(rec.assignedUserId));
|
|
23099
23686
|
const comments = asList(rec.comments).map((item) => {
|
|
23100
|
-
const comment =
|
|
23687
|
+
const comment = asRecord9(item) ?? {};
|
|
23101
23688
|
const user = userDisplayName(comment);
|
|
23102
23689
|
return {
|
|
23103
23690
|
id: asString(comment.commentId) || asString(comment.id),
|
|
@@ -23127,13 +23714,13 @@ function restTaskToRaw(raw, users) {
|
|
|
23127
23714
|
};
|
|
23128
23715
|
}
|
|
23129
23716
|
function restProjectToRaw(raw) {
|
|
23130
|
-
const rec =
|
|
23717
|
+
const rec = asRecord9(raw);
|
|
23131
23718
|
if (!rec) return null;
|
|
23132
23719
|
const id = asString(rec.projectId) || asString(rec.id);
|
|
23133
23720
|
const name = asString(rec.projectName) || asString(rec.name);
|
|
23134
23721
|
if (!id && !name) return null;
|
|
23135
23722
|
const categories = asList(rec.categories).map((item) => {
|
|
23136
|
-
const cat =
|
|
23723
|
+
const cat = asRecord9(item) ?? {};
|
|
23137
23724
|
return {
|
|
23138
23725
|
id: asString(cat.projectCategoryId) || asString(cat.categoryId) || asString(cat.id),
|
|
23139
23726
|
name: asString(cat.categoryName) || asString(cat.name)
|
|
@@ -23145,7 +23732,7 @@ async function listUsers(opts) {
|
|
|
23145
23732
|
const users = /* @__PURE__ */ new Map();
|
|
23146
23733
|
for (const item of await restPages("/users", opts).catch(() => [])) {
|
|
23147
23734
|
const user = userDisplayName(item);
|
|
23148
|
-
const rec =
|
|
23735
|
+
const rec = asRecord9(item);
|
|
23149
23736
|
const id = user?.id || (rec ? asString(rec.userId) : "");
|
|
23150
23737
|
if (user && id) users.set(id, user);
|
|
23151
23738
|
}
|
|
@@ -23271,10 +23858,10 @@ async function callAbleTimeRestTool(name, args = {}, opts) {
|
|
|
23271
23858
|
if (!project) throw new Error("AbleTime has no projects to create a task in");
|
|
23272
23859
|
const categories = asList(project.categories);
|
|
23273
23860
|
const wantedCategory = firstStringArg(args, ["category_id", "categoryId", "category"]);
|
|
23274
|
-
const category = categories.map((item) =>
|
|
23861
|
+
const category = categories.map((item) => asRecord9(item)).find((item) => {
|
|
23275
23862
|
if (!item || !wantedCategory) return false;
|
|
23276
23863
|
return asString(item.id).toLowerCase() === wantedCategory.toLowerCase() || asString(item.name).toLowerCase() === wantedCategory.toLowerCase();
|
|
23277
|
-
}) ??
|
|
23864
|
+
}) ?? asRecord9(categories[0]);
|
|
23278
23865
|
const parentArg = firstStringArg(args, ["parent", "parent_id", "parentId", "related_task_id"]);
|
|
23279
23866
|
const parentTaskId = parentArg ? await resolveRestParentTaskId(parentArg, requestOpts) : void 0;
|
|
23280
23867
|
const created = await abletimeRestRequest("/tasks", {
|
|
@@ -23288,7 +23875,7 @@ async function callAbleTimeRestTool(name, args = {}, opts) {
|
|
|
23288
23875
|
}
|
|
23289
23876
|
});
|
|
23290
23877
|
const state = firstStringArg(args, ["state"]);
|
|
23291
|
-
const createdId = asString(
|
|
23878
|
+
const createdId = asString(asRecord9(created)?.timeflowTaskId);
|
|
23292
23879
|
const description = asString(args.description);
|
|
23293
23880
|
if (createdId && description) {
|
|
23294
23881
|
await abletimeRestRequest(`/tasks/${encodeURIComponent(createdId)}`, {
|
|
@@ -23361,7 +23948,7 @@ async function callAbleTimeRestTool(name, args = {}, opts) {
|
|
|
23361
23948
|
method: "POST",
|
|
23362
23949
|
body: { content: ableTimeDocFromText(body) }
|
|
23363
23950
|
});
|
|
23364
|
-
const rec =
|
|
23951
|
+
const rec = asRecord9(created) ?? {};
|
|
23365
23952
|
return {
|
|
23366
23953
|
id: asString(rec.commentId) || void 0,
|
|
23367
23954
|
body: textFromAbleTimeDoc(rec.content) || body
|
|
@@ -23456,7 +24043,7 @@ function rewriteAbleTimeError(message) {
|
|
|
23456
24043
|
}
|
|
23457
24044
|
return message;
|
|
23458
24045
|
}
|
|
23459
|
-
function
|
|
24046
|
+
function asRecord10(value) {
|
|
23460
24047
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
23461
24048
|
}
|
|
23462
24049
|
function parseSseJson(body) {
|
|
@@ -23478,12 +24065,12 @@ function parseSseJson(body) {
|
|
|
23478
24065
|
}
|
|
23479
24066
|
}
|
|
23480
24067
|
function unwrapToolResult(result) {
|
|
23481
|
-
const record =
|
|
24068
|
+
const record = asRecord10(result);
|
|
23482
24069
|
if (!record) return result;
|
|
23483
24070
|
const content = record.content;
|
|
23484
24071
|
if (Array.isArray(content)) {
|
|
23485
24072
|
const texts = content.map((part) => {
|
|
23486
|
-
const item =
|
|
24073
|
+
const item = asRecord10(part);
|
|
23487
24074
|
if (!item) return "";
|
|
23488
24075
|
return typeof item.text === "string" ? item.text : "";
|
|
23489
24076
|
}).filter(Boolean);
|
|
@@ -23505,7 +24092,7 @@ function unwrapToolResult(result) {
|
|
|
23505
24092
|
return result;
|
|
23506
24093
|
}
|
|
23507
24094
|
function textsFromUnknown(value) {
|
|
23508
|
-
const record =
|
|
24095
|
+
const record = asRecord10(value);
|
|
23509
24096
|
if (!record) return "";
|
|
23510
24097
|
if (typeof record.message === "string") return record.message;
|
|
23511
24098
|
if (typeof record.error === "string") return record.error;
|
|
@@ -23552,7 +24139,7 @@ async function abletimeMcpRequest(method, params, opts) {
|
|
|
23552
24139
|
return parseSseJson(body);
|
|
23553
24140
|
}
|
|
23554
24141
|
})();
|
|
23555
|
-
const rpc =
|
|
24142
|
+
const rpc = asRecord10(parsed);
|
|
23556
24143
|
if (rpc?.error) {
|
|
23557
24144
|
const detail = typeof rpc.error.message === "string" && rpc.error.message.trim() ? rpc.error.message : `AbleTime MCP error ${rpc.error.code ?? ""}`.trim();
|
|
23558
24145
|
throw new Error(rewriteAbleTimeError(detail));
|
|
@@ -23707,7 +24294,7 @@ function uniqueAttachmentFileName(dir, originalName) {
|
|
|
23707
24294
|
const candidate = `${stem}-${i}${ext}`;
|
|
23708
24295
|
if (!(0, import_node_fs55.existsSync)((0, import_node_path56.join)(dir, candidate))) return candidate;
|
|
23709
24296
|
}
|
|
23710
|
-
return `${stem}-${(0,
|
|
24297
|
+
return `${stem}-${(0, import_node_crypto17.randomUUID)()}${ext}`;
|
|
23711
24298
|
}
|
|
23712
24299
|
function extractHttpUrls(markdown) {
|
|
23713
24300
|
const text7 = markdown ?? "";
|
|
@@ -23813,13 +24400,13 @@ async function downloadAuthenticatedFile(opts) {
|
|
|
23813
24400
|
...contentType ? { contentType } : {}
|
|
23814
24401
|
};
|
|
23815
24402
|
}
|
|
23816
|
-
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;
|
|
23817
24404
|
var init_issue_attachments = __esm({
|
|
23818
24405
|
"src/integrations/issue-attachments.ts"() {
|
|
23819
24406
|
"use strict";
|
|
23820
24407
|
import_node_fs55 = require("fs");
|
|
23821
24408
|
import_node_path56 = require("path");
|
|
23822
|
-
|
|
24409
|
+
import_node_crypto17 = require("crypto");
|
|
23823
24410
|
init_fetch();
|
|
23824
24411
|
init_workspace_scratch();
|
|
23825
24412
|
ISSUE_ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;
|
|
@@ -23844,7 +24431,7 @@ var init_issue_attachments = __esm({
|
|
|
23844
24431
|
});
|
|
23845
24432
|
|
|
23846
24433
|
// src/integrations/abletime-attachments.ts
|
|
23847
|
-
function
|
|
24434
|
+
function asRecord11(value) {
|
|
23848
24435
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
23849
24436
|
}
|
|
23850
24437
|
function asString2(value) {
|
|
@@ -23852,7 +24439,7 @@ function asString2(value) {
|
|
|
23852
24439
|
}
|
|
23853
24440
|
function asList2(value) {
|
|
23854
24441
|
if (Array.isArray(value)) return value;
|
|
23855
|
-
const record =
|
|
24442
|
+
const record = asRecord11(value);
|
|
23856
24443
|
if (!record) return [];
|
|
23857
24444
|
for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
|
|
23858
24445
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -23871,9 +24458,9 @@ function filesFromAbleTimeDoc(value) {
|
|
|
23871
24458
|
const out = [];
|
|
23872
24459
|
const seen = /* @__PURE__ */ new Set();
|
|
23873
24460
|
const walk = (node) => {
|
|
23874
|
-
const rec =
|
|
24461
|
+
const rec = asRecord11(node);
|
|
23875
24462
|
if (!rec) return;
|
|
23876
|
-
const attrs =
|
|
24463
|
+
const attrs = asRecord11(rec.attrs) ?? rec;
|
|
23877
24464
|
const url = asString2(attrs.src) || asString2(attrs.href) || asString2(attrs.url) || asString2(attrs.fileUrl) || asString2(attrs.downloadUrl);
|
|
23878
24465
|
if (url && !seen.has(url)) {
|
|
23879
24466
|
seen.add(url);
|
|
@@ -23891,7 +24478,7 @@ function filesFromAbleTimeDoc(value) {
|
|
|
23891
24478
|
function listedAbleTimeFiles(raw) {
|
|
23892
24479
|
const out = [];
|
|
23893
24480
|
for (const item of asList2(raw)) {
|
|
23894
|
-
const rec =
|
|
24481
|
+
const rec = asRecord11(item);
|
|
23895
24482
|
if (!rec) continue;
|
|
23896
24483
|
const url = firstString(rec, ["url", "href", "src", "fileUrl", "downloadUrl", "permalink"]);
|
|
23897
24484
|
if (!url) continue;
|
|
@@ -23911,7 +24498,7 @@ function mapAbleTimeAttachments(record) {
|
|
|
23911
24498
|
...filesFromAbleTimeDoc(record.description),
|
|
23912
24499
|
...filesFromAbleTimeDoc(record.content),
|
|
23913
24500
|
...asList2(record.comments).flatMap((item) => {
|
|
23914
|
-
const rec =
|
|
24501
|
+
const rec = asRecord11(item);
|
|
23915
24502
|
return rec ? filesFromAbleTimeDoc(rec.content ?? rec.body) : [];
|
|
23916
24503
|
})
|
|
23917
24504
|
].map((file) => ({
|
|
@@ -23953,7 +24540,7 @@ async function resolveAbleTimeAttachmentUrl(id, opts) {
|
|
|
23953
24540
|
const json = await res.json().catch(() => null);
|
|
23954
24541
|
const rec = json && typeof json === "object" && !Array.isArray(json) ? json.data && typeof json.data === "object" ? json.data : json : null;
|
|
23955
24542
|
if (!rec) continue;
|
|
23956
|
-
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"]);
|
|
23957
24544
|
if (url) {
|
|
23958
24545
|
return {
|
|
23959
24546
|
url,
|
|
@@ -23995,7 +24582,7 @@ var init_abletime_attachments = __esm({
|
|
|
23995
24582
|
});
|
|
23996
24583
|
|
|
23997
24584
|
// src/integrations/abletime-projects.ts
|
|
23998
|
-
function
|
|
24585
|
+
function asRecord12(value) {
|
|
23999
24586
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
24000
24587
|
}
|
|
24001
24588
|
function firstString2(record, keys) {
|
|
@@ -24008,7 +24595,7 @@ function firstString2(record, keys) {
|
|
|
24008
24595
|
}
|
|
24009
24596
|
function asList3(value) {
|
|
24010
24597
|
if (Array.isArray(value)) return value;
|
|
24011
|
-
const record =
|
|
24598
|
+
const record = asRecord12(value);
|
|
24012
24599
|
if (!record) return [];
|
|
24013
24600
|
for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
|
|
24014
24601
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -24016,7 +24603,7 @@ function asList3(value) {
|
|
|
24016
24603
|
return [];
|
|
24017
24604
|
}
|
|
24018
24605
|
function ableTimeProjectFields(nested) {
|
|
24019
|
-
const projectRecord =
|
|
24606
|
+
const projectRecord = asRecord12(nested.project);
|
|
24020
24607
|
const projectId = firstString2(nested, ["project_id", "projectId"]) || firstString2(projectRecord, ["id"]) || void 0;
|
|
24021
24608
|
const projectName = firstString2(nested, ["project_name", "projectName"]) || firstString2(projectRecord, ["name", "title"]) || void 0;
|
|
24022
24609
|
if (!projectId && !projectName) return {};
|
|
@@ -24029,13 +24616,13 @@ function ableTimeProjectFields(nested) {
|
|
|
24029
24616
|
};
|
|
24030
24617
|
}
|
|
24031
24618
|
function mapAbleTimeProject(raw) {
|
|
24032
|
-
const record =
|
|
24619
|
+
const record = asRecord12(raw);
|
|
24033
24620
|
if (!record) return null;
|
|
24034
24621
|
const id = firstString2(record, ["id", "project_id", "projectId"]);
|
|
24035
24622
|
const name = firstString2(record, ["name", "title", "projectName"]);
|
|
24036
24623
|
if (!id && !name) return null;
|
|
24037
24624
|
const categories = asList3(record.categories ?? record.category).map((item) => {
|
|
24038
|
-
const rec =
|
|
24625
|
+
const rec = asRecord12(item);
|
|
24039
24626
|
if (!rec) return null;
|
|
24040
24627
|
const categoryId = firstString2(rec, ["id", "category_id", "projectCategoryId", "categoryId"]);
|
|
24041
24628
|
const categoryName = firstString2(rec, ["name", "title", "categoryName"]);
|
|
@@ -24071,7 +24658,7 @@ __export(abletime_exports, {
|
|
|
24071
24658
|
updateAbleTimeTask: () => updateAbleTimeTask,
|
|
24072
24659
|
verifyAbleTimeConnection: () => verifyAbleTimeConnection
|
|
24073
24660
|
});
|
|
24074
|
-
function
|
|
24661
|
+
function asRecord13(value) {
|
|
24075
24662
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
24076
24663
|
}
|
|
24077
24664
|
function asString3(value) {
|
|
@@ -24088,14 +24675,14 @@ function firstString3(record, keys) {
|
|
|
24088
24675
|
function firstRecord(record, keys) {
|
|
24089
24676
|
if (!record) return null;
|
|
24090
24677
|
for (const key of keys) {
|
|
24091
|
-
const value =
|
|
24678
|
+
const value = asRecord13(record[key]);
|
|
24092
24679
|
if (value) return value;
|
|
24093
24680
|
}
|
|
24094
24681
|
return null;
|
|
24095
24682
|
}
|
|
24096
24683
|
function asList4(value) {
|
|
24097
24684
|
if (Array.isArray(value)) return value;
|
|
24098
|
-
const record =
|
|
24685
|
+
const record = asRecord13(value);
|
|
24099
24686
|
if (!record) return [];
|
|
24100
24687
|
for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
|
|
24101
24688
|
if (Array.isArray(record[key])) return record[key];
|
|
@@ -24107,18 +24694,18 @@ function labelsOf(record) {
|
|
|
24107
24694
|
if (!Array.isArray(raw)) return [];
|
|
24108
24695
|
return raw.map((item) => {
|
|
24109
24696
|
if (typeof item === "string") return item.trim();
|
|
24110
|
-
const rec =
|
|
24697
|
+
const rec = asRecord13(item);
|
|
24111
24698
|
return rec ? firstString3(rec, ["name", "title", "label"]) : "";
|
|
24112
24699
|
}).filter(Boolean);
|
|
24113
24700
|
}
|
|
24114
24701
|
function commentsOf(record) {
|
|
24115
24702
|
const out = [];
|
|
24116
24703
|
for (const item of asList4(record.comments ?? record.notes ?? record.discussion)) {
|
|
24117
|
-
const rec =
|
|
24704
|
+
const rec = asRecord13(item);
|
|
24118
24705
|
if (!rec) continue;
|
|
24119
24706
|
const body = firstString3(rec, ["body", "text", "comment", "message", "contentSanitized"]) || textFromAbleTimeDoc(rec.content);
|
|
24120
24707
|
if (!body) continue;
|
|
24121
|
-
const user = firstString3(
|
|
24708
|
+
const user = firstString3(asRecord13(rec.user) ?? asRecord13(rec.author), ["name", "display_name", "username"]) || firstString3(rec, ["user_name", "author", "username"]);
|
|
24122
24709
|
const id = firstString3(rec, ["id", "comment_id", "commentId"]);
|
|
24123
24710
|
const url = firstString3(rec, ["url", "permalink"]);
|
|
24124
24711
|
const createdAt = firstString3(rec, ["created_at", "createdAt", "created"]);
|
|
@@ -24145,7 +24732,7 @@ function taskUrl(task, host) {
|
|
|
24145
24732
|
return `${base}/tasks/${slug}`;
|
|
24146
24733
|
}
|
|
24147
24734
|
function mapAbleTimeTask(raw, host) {
|
|
24148
|
-
const record =
|
|
24735
|
+
const record = asRecord13(raw);
|
|
24149
24736
|
if (!record) return null;
|
|
24150
24737
|
const nested = firstRecord(record, ["task", "data"]) ?? record;
|
|
24151
24738
|
const id = firstString3(nested, ["id", "task_id", "taskId", "timeflowTaskId"]);
|
|
@@ -24163,7 +24750,7 @@ function mapAbleTimeTask(raw, host) {
|
|
|
24163
24750
|
description: firstString3(nested, ["description", "body", "details", "descriptionSanitized"]) || textFromAbleTimeDoc(nested.description) || void 0,
|
|
24164
24751
|
state: firstString3(nested, ["state", "board_state", "boardState", "status", "taskState"]) || void 0,
|
|
24165
24752
|
...ableTimeProjectFields(nested),
|
|
24166
|
-
categoryId: firstString3(nested, ["category_id", "categoryId", "projectCategoryId"]) || firstString3(
|
|
24753
|
+
categoryId: firstString3(nested, ["category_id", "categoryId", "projectCategoryId"]) || firstString3(asRecord13(nested.category), ["id"]) || void 0,
|
|
24167
24754
|
assignee: assigneeOf(nested),
|
|
24168
24755
|
labels: labelsOf(nested),
|
|
24169
24756
|
comments: commentsOf(nested),
|
|
@@ -24213,7 +24800,7 @@ function isOpenTask(task) {
|
|
|
24213
24800
|
}
|
|
24214
24801
|
async function getAbleTimeOrientation(opts) {
|
|
24215
24802
|
const raw = await callAbleTimeTool("orientation", {}, opts);
|
|
24216
|
-
const record =
|
|
24803
|
+
const record = asRecord13(raw);
|
|
24217
24804
|
const viewerRec = firstRecord(record, ["viewer", "principal", "user", "actor", "me", "person"]) ?? record;
|
|
24218
24805
|
const viewer = {
|
|
24219
24806
|
id: firstString3(viewerRec, ["id", "user_id"]) || void 0,
|
|
@@ -24292,7 +24879,7 @@ async function commentAbleTimeTask(input, opts) {
|
|
|
24292
24879
|
{ id, task_id: id, task: id, body, comment: body, text: body },
|
|
24293
24880
|
opts
|
|
24294
24881
|
);
|
|
24295
|
-
const rec =
|
|
24882
|
+
const rec = asRecord13(raw);
|
|
24296
24883
|
return {
|
|
24297
24884
|
id: rec ? firstString3(rec, ["id", "comment_id"]) || void 0 : void 0,
|
|
24298
24885
|
body: rec ? firstString3(rec, ["body", "text", "comment"]) || body : body
|
|
@@ -25168,6 +25755,7 @@ function noteTurnLiveEvent(threadId, event) {
|
|
|
25168
25755
|
const prev = buffers.get(threadId) ?? { parts: [], timer: null };
|
|
25169
25756
|
prev.parts = trimParts(applyAgentEvent(prev.parts, event));
|
|
25170
25757
|
buffers.set(threadId, prev);
|
|
25758
|
+
syncAskUserBlockFromLive(threadId, prev.parts);
|
|
25171
25759
|
if (event.type === "exit") {
|
|
25172
25760
|
flush(threadId);
|
|
25173
25761
|
const cur = buffers.get(threadId);
|
|
@@ -25224,6 +25812,7 @@ var init_turn_live = __esm({
|
|
|
25224
25812
|
import_node_fs57 = require("fs");
|
|
25225
25813
|
init_message_parts();
|
|
25226
25814
|
init_paths();
|
|
25815
|
+
init_agent_block();
|
|
25227
25816
|
buffers = /* @__PURE__ */ new Map();
|
|
25228
25817
|
FLUSH_MS = 800;
|
|
25229
25818
|
MAX_PARTS = 80;
|
|
@@ -25443,7 +26032,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
25443
26032
|
...instructions
|
|
25444
26033
|
].join("\n");
|
|
25445
26034
|
return {
|
|
25446
|
-
id: (0,
|
|
26035
|
+
id: (0, import_node_crypto18.randomUUID)(),
|
|
25447
26036
|
name: orch ? "Orchestration quota handoff.md" : "Quota handoff.md",
|
|
25448
26037
|
kind: "transcript",
|
|
25449
26038
|
content: body
|
|
@@ -25475,11 +26064,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
|
|
|
25475
26064
|
}
|
|
25476
26065
|
return updateThread(tab.id, patch);
|
|
25477
26066
|
}
|
|
25478
|
-
var
|
|
26067
|
+
var import_node_crypto18, QUOTA_CONTINUE_PROMPT, QUOTA_CONTINUE_ACCOUNT_PROMPT, QUOTA_RESUME_PROMPT;
|
|
25479
26068
|
var init_quota_failover = __esm({
|
|
25480
26069
|
"src/orchestrator/quota-failover.ts"() {
|
|
25481
26070
|
"use strict";
|
|
25482
|
-
|
|
26071
|
+
import_node_crypto18 = require("crypto");
|
|
25483
26072
|
init_session_quota();
|
|
25484
26073
|
init_app_settings();
|
|
25485
26074
|
init_managed_accounts();
|
|
@@ -27555,7 +28144,7 @@ function compiledModuleDir() {
|
|
|
27555
28144
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
27556
28145
|
if (cjsDir) return cjsDir;
|
|
27557
28146
|
try {
|
|
27558
|
-
const url =
|
|
28147
|
+
const url = import_meta8.url;
|
|
27559
28148
|
if (typeof url === "string" && url.length > 0) {
|
|
27560
28149
|
return (0, import_node_path62.dirname)((0, import_node_url5.fileURLToPath)(url));
|
|
27561
28150
|
}
|
|
@@ -27594,7 +28183,7 @@ function formatDetachedJobInvoke(scriptPath) {
|
|
|
27594
28183
|
if (resolved) return `node ${JSON.stringify(resolved)}`;
|
|
27595
28184
|
return "node scripts/detached-job.cjs";
|
|
27596
28185
|
}
|
|
27597
|
-
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;
|
|
27598
28187
|
var init_detached_job_path = __esm({
|
|
27599
28188
|
"src/skills/detached-job-path.ts"() {
|
|
27600
28189
|
"use strict";
|
|
@@ -27602,7 +28191,7 @@ var init_detached_job_path = __esm({
|
|
|
27602
28191
|
import_node_path62 = require("path");
|
|
27603
28192
|
import_node_url5 = require("url");
|
|
27604
28193
|
init_packaged_runtime();
|
|
27605
|
-
|
|
28194
|
+
import_meta8 = {};
|
|
27606
28195
|
DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
|
|
27607
28196
|
}
|
|
27608
28197
|
});
|
|
@@ -28002,7 +28591,7 @@ function normalizeServiceOrigin(raw, fallback) {
|
|
|
28002
28591
|
return fallback;
|
|
28003
28592
|
}
|
|
28004
28593
|
}
|
|
28005
|
-
function
|
|
28594
|
+
function asRecord14(value) {
|
|
28006
28595
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
28007
28596
|
}
|
|
28008
28597
|
function asString4(value) {
|
|
@@ -28035,7 +28624,7 @@ async function authorizedGet(url, token) {
|
|
|
28035
28624
|
});
|
|
28036
28625
|
const body = await readJson2(res);
|
|
28037
28626
|
if (!res.ok) {
|
|
28038
|
-
const record =
|
|
28627
|
+
const record = asRecord14(body);
|
|
28039
28628
|
const message = firstString4(record, ["message", "error", "error_description", "detail"]) || (typeof body === "string" ? body.trim().slice(0, 160) : "");
|
|
28040
28629
|
throw new Error(
|
|
28041
28630
|
message ? `${res.status}: ${message}` : `Request failed (${res.status})`
|
|
@@ -28049,28 +28638,28 @@ async function verifyOptionalService(input) {
|
|
|
28049
28638
|
const spec = optionalServiceSpec(input.id);
|
|
28050
28639
|
try {
|
|
28051
28640
|
if (input.id === "vercel") {
|
|
28052
|
-
const body2 =
|
|
28053
|
-
const user =
|
|
28641
|
+
const body2 = asRecord14(await authorizedGet("https://api.vercel.com/v2/user", token));
|
|
28642
|
+
const user = asRecord14(body2?.user) ?? body2;
|
|
28054
28643
|
const name2 = firstString4(user, ["username", "name", "email"]) || "Vercel user";
|
|
28055
28644
|
return { viewerName: name2 };
|
|
28056
28645
|
}
|
|
28057
28646
|
if (input.id === "supabase") {
|
|
28058
28647
|
const body2 = await authorizedGet("https://api.supabase.com/v1/organizations", token);
|
|
28059
28648
|
const list2 = Array.isArray(body2) ? body2 : [];
|
|
28060
|
-
const first2 =
|
|
28649
|
+
const first2 = asRecord14(list2[0]);
|
|
28061
28650
|
const name2 = firstString4(first2, ["name", "slug"]) || "Supabase";
|
|
28062
28651
|
return { viewerName: list2.length > 1 ? `${name2} +${list2.length - 1}` : name2 };
|
|
28063
28652
|
}
|
|
28064
28653
|
if (input.id === "posthog") {
|
|
28065
28654
|
const host2 = normalizeServiceOrigin(input.host, spec.defaultHost ?? "https://us.posthog.com");
|
|
28066
|
-
const body2 =
|
|
28655
|
+
const body2 = asRecord14(await authorizedGet(`${host2}/api/users/@me/`, token));
|
|
28067
28656
|
const name2 = firstString4(body2, ["email", "distinct_id"]) || [firstString4(body2, ["first_name"]), firstString4(body2, ["last_name"])].filter(Boolean).join(" ") || "PostHog user";
|
|
28068
28657
|
return { viewerName: name2, host: host2 };
|
|
28069
28658
|
}
|
|
28070
28659
|
const host = normalizeServiceOrigin(input.host, spec.defaultHost ?? "https://sentry.io");
|
|
28071
28660
|
const body = await authorizedGet(`${host}/api/0/organizations/`, token);
|
|
28072
28661
|
const list = Array.isArray(body) ? body : [];
|
|
28073
|
-
const first =
|
|
28662
|
+
const first = asRecord14(list[0]);
|
|
28074
28663
|
const name = firstString4(first, ["slug", "name"]) || "Sentry";
|
|
28075
28664
|
return { viewerName: list.length > 1 ? `${name} +${list.length - 1}` : name, host };
|
|
28076
28665
|
} catch (err) {
|
|
@@ -28944,10 +29533,10 @@ function collectActiveRunPorts(runs) {
|
|
|
28944
29533
|
return [...ports];
|
|
28945
29534
|
}
|
|
28946
29535
|
function getOrchestrator() {
|
|
28947
|
-
if (!
|
|
28948
|
-
|
|
29536
|
+
if (!singleton2) {
|
|
29537
|
+
singleton2 = new Orchestrator();
|
|
28949
29538
|
}
|
|
28950
|
-
return
|
|
29539
|
+
return singleton2;
|
|
28951
29540
|
}
|
|
28952
29541
|
async function startOrchestration(opts) {
|
|
28953
29542
|
const repoPath = opts.repoPath?.trim();
|
|
@@ -29007,7 +29596,7 @@ async function startOrchestration(opts) {
|
|
|
29007
29596
|
}
|
|
29008
29597
|
return updated;
|
|
29009
29598
|
}
|
|
29010
|
-
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;
|
|
29011
29600
|
var init_orchestrator = __esm({
|
|
29012
29601
|
"src/orchestrator/orchestrator.ts"() {
|
|
29013
29602
|
"use strict";
|
|
@@ -29015,7 +29604,7 @@ var init_orchestrator = __esm({
|
|
|
29015
29604
|
init_injected_notices();
|
|
29016
29605
|
init_task_state();
|
|
29017
29606
|
init_wait_for_turn();
|
|
29018
|
-
|
|
29607
|
+
import_node_crypto19 = require("crypto");
|
|
29019
29608
|
import_node_fs67 = require("fs");
|
|
29020
29609
|
init_error_detail();
|
|
29021
29610
|
init_run();
|
|
@@ -29041,6 +29630,7 @@ var init_orchestrator = __esm({
|
|
|
29041
29630
|
init_usage();
|
|
29042
29631
|
init_thread_store();
|
|
29043
29632
|
init_desktop_host();
|
|
29633
|
+
init_model_context();
|
|
29044
29634
|
init_agent_block();
|
|
29045
29635
|
init_child_halt();
|
|
29046
29636
|
init_stop_reason();
|
|
@@ -30039,6 +30629,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
30039
30629
|
orchestrationReminder,
|
|
30040
30630
|
prGateDirective,
|
|
30041
30631
|
injectedNoticeContext,
|
|
30632
|
+
takeMcpAppModelContext(threadId),
|
|
30042
30633
|
expandedPrompt
|
|
30043
30634
|
].filter(Boolean).join("\n\n");
|
|
30044
30635
|
if (!autoContinue && sentAttachments) {
|
|
@@ -30667,7 +31258,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
30667
31258
|
const request = sameIntent ? pending : {
|
|
30668
31259
|
op,
|
|
30669
31260
|
scriptName: scriptName ?? null,
|
|
30670
|
-
requestId: (0,
|
|
31261
|
+
requestId: (0, import_node_crypto19.randomUUID)(),
|
|
30671
31262
|
requestedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
30672
31263
|
};
|
|
30673
31264
|
if (!sameIntent) {
|
|
@@ -31788,7 +32379,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
31788
32379
|
return thread;
|
|
31789
32380
|
}
|
|
31790
32381
|
};
|
|
31791
|
-
|
|
32382
|
+
singleton2 = null;
|
|
31792
32383
|
}
|
|
31793
32384
|
});
|
|
31794
32385
|
|
|
@@ -32117,6 +32708,7 @@ __export(index_exports, {
|
|
|
32117
32708
|
archiveRemovedWorkspaceChats: () => archiveRemovedWorkspaceChats,
|
|
32118
32709
|
archivesWithRemovedWorkspace: () => archivesWithRemovedWorkspace,
|
|
32119
32710
|
armSchedules: () => armSchedules,
|
|
32711
|
+
askBlockStillWaiting: () => askBlockStillWaiting,
|
|
32120
32712
|
assertAbleTimeCredential: () => assertAbleTimeCredential,
|
|
32121
32713
|
assertAbleTimeMcpCredential: () => assertAbleTimeMcpCredential,
|
|
32122
32714
|
assertOrchestratorCapableAgent: () => assertOrchestratorCapableAgent,
|
|
@@ -32557,6 +33149,7 @@ __export(index_exports, {
|
|
|
32557
33149
|
lastAgentReply: () => lastAgentReply,
|
|
32558
33150
|
lastAssistantMessageText: () => lastAssistantMessageText,
|
|
32559
33151
|
lastRequestOccupancy: () => lastRequestOccupancy,
|
|
33152
|
+
lastTopLevelToolIsAskUser: () => lastTopLevelToolIsAskUser,
|
|
32560
33153
|
latestPendingPlanQuestions: () => latestPendingPlanQuestions,
|
|
32561
33154
|
linearAuthorizationHeader: () => linearAuthorizationHeader,
|
|
32562
33155
|
linearCycleIsActive: () => linearCycleIsActive,
|
|
@@ -32903,6 +33496,7 @@ __export(index_exports, {
|
|
|
32903
33496
|
startRelayServer: () => startRelayServer,
|
|
32904
33497
|
startRemoteAccountLogin: () => startRemoteAccountLogin,
|
|
32905
33498
|
startSlackOAuth: () => startSlackOAuth,
|
|
33499
|
+
stashMcpAppModelContext: () => stashMcpAppModelContext,
|
|
32906
33500
|
statWorktreePath: () => statWorktreePath,
|
|
32907
33501
|
stopAgentRpcServer: () => stopAgentRpcServer,
|
|
32908
33502
|
stripBrightsyNdjsonNoise: () => stripBrightsyNdjsonNoise,
|
|
@@ -33469,7 +34063,7 @@ init_schedule_runner();
|
|
|
33469
34063
|
|
|
33470
34064
|
// src/host/serve.ts
|
|
33471
34065
|
var import_node_child_process7 = require("child_process");
|
|
33472
|
-
var
|
|
34066
|
+
var import_node_os21 = require("os");
|
|
33473
34067
|
init_system_ca();
|
|
33474
34068
|
init_app_settings();
|
|
33475
34069
|
init_desktop_host();
|
|
@@ -33482,7 +34076,7 @@ init_system_ca();
|
|
|
33482
34076
|
|
|
33483
34077
|
// src/slack/public-dns.ts
|
|
33484
34078
|
var import_node_dns = require("dns");
|
|
33485
|
-
var
|
|
34079
|
+
var import_node_http3 = require("http");
|
|
33486
34080
|
var import_node_https = require("https");
|
|
33487
34081
|
var PUBLIC_DNS = ["1.1.1.1", "8.8.8.8"];
|
|
33488
34082
|
function finishLookup(options, callback, address, family) {
|
|
@@ -33612,213 +34206,12 @@ function buildPathRefAttachment(input) {
|
|
|
33612
34206
|
init_stage_files();
|
|
33613
34207
|
init_orchestrator();
|
|
33614
34208
|
|
|
33615
|
-
// src/mcp-ui
|
|
33616
|
-
|
|
33617
|
-
|
|
33618
|
-
init_meta();
|
|
33619
|
-
|
|
33620
|
-
// src/mcp-ui/session.ts
|
|
33621
|
-
var import_client2 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
33622
|
-
var import_sse = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
33623
|
-
var import_stdio = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
33624
|
-
var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
33625
|
-
init_meta();
|
|
33626
|
-
var REQUEST_TIMEOUT_MS = 2e4;
|
|
33627
|
-
var UI_CAPABILITIES = {
|
|
33628
|
-
extensions: {
|
|
33629
|
-
"io.modelcontextprotocol/ui": {
|
|
33630
|
-
mimeTypes: ["text/html;profile=mcp-app"]
|
|
33631
|
-
}
|
|
33632
|
-
}
|
|
33633
|
-
};
|
|
33634
|
-
async function openMcpUiSession(launch) {
|
|
33635
|
-
return openMcpUiSessionFromTransport(transportForLaunch(launch));
|
|
33636
|
-
}
|
|
33637
|
-
async function openMcpUiSessionFromTransport(transport) {
|
|
33638
|
-
const client = new import_client2.Client(
|
|
33639
|
-
{ name: "sideboard", version: "1.0.0" },
|
|
33640
|
-
{ capabilities: UI_CAPABILITIES }
|
|
33641
|
-
);
|
|
33642
|
-
await client.connect(transport, { timeout: REQUEST_TIMEOUT_MS });
|
|
33643
|
-
return {
|
|
33644
|
-
async listTools() {
|
|
33645
|
-
const listed = await client.listTools(void 0, { timeout: REQUEST_TIMEOUT_MS });
|
|
33646
|
-
return listed.tools.map((tool) => {
|
|
33647
|
-
const meta = tool._meta;
|
|
33648
|
-
return {
|
|
33649
|
-
name: tool.name,
|
|
33650
|
-
...tool.description ? { description: tool.description } : {},
|
|
33651
|
-
...tool.inputSchema ? { inputSchema: tool.inputSchema } : {},
|
|
33652
|
-
resourceUri: uiResourceUriFromMeta(meta),
|
|
33653
|
-
...cspFromMeta(meta) ? { csp: cspFromMeta(meta) } : {}
|
|
33654
|
-
};
|
|
33655
|
-
});
|
|
33656
|
-
},
|
|
33657
|
-
async readResource(uri) {
|
|
33658
|
-
const result = await client.readResource({ uri }, { timeout: REQUEST_TIMEOUT_MS });
|
|
33659
|
-
const content = result.contents?.[0];
|
|
33660
|
-
if (!content) return null;
|
|
33661
|
-
const text7 = "text" in content && typeof content.text === "string" ? content.text : void 0;
|
|
33662
|
-
const blob = "blob" in content && typeof content.blob === "string" ? content.blob : void 0;
|
|
33663
|
-
return {
|
|
33664
|
-
uri: content.uri,
|
|
33665
|
-
...content.mimeType ? { mimeType: content.mimeType } : {},
|
|
33666
|
-
...text7 != null ? { text: text7 } : {},
|
|
33667
|
-
...blob != null ? { blob } : {},
|
|
33668
|
-
...cspFromMeta(content._meta) ? { csp: cspFromMeta(content._meta) } : {}
|
|
33669
|
-
};
|
|
33670
|
-
},
|
|
33671
|
-
async callTool(name, args) {
|
|
33672
|
-
return client.callTool({ name, arguments: args }, void 0, { timeout: REQUEST_TIMEOUT_MS });
|
|
33673
|
-
},
|
|
33674
|
-
async close() {
|
|
33675
|
-
await client.close();
|
|
33676
|
-
}
|
|
33677
|
-
};
|
|
33678
|
-
}
|
|
33679
|
-
function transportForLaunch(launch) {
|
|
33680
|
-
if (launch.kind === "stdio") {
|
|
33681
|
-
return new import_stdio.StdioClientTransport({
|
|
33682
|
-
command: launch.command,
|
|
33683
|
-
args: launch.args,
|
|
33684
|
-
env: { ...(0, import_stdio.getDefaultEnvironment)(), ...launch.env },
|
|
33685
|
-
stderr: "ignore",
|
|
33686
|
-
...launch.cwd ? { cwd: launch.cwd } : {}
|
|
33687
|
-
});
|
|
33688
|
-
}
|
|
33689
|
-
const url = new URL(launch.url);
|
|
33690
|
-
const requestInit = launch.headers ? { headers: launch.headers } : void 0;
|
|
33691
|
-
if (launch.kind === "sse") {
|
|
33692
|
-
return new import_sse.SSEClientTransport(url, requestInit ? { requestInit } : void 0);
|
|
33693
|
-
}
|
|
33694
|
-
return new import_streamableHttp.StreamableHTTPClientTransport(url, requestInit ? { requestInit } : void 0);
|
|
33695
|
-
}
|
|
33696
|
-
|
|
33697
|
-
// src/mcp-ui/host.ts
|
|
33698
|
-
var TOOL_TTL_MS = 5 * 60 * 1e3;
|
|
33699
|
-
var McpUiHost = class {
|
|
33700
|
-
constructor(opts) {
|
|
33701
|
-
this.opts = opts;
|
|
33702
|
-
}
|
|
33703
|
-
opts;
|
|
33704
|
-
sessions = /* @__PURE__ */ new Map();
|
|
33705
|
-
toolLists = /* @__PURE__ */ new Map();
|
|
33706
|
-
async viewForClaudeTool(toolName, projectDirs) {
|
|
33707
|
-
const entries = this.userEntries(projectDirs);
|
|
33708
|
-
const match = matchClaudeMcpTool(toolName, Object.keys(entries));
|
|
33709
|
-
if (!match) return null;
|
|
33710
|
-
const launch = parseMcpServerLaunch(entries[match.server] ?? {});
|
|
33711
|
-
if (!launch) return null;
|
|
33712
|
-
try {
|
|
33713
|
-
const session = await this.sessionFor(match.server, launch);
|
|
33714
|
-
const tools = await this.toolsFor(match.server, launch, session);
|
|
33715
|
-
const tool = tools.find((item) => item.name === match.tool);
|
|
33716
|
-
if (!tool?.resourceUri) return null;
|
|
33717
|
-
const resource = await session.readResource(tool.resourceUri);
|
|
33718
|
-
if (!resource) return null;
|
|
33719
|
-
const html = htmlFromResourceContent(resource);
|
|
33720
|
-
if (!html) return null;
|
|
33721
|
-
const csp = resource.csp ?? tool.csp;
|
|
33722
|
-
return {
|
|
33723
|
-
server: match.server,
|
|
33724
|
-
tool: match.tool,
|
|
33725
|
-
uri: html.uri,
|
|
33726
|
-
mimeType: html.mimeType,
|
|
33727
|
-
html: html.html,
|
|
33728
|
-
csp: mcpUiContentSecurityPolicy(csp)
|
|
33729
|
-
};
|
|
33730
|
-
} catch (err) {
|
|
33731
|
-
console.error(
|
|
33732
|
-
`[mcp-ui] ${match.server}/${match.tool}:`,
|
|
33733
|
-
err instanceof Error ? err.message : err
|
|
33734
|
-
);
|
|
33735
|
-
return null;
|
|
33736
|
-
}
|
|
33737
|
-
}
|
|
33738
|
-
async callTool(server, tool, args, projectDirs) {
|
|
33739
|
-
const session = await this.sessionForName(server, projectDirs);
|
|
33740
|
-
if (!session) throw new Error(`MCP server ${server} is not available`);
|
|
33741
|
-
return session.callTool(tool, args);
|
|
33742
|
-
}
|
|
33743
|
-
async readResource(server, uri, projectDirs) {
|
|
33744
|
-
const session = await this.sessionForName(server, projectDirs);
|
|
33745
|
-
if (!session) throw new Error(`MCP server ${server} is not available`);
|
|
33746
|
-
const resource = await session.readResource(uri);
|
|
33747
|
-
if (!resource) throw new Error(`Resource ${uri} was empty`);
|
|
33748
|
-
return {
|
|
33749
|
-
contents: [
|
|
33750
|
-
{
|
|
33751
|
-
uri: resource.uri,
|
|
33752
|
-
...resource.mimeType ? { mimeType: resource.mimeType } : {},
|
|
33753
|
-
...resource.text != null ? { text: resource.text } : {},
|
|
33754
|
-
...resource.blob != null ? { blob: resource.blob } : {}
|
|
33755
|
-
}
|
|
33756
|
-
]
|
|
33757
|
-
};
|
|
33758
|
-
}
|
|
33759
|
-
async closeAll() {
|
|
33760
|
-
const pending = [...this.sessions.values()];
|
|
33761
|
-
this.sessions.clear();
|
|
33762
|
-
this.toolLists.clear();
|
|
33763
|
-
await Promise.all(
|
|
33764
|
-
pending.map((session) => session.then((open) => open.close()).catch(() => void 0))
|
|
33765
|
-
);
|
|
33766
|
-
}
|
|
33767
|
-
userEntries(projectDirs) {
|
|
33768
|
-
const out = {};
|
|
33769
|
-
for (const [name, entry] of Object.entries(this.opts.entries(projectDirs))) {
|
|
33770
|
-
if (!name.trim() || isInjectedOrchMcpName(name) || !entry) continue;
|
|
33771
|
-
out[name] = entry;
|
|
33772
|
-
}
|
|
33773
|
-
return out;
|
|
33774
|
-
}
|
|
33775
|
-
async sessionForName(server, projectDirs) {
|
|
33776
|
-
const entry = this.userEntries(projectDirs)[server];
|
|
33777
|
-
if (!entry) return null;
|
|
33778
|
-
const launch = parseMcpServerLaunch(entry);
|
|
33779
|
-
if (!launch) return null;
|
|
33780
|
-
return this.sessionFor(server, launch);
|
|
33781
|
-
}
|
|
33782
|
-
sessionFor(server, launch) {
|
|
33783
|
-
const key = `${server}
|
|
33784
|
-
${JSON.stringify(launch)}`;
|
|
33785
|
-
const existing = this.sessions.get(key);
|
|
33786
|
-
if (existing) return existing;
|
|
33787
|
-
const open = this.opts.openSession ?? openMcpUiSession;
|
|
33788
|
-
const pending = open(launch).catch((err) => {
|
|
33789
|
-
this.sessions.delete(key);
|
|
33790
|
-
throw err;
|
|
33791
|
-
});
|
|
33792
|
-
this.sessions.set(key, pending);
|
|
33793
|
-
return pending;
|
|
33794
|
-
}
|
|
33795
|
-
async toolsFor(server, launch, session) {
|
|
33796
|
-
const key = `${server}
|
|
33797
|
-
${JSON.stringify(launch)}`;
|
|
33798
|
-
const cached2 = this.toolLists.get(key);
|
|
33799
|
-
if (cached2 && cached2.key === key && Date.now() - cached2.at < TOOL_TTL_MS) return cached2.tools;
|
|
33800
|
-
const tools = await session.listTools();
|
|
33801
|
-
this.toolLists.set(key, { at: Date.now(), key, tools });
|
|
33802
|
-
return tools;
|
|
33803
|
-
}
|
|
33804
|
-
};
|
|
33805
|
-
var singleton2;
|
|
33806
|
-
function getMcpUiHost() {
|
|
33807
|
-
if (!singleton2) {
|
|
33808
|
-
singleton2 = new McpUiHost({
|
|
33809
|
-
entries: (projectDirs) => listUserClaudeMcpServerEntries((0, import_node_os21.homedir)(), projectDirs)
|
|
33810
|
-
});
|
|
33811
|
-
}
|
|
33812
|
-
return singleton2;
|
|
33813
|
-
}
|
|
33814
|
-
function closeMcpUiHost() {
|
|
33815
|
-
const host = singleton2;
|
|
33816
|
-
singleton2 = void 0;
|
|
33817
|
-
if (host) void host.closeAll();
|
|
33818
|
-
}
|
|
34209
|
+
// src/remote/phone-mcp-ui-listen.ts
|
|
34210
|
+
init_host();
|
|
34211
|
+
init_model_context();
|
|
33819
34212
|
|
|
33820
34213
|
// src/remote/phone-chats.ts
|
|
33821
|
-
var
|
|
34214
|
+
var import_node_crypto20 = require("crypto");
|
|
33822
34215
|
init_list_models();
|
|
33823
34216
|
init_home_board();
|
|
33824
34217
|
init_stage_files();
|
|
@@ -33840,10 +34233,10 @@ var MIN_MD_CHARS = 120;
|
|
|
33840
34233
|
function oneLine2(value, max) {
|
|
33841
34234
|
return value.replace(/[`\r\n]/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
|
|
33842
34235
|
}
|
|
33843
|
-
function
|
|
34236
|
+
function asRecord15(value) {
|
|
33844
34237
|
if (typeof value === "string") {
|
|
33845
34238
|
try {
|
|
33846
|
-
return
|
|
34239
|
+
return asRecord15(JSON.parse(value));
|
|
33847
34240
|
} catch {
|
|
33848
34241
|
return void 0;
|
|
33849
34242
|
}
|
|
@@ -33918,7 +34311,7 @@ function toolContent(input) {
|
|
|
33918
34311
|
if (!input) return "";
|
|
33919
34312
|
const direct = input.content;
|
|
33920
34313
|
if (typeof direct === "string") return direct;
|
|
33921
|
-
const nested =
|
|
34314
|
+
const nested = asRecord15(direct);
|
|
33922
34315
|
if (!nested) return "";
|
|
33923
34316
|
for (const key of ["html", "markup", "text", "source", "content", "code"]) {
|
|
33924
34317
|
if (typeof nested[key] === "string") return nested[key];
|
|
@@ -33941,7 +34334,7 @@ function phoneArtifactText(text7, parts, limit = Number.POSITIVE_INFINITY) {
|
|
|
33941
34334
|
const extras = [];
|
|
33942
34335
|
for (const part of parts ?? []) {
|
|
33943
34336
|
if (part.type !== "tool" || part.parentId || !isArtifactTool(part.name)) continue;
|
|
33944
|
-
const input =
|
|
34337
|
+
const input = asRecord15(part.input);
|
|
33945
34338
|
const content = toolContent(input);
|
|
33946
34339
|
const hint = artifactHint(content);
|
|
33947
34340
|
if (hint && hints.has(hint)) continue;
|
|
@@ -33960,7 +34353,7 @@ function phoneArtifactText(text7, parts, limit = Number.POSITIVE_INFINITY) {
|
|
|
33960
34353
|
${tail}` : tail;
|
|
33961
34354
|
}
|
|
33962
34355
|
function parseOpenArtifact(value, chatId) {
|
|
33963
|
-
const record =
|
|
34356
|
+
const record = asRecord15(value);
|
|
33964
34357
|
if (!record) return "invalid";
|
|
33965
34358
|
const title = oneLine2(str5(record.title), 200);
|
|
33966
34359
|
if (!title) return "invalid";
|
|
@@ -33983,7 +34376,7 @@ function phoneArtifactDocuments(sources) {
|
|
|
33983
34376
|
}
|
|
33984
34377
|
for (const part of source.parts ?? []) {
|
|
33985
34378
|
if (part.type !== "tool" || part.parentId || !isArtifactTool(part.name)) continue;
|
|
33986
|
-
const input =
|
|
34379
|
+
const input = asRecord15(part.input);
|
|
33987
34380
|
const content = toolContent(input);
|
|
33988
34381
|
const hint = artifactHint(content);
|
|
33989
34382
|
if (hint && hints.has(hint)) continue;
|
|
@@ -34428,13 +34821,21 @@ function parsePhoneMcpUi(value, op, chatId) {
|
|
|
34428
34821
|
}
|
|
34429
34822
|
return { op: "mcp-ui", chatId, tool: tool2, callId, reqId: reqId2 };
|
|
34430
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
|
+
}
|
|
34431
34830
|
if (op !== "mcp-ui-call" && op !== "mcp-ui-read") return "invalid";
|
|
34432
34831
|
const reqId = controlText(value, "reqId");
|
|
34433
34832
|
const server = controlText(value, "server");
|
|
34434
34833
|
if (!reqId || reqId.length > 40 || !server || server.length > 120) return "invalid";
|
|
34435
34834
|
if (op === "mcp-ui-read") {
|
|
34436
34835
|
const uri = controlText(value, "uri");
|
|
34437
|
-
if (!uri
|
|
34836
|
+
if (!uri || uri.length > 500 || /\s/.test(uri) || /^(javascript|data):/i.test(uri)) {
|
|
34837
|
+
return "invalid";
|
|
34838
|
+
}
|
|
34438
34839
|
return { op, chatId, reqId, server, uri };
|
|
34439
34840
|
}
|
|
34440
34841
|
const tool = controlText(value, "tool");
|
|
@@ -34656,7 +35057,7 @@ function parsePhoneControl(value) {
|
|
|
34656
35057
|
}
|
|
34657
35058
|
if (op === "pane") return parsePhonePane(value, chatId);
|
|
34658
35059
|
if (op === "open-artifact") return parseOpenArtifact(value, chatId);
|
|
34659
|
-
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);
|
|
34660
35061
|
if (op === "open-file" || op === "media") {
|
|
34661
35062
|
const path2 = textField(value, "path");
|
|
34662
35063
|
if (!path2 || path2.length > 2e3) return "invalid";
|
|
@@ -34828,6 +35229,7 @@ function parsePhoneCreate(value) {
|
|
|
34828
35229
|
}
|
|
34829
35230
|
function summarize(thread) {
|
|
34830
35231
|
const pr = phonePrPill(thread);
|
|
35232
|
+
const block = visibleAgentBlock(thread);
|
|
34831
35233
|
return {
|
|
34832
35234
|
id: thread.id,
|
|
34833
35235
|
title: thread.title?.trim() || "Untitled",
|
|
@@ -34838,14 +35240,12 @@ function summarize(thread) {
|
|
|
34838
35240
|
...pr?.url ? { prUrl: pr.url } : {},
|
|
34839
35241
|
...pr?.number ? { prNumber: pr.number } : {},
|
|
34840
35242
|
...pr?.status ? { prStatus: pr.status } : {},
|
|
34841
|
-
...
|
|
35243
|
+
...block ? { needsYou: true, blockedReason: block.reason } : {}
|
|
34842
35244
|
};
|
|
34843
35245
|
}
|
|
34844
35246
|
function previewOf2(thread) {
|
|
34845
|
-
const
|
|
34846
|
-
|
|
34847
|
-
if (!last) return "";
|
|
34848
|
-
return clip(last.text.replace(/\s+/g, " ").trim(), PREVIEW_LIMIT2);
|
|
35247
|
+
const last = listPhoneMessages(thread).at(-1);
|
|
35248
|
+
return last ? clip(last.text.replace(/\s+/g, " ").trim(), PREVIEW_LIMIT2) : "";
|
|
34849
35249
|
}
|
|
34850
35250
|
function repoName2(repoPath) {
|
|
34851
35251
|
return repoPath.replace(/\/$/, "").split("/").pop() || repoPath;
|
|
@@ -34924,13 +35324,13 @@ function phoneComposerOptions(thread) {
|
|
|
34924
35324
|
}
|
|
34925
35325
|
function phoneTurnAttachments(draft) {
|
|
34926
35326
|
const links = (draft.links ?? []).map((link) => ({
|
|
34927
|
-
id: (0,
|
|
35327
|
+
id: (0, import_node_crypto20.randomUUID)(),
|
|
34928
35328
|
name: link.ref,
|
|
34929
35329
|
kind: "issue",
|
|
34930
35330
|
content: [`Linked issue: ${link.ref} \u2014 ${link.title}`, link.url ? `URL: ${link.url}` : null].filter(Boolean).join("\n")
|
|
34931
35331
|
}));
|
|
34932
35332
|
const files = (draft.files ?? []).map((file) => ({
|
|
34933
|
-
id: (0,
|
|
35333
|
+
id: (0, import_node_crypto20.randomUUID)(),
|
|
34934
35334
|
name: file.name,
|
|
34935
35335
|
kind: "file",
|
|
34936
35336
|
previewDataUrl: `data:application/octet-stream;base64,${file.dataBase64}`,
|
|
@@ -35201,7 +35601,8 @@ function emitChatTurn(opts, chatId, threadId) {
|
|
|
35201
35601
|
const pending = latestPendingPlanQuestions({
|
|
35202
35602
|
messages: thread.messages,
|
|
35203
35603
|
agentBlock: thread.agentBlock,
|
|
35204
|
-
dismissedQuestionSignature: thread.dismissedQuestionSignature
|
|
35604
|
+
dismissedQuestionSignature: thread.dismissedQuestionSignature,
|
|
35605
|
+
status: thread.status
|
|
35205
35606
|
});
|
|
35206
35607
|
if (pending && result.taskState !== "failed" && result.taskState !== "canceled" && (result.taskState === "input-required" || thread.agentBlock?.source === "ask_user")) {
|
|
35207
35608
|
emitControl(opts, {
|
|
@@ -35265,7 +35666,9 @@ function deliverPhoneTurn(opts, chatId) {
|
|
|
35265
35666
|
// src/remote/phone-mcp-ui-listen.ts
|
|
35266
35667
|
var PHONE_HTML_CAP = 7e5;
|
|
35267
35668
|
function dispatchPhoneMcpUi(cmd, opts) {
|
|
35268
|
-
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
|
+
}
|
|
35269
35672
|
const thread = readPhoneThread(cmd.chatId);
|
|
35270
35673
|
const reqId = cmd.reqId;
|
|
35271
35674
|
const chatId = cmd.chatId;
|
|
@@ -35275,6 +35678,11 @@ function dispatchPhoneMcpUi(cmd, opts) {
|
|
|
35275
35678
|
return true;
|
|
35276
35679
|
}
|
|
35277
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
|
+
}
|
|
35278
35686
|
if (cmd.op === "mcp-ui-call") {
|
|
35279
35687
|
void getMcpUiHost().callTool(cmd.server, cmd.tool, cmd.args, projectDirs).then((result) => emitControl(opts, { op: "mcp-ui-call", chatId, reqId, result })).catch(
|
|
35280
35688
|
(err) => emitControl(opts, { op: "mcp-ui-call", chatId, reqId, error: phoneError(err) })
|
|
@@ -35572,7 +35980,8 @@ function republishPendingAsk(opts, chatId) {
|
|
|
35572
35980
|
const pending = latestPendingPlanQuestions({
|
|
35573
35981
|
messages: thread.messages,
|
|
35574
35982
|
agentBlock: thread.agentBlock,
|
|
35575
|
-
dismissedQuestionSignature: thread.dismissedQuestionSignature
|
|
35983
|
+
dismissedQuestionSignature: thread.dismissedQuestionSignature,
|
|
35984
|
+
status: thread.status
|
|
35576
35985
|
});
|
|
35577
35986
|
if (!pending) return;
|
|
35578
35987
|
emitControl(opts, {
|
|
@@ -36110,8 +36519,8 @@ init_fetch();
|
|
|
36110
36519
|
init_issue_attachments();
|
|
36111
36520
|
|
|
36112
36521
|
// src/integrations/linear-oauth.ts
|
|
36113
|
-
var
|
|
36114
|
-
var
|
|
36522
|
+
var import_node_crypto21 = require("crypto");
|
|
36523
|
+
var import_node_http4 = require("http");
|
|
36115
36524
|
init_app_settings();
|
|
36116
36525
|
init_fetch();
|
|
36117
36526
|
|
|
@@ -36142,8 +36551,8 @@ function linearOAuthCredentials() {
|
|
|
36142
36551
|
return { clientId, clientSecret };
|
|
36143
36552
|
}
|
|
36144
36553
|
function createLinearPkce() {
|
|
36145
|
-
const verifier = (0,
|
|
36146
|
-
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");
|
|
36147
36556
|
return { verifier, challenge };
|
|
36148
36557
|
}
|
|
36149
36558
|
function linearOAuthAuthorizeUrl(clientId, state, codeChallenge) {
|
|
@@ -36274,7 +36683,7 @@ async function startLinearOAuth(opts) {
|
|
|
36274
36683
|
throw new LinearOAuthCancelledError();
|
|
36275
36684
|
}
|
|
36276
36685
|
const { clientId, clientSecret } = linearOAuthCredentials();
|
|
36277
|
-
const state = (0,
|
|
36686
|
+
const state = (0, import_node_crypto21.randomBytes)(16).toString("hex");
|
|
36278
36687
|
const pkce = createLinearPkce();
|
|
36279
36688
|
const authorizeUrl = linearOAuthAuthorizeUrl(clientId, state, pkce.challenge);
|
|
36280
36689
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
@@ -36287,7 +36696,7 @@ async function startLinearOAuth(opts) {
|
|
|
36287
36696
|
if (err) reject(err);
|
|
36288
36697
|
else resolve3(value);
|
|
36289
36698
|
};
|
|
36290
|
-
const server = (0,
|
|
36699
|
+
const server = (0, import_node_http4.createServer)((req, res) => {
|
|
36291
36700
|
try {
|
|
36292
36701
|
const url = new URL(req.url || "/", `http://127.0.0.1:${LINEAR_OAUTH_PORT}`);
|
|
36293
36702
|
if (url.pathname !== "/callback") {
|
|
@@ -37835,7 +38244,8 @@ function runCoordinatorPrompt(opts, body, generation) {
|
|
|
37835
38244
|
const pending = latestPendingPlanQuestions({
|
|
37836
38245
|
messages: thread.messages,
|
|
37837
38246
|
agentBlock: thread.agentBlock,
|
|
37838
|
-
dismissedQuestionSignature: thread.dismissedQuestionSignature
|
|
38247
|
+
dismissedQuestionSignature: thread.dismissedQuestionSignature,
|
|
38248
|
+
status: thread.status
|
|
37839
38249
|
});
|
|
37840
38250
|
if (pending && result.taskState !== "failed" && result.taskState !== "canceled" && (result.taskState === "input-required" || thread.agentBlock?.source === "ask_user")) {
|
|
37841
38251
|
opts.onOutbound({
|
|
@@ -38284,7 +38694,15 @@ init_paths();
|
|
|
38284
38694
|
init_thread_store();
|
|
38285
38695
|
var PHONE_BOARD_SYNC_MS = 300;
|
|
38286
38696
|
function chatKey(row2) {
|
|
38287
|
-
return [
|
|
38697
|
+
return [
|
|
38698
|
+
row2.id,
|
|
38699
|
+
row2.title,
|
|
38700
|
+
row2.status,
|
|
38701
|
+
row2.agent,
|
|
38702
|
+
row2.preview,
|
|
38703
|
+
row2.needsYou ? "1" : "0",
|
|
38704
|
+
row2.blockedReason ?? ""
|
|
38705
|
+
].join(" ");
|
|
38288
38706
|
}
|
|
38289
38707
|
function phoneBoardKey(sidebar) {
|
|
38290
38708
|
const orchestration = sidebar.orchestration.map(chatKey).join("\n");
|
|
@@ -38691,7 +39109,7 @@ function runRemoteHost(opts) {
|
|
|
38691
39109
|
init_protocol();
|
|
38692
39110
|
|
|
38693
39111
|
// src/relay/server.ts
|
|
38694
|
-
var
|
|
39112
|
+
var import_node_http5 = require("http");
|
|
38695
39113
|
var import_ws4 = require("ws");
|
|
38696
39114
|
|
|
38697
39115
|
// src/slack/oauth-redirect.ts
|
|
@@ -39100,7 +39518,7 @@ function connectSession(ws, opts, log) {
|
|
|
39100
39518
|
}
|
|
39101
39519
|
|
|
39102
39520
|
// src/slack/relay-protocol.ts
|
|
39103
|
-
var
|
|
39521
|
+
var import_node_crypto22 = require("crypto");
|
|
39104
39522
|
var SLACK_RELAY_PING_INTERVAL_MS = 2e4;
|
|
39105
39523
|
var SLACK_RELAY_PONG_TIMEOUT_MS = 15e3;
|
|
39106
39524
|
function slackRelaySessionKey(teamId, userId, deviceId) {
|
|
@@ -39110,7 +39528,7 @@ function slackRelayUserKey(teamId, userId) {
|
|
|
39110
39528
|
return `${teamId.trim()}:${userId.trim()}`;
|
|
39111
39529
|
}
|
|
39112
39530
|
function newSlackRelayEventId() {
|
|
39113
|
-
return (0,
|
|
39531
|
+
return (0, import_node_crypto22.randomBytes)(12).toString("hex");
|
|
39114
39532
|
}
|
|
39115
39533
|
function parseSlackRelayClientMessage(raw) {
|
|
39116
39534
|
try {
|
|
@@ -39638,7 +40056,7 @@ async function tryServeStatic(req, res, root) {
|
|
|
39638
40056
|
}
|
|
39639
40057
|
|
|
39640
40058
|
// src/remote/hub.ts
|
|
39641
|
-
var
|
|
40059
|
+
var import_node_crypto23 = require("crypto");
|
|
39642
40060
|
init_protocol();
|
|
39643
40061
|
var CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
39644
40062
|
var CODE_TTL_MS = 10 * 60 * 1e3;
|
|
@@ -39649,7 +40067,7 @@ function send(socket, msg) {
|
|
|
39649
40067
|
}
|
|
39650
40068
|
}
|
|
39651
40069
|
function newCode() {
|
|
39652
|
-
const bytes = (0,
|
|
40070
|
+
const bytes = (0, import_node_crypto23.randomBytes)(6);
|
|
39653
40071
|
let code = "";
|
|
39654
40072
|
for (let i = 0; i < 6; i++) code += CODE_ALPHABET[bytes[i] % CODE_ALPHABET.length];
|
|
39655
40073
|
return code;
|
|
@@ -39908,7 +40326,7 @@ var RemoteHub = class {
|
|
|
39908
40326
|
host.phone = null;
|
|
39909
40327
|
}
|
|
39910
40328
|
const created = sessionToken == null;
|
|
39911
|
-
const token = sessionToken ?? (0,
|
|
40329
|
+
const token = sessionToken ?? (0, import_node_crypto23.randomBytes)(24).toString("hex");
|
|
39912
40330
|
if (host.sessionToken && host.sessionToken !== token) {
|
|
39913
40331
|
this.phonesByToken.delete(host.sessionToken);
|
|
39914
40332
|
}
|
|
@@ -39960,7 +40378,7 @@ var RemoteHub = class {
|
|
|
39960
40378
|
init_protocol();
|
|
39961
40379
|
|
|
39962
40380
|
// src/relay/accounts.ts
|
|
39963
|
-
var
|
|
40381
|
+
var import_node_crypto24 = require("crypto");
|
|
39964
40382
|
var import_node_fs70 = require("fs");
|
|
39965
40383
|
var import_node_module7 = require("module");
|
|
39966
40384
|
var import_node_path68 = require("path");
|
|
@@ -39979,12 +40397,12 @@ function openDatabase(filePath) {
|
|
|
39979
40397
|
return db;
|
|
39980
40398
|
}
|
|
39981
40399
|
function sha2562(value) {
|
|
39982
|
-
return (0,
|
|
40400
|
+
return (0, import_node_crypto24.createHash)("sha256").update(value).digest("hex");
|
|
39983
40401
|
}
|
|
39984
40402
|
function sameHash(a, b) {
|
|
39985
40403
|
const left = Buffer.from(a);
|
|
39986
40404
|
const right = Buffer.from(b);
|
|
39987
|
-
return left.length === right.length && (0,
|
|
40405
|
+
return left.length === right.length && (0, import_node_crypto24.timingSafeEqual)(left, right);
|
|
39988
40406
|
}
|
|
39989
40407
|
function normalizeEmail(email) {
|
|
39990
40408
|
const trimmed = email?.trim().toLowerCase() ?? "";
|
|
@@ -40089,7 +40507,7 @@ var RelayAccountStore = class {
|
|
|
40089
40507
|
this.insertIdentity(issuer, subject, accountId, email, verified);
|
|
40090
40508
|
} else {
|
|
40091
40509
|
const byEmail = verified ? this.accountIdForVerifiedEmail(email) : void 0;
|
|
40092
|
-
accountId = byEmail ?? (0,
|
|
40510
|
+
accountId = byEmail ?? (0, import_node_crypto24.randomUUID)();
|
|
40093
40511
|
if (!byEmail) {
|
|
40094
40512
|
this.db.prepare("INSERT INTO accounts (id, created_at, device_cap) VALUES (?, ?, ?)").run(accountId, Date.now(), RELAY_DEVICE_CAP);
|
|
40095
40513
|
}
|
|
@@ -40211,7 +40629,7 @@ var RelayAccountStore = class {
|
|
|
40211
40629
|
).run(issuer, subject, accountId, email, verified ? 1 : 0);
|
|
40212
40630
|
}
|
|
40213
40631
|
mintCredential(accountId) {
|
|
40214
|
-
const credential = (0,
|
|
40632
|
+
const credential = (0, import_node_crypto24.randomBytes)(32).toString("hex");
|
|
40215
40633
|
this.db.prepare("INSERT INTO credentials (token_hash, account_id, created_at) VALUES (?, ?, ?)").run(sha2562(credential), accountId, Date.now());
|
|
40216
40634
|
return credential;
|
|
40217
40635
|
}
|
|
@@ -40686,7 +41104,7 @@ async function startRelayServer(opts) {
|
|
|
40686
41104
|
sendJson2(res, 200, { ok: true, ...value.payload });
|
|
40687
41105
|
return true;
|
|
40688
41106
|
};
|
|
40689
|
-
const httpServer = (0,
|
|
41107
|
+
const httpServer = (0, import_node_http5.createServer)((req, res) => {
|
|
40690
41108
|
void (async () => {
|
|
40691
41109
|
const reqUrl = req.url || "/";
|
|
40692
41110
|
if (accountStore && await handleRelayAccountHttp({
|
|
@@ -41023,7 +41441,7 @@ async function bindAbort(signal, stop) {
|
|
|
41023
41441
|
}
|
|
41024
41442
|
function flatInterfaces() {
|
|
41025
41443
|
const out = [];
|
|
41026
|
-
for (const rows of Object.values((0,
|
|
41444
|
+
for (const rows of Object.values((0, import_node_os21.networkInterfaces)())) {
|
|
41027
41445
|
if (!rows) continue;
|
|
41028
41446
|
out.push(...rows);
|
|
41029
41447
|
}
|
|
@@ -41120,7 +41538,7 @@ init_stage_files();
|
|
|
41120
41538
|
init_consume_attachments();
|
|
41121
41539
|
|
|
41122
41540
|
// src/composer/pasted-text.ts
|
|
41123
|
-
var
|
|
41541
|
+
var import_node_crypto25 = require("crypto");
|
|
41124
41542
|
var PASTE_ATTACH_MIN_CHARS = 1200;
|
|
41125
41543
|
var PASTE_ATTACH_MIN_LINES = 15;
|
|
41126
41544
|
var PASTED_NAME_RE = /^Pasted text #(\d+)\.txt$/i;
|
|
@@ -41147,7 +41565,7 @@ function nextPastedTextName(existing) {
|
|
|
41147
41565
|
}
|
|
41148
41566
|
function buildPastedTextAttachment(text7, opts) {
|
|
41149
41567
|
return {
|
|
41150
|
-
id: opts?.id ?? (0,
|
|
41568
|
+
id: opts?.id ?? (0, import_node_crypto25.randomUUID)(),
|
|
41151
41569
|
name: opts?.name ?? "Pasted text #1.txt",
|
|
41152
41570
|
kind: "file",
|
|
41153
41571
|
path: opts?.path,
|
|
@@ -41323,7 +41741,7 @@ function createClippedMcpServer() {
|
|
|
41323
41741
|
|
|
41324
41742
|
// src/mcp/server.ts
|
|
41325
41743
|
var import_zod11 = require("zod");
|
|
41326
|
-
var
|
|
41744
|
+
var import_node_crypto28 = require("crypto");
|
|
41327
41745
|
var import_node_path73 = require("path");
|
|
41328
41746
|
init_orchestrator();
|
|
41329
41747
|
init_task_state();
|
|
@@ -42915,7 +43333,7 @@ function registerScheduleTools(server) {
|
|
|
42915
43333
|
}
|
|
42916
43334
|
|
|
42917
43335
|
// src/agent-rpc/handlers.ts
|
|
42918
|
-
var
|
|
43336
|
+
var import_node_crypto26 = require("crypto");
|
|
42919
43337
|
var import_node_path70 = require("path");
|
|
42920
43338
|
init_wait_for_job();
|
|
42921
43339
|
init_wait_for_turn();
|
|
@@ -42946,7 +43364,7 @@ setToolPermissionPublisher({
|
|
|
42946
43364
|
}
|
|
42947
43365
|
}
|
|
42948
43366
|
});
|
|
42949
|
-
function
|
|
43367
|
+
function asRecord16(value) {
|
|
42950
43368
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
42951
43369
|
return value;
|
|
42952
43370
|
}
|
|
@@ -42957,12 +43375,12 @@ function invalidParams(message) {
|
|
|
42957
43375
|
return Object.assign(new Error(message), { rpcCode: -32602 });
|
|
42958
43376
|
}
|
|
42959
43377
|
var handlePermissionAsk = async (params, _ctx) => {
|
|
42960
|
-
const rec =
|
|
43378
|
+
const rec = asRecord16(params);
|
|
42961
43379
|
const threadId = str6(rec.threadId).trim();
|
|
42962
43380
|
const toolName = str6(rec.toolName).trim();
|
|
42963
43381
|
if (!threadId) throw invalidParams("threadId is required");
|
|
42964
43382
|
if (!toolName) throw invalidParams("toolName is required");
|
|
42965
|
-
const input =
|
|
43383
|
+
const input = asRecord16(rec.input);
|
|
42966
43384
|
const ask = {
|
|
42967
43385
|
threadId,
|
|
42968
43386
|
toolName,
|
|
@@ -42998,7 +43416,7 @@ var handlePermissionAsk = async (params, _ctx) => {
|
|
|
42998
43416
|
// src/agent-rpc/handlers.ts
|
|
42999
43417
|
init_protocol2();
|
|
43000
43418
|
function presentArtifactResult(input) {
|
|
43001
|
-
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)}`;
|
|
43002
43420
|
return {
|
|
43003
43421
|
ok: true,
|
|
43004
43422
|
artifact_id: id,
|
|
@@ -43010,7 +43428,7 @@ function presentArtifactResult(input) {
|
|
|
43010
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."
|
|
43011
43429
|
};
|
|
43012
43430
|
}
|
|
43013
|
-
function
|
|
43431
|
+
function asRecord17(value) {
|
|
43014
43432
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
43015
43433
|
return value;
|
|
43016
43434
|
}
|
|
@@ -43034,7 +43452,7 @@ async function handleRuntimePing(_params, _ctx) {
|
|
|
43034
43452
|
};
|
|
43035
43453
|
}
|
|
43036
43454
|
async function handlePresentArtifact(params, _ctx) {
|
|
43037
|
-
const rec =
|
|
43455
|
+
const rec = asRecord17(params);
|
|
43038
43456
|
const title = str7(rec.title).trim();
|
|
43039
43457
|
const type = str7(rec.type).trim();
|
|
43040
43458
|
const allowed = ["html", "svg", "markdown", "react", "log"];
|
|
@@ -43058,7 +43476,7 @@ async function handlePresentArtifact(params, _ctx) {
|
|
|
43058
43476
|
});
|
|
43059
43477
|
}
|
|
43060
43478
|
async function handleJobWait(params, ctx, waitFn = waitForDetachedJob) {
|
|
43061
|
-
const rec =
|
|
43479
|
+
const rec = asRecord17(params);
|
|
43062
43480
|
const id = str7(rec.id).trim();
|
|
43063
43481
|
if (!id) throw invalidParams2("id is required");
|
|
43064
43482
|
const cwd = jobCwd(rec);
|
|
@@ -43082,7 +43500,7 @@ async function handleJobWait(params, ctx, waitFn = waitForDetachedJob) {
|
|
|
43082
43500
|
};
|
|
43083
43501
|
}
|
|
43084
43502
|
async function handleJobStop(params, _ctx) {
|
|
43085
|
-
const rec =
|
|
43503
|
+
const rec = asRecord17(params);
|
|
43086
43504
|
const id = str7(rec.id).trim();
|
|
43087
43505
|
if (!id) throw invalidParams2("id is required");
|
|
43088
43506
|
const reason = str7(rec.reason).trim() || void 0;
|
|
@@ -43110,7 +43528,7 @@ async function defaultTurnWait(ref, timeoutMs) {
|
|
|
43110
43528
|
});
|
|
43111
43529
|
}
|
|
43112
43530
|
async function handleTurnWait(params, ctx, waitFn = defaultTurnWait) {
|
|
43113
|
-
const rec =
|
|
43531
|
+
const rec = asRecord17(params);
|
|
43114
43532
|
const ref = str7(rec.ref).trim();
|
|
43115
43533
|
if (!ref) throw invalidParams2("ref is required");
|
|
43116
43534
|
const requested = typeof rec.timeoutMs === "number" && Number.isFinite(rec.timeoutMs) ? rec.timeoutMs : void 0;
|
|
@@ -43162,7 +43580,7 @@ init_worktree();
|
|
|
43162
43580
|
init_paths();
|
|
43163
43581
|
|
|
43164
43582
|
// src/board/board-pins.ts
|
|
43165
|
-
var
|
|
43583
|
+
var import_node_crypto27 = require("crypto");
|
|
43166
43584
|
var import_node_fs72 = require("fs");
|
|
43167
43585
|
var import_node_path71 = require("path");
|
|
43168
43586
|
init_paths();
|
|
@@ -43194,7 +43612,7 @@ function addBoardPin(input) {
|
|
|
43194
43612
|
const ref = input.ref.trim();
|
|
43195
43613
|
if (!ref) throw new Error("Board item needs a ref");
|
|
43196
43614
|
const pin = {
|
|
43197
|
-
id: (0,
|
|
43615
|
+
id: (0, import_node_crypto27.randomUUID)(),
|
|
43198
43616
|
kind: input.kind,
|
|
43199
43617
|
ref,
|
|
43200
43618
|
repoPath: input.repoPath.trim(),
|
|
@@ -44127,7 +44545,7 @@ async function startMcpServer() {
|
|
|
44127
44545
|
const ident = issue?.identifier ?? ref.trim();
|
|
44128
44546
|
const attachments = issue ? [
|
|
44129
44547
|
{
|
|
44130
|
-
id: (0,
|
|
44548
|
+
id: (0, import_node_crypto28.randomUUID)(),
|
|
44131
44549
|
name: issue.identifier,
|
|
44132
44550
|
kind: "issue",
|
|
44133
44551
|
content: [
|
|
@@ -44689,8 +45107,8 @@ init_protocol2();
|
|
|
44689
45107
|
init_metadata();
|
|
44690
45108
|
|
|
44691
45109
|
// src/agent-rpc/server.ts
|
|
44692
|
-
var
|
|
44693
|
-
var
|
|
45110
|
+
var import_node_crypto29 = require("crypto");
|
|
45111
|
+
var import_node_http6 = require("http");
|
|
44694
45112
|
var import_ws5 = require("ws");
|
|
44695
45113
|
init_protocol2();
|
|
44696
45114
|
init_metadata();
|
|
@@ -44698,7 +45116,7 @@ function tokensEqual(a, b) {
|
|
|
44698
45116
|
const left = Buffer.from(a);
|
|
44699
45117
|
const right = Buffer.from(b);
|
|
44700
45118
|
if (left.length !== right.length) return false;
|
|
44701
|
-
return (0,
|
|
45119
|
+
return (0, import_node_crypto29.timingSafeEqual)(left, right);
|
|
44702
45120
|
}
|
|
44703
45121
|
function authTokenFromUpgrade(req) {
|
|
44704
45122
|
try {
|
|
@@ -44731,16 +45149,16 @@ var AgentRpcServer = class {
|
|
|
44731
45149
|
async listen(opts = {}) {
|
|
44732
45150
|
const host = opts.host ?? "127.0.0.1";
|
|
44733
45151
|
const port = opts.port ?? 0;
|
|
44734
|
-
const authToken = (0,
|
|
45152
|
+
const authToken = (0, import_node_crypto29.randomBytes)(24).toString("base64url");
|
|
44735
45153
|
this.meta = {
|
|
44736
|
-
runtimeId: (0,
|
|
45154
|
+
runtimeId: (0, import_node_crypto29.randomUUID)(),
|
|
44737
45155
|
pid: process.pid,
|
|
44738
45156
|
protocolVersion: AGENT_RPC_PROTOCOL_VERSION,
|
|
44739
45157
|
authToken,
|
|
44740
45158
|
startedAt: Date.now(),
|
|
44741
45159
|
transports: []
|
|
44742
45160
|
};
|
|
44743
|
-
const http = (0,
|
|
45161
|
+
const http = (0, import_node_http6.createServer)((_req, res) => {
|
|
44744
45162
|
res.statusCode = 404;
|
|
44745
45163
|
res.end();
|
|
44746
45164
|
});
|
|
@@ -45226,6 +45644,8 @@ init_oauth();
|
|
|
45226
45644
|
init_injected_mcp();
|
|
45227
45645
|
init_user_mcp_config();
|
|
45228
45646
|
init_orch_mcp_isolation();
|
|
45647
|
+
init_host();
|
|
45648
|
+
init_model_context();
|
|
45229
45649
|
init_meta();
|
|
45230
45650
|
|
|
45231
45651
|
// src/slack/workspaces.ts
|
|
@@ -45324,7 +45744,7 @@ function slackTokenFor(ws, kind = "read") {
|
|
|
45324
45744
|
}
|
|
45325
45745
|
|
|
45326
45746
|
// src/slack/oauth.ts
|
|
45327
|
-
var
|
|
45747
|
+
var import_node_crypto30 = require("crypto");
|
|
45328
45748
|
init_app_settings();
|
|
45329
45749
|
var SLACK_BOT_SCOPES = [
|
|
45330
45750
|
"app_mentions:read",
|
|
@@ -45418,7 +45838,7 @@ async function startSlackOAuth(opts) {
|
|
|
45418
45838
|
throw new SlackOAuthCancelledError();
|
|
45419
45839
|
}
|
|
45420
45840
|
const { clientId } = slackOAuthCredentials();
|
|
45421
|
-
const state = (0,
|
|
45841
|
+
const state = (0, import_node_crypto30.randomBytes)(16).toString("hex");
|
|
45422
45842
|
const authorizeUrl = slackOAuthAuthorizeUrl(clientId, state);
|
|
45423
45843
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
45424
45844
|
const pollIntervalMs = opts?.pollIntervalMs ?? 400;
|
|
@@ -46327,7 +46747,7 @@ function resolveSlackListenMode(opts) {
|
|
|
46327
46747
|
init_protocol();
|
|
46328
46748
|
|
|
46329
46749
|
// src/relay/account-login.ts
|
|
46330
|
-
var
|
|
46750
|
+
var import_node_crypto31 = require("crypto");
|
|
46331
46751
|
init_fetch();
|
|
46332
46752
|
init_protocol();
|
|
46333
46753
|
var RemoteAccountLoginCancelled = class extends Error {
|
|
@@ -46395,7 +46815,7 @@ async function readJson4(res, url) {
|
|
|
46395
46815
|
async function startRemoteAccountLogin(opts) {
|
|
46396
46816
|
if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
|
|
46397
46817
|
const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
|
|
46398
|
-
const state = (0,
|
|
46818
|
+
const state = (0, import_node_crypto31.randomBytes)(16).toString("hex");
|
|
46399
46819
|
const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
|
|
46400
46820
|
const pollIntervalMs = opts.pollIntervalMs ?? 400;
|
|
46401
46821
|
const linkToken = opts.linkToken?.trim() ?? "";
|
|
@@ -47003,6 +47423,7 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
47003
47423
|
archiveRemovedWorkspaceChats,
|
|
47004
47424
|
archivesWithRemovedWorkspace,
|
|
47005
47425
|
armSchedules,
|
|
47426
|
+
askBlockStillWaiting,
|
|
47006
47427
|
assertAbleTimeCredential,
|
|
47007
47428
|
assertAbleTimeMcpCredential,
|
|
47008
47429
|
assertOrchestratorCapableAgent,
|
|
@@ -47443,6 +47864,7 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
47443
47864
|
lastAgentReply,
|
|
47444
47865
|
lastAssistantMessageText,
|
|
47445
47866
|
lastRequestOccupancy,
|
|
47867
|
+
lastTopLevelToolIsAskUser,
|
|
47446
47868
|
latestPendingPlanQuestions,
|
|
47447
47869
|
linearAuthorizationHeader,
|
|
47448
47870
|
linearCycleIsActive,
|
|
@@ -47789,6 +48211,7 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
47789
48211
|
startRelayServer,
|
|
47790
48212
|
startRemoteAccountLogin,
|
|
47791
48213
|
startSlackOAuth,
|
|
48214
|
+
stashMcpAppModelContext,
|
|
47792
48215
|
statWorktreePath,
|
|
47793
48216
|
stopAgentRpcServer,
|
|
47794
48217
|
stripBrightsyNdjsonNoise,
|