@qredence/fleet 0.5.11 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/web/client/assets/{artifacts-panel-CQmFEF_H.js → artifacts-panel-CJ75gQub.js} +1 -1
- package/dist/web/client/assets/chat-Ci2cEQrR.js +52 -0
- package/dist/web/client/assets/{chat-command-palette-CmHTS3rs.js → chat-command-palette-CkISHfKE.js} +1 -1
- package/dist/web/client/assets/{command-DPfiaYUL.js → command-_WjnervL.js} +1 -1
- package/dist/web/client/assets/fleet-message-queue-BCno4XP-.js +1 -0
- package/dist/web/client/assets/{horizontal-resize-qK6eRhIG.js → horizontal-resize-CwoDojST.js} +1 -1
- package/dist/web/client/assets/{index-C1zOjrMK.js → index-DJ1fFbQu.js} +2 -2
- package/dist/web/client/assets/input-group-Tb5TYbzi.js +1 -0
- package/dist/web/client/assets/{model-selector-list-DsKTuAgS.js → model-selector-list-Ch05B2nZ.js} +1 -1
- package/dist/web/client/assets/{openui-renderer-J3dhPpL4.js → openui-renderer-Bf60nxNi.js} +5 -5
- package/dist/web/client/assets/pencil-DcUwsKLn.js +1 -0
- package/dist/web/client/assets/{provider-label-Dpr7djG9.js → provider-label-DDLRnZyC.js} +1 -1
- package/dist/web/client/assets/{right-panel-registry-DewpBWHM.js → right-panel-registry-Dp8yX-oL.js} +2 -2
- package/dist/web/client/assets/routes-DpgMJZ5n.js +16 -0
- package/dist/web/client/assets/settings-dialog-YJkvt5EB.js +2 -0
- package/dist/web/client/assets/{subagent-chat-panel-DkVUumrP.js → subagent-chat-panel-Yujplxpb.js} +1 -1
- package/dist/web/client/assets/{subagent-transcript-D8wmQxXe.js → subagent-transcript-CnI-mqN0.js} +1 -1
- package/dist/web/client/assets/{subagents-panel-BMp2Ego0.js → subagents-panel-CjXEdimj.js} +1 -1
- package/dist/web/client/assets/{virtualized-turn-list-DMJENRY0.js → virtualized-turn-list--Vynre4D.js} +2 -2
- package/dist/web/client/assets/{workspace-panel-G6yMpKJ8.js → workspace-panel-CPPIznT9.js} +1 -1
- package/dist/web/client/bundle-budget.json +6 -6
- package/dist/web/server/{_tanstack-start-manifest_v-po4woX6g-AUGCOEZ2.js → _tanstack-start-manifest_v-DS_CSIFQ-WB3VTKF3.js} +10 -9
- package/dist/web/server/{artifacts-panel-8GGUCtOd-X5TNKTY2.js → artifacts-panel-CaKrX2XC-R37I4BHF.js} +5 -5
- package/dist/web/server/{chat-command-palette-Dgl5tqWn-72LLEWUD.js → chat-command-palette-7gbqEnm9-6XICQZN7.js} +4 -4
- package/dist/web/server/{chunk-WILCIZYU.js → chunk-BBBS5AS7.js} +2 -2
- package/dist/web/server/{chunk-O4OTWWPF.js → chunk-CNXJN5HN.js} +4 -4
- package/dist/web/server/{chunk-XKKXXG6N.js → chunk-DI7XRK2H.js} +2 -2
- package/dist/web/server/{chunk-BXWAUTTH.js → chunk-DZ2IC3FH.js} +2 -2
- package/dist/web/server/{chunk-7MDZVLIY.js → chunk-EAE2QXRK.js} +1 -1
- package/dist/web/server/{chunk-JUROEEWM.js → chunk-EH4BZ6QM.js} +82 -4
- package/dist/web/server/{chunk-ABBWBBSS.js → chunk-KELEYPVK.js} +4 -4
- package/dist/web/server/{chunk-RNOJACWQ.js → chunk-LXJD6IGW.js} +2 -2
- package/dist/web/server/chunk-M5RSPNYN.js +22 -0
- package/dist/web/server/{chunk-P7H2OPKF.js → chunk-PIOFZUOU.js} +9 -1
- package/dist/web/server/chunk-PTCKOR23.js +39 -0
- package/dist/web/server/{chunk-MIW4LJTV.js → chunk-TWYHHG5N.js} +1 -9
- package/dist/web/server/{chunk-WKV2Z4KO.js → chunk-WHBVQJ4K.js} +2 -2
- package/dist/web/server/{chunk-GGT2ZKDB.js → chunk-YNUWKMNQ.js} +11 -4
- package/dist/web/server/fleet-message-queue-BS-cZ56r-GLZXUKDF.js +152 -0
- package/dist/web/server/{model-selector-list-OYnzNbyu-HBGCNF2L.js → model-selector-list-jBTZc2Mu-OXJOS5NA.js} +3 -3
- package/dist/web/server/{openui-renderer-Cj7kfqyL-EKJ6JTTQ.js → openui-renderer-Biyyjhjn-SJOEKPTJ.js} +4 -4
- package/dist/web/server/{router-Ci1wxI7I-E2AYMNON.js → router-DWALoX_M-I5CBL7FQ.js} +1228 -459
- package/dist/web/server/{routes-CRpm9-Sa-IYK6MUJO.js → routes-BBVirYfL-5WXMOT7M.js} +223 -49
- package/dist/web/server/server.js +2 -2
- package/dist/web/server/{settings-dialog-BvkgNflv-GPJ6COQO.js → settings-dialog-DndPbM-v-RFNXXEAN.js} +890 -567
- package/dist/web/server/{subagent-chat-panel-CMuvW9Sd-M5TEEGQW.js → subagent-chat-panel-C0RpnXav-J7VYO7QY.js} +3 -3
- package/dist/web/server/{subagents-panel-DgfB6_Yy-4INEPE3Y.js → subagents-panel-jDqIn9Nh-YEV6QLUY.js} +3 -3
- package/dist/web/server/{workspace-panel-bpwj-Veu-Q2CEJMN4.js → workspace-panel-CX_Vo6As-EWO6AMPI.js} +3 -3
- package/package.json +1 -1
- package/dist/web/client/assets/chat-yh02zgA7.js +0 -52
- package/dist/web/client/assets/fleet-message-queue-DUz6Hfrf.js +0 -1
- package/dist/web/client/assets/input-group-BFDsCVS9.js +0 -1
- package/dist/web/client/assets/routes-vNkVToAF.js +0 -16
- package/dist/web/client/assets/settings-dialog-B-v4me3Y.js +0 -1
- package/dist/web/server/chunk-QK4CHLVV.js +0 -17
- package/dist/web/server/fleet-message-queue-j0DCU5Xy-5HKBHMPV.js +0 -75
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ChatMcpDeleteRequestSchema,
|
|
3
|
+
ChatMcpOAuthLoginRequestSchema,
|
|
4
|
+
ChatMcpUpsertRequestSchema,
|
|
2
5
|
ChatModelsDiscoverRequestSchema,
|
|
3
6
|
ChatProviderOAuthLoginRequestSchema,
|
|
4
7
|
ChatProviderRemoveRequestSchema,
|
|
@@ -12,7 +15,7 @@ import {
|
|
|
12
15
|
domAnimation,
|
|
13
16
|
initAnalytics,
|
|
14
17
|
isServer
|
|
15
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-EH4BZ6QM.js";
|
|
16
19
|
import {
|
|
17
20
|
DEFAULT_UI_PREFERENCES,
|
|
18
21
|
isModelPatternEnabled,
|
|
@@ -22,8 +25,10 @@ import {
|
|
|
22
25
|
Toaster
|
|
23
26
|
} from "./chunk-KOUEJ3NU.js";
|
|
24
27
|
import {
|
|
28
|
+
fallbackSessionLabel,
|
|
29
|
+
meaningfulSessionLabel,
|
|
25
30
|
redactSessionLabelSecrets
|
|
26
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-PTCKOR23.js";
|
|
27
32
|
import "./chunk-SZJUXVWG.js";
|
|
28
33
|
import "./chunk-TNL4YV63.js";
|
|
29
34
|
import {
|
|
@@ -37,7 +42,7 @@ import {
|
|
|
37
42
|
CardHeader,
|
|
38
43
|
CardTitle,
|
|
39
44
|
validateAndNormalizeOpenUIHtmlArtifact
|
|
40
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-EAE2QXRK.js";
|
|
41
46
|
import {
|
|
42
47
|
ChatNewRequestSchema,
|
|
43
48
|
ChatOpenUIArtifactUpsertRequestSchema,
|
|
@@ -57,7 +62,7 @@ import {
|
|
|
57
62
|
UploadedAttachmentSchema,
|
|
58
63
|
ZodError,
|
|
59
64
|
external_exports
|
|
60
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-YNUWKMNQ.js";
|
|
61
66
|
import {
|
|
62
67
|
KNOWN_PROVIDERS,
|
|
63
68
|
OPENAI_CHAT_COMPLETIONS_PROVIDER_ID,
|
|
@@ -91,7 +96,7 @@ import "./chunk-JDCCC7A7.js";
|
|
|
91
96
|
import "./chunk-L547YHC4.js";
|
|
92
97
|
import "./chunk-MLKGABMK.js";
|
|
93
98
|
|
|
94
|
-
// web/app/dist/server/assets/router-
|
|
99
|
+
// web/app/dist/server/assets/router-DWALoX_M.js
|
|
95
100
|
import { useEffect, useLayoutEffect } from "react";
|
|
96
101
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
97
102
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -140,7 +145,7 @@ function getQueryClient() {
|
|
|
140
145
|
if (!browserQueryClient) browserQueryClient = makeQueryClient();
|
|
141
146
|
return browserQueryClient;
|
|
142
147
|
}
|
|
143
|
-
var Route$
|
|
148
|
+
var Route$29 = createRootRoute({
|
|
144
149
|
head: () => ({
|
|
145
150
|
meta: [
|
|
146
151
|
{ charSet: "utf-8" },
|
|
@@ -210,8 +215,8 @@ function RootDocument({ children }) {
|
|
|
210
215
|
] })]
|
|
211
216
|
});
|
|
212
217
|
}
|
|
213
|
-
var $$splitComponentImporter = () => import("./routes-
|
|
214
|
-
var Route$
|
|
218
|
+
var $$splitComponentImporter = () => import("./routes-BBVirYfL-5WXMOT7M.js");
|
|
219
|
+
var Route$28 = createFileRoute("/")({ component: lazyRouteComponent($$splitComponentImporter, "component") });
|
|
215
220
|
var ManagedAttachmentValidationError = class extends Error {
|
|
216
221
|
status;
|
|
217
222
|
constructor(message, status) {
|
|
@@ -5626,9 +5631,14 @@ var PrimeBridge = class {
|
|
|
5626
5631
|
async followUp(sessionId, text) {
|
|
5627
5632
|
await this.#requireSession(sessionId).connection.followUp(text);
|
|
5628
5633
|
}
|
|
5629
|
-
async
|
|
5634
|
+
async mutateQueuedMessage(sessionId, lane, index, expectedText, mutation) {
|
|
5630
5635
|
const session = this.#requireSession(sessionId);
|
|
5631
|
-
const
|
|
5636
|
+
const upstreamMutation = mutation.type === "delete" ? { type: "delete" } : {
|
|
5637
|
+
type: "replace",
|
|
5638
|
+
text: mutation.text,
|
|
5639
|
+
lane: mutation.lane ?? lane
|
|
5640
|
+
};
|
|
5641
|
+
const status = await session.connection.mutateQueuedMessage(lane, index, expectedText, upstreamMutation);
|
|
5632
5642
|
const queue = await session.connection.getQueue();
|
|
5633
5643
|
return {
|
|
5634
5644
|
status,
|
|
@@ -5638,6 +5648,9 @@ var PrimeBridge = class {
|
|
|
5638
5648
|
}
|
|
5639
5649
|
};
|
|
5640
5650
|
}
|
|
5651
|
+
async deleteQueuedMessage(sessionId, lane, index, expectedText) {
|
|
5652
|
+
return this.mutateQueuedMessage(sessionId, lane, index, expectedText, { type: "delete" });
|
|
5653
|
+
}
|
|
5641
5654
|
async abort(sessionId) {
|
|
5642
5655
|
const session = this.#requireSession(sessionId);
|
|
5643
5656
|
this.#dialogs.cancelAll(sessionId, "user-abort");
|
|
@@ -6886,370 +6899,6 @@ function handleChatEventsGet(request) {
|
|
|
6886
6899
|
return createSseResponse(request, getBridge(), { sessionId: sessionId.data }, lastEventIdFor(request, url));
|
|
6887
6900
|
}, request);
|
|
6888
6901
|
}
|
|
6889
|
-
var BodySchema$1 = external_exports.object({
|
|
6890
|
-
sessionId: SessionIdSchema,
|
|
6891
|
-
model: external_exports.object({
|
|
6892
|
-
provider: external_exports.string(),
|
|
6893
|
-
id: external_exports.string()
|
|
6894
|
-
})
|
|
6895
|
-
});
|
|
6896
|
-
function handleChatModelPost(request) {
|
|
6897
|
-
return wrapApiHandler(async () => {
|
|
6898
|
-
const raw = await request.json().catch(() => ({}));
|
|
6899
|
-
const body = BodySchema$1.parse(raw);
|
|
6900
|
-
const bridge = getBridge();
|
|
6901
|
-
const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
|
|
6902
|
-
if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
|
|
6903
|
-
await bridge.setModel(body.sessionId, {
|
|
6904
|
-
provider: body.model.provider,
|
|
6905
|
-
id: body.model.id
|
|
6906
|
-
});
|
|
6907
|
-
return Response.json({ ok: true });
|
|
6908
|
-
}, request);
|
|
6909
|
-
}
|
|
6910
|
-
function toPatternCandidate(model) {
|
|
6911
|
-
return {
|
|
6912
|
-
id: model.id,
|
|
6913
|
-
name: model.name,
|
|
6914
|
-
provider: model.provider,
|
|
6915
|
-
modelId: model.id,
|
|
6916
|
-
key: `${model.provider}/${model.id}`
|
|
6917
|
-
};
|
|
6918
|
-
}
|
|
6919
|
-
function handleChatModelsGet(request) {
|
|
6920
|
-
return wrapApiHandler(async () => {
|
|
6921
|
-
const config = getPrimeConfig();
|
|
6922
|
-
const cwd = await cwdForRequest(request);
|
|
6923
|
-
const settings = config.settingsFor(cwd);
|
|
6924
|
-
const registry = config.modelRegistry;
|
|
6925
|
-
const scope = new URL(request.url).searchParams.get("scope") === "all" ? "all" : "enabled";
|
|
6926
|
-
let models = registry.getAll();
|
|
6927
|
-
if (scope === "enabled") {
|
|
6928
|
-
models = models.filter((model) => registry.hasConfiguredAuth(model));
|
|
6929
|
-
const patterns = settings.getEnabledModels();
|
|
6930
|
-
if (patterns !== void 0) models = models.filter((model) => isModelPatternEnabled(toPatternCandidate(model), patterns));
|
|
6931
|
-
}
|
|
6932
|
-
const diagnostics = [];
|
|
6933
|
-
const defaultProvider = settings.getDefaultProvider();
|
|
6934
|
-
const defaultModel = settings.getDefaultModel();
|
|
6935
|
-
const defaultThinkingLevel = settings.getDefaultThinkingLevel();
|
|
6936
|
-
const selectedModelKey = defaultProvider && defaultModel ? `${defaultProvider}/${defaultModel}` : void 0;
|
|
6937
|
-
return Response.json({
|
|
6938
|
-
models: models.map((m) => {
|
|
6939
|
-
const thinkingLevels = getSupportedThinkingLevels(m);
|
|
6940
|
-
const fallback = m.reasoning ? "medium" : "off";
|
|
6941
|
-
return {
|
|
6942
|
-
key: `${m.provider}/${m.id}`,
|
|
6943
|
-
provider: m.provider,
|
|
6944
|
-
id: m.id,
|
|
6945
|
-
name: m.name,
|
|
6946
|
-
reasoning: m.reasoning,
|
|
6947
|
-
input: m.input,
|
|
6948
|
-
contextWindow: m.contextWindow,
|
|
6949
|
-
maxTokens: m.maxTokens,
|
|
6950
|
-
available: registry.hasConfiguredAuth(m),
|
|
6951
|
-
thinkingLevels,
|
|
6952
|
-
defaultThinkingLevel: thinkingLevels.includes(fallback) ? fallback : thinkingLevels[0] ?? "off"
|
|
6953
|
-
};
|
|
6954
|
-
}),
|
|
6955
|
-
...selectedModelKey ? { selectedModelKey } : {},
|
|
6956
|
-
...defaultProvider ? { defaultProvider } : {},
|
|
6957
|
-
...defaultModel ? { defaultModel } : {},
|
|
6958
|
-
...defaultThinkingLevel ? { defaultThinkingLevel } : {},
|
|
6959
|
-
diagnostics
|
|
6960
|
-
});
|
|
6961
|
-
}, request);
|
|
6962
|
-
}
|
|
6963
|
-
function storedApiForCustomProvider(api) {
|
|
6964
|
-
return api === "google-genai" ? "google-generative-ai" : api;
|
|
6965
|
-
}
|
|
6966
|
-
function uiApiForCustomProvider(value) {
|
|
6967
|
-
if (value === "google-generative-ai") return "google-genai";
|
|
6968
|
-
return isPiCustomProviderApi(value) ? value : void 0;
|
|
6969
|
-
}
|
|
6970
|
-
function envVarNameForManagedProvider(providerId) {
|
|
6971
|
-
if (providerId === "openai-chat-completions") return "OPENAI_CHAT_COMPLETIONS_API_KEY";
|
|
6972
|
-
const slug = providerId.slice(providerId.indexOf("+") + 1).toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
6973
|
-
return isOccProviderId(providerId) ? `OPENAI_CHAT_COMPLETIONS_${slug}_API_KEY` : `CUSTOM_${slug}_API_KEY`;
|
|
6974
|
-
}
|
|
6975
|
-
function readModelsJson(filePath) {
|
|
6976
|
-
try {
|
|
6977
|
-
if (!existsSync(filePath)) return {};
|
|
6978
|
-
return parseModelsJson(readFileSync(filePath, "utf-8"));
|
|
6979
|
-
} catch {
|
|
6980
|
-
return {};
|
|
6981
|
-
}
|
|
6982
|
-
}
|
|
6983
|
-
function stripJsonComments(input) {
|
|
6984
|
-
return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (match) => match[0] === '"' ? match : "").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (match, tail) => tail ?? (match[0] === '"' ? match : ""));
|
|
6985
|
-
}
|
|
6986
|
-
function parseModelsJson(raw) {
|
|
6987
|
-
const parsed = JSON.parse(stripJsonComments(raw));
|
|
6988
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("models.json must contain an object");
|
|
6989
|
-
return parsed;
|
|
6990
|
-
}
|
|
6991
|
-
function readModelsJsonForWrite(filePath) {
|
|
6992
|
-
if (!existsSync(filePath)) return {};
|
|
6993
|
-
try {
|
|
6994
|
-
return parseModelsJson(readFileSync(filePath, "utf-8"));
|
|
6995
|
-
} catch (error) {
|
|
6996
|
-
throw new Error(`Refusing to update models.json because it could not be parsed: ${error instanceof Error ? error.message : error}`);
|
|
6997
|
-
}
|
|
6998
|
-
}
|
|
6999
|
-
function mergeModelDefinitions(existing, incoming) {
|
|
7000
|
-
const existingById = new Map((existing ?? []).map((model) => [model.id, model]));
|
|
7001
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7002
|
-
return incoming.flatMap((model) => {
|
|
7003
|
-
if (seen.has(model.id)) return [];
|
|
7004
|
-
seen.add(model.id);
|
|
7005
|
-
return [{
|
|
7006
|
-
...existingById.get(model.id),
|
|
7007
|
-
...model
|
|
7008
|
-
}];
|
|
7009
|
-
});
|
|
7010
|
-
}
|
|
7011
|
-
function listCustomProviders(filePath) {
|
|
7012
|
-
return readModelsJson(filePath).providers ?? {};
|
|
7013
|
-
}
|
|
7014
|
-
function writeModelsJson(filePath, data) {
|
|
7015
|
-
mkdirSync(dirname(filePath), {
|
|
7016
|
-
recursive: true,
|
|
7017
|
-
mode: 448
|
|
7018
|
-
});
|
|
7019
|
-
const serialized = `${JSON.stringify(data, null, " ")}
|
|
7020
|
-
`;
|
|
7021
|
-
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
7022
|
-
writeFileSync(tmpPath, serialized, "utf-8");
|
|
7023
|
-
renameSync(tmpPath, filePath);
|
|
7024
|
-
}
|
|
7025
|
-
function upsertCustomProvider(filePath, providerId, input) {
|
|
7026
|
-
const data = readModelsJsonForWrite(filePath);
|
|
7027
|
-
const providers = { ...data.providers ?? {} };
|
|
7028
|
-
const existing = providers[providerId] ?? {};
|
|
7029
|
-
providers[providerId] = {
|
|
7030
|
-
...existing,
|
|
7031
|
-
name: input.name ?? existing.name,
|
|
7032
|
-
baseUrl: input.baseUrl,
|
|
7033
|
-
api: storedApiForCustomProvider(input.api),
|
|
7034
|
-
apiKey: input.apiKey,
|
|
7035
|
-
models: mergeModelDefinitions(existing.models, input.models)
|
|
7036
|
-
};
|
|
7037
|
-
writeModelsJson(filePath, {
|
|
7038
|
-
...data,
|
|
7039
|
-
providers
|
|
7040
|
-
});
|
|
7041
|
-
}
|
|
7042
|
-
function addCustomProviderModelIds(filePath, providerId, modelIds) {
|
|
7043
|
-
const data = readModelsJsonForWrite(filePath);
|
|
7044
|
-
const providers = { ...data.providers ?? {} };
|
|
7045
|
-
const existing = providers[providerId];
|
|
7046
|
-
if (!existing) return;
|
|
7047
|
-
providers[providerId] = {
|
|
7048
|
-
...existing,
|
|
7049
|
-
models: mergeModelDefinitions(existing.models, [...existing.models ?? [], ...modelIds.map((id) => ({ id }))])
|
|
7050
|
-
};
|
|
7051
|
-
writeModelsJson(filePath, {
|
|
7052
|
-
...data,
|
|
7053
|
-
providers
|
|
7054
|
-
});
|
|
7055
|
-
}
|
|
7056
|
-
function removeCustomProvider(filePath, providerId) {
|
|
7057
|
-
const data = readModelsJsonForWrite(filePath);
|
|
7058
|
-
const providers = data.providers;
|
|
7059
|
-
if (!providers || !(providerId in providers)) return;
|
|
7060
|
-
const next = { ...providers };
|
|
7061
|
-
delete next[providerId];
|
|
7062
|
-
writeModelsJson(filePath, {
|
|
7063
|
-
...data,
|
|
7064
|
-
providers: next
|
|
7065
|
-
});
|
|
7066
|
-
}
|
|
7067
|
-
function isDiscoverableEntry(entry) {
|
|
7068
|
-
const baseUrl = entry?.baseUrl;
|
|
7069
|
-
if (!baseUrl) return false;
|
|
7070
|
-
const api = uiApiForCustomProvider(entry?.api);
|
|
7071
|
-
if (api && !isOccFamilyApi(api)) return false;
|
|
7072
|
-
if (entry?.api && !api) return false;
|
|
7073
|
-
try {
|
|
7074
|
-
const parsed = new URL(baseUrl);
|
|
7075
|
-
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
7076
|
-
} catch {
|
|
7077
|
-
return false;
|
|
7078
|
-
}
|
|
7079
|
-
}
|
|
7080
|
-
function openAiModelsUrl(baseUrl) {
|
|
7081
|
-
const parsed = new URL(baseUrl);
|
|
7082
|
-
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw new Error("model discovery requires an http(s) URL");
|
|
7083
|
-
if (parsed.protocol === "http:" && !isLoopbackHostname(parsed.hostname)) throw new Error("model discovery requires https for non-loopback hosts");
|
|
7084
|
-
const path = parsed.pathname.replace(/\/+$/, "");
|
|
7085
|
-
parsed.pathname = path.endsWith("/v1") ? `${path}/models` : `${path}/v1/models`;
|
|
7086
|
-
parsed.search = "";
|
|
7087
|
-
parsed.hash = "";
|
|
7088
|
-
return parsed;
|
|
7089
|
-
}
|
|
7090
|
-
function handleChatModelsDiscoverPost(request) {
|
|
7091
|
-
return wrapApiHandler(async () => {
|
|
7092
|
-
const raw = await request.json().catch(() => ({}));
|
|
7093
|
-
const body = ChatModelsDiscoverRequestSchema.parse(raw);
|
|
7094
|
-
const config = getPrimeConfig();
|
|
7095
|
-
const apiKey = await config.modelRegistry.getApiKeyForProvider(body.providerId);
|
|
7096
|
-
if (!apiKey) return Response.json({
|
|
7097
|
-
providerId: body.providerId,
|
|
7098
|
-
models: []
|
|
7099
|
-
});
|
|
7100
|
-
const provider = body.providerId;
|
|
7101
|
-
const entry = listCustomProviders(`${config.agentDir}/models.json`)[provider];
|
|
7102
|
-
const api = uiApiForCustomProvider(entry?.api);
|
|
7103
|
-
if (entry?.api && !api || api && !isOccFamilyApi(api)) return Response.json({
|
|
7104
|
-
providerId: provider,
|
|
7105
|
-
models: []
|
|
7106
|
-
});
|
|
7107
|
-
const baseUrl = entry?.baseUrl;
|
|
7108
|
-
if (!baseUrl) return Response.json({
|
|
7109
|
-
providerId: provider,
|
|
7110
|
-
models: []
|
|
7111
|
-
});
|
|
7112
|
-
try {
|
|
7113
|
-
const modelsUrl = openAiModelsUrl(baseUrl);
|
|
7114
|
-
const response = await fetch(modelsUrl, {
|
|
7115
|
-
headers: { Authorization: `Bearer ${apiKey}` },
|
|
7116
|
-
redirect: "error",
|
|
7117
|
-
signal: AbortSignal.timeout(1e4)
|
|
7118
|
-
});
|
|
7119
|
-
if (!response.ok) return Response.json({
|
|
7120
|
-
providerId: provider,
|
|
7121
|
-
models: []
|
|
7122
|
-
});
|
|
7123
|
-
const models = ((await response.json()).data ?? []).map((m) => ({
|
|
7124
|
-
key: `${provider}/${m.id}`,
|
|
7125
|
-
provider,
|
|
7126
|
-
id: m.id,
|
|
7127
|
-
name: m.id,
|
|
7128
|
-
reasoning: false,
|
|
7129
|
-
input: ["text"],
|
|
7130
|
-
available: true,
|
|
7131
|
-
defaultThinkingLevel: "off",
|
|
7132
|
-
thinkingLevels: ["off"]
|
|
7133
|
-
}));
|
|
7134
|
-
if (models.length > 0) {
|
|
7135
|
-
addCustomProviderModelIds(`${config.agentDir}/models.json`, provider, models.map((model) => model.id));
|
|
7136
|
-
config.reloadAuth();
|
|
7137
|
-
}
|
|
7138
|
-
return Response.json({
|
|
7139
|
-
providerId: provider,
|
|
7140
|
-
models
|
|
7141
|
-
});
|
|
7142
|
-
} catch {
|
|
7143
|
-
return Response.json({
|
|
7144
|
-
providerId: provider,
|
|
7145
|
-
models: []
|
|
7146
|
-
});
|
|
7147
|
-
}
|
|
7148
|
-
}, request);
|
|
7149
|
-
}
|
|
7150
|
-
function toThinkingLevel(level) {
|
|
7151
|
-
return level;
|
|
7152
|
-
}
|
|
7153
|
-
function handleChatNewPost(request) {
|
|
7154
|
-
return wrapApiHandler(async () => {
|
|
7155
|
-
const bridge = getBridge();
|
|
7156
|
-
const registry = getPrimeConfig().projectRegistry;
|
|
7157
|
-
const raw = await request.json().catch(() => ({}));
|
|
7158
|
-
const body = ChatNewRequestSchema.parse(raw);
|
|
7159
|
-
const projectId = body.projectId ?? await registry.projectIdForCwd(getPrimeConfig().defaultCwd) ?? (await registry.register(getPrimeConfig().defaultCwd)).projectId;
|
|
7160
|
-
const project = await registry.get(projectId);
|
|
7161
|
-
bridge.ensureKernelReady(project.canonicalPath).catch(() => {
|
|
7162
|
-
});
|
|
7163
|
-
const session = await bridge.createSession({
|
|
7164
|
-
cwd: project.canonicalPath,
|
|
7165
|
-
projectId,
|
|
7166
|
-
thinkingLevel: toThinkingLevel(body.thinkingLevel),
|
|
7167
|
-
mode: body.mode,
|
|
7168
|
-
openUI: body.openUI
|
|
7169
|
-
});
|
|
7170
|
-
if (body.model) {
|
|
7171
|
-
await bridge.setModel(session.sessionId, body.model);
|
|
7172
|
-
const thinking = body.model.thinkingLevel ?? body.thinkingLevel;
|
|
7173
|
-
if (thinking) await session.connection.setThinkingLevel(toThinkingLevel(thinking));
|
|
7174
|
-
}
|
|
7175
|
-
return Response.json({
|
|
7176
|
-
session: {
|
|
7177
|
-
sessionId: session.sessionId,
|
|
7178
|
-
projectId
|
|
7179
|
-
},
|
|
7180
|
-
messages: [],
|
|
7181
|
-
planPresentations: [],
|
|
7182
|
-
presentation: bridge.getPresentation(session.sessionId)
|
|
7183
|
-
});
|
|
7184
|
-
}, request);
|
|
7185
|
-
}
|
|
7186
|
-
function record(value) {
|
|
7187
|
-
return typeof value === "object" && value !== null ? value : void 0;
|
|
7188
|
-
}
|
|
7189
|
-
function artifactIndexFor(artifact) {
|
|
7190
|
-
const input = record(artifact.input);
|
|
7191
|
-
return typeof input?.artifactIndex === "number" ? input.artifactIndex : void 0;
|
|
7192
|
-
}
|
|
7193
|
-
function handleChatOpenUIArtifactPut(request) {
|
|
7194
|
-
return wrapApiHandler(async () => {
|
|
7195
|
-
const raw = await request.json().catch(() => ({}));
|
|
7196
|
-
const parsed = ChatOpenUIArtifactUpsertRequestSchema.safeParse(raw);
|
|
7197
|
-
if (!parsed.success) return Response.json({ message: "Invalid OpenUI artifact request." }, { status: 400 });
|
|
7198
|
-
const body = parsed.data;
|
|
7199
|
-
const validation = validateAndNormalizeOpenUIHtmlArtifact(body.artifact);
|
|
7200
|
-
if (!validation.ok) return Response.json({ message: validation.reason }, { status: validation.status ?? 400 });
|
|
7201
|
-
const bridge = getBridge();
|
|
7202
|
-
const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
|
|
7203
|
-
if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
|
|
7204
|
-
const messages = await bridge.getMessages(session.sessionId);
|
|
7205
|
-
const incomingId = body.assistantMessageId;
|
|
7206
|
-
const exact = messages.find((message) => message.role === "assistant" && message.id === incomingId);
|
|
7207
|
-
const existing = bridge.getPresentation(session.sessionId).artifactRuns.flatMap((run) => run.artifacts).filter((artifact2) => artifact2.kind === "openui-html").find((artifact2) => artifactIndexFor(artifact2) === body.artifactIndex && (record(artifact2.input)?.clientMessageId === incomingId || artifact2.sourceMessageId === incomingId));
|
|
7208
|
-
const fallback = existing ? void 0 : [...messages].reverse().find((message) => message.role === "assistant");
|
|
7209
|
-
const assistantMessageId = exact?.id ?? existing?.sourceMessageId ?? fallback?.id;
|
|
7210
|
-
if (!assistantMessageId) return Response.json({ message: "Unable to associate OpenUI artifact with an assistant message." }, { status: 409 });
|
|
7211
|
-
const artifact = {
|
|
7212
|
-
id: stablePresentationId(`${assistantMessageId}:openui-html:${body.artifactIndex}`),
|
|
7213
|
-
runId: stablePresentationId(`${assistantMessageId}:openui`),
|
|
7214
|
-
sourceMessageId: assistantMessageId,
|
|
7215
|
-
kind: "openui-html",
|
|
7216
|
-
title: validation.value.title,
|
|
7217
|
-
status: "success",
|
|
7218
|
-
input: {
|
|
7219
|
-
clientMessageId: incomingId,
|
|
7220
|
-
artifactIndex: body.artifactIndex
|
|
7221
|
-
},
|
|
7222
|
-
output: validation.value,
|
|
7223
|
-
timestamp: Date.now()
|
|
7224
|
-
};
|
|
7225
|
-
const presentation = await bridge.upsertPresentationArtifact(session.sessionId, artifact);
|
|
7226
|
-
return Response.json({
|
|
7227
|
-
artifact,
|
|
7228
|
-
presentation
|
|
7229
|
-
});
|
|
7230
|
-
}, request);
|
|
7231
|
-
}
|
|
7232
|
-
function handleChatPlanPresentationPut(request) {
|
|
7233
|
-
return wrapApiHandler(async () => {
|
|
7234
|
-
const body = ChatPlanPresentationUpsertRequestSchema.parse(await request.json().catch(() => ({})));
|
|
7235
|
-
const bridge = getBridge();
|
|
7236
|
-
const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
|
|
7237
|
-
if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
|
|
7238
|
-
const messages = await bridge.getMessages(body.sessionId);
|
|
7239
|
-
const incomingId = body.presentation.assistantMessageId;
|
|
7240
|
-
const known = messages.find((message) => message.id === incomingId && message.role === "assistant");
|
|
7241
|
-
const existing = (await loadManagedPlanPresentations(session)).find((item) => item.assistantMessageId === incomingId || item.clientMessageId === incomingId);
|
|
7242
|
-
const fallback = existing ? void 0 : [...messages].reverse().find((message) => message.role === "assistant");
|
|
7243
|
-
const assistantMessageId = known?.id ?? existing?.assistantMessageId ?? fallback?.id;
|
|
7244
|
-
if (!assistantMessageId) return Response.json({ message: "Unable to associate Plan presentation with an assistant message" }, { status: 409 });
|
|
7245
|
-
const clientMessageId = incomingId !== assistantMessageId ? existing?.clientMessageId ?? incomingId : existing?.clientMessageId;
|
|
7246
|
-
return Response.json({ presentation: await upsertManagedPlanPresentation(session, {
|
|
7247
|
-
...body.presentation,
|
|
7248
|
-
assistantMessageId,
|
|
7249
|
-
...clientMessageId ? { clientMessageId } : {}
|
|
7250
|
-
}) });
|
|
7251
|
-
}, request);
|
|
7252
|
-
}
|
|
7253
6902
|
var PRIME_BUTTERFLY_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 178 178" aria-hidden="true"><path fill="currentColor" d="m 123.322,84.092671 c -0.192,0.0065 -0.43,0.0147 -0.74,0.0147 l -0.018,-0.0247 c -0.873,0.1977 -1.958,0.1266 -3.067,0.0537 -3.29,-0.216 -6.799,-0.4465 -5.635,6.2824 0.259,1.4822 -1.538,1.8465 -2.73,1.9082 -3.384,0.1853 -6.78,0.2594 -10.171,0.1915 -0.641,-0.0106 -1.2979,-0.5506 -1.8904,-1.0388 -0.1022,-0.0844 -0.2034,-0.1673 -0.3016,-0.2457 -0.1052,-0.0865 0.2898,-1.2042 0.4942,-1.2166 3.3078,-0.1931 4.5068,-2.4361 5.7028,-4.6724 0.603,-1.1253 1.204,-2.2488 2.072,-3.1088 7.856,-7.7874 15.878,-15.4265 25.054,-21.7008 0.895,-0.6114 1.989,-1.1733 2.73,-0.1111 0.571,0.8205 0.036,1.2854 -0.512,1.7627 -0.24,0.2088 -0.482,0.4199 -0.637,0.6642 -0.554,0.8792 -1.538,1.5273 -2.514,2.1717 -1.92,1.2655 -3.82,2.5172 -2.408,5.4798 1.225,2.5651 0.129,3.0202 -1.555,3.7198 l -0.069,0.0287 c -0.72,0.3021 -1.458,0.5764 -2.194,0.8506 -1.568,0.5835 -3.134,1.1662 -4.537,2.0149 -1.408,0.8522 -2.081,2.5134 0.222,3.4954 5.033,2.1428 18.064,-1.2784 20.608,-5.9965 2.377,-4.4147 5.931,-7.6891 9.481,-10.9611 1.992,-1.836 3.984,-3.6712 5.767,-5.7067 3.844,-4.3849 8.344,-8.1939 12.846,-12.005 2.239,-1.8944 4.478,-3.78938 6.637,-5.75588 1.624,-1.48207 2.297,-3.43353 1.026,-5.56412 -1.267,-2.118215 -3.416,-2.402287 -5.435,-1.926802 -13.309,3.130982 -26.166,7.355122 -37.585,15.241302 -18.23,12.5919 -36.4911,25.1406 -54.9002,37.4669 -6.2743,4.2056 -10.0723,2.1491 -12.1657,-5.1318 -4.6502,-16.1676 -11.4681,-30.2664 -31.0569,-32.4587 -7.1574,-0.8028 -12.4066,3.6807 -11.3692,10.7949 0.5249,3.6065 0.0495,7.003 -1.6858,10.3872 -0.3827,0.7472 -0.7689,1.4947 -1.1556,2.243 -2.672,5.1706 -5.3671,10.3857 -7.0394,15.8885 -0.1399,0.4602 -0.3002,0.9444 -0.4654,1.4437 -1.4909,4.5052 -3.3862,10.2323 5.659,10.5492 0.3705,0.0123 1.0808,0.944799 0.9943,1.290699 -0.1976,0.8213 -0.5991,1.797 -1.2413,2.2725 -8.6705,6.3917 -15.79706,14.1294 -18.860151,24.5971 -1.550066,5.2865 -0.524909,10.7765 3.989391,14.8705 3.22984,2.928 7.35516,4.625 10.97396,2.162 3.3009,-2.247 6.9232,-3.754 10.538,-5.259 3.1819,-1.324 6.358,-2.646 9.3041,-4.468 0.7101,-0.439 1.5727,-0.841 2.4456,-1.248 2.4138,-1.1228 4.9063,-2.2843 4.4709,-4.3841 -0.6854,-3.2908 -4.1623,-6.3418 -7.0586,-8.7384 -2.8716,-2.3769 -10.1897,-18.3411 -9.3189,-22.176099 1.2193,-5.3704 3.9645,-10.0201 6.7125,-14.6744 2.3458,-3.9731 4.6935,-7.9497 6.0956,-12.3806 0.5804,-1.828 2.8037,-2.8284 4.9466,-2.0997 1.4543,0.4928 1.2068,1.8278 0.9762,3.0715 -0.0063,0.0344 -0.0127,0.0685 -0.019,0.1027 -0.8688,4.7802 -1.721,9.566 -2.5733,14.3517 -0.4261,2.3924 -0.8521,4.7847 -1.2803,7.1762 -0.2717,1.5316 0.2038,2.7544 1.7909,3.0631 3.0569,0.599 2.989,1.9762 1.6119,4.341499 -1.4636,2.5072 -1.6674,5.5703 -0.0309,7.8861 1.6427,2.3282 4.3908,2.8161 7.1821,1.4204 1.7415,-0.8646 3.094,-0.0927 3.0755,1.6612 -0.1112,9.3688 3.8103,7.2561 8.584,3.1681 0.439,-0.3763 1.0373,-0.5846 1.6152,-0.7857 0.1048,-0.0366 0.2091,-0.0728 0.3116,-0.1098 0.4529,-0.1616 0.9062,-0.3224 1.3595,-0.4833 8.986,-3.1884 17.9603,-6.3725 23.0334,-15.573099 0.392,-0.7187 1.6783,-1.0669 2.6795,-1.3377 0.057,-0.0154 0.113,-0.0307 0.1681,-0.0456 5.8013,-1.5766 11.7248,-1.6001 17.6438,-1.6237 4.445,-0.0176 8.888,-0.0352 13.277,-0.7107 4.329,-0.667 9.047,-3.1928 9.084,-7.3736 0.035,-3.3707 -2.546,-3.1612 -5.123,-2.9519 -1.115,0.0906 -2.231,0.1811 -3.134,-0.0185 -0.182,-0.0381 -0.375,-0.0316 -0.686,-0.0209 z"/><path fill="currentColor" d="m 55.1325,131.29447 c -1.0745,7.1515 1.6551,13.2715 12.8266,13.1915 h -0.0062 c 9.5413,-0.389 20.3365,-6.164 30.8838,-13.5492 6.9653,-4.8787 12.9873,-10.0236 16.8903,-17.6253 2.872,-5.5889 1.395,-10.0723 -2.933,-13.993799 -1.908,-1.7291 -3.73,-1.9205 -5.867,0.1667 -7.5842,7.423099 -17.0261,11.474299 -26.7218,15.550099 -2.4706,1.0393 -5.2847,1.5582 -8.1187,2.0809 -7.5511,1.3924 -15.2431,2.8103 -16.954,14.1791 z"/></svg>`;
|
|
7254
6903
|
function escapeHtml(value) {
|
|
7255
6904
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
@@ -7377,10 +7026,10 @@ var decode$1 = (s) => atob(s);
|
|
|
7377
7026
|
var CLIENT_ID$2 = decode$1("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
|
|
7378
7027
|
var AUTHORIZE_URL$1 = "https://claude.ai/oauth/authorize";
|
|
7379
7028
|
var TOKEN_URL$1 = "https://platform.claude.com/v1/oauth/token";
|
|
7380
|
-
var CALLBACK_HOST$
|
|
7029
|
+
var CALLBACK_HOST$2 = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
|
|
7381
7030
|
var CALLBACK_PORT = 53692;
|
|
7382
|
-
var CALLBACK_PATH = "/callback";
|
|
7383
|
-
var REDIRECT_URI$1 = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
7031
|
+
var CALLBACK_PATH$1 = "/callback";
|
|
7032
|
+
var REDIRECT_URI$1 = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH$1}`;
|
|
7384
7033
|
var SCOPES = "org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload";
|
|
7385
7034
|
async function getNodeApis() {
|
|
7386
7035
|
if (nodeApis) return nodeApis;
|
|
@@ -7430,7 +7079,7 @@ function formatErrorDetails(error) {
|
|
|
7430
7079
|
}
|
|
7431
7080
|
return String(error);
|
|
7432
7081
|
}
|
|
7433
|
-
async function startCallbackServer(expectedState) {
|
|
7082
|
+
async function startCallbackServer$1(expectedState) {
|
|
7434
7083
|
const { createServer } = await getNodeApis();
|
|
7435
7084
|
return new Promise((resolve2, reject) => {
|
|
7436
7085
|
let settleWait;
|
|
@@ -7445,7 +7094,7 @@ async function startCallbackServer(expectedState) {
|
|
|
7445
7094
|
const server = createServer((req, res) => {
|
|
7446
7095
|
try {
|
|
7447
7096
|
const url = new URL(req.url || "", "http://localhost");
|
|
7448
|
-
if (url.pathname !== CALLBACK_PATH) {
|
|
7097
|
+
if (url.pathname !== CALLBACK_PATH$1) {
|
|
7449
7098
|
res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
|
7450
7099
|
res.end(oauthErrorHtml("Callback route not found."));
|
|
7451
7100
|
return;
|
|
@@ -7482,7 +7131,7 @@ async function startCallbackServer(expectedState) {
|
|
|
7482
7131
|
server.on("error", (err) => {
|
|
7483
7132
|
reject(err);
|
|
7484
7133
|
});
|
|
7485
|
-
server.listen(CALLBACK_PORT, CALLBACK_HOST$
|
|
7134
|
+
server.listen(CALLBACK_PORT, CALLBACK_HOST$2, () => {
|
|
7486
7135
|
resolve2({
|
|
7487
7136
|
server,
|
|
7488
7137
|
redirectUri: REDIRECT_URI$1,
|
|
@@ -7536,7 +7185,7 @@ async function exchangeAuthorizationCode$1(code, state, verifier, redirectUri) {
|
|
|
7536
7185
|
}
|
|
7537
7186
|
async function loginAnthropic(options) {
|
|
7538
7187
|
const { verifier, challenge } = await generatePKCE();
|
|
7539
|
-
const server = await startCallbackServer(verifier);
|
|
7188
|
+
const server = await startCallbackServer$1(verifier);
|
|
7540
7189
|
let code;
|
|
7541
7190
|
let state;
|
|
7542
7191
|
let redirectUriForExchange = REDIRECT_URI$1;
|
|
@@ -34611,7 +34260,7 @@ function getGitHubCopilotBaseUrl(token, enterpriseDomain) {
|
|
|
34611
34260
|
if (enterpriseDomain) return `https://copilot-api.${enterpriseDomain}`;
|
|
34612
34261
|
return "https://api.individual.githubcopilot.com";
|
|
34613
34262
|
}
|
|
34614
|
-
async function fetchJson(url, init) {
|
|
34263
|
+
async function fetchJson$1(url, init) {
|
|
34615
34264
|
const response = await fetch(url, init);
|
|
34616
34265
|
if (!response.ok) {
|
|
34617
34266
|
const text = await response.text();
|
|
@@ -34620,7 +34269,7 @@ async function fetchJson(url, init) {
|
|
|
34620
34269
|
return response.json();
|
|
34621
34270
|
}
|
|
34622
34271
|
async function startDeviceFlow(domain) {
|
|
34623
|
-
const data = await fetchJson(getUrls(domain).deviceCodeUrl, {
|
|
34272
|
+
const data = await fetchJson$1(getUrls(domain).deviceCodeUrl, {
|
|
34624
34273
|
method: "POST",
|
|
34625
34274
|
headers: {
|
|
34626
34275
|
Accept: "application/json",
|
|
@@ -34670,7 +34319,7 @@ async function pollForGitHubAccessToken(domain, deviceCode, intervalSeconds, exp
|
|
|
34670
34319
|
if (signal?.aborted) throw new Error("Login cancelled");
|
|
34671
34320
|
const remainingMs = deadline - Date.now();
|
|
34672
34321
|
await abortableSleep(Math.min(Math.ceil(intervalMs * intervalMultiplier), remainingMs), signal);
|
|
34673
|
-
const raw = await fetchJson(urls.accessTokenUrl, {
|
|
34322
|
+
const raw = await fetchJson$1(urls.accessTokenUrl, {
|
|
34674
34323
|
method: "POST",
|
|
34675
34324
|
headers: {
|
|
34676
34325
|
Accept: "application/json",
|
|
@@ -34701,7 +34350,7 @@ async function pollForGitHubAccessToken(domain, deviceCode, intervalSeconds, exp
|
|
|
34701
34350
|
throw new Error("Device flow timed out");
|
|
34702
34351
|
}
|
|
34703
34352
|
async function refreshGitHubCopilotToken(refreshToken, enterpriseDomain) {
|
|
34704
|
-
const raw = await fetchJson(getUrls(enterpriseDomain || "github.com").copilotTokenUrl, { headers: {
|
|
34353
|
+
const raw = await fetchJson$1(getUrls(enterpriseDomain || "github.com").copilotTokenUrl, { headers: {
|
|
34705
34354
|
Accept: "application/json",
|
|
34706
34355
|
Authorization: `Bearer ${refreshToken}`,
|
|
34707
34356
|
...COPILOT_HEADERS
|
|
@@ -34801,7 +34450,7 @@ if (typeof process !== "undefined" && (process.versions?.node || process.version
|
|
|
34801
34450
|
_http = m;
|
|
34802
34451
|
});
|
|
34803
34452
|
}
|
|
34804
|
-
var CALLBACK_HOST = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
|
|
34453
|
+
var CALLBACK_HOST$1 = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
|
|
34805
34454
|
var CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
34806
34455
|
var AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
|
|
34807
34456
|
var TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
@@ -34983,7 +34632,7 @@ function startLocalOAuthServer(state) {
|
|
|
34983
34632
|
}
|
|
34984
34633
|
});
|
|
34985
34634
|
return new Promise((resolve2) => {
|
|
34986
|
-
server.listen(1455, CALLBACK_HOST, () => {
|
|
34635
|
+
server.listen(1455, CALLBACK_HOST$1, () => {
|
|
34987
34636
|
resolve2({
|
|
34988
34637
|
close: () => server.close(),
|
|
34989
34638
|
cancelWait: () => {
|
|
@@ -35109,9 +34758,652 @@ var oauthProviderRegistry = new Map([
|
|
|
35109
34758
|
function getOAuthProvider(id) {
|
|
35110
34759
|
return oauthProviderRegistry.get(id);
|
|
35111
34760
|
}
|
|
34761
|
+
function registerOAuthProvider(provider) {
|
|
34762
|
+
oauthProviderRegistry.set(provider.id, provider);
|
|
34763
|
+
}
|
|
35112
34764
|
function getOAuthProviders() {
|
|
35113
34765
|
return Array.from(oauthProviderRegistry.values());
|
|
35114
34766
|
}
|
|
34767
|
+
var CALLBACK_HOST = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
|
|
34768
|
+
var CALLBACK_PORT_BASE = Number(process.env.PI_MCP_OAUTH_CALLBACK_PORT || 53700);
|
|
34769
|
+
var CALLBACK_PORT_COUNT = 10;
|
|
34770
|
+
var CALLBACK_PATH = "/callback";
|
|
34771
|
+
var CALLBACK_PORTS = Array.from({ length: CALLBACK_PORT_COUNT }, (_, i) => CALLBACK_PORT_BASE + i);
|
|
34772
|
+
var redirectUriFor = (port) => `http://localhost:${port}${CALLBACK_PATH}`;
|
|
34773
|
+
var ALL_REDIRECT_URIS = CALLBACK_PORTS.map(redirectUriFor);
|
|
34774
|
+
var TOKEN_EXPIRY_BUFFER_MS = 3e5;
|
|
34775
|
+
function validatedHttpsUrl(value, name) {
|
|
34776
|
+
let url;
|
|
34777
|
+
try {
|
|
34778
|
+
url = new URL(value);
|
|
34779
|
+
} catch {
|
|
34780
|
+
throw new Error(`${name} must be an absolute HTTPS URL`);
|
|
34781
|
+
}
|
|
34782
|
+
if (url.protocol !== "https:" || url.username || url.password || url.hash) throw new Error(`${name} must be an absolute HTTPS URL without credentials or a fragment`);
|
|
34783
|
+
return url;
|
|
34784
|
+
}
|
|
34785
|
+
function canonicalResource(url) {
|
|
34786
|
+
if (url.pathname === "/" && !url.search) return url.origin;
|
|
34787
|
+
return `${url.origin}${url.pathname}${url.search}`;
|
|
34788
|
+
}
|
|
34789
|
+
function authorizationServerMetadataUrls(issuer) {
|
|
34790
|
+
const url = validatedHttpsUrl(issuer, "Authorization server issuer");
|
|
34791
|
+
if (url.search) throw new Error("Authorization server issuer must not contain a query string");
|
|
34792
|
+
const path = url.pathname === "/" ? "" : url.pathname.replace(/\/$/, "");
|
|
34793
|
+
return [new URL(`/.well-known/oauth-authorization-server${path}`, url.origin).toString(), new URL(`${path}/.well-known/openid-configuration`, url.origin).toString()];
|
|
34794
|
+
}
|
|
34795
|
+
async function fetchResponse(url, init) {
|
|
34796
|
+
return fetch(url, {
|
|
34797
|
+
...init,
|
|
34798
|
+
redirect: "error"
|
|
34799
|
+
});
|
|
34800
|
+
}
|
|
34801
|
+
async function fetchJson(url, init) {
|
|
34802
|
+
const res = await fetchResponse(url, init);
|
|
34803
|
+
if (!res.ok) throw new Error(`${init?.method ?? "GET"} ${url} failed: ${res.status}`);
|
|
34804
|
+
return res.json();
|
|
34805
|
+
}
|
|
34806
|
+
function authorizationServerMetadata(value, issuer, requireExactIssuer) {
|
|
34807
|
+
if (!value || typeof value !== "object") throw new Error(`Authorization server metadata for ${issuer} is invalid`);
|
|
34808
|
+
const metadata = value;
|
|
34809
|
+
if (typeof metadata.issuer !== "string") throw new Error(`Authorization server metadata for ${issuer} is missing its issuer`);
|
|
34810
|
+
if (requireExactIssuer) {
|
|
34811
|
+
if (metadata.issuer !== issuer) throw new Error(`Authorization server metadata issuer does not exactly match ${issuer}`);
|
|
34812
|
+
} else {
|
|
34813
|
+
const advertisedIssuer = validatedHttpsUrl(metadata.issuer, "Authorization server metadata issuer");
|
|
34814
|
+
if (advertisedIssuer.origin !== new URL(issuer).origin || advertisedIssuer.search) throw new Error(`Origin authorization server metadata issuer must stay on ${new URL(issuer).origin}`);
|
|
34815
|
+
}
|
|
34816
|
+
if (typeof metadata.authorization_endpoint !== "string" || typeof metadata.token_endpoint !== "string") throw new Error(`Authorization server metadata for ${issuer} is missing required endpoints`);
|
|
34817
|
+
validatedHttpsUrl(metadata.authorization_endpoint, "Authorization endpoint");
|
|
34818
|
+
validatedHttpsUrl(metadata.token_endpoint, "Token endpoint");
|
|
34819
|
+
if (metadata.registration_endpoint) validatedHttpsUrl(metadata.registration_endpoint, "Registration endpoint");
|
|
34820
|
+
return metadata;
|
|
34821
|
+
}
|
|
34822
|
+
async function jsonMetadata(response, url) {
|
|
34823
|
+
if (response.status !== 200) throw new Error(`GET ${url} failed: ${response.status}`);
|
|
34824
|
+
if (response.headers.get("content-type")?.split(";", 1)[0].trim().toLowerCase() !== "application/json") throw new Error(`GET ${url} did not return application/json`);
|
|
34825
|
+
return response.json();
|
|
34826
|
+
}
|
|
34827
|
+
async function discoverAuthorizationServer(issuer, requireExactIssuer) {
|
|
34828
|
+
const candidates = authorizationServerMetadataUrls(issuer);
|
|
34829
|
+
let lastError;
|
|
34830
|
+
for (const candidate of candidates) try {
|
|
34831
|
+
const response = await fetchResponse(candidate);
|
|
34832
|
+
if (response.status === 404) continue;
|
|
34833
|
+
return authorizationServerMetadata(await jsonMetadata(response, candidate), issuer, requireExactIssuer);
|
|
34834
|
+
} catch (error) {
|
|
34835
|
+
lastError = error;
|
|
34836
|
+
}
|
|
34837
|
+
throw new Error(`Could not discover OAuth metadata for ${issuer}. Tried ${candidates.join(", ")}. Last error: ${String(lastError)}`);
|
|
34838
|
+
}
|
|
34839
|
+
function randomState() {
|
|
34840
|
+
const bytes = /* @__PURE__ */ new Uint8Array(32);
|
|
34841
|
+
crypto.getRandomValues(bytes);
|
|
34842
|
+
return btoa(String.fromCharCode(...bytes)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
34843
|
+
}
|
|
34844
|
+
function resourceMetadata(value, resource) {
|
|
34845
|
+
if (!value || typeof value !== "object") throw new Error("Protected-resource metadata is invalid");
|
|
34846
|
+
const metadata = value;
|
|
34847
|
+
if (metadata.resource !== resource) throw new Error(`Protected-resource metadata resource does not exactly match ${resource}`);
|
|
34848
|
+
if (!Array.isArray(metadata.authorization_servers) || metadata.authorization_servers.length === 0) throw new Error("Protected-resource metadata has no authorization_servers");
|
|
34849
|
+
for (const issuer of metadata.authorization_servers) {
|
|
34850
|
+
if (typeof issuer !== "string") throw new Error("Protected-resource metadata has an invalid authorization server");
|
|
34851
|
+
validatedHttpsUrl(issuer, "Authorization server issuer");
|
|
34852
|
+
}
|
|
34853
|
+
return metadata;
|
|
34854
|
+
}
|
|
34855
|
+
function resourceMetadataUrl(resource) {
|
|
34856
|
+
const path = resource.pathname === "/" ? "" : resource.pathname;
|
|
34857
|
+
return `${resource.origin}/.well-known/oauth-protected-resource${path}${resource.search}`;
|
|
34858
|
+
}
|
|
34859
|
+
function headerResourceMetadata(value) {
|
|
34860
|
+
const match = value?.match(/(?:^|[,\s])resource_metadata\s*=\s*"((?:[^"\\]|\\.)*)"/i);
|
|
34861
|
+
if (!match) return void 0;
|
|
34862
|
+
return match[1].replace(/\\(.)/g, "$1");
|
|
34863
|
+
}
|
|
34864
|
+
async function tryProtectedResourceMetadata(url) {
|
|
34865
|
+
const resource = validatedHttpsUrl(url, "MCP endpoint");
|
|
34866
|
+
let headerUrl;
|
|
34867
|
+
try {
|
|
34868
|
+
const response2 = await fetchResponse(resource.toString());
|
|
34869
|
+
headerUrl = headerResourceMetadata(response2.headers.get("www-authenticate"));
|
|
34870
|
+
await response2.body?.cancel();
|
|
34871
|
+
} catch {
|
|
34872
|
+
}
|
|
34873
|
+
const candidate = headerUrl ? validatedHttpsUrl(headerUrl, "resource_metadata").toString() : resourceMetadataUrl(resource);
|
|
34874
|
+
const response = await fetchResponse(candidate);
|
|
34875
|
+
if (response.status === 404 && !headerUrl) return void 0;
|
|
34876
|
+
return resourceMetadata(await jsonMetadata(response, candidate), canonicalResource(resource));
|
|
34877
|
+
}
|
|
34878
|
+
async function discover(url) {
|
|
34879
|
+
const protectedResource = await tryProtectedResourceMetadata(url);
|
|
34880
|
+
if (protectedResource) {
|
|
34881
|
+
const issuer2 = protectedResource.authorization_servers[0];
|
|
34882
|
+
return {
|
|
34883
|
+
metadata: await discoverAuthorizationServer(issuer2, true),
|
|
34884
|
+
resource: protectedResource.resource,
|
|
34885
|
+
issuer: issuer2
|
|
34886
|
+
};
|
|
34887
|
+
}
|
|
34888
|
+
const issuer = validatedHttpsUrl(url, "MCP endpoint").origin;
|
|
34889
|
+
return { metadata: await discoverAuthorizationServer(issuer, false) };
|
|
34890
|
+
}
|
|
34891
|
+
async function registerClient(registrationEndpoint, label) {
|
|
34892
|
+
validatedHttpsUrl(registrationEndpoint, "Registration endpoint");
|
|
34893
|
+
const data = await fetchJson(registrationEndpoint, {
|
|
34894
|
+
method: "POST",
|
|
34895
|
+
headers: { "Content-Type": "application/json" },
|
|
34896
|
+
body: JSON.stringify({
|
|
34897
|
+
client_name: label,
|
|
34898
|
+
redirect_uris: ALL_REDIRECT_URIS,
|
|
34899
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
34900
|
+
response_types: ["code"],
|
|
34901
|
+
token_endpoint_auth_method: "none"
|
|
34902
|
+
})
|
|
34903
|
+
});
|
|
34904
|
+
if (typeof data.client_id !== "string" || !data.client_id) throw new Error(`Dynamic client registration at ${registrationEndpoint} returned no client_id`);
|
|
34905
|
+
return data.client_id;
|
|
34906
|
+
}
|
|
34907
|
+
async function startCallbackServer(label) {
|
|
34908
|
+
const { createServer } = await import("node:http");
|
|
34909
|
+
let settle;
|
|
34910
|
+
const waitPromise = new Promise((resolve2) => {
|
|
34911
|
+
let settled = false;
|
|
34912
|
+
settle = (value) => {
|
|
34913
|
+
if (!settled) {
|
|
34914
|
+
settled = true;
|
|
34915
|
+
resolve2(value);
|
|
34916
|
+
}
|
|
34917
|
+
};
|
|
34918
|
+
});
|
|
34919
|
+
const handler = (req, res) => {
|
|
34920
|
+
const url = new URL(req.url || "", "http://localhost");
|
|
34921
|
+
if (url.pathname !== CALLBACK_PATH) {
|
|
34922
|
+
res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
|
34923
|
+
res.end(oauthErrorHtml("Callback route not found."));
|
|
34924
|
+
return;
|
|
34925
|
+
}
|
|
34926
|
+
const error = url.searchParams.get("error");
|
|
34927
|
+
const code = url.searchParams.get("code");
|
|
34928
|
+
const state = url.searchParams.get("state");
|
|
34929
|
+
res.writeHead(error || !code ? 400 : 200, { "Content-Type": "text/html; charset=utf-8" });
|
|
34930
|
+
if (error) {
|
|
34931
|
+
res.end(oauthErrorHtml(`${label} authentication failed.`, `Error: ${error}`));
|
|
34932
|
+
settle?.(null);
|
|
34933
|
+
return;
|
|
34934
|
+
}
|
|
34935
|
+
if (!code || !state) {
|
|
34936
|
+
res.end(oauthErrorHtml("Missing code or state parameter."));
|
|
34937
|
+
settle?.(null);
|
|
34938
|
+
return;
|
|
34939
|
+
}
|
|
34940
|
+
res.end(oauthSuccessHtml(`${label} authentication completed. You can close this window.`));
|
|
34941
|
+
settle?.({
|
|
34942
|
+
code,
|
|
34943
|
+
state
|
|
34944
|
+
});
|
|
34945
|
+
};
|
|
34946
|
+
let lastError;
|
|
34947
|
+
for (const port of CALLBACK_PORTS) {
|
|
34948
|
+
const server = createServer(handler);
|
|
34949
|
+
let bindErr;
|
|
34950
|
+
server.on("error", (err) => bindErr?.(err));
|
|
34951
|
+
try {
|
|
34952
|
+
if (await new Promise((resolve2) => {
|
|
34953
|
+
bindErr = () => resolve2(false);
|
|
34954
|
+
server.listen(port, CALLBACK_HOST, () => {
|
|
34955
|
+
bindErr = void 0;
|
|
34956
|
+
resolve2(true);
|
|
34957
|
+
});
|
|
34958
|
+
})) return {
|
|
34959
|
+
server,
|
|
34960
|
+
redirectUri: redirectUriFor(port),
|
|
34961
|
+
cancel: () => settle?.(null),
|
|
34962
|
+
waitForCode: () => waitPromise
|
|
34963
|
+
};
|
|
34964
|
+
lastError = `port ${port} in use`;
|
|
34965
|
+
server.close();
|
|
34966
|
+
} catch (err) {
|
|
34967
|
+
lastError = err;
|
|
34968
|
+
server.close();
|
|
34969
|
+
}
|
|
34970
|
+
}
|
|
34971
|
+
throw new Error(`Could not start the OAuth callback server: ports ${CALLBACK_PORT_BASE}-${CALLBACK_PORT_BASE + CALLBACK_PORT_COUNT - 1} are all in use. Close other login attempts and retry. (${String(lastError)})`);
|
|
34972
|
+
}
|
|
34973
|
+
function parseRedirectInput(input, expectedState) {
|
|
34974
|
+
const value = input.trim();
|
|
34975
|
+
let code;
|
|
34976
|
+
let state;
|
|
34977
|
+
try {
|
|
34978
|
+
const url = new URL(value);
|
|
34979
|
+
code = url.searchParams.get("code") ?? void 0;
|
|
34980
|
+
state = url.searchParams.get("state") ?? void 0;
|
|
34981
|
+
} catch {
|
|
34982
|
+
const params = new URLSearchParams(value);
|
|
34983
|
+
code = params.get("code") ?? value;
|
|
34984
|
+
state = params.get("state") ?? void 0;
|
|
34985
|
+
}
|
|
34986
|
+
if (state && state !== expectedState) throw new Error("OAuth state mismatch");
|
|
34987
|
+
if (!code) throw new Error("Missing authorization code");
|
|
34988
|
+
return {
|
|
34989
|
+
code,
|
|
34990
|
+
state: state ?? expectedState
|
|
34991
|
+
};
|
|
34992
|
+
}
|
|
34993
|
+
async function exchangeToken(tokenEndpoint, params) {
|
|
34994
|
+
validatedHttpsUrl(tokenEndpoint, "Token endpoint");
|
|
34995
|
+
const res = await fetchResponse(tokenEndpoint, {
|
|
34996
|
+
method: "POST",
|
|
34997
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
34998
|
+
body: new URLSearchParams(params).toString()
|
|
34999
|
+
});
|
|
35000
|
+
const text = await res.text();
|
|
35001
|
+
if (!res.ok) throw new Error(`Token request to ${tokenEndpoint} failed: ${res.status}`);
|
|
35002
|
+
let token;
|
|
35003
|
+
try {
|
|
35004
|
+
token = JSON.parse(text);
|
|
35005
|
+
} catch {
|
|
35006
|
+
throw new Error(`Token request to ${tokenEndpoint} returned invalid JSON`);
|
|
35007
|
+
}
|
|
35008
|
+
if (!token || typeof token !== "object" || typeof token.access_token !== "string") throw new Error(`Token request to ${tokenEndpoint} returned no access_token`);
|
|
35009
|
+
const result = token;
|
|
35010
|
+
if (!result.access_token) throw new Error(`Token request to ${tokenEndpoint} returned no access_token`);
|
|
35011
|
+
if (result.refresh_token !== void 0 && typeof result.refresh_token !== "string") throw new Error(`Token request to ${tokenEndpoint} returned an invalid refresh_token`);
|
|
35012
|
+
if (result.expires_in !== void 0 && (typeof result.expires_in !== "number" || !Number.isFinite(result.expires_in))) throw new Error(`Token request to ${tokenEndpoint} returned an invalid expires_in`);
|
|
35013
|
+
return result;
|
|
35014
|
+
}
|
|
35015
|
+
function toCredentials(token, tokenEndpoint, clientId, endpoint, resource, issuer, previousRefresh) {
|
|
35016
|
+
return {
|
|
35017
|
+
access: token.access_token,
|
|
35018
|
+
refresh: token.refresh_token ?? previousRefresh ?? "",
|
|
35019
|
+
expires: token.expires_in ? Date.now() + token.expires_in * 1e3 - TOKEN_EXPIRY_BUFFER_MS : Date.now() + 36e5 - TOKEN_EXPIRY_BUFFER_MS,
|
|
35020
|
+
tokenEndpoint,
|
|
35021
|
+
clientId,
|
|
35022
|
+
endpoint,
|
|
35023
|
+
resource,
|
|
35024
|
+
issuer
|
|
35025
|
+
};
|
|
35026
|
+
}
|
|
35027
|
+
function createMcpOAuthProvider(config) {
|
|
35028
|
+
const label = config.label ?? config.server;
|
|
35029
|
+
async function login(callbacks) {
|
|
35030
|
+
const discovery = await discover(config.url);
|
|
35031
|
+
const { metadata: meta } = discovery;
|
|
35032
|
+
callbacks.onProgress?.(`Discovered ${discovery.issuer ?? meta.issuer}`);
|
|
35033
|
+
let clientId = config.clientId;
|
|
35034
|
+
if (!clientId) {
|
|
35035
|
+
if (!meta.registration_endpoint) throw new Error(`${label} does not support dynamic client registration and no clientId was configured. Set a pre-registered client id for this server.`);
|
|
35036
|
+
callbacks.onProgress?.("Registering OAuth client\u2026");
|
|
35037
|
+
clientId = await registerClient(meta.registration_endpoint, `Prime Agent (${label})`);
|
|
35038
|
+
}
|
|
35039
|
+
const { verifier, challenge } = await generatePKCE();
|
|
35040
|
+
const state = randomState();
|
|
35041
|
+
const scope = config.scopes ?? meta.scopes_supported?.join(" ");
|
|
35042
|
+
const cb = await startCallbackServer(label);
|
|
35043
|
+
try {
|
|
35044
|
+
const authParams = new URLSearchParams({
|
|
35045
|
+
client_id: clientId,
|
|
35046
|
+
response_type: "code",
|
|
35047
|
+
redirect_uri: cb.redirectUri,
|
|
35048
|
+
code_challenge: challenge,
|
|
35049
|
+
code_challenge_method: "S256",
|
|
35050
|
+
state
|
|
35051
|
+
});
|
|
35052
|
+
if (scope) authParams.set("scope", scope);
|
|
35053
|
+
if (discovery.resource) authParams.set("resource", discovery.resource);
|
|
35054
|
+
const authorizationUrl = new URL(meta.authorization_endpoint);
|
|
35055
|
+
for (const [name, value] of authParams) authorizationUrl.searchParams.set(name, value);
|
|
35056
|
+
callbacks.onAuth({
|
|
35057
|
+
url: authorizationUrl.toString(),
|
|
35058
|
+
instructions: "Complete login in your browser. If the browser is on another machine, paste the final redirect URL here."
|
|
35059
|
+
});
|
|
35060
|
+
let result;
|
|
35061
|
+
let manualCancelled = false;
|
|
35062
|
+
let manualError;
|
|
35063
|
+
if (callbacks.onManualCodeInput) {
|
|
35064
|
+
const manual = callbacks.onManualCodeInput().then((input) => {
|
|
35065
|
+
const parsed = parseRedirectInput(input, state);
|
|
35066
|
+
cb.cancel();
|
|
35067
|
+
return parsed;
|
|
35068
|
+
}).catch(async (err) => {
|
|
35069
|
+
if (err instanceof Error && /state mismatch|authorization code/i.test(err.message)) manualError = err;
|
|
35070
|
+
else manualCancelled = true;
|
|
35071
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
35072
|
+
cb.cancel();
|
|
35073
|
+
return null;
|
|
35074
|
+
});
|
|
35075
|
+
result = await cb.waitForCode() ?? await manual;
|
|
35076
|
+
if (!result && manualError) throw manualError;
|
|
35077
|
+
} else {
|
|
35078
|
+
result = await cb.waitForCode();
|
|
35079
|
+
if (!result) result = parseRedirectInput(await callbacks.onPrompt({
|
|
35080
|
+
message: "Paste the authorization code or full redirect URL:",
|
|
35081
|
+
placeholder: cb.redirectUri
|
|
35082
|
+
}), state);
|
|
35083
|
+
}
|
|
35084
|
+
if (!result) throw new Error(manualCancelled ? "Login cancelled" : "Missing authorization code");
|
|
35085
|
+
if (result.state !== state) throw new Error("OAuth state mismatch");
|
|
35086
|
+
callbacks.onProgress?.("Exchanging authorization code for tokens\u2026");
|
|
35087
|
+
return toCredentials(await exchangeToken(meta.token_endpoint, {
|
|
35088
|
+
grant_type: "authorization_code",
|
|
35089
|
+
code: result.code,
|
|
35090
|
+
redirect_uri: cb.redirectUri,
|
|
35091
|
+
client_id: clientId,
|
|
35092
|
+
code_verifier: verifier,
|
|
35093
|
+
...discovery.resource ? { resource: discovery.resource } : {}
|
|
35094
|
+
}), meta.token_endpoint, clientId, config.url, discovery.resource, discovery.issuer);
|
|
35095
|
+
} finally {
|
|
35096
|
+
cb.server.close();
|
|
35097
|
+
}
|
|
35098
|
+
}
|
|
35099
|
+
async function refreshToken(credentials) {
|
|
35100
|
+
const creds = credentials;
|
|
35101
|
+
if (creds.endpoint !== config.url) throw new Error(`Stored OAuth credentials are not bound to ${config.url}; re-run /mcp login ${config.server}`);
|
|
35102
|
+
const configuredResource = canonicalResource(validatedHttpsUrl(config.url, "MCP endpoint"));
|
|
35103
|
+
if (creds.resource !== void 0 && creds.resource !== configuredResource) throw new Error(`Stored OAuth credentials are not bound to ${configuredResource}; re-run /mcp login ${config.server}`);
|
|
35104
|
+
if (creds.resource === void 0 !== (creds.issuer === void 0)) throw new Error(`Stored OAuth credentials for ${label} have incomplete resource binding; re-run /mcp login ${config.server}`);
|
|
35105
|
+
if (creds.issuer !== void 0) validatedHttpsUrl(creds.issuer, "Stored authorization server issuer");
|
|
35106
|
+
if (!creds.refresh) throw new Error(`No refresh token stored for ${label}; re-run /mcp login ${config.server}`);
|
|
35107
|
+
const discovery = await discover(config.url);
|
|
35108
|
+
if (creds.resource === void 0 !== (discovery.resource === void 0)) throw new Error(`OAuth discovery mode changed for ${config.url}; re-run /mcp login ${config.server}`);
|
|
35109
|
+
if (creds.resource) {
|
|
35110
|
+
if (discovery.resource !== creds.resource || discovery.issuer !== creds.issuer) throw new Error(`Stored OAuth credentials do not match current protected-resource metadata for ${config.url}`);
|
|
35111
|
+
}
|
|
35112
|
+
const tokenEndpoint = creds.tokenEndpoint ?? discovery.metadata.token_endpoint;
|
|
35113
|
+
if (creds.tokenEndpoint && discovery.metadata.token_endpoint !== creds.tokenEndpoint) throw new Error(`Stored OAuth token endpoint does not match current authorization-server metadata for ${config.url}`);
|
|
35114
|
+
const clientId = creds.clientId ?? config.clientId;
|
|
35115
|
+
if (!tokenEndpoint) throw new Error(`No token endpoint stored for ${label}; re-run /mcp login ${config.server}`);
|
|
35116
|
+
return toCredentials(await exchangeToken(tokenEndpoint, {
|
|
35117
|
+
grant_type: "refresh_token",
|
|
35118
|
+
refresh_token: creds.refresh,
|
|
35119
|
+
...clientId ? { client_id: clientId } : {},
|
|
35120
|
+
...creds.resource ? { resource: creds.resource } : {}
|
|
35121
|
+
}), tokenEndpoint, clientId ?? "", creds.endpoint, creds.resource, creds.issuer, creds.refresh);
|
|
35122
|
+
}
|
|
35123
|
+
return {
|
|
35124
|
+
id: `mcp:${config.server}`,
|
|
35125
|
+
name: label,
|
|
35126
|
+
usesCallbackServer: true,
|
|
35127
|
+
login,
|
|
35128
|
+
refreshToken,
|
|
35129
|
+
getApiKey: (credentials) => credentials.access
|
|
35130
|
+
};
|
|
35131
|
+
}
|
|
35132
|
+
var BUILTIN_MCP_CATALOG = [{
|
|
35133
|
+
server: "linear",
|
|
35134
|
+
label: "Linear",
|
|
35135
|
+
url: "https://mcp.linear.app/mcp",
|
|
35136
|
+
oauth: {
|
|
35137
|
+
kind: "oauth",
|
|
35138
|
+
label: "Linear"
|
|
35139
|
+
}
|
|
35140
|
+
}, {
|
|
35141
|
+
server: "notion",
|
|
35142
|
+
label: "Notion",
|
|
35143
|
+
url: "https://mcp.notion.com/mcp",
|
|
35144
|
+
oauth: {
|
|
35145
|
+
kind: "oauth",
|
|
35146
|
+
label: "Notion"
|
|
35147
|
+
}
|
|
35148
|
+
}];
|
|
35149
|
+
function getCatalogEntry(server) {
|
|
35150
|
+
return BUILTIN_MCP_CATALOG.find((entry) => entry.server === server);
|
|
35151
|
+
}
|
|
35152
|
+
function registerBuiltinMcpOAuthProviders() {
|
|
35153
|
+
for (const entry of BUILTIN_MCP_CATALOG) {
|
|
35154
|
+
if (entry.oauth?.kind !== "oauth") continue;
|
|
35155
|
+
if (getOAuthProvider(`mcp:${entry.server}`)) continue;
|
|
35156
|
+
registerOAuthProvider(createMcpOAuthProvider({
|
|
35157
|
+
server: entry.server,
|
|
35158
|
+
label: entry.label,
|
|
35159
|
+
url: entry.url,
|
|
35160
|
+
scopes: entry.oauth.scopes,
|
|
35161
|
+
clientId: entry.oauth.clientId
|
|
35162
|
+
}));
|
|
35163
|
+
}
|
|
35164
|
+
}
|
|
35165
|
+
var MCP_AUTH_PREFIX = "mcp:";
|
|
35166
|
+
function mcpProviderId(name) {
|
|
35167
|
+
return `${MCP_AUTH_PREFIX}${name}`;
|
|
35168
|
+
}
|
|
35169
|
+
var McpRequestError = class extends Error {
|
|
35170
|
+
status = 400;
|
|
35171
|
+
constructor(message) {
|
|
35172
|
+
super(message);
|
|
35173
|
+
this.name = "McpRequestError";
|
|
35174
|
+
}
|
|
35175
|
+
};
|
|
35176
|
+
function validateHttpMcpUrl(value) {
|
|
35177
|
+
let url;
|
|
35178
|
+
try {
|
|
35179
|
+
url = new URL(value);
|
|
35180
|
+
} catch {
|
|
35181
|
+
throw new McpRequestError("Invalid MCP URL.");
|
|
35182
|
+
}
|
|
35183
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || !url.hostname || url.username || url.password) throw new McpRequestError("MCP URL must be an http(s) URL without embedded credentials.");
|
|
35184
|
+
return url.toString();
|
|
35185
|
+
}
|
|
35186
|
+
function stdioCommandPreview(config) {
|
|
35187
|
+
return [config.command, ...config.args ?? []].join(" ");
|
|
35188
|
+
}
|
|
35189
|
+
function mcpEnvBindings(config) {
|
|
35190
|
+
if (config.type !== "stdio" || !config.env) return void 0;
|
|
35191
|
+
const bindings = Object.entries(config.env).map(([child, mapping]) => ({
|
|
35192
|
+
child,
|
|
35193
|
+
source: mapping.env
|
|
35194
|
+
}));
|
|
35195
|
+
return bindings.length > 0 ? bindings : void 0;
|
|
35196
|
+
}
|
|
35197
|
+
function isMcpAuthed(server, auth, env) {
|
|
35198
|
+
if (server.config.enabled === false) return false;
|
|
35199
|
+
if (server.userDeclared && getCatalogEntry(server.name)) return false;
|
|
35200
|
+
if (server.config.type === "stdio") return true;
|
|
35201
|
+
const usesOAuth = server.config.type === "http" && server.config.oauth === true;
|
|
35202
|
+
const bearerTokenEnvVar = server.config.type === "http" ? server.config.bearerTokenEnvVar : void 0;
|
|
35203
|
+
if (!usesOAuth && !bearerTokenEnvVar) return true;
|
|
35204
|
+
if (bearerTokenEnvVar && env[bearerTokenEnvVar]?.trim()) return true;
|
|
35205
|
+
const cred = auth.get(mcpProviderId(server.name));
|
|
35206
|
+
if (cred === void 0) return false;
|
|
35207
|
+
if (!server.userDeclared) return true;
|
|
35208
|
+
const endpoint = cred.endpoint;
|
|
35209
|
+
return typeof endpoint === "string" && server.config.type === "http" && endpoint === server.config.url;
|
|
35210
|
+
}
|
|
35211
|
+
function mcpConnectionStatus(server, authed) {
|
|
35212
|
+
if (server.config.enabled === false) return "disabled";
|
|
35213
|
+
if (authed) return server.config.type === "http" && server.config.oauth !== true && !server.config.bearerTokenEnvVar ? "anonymous" : "connected";
|
|
35214
|
+
return "needs_auth";
|
|
35215
|
+
}
|
|
35216
|
+
function toMcpConnectionInfo(server, auth, env) {
|
|
35217
|
+
const usesOAuth = server.config.type === "http" && server.config.oauth === true;
|
|
35218
|
+
const catalogShadow = server.userDeclared && Boolean(getCatalogEntry(server.name));
|
|
35219
|
+
const authed = isMcpAuthed(server, auth, env);
|
|
35220
|
+
const envBindings = mcpEnvBindings(server.config);
|
|
35221
|
+
return {
|
|
35222
|
+
name: server.name,
|
|
35223
|
+
label: server.label,
|
|
35224
|
+
source: server.source,
|
|
35225
|
+
transport: server.config.type,
|
|
35226
|
+
usesOAuth,
|
|
35227
|
+
enabled: authed,
|
|
35228
|
+
status: mcpConnectionStatus(server, authed),
|
|
35229
|
+
...server.config.type === "http" ? { url: server.config.url } : {},
|
|
35230
|
+
...server.config.type === "stdio" ? { commandPreview: stdioCommandPreview(server.config) } : {},
|
|
35231
|
+
...server.config.type === "stdio" && server.config.cwd ? { cwdPreview: safePathLabel(server.config.cwd) } : {},
|
|
35232
|
+
...server.config.type === "http" && server.config.bearerTokenEnvVar ? { bearerTokenEnvVar: server.config.bearerTokenEnvVar } : {},
|
|
35233
|
+
...envBindings ? { envBindings } : {},
|
|
35234
|
+
...catalogShadow ? { error: "This name is reserved for a built-in integration." } : {}
|
|
35235
|
+
};
|
|
35236
|
+
}
|
|
35237
|
+
function listMcpServers(userServers) {
|
|
35238
|
+
const listed = [];
|
|
35239
|
+
for (const entry of BUILTIN_MCP_CATALOG) listed.push({
|
|
35240
|
+
name: entry.server,
|
|
35241
|
+
label: entry.label,
|
|
35242
|
+
source: "builtin",
|
|
35243
|
+
userDeclared: false,
|
|
35244
|
+
config: {
|
|
35245
|
+
type: "http",
|
|
35246
|
+
url: entry.url,
|
|
35247
|
+
oauth: true
|
|
35248
|
+
}
|
|
35249
|
+
});
|
|
35250
|
+
for (const [name, config] of Object.entries(userServers ?? {}).sort(([left], [right]) => left.localeCompare(right))) listed.push({
|
|
35251
|
+
name,
|
|
35252
|
+
label: name,
|
|
35253
|
+
source: "user",
|
|
35254
|
+
userDeclared: true,
|
|
35255
|
+
config
|
|
35256
|
+
});
|
|
35257
|
+
return listed;
|
|
35258
|
+
}
|
|
35259
|
+
function listMcpConnections(userServers, auth, env = process.env) {
|
|
35260
|
+
return listMcpServers(userServers).map((server) => toMcpConnectionInfo(server, auth, env));
|
|
35261
|
+
}
|
|
35262
|
+
function dropMcpServerCredentials(name, auth) {
|
|
35263
|
+
if (getCatalogEntry(name)) return;
|
|
35264
|
+
try {
|
|
35265
|
+
auth.removeVerified(mcpProviderId(name));
|
|
35266
|
+
} catch (error) {
|
|
35267
|
+
throw new McpRequestError(`Could not remove stored credentials for this MCP server: ${error instanceof Error ? error.message : String(error)}`);
|
|
35268
|
+
}
|
|
35269
|
+
}
|
|
35270
|
+
async function confineMcpStdioCwd(cwd, workspaceRoot) {
|
|
35271
|
+
if (cwd === void 0 || cwd.trim() === "") return void 0;
|
|
35272
|
+
const root2 = resolve(workspaceRoot);
|
|
35273
|
+
const canonicalRoot = await realpath(root2).catch(() => root2);
|
|
35274
|
+
const candidate = resolve(root2, cwd);
|
|
35275
|
+
const existingCandidate = await realpath(candidate).catch(() => void 0);
|
|
35276
|
+
if (existingCandidate && existingCandidate !== canonicalRoot && !existingCandidate.startsWith(`${canonicalRoot}${sep}`)) throw new McpRequestError("MCP stdio working directory must stay inside the workspace.");
|
|
35277
|
+
let ancestor = dirname(candidate);
|
|
35278
|
+
while (true) {
|
|
35279
|
+
const resolvedAncestor = await realpath(ancestor).catch(() => void 0);
|
|
35280
|
+
if (resolvedAncestor) {
|
|
35281
|
+
if (resolvedAncestor !== canonicalRoot && !resolvedAncestor.startsWith(`${canonicalRoot}${sep}`)) throw new McpRequestError("MCP stdio working directory must stay inside the workspace.");
|
|
35282
|
+
break;
|
|
35283
|
+
}
|
|
35284
|
+
const parent = dirname(ancestor);
|
|
35285
|
+
if (parent === ancestor) throw new McpRequestError("MCP stdio working directory must stay inside the workspace.");
|
|
35286
|
+
ancestor = parent;
|
|
35287
|
+
}
|
|
35288
|
+
return candidate;
|
|
35289
|
+
}
|
|
35290
|
+
function storedApiForCustomProvider(api) {
|
|
35291
|
+
return api === "google-genai" ? "google-generative-ai" : api;
|
|
35292
|
+
}
|
|
35293
|
+
function uiApiForCustomProvider(value) {
|
|
35294
|
+
if (value === "google-generative-ai") return "google-genai";
|
|
35295
|
+
return isPiCustomProviderApi(value) ? value : void 0;
|
|
35296
|
+
}
|
|
35297
|
+
function envVarNameForManagedProvider(providerId) {
|
|
35298
|
+
if (providerId === "openai-chat-completions") return "OPENAI_CHAT_COMPLETIONS_API_KEY";
|
|
35299
|
+
const slug = providerId.slice(providerId.indexOf("+") + 1).toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
35300
|
+
return isOccProviderId(providerId) ? `OPENAI_CHAT_COMPLETIONS_${slug}_API_KEY` : `CUSTOM_${slug}_API_KEY`;
|
|
35301
|
+
}
|
|
35302
|
+
function readModelsJson(filePath) {
|
|
35303
|
+
try {
|
|
35304
|
+
if (!existsSync(filePath)) return {};
|
|
35305
|
+
return parseModelsJson(readFileSync(filePath, "utf-8"));
|
|
35306
|
+
} catch {
|
|
35307
|
+
return {};
|
|
35308
|
+
}
|
|
35309
|
+
}
|
|
35310
|
+
function stripJsonComments(input) {
|
|
35311
|
+
return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (match) => match[0] === '"' ? match : "").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (match, tail) => tail ?? (match[0] === '"' ? match : ""));
|
|
35312
|
+
}
|
|
35313
|
+
function parseModelsJson(raw) {
|
|
35314
|
+
const parsed = JSON.parse(stripJsonComments(raw));
|
|
35315
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("models.json must contain an object");
|
|
35316
|
+
return parsed;
|
|
35317
|
+
}
|
|
35318
|
+
function readModelsJsonForWrite(filePath) {
|
|
35319
|
+
if (!existsSync(filePath)) return {};
|
|
35320
|
+
try {
|
|
35321
|
+
return parseModelsJson(readFileSync(filePath, "utf-8"));
|
|
35322
|
+
} catch (error) {
|
|
35323
|
+
throw new Error(`Refusing to update models.json because it could not be parsed: ${error instanceof Error ? error.message : error}`);
|
|
35324
|
+
}
|
|
35325
|
+
}
|
|
35326
|
+
function mergeModelDefinitions(existing, incoming) {
|
|
35327
|
+
const existingById = new Map((existing ?? []).map((model) => [model.id, model]));
|
|
35328
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35329
|
+
return incoming.flatMap((model) => {
|
|
35330
|
+
if (seen.has(model.id)) return [];
|
|
35331
|
+
seen.add(model.id);
|
|
35332
|
+
return [{
|
|
35333
|
+
...existingById.get(model.id),
|
|
35334
|
+
...model
|
|
35335
|
+
}];
|
|
35336
|
+
});
|
|
35337
|
+
}
|
|
35338
|
+
function listCustomProviders(filePath) {
|
|
35339
|
+
return readModelsJson(filePath).providers ?? {};
|
|
35340
|
+
}
|
|
35341
|
+
function writeModelsJson(filePath, data) {
|
|
35342
|
+
mkdirSync(dirname(filePath), {
|
|
35343
|
+
recursive: true,
|
|
35344
|
+
mode: 448
|
|
35345
|
+
});
|
|
35346
|
+
const serialized = `${JSON.stringify(data, null, " ")}
|
|
35347
|
+
`;
|
|
35348
|
+
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
35349
|
+
writeFileSync(tmpPath, serialized, "utf-8");
|
|
35350
|
+
renameSync(tmpPath, filePath);
|
|
35351
|
+
}
|
|
35352
|
+
function upsertCustomProvider(filePath, providerId, input) {
|
|
35353
|
+
const data = readModelsJsonForWrite(filePath);
|
|
35354
|
+
const providers = { ...data.providers ?? {} };
|
|
35355
|
+
const existing = providers[providerId] ?? {};
|
|
35356
|
+
providers[providerId] = {
|
|
35357
|
+
...existing,
|
|
35358
|
+
name: input.name ?? existing.name,
|
|
35359
|
+
baseUrl: input.baseUrl,
|
|
35360
|
+
api: storedApiForCustomProvider(input.api),
|
|
35361
|
+
apiKey: input.apiKey,
|
|
35362
|
+
models: mergeModelDefinitions(existing.models, input.models)
|
|
35363
|
+
};
|
|
35364
|
+
writeModelsJson(filePath, {
|
|
35365
|
+
...data,
|
|
35366
|
+
providers
|
|
35367
|
+
});
|
|
35368
|
+
}
|
|
35369
|
+
function addCustomProviderModelIds(filePath, providerId, modelIds) {
|
|
35370
|
+
const data = readModelsJsonForWrite(filePath);
|
|
35371
|
+
const providers = { ...data.providers ?? {} };
|
|
35372
|
+
const existing = providers[providerId];
|
|
35373
|
+
if (!existing) return;
|
|
35374
|
+
providers[providerId] = {
|
|
35375
|
+
...existing,
|
|
35376
|
+
models: mergeModelDefinitions(existing.models, [...existing.models ?? [], ...modelIds.map((id) => ({ id }))])
|
|
35377
|
+
};
|
|
35378
|
+
writeModelsJson(filePath, {
|
|
35379
|
+
...data,
|
|
35380
|
+
providers
|
|
35381
|
+
});
|
|
35382
|
+
}
|
|
35383
|
+
function removeCustomProvider(filePath, providerId) {
|
|
35384
|
+
const data = readModelsJsonForWrite(filePath);
|
|
35385
|
+
const providers = data.providers;
|
|
35386
|
+
if (!providers || !(providerId in providers)) return;
|
|
35387
|
+
const next = { ...providers };
|
|
35388
|
+
delete next[providerId];
|
|
35389
|
+
writeModelsJson(filePath, {
|
|
35390
|
+
...data,
|
|
35391
|
+
providers: next
|
|
35392
|
+
});
|
|
35393
|
+
}
|
|
35394
|
+
function isDiscoverableEntry(entry) {
|
|
35395
|
+
const baseUrl = entry?.baseUrl;
|
|
35396
|
+
if (!baseUrl) return false;
|
|
35397
|
+
const api = uiApiForCustomProvider(entry?.api);
|
|
35398
|
+
if (api && !isOccFamilyApi(api)) return false;
|
|
35399
|
+
if (entry?.api && !api) return false;
|
|
35400
|
+
try {
|
|
35401
|
+
const parsed = new URL(baseUrl);
|
|
35402
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
35403
|
+
} catch {
|
|
35404
|
+
return false;
|
|
35405
|
+
}
|
|
35406
|
+
}
|
|
35115
35407
|
var PRIME_PROVIDER_ENV_MAP = {
|
|
35116
35408
|
openai: "OPENAI_API_KEY",
|
|
35117
35409
|
"azure-openai-responses": "AZURE_OPENAI_API_KEY",
|
|
@@ -35448,7 +35740,7 @@ function cancelOAuthLogin(loginId) {
|
|
|
35448
35740
|
error: "Login cancelled"
|
|
35449
35741
|
};
|
|
35450
35742
|
}
|
|
35451
|
-
function oauthDeps() {
|
|
35743
|
+
function oauthDeps$1() {
|
|
35452
35744
|
const config = getPrimeConfig();
|
|
35453
35745
|
return {
|
|
35454
35746
|
login: (providerId, callbacks) => config.authStorage.login(providerId, callbacks),
|
|
@@ -35475,7 +35767,422 @@ function handleChatProvidersOAuthPost(request) {
|
|
|
35475
35767
|
status: "error",
|
|
35476
35768
|
error: `Unknown OAuth provider: ${body.providerId}`
|
|
35477
35769
|
}, { status: 400 });
|
|
35478
|
-
return Response.json(startOAuthLogin(body.providerId, oauthDeps()));
|
|
35770
|
+
return Response.json(startOAuthLogin(body.providerId, oauthDeps$1()));
|
|
35771
|
+
}, request);
|
|
35772
|
+
}
|
|
35773
|
+
function defaultMcpDeps() {
|
|
35774
|
+
const config = getPrimeConfig();
|
|
35775
|
+
const settings = config.defaultSettings;
|
|
35776
|
+
return {
|
|
35777
|
+
getUserServers: () => settings.getGlobalMcpServers(),
|
|
35778
|
+
setUserServer: (name, serverConfig, force) => {
|
|
35779
|
+
settings.setGlobalMcpServer(name, serverConfig, force);
|
|
35780
|
+
},
|
|
35781
|
+
removeUserServer: (name) => settings.removeGlobalMcpServer(name),
|
|
35782
|
+
flushSettings: async () => {
|
|
35783
|
+
await settings.flush();
|
|
35784
|
+
const error = settings.drainErrors("global")[0];
|
|
35785
|
+
if (error) throw error.error;
|
|
35786
|
+
},
|
|
35787
|
+
auth: config.authStorage,
|
|
35788
|
+
workspaceRoot: config.defaultCwd,
|
|
35789
|
+
env: process.env,
|
|
35790
|
+
reloadAuth: () => {
|
|
35791
|
+
config.reloadAuth();
|
|
35792
|
+
},
|
|
35793
|
+
reloadResources: async () => {
|
|
35794
|
+
await getBridge().reloadResources();
|
|
35795
|
+
}
|
|
35796
|
+
};
|
|
35797
|
+
}
|
|
35798
|
+
function listedConnections(deps) {
|
|
35799
|
+
return listMcpConnections(deps.getUserServers(), deps.auth, deps.env);
|
|
35800
|
+
}
|
|
35801
|
+
function listResponse(deps) {
|
|
35802
|
+
return { connections: listedConnections(deps) };
|
|
35803
|
+
}
|
|
35804
|
+
function toMcpOAuthResponse(snapshot2, connections) {
|
|
35805
|
+
return {
|
|
35806
|
+
status: snapshot2.status,
|
|
35807
|
+
...snapshot2.loginId ? { loginId: snapshot2.loginId } : {},
|
|
35808
|
+
...snapshot2.authUrl ? { authUrl: snapshot2.authUrl } : {},
|
|
35809
|
+
...snapshot2.userCode ? { userCode: snapshot2.userCode } : {},
|
|
35810
|
+
...snapshot2.instructions ? { instructions: snapshot2.instructions } : {},
|
|
35811
|
+
...snapshot2.prompt ? { prompt: snapshot2.prompt } : {},
|
|
35812
|
+
...snapshot2.error ? { error: snapshot2.error } : {},
|
|
35813
|
+
...connections ? { connections } : {}
|
|
35814
|
+
};
|
|
35815
|
+
}
|
|
35816
|
+
function ensureMcpOAuthProvider(name, deps) {
|
|
35817
|
+
registerBuiltinMcpOAuthProviders();
|
|
35818
|
+
if (getCatalogEntry(name)) return;
|
|
35819
|
+
const config = deps.getUserServers()?.[name];
|
|
35820
|
+
if (!config || config.type !== "http" || config.oauth !== true) throw new McpRequestError("This MCP server does not use OAuth.");
|
|
35821
|
+
registerOAuthProvider(createMcpOAuthProvider({
|
|
35822
|
+
server: name,
|
|
35823
|
+
label: name,
|
|
35824
|
+
url: config.url
|
|
35825
|
+
}));
|
|
35826
|
+
}
|
|
35827
|
+
function oauthDeps(deps) {
|
|
35828
|
+
return {
|
|
35829
|
+
login: (providerId, callbacks) => deps.auth.login(providerId, callbacks),
|
|
35830
|
+
reloadAuth: () => {
|
|
35831
|
+
deps.reloadAuth();
|
|
35832
|
+
deps.reloadResources();
|
|
35833
|
+
},
|
|
35834
|
+
listProviders: () => []
|
|
35835
|
+
};
|
|
35836
|
+
}
|
|
35837
|
+
async function logoutMcp(name, deps) {
|
|
35838
|
+
try {
|
|
35839
|
+
deps.auth.removeVerified(mcpProviderId(name));
|
|
35840
|
+
} catch (error) {
|
|
35841
|
+
throw new McpRequestError(`Could not remove stored credentials: ${error instanceof Error ? error.message : String(error)}`);
|
|
35842
|
+
}
|
|
35843
|
+
deps.reloadAuth();
|
|
35844
|
+
await deps.reloadResources();
|
|
35845
|
+
return {
|
|
35846
|
+
status: "success",
|
|
35847
|
+
connections: listedConnections(deps)
|
|
35848
|
+
};
|
|
35849
|
+
}
|
|
35850
|
+
function handleChatMcpGet(_request, deps = defaultMcpDeps()) {
|
|
35851
|
+
return wrapApiHandler(async () => Response.json(listResponse(deps)), _request);
|
|
35852
|
+
}
|
|
35853
|
+
function handleChatMcpPost(request, deps = defaultMcpDeps()) {
|
|
35854
|
+
return wrapApiHandler(async () => {
|
|
35855
|
+
const body = ChatMcpUpsertRequestSchema.parse(await request.json().catch(() => ({})));
|
|
35856
|
+
if (getCatalogEntry(body.name)) throw new McpRequestError(`MCP server name "${body.name}" is reserved for a built-in integration.`);
|
|
35857
|
+
if (deps.getUserServers()?.[body.name] && body.force !== true) throw new McpRequestError(`MCP server "${body.name}" already exists. Replace it to continue.`);
|
|
35858
|
+
let config;
|
|
35859
|
+
switch (body.transport) {
|
|
35860
|
+
case "http":
|
|
35861
|
+
if (body.bearerTokenEnvVar && body.oauth) throw new McpRequestError("OAuth and a bearer-token environment variable cannot be combined.");
|
|
35862
|
+
config = {
|
|
35863
|
+
type: "http",
|
|
35864
|
+
url: validateHttpMcpUrl(body.url),
|
|
35865
|
+
...body.bearerTokenEnvVar ? { bearerTokenEnvVar: body.bearerTokenEnvVar } : {},
|
|
35866
|
+
...body.oauth ? { oauth: true } : {}
|
|
35867
|
+
};
|
|
35868
|
+
break;
|
|
35869
|
+
case "stdio": {
|
|
35870
|
+
if (body.command.includes("\0") || body.args?.some((part) => part.includes("\0"))) throw new McpRequestError("MCP command arguments cannot contain NUL.");
|
|
35871
|
+
const env = Object.fromEntries((body.env ?? []).map((binding) => [binding.child, { env: binding.source }]));
|
|
35872
|
+
const cwd = await confineMcpStdioCwd(body.cwd, deps.workspaceRoot);
|
|
35873
|
+
config = {
|
|
35874
|
+
type: "stdio",
|
|
35875
|
+
command: body.command,
|
|
35876
|
+
...body.args && body.args.length > 0 ? { args: body.args } : {},
|
|
35877
|
+
...cwd ? { cwd } : {},
|
|
35878
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
35879
|
+
};
|
|
35880
|
+
break;
|
|
35881
|
+
}
|
|
35882
|
+
default:
|
|
35883
|
+
throw new McpRequestError(`Unsupported MCP transport: ${String(body)}`);
|
|
35884
|
+
}
|
|
35885
|
+
dropMcpServerCredentials(body.name, deps.auth);
|
|
35886
|
+
deps.setUserServer(body.name, config, true);
|
|
35887
|
+
await deps.flushSettings();
|
|
35888
|
+
deps.reloadAuth();
|
|
35889
|
+
await deps.reloadResources();
|
|
35890
|
+
return Response.json(listResponse(deps));
|
|
35891
|
+
}, request);
|
|
35892
|
+
}
|
|
35893
|
+
function handleChatMcpDelete(request, deps = defaultMcpDeps()) {
|
|
35894
|
+
return wrapApiHandler(async () => {
|
|
35895
|
+
const body = ChatMcpDeleteRequestSchema.parse(await request.json().catch(() => ({})));
|
|
35896
|
+
if (!deps.removeUserServer(body.name)) throw new McpRequestError(`MCP server "${body.name}" was not found.`);
|
|
35897
|
+
await deps.flushSettings();
|
|
35898
|
+
dropMcpServerCredentials(body.name, deps.auth);
|
|
35899
|
+
deps.reloadAuth();
|
|
35900
|
+
await deps.reloadResources();
|
|
35901
|
+
return Response.json(listResponse(deps));
|
|
35902
|
+
}, request);
|
|
35903
|
+
}
|
|
35904
|
+
function handleChatMcpOAuthPost(request, deps = defaultMcpDeps()) {
|
|
35905
|
+
return wrapApiHandler(async () => {
|
|
35906
|
+
const body = ChatMcpOAuthLoginRequestSchema.parse(await request.json().catch(() => ({})));
|
|
35907
|
+
if (![...BUILTIN_MCP_CATALOG.map((entry) => entry.server), ...Object.keys(deps.getUserServers() ?? {})].includes(body.name) && !body.loginId) throw new McpRequestError(`Unknown MCP server: ${body.name}`);
|
|
35908
|
+
if (body.cancel) {
|
|
35909
|
+
if (!body.loginId) return Response.json({
|
|
35910
|
+
status: "error",
|
|
35911
|
+
error: "loginId is required to cancel"
|
|
35912
|
+
}, { status: 400 });
|
|
35913
|
+
return Response.json(toMcpOAuthResponse(cancelOAuthLogin(body.loginId)));
|
|
35914
|
+
}
|
|
35915
|
+
if (body.loginId && body.promptAnswer !== void 0) return Response.json(toMcpOAuthResponse(continueOAuthLogin(body.loginId, body.promptAnswer)));
|
|
35916
|
+
if (body.loginId) {
|
|
35917
|
+
const snapshot2 = pollOAuthLogin(body.loginId);
|
|
35918
|
+
return Response.json(toMcpOAuthResponse(snapshot2, snapshot2.status === "success" ? listedConnections(deps) : void 0));
|
|
35919
|
+
}
|
|
35920
|
+
const action = body.action ?? "login";
|
|
35921
|
+
switch (action) {
|
|
35922
|
+
case "logout":
|
|
35923
|
+
return Response.json(await logoutMcp(body.name, deps));
|
|
35924
|
+
case "reconnect":
|
|
35925
|
+
await logoutMcp(body.name, deps);
|
|
35926
|
+
break;
|
|
35927
|
+
case "login":
|
|
35928
|
+
break;
|
|
35929
|
+
default:
|
|
35930
|
+
throw new McpRequestError(`Unsupported MCP OAuth action: ${String(action)}`);
|
|
35931
|
+
}
|
|
35932
|
+
ensureMcpOAuthProvider(body.name, deps);
|
|
35933
|
+
const providerId = mcpProviderId(body.name);
|
|
35934
|
+
if (!getOAuthProvider(providerId)) return Response.json({
|
|
35935
|
+
status: "error",
|
|
35936
|
+
error: `Unknown OAuth provider: ${providerId}`
|
|
35937
|
+
}, { status: 400 });
|
|
35938
|
+
return Response.json(toMcpOAuthResponse(startOAuthLogin(providerId, oauthDeps(deps))));
|
|
35939
|
+
}, request);
|
|
35940
|
+
}
|
|
35941
|
+
var BodySchema$1 = external_exports.object({
|
|
35942
|
+
sessionId: SessionIdSchema,
|
|
35943
|
+
model: external_exports.object({
|
|
35944
|
+
provider: external_exports.string(),
|
|
35945
|
+
id: external_exports.string()
|
|
35946
|
+
})
|
|
35947
|
+
});
|
|
35948
|
+
function handleChatModelPost(request) {
|
|
35949
|
+
return wrapApiHandler(async () => {
|
|
35950
|
+
const raw = await request.json().catch(() => ({}));
|
|
35951
|
+
const body = BodySchema$1.parse(raw);
|
|
35952
|
+
const bridge = getBridge();
|
|
35953
|
+
const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
|
|
35954
|
+
if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
|
|
35955
|
+
await bridge.setModel(body.sessionId, {
|
|
35956
|
+
provider: body.model.provider,
|
|
35957
|
+
id: body.model.id
|
|
35958
|
+
});
|
|
35959
|
+
return Response.json({ ok: true });
|
|
35960
|
+
}, request);
|
|
35961
|
+
}
|
|
35962
|
+
function toPatternCandidate(model) {
|
|
35963
|
+
return {
|
|
35964
|
+
id: model.id,
|
|
35965
|
+
name: model.name,
|
|
35966
|
+
provider: model.provider,
|
|
35967
|
+
modelId: model.id,
|
|
35968
|
+
key: `${model.provider}/${model.id}`
|
|
35969
|
+
};
|
|
35970
|
+
}
|
|
35971
|
+
function handleChatModelsGet(request) {
|
|
35972
|
+
return wrapApiHandler(async () => {
|
|
35973
|
+
const config = getPrimeConfig();
|
|
35974
|
+
const cwd = await cwdForRequest(request);
|
|
35975
|
+
const settings = config.settingsFor(cwd);
|
|
35976
|
+
const registry = config.modelRegistry;
|
|
35977
|
+
const scope = new URL(request.url).searchParams.get("scope") === "all" ? "all" : "enabled";
|
|
35978
|
+
let models = registry.getAll();
|
|
35979
|
+
if (scope === "enabled") {
|
|
35980
|
+
models = models.filter((model) => registry.hasConfiguredAuth(model));
|
|
35981
|
+
const patterns = settings.getEnabledModels();
|
|
35982
|
+
if (patterns !== void 0) models = models.filter((model) => isModelPatternEnabled(toPatternCandidate(model), patterns));
|
|
35983
|
+
}
|
|
35984
|
+
const diagnostics = [];
|
|
35985
|
+
const defaultProvider = settings.getDefaultProvider();
|
|
35986
|
+
const defaultModel = settings.getDefaultModel();
|
|
35987
|
+
const defaultThinkingLevel = settings.getDefaultThinkingLevel();
|
|
35988
|
+
const selectedModelKey = defaultProvider && defaultModel ? `${defaultProvider}/${defaultModel}` : void 0;
|
|
35989
|
+
return Response.json({
|
|
35990
|
+
models: models.map((m) => {
|
|
35991
|
+
const thinkingLevels = getSupportedThinkingLevels(m);
|
|
35992
|
+
const fallback = m.reasoning ? "medium" : "off";
|
|
35993
|
+
return {
|
|
35994
|
+
key: `${m.provider}/${m.id}`,
|
|
35995
|
+
provider: m.provider,
|
|
35996
|
+
id: m.id,
|
|
35997
|
+
name: m.name,
|
|
35998
|
+
reasoning: m.reasoning,
|
|
35999
|
+
input: m.input,
|
|
36000
|
+
contextWindow: m.contextWindow,
|
|
36001
|
+
maxTokens: m.maxTokens,
|
|
36002
|
+
available: registry.hasConfiguredAuth(m),
|
|
36003
|
+
thinkingLevels,
|
|
36004
|
+
defaultThinkingLevel: thinkingLevels.includes(fallback) ? fallback : thinkingLevels[0] ?? "off"
|
|
36005
|
+
};
|
|
36006
|
+
}),
|
|
36007
|
+
...selectedModelKey ? { selectedModelKey } : {},
|
|
36008
|
+
...defaultProvider ? { defaultProvider } : {},
|
|
36009
|
+
...defaultModel ? { defaultModel } : {},
|
|
36010
|
+
...defaultThinkingLevel ? { defaultThinkingLevel } : {},
|
|
36011
|
+
diagnostics
|
|
36012
|
+
});
|
|
36013
|
+
}, request);
|
|
36014
|
+
}
|
|
36015
|
+
function openAiModelsUrl(baseUrl) {
|
|
36016
|
+
const parsed = new URL(baseUrl);
|
|
36017
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw new Error("model discovery requires an http(s) URL");
|
|
36018
|
+
if (parsed.protocol === "http:" && !isLoopbackHostname(parsed.hostname)) throw new Error("model discovery requires https for non-loopback hosts");
|
|
36019
|
+
const path = parsed.pathname.replace(/\/+$/, "");
|
|
36020
|
+
parsed.pathname = path.endsWith("/v1") ? `${path}/models` : `${path}/v1/models`;
|
|
36021
|
+
parsed.search = "";
|
|
36022
|
+
parsed.hash = "";
|
|
36023
|
+
return parsed;
|
|
36024
|
+
}
|
|
36025
|
+
function handleChatModelsDiscoverPost(request) {
|
|
36026
|
+
return wrapApiHandler(async () => {
|
|
36027
|
+
const raw = await request.json().catch(() => ({}));
|
|
36028
|
+
const body = ChatModelsDiscoverRequestSchema.parse(raw);
|
|
36029
|
+
const config = getPrimeConfig();
|
|
36030
|
+
const apiKey = await config.modelRegistry.getApiKeyForProvider(body.providerId);
|
|
36031
|
+
if (!apiKey) return Response.json({
|
|
36032
|
+
providerId: body.providerId,
|
|
36033
|
+
models: []
|
|
36034
|
+
});
|
|
36035
|
+
const provider = body.providerId;
|
|
36036
|
+
const entry = listCustomProviders(`${config.agentDir}/models.json`)[provider];
|
|
36037
|
+
const api = uiApiForCustomProvider(entry?.api);
|
|
36038
|
+
if (entry?.api && !api || api && !isOccFamilyApi(api)) return Response.json({
|
|
36039
|
+
providerId: provider,
|
|
36040
|
+
models: []
|
|
36041
|
+
});
|
|
36042
|
+
const baseUrl = entry?.baseUrl;
|
|
36043
|
+
if (!baseUrl) return Response.json({
|
|
36044
|
+
providerId: provider,
|
|
36045
|
+
models: []
|
|
36046
|
+
});
|
|
36047
|
+
try {
|
|
36048
|
+
const modelsUrl = openAiModelsUrl(baseUrl);
|
|
36049
|
+
const response = await fetch(modelsUrl, {
|
|
36050
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
36051
|
+
redirect: "error",
|
|
36052
|
+
signal: AbortSignal.timeout(1e4)
|
|
36053
|
+
});
|
|
36054
|
+
if (!response.ok) return Response.json({
|
|
36055
|
+
providerId: provider,
|
|
36056
|
+
models: []
|
|
36057
|
+
});
|
|
36058
|
+
const models = ((await response.json()).data ?? []).map((m) => ({
|
|
36059
|
+
key: `${provider}/${m.id}`,
|
|
36060
|
+
provider,
|
|
36061
|
+
id: m.id,
|
|
36062
|
+
name: m.id,
|
|
36063
|
+
reasoning: false,
|
|
36064
|
+
input: ["text"],
|
|
36065
|
+
available: true,
|
|
36066
|
+
defaultThinkingLevel: "off",
|
|
36067
|
+
thinkingLevels: ["off"]
|
|
36068
|
+
}));
|
|
36069
|
+
if (models.length > 0) {
|
|
36070
|
+
addCustomProviderModelIds(`${config.agentDir}/models.json`, provider, models.map((model) => model.id));
|
|
36071
|
+
config.reloadAuth();
|
|
36072
|
+
}
|
|
36073
|
+
return Response.json({
|
|
36074
|
+
providerId: provider,
|
|
36075
|
+
models
|
|
36076
|
+
});
|
|
36077
|
+
} catch {
|
|
36078
|
+
return Response.json({
|
|
36079
|
+
providerId: provider,
|
|
36080
|
+
models: []
|
|
36081
|
+
});
|
|
36082
|
+
}
|
|
36083
|
+
}, request);
|
|
36084
|
+
}
|
|
36085
|
+
function toThinkingLevel(level) {
|
|
36086
|
+
return level;
|
|
36087
|
+
}
|
|
36088
|
+
function handleChatNewPost(request) {
|
|
36089
|
+
return wrapApiHandler(async () => {
|
|
36090
|
+
const bridge = getBridge();
|
|
36091
|
+
const registry = getPrimeConfig().projectRegistry;
|
|
36092
|
+
const raw = await request.json().catch(() => ({}));
|
|
36093
|
+
const body = ChatNewRequestSchema.parse(raw);
|
|
36094
|
+
const projectId = body.projectId ?? await registry.projectIdForCwd(getPrimeConfig().defaultCwd) ?? (await registry.register(getPrimeConfig().defaultCwd)).projectId;
|
|
36095
|
+
const project = await registry.get(projectId);
|
|
36096
|
+
bridge.ensureKernelReady(project.canonicalPath).catch(() => {
|
|
36097
|
+
});
|
|
36098
|
+
const session = await bridge.createSession({
|
|
36099
|
+
cwd: project.canonicalPath,
|
|
36100
|
+
projectId,
|
|
36101
|
+
thinkingLevel: toThinkingLevel(body.thinkingLevel),
|
|
36102
|
+
mode: body.mode,
|
|
36103
|
+
openUI: body.openUI
|
|
36104
|
+
});
|
|
36105
|
+
if (body.model) {
|
|
36106
|
+
await bridge.setModel(session.sessionId, body.model);
|
|
36107
|
+
const thinking = body.model.thinkingLevel ?? body.thinkingLevel;
|
|
36108
|
+
if (thinking) await session.connection.setThinkingLevel(toThinkingLevel(thinking));
|
|
36109
|
+
}
|
|
36110
|
+
return Response.json({
|
|
36111
|
+
session: {
|
|
36112
|
+
sessionId: session.sessionId,
|
|
36113
|
+
projectId
|
|
36114
|
+
},
|
|
36115
|
+
messages: [],
|
|
36116
|
+
planPresentations: [],
|
|
36117
|
+
presentation: bridge.getPresentation(session.sessionId)
|
|
36118
|
+
});
|
|
36119
|
+
}, request);
|
|
36120
|
+
}
|
|
36121
|
+
function record(value) {
|
|
36122
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
36123
|
+
}
|
|
36124
|
+
function artifactIndexFor(artifact) {
|
|
36125
|
+
const input = record(artifact.input);
|
|
36126
|
+
return typeof input?.artifactIndex === "number" ? input.artifactIndex : void 0;
|
|
36127
|
+
}
|
|
36128
|
+
function handleChatOpenUIArtifactPut(request) {
|
|
36129
|
+
return wrapApiHandler(async () => {
|
|
36130
|
+
const raw = await request.json().catch(() => ({}));
|
|
36131
|
+
const parsed = ChatOpenUIArtifactUpsertRequestSchema.safeParse(raw);
|
|
36132
|
+
if (!parsed.success) return Response.json({ message: "Invalid OpenUI artifact request." }, { status: 400 });
|
|
36133
|
+
const body = parsed.data;
|
|
36134
|
+
const validation = validateAndNormalizeOpenUIHtmlArtifact(body.artifact);
|
|
36135
|
+
if (!validation.ok) return Response.json({ message: validation.reason }, { status: validation.status ?? 400 });
|
|
36136
|
+
const bridge = getBridge();
|
|
36137
|
+
const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
|
|
36138
|
+
if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
|
|
36139
|
+
const messages = await bridge.getMessages(session.sessionId);
|
|
36140
|
+
const incomingId = body.assistantMessageId;
|
|
36141
|
+
const exact = messages.find((message) => message.role === "assistant" && message.id === incomingId);
|
|
36142
|
+
const existing = bridge.getPresentation(session.sessionId).artifactRuns.flatMap((run) => run.artifacts).filter((artifact2) => artifact2.kind === "openui-html").find((artifact2) => artifactIndexFor(artifact2) === body.artifactIndex && (record(artifact2.input)?.clientMessageId === incomingId || artifact2.sourceMessageId === incomingId));
|
|
36143
|
+
const fallback = existing ? void 0 : [...messages].reverse().find((message) => message.role === "assistant");
|
|
36144
|
+
const assistantMessageId = exact?.id ?? existing?.sourceMessageId ?? fallback?.id;
|
|
36145
|
+
if (!assistantMessageId) return Response.json({ message: "Unable to associate OpenUI artifact with an assistant message." }, { status: 409 });
|
|
36146
|
+
const artifact = {
|
|
36147
|
+
id: stablePresentationId(`${assistantMessageId}:openui-html:${body.artifactIndex}`),
|
|
36148
|
+
runId: stablePresentationId(`${assistantMessageId}:openui`),
|
|
36149
|
+
sourceMessageId: assistantMessageId,
|
|
36150
|
+
kind: "openui-html",
|
|
36151
|
+
title: validation.value.title,
|
|
36152
|
+
status: "success",
|
|
36153
|
+
input: {
|
|
36154
|
+
clientMessageId: incomingId,
|
|
36155
|
+
artifactIndex: body.artifactIndex
|
|
36156
|
+
},
|
|
36157
|
+
output: validation.value,
|
|
36158
|
+
timestamp: Date.now()
|
|
36159
|
+
};
|
|
36160
|
+
const presentation = await bridge.upsertPresentationArtifact(session.sessionId, artifact);
|
|
36161
|
+
return Response.json({
|
|
36162
|
+
artifact,
|
|
36163
|
+
presentation
|
|
36164
|
+
});
|
|
36165
|
+
}, request);
|
|
36166
|
+
}
|
|
36167
|
+
function handleChatPlanPresentationPut(request) {
|
|
36168
|
+
return wrapApiHandler(async () => {
|
|
36169
|
+
const body = ChatPlanPresentationUpsertRequestSchema.parse(await request.json().catch(() => ({})));
|
|
36170
|
+
const bridge = getBridge();
|
|
36171
|
+
const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
|
|
36172
|
+
if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
|
|
36173
|
+
const messages = await bridge.getMessages(body.sessionId);
|
|
36174
|
+
const incomingId = body.presentation.assistantMessageId;
|
|
36175
|
+
const known = messages.find((message) => message.id === incomingId && message.role === "assistant");
|
|
36176
|
+
const existing = (await loadManagedPlanPresentations(session)).find((item) => item.assistantMessageId === incomingId || item.clientMessageId === incomingId);
|
|
36177
|
+
const fallback = existing ? void 0 : [...messages].reverse().find((message) => message.role === "assistant");
|
|
36178
|
+
const assistantMessageId = known?.id ?? existing?.assistantMessageId ?? fallback?.id;
|
|
36179
|
+
if (!assistantMessageId) return Response.json({ message: "Unable to associate Plan presentation with an assistant message" }, { status: 409 });
|
|
36180
|
+
const clientMessageId = incomingId !== assistantMessageId ? existing?.clientMessageId ?? incomingId : existing?.clientMessageId;
|
|
36181
|
+
return Response.json({ presentation: await upsertManagedPlanPresentation(session, {
|
|
36182
|
+
...body.presentation,
|
|
36183
|
+
assistantMessageId,
|
|
36184
|
+
...clientMessageId ? { clientMessageId } : {}
|
|
36185
|
+
}) });
|
|
35479
36186
|
}, request);
|
|
35480
36187
|
}
|
|
35481
36188
|
function handleChatQuestionPost(request) {
|
|
@@ -35505,7 +36212,8 @@ function handleChatQueueMutationPost(request) {
|
|
|
35505
36212
|
const body = ChatQueueMutationRequestSchema.parse(await request.json().catch(() => ({})));
|
|
35506
36213
|
const bridge = getBridge();
|
|
35507
36214
|
if (!await requireProjectSession(bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId))) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
|
|
35508
|
-
const
|
|
36215
|
+
const mutation = body.mutation ?? { type: "delete" };
|
|
36216
|
+
const result = await bridge.mutateQueuedMessage(body.sessionId, body.lane, body.index, body.expectedText, mutation);
|
|
35509
36217
|
return Response.json(ChatQueueMutationResponseSchema.parse(result));
|
|
35510
36218
|
}, request);
|
|
35511
36219
|
}
|
|
@@ -35686,14 +36394,53 @@ function normalizeSessionListRow(source) {
|
|
|
35686
36394
|
source,
|
|
35687
36395
|
sessionId,
|
|
35688
36396
|
cwd,
|
|
35689
|
-
title: stringValue(raw.sessionName) ?? stringValue(raw.name),
|
|
36397
|
+
title: meaningfulSessionLabel(stringValue(raw.sessionName) ?? stringValue(raw.name)),
|
|
35690
36398
|
createdAt,
|
|
35691
36399
|
updatedAt,
|
|
35692
36400
|
messageCount: messageCountValue(raw.messageCount),
|
|
35693
|
-
firstMessage: typeof raw.firstMessage === "string" ? raw.firstMessage : "",
|
|
36401
|
+
firstMessage: meaningfulSessionLabel(typeof raw.firstMessage === "string" ? raw.firstMessage : void 0) ?? "",
|
|
35694
36402
|
isSubagent
|
|
35695
36403
|
};
|
|
35696
36404
|
}
|
|
36405
|
+
function sessionSourcePath(source) {
|
|
36406
|
+
const raw = source;
|
|
36407
|
+
return stringValue(raw.sessionFile) ?? stringValue(raw.path);
|
|
36408
|
+
}
|
|
36409
|
+
function latestBy(entries, time) {
|
|
36410
|
+
if (entries.length === 0) return void 0;
|
|
36411
|
+
return entries.reduce((latest, entry) => time(entry) >= time(latest) ? entry : latest);
|
|
36412
|
+
}
|
|
36413
|
+
function presentationListActivity(presentation) {
|
|
36414
|
+
if (!presentation) return { activityCount: 0 };
|
|
36415
|
+
const artifacts = presentation.artifactRuns.flatMap((run) => run.artifacts);
|
|
36416
|
+
const latestRefinement = latestBy(presentation.refinements, (entry) => entry.timestamp);
|
|
36417
|
+
const latestArtifact = latestBy(artifacts, (entry) => entry.timestamp);
|
|
36418
|
+
const latestBash = latestBy(presentation.userBash, (entry) => entry.startedAt);
|
|
36419
|
+
return {
|
|
36420
|
+
title: meaningfulSessionLabel(presentation.sessionName) ?? meaningfulSessionLabel(latestRefinement?.summary) ?? meaningfulSessionLabel(latestArtifact?.title) ?? meaningfulSessionLabel(latestBash?.command),
|
|
36421
|
+
activityCount: presentation.refinements.length + artifacts.length + presentation.userBash.length
|
|
36422
|
+
};
|
|
36423
|
+
}
|
|
36424
|
+
function applyPresentationToSessionRow(row, presentation) {
|
|
36425
|
+
const { title: presentationTitle, activityCount } = presentationListActivity(presentation);
|
|
36426
|
+
const firstMessage = row.firstMessage || presentationTitle || "";
|
|
36427
|
+
return {
|
|
36428
|
+
title: row.title ?? meaningfulSessionLabel(firstMessage) ?? presentationTitle ?? fallbackSessionLabel(row.sessionId),
|
|
36429
|
+
firstMessage,
|
|
36430
|
+
messageCount: row.messageCount > 0 ? row.messageCount : activityCount > 0 ? 1 : 0
|
|
36431
|
+
};
|
|
36432
|
+
}
|
|
36433
|
+
function sessionNeedsPresentationJoin(row) {
|
|
36434
|
+
return row.messageCount === 0 || !row.title || !row.firstMessage;
|
|
36435
|
+
}
|
|
36436
|
+
async function loadSessionListPresentation(row, source, livePresentation) {
|
|
36437
|
+
const liveActivity = presentationListActivity(livePresentation);
|
|
36438
|
+
if (liveActivity.activityCount > 0 || liveActivity.title) return livePresentation;
|
|
36439
|
+
if (!sessionNeedsPresentationJoin(row)) return livePresentation;
|
|
36440
|
+
const path = sessionSourcePath(source);
|
|
36441
|
+
if (!path) return livePresentation;
|
|
36442
|
+
return await loadManagedPrimePresentation({ sessionPath: path }) ?? livePresentation;
|
|
36443
|
+
}
|
|
35697
36444
|
function sessionStatus(info, live) {
|
|
35698
36445
|
if (live?.isStreaming || live?.session?.isStreaming || info.isStreaming) return "running";
|
|
35699
36446
|
if (info.activity === "working" && (info.isSessionActive || info.hasRunningRlmChildren === true)) return "running";
|
|
@@ -35721,20 +36468,22 @@ function handleProjectsGet(_request) {
|
|
|
35721
36468
|
for (const projectId of assignments.values()) if (projectId) counts.set(projectId, (counts.get(projectId) ?? 0) + 1);
|
|
35722
36469
|
return Response.json({
|
|
35723
36470
|
projects: await getPrimeConfig().projectRegistry.list(counts),
|
|
35724
|
-
sessions: sessions2.map((source) => {
|
|
36471
|
+
sessions: await Promise.all(sessions2.map(async (source) => {
|
|
35725
36472
|
const session = normalizeSessionListRow(source);
|
|
36473
|
+
const liveSession = getBridge().getSession(session.sessionId);
|
|
36474
|
+
const fields = applyPresentationToSessionRow(session, await loadSessionListPresentation(session, source, liveSession?.mapperState?.presentation));
|
|
35726
36475
|
return {
|
|
35727
36476
|
sessionId: session.sessionId,
|
|
35728
36477
|
projectId: assignments.get(session.sessionId) ?? null,
|
|
35729
|
-
title: redactSessionLabelSecrets(
|
|
36478
|
+
title: redactSessionLabelSecrets(fields.title),
|
|
35730
36479
|
createdAt: session.createdAt,
|
|
35731
36480
|
updatedAt: session.updatedAt,
|
|
35732
|
-
status: sessionStatus(session.source,
|
|
35733
|
-
messageCount:
|
|
35734
|
-
firstMessage:
|
|
36481
|
+
status: sessionStatus(session.source, liveSession),
|
|
36482
|
+
messageCount: fields.messageCount,
|
|
36483
|
+
firstMessage: fields.firstMessage ? redactSessionLabelSecrets(fields.firstMessage) : "",
|
|
35735
36484
|
...session.isSubagent ? { isSubagent: true } : {}
|
|
35736
36485
|
};
|
|
35737
|
-
})
|
|
36486
|
+
}))
|
|
35738
36487
|
});
|
|
35739
36488
|
}, _request);
|
|
35740
36489
|
}
|
|
@@ -35788,15 +36537,16 @@ function handleChatSessionsGet(_request) {
|
|
|
35788
36537
|
const formatted = await Promise.all(sessions2.map(async (s) => {
|
|
35789
36538
|
const session = normalizeSessionListRow(s);
|
|
35790
36539
|
const liveSession = bridge.getSession(session.sessionId);
|
|
36540
|
+
const fields = applyPresentationToSessionRow(session, await loadSessionListPresentation(session, s, liveSession?.mapperState?.presentation));
|
|
35791
36541
|
return {
|
|
35792
36542
|
sessionId: session.sessionId,
|
|
35793
36543
|
projectId: await getPrimeConfig().projectRegistry.projectIdForSession(session.sessionId, liveSession?.cwd ?? session.cwd),
|
|
35794
|
-
title:
|
|
36544
|
+
title: fields.title,
|
|
35795
36545
|
createdAt: session.createdAt,
|
|
35796
36546
|
updatedAt: session.updatedAt,
|
|
35797
36547
|
status: sessionStatus(session.source, liveSession),
|
|
35798
|
-
messageCount:
|
|
35799
|
-
firstMessage:
|
|
36548
|
+
messageCount: fields.messageCount,
|
|
36549
|
+
firstMessage: fields.firstMessage,
|
|
35800
36550
|
...session.isSubagent ? { isSubagent: true } : {}
|
|
35801
36551
|
};
|
|
35802
36552
|
}));
|
|
@@ -36114,177 +36864,193 @@ function handleWorkspaceTreeGet(_request) {
|
|
|
36114
36864
|
});
|
|
36115
36865
|
}, _request);
|
|
36116
36866
|
}
|
|
36117
|
-
var Route$
|
|
36118
|
-
var Route$
|
|
36119
|
-
var Route$
|
|
36867
|
+
var Route$27 = createFileRoute("/api/chat")({ server: { handlers: { POST: ({ request }) => handleChatPost(request) } } });
|
|
36868
|
+
var Route$26 = createFileRoute("/api/health")({ server: { handlers: { GET: ({ request }) => handleHealthGet(request) } } });
|
|
36869
|
+
var Route$25 = createFileRoute("/api/projects")({ server: { handlers: {
|
|
36120
36870
|
DELETE: ({ request }) => handleProjectDelete(request),
|
|
36121
36871
|
GET: ({ request }) => handleProjectsGet(request),
|
|
36122
36872
|
PATCH: ({ request }) => handleProjectPatch(request),
|
|
36123
36873
|
POST: ({ request }) => handleProjectsPost(request)
|
|
36124
36874
|
} } });
|
|
36125
|
-
var Route$
|
|
36126
|
-
var Route$
|
|
36127
|
-
var Route$
|
|
36128
|
-
var Route$
|
|
36129
|
-
var Route$
|
|
36130
|
-
var Route$
|
|
36131
|
-
|
|
36132
|
-
|
|
36133
|
-
|
|
36875
|
+
var Route$24 = createFileRoute("/api/chat/abort")({ server: { handlers: { POST: ({ request }) => handleChatAbortPost(request) } } });
|
|
36876
|
+
var Route$23 = createFileRoute("/api/chat/artifacts")({ server: { handlers: { PUT: ({ request }) => handleChatOpenUIArtifactPut(request) } } });
|
|
36877
|
+
var Route$22 = createFileRoute("/api/chat/command")({ server: { handlers: { POST: ({ request }) => handleChatCommandPost(request) } } });
|
|
36878
|
+
var Route$21 = createFileRoute("/api/chat/commands")({ server: { handlers: { GET: ({ request }) => handleChatCommandsGet(request) } } });
|
|
36879
|
+
var Route$20 = createFileRoute("/api/chat/events")({ server: { handlers: { GET: ({ request }) => handleChatEventsGet(request) } } });
|
|
36880
|
+
var Route$19 = createFileRoute("/api/chat/mcp")({ server: { handlers: {
|
|
36881
|
+
GET: ({ request }) => handleChatMcpGet(request),
|
|
36882
|
+
POST: ({ request }) => handleChatMcpPost(request),
|
|
36883
|
+
DELETE: ({ request }) => handleChatMcpDelete(request)
|
|
36884
|
+
} } });
|
|
36885
|
+
var Route$18 = createFileRoute("/api/chat/model")({ server: { handlers: { POST: ({ request }) => handleChatModelPost(request) } } });
|
|
36886
|
+
var Route$17 = createFileRoute("/api/chat/models")({ server: { handlers: { GET: ({ request }) => handleChatModelsGet(request) } } });
|
|
36887
|
+
var Route$16 = createFileRoute("/api/chat/new")({ server: { handlers: { POST: ({ request }) => handleChatNewPost(request) } } });
|
|
36888
|
+
var Route$15 = createFileRoute("/api/chat/providers")({ server: { handlers: {
|
|
36134
36889
|
GET: ({ request }) => handleChatProvidersGet(request),
|
|
36135
36890
|
POST: ({ request }) => handleChatProvidersPost(request),
|
|
36136
36891
|
DELETE: ({ request }) => handleChatProvidersDelete(request)
|
|
36137
36892
|
} } });
|
|
36138
|
-
var Route$
|
|
36139
|
-
var Route$
|
|
36140
|
-
var Route$
|
|
36141
|
-
var Route$
|
|
36893
|
+
var Route$14 = createFileRoute("/api/chat/question")({ server: { handlers: { POST: ({ request }) => handleChatQuestionPost(request) } } });
|
|
36894
|
+
var Route$13 = createFileRoute("/api/chat/resources")({ server: { handlers: { GET: ({ request }) => handleChatResourcesGet(request) } } });
|
|
36895
|
+
var Route$12 = createFileRoute("/api/chat/resume")({ server: { handlers: { POST: ({ request }) => handleChatResumePost(request) } } });
|
|
36896
|
+
var Route$11 = createFileRoute("/api/chat/session")({ server: { handlers: {
|
|
36142
36897
|
GET: ({ request }) => new URL(request.url).searchParams.has("attachmentId") ? handleChatAttachmentGet(request) : handleChatSessionGet(request),
|
|
36143
36898
|
POST: ({ request }) => handleChatAttachmentsPost(request),
|
|
36144
36899
|
PUT: ({ request }) => handleChatPlanPresentationPut(request),
|
|
36145
36900
|
PATCH: ({ request }) => handleChatQueueMutationPost(request)
|
|
36146
36901
|
} } });
|
|
36147
|
-
var Route$
|
|
36902
|
+
var Route$10 = createFileRoute("/api/chat/sessions")({ server: { handlers: {
|
|
36148
36903
|
DELETE: ({ request }) => handleChatSessionDelete(request),
|
|
36149
36904
|
GET: ({ request }) => handleChatSessionsGet(request),
|
|
36150
36905
|
PATCH: ({ request }) => handleChatSessionRenamePatch(request)
|
|
36151
36906
|
} } });
|
|
36152
|
-
var Route$
|
|
36907
|
+
var Route$9 = createFileRoute("/api/chat/settings")({ server: { handlers: {
|
|
36153
36908
|
GET: ({ request }) => handleChatSettingsGet(request),
|
|
36154
36909
|
PATCH: ({ request }) => handleChatSettingsPatch(request)
|
|
36155
36910
|
} } });
|
|
36156
|
-
var Route$
|
|
36157
|
-
var Route$
|
|
36158
|
-
var Route$
|
|
36159
|
-
var Route$
|
|
36160
|
-
var Route$
|
|
36161
|
-
var Route$
|
|
36911
|
+
var Route$8 = createFileRoute("/api/projects/browse")({ server: { handlers: { GET: ({ request }) => handleProjectBrowseGet(request) } } });
|
|
36912
|
+
var Route$7 = createFileRoute("/api/projects/fork")({ server: { handlers: { POST: ({ request }) => handleProjectSessionFork(request) } } });
|
|
36913
|
+
var Route$6 = createFileRoute("/api/workspace/browse")({ server: { handlers: { GET: ({ request }) => handleWorkspaceBrowseGet(request) } } });
|
|
36914
|
+
var Route$5 = createFileRoute("/api/workspace/file")({ server: { handlers: { GET: ({ request }) => handleWorkspaceFileGet(request) } } });
|
|
36915
|
+
var Route$4 = createFileRoute("/api/workspace/root")({ server: { handlers: { POST: () => Response.json({ message: "The workspace root is fixed when Fleet starts" }, { status: 405 }) } } });
|
|
36916
|
+
var Route$3 = createFileRoute("/api/workspace/tree")({ server: { handlers: { GET: ({ request }) => handleWorkspaceTreeGet(request) } } });
|
|
36917
|
+
var Route$2 = createFileRoute("/api/chat/mcp/oauth")({ server: { handlers: { POST: ({ request }) => handleChatMcpOAuthPost(request) } } });
|
|
36162
36918
|
var Route$1 = createFileRoute("/api/chat/models/discover")({ server: { handlers: { POST: ({ request }) => handleChatModelsDiscoverPost(request) } } });
|
|
36163
36919
|
var Route = createFileRoute("/api/chat/providers/oauth")({ server: { handlers: { POST: ({ request }) => handleChatProvidersOAuthPost(request) } } });
|
|
36164
|
-
var IndexRoute = Route$
|
|
36920
|
+
var IndexRoute = Route$28.update({
|
|
36165
36921
|
id: "/",
|
|
36166
36922
|
path: "/",
|
|
36167
|
-
getParentRoute: () => Route$
|
|
36923
|
+
getParentRoute: () => Route$29
|
|
36168
36924
|
});
|
|
36169
|
-
var ApiChatRoute = Route$
|
|
36925
|
+
var ApiChatRoute = Route$27.update({
|
|
36170
36926
|
id: "/api/chat",
|
|
36171
36927
|
path: "/api/chat",
|
|
36172
|
-
getParentRoute: () => Route$
|
|
36928
|
+
getParentRoute: () => Route$29
|
|
36173
36929
|
});
|
|
36174
|
-
var ApiHealthRoute = Route$
|
|
36930
|
+
var ApiHealthRoute = Route$26.update({
|
|
36175
36931
|
id: "/api/health",
|
|
36176
36932
|
path: "/api/health",
|
|
36177
|
-
getParentRoute: () => Route$
|
|
36933
|
+
getParentRoute: () => Route$29
|
|
36178
36934
|
});
|
|
36179
|
-
var ApiProjectsRoute = Route$
|
|
36935
|
+
var ApiProjectsRoute = Route$25.update({
|
|
36180
36936
|
id: "/api/projects",
|
|
36181
36937
|
path: "/api/projects",
|
|
36182
|
-
getParentRoute: () => Route$
|
|
36938
|
+
getParentRoute: () => Route$29
|
|
36183
36939
|
});
|
|
36184
|
-
var ApiChatAbortRoute = Route$
|
|
36940
|
+
var ApiChatAbortRoute = Route$24.update({
|
|
36185
36941
|
id: "/abort",
|
|
36186
36942
|
path: "/abort",
|
|
36187
36943
|
getParentRoute: () => ApiChatRoute
|
|
36188
36944
|
});
|
|
36189
|
-
var ApiChatArtifactsRoute = Route$
|
|
36945
|
+
var ApiChatArtifactsRoute = Route$23.update({
|
|
36190
36946
|
id: "/artifacts",
|
|
36191
36947
|
path: "/artifacts",
|
|
36192
36948
|
getParentRoute: () => ApiChatRoute
|
|
36193
36949
|
});
|
|
36194
|
-
var ApiChatCommandRoute = Route$
|
|
36950
|
+
var ApiChatCommandRoute = Route$22.update({
|
|
36195
36951
|
id: "/command",
|
|
36196
36952
|
path: "/command",
|
|
36197
36953
|
getParentRoute: () => ApiChatRoute
|
|
36198
36954
|
});
|
|
36199
|
-
var ApiChatCommandsRoute = Route$
|
|
36955
|
+
var ApiChatCommandsRoute = Route$21.update({
|
|
36200
36956
|
id: "/commands",
|
|
36201
36957
|
path: "/commands",
|
|
36202
36958
|
getParentRoute: () => ApiChatRoute
|
|
36203
36959
|
});
|
|
36204
|
-
var ApiChatEventsRoute = Route$
|
|
36960
|
+
var ApiChatEventsRoute = Route$20.update({
|
|
36205
36961
|
id: "/events",
|
|
36206
36962
|
path: "/events",
|
|
36207
36963
|
getParentRoute: () => ApiChatRoute
|
|
36208
36964
|
});
|
|
36209
|
-
var
|
|
36965
|
+
var ApiChatMcpRoute = Route$19.update({
|
|
36966
|
+
id: "/mcp",
|
|
36967
|
+
path: "/mcp",
|
|
36968
|
+
getParentRoute: () => ApiChatRoute
|
|
36969
|
+
});
|
|
36970
|
+
var ApiChatModelRoute = Route$18.update({
|
|
36210
36971
|
id: "/model",
|
|
36211
36972
|
path: "/model",
|
|
36212
36973
|
getParentRoute: () => ApiChatRoute
|
|
36213
36974
|
});
|
|
36214
|
-
var ApiChatModelsRoute = Route$
|
|
36975
|
+
var ApiChatModelsRoute = Route$17.update({
|
|
36215
36976
|
id: "/models",
|
|
36216
36977
|
path: "/models",
|
|
36217
36978
|
getParentRoute: () => ApiChatRoute
|
|
36218
36979
|
});
|
|
36219
|
-
var ApiChatNewRoute = Route$
|
|
36980
|
+
var ApiChatNewRoute = Route$16.update({
|
|
36220
36981
|
id: "/new",
|
|
36221
36982
|
path: "/new",
|
|
36222
36983
|
getParentRoute: () => ApiChatRoute
|
|
36223
36984
|
});
|
|
36224
|
-
var ApiChatProvidersRoute = Route$
|
|
36985
|
+
var ApiChatProvidersRoute = Route$15.update({
|
|
36225
36986
|
id: "/providers",
|
|
36226
36987
|
path: "/providers",
|
|
36227
36988
|
getParentRoute: () => ApiChatRoute
|
|
36228
36989
|
});
|
|
36229
|
-
var ApiChatQuestionRoute = Route$
|
|
36990
|
+
var ApiChatQuestionRoute = Route$14.update({
|
|
36230
36991
|
id: "/question",
|
|
36231
36992
|
path: "/question",
|
|
36232
36993
|
getParentRoute: () => ApiChatRoute
|
|
36233
36994
|
});
|
|
36234
|
-
var ApiChatResourcesRoute = Route$
|
|
36995
|
+
var ApiChatResourcesRoute = Route$13.update({
|
|
36235
36996
|
id: "/resources",
|
|
36236
36997
|
path: "/resources",
|
|
36237
36998
|
getParentRoute: () => ApiChatRoute
|
|
36238
36999
|
});
|
|
36239
|
-
var ApiChatResumeRoute = Route$
|
|
37000
|
+
var ApiChatResumeRoute = Route$12.update({
|
|
36240
37001
|
id: "/resume",
|
|
36241
37002
|
path: "/resume",
|
|
36242
37003
|
getParentRoute: () => ApiChatRoute
|
|
36243
37004
|
});
|
|
36244
|
-
var ApiChatSessionRoute = Route$
|
|
37005
|
+
var ApiChatSessionRoute = Route$11.update({
|
|
36245
37006
|
id: "/session",
|
|
36246
37007
|
path: "/session",
|
|
36247
37008
|
getParentRoute: () => ApiChatRoute
|
|
36248
37009
|
});
|
|
36249
|
-
var ApiChatSessionsRoute = Route$
|
|
37010
|
+
var ApiChatSessionsRoute = Route$10.update({
|
|
36250
37011
|
id: "/sessions",
|
|
36251
37012
|
path: "/sessions",
|
|
36252
37013
|
getParentRoute: () => ApiChatRoute
|
|
36253
37014
|
});
|
|
36254
|
-
var ApiChatSettingsRoute = Route$
|
|
37015
|
+
var ApiChatSettingsRoute = Route$9.update({
|
|
36255
37016
|
id: "/settings",
|
|
36256
37017
|
path: "/settings",
|
|
36257
37018
|
getParentRoute: () => ApiChatRoute
|
|
36258
37019
|
});
|
|
36259
|
-
var ApiProjectsBrowseRoute = Route$
|
|
37020
|
+
var ApiProjectsBrowseRoute = Route$8.update({
|
|
36260
37021
|
id: "/browse",
|
|
36261
37022
|
path: "/browse",
|
|
36262
37023
|
getParentRoute: () => ApiProjectsRoute
|
|
36263
37024
|
});
|
|
36264
|
-
var ApiProjectsForkRoute = Route$
|
|
37025
|
+
var ApiProjectsForkRoute = Route$7.update({
|
|
36265
37026
|
id: "/fork",
|
|
36266
37027
|
path: "/fork",
|
|
36267
37028
|
getParentRoute: () => ApiProjectsRoute
|
|
36268
37029
|
});
|
|
36269
|
-
var ApiWorkspaceBrowseRoute = Route$
|
|
37030
|
+
var ApiWorkspaceBrowseRoute = Route$6.update({
|
|
36270
37031
|
id: "/api/workspace/browse",
|
|
36271
37032
|
path: "/api/workspace/browse",
|
|
36272
|
-
getParentRoute: () => Route$
|
|
37033
|
+
getParentRoute: () => Route$29
|
|
36273
37034
|
});
|
|
36274
|
-
var ApiWorkspaceFileRoute = Route$
|
|
37035
|
+
var ApiWorkspaceFileRoute = Route$5.update({
|
|
36275
37036
|
id: "/api/workspace/file",
|
|
36276
37037
|
path: "/api/workspace/file",
|
|
36277
|
-
getParentRoute: () => Route$
|
|
37038
|
+
getParentRoute: () => Route$29
|
|
36278
37039
|
});
|
|
36279
|
-
var ApiWorkspaceRootRoute = Route$
|
|
37040
|
+
var ApiWorkspaceRootRoute = Route$4.update({
|
|
36280
37041
|
id: "/api/workspace/root",
|
|
36281
37042
|
path: "/api/workspace/root",
|
|
36282
|
-
getParentRoute: () => Route$
|
|
37043
|
+
getParentRoute: () => Route$29
|
|
36283
37044
|
});
|
|
36284
|
-
var ApiWorkspaceTreeRoute = Route$
|
|
37045
|
+
var ApiWorkspaceTreeRoute = Route$3.update({
|
|
36285
37046
|
id: "/api/workspace/tree",
|
|
36286
37047
|
path: "/api/workspace/tree",
|
|
36287
|
-
getParentRoute: () => Route$
|
|
37048
|
+
getParentRoute: () => Route$29
|
|
37049
|
+
});
|
|
37050
|
+
var ApiChatMcpOauthRoute = Route$2.update({
|
|
37051
|
+
id: "/oauth",
|
|
37052
|
+
path: "/oauth",
|
|
37053
|
+
getParentRoute: () => ApiChatMcpRoute
|
|
36288
37054
|
});
|
|
36289
37055
|
var ApiChatModelsDiscoverRoute = Route$1.update({
|
|
36290
37056
|
id: "/discover",
|
|
@@ -36296,6 +37062,8 @@ var ApiChatProvidersOauthRoute = Route.update({
|
|
|
36296
37062
|
path: "/oauth",
|
|
36297
37063
|
getParentRoute: () => ApiChatProvidersRoute
|
|
36298
37064
|
});
|
|
37065
|
+
var ApiChatMcpRouteChildren = { ApiChatMcpOauthRoute };
|
|
37066
|
+
var ApiChatMcpRouteWithChildren = ApiChatMcpRoute._addFileChildren(ApiChatMcpRouteChildren);
|
|
36299
37067
|
var ApiChatModelsRouteChildren = { ApiChatModelsDiscoverRoute };
|
|
36300
37068
|
var ApiChatModelsRouteWithChildren = ApiChatModelsRoute._addFileChildren(ApiChatModelsRouteChildren);
|
|
36301
37069
|
var ApiChatProvidersRouteChildren = { ApiChatProvidersOauthRoute };
|
|
@@ -36305,6 +37073,7 @@ var ApiChatRouteChildren = {
|
|
|
36305
37073
|
ApiChatCommandRoute,
|
|
36306
37074
|
ApiChatCommandsRoute,
|
|
36307
37075
|
ApiChatEventsRoute,
|
|
37076
|
+
ApiChatMcpRoute: ApiChatMcpRouteWithChildren,
|
|
36308
37077
|
ApiChatModelRoute,
|
|
36309
37078
|
ApiChatModelsRoute: ApiChatModelsRouteWithChildren,
|
|
36310
37079
|
ApiChatNewRoute,
|
|
@@ -36331,7 +37100,7 @@ var rootRouteChildren = {
|
|
|
36331
37100
|
ApiWorkspaceRootRoute,
|
|
36332
37101
|
ApiWorkspaceTreeRoute
|
|
36333
37102
|
};
|
|
36334
|
-
var routeTree = Route$
|
|
37103
|
+
var routeTree = Route$29._addFileChildren(rootRouteChildren)._addFileTypes();
|
|
36335
37104
|
function getRouter() {
|
|
36336
37105
|
return createRouter({
|
|
36337
37106
|
routeTree,
|